fpu: Have opcode 0xDF use fixed_g instruction functions
This commit is contained in:
parent
cd17dda054
commit
1f0e7c3ce0
|
@ -163,8 +163,6 @@ const encodings = [
|
|||
{ opcode: 0xD6, nonfaulting: 1, },
|
||||
{ opcode: 0xD7, skip: 1, },
|
||||
|
||||
{ opcode: 0xDF, e: 1, skip: 1, },
|
||||
|
||||
{ opcode: 0xE0, imm8s: 1, skip: 1, jump: 1, },
|
||||
{ opcode: 0xE1, imm8s: 1, skip: 1, jump: 1, },
|
||||
{ opcode: 0xE2, imm8s: 1, skip: 1, jump: 1, },
|
||||
|
@ -665,6 +663,7 @@ for(let i = 0; i < 8; i++)
|
|||
{ opcode: 0xDC, e: 1, fixed_g: i, skip: 1, },
|
||||
{ opcode: 0xDD, e: 1, fixed_g: i, skip: 1, },
|
||||
{ opcode: 0xDE, e: 1, fixed_g: i, skip: 1, },
|
||||
{ opcode: 0xDF, e: 1, fixed_g: i, skip: 1, },
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
146
src/native/fpu.c
146
src/native/fpu.c
|
@ -966,149 +966,3 @@ void fpu_fistp(int32_t addr)
|
|||
|
||||
fpu_pop();
|
||||
}
|
||||
|
||||
void fpu_op_DF_reg(int32_t imm8)
|
||||
{
|
||||
dbg_log_fpu_op(0xDF, imm8);
|
||||
|
||||
int32_t mod = imm8 >> 3 & 7;
|
||||
int32_t low = imm8 & 7;
|
||||
|
||||
switch(mod)
|
||||
{
|
||||
case 4:
|
||||
if(imm8 == 0xE0)
|
||||
{
|
||||
// fnstsw
|
||||
reg16[AX] = fpu_load_status_word();
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("%x", imm8);
|
||||
fpu_unimpl();
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
// fucomip
|
||||
fpu_fucomi(low);
|
||||
fpu_pop();
|
||||
break;
|
||||
case 6:
|
||||
// fcomip
|
||||
fpu_fcomi(low);
|
||||
fpu_pop();
|
||||
break;
|
||||
default:
|
||||
dbg_log("%x", mod);
|
||||
fpu_unimpl();
|
||||
}
|
||||
}
|
||||
|
||||
void fpu_op_DF_mem(int32_t mod, int32_t addr)
|
||||
{
|
||||
dbg_log_fpu_op(0xDF, mod);
|
||||
|
||||
switch(mod)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
int32_t m16 = safe_read16(addr) << 16 >> 16;
|
||||
fpu_push(m16);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
// fisttp
|
||||
dbg_log("df/fisttp");
|
||||
fpu_unimpl();
|
||||
break;
|
||||
case 2:
|
||||
// fist
|
||||
{
|
||||
double_t st0 = fpu_integer_round(fpu_get_st0());
|
||||
if(st0 <= 0x7FFF && st0 >= -0x8000)
|
||||
{
|
||||
safe_write16(addr, st0);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpu_invalid_arithmetic();
|
||||
safe_write16(addr, 0x8000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
// fistp
|
||||
{
|
||||
double_t st0 = fpu_integer_round(fpu_get_st0());
|
||||
if(st0 <= 0x7FFF && st0 >= -0x8000)
|
||||
{
|
||||
safe_write16(addr, st0);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpu_invalid_arithmetic();
|
||||
safe_write16(addr, 0x8000);
|
||||
}
|
||||
fpu_pop();
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
// fbld
|
||||
dbg_log("fbld");
|
||||
fpu_unimpl();
|
||||
break;
|
||||
case 5:
|
||||
// fild
|
||||
// XXX: Use safe_read64s
|
||||
{
|
||||
uint32_t low = safe_read32s(addr);
|
||||
int32_t high = safe_read32s(addr + 4);
|
||||
|
||||
double_t m64 = (double_t)low + 0x100000000 * (double_t)high;
|
||||
|
||||
fpu_push(m64);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
// fbstp
|
||||
dbg_log("fbstp");
|
||||
fpu_unimpl();
|
||||
break;
|
||||
case 7:
|
||||
{
|
||||
// fistp
|
||||
writable_or_pagefault(addr, 8);
|
||||
|
||||
double_t st0 = fpu_integer_round(fpu_get_st0());
|
||||
|
||||
//union f64_int v = { .f64 = st0 };
|
||||
//dbg_log("fistp %x %x", v.i32[0], v.i32[1]);
|
||||
|
||||
int32_t st0_low;
|
||||
int32_t st0_high;
|
||||
|
||||
if(st0 < TWO_POW_63 && st0 >= -TWO_POW_63)
|
||||
{
|
||||
int64_t st0_int = st0;
|
||||
st0_low = st0_int;
|
||||
st0_high = st0_int >> 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
// write 0x8000000000000000
|
||||
st0_low = 0;
|
||||
st0_high = 0x80000000;
|
||||
fpu_invalid_arithmetic();
|
||||
}
|
||||
|
||||
// XXX: Use safe_write64
|
||||
safe_write32(addr, st0_low);
|
||||
safe_write32(addr + 4, st0_high);
|
||||
|
||||
fpu_pop();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dbg_assert(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1366,9 +1366,34 @@ void instr_DE_7_reg(int32_t r)
|
|||
fpu_pop();
|
||||
}
|
||||
|
||||
void instr_DF_mem(int32_t addr, int32_t r) { task_switch_test(); fpu_op_DF_mem(r, addr); }
|
||||
void instr_DF_reg(int32_t r2, int32_t r) { task_switch_test(); fpu_op_DF_reg(0xC0 | r2 | r << 3); }
|
||||
void instr_DF_0_mem(int32_t addr) { task_switch_test(); fpu_push((int16_t) safe_read16(addr)); }
|
||||
void instr_DF_1_mem(int32_t addr) { dbg_log("df/fisttp"); trigger_ud(); }
|
||||
void instr_DF_2_mem(int32_t addr) { task_switch_test(); fpu_fistm16(addr); }
|
||||
void instr_DF_3_mem(int32_t addr) { task_switch_test(); fpu_fistm16p(addr); }
|
||||
void instr_DF_4_mem(int32_t addr) { dbg_log("fbld"); trigger_ud(); }
|
||||
void instr_DF_5_mem(int32_t addr) { task_switch_test(); fpu_fild(addr); }
|
||||
void instr_DF_6_mem(int32_t addr) { dbg_log("fbstp"); trigger_ud(); }
|
||||
void instr_DF_7_mem(int32_t addr) { task_switch_test(); fpu_fistp(addr); }
|
||||
|
||||
void instr_DF_0_reg(int32_t r) { trigger_ud(); }
|
||||
void instr_DF_1_reg(int32_t r) { trigger_ud(); }
|
||||
void instr_DF_2_reg(int32_t r) { trigger_ud(); }
|
||||
void instr_DF_3_reg(int32_t r) { trigger_ud(); }
|
||||
void instr_DF_4_reg(int32_t r)
|
||||
{
|
||||
task_switch_test();
|
||||
if(r == 0)
|
||||
{
|
||||
fpu_fnstsw_reg();
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_ud();
|
||||
}
|
||||
}
|
||||
void instr_DF_5_reg(int32_t r) { task_switch_test(); fpu_fucomip(r); }
|
||||
void instr_DF_6_reg(int32_t r) { task_switch_test(); fpu_fcomip(r); }
|
||||
void instr_DF_7_reg(int32_t r) { trigger_ud(); }
|
||||
|
||||
void instr_E0(int32_t off) { loopne(off); }
|
||||
void instr_E1(int32_t off) { loope(off); }
|
||||
|
|
Loading…
Reference in a new issue