From 087f412d3fdf5c44beda16843abefdcc4e7ba0ae Mon Sep 17 00:00:00 2001 From: TomW Date: Sun, 9 Nov 2014 14:07:03 +0000 Subject: [PATCH] Reorganised FPU emulation. --- src/386_common.h | 17 + src/386_ops.h | 8 +- src/codegen_x86.c | 65 +- src/cpu.c | 119 ++++ src/x86_ops.h | 69 ++ src/x86_ops_fpu.h | 125 ++-- src/x87.c | 1374 +-------------------------------------- src/x87.h | 8 +- src/x87_ops.h | 784 ++++++++++++++++++++++ src/x87_ops_arith.h | 343 ++++++++++ src/x87_ops_loadstore.h | 456 +++++++++++++ src/x87_ops_misc.h | 738 +++++++++++++++++++++ 12 files changed, 2670 insertions(+), 1436 deletions(-) create mode 100644 src/x87_ops.h create mode 100644 src/x87_ops_arith.h create mode 100644 src/x87_ops_loadstore.h create mode 100644 src/x87_ops_misc.h diff --git a/src/386_common.h b/src/386_common.h index 7c97b5d..f5cf73b 100644 --- a/src/386_common.h +++ b/src/386_common.h @@ -134,6 +134,12 @@ static inline uint32_t getlong() return fastreadl(cs+(pc-4)); } +static inline uint64_t getquad() +{ + pc+=8; + return fastreadl(cs+(pc-8)) | ((uint64_t)fastreadl(cs+(pc-4)) << 32); +} + static inline uint8_t geteab() @@ -162,6 +168,11 @@ static inline uint32_t geteal() return readmeml(easeg,eaaddr); } +static inline uint64_t geteaq() +{ + return readmeml(easeg,eaaddr) | ((uint64_t)readmeml(easeg, eaaddr + 4) << 32); +} + static inline uint8_t geteab_mem() { if (eal_r) return *(uint8_t *)eal_r; @@ -178,6 +189,12 @@ static inline uint32_t geteal_mem() return readmeml(easeg,eaaddr); } +static inline void seteaq(uint64_t v) +{ + writememll(easeg, eaaddr, v & 0xffffffff); if (abrt) return; + writememll(easeg, eaaddr + 4, v >> 32); +} + #define seteab(v) if (mod!=3) { if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,eaaddr,v); } else if (rm&4) regs[rm&3].b.h=v; else regs[rm].b.l=v #define seteaw(v) if (mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,eaaddr,v); } else regs[rm].w=v #define seteal(v) if (mod!=3) { if (eal_w) *eal_w=v; else writememll(easeg,eaaddr,v); } else regs[rm].l=v diff --git a/src/386_ops.h b/src/386_ops.h index 5e80cbd..b3f8a4b 100644 --- a/src/386_ops.h +++ b/src/386_ops.h @@ -1,11 +1,5 @@ #include "x86_ops.h" -OpFn *x86_opcodes; -OpFn *x86_opcodes_0f; -#ifdef DYNAREC -OpFn *x86_dynarec_opcodes; -OpFn *x86_dynarec_opcodes_0f; -#endif #define ILLEGAL_ON(cond) \ do \ @@ -638,3 +632,5 @@ OpFn OP_TABLE(386)[1024] = /*e0*/ opLOOPNE_l, opLOOPE_l, opLOOP_l, opJECXZ, opIN_AL_imm, opIN_EAX_imm, opOUT_AL_imm, opOUT_EAX_imm, opCALL_r32, opJMP_r32, opJMP_far_a32, opJMP_r8, opIN_AL_DX, opIN_EAX_DX, opOUT_AL_DX, opOUT_EAX_DX, /*f0*/ opLOCK, ILLEGAL, opREPNE, opREPE, opHLT, opCMC, opF6_a32, opF7_l_a32, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a32, opFF_l_a32, }; + +#include "x87_ops.h" diff --git a/src/codegen_x86.c b/src/codegen_x86.c index d7bb793..8cdf955 100644 --- a/src/codegen_x86.c +++ b/src/codegen_x86.c @@ -448,14 +448,19 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t OpFn *op_table = x86_dynarec_opcodes; x86seg *op_ea_seg = &_ds; int op_ssegs = 0; + int opcode_shift = 0; + int opcode_mask = 0x3ff; + int over = 0; + int pc_off = 0; - while (1) + while (!over) { switch (opcode) { case 0x0f: op_table = x86_dynarec_opcodes_0f; + over = 1; break; case 0x26: /*ES:*/ @@ -498,6 +503,57 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t addbyte(0x83); addbyte(0x2D); addlong((uint32_t)&cycles); addbyte(2); break; + case 0xd8: + op_table = (op_32 & 0x200) ? x86_opcodes_d8_a32 : x86_opcodes_d8_a16; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + break; + case 0xd9: + op_table = (op_32 & 0x200) ? x86_opcodes_d9_a32 : x86_opcodes_d9_a16; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + break; + case 0xda: + op_table = (op_32 & 0x200) ? x86_opcodes_da_a32 : x86_opcodes_da_a16; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + break; + case 0xdb: + op_table = (op_32 & 0x200) ? x86_opcodes_db_a32 : x86_opcodes_db_a16; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + break; + case 0xdc: + op_table = (op_32 & 0x200) ? x86_opcodes_dc_a32 : x86_opcodes_dc_a16; + opcode_shift = 3; + opcode_mask = 0x1f; + over = 1; + pc_off = -1; + break; + case 0xdd: + op_table = (op_32 & 0x200) ? x86_opcodes_dd_a32 : x86_opcodes_dd_a16; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + break; + case 0xde: + op_table = (op_32 & 0x200) ? x86_opcodes_de_a32 : x86_opcodes_de_a16; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + break; + case 0xdf: + op_table = (op_32 & 0x200) ? x86_opcodes_df_a32 : x86_opcodes_df_a16; + opcode_mask = 0xff; + over = 1; + pc_off = -1; + break; + case 0xf0: /*LOCK*/ addbyte(0x83); addbyte(0x2D); addlong((uint32_t)&cycles); addbyte(2); break; @@ -510,13 +566,14 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t if (abrt) return; opcode = fetchdat & 0xff; - fetchdat >>= 8; + if (!pc_off) + fetchdat >>= 8; op_pc++; } generate_call: - op = op_table[(opcode | op_32) & 0x3ff]; + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; // if (output) // pclog("Generate call at %08X %02X %08X %02X %08X %08X %08X %08X %08X %02X %02X %02X %02X\n", &codeblock[block_current][block_pos], opcode, new_pc, ram[old_pc], EAX, EBX, ECX, EDX, ESI, ram[0x7bd2+6],ram[0x7bd2+7],ram[0x7bd2+8],ram[0x7bd2+9]); if (opcode_needs_tempc[opcode]) @@ -548,7 +605,7 @@ generate_call: addbyte(0xC7); /*MOVL $new_pc,(pc)*/ addbyte(0x05); addlong((uint32_t)&pc); - addlong(op_pc); + addlong(op_pc + pc_off); addbyte(0xC7); /*MOVL $old_pc,(oldpc)*/ addbyte(0x05); addlong((uint32_t)&oldpc); diff --git a/src/cpu.c b/src/cpu.c index 75ae0b8..3bae2a9 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -4,6 +4,46 @@ #include "io.h" #include "x86_ops.h" +#ifdef DYNAREC +OpFn *x86_dynarec_opcodes; +OpFn *x86_dynarec_opcodes_0f; +OpFn *x86_dynarec_opcodes_d8_a16; +OpFn *x86_dynarec_opcodes_d8_a32; +OpFn *x86_dynarec_opcodes_d9_a16; +OpFn *x86_dynarec_opcodes_d9_a32; +OpFn *x86_dynarec_opcodes_da_a16; +OpFn *x86_dynarec_opcodes_da_a32; +OpFn *x86_dynarec_opcodes_db_a16; +OpFn *x86_dynarec_opcodes_db_a32; +OpFn *x86_dynarec_opcodes_dc_a16; +OpFn *x86_dynarec_opcodes_dc_a32; +OpFn *x86_dynarec_opcodes_dd_a16; +OpFn *x86_dynarec_opcodes_dd_a32; +OpFn *x86_dynarec_opcodes_de_a16; +OpFn *x86_dynarec_opcodes_de_a32; +OpFn *x86_dynarec_opcodes_df_a16; +OpFn *x86_dynarec_opcodes_df_a32; +#endif + +OpFn *x86_opcodes; +OpFn *x86_opcodes_0f; +OpFn *x86_opcodes_d8_a16; +OpFn *x86_opcodes_d8_a32; +OpFn *x86_opcodes_d9_a16; +OpFn *x86_opcodes_d9_a32; +OpFn *x86_opcodes_da_a16; +OpFn *x86_opcodes_da_a32; +OpFn *x86_opcodes_db_a16; +OpFn *x86_opcodes_db_a32; +OpFn *x86_opcodes_dc_a16; +OpFn *x86_opcodes_dc_a32; +OpFn *x86_opcodes_dd_a16; +OpFn *x86_opcodes_dd_a32; +OpFn *x86_opcodes_de_a16; +OpFn *x86_opcodes_de_a32; +OpFn *x86_opcodes_df_a16; +OpFn *x86_opcodes_df_a32; + enum { CPUID_FPU = (1 << 0), @@ -286,6 +326,85 @@ void cpu_set() #else x86_setopcodes(ops_386, ops_386_0f); #endif +#ifdef DYNAREC + if (hasfpu) + { + x86_dynarec_opcodes_d8_a16 = dynarec_ops_fpu_d8_a16; + x86_dynarec_opcodes_d8_a32 = dynarec_ops_fpu_d8_a32; + x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_d9_a16; + x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_d9_a32; + x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_db_a32; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_dc_a16; + x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_dc_a32; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_dd_a16; + x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_dd_a32; + x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_de_a16; + x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_de_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_df_a32; + } + else + { + x86_dynarec_opcodes_d8_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_d8_a16 = dynarec_ops_nofpu_a32; + x86_dynarec_opcodes_d9_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_d9_a16 = dynarec_ops_nofpu_a32; + x86_dynarec_opcodes_da_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_da_a16 = dynarec_ops_nofpu_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_db_a16 = dynarec_ops_nofpu_a32; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_nofpu_a32; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_nofpu_a32; + x86_dynarec_opcodes_de_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_de_a16 = dynarec_ops_nofpu_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_nofpu_a16; + x86_dynarec_opcodes_df_a16 = dynarec_ops_nofpu_a32; + } +#endif + if (hasfpu) + { + x86_opcodes_d8_a16 = ops_fpu_d8_a16; + x86_opcodes_d8_a32 = ops_fpu_d8_a32; + x86_opcodes_d9_a16 = ops_fpu_d9_a16; + x86_opcodes_d9_a32 = ops_fpu_d9_a32; + x86_opcodes_da_a16 = ops_fpu_da_a16; + x86_opcodes_da_a32 = ops_fpu_da_a32; + x86_opcodes_db_a16 = ops_fpu_db_a16; + x86_opcodes_db_a32 = ops_fpu_db_a32; + x86_opcodes_dc_a16 = ops_fpu_dc_a16; + x86_opcodes_dc_a32 = ops_fpu_dc_a32; + x86_opcodes_dd_a16 = ops_fpu_dd_a16; + x86_opcodes_dd_a32 = ops_fpu_dd_a32; + x86_opcodes_de_a16 = ops_fpu_de_a16; + x86_opcodes_de_a32 = ops_fpu_de_a32; + x86_opcodes_df_a16 = ops_fpu_df_a16; + x86_opcodes_df_a32 = ops_fpu_df_a32; + } + else + { + x86_opcodes_d8_a16 = ops_nofpu_a16; + x86_opcodes_d8_a32 = ops_nofpu_a32; + x86_opcodes_d9_a16 = ops_nofpu_a16; + x86_opcodes_d9_a32 = ops_nofpu_a32; + x86_opcodes_da_a16 = ops_nofpu_a16; + x86_opcodes_da_a32 = ops_nofpu_a32; + x86_opcodes_db_a16 = ops_nofpu_a16; + x86_opcodes_db_a32 = ops_nofpu_a32; + x86_opcodes_dc_a16 = ops_nofpu_a16; + x86_opcodes_dc_a32 = ops_nofpu_a32; + x86_opcodes_dd_a16 = ops_nofpu_a16; + x86_opcodes_dd_a32 = ops_nofpu_a32; + x86_opcodes_de_a16 = ops_nofpu_a16; + x86_opcodes_de_a32 = ops_nofpu_a32; + x86_opcodes_df_a16 = ops_nofpu_a16; + x86_opcodes_df_a32 = ops_nofpu_a32; + } + memset(&msr, 0, sizeof(msr)); switch (cpu_s->cpu_type) diff --git a/src/x86_ops.h b/src/x86_ops.h index 08c66be..75cdb32 100644 --- a/src/x86_ops.h +++ b/src/x86_ops.h @@ -5,6 +5,22 @@ void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f, OpFn *dynarec_opcodes, OpFn extern OpFn *x86_dynarec_opcodes; extern OpFn *x86_dynarec_opcodes_0f; +extern OpFn *x86_dynarec_opcodes_d8_a16; +extern OpFn *x86_dynarec_opcodes_d8_a32; +extern OpFn *x86_dynarec_opcodes_d9_a16; +extern OpFn *x86_dynarec_opcodes_d9_a32; +extern OpFn *x86_dynarec_opcodes_da_a16; +extern OpFn *x86_dynarec_opcodes_da_a32; +extern OpFn *x86_dynarec_opcodes_db_a16; +extern OpFn *x86_dynarec_opcodes_db_a32; +extern OpFn *x86_dynarec_opcodes_dc_a16; +extern OpFn *x86_dynarec_opcodes_dc_a32; +extern OpFn *x86_dynarec_opcodes_dd_a16; +extern OpFn *x86_dynarec_opcodes_dd_a32; +extern OpFn *x86_dynarec_opcodes_de_a16; +extern OpFn *x86_dynarec_opcodes_de_a32; +extern OpFn *x86_dynarec_opcodes_df_a16; +extern OpFn *x86_dynarec_opcodes_df_a32; extern OpFn dynarec_ops_286[1024]; extern OpFn dynarec_ops_286_0f[1024]; @@ -14,12 +30,46 @@ extern OpFn dynarec_ops_386_0f[1024]; extern OpFn dynarec_ops_winchip_0f[1024]; +extern OpFn dynarec_ops_fpu_d8_a16[32]; +extern OpFn dynarec_ops_fpu_d8_a32[32]; +extern OpFn dynarec_ops_fpu_d9_a16[256]; +extern OpFn dynarec_ops_fpu_d9_a32[256]; +extern OpFn dynarec_ops_fpu_da_a16[256]; +extern OpFn dynarec_ops_fpu_da_a32[256]; +extern OpFn dynarec_ops_fpu_db_a16[256]; +extern OpFn dynarec_ops_fpu_db_a32[256]; +extern OpFn dynarec_ops_fpu_dc_a16[32]; +extern OpFn dynarec_ops_fpu_dc_a32[32]; +extern OpFn dynarec_ops_fpu_dd_a16[256]; +extern OpFn dynarec_ops_fpu_dd_a32[256]; +extern OpFn dynarec_ops_fpu_de_a16[256]; +extern OpFn dynarec_ops_fpu_de_a32[256]; +extern OpFn dynarec_ops_fpu_df_a16[256]; +extern OpFn dynarec_ops_fpu_df_a32[256]; +extern OpFn dynarec_ops_nofpu_a16[256]; +extern OpFn dynarec_ops_nofpu_a32[256]; #else void x86_setopcodes(OpFn *opcodes, OpFn *opcodes_0f); #endif extern OpFn *x86_opcodes; extern OpFn *x86_opcodes_0f; +extern OpFn *x86_opcodes_d8_a16; +extern OpFn *x86_opcodes_d8_a32; +extern OpFn *x86_opcodes_d9_a16; +extern OpFn *x86_opcodes_d9_a32; +extern OpFn *x86_opcodes_da_a16; +extern OpFn *x86_opcodes_da_a32; +extern OpFn *x86_opcodes_db_a16; +extern OpFn *x86_opcodes_db_a32; +extern OpFn *x86_opcodes_dc_a16; +extern OpFn *x86_opcodes_dc_a32; +extern OpFn *x86_opcodes_dd_a16; +extern OpFn *x86_opcodes_dd_a32; +extern OpFn *x86_opcodes_de_a16; +extern OpFn *x86_opcodes_de_a32; +extern OpFn *x86_opcodes_df_a16; +extern OpFn *x86_opcodes_df_a32; extern OpFn ops_286[1024]; extern OpFn ops_286_0f[1024]; @@ -28,3 +78,22 @@ extern OpFn ops_386[1024]; extern OpFn ops_386_0f[1024]; extern OpFn ops_winchip_0f[1024]; + +extern OpFn ops_fpu_d8_a16[32]; +extern OpFn ops_fpu_d8_a32[32]; +extern OpFn ops_fpu_d9_a16[256]; +extern OpFn ops_fpu_d9_a32[256]; +extern OpFn ops_fpu_da_a16[256]; +extern OpFn ops_fpu_da_a32[256]; +extern OpFn ops_fpu_db_a16[256]; +extern OpFn ops_fpu_db_a32[256]; +extern OpFn ops_fpu_dc_a16[32]; +extern OpFn ops_fpu_dc_a32[32]; +extern OpFn ops_fpu_dd_a16[256]; +extern OpFn ops_fpu_dd_a32[256]; +extern OpFn ops_fpu_de_a16[256]; +extern OpFn ops_fpu_de_a32[256]; +extern OpFn ops_fpu_df_a16[256]; +extern OpFn ops_fpu_df_a32[256]; +extern OpFn ops_nofpu_a16[256]; +extern OpFn ops_nofpu_a32[256]; diff --git a/src/x86_ops_fpu.h b/src/x86_ops_fpu.h index 90e7f48..fc1c162 100644 --- a/src/x86_ops_fpu.h +++ b/src/x86_ops_fpu.h @@ -1,59 +1,74 @@ -#define opESCAPE(num) \ - static int opESCAPE_ ## num ##_a16(uint32_t fetchdat) \ - { \ - flags_rebuild(); \ - if (cr0 & 0xc) \ - { \ - x86_int(7); \ - return 1; \ - } \ - else \ - { \ - fpucount++; \ - fetch_ea_16(fetchdat); \ - if (hasfpu) \ - { \ - x87_pc_off = oldpc; \ - x87_pc_seg = CS; \ - x87_op_off = eaaddr; \ - x87_op_seg = ea_rseg; \ - x87_ ## num(fetchdat); \ - } \ - } \ - return abrt; \ - } \ - static int opESCAPE_ ## num ## _a32(uint32_t fetchdat) \ - { \ - flags_rebuild(); \ - if (cr0 & 0xc) \ - { \ - x86_int(7); \ - return 1; \ - } \ - else \ - { \ - fpucount++; \ - fetch_ea_32(fetchdat); \ - if (hasfpu) \ - { \ - x87_pc_off = oldpc; \ - x87_pc_seg = CS; \ - x87_op_off = eaaddr; \ - x87_op_seg = ea_rseg; \ - x87_ ## num(fetchdat); \ - } \ - } \ - return abrt; \ - } +static int opESCAPE_d8_a16(uint32_t fetchdat) +{ + return x86_opcodes_d8_a16[(fetchdat >> 3) & 0x1f](fetchdat); +} +static int opESCAPE_d8_a32(uint32_t fetchdat) +{ + return x86_opcodes_d8_a32[(fetchdat >> 3) & 0x1f](fetchdat); +} -opESCAPE(d8); -opESCAPE(d9); -opESCAPE(da); -opESCAPE(db); -opESCAPE(dc); -opESCAPE(dd); -opESCAPE(de); -opESCAPE(df); +static int opESCAPE_d9_a16(uint32_t fetchdat) +{ + return x86_opcodes_d9_a16[fetchdat & 0xff](fetchdat); +} +static int opESCAPE_d9_a32(uint32_t fetchdat) +{ + return x86_opcodes_d9_a32[fetchdat & 0xff](fetchdat); +} + +static int opESCAPE_da_a16(uint32_t fetchdat) +{ + return x86_opcodes_da_a16[fetchdat & 0xff](fetchdat); +} +static int opESCAPE_da_a32(uint32_t fetchdat) +{ + return x86_opcodes_da_a32[fetchdat & 0xff](fetchdat); +} + +static int opESCAPE_db_a16(uint32_t fetchdat) +{ + return x86_opcodes_db_a16[fetchdat & 0xff](fetchdat); +} +static int opESCAPE_db_a32(uint32_t fetchdat) +{ + return x86_opcodes_db_a32[fetchdat & 0xff](fetchdat); +} + +static int opESCAPE_dc_a16(uint32_t fetchdat) +{ + return x86_opcodes_dc_a16[(fetchdat >> 3) & 0x1f](fetchdat); +} +static int opESCAPE_dc_a32(uint32_t fetchdat) +{ + return x86_opcodes_dc_a32[(fetchdat >> 3) & 0x1f](fetchdat); +} + +static int opESCAPE_dd_a16(uint32_t fetchdat) +{ + return x86_opcodes_dd_a16[fetchdat & 0xff](fetchdat); +} +static int opESCAPE_dd_a32(uint32_t fetchdat) +{ + return x86_opcodes_dd_a32[fetchdat & 0xff](fetchdat); +} + +static int opESCAPE_de_a16(uint32_t fetchdat) +{ + return x86_opcodes_de_a16[fetchdat & 0xff](fetchdat); +} +static int opESCAPE_de_a32(uint32_t fetchdat) +{ + return x86_opcodes_de_a32[fetchdat & 0xff](fetchdat); +} + +static int opESCAPE_df_a16(uint32_t fetchdat) +{ + return x86_opcodes_df_a16[fetchdat & 0xff](fetchdat); +} +static int opESCAPE_df_a32(uint32_t fetchdat) +{ + return x86_opcodes_df_a32[fetchdat & 0xff](fetchdat); +} static int opWAIT(uint32_t fetchdat) { diff --git a/src/x87.c b/src/x87.c index e10dfd7..c4e2bef 100644 --- a/src/x87.c +++ b/src/x87.c @@ -14,104 +14,17 @@ #include "ibm.h" #include "pic.h" #include "x86.h" +#include "x86_flags.h" +#include "x86_ops.h" #include "x87.h" - -#undef readmemb -#undef writememb - -#define readmemb(s,a) ((readlookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)?readmemb386l(s,a): *((uint8_t *)readlookup2[((s)+(a))>>12]+ (s) + (a)) ) -#define writememb(s,a,v) if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememb386l(s,a,v); else *(uint8_t *)(writelookup2[((s) + (a)) >> 12] + (s) + (a)) = v - -#define writememw(s,a,v) if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFE) writememwl(s,a,v); else *(uint16_t *)(writelookup2[((s) + (a)) >> 12] + (s) + (a)) = v -#define writememl(s,a,v) if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFC) writememll(s,a,v); else *(uint32_t *)(writelookup2[((s) + (a)) >> 12] + (s) + (a)) = v - -static inline uint8_t geteab() -{ - if (mod==3) - return (rm&4)?regs[rm&3].b.h:regs[rm&3].b.l; -// cycles-=3; - if (eal_r) return *(uint8_t *)eal_r; - return readmemb(easeg,eaaddr); -} - -static inline uint16_t geteaw() -{ - if (mod==3) - return regs[rm].w; -// cycles-=3; - if (eal_r) return *(uint16_t *)eal_r; - return readmemw(easeg,eaaddr); -} - -static inline uint32_t geteal() -{ - if (mod==3) - return regs[rm].l; -// cycles-=3; - if (eal_r) return *eal_r; - return readmeml(easeg,eaaddr); -} - - -#define seteab(v) if (mod!=3) { if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,eaaddr,v); } else if (rm&4) regs[rm&3].b.h=v; else regs[rm].b.l=v -#define seteaw(v) if (mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,eaaddr,v); } else regs[rm].w=v -#define seteal(v) if (mod!=3) { if (eal_w) *eal_w=v; else writememll(easeg,eaaddr,v); } else regs[rm].l=v - - +#include "386_common.h" double ST[8]; MMX_REG MM[8]; -int ismmx = 0; +int ismmx; uint16_t npxs,npxc,tag; int TOP; -#define ST(x) ST[((TOP+(x))&7)] - -#define C0 (1<<8) -#define C1 (1<<9) -#define C2 (1<<10) -#define C3 (1<<14) - -#define STATUS_ZERODIVIDE 4 - -#define x87_div(dst, src1, src2) do \ - { \ - if (((double)src2) == 0.0) \ - { \ - npxs |= STATUS_ZERODIVIDE; \ - if (npxc & STATUS_ZERODIVIDE) \ - dst = src1 / (double)src2; \ - else \ - { \ - pclog("FPU : divide by zero\n"); \ - picint(1 << 13); \ - } \ - return; \ - } \ - else \ - dst = src1 / (double)src2; \ - } while (0) - -void x87_set_mmx() -{ - TOP = 0; - tag = 0; - ismmx = 1; -} - -void x87_emms() -{ - tag = 0xffff; - ismmx = 0; -} - -void x87_checkexceptions() -{ -} - -void x87_reset() -{ -} void x87_dumpregs() { @@ -142,1283 +55,6 @@ void x87_print() } } -void x87_push(double i) +void x87_reset() { - TOP=(TOP-1)&7; - ST[TOP]=i; - tag&=~(3<<((TOP&7)<<1)); - if (i==0.0) tag|=(1<<((TOP&7)<<1)); } - -double x87_pop() -{ - double t=ST[TOP]; - tag|=(3<<((TOP&7)<<1)); - TOP=(TOP+1)&7; - return t; -} - -int64_t x87_fround(double b) -{ - switch ((npxc>>10)&3) - { - case 0: /*Nearest*/ - return (int64_t)(b+0.5); - case 1: /*Down*/ - return (int64_t)floor(b); - case 2: /*Up*/ - return (int64_t)ceil(b); - case 3: /*Chop*/ - return (int64_t)b; - } -} -#define BIAS80 16383 -#define BIAS64 1023 - -double x87_ld80() -{ - struct { - int16_t begin; - union - { - double d; - uint64_t ll; - } eind; - } test; - test.eind.ll = readmeml(easeg,eaaddr); - test.eind.ll |= (uint64_t)readmeml(easeg,eaaddr+4)<<32; - test.begin = readmemw(easeg,eaaddr+8); - - int64_t exp64 = (((test.begin&0x7fff) - BIAS80)); - int64_t blah = ((exp64 >0)?exp64:-exp64)&0x3ff; - int64_t exp64final = ((exp64 >0)?blah:-blah) +BIAS64; - - int64_t mant64 = (test.eind.ll >> 11) & (0xfffffffffffff); - int64_t sign = (test.begin&0x8000)?1:0; - - if ((test.begin & 0x7fff) == 0x7fff) - exp64final = 0x7ff; - if ((test.begin & 0x7fff) == 0) - exp64final = 0; - if (test.eind.ll & 0x400) - mant64++; - - test.eind.ll = (sign <<63)|(exp64final << 52)| mant64; - - return test.eind.d; -} - -void x87_st80(double d) -{ - struct { - int16_t begin; - union - { - double d; - uint64_t ll; - } eind; - } test; - - test.eind.d=d; - - int64_t sign80 = (test.eind.ll&(0x8000000000000000))?1:0; - int64_t exp80 = test.eind.ll&(0x7ff0000000000000); - int64_t exp80final = (exp80>>52); - int64_t mant80 = test.eind.ll&(0x000fffffffffffff); - int64_t mant80final = (mant80 << 11); - - if (exp80final == 0x7ff) /*Infinity / Nan*/ - { - exp80final = 0x7fff; - mant80final |= (0x8000000000000000); - } - else if (d != 0){ //Zero is a special case - // Elvira wants the 8 and tcalc doesn't - mant80final |= (0x8000000000000000); - //Ca-cyber doesn't like this when result is zero. - exp80final += (BIAS80 - BIAS64); - } - test.begin = (((int16_t)sign80)<<15)| (int16_t)exp80final; - test.eind.ll = mant80final; - - writememl(easeg,eaaddr,test.eind.ll); - writememl(easeg,eaaddr+4,test.eind.ll>>32); - writememw(easeg,eaaddr+8,test.begin); -} - -void x87_ldmmx(MMX_REG *r) -{ - r->l[0] = readmeml(easeg, eaaddr); - r->l[1] = readmeml(easeg, eaaddr + 4); - r->w[4] = readmemw(easeg, eaaddr + 8); -} - -void x87_stmmx(MMX_REG r) -{ - writememl(easeg, eaaddr, r.l[0]); - writememl(easeg, eaaddr + 4, r.l[1]); - writememw(easeg, eaaddr + 8, 0xffff); -} - -void x87_d8(uint32_t fetchdat) -{ - union - { - float s; - uint32_t i; - } ts; - if (mod==3) - { - switch (fetchdat&0xFF) - { - case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FADD*/ - case 0xC4: case 0xC5: case 0xC6: case 0xC7: - if (fplog) pclog("FADD\n"); - ST(0)=ST(0)+ST(fetchdat&7); - cycles-=8; - return; - case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FMUL*/ - case 0xCC: case 0xCD: case 0xCE: case 0xCF: - if (fplog) pclog("FMUL\n"); - ST(0)=ST(0)*ST(fetchdat&7); - cycles-=16; - return; - case 0xD0: case 0xD1: case 0xD2: case 0xD3: /*FCOM*/ - case 0xD4: case 0xD5: case 0xD6: case 0xD7: - if (fplog) pclog("FCOM\n"); - npxs&=~(C0|C2|C3); - if (ST(0)==ST(fetchdat&7)) npxs|=C3; - else if (ST(0)> ((TOP & 7) << 1)) & 3; - tag &= ~(3 << (((TOP + fetchdat) & 7) << 1)); - tag |= (temp << (((TOP + fetchdat) & 7) << 1)); - x87_pop(); - cycles-=3; - return; - case 0xE0: /*FCHS*/ - if (fplog) pclog("FCHS\n"); - ST(0)=-ST(0); - cycles-=6; - return; - case 0xE1: /*FABS*/ - if (fplog) pclog("FABS %f\n", ST(0)); - ST(0)=fabs(ST(0)); - cycles-=3; - return; - case 0xE4: /*FTST*/ - if (fplog) pclog("FTST\n"); - npxs&=~(C0|C2|C3); - if (ST(0)==0.0) npxs|=C3; - else if (ST(0)<0.0) npxs|=C0; - cycles-=4; - return; - case 0xE5: /*FXAM*/ - if (fplog) pclog("FXAM %i %f\n", ((tag>>((TOP&7)<<1))&3), ST(0)); -// pclog("FXAM %f %i\n",ST(0),(tag>>((TOP&7)<<1))&3); - npxs&=~(C0|C2|C3); - if (((tag>>((TOP&7)<<1))&3)==3) npxs|=(C0|C3); - else if (ST(0)==0.0) npxs|=C3; - else npxs|=C2; - if (ST(0)<0.0) npxs|=C1; - cycles-=8; - return; - case 0xE8: /*FLD1*/ - if (fplog) pclog("FLD1\n"); - x87_push(1.0); - cycles-=4; - return; - case 0xE9: /*FLDL2T*/ - if (fplog) pclog("FLDL2T\n"); - x87_push(3.3219280948873623); - cycles-=8; - return; - case 0xEA: /*FLDL2E*/ - if (fplog) pclog("FLDL2E\n"); - x87_push(1.4426950408889634); - cycles-=8; - return; - case 0xEB: /*FLDPI*/ - if (fplog) pclog("FLDPI\n"); - x87_push(3.141592653589793); - cycles-=8; - return; - case 0xEC: /*FLDEG2*/ - if (fplog) pclog("FLDEG2\n"); - x87_push(0.3010299956639812); - cycles-=8; - return; - case 0xED: /*FLDLN2*/ - if (fplog) pclog("FLDLN2\n"); - x87_push(0.693147180559945); - cycles-=8; - return; - case 0xEE: /*FLDZ*/ - if (fplog) pclog("FLDZ\n"); -// pclog("FLDZ %04X:%08X\n",CS,pc); - x87_push(0.0); - tag|=(1<<((TOP&7)<<1)); - cycles-=4; - return; - case 0xF0: /*F2XM1*/ - if (fplog) pclog("F2XM1\n"); - ST(0)=pow(2.0,ST(0))-1.0; - cycles-=200; - return; - case 0xF1: /*FYL2X*/ - if (fplog) pclog("FYL2X\n"); - ST(1)=ST(1)*(log(ST(0))/log(2.0)); - x87_pop(); - cycles-=250; - return; - case 0xF2: /*FPTAN*/ - if (fplog) pclog("FPTAN\n"); -// pclog("Tan of %f = ",ST(0)); - ST(0)=tan(ST(0)); -// pclog("%f\n",ST(0)); - x87_push(1.0); - npxs&=~C2; - cycles-=235; - return; - case 0xF3: /*FPATAN*/ - if (fplog) pclog("FPATAN\n"); -/* times++; - if (times==50) - { - dumpregs(); - exit(-1); - }*/ -// pclog("FPATAN %08X\n",pc); - ST(1)=atan2(ST(1),ST(0)); - x87_pop(); - cycles-=250; - return; - case 0xF6: /*FDECSTP*/ - if (fplog) pclog("FDECSTP\n"); - TOP=(TOP-1)&7; - return; - case 0xF7: /*FINCSTP*/ - if (fplog) pclog("FINCSTP\n"); - TOP=(TOP+1)&7; - return; - case 0xF8: /*FPREM*/ - if (fplog) pclog("FPREM %f %f ", ST(0), ST(1)); - temp64=(int64_t)(ST(0)/ST(1)); - ST(0)=ST(0)-(ST(1)*(double)temp64); - if (fplog) pclog("%f\n", ST(0)); - npxs&=~(C0|C1|C2|C3); - if (temp64&4) npxs|=C0; - if (temp64&2) npxs|=C3; - if (temp64&1) npxs|=C1; - cycles-=100; - return; - case 0xFA: /*FSQRT*/ - if (fplog) pclog("FSQRT\n"); - ST(0)=sqrt(ST(0)); - cycles-=83; - return; - case 0xFB: /*FSINCOS*/ - if (fplog) pclog("FSINCOS\n"); - td=ST(0); - ST(0)=sin(td); - x87_push(cos(td)); - npxs&=~C2; - cycles-=330; - return; - case 0xFC: /*FRNDINT*/ - if (fplog) pclog("FRNDINT %g ", ST(0)); -// pclog("FRNDINT %f %i ",ST(0),(npxc>>10)&3); - ST(0)=(double)x87_fround(ST(0)); -// pclog("%f\n",ST(0)); - if (fplog) pclog("%g\n", ST(0)); - cycles-=21; - return; - case 0xFD: /*FSCALE*/ - if (fplog) pclog("FSCALE\n"); - temp64=(int64_t)ST(1); - ST(0)=ST(0)*pow(2.0,(double)temp64); - cycles-=30; - return; - case 0xFE: /*FSIN*/ - if (fplog) pclog("FSIN\n"); - ST(0)=sin(ST(0)); - npxs&=~C2; - cycles-=300; - return; - case 0xFF: /*FCOS*/ - if (fplog) pclog("FCOS\n"); - ST(0)=cos(ST(0)); - npxs&=~C2; - cycles-=300; - return; - } - } - else - { - switch (reg) - { - case 0: /*FLD single-precision*/ - if (fplog) pclog("FLDs %08X:%08X\n", easeg, eaaddr); -// if ((fetchdat&0xFFFF)==0xD445) { pclog("FLDS\n"); output=3; dumpregs(); exit(-1); } - ts.i=geteal(); if (abrt) { pclog("FLD sp abort\n"); return; } - if (fplog) pclog(" %f\n", ts.s); - x87_push((double)ts.s); - cycles-=3; - return; - case 2: /*FST single-precision*/ - if (fplog) pclog("FSTs %08X:%08X\n", easeg, eaaddr); - ts.s=(float)ST(0); - seteal(ts.i); - if (abrt) { pclog("FST sp abort\n"); return; } - cycles-=7; - return; - case 3: /*FSTP single-precision*/ - if (fplog) pclog("FSTPs %08X:%08X %f\n", easeg, eaaddr, ST(0)); - ts.s=(float)ST(0); - seteal(ts.i); if (abrt) { pclog("FSTP sp abort\n"); return; } - // if (pc==0x3f50c) pclog("FSTP %f %f %08X\n",ST(0),ts.s,ts.i); - x87_pop(); - cycles-=7; - return; - case 4: /*FLDENV*/ - if (fplog) pclog("FLDENV %08X:%08X\n", easeg, eaaddr); - switch ((cr0&1)|(op32&0x100)) - { - case 0x000: /*16-bit real mode*/ - case 0x001: /*16-bit protected mode*/ - npxc=readmemw(easeg,eaaddr); - npxs=readmemw(easeg,eaaddr+2); - tag=readmemw(easeg,eaaddr+4); - TOP=(npxs>>11)&7; - break; - case 0x100: /*32-bit real mode*/ - case 0x101: /*32-bit protected mode*/ - npxc=readmemw(easeg,eaaddr); - npxs=readmemw(easeg,eaaddr+4); - tag=readmemw(easeg,eaaddr+8); - TOP=(npxs>>11)&7; - break; - } - cycles-=(cr0&1)?34:44; - if (abrt) { pclog("FLDENV\n"); return; } - return; - case 5: /*FLDCW*/ - if (fplog) pclog("FLDCW %08X:%08X\n", easeg, eaaddr); - tempw=geteaw(); - if (abrt) if (abrt) { pclog("FLDCW abort\n"); return; } - npxc=tempw; - cycles-=4; - return; - case 6: /*FSTENV*/ - if (fplog) pclog("FSTENV %08X:%08X\n", easeg, eaaddr); - switch ((cr0&1)|(op32&0x100)) - { - case 0x000: /*16-bit real mode*/ - writememw(easeg,eaaddr,npxc); - writememw(easeg,eaaddr+2,npxs); - writememw(easeg,eaaddr+4,tag); - writememw(easeg,eaaddr+6,x87_pc_off); - writememw(easeg,eaaddr+10,x87_op_off); - break; - case 0x001: /*16-bit protected mode*/ - writememw(easeg,eaaddr,npxc); - writememw(easeg,eaaddr+2,npxs); - writememw(easeg,eaaddr+4,tag); - writememw(easeg,eaaddr+6,x87_pc_off); - writememw(easeg,eaaddr+8,x87_pc_seg); - writememw(easeg,eaaddr+10,x87_op_off); - writememw(easeg,eaaddr+12,x87_op_seg); - break; - case 0x100: /*32-bit real mode*/ - writememw(easeg,eaaddr,npxc); - writememw(easeg,eaaddr+4,npxs); - writememw(easeg,eaaddr+8,tag); - writememw(easeg,eaaddr+12,x87_pc_off); - writememw(easeg,eaaddr+20,x87_op_off); - writememl(easeg,eaaddr+24,(x87_op_off>>16)<<12); - break; - case 0x101: /*32-bit protected mode*/ - writememw(easeg,eaaddr,npxc); - writememw(easeg,eaaddr+4,npxs); - writememw(easeg,eaaddr+8,tag); - writememl(easeg,eaaddr+12,x87_pc_off); - writememl(easeg,eaaddr+16,x87_pc_seg); - writememl(easeg,eaaddr+20,x87_op_off); - writememl(easeg,eaaddr+24,x87_op_seg); - break; - } - if (abrt) { pclog("FSTENV\n"); return; } - cycles-=(cr0&1)?56:67; - return; - case 7: /*FSTCW*/ - if (fplog) pclog("FSTCW %08X:%08X\n", easeg, eaaddr); - seteaw(npxc); - if (abrt) { pclog("FSTCW\n"); return; } - cycles-=3; - return; - } - } -// fatal("Bad x87 D9 opcode %i %02X\n",reg,fetchdat&0xFF); - x86illegal(); -} -void x87_da(uint32_t fetchdat) -{ - int32_t templ; - if (mod==3) - { - switch (fetchdat&0xFF) - { - case 0xE9: /*FUCOMPP*/ - if (fplog) pclog("FUCOMPP\n", easeg, eaaddr); - npxs&=~(C0|C2|C3); - if (ST(0)==ST(1)) npxs|=C3; - else if (ST(0) 2147483647 || temp64 < -2147483647) - fatal("FISTl out of range! %i\n", temp64);*/ - seteal((int32_t)temp64); - cycles-=28; - return; - case 3: /*FISTP short*/ - if (fplog) pclog("FISTPs %08X:%08X %g ", easeg, eaaddr, ST(0)); - temp64 = x87_fround(ST(0)); -/* if (temp64 > 2147483647 || temp64 < -2147483647) - fatal("FISTPl out of range! %i\n", temp64);*/ - if (fplog) pclog("%lli %llX\n", temp64, temp64); - seteal((int32_t)temp64); if (abrt) return; - x87_pop(); - cycles-=28; - return; - case 5: /*FLD extended*/ - if (fplog) pclog("FLDe %08X:%08X\n", easeg, eaaddr); - t=x87_ld80(); if (abrt) return; - if (fplog) pclog(" %f\n", t); - x87_push(t); - cycles-=6; - return; - case 7: /*FSTP extended*/ - if (fplog) pclog("FSTPe %08X:%08X\n", easeg, eaaddr); - x87_st80(ST(0)); if (abrt) return; - x87_pop(); - cycles-=6; - return; - } - } -// fatal("Bad x87 DB opcode %i %02X\n",reg,fetchdat&0xFF); - x86illegal(); -} -void x87_dc(uint32_t fetchdat) -{ - union - { - double d; - uint64_t i; - } t; - if (mod==3) - { - switch (fetchdat&0xFF) - { - case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FADD*/ - case 0xC4: case 0xC5: case 0xC6: case 0xC7: - if (fplog) pclog("FADD %f %f\n", ST(fetchdat & 7), ST(0)); - ST(fetchdat&7)=ST(fetchdat&7)+ST(0); - cycles-=8; - return; - case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FMUL*/ - case 0xCC: case 0xCD: case 0xCE: case 0xCF: - if (fplog) pclog("FMUL %f %f\n", ST(fetchdat & 7), ST(0)); - ST(fetchdat&7)=ST(fetchdat&7)*ST(0); - cycles-=16; - return; - case 0xE0: case 0xE1: case 0xE2: case 0xE3: /*FSUBR*/ - case 0xE4: case 0xE5: case 0xE6: case 0xE7: - if (fplog) pclog("FSUBR %f %f\n", ST(fetchdat & 7), ST(0)); - ST(fetchdat&7)=ST(0)-ST(fetchdat&7); - cycles-=8; - return; - case 0xE8: case 0xE9: case 0xEA: case 0xEB: /*FSUB*/ - case 0xEC: case 0xED: case 0xEE: case 0xEF: - if (fplog) pclog("FSUB %f %f\n", ST(fetchdat & 7), ST(0)); - ST(fetchdat&7)=ST(fetchdat&7)-ST(0); - cycles-=8; - return; - case 0xF0: case 0xF1: case 0xF2: case 0xF3: /*FDIVR*/ - case 0xF4: case 0xF5: case 0xF6: case 0xF7: - if (fplog) pclog("FDIVR %f %f\n", ST(fetchdat & 7), ST(0)); - x87_div(ST(fetchdat&7), ST(0), ST(fetchdat&7)); - cycles-=73; - return; - case 0xF8: case 0xF9: case 0xFA: case 0xFB: /*FDIV*/ - case 0xFC: case 0xFD: case 0xFE: case 0xFF: - if (fplog) pclog("FDIV %f %f\n", ST(fetchdat & 7), ST(0)); - x87_div(ST(fetchdat&7), ST(fetchdat&7), ST(0)); - cycles-=73; - return; - } - } - else - { - t.i=readmeml(easeg,eaaddr); - t.i|=(uint64_t)readmeml(easeg,eaaddr+4)<<32; - if (abrt) return; - switch (reg) - { - case 0: /*FADD double*/ - if (fplog) pclog("FADDd %08X:%08X %f %f\n", easeg, eaaddr, ST(0), t.d); - ST(0)+=t.d; - cycles-=8; - return; - case 1: /*FMUL double*/ - if (fplog) pclog("FMULd %08X:%08X %f %f\n", easeg, eaaddr, ST(0), t.d); - ST(0)*=t.d; - cycles-=14; - return; - case 2: /*FCOM double*/ - if (fplog) pclog("FCOMd %08X:%08X %f %f\n", easeg, eaaddr, ST(0), t.d); - npxs&=~(C0|C2|C3); - if (ST(0)==t.d) npxs|=C3; - else if (ST(0)> ((TOP & 7) << 1)) & 3; - tag &= ~(3 << (((TOP + fetchdat) & 7) << 1)); - tag |= (temp << (((TOP + fetchdat) & 7) << 1)); - cycles-=3; - return; - case 3: /*FSTP*/ - if (fplog) pclog("FSTP\n"); - ST(fetchdat & 7) = ST(0); - temp = (tag >> ((TOP & 7) << 1)) & 3; - tag &= ~(3 << (((TOP + fetchdat) & 7) << 1)); - tag |= (temp << (((TOP + fetchdat) & 7) << 1)); - x87_pop(); - cycles-=3; - return; - case 4: /*FUCOM*/ - if (fplog) pclog("FUCOM\n"); - npxs&=~(C0|C2|C3); - if (ST(0)==ST(fetchdat&7)) npxs|=C3; - else if (ST(0)>32)); - cycles-=8; - return; - case 3: /*FSTP double-precision*/ - if (fplog) pclog("FSTPd %08X:%08X\n", easeg, eaaddr); - t.d=ST(0); - writememl(easeg,eaaddr,t.i); - writememl(easeg,eaaddr+4,(t.i>>32)); if (abrt) return; - x87_pop(); - cycles-=8; - return; - case 4: /*FRSTOR*/ - switch ((cr0&1)|(op32&0x100)) - { - case 0x000: /*16-bit real mode*/ - case 0x001: /*16-bit protected mode*/ - npxc=readmemw(easeg,eaaddr); - npxs=readmemw(easeg,eaaddr+2); - tag=readmemw(easeg,eaaddr+4); - TOP=(npxs>>11)&7; - eaaddr+=14; - break; - case 0x100: /*32-bit real mode*/ - case 0x101: /*32-bit protected mode*/ - npxc=readmemw(easeg,eaaddr); - npxs=readmemw(easeg,eaaddr+4); - tag=readmemw(easeg,eaaddr+8); - TOP=(npxs>>11)&7; - eaaddr+=28; - break; - } - x87_ldmmx(&MM[0]); ST(0)=x87_ld80(); eaaddr += 10; - x87_ldmmx(&MM[1]); ST(1)=x87_ld80(); eaaddr += 10; - x87_ldmmx(&MM[2]); ST(2)=x87_ld80(); eaaddr += 10; - x87_ldmmx(&MM[3]); ST(3)=x87_ld80(); eaaddr += 10; - x87_ldmmx(&MM[4]); ST(4)=x87_ld80(); eaaddr += 10; - x87_ldmmx(&MM[5]); ST(5)=x87_ld80(); eaaddr += 10; - x87_ldmmx(&MM[6]); ST(6)=x87_ld80(); eaaddr += 10; - x87_ldmmx(&MM[7]); ST(7)=x87_ld80(); - ismmx = 0; - /*Horrible hack, but as PCem doesn't keep the FPU stack in 80-bit precision at all times - something like this is needed*/ - if (MM[0].w == 0xffff && MM[1].w == 0xffff && MM[2].w == 0xffff && MM[3].w == 0xffff && - MM[4].w == 0xffff && MM[5].w == 0xffff && MM[6].w == 0xffff && MM[7].w == 0xffff && - !TOP && !tag) - ismmx = 1; - - cycles-=(cr0&1)?34:44; - if (fplog) pclog("FRSTOR %08X:%08X %i %i %04X\n", easeg, eaaddr, ismmx, TOP, tag); -/* pclog("new TOP %i\n", TOP); - pclog("%04X %04X %04X %f %f %f %f %f %f %f %f\n", npxc, npxs, tag, ST(0), ST(1), ST(2), ST(3), ST(4), ST(5), ST(6), ST(7));*/ - return; - case 6: /*FSAVE*/ - if (fplog) pclog("FSAVE %08X:%08X %i\n", easeg, eaaddr, ismmx); - npxs = (npxs & ~(7 << 11)) | (TOP << 11); -/* pclog("old TOP %i %04X\n", TOP, npxs); - pclog("%04X %04X %04X %f %f %f %f %f %f %f %f\n", npxc, npxs, tag, ST(0), ST(1), ST(2), ST(3), ST(4), ST(5), ST(6), ST(7));*/ - - switch ((cr0&1)|(op32&0x100)) - { - case 0x000: /*16-bit real mode*/ - writememw(easeg,eaaddr,npxc); - writememw(easeg,eaaddr+2,npxs); - writememw(easeg,eaaddr+4,tag); - writememw(easeg,eaaddr+6,x87_pc_off); - writememw(easeg,eaaddr+10,x87_op_off); - eaaddr+=14; - if (ismmx) - { - x87_stmmx(MM[0]); eaaddr+=10; - x87_stmmx(MM[1]); eaaddr+=10; - x87_stmmx(MM[2]); eaaddr+=10; - x87_stmmx(MM[3]); eaaddr+=10; - x87_stmmx(MM[4]); eaaddr+=10; - x87_stmmx(MM[5]); eaaddr+=10; - x87_stmmx(MM[6]); eaaddr+=10; - x87_stmmx(MM[7]); - } - else - { - x87_st80(ST(0)); eaaddr+=10; - x87_st80(ST(1)); eaaddr+=10; - x87_st80(ST(2)); eaaddr+=10; - x87_st80(ST(3)); eaaddr+=10; - x87_st80(ST(4)); eaaddr+=10; - x87_st80(ST(5)); eaaddr+=10; - x87_st80(ST(6)); eaaddr+=10; - x87_st80(ST(7)); - } - break; - case 0x001: /*16-bit protected mode*/ - writememw(easeg,eaaddr,npxc); - writememw(easeg,eaaddr+2,npxs); - writememw(easeg,eaaddr+4,tag); - writememw(easeg,eaaddr+6,x87_pc_off); - writememw(easeg,eaaddr+8,x87_pc_seg); - writememw(easeg,eaaddr+10,x87_op_off); - writememw(easeg,eaaddr+12,x87_op_seg); - eaaddr+=14; - if (ismmx) - { - x87_stmmx(MM[0]); eaaddr+=10; - x87_stmmx(MM[1]); eaaddr+=10; - x87_stmmx(MM[2]); eaaddr+=10; - x87_stmmx(MM[3]); eaaddr+=10; - x87_stmmx(MM[4]); eaaddr+=10; - x87_stmmx(MM[5]); eaaddr+=10; - x87_stmmx(MM[6]); eaaddr+=10; - x87_stmmx(MM[7]); - } - else - { - x87_st80(ST(0)); eaaddr+=10; - x87_st80(ST(1)); eaaddr+=10; - x87_st80(ST(2)); eaaddr+=10; - x87_st80(ST(3)); eaaddr+=10; - x87_st80(ST(4)); eaaddr+=10; - x87_st80(ST(5)); eaaddr+=10; - x87_st80(ST(6)); eaaddr+=10; - x87_st80(ST(7)); - } - break; - case 0x100: /*32-bit real mode*/ - writememw(easeg,eaaddr,npxc); - writememw(easeg,eaaddr+4,npxs); - writememw(easeg,eaaddr+8,tag); - writememw(easeg,eaaddr+12,x87_pc_off); - writememw(easeg,eaaddr+20,x87_op_off); - writememl(easeg,eaaddr+24,(x87_op_off>>16)<<12); - eaaddr+=28; - if (ismmx) - { - x87_stmmx(MM[0]); eaaddr+=10; - x87_stmmx(MM[1]); eaaddr+=10; - x87_stmmx(MM[2]); eaaddr+=10; - x87_stmmx(MM[3]); eaaddr+=10; - x87_stmmx(MM[4]); eaaddr+=10; - x87_stmmx(MM[5]); eaaddr+=10; - x87_stmmx(MM[6]); eaaddr+=10; - x87_stmmx(MM[7]); - } - else - { - x87_st80(ST(0)); eaaddr+=10; - x87_st80(ST(1)); eaaddr+=10; - x87_st80(ST(2)); eaaddr+=10; - x87_st80(ST(3)); eaaddr+=10; - x87_st80(ST(4)); eaaddr+=10; - x87_st80(ST(5)); eaaddr+=10; - x87_st80(ST(6)); eaaddr+=10; - x87_st80(ST(7)); - } - break; - case 0x101: /*32-bit protected mode*/ - writememw(easeg,eaaddr,npxc); - writememw(easeg,eaaddr+4,npxs); - writememw(easeg,eaaddr+8,tag); - writememl(easeg,eaaddr+12,x87_pc_off); - writememl(easeg,eaaddr+16,x87_pc_seg); - writememl(easeg,eaaddr+20,x87_op_off); - writememl(easeg,eaaddr+24,x87_op_seg); - eaaddr+=28; - if (ismmx) - { - x87_stmmx(MM[0]); eaaddr+=10; - x87_stmmx(MM[1]); eaaddr+=10; - x87_stmmx(MM[2]); eaaddr+=10; - x87_stmmx(MM[3]); eaaddr+=10; - x87_stmmx(MM[4]); eaaddr+=10; - x87_stmmx(MM[5]); eaaddr+=10; - x87_stmmx(MM[6]); eaaddr+=10; - x87_stmmx(MM[7]); - } - else - { - x87_st80(ST(0)); eaaddr+=10; - x87_st80(ST(1)); eaaddr+=10; - x87_st80(ST(2)); eaaddr+=10; - x87_st80(ST(3)); eaaddr+=10; - x87_st80(ST(4)); eaaddr+=10; - x87_st80(ST(5)); eaaddr+=10; - x87_st80(ST(6)); eaaddr+=10; - x87_st80(ST(7)); - } - break; - } - cycles-=(cr0&1)?56:67; - return; - case 7: /*FSTSW*/ - if (fplog) pclog("FSTSW %08X:%08X\n", easeg, eaaddr); - seteaw((npxs&0xC7FF)|(TOP<<11)); - cycles-=3; - return; - } - } -// fatal("Bad x87 DD opcode %i %02X\n",reg,fetchdat&0xFF); - x86illegal(); -} -void x87_de(uint32_t fetchdat) -{ - int32_t templ; - if (mod==3) - { - switch (fetchdat&0xFF) - { - case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FADDP*/ - case 0xC4: case 0xC5: case 0xC6: case 0xC7: - if (fplog) pclog("FADDP %f %f\n", ST(fetchdat & 7), ST(0)); - ST(fetchdat&7)=ST(fetchdat&7)+ST(0); - x87_pop(); - cycles-=8; - return; - case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FMULP*/ - case 0xCC: case 0xCD: case 0xCE: case 0xCF: - if (fplog) pclog("FMULP %f %f\n", ST(fetchdat & 7), ST(0)); - ST(fetchdat&7)=ST(fetchdat&7)*ST(0); - x87_pop(); - cycles-=16; - return; - case 0xD9: /*FCOMPP*/ - if (fplog) pclog("FCOMPP %f %f\n", ST(0), ST(1)); - npxs&=~(C0|C2|C3); - if (*(uint64_t *)&ST(0) == ((uint64_t)1 << 63) && *(uint64_t *)&ST(1) == 0) - npxs |= C0; /*Nasty hack to fix 80387 detection*/ - else if (ST(0) == ST(1)) - npxs |= C3; - else if (ST(0) < ST(1)) - npxs |= C0; - x87_pop(); - x87_pop(); - cycles-=5; - return; - case 0xE0: case 0xE1: case 0xE2: case 0xE3: /*FSUBRP*/ - case 0xE4: case 0xE5: case 0xE6: case 0xE7: - if (fplog) pclog("FSUBRP %f %f\n", ST(fetchdat & 7), ST(0)); - ST(fetchdat&7)=ST(0)-ST(fetchdat&7); - x87_pop(); - cycles-=8; - return; - case 0xE8: case 0xE9: case 0xEA: case 0xEB: /*FSUBP*/ - case 0xEC: case 0xED: case 0xEE: case 0xEF: - if (fplog) pclog("FSUBP %f %f\n", ST(fetchdat & 7), ST(0)); - ST(fetchdat&7)=ST(fetchdat&7)-ST(0); - x87_pop(); - cycles-=8; - return; - case 0xF0: case 0xF1: case 0xF2: case 0xF3: /*FDIVRP*/ - case 0xF4: case 0xF5: case 0xF6: case 0xF7: - if (fplog) pclog("FDIVRP %f %f\n", ST(fetchdat & 7), ST(0)); - x87_div(ST(fetchdat&7), ST(0), ST(fetchdat&7)); - x87_pop(); - cycles-=73; - return; - case 0xF8: case 0xF9: case 0xFA: case 0xFB: /*FDIVP*/ - case 0xFC: case 0xFD: case 0xFE: case 0xFF: - if (fplog) pclog("FDIVP %f %f %i\n", ST(fetchdat & 7), ST(0), fetchdat & 7); - x87_div(ST(fetchdat&7), ST(fetchdat&7), ST(0)); - x87_pop(); - cycles-=73; - return; - } - } - else - { - templ=(int32_t)(int16_t)geteaw(); if (abrt) return; - switch (reg) - { - case 0: /*FIADD*/ - if (fplog) pclog("FIADDw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ); - ST(0)=ST(0)+(double)templ; - cycles-=20; - return; - case 1: /*FIMUL*/ - if (fplog) pclog("FIMULw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ); - ST(0)=ST(0)*(double)templ; - cycles-=22; - return; - case 2: /*FICOM*/ - if (fplog) pclog("FICOMw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ); - npxs&=~(C0|C2|C3); - if (ST(0)==(double)templ) npxs|=C3; - else if (ST(0)<(double)templ) npxs|=C0; - cycles-=15; - return; - case 3: /*FICOMP*/ - if (fplog) pclog("FICOMPw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ); - npxs&=~(C0|C2|C3); - if (ST(0)==(double)templ) npxs|=C3; - else if (ST(0)<(double)templ) npxs|=C0; - x87_pop(); - cycles-=15; - return; - case 4: /*FISUB*/ - if (fplog) pclog("FISUBw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ); - ST(0)=ST(0)-(double)templ; - cycles-=20; - return; - case 5: /*FISUBR*/ - if (fplog) pclog("FISUBRw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ); - ST(0)=(double)templ-ST(0); - cycles-=19; - return; - case 6: /*FIDIV*/ - if (fplog) pclog("FIDIVw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ); - x87_div(ST(0), ST(0), (double)templ); - cycles-=84; - return; - case 7: /*FIDIVR*/ - if (fplog) pclog("FIDIVRw %08X:%08X %f %f\n", easeg, eaaddr, ST(0), (double)templ); - x87_div(ST(0), (double)templ, ST(0)); - cycles-=84; - return; - } - } -// fatal("Bad x87 DE opcode %i %02X\n",reg,fetchdat&0xFF); - x86illegal(); -} -void x87_df(uint32_t fetchdat) -{ - int c; - int64_t temp64; - int16_t temp16; - double tempd; - uint8_t tempc; - if (mod==3) - { - switch (reg) - { - case 4: - switch (fetchdat&0xFF) - { - case 0xE0: /*FSTSW AX*/ - if (fplog) pclog("FSTSW\n"); - AX=npxs; - cycles-=3; - return; - } - break; - } - } - else - { - switch (reg) - { - case 0: /*FILD short*/ - if (fplog) pclog("FILDw %08X:%08X\n", easeg, eaaddr); - temp16=geteaw(); if (abrt) return; - if (fplog) pclog(" %f\n", (double)temp16); - x87_push((double)temp16); - cycles-=13; - return; - case 2: /*FIST word*/ - if (fplog) pclog("FISTw %08X:%08X\n", easeg, eaaddr); - temp64 = x87_fround(ST(0)); -/* if (temp64 > 32767 || temp64 < -32768) - fatal("FISTw overflow %i\n", temp64);*/ - seteaw((int16_t)temp64); - cycles-=29; - return; - case 3: /*FISTP word*/ - if (fplog) pclog("FISTPw %08X:%08X\n", easeg, eaaddr); - temp64 = x87_fround(ST(0)); -/* if (temp64 > 32767 || temp64 < -32768) - fatal("FISTw overflow %i\n", temp64);*/ - seteaw((int16_t)temp64); if (abrt) return; - x87_pop(); - cycles-=29; - return; - case 5: /*FILD long*/ - if (fplog) pclog("FILDl %08X:%08X\n", easeg, eaaddr); - temp64=geteal(); if (abrt) return; - temp64|=(uint64_t)readmeml(easeg,eaaddr+4)<<32; - if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,eaaddr), readmeml(easeg,eaaddr+4)); - x87_push((double)temp64); - cycles-=10; - return; - case 6: /*FBSTP*/ - if (fplog) pclog("FBSTP %08X:%08X\n", easeg, eaaddr); - tempd=ST(0); - if (tempd < 0.0) - tempd = -tempd; - for (c=0;c<9;c++) - { - tempc=(uint8_t)floor(fmod(tempd,10.0)); tempd-=floor(fmod(tempd,10.0)); tempd/=10.0; - tempc|=((uint8_t)floor(fmod(tempd,10.0)))<<4; tempd-=floor(fmod(tempd,10.0)); tempd/=10.0; - writememb(easeg,eaaddr+c,tempc); - } - tempc=(uint8_t)floor(fmod(tempd,10.0)); - if (ST(0)<0.0) tempc|=0x80; - writememb(easeg,eaaddr+9,tempc); if (abrt) return; - x87_pop(); - return; - case 7: /*FISTP long*/ - if (fplog) pclog("FISTPl %08X:%08X\n", easeg, eaaddr); - temp64=x87_fround(ST(0)); - seteal(temp64); - writememl(easeg,eaaddr+4,temp64>>32); if (abrt) return; - x87_pop(); - cycles-=29; - return; - } - } -// fatal("Bad x87 DF opcode %i %02X\n",reg,fetchdat&0xFF); - x86illegal(); -} - diff --git a/src/x87.h b/src/x87.h index 84988bd..797dd4e 100644 --- a/src/x87.h +++ b/src/x87.h @@ -1,6 +1,10 @@ uint32_t x87_pc_off,x87_op_off; uint16_t x87_pc_seg,x87_op_seg; extern uint32_t op32; +extern int TOP; +extern uint16_t npxs, npxc, tag; +extern int ismmx; +extern double ST[8]; typedef union MMX_REG { @@ -16,5 +20,5 @@ typedef union MMX_REG extern MMX_REG MM[8]; -void x87_set_mmx(); -void x87_emms(); +static inline void x87_set_mmx(); +static inline void x87_emms(); diff --git a/src/x87_ops.h b/src/x87_ops.h new file mode 100644 index 0000000..2294134 --- /dev/null +++ b/src/x87_ops.h @@ -0,0 +1,784 @@ +#include + +#define fplog 0 + +#define ST(x) ST[((TOP+(x))&7)] + +#define C0 (1<<8) +#define C1 (1<<9) +#define C2 (1<<10) +#define C3 (1<<14) + +#define STATUS_ZERODIVIDE 4 + +#define x87_div(dst, src1, src2) do \ + { \ + if (((double)src2) == 0.0) \ + { \ + npxs |= STATUS_ZERODIVIDE; \ + if (npxc & STATUS_ZERODIVIDE) \ + dst = src1 / (double)src2; \ + else \ + { \ + pclog("FPU : divide by zero\n"); \ + picint(1 << 13); \ + } \ + return; \ + } \ + else \ + dst = src1 / (double)src2; \ + } while (0) + +static inline void x87_set_mmx() +{ + TOP = 0; + tag = 0; + ismmx = 1; +} + +static inline void x87_emms() +{ + tag = 0xffff; + ismmx = 0; +} + +static inline void x87_checkexceptions() +{ +} + +static inline void x87_push(double i) +{ + TOP=(TOP-1)&7; + ST[TOP]=i; + tag&=~(3<<((TOP&7)<<1)); + if (i==0.0) tag|=(1<<((TOP&7)<<1)); +} + +static inline double x87_pop() +{ + double t=ST[TOP]; + tag|=(3<<((TOP&7)<<1)); + TOP=(TOP+1)&7; + return t; +} + +static inline int64_t x87_fround(double b) +{ + switch ((npxc>>10)&3) + { + case 0: /*Nearest*/ + return (int64_t)(b+0.5); + case 1: /*Down*/ + return (int64_t)floor(b); + case 2: /*Up*/ + return (int64_t)ceil(b); + case 3: /*Chop*/ + return (int64_t)b; + } +} +#define BIAS80 16383 +#define BIAS64 1023 + +static inline double x87_ld80() +{ + struct { + int16_t begin; + union + { + double d; + uint64_t ll; + } eind; + } test; + test.eind.ll = readmeml(easeg,eaaddr); + test.eind.ll |= (uint64_t)readmeml(easeg,eaaddr+4)<<32; + test.begin = readmemw(easeg,eaaddr+8); + + int64_t exp64 = (((test.begin&0x7fff) - BIAS80)); + int64_t blah = ((exp64 >0)?exp64:-exp64)&0x3ff; + int64_t exp64final = ((exp64 >0)?blah:-blah) +BIAS64; + + int64_t mant64 = (test.eind.ll >> 11) & (0xfffffffffffff); + int64_t sign = (test.begin&0x8000)?1:0; + + if ((test.begin & 0x7fff) == 0x7fff) + exp64final = 0x7ff; + if ((test.begin & 0x7fff) == 0) + exp64final = 0; + if (test.eind.ll & 0x400) + mant64++; + + test.eind.ll = (sign <<63)|(exp64final << 52)| mant64; + + return test.eind.d; +} + +static inline void x87_st80(double d) +{ + struct { + int16_t begin; + union + { + double d; + uint64_t ll; + } eind; + } test; + + test.eind.d=d; + + int64_t sign80 = (test.eind.ll&(0x8000000000000000))?1:0; + int64_t exp80 = test.eind.ll&(0x7ff0000000000000); + int64_t exp80final = (exp80>>52); + int64_t mant80 = test.eind.ll&(0x000fffffffffffff); + int64_t mant80final = (mant80 << 11); + + if (exp80final == 0x7ff) /*Infinity / Nan*/ + { + exp80final = 0x7fff; + mant80final |= (0x8000000000000000); + } + else if (d != 0){ //Zero is a special case + // Elvira wants the 8 and tcalc doesn't + mant80final |= (0x8000000000000000); + //Ca-cyber doesn't like this when result is zero. + exp80final += (BIAS80 - BIAS64); + } + test.begin = (((int16_t)sign80)<<15)| (int16_t)exp80final; + test.eind.ll = mant80final; + + writememl(easeg,eaaddr,test.eind.ll); + writememl(easeg,eaaddr+4,test.eind.ll>>32); + writememw(easeg,eaaddr+8,test.begin); +} + +static inline void x87_ldmmx(MMX_REG *r) +{ + r->l[0] = readmeml(easeg, eaaddr); + r->l[1] = readmeml(easeg, eaaddr + 4); + r->w[4] = readmemw(easeg, eaaddr + 8); +} + +static inline void x87_stmmx(MMX_REG r) +{ + writememl(easeg, eaaddr, r.l[0]); + writememl(easeg, eaaddr + 4, r.l[1]); + writememw(easeg, eaaddr + 8, 0xffff); +} + +typedef union +{ + float s; + uint32_t i; +} x87_ts; + +typedef union +{ + double d; + uint64_t i; +} x87_td; + +#define FP_ENTER() do \ + { \ + flags_rebuild(); \ + if (cr0 & 0xc) \ + { \ + x86_int(7); \ + return 1; \ + } \ + fpucount++; \ + } while (0) + +#include "x87_ops_arith.h" +#include "x87_ops_misc.h" +#include "x87_ops_loadstore.h" + +static int op_nofpu_a16(uint32_t fetchdat) +{ + if (cr0 & 0xc) + { + x86_int(7); + return 1; + } + else + fetch_ea_16(fetchdat); +} +static int op_nofpu_a32(uint32_t fetchdat) +{ + if (cr0 & 0xc) + { + x86_int(7); + return 1; + } + else + fetch_ea_32(fetchdat); +} + +OpFn OP_TABLE(fpu_d8_a16)[32] = +{ + opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, + opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, + opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, + opFADD, opFMUL, opFCOM, opFCOMP, opFSUB, opFSUBR, opFDIV, opFDIVR +}; +OpFn OP_TABLE(fpu_d8_a32)[32] = +{ + opFADDs_a32, opFMULs_a32, opFCOMs_a32, opFCOMPs_a32, opFSUBs_a32, opFSUBRs_a32, opFDIVs_a32, opFDIVRs_a32, + opFADDs_a32, opFMULs_a32, opFCOMs_a32, opFCOMPs_a32, opFSUBs_a32, opFSUBRs_a32, opFDIVs_a32, opFDIVRs_a32, + opFADDs_a32, opFMULs_a32, opFCOMs_a32, opFCOMPs_a32, opFSUBs_a32, opFSUBRs_a32, opFDIVs_a32, opFDIVRs_a32, + opFADD, opFMUL, opFCOM, opFCOMP, opFSUB, opFSUBR, opFDIV, opFDIVR +}; + +OpFn OP_TABLE(fpu_d9_a16)[256] = +{ + opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, + opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, + opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, + opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, + + opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, + opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, + opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, + opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, + + opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, + opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, + opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, + opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, + + opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, + opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, + opFNOP, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, /*Invalid*/ + opFCHS, opFABS, ILLEGAL, ILLEGAL, opFTST, opFXAM, ILLEGAL, ILLEGAL, + opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL, + opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL, ILLEGAL, opFDECSTP, opFINCSTP, + opFPREM, ILLEGAL, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS +}; + +OpFn OP_TABLE(fpu_d9_a32)[256] = +{ + opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, + opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, + opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, + opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, + opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, + opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, + + opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, + opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, + opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, + opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, + opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, + opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, + + opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, + opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, + opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, + opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, + opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, + opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, + + opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, + opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, + opFNOP, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, /*Invalid*/ + opFCHS, opFABS, ILLEGAL, ILLEGAL, opFTST, opFXAM, ILLEGAL, ILLEGAL, + opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL, + opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL, ILLEGAL, opFDECSTP, opFINCSTP, + opFPREM, ILLEGAL, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS +}; + +OpFn OP_TABLE(fpu_da_a16)[256] = +{ + opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, + opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, + opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, + opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, + opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, + opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, + opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, + opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, + + opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, + opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, + opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, + opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, + opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, + opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, + opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, + opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, + + opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, + opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, + opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, opFCOMil_a16, + opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, opFCOMPil_a16, + opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, opFSUBil_a16, + opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, opFSUBRil_a16, + opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, opFDIVil_a16, + opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, opFDIVRil_a16, + + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, opFUCOMPP, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +}; +OpFn OP_TABLE(fpu_da_a32)[256] = +{ + opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, + opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, + opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, + opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, + opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, + opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, + opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, + opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, + + opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, + opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, + opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, + opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, + opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, + opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, + opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, + opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, + + opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, opFADDil_a32, + opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, opFMULil_a32, + opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, opFCOMil_a32, + opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, opFCOMPil_a32, + opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, opFSUBil_a32, + opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, opFSUBRil_a32, + opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, opFDIVil_a32, + opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, opFDIVRil_a32, + + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, opFUCOMPP, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +}; + +OpFn OP_TABLE(fpu_db_a16)[256] = +{ + opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, + opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, + + opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, + opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, + + opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, + opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, + + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, opFNOP, opFCLEX, opFINIT, opFNOP, opFNOP, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +}; +OpFn OP_TABLE(fpu_db_a32)[256] = +{ + opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, + opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, + + opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, + opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, + + opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, + opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, + + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, opFNOP, opFCLEX, opFINIT, opFNOP, opFNOP, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +}; + +OpFn OP_TABLE(fpu_dc_a16)[32] = +{ + opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, + opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, + opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, + opFADDr, opFMULr, ILLEGAL, ILLEGAL, opFSUBRr, opFSUBr, opFDIVRr, opFDIVr +}; +OpFn OP_TABLE(fpu_dc_a32)[32] = +{ + opFADDd_a32, opFMULd_a32, opFCOMd_a32, opFCOMPd_a32, opFSUBd_a32, opFSUBRd_a32, opFDIVd_a32, opFDIVRd_a32, + opFADDd_a32, opFMULd_a32, opFCOMd_a32, opFCOMPd_a32, opFSUBd_a32, opFSUBRd_a32, opFDIVd_a32, opFDIVRd_a32, + opFADDd_a32, opFMULd_a32, opFCOMd_a32, opFCOMPd_a32, opFSUBd_a32, opFSUBRd_a32, opFDIVd_a32, opFDIVRd_a32, + opFADDr, opFMULr, ILLEGAL, ILLEGAL, opFSUBRr, opFSUBr, opFDIVRr, opFDIVr +}; + +OpFn OP_TABLE(fpu_dd_a16)[256] = +{ + opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, + opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, + opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, + opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, + + opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, + opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, + opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, + opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, + + opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, + opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, + opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, + opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, + + opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFST, opFST, opFST, opFST, opFST, opFST, opFST, opFST, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, + opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, + opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +}; +OpFn OP_TABLE(fpu_dd_a32)[256] = +{ + opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, + opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, + opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, + opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, + + opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, + opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, + opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, + opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, + + opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, + opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, + opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, + opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, + + opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFST, opFST, opFST, opFST, opFST, opFST, opFST, opFST, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, + opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, + opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +}; + +OpFn OP_TABLE(fpu_de_a16)[256] = +{ + opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, + opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, + opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, + opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, + opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, + opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, + opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, + opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, + + opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, + opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, + opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, + opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, + opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, + opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, + opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, + opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, + + opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, + opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, + opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, opFCOMiw_a16, + opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, opFCOMPiw_a16, + opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, opFSUBiw_a16, + opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, opFSUBRiw_a16, + opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, opFDIViw_a16, + opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, opFDIVRiw_a16, + + opFADDP, opFADDP, opFADDP, opFADDP, opFADDP, opFADDP, opFADDP, opFADDP, + opFMULP, opFMULP, opFMULP, opFMULP, opFMULP, opFMULP, opFMULP, opFMULP, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, opFCOMPP, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSUBRP, opFSUBRP, opFSUBRP, opFSUBRP, opFSUBRP, opFSUBRP, opFSUBRP, opFSUBRP, + opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, + opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, + opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, +}; + +OpFn OP_TABLE(fpu_de_a32)[256] = +{ + opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, + opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, + opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, + opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, + opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, + opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, + opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, + opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, + + opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, + opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, + opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, + opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, + opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, + opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, + opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, + opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, + + opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, opFADDiw_a32, + opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, opFMULiw_a32, + opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, opFCOMiw_a32, + opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, opFCOMPiw_a32, + opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, opFSUBiw_a32, + opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, opFSUBRiw_a32, + opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, opFDIViw_a32, + opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, opFDIVRd_a32, + + opFADDP, opFADDP, opFADDP, opFADDP, opFADDP, opFADDP, opFADDP, opFADDP, + opFMULP, opFMULP, opFMULP, opFMULP, opFMULP, opFMULP, opFMULP, opFMULP, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, opFCOMPP, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSUBRP, opFSUBRP, opFSUBRP, opFSUBRP, opFSUBRP, opFSUBRP, opFSUBRP, opFSUBRP, + opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, opFSUBP, + opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, opFDIVRP, + opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, opFDIVP, +}; + +OpFn OP_TABLE(fpu_df_a16)[256] = +{ + opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, + opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, + FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, + FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, + + opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, + opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, + FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, + FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, + + opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, + opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, + FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, + FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, + + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTSW_AX, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +}; +OpFn OP_TABLE(fpu_df_a32)[256] = +{ + opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, + opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, + FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, + FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, + + opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, + opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, + FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, + FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, + + opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, + opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, + FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, + FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, + + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + opFSTSW_AX, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +}; + +OpFn OP_TABLE(nofpu_a16)[256] = +{ + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, + op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, +}; +OpFn OP_TABLE(nofpu_a32)[256] = +{ + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, + op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, op_nofpu_a32, +}; diff --git a/src/x87_ops_arith.h b/src/x87_ops_arith.h new file mode 100644 index 0000000..30a6503 --- /dev/null +++ b/src/x87_ops_arith.h @@ -0,0 +1,343 @@ +#define opFPU(name, optype, a_size, load_var, get, use_var) \ +static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \ +{ \ + optype t; \ + FP_ENTER(); \ + fetch_ea_ ## a_size(fetchdat); \ + load_var = get(); if (abrt) return 1; \ + ST(0) += use_var; \ + cycles -= 8; \ +} \ +static int opFCOM ## name ## _a ## a_size(uint32_t fetchdat) \ +{ \ + optype t; \ + FP_ENTER(); \ + fetch_ea_ ## a_size(fetchdat); \ + load_var = get(); if (abrt) return 1; \ + npxs &= ~(C0|C2|C3); \ + if (ST(0) == use_var) npxs |= C3; \ + else if (ST(0) < use_var) npxs |= C0; \ + cycles -= 4; \ +} \ +static int opFCOMP ## name ## _a ## a_size(uint32_t fetchdat) \ +{ \ + optype t; \ + FP_ENTER(); \ + fetch_ea_ ## a_size(fetchdat); \ + load_var = get(); if (abrt) return 1; \ + npxs &= ~(C0|C2|C3); \ + if (ST(0) == use_var) npxs |= C3; \ + else if (ST(0) < use_var) npxs |= C0; \ + x87_pop(); \ + cycles -= 4; \ +} \ +static int opFDIV ## name ## _a ## a_size(uint32_t fetchdat) \ +{ \ + optype t; \ + FP_ENTER(); \ + fetch_ea_ ## a_size(fetchdat); \ + load_var = get(); if (abrt) return 1; \ + x87_div(ST(0), ST(0), use_var); \ + cycles -= 73; \ +} \ +static int opFDIVR ## name ## _a ## a_size(uint32_t fetchdat) \ +{ \ + optype t; \ + FP_ENTER(); \ + fetch_ea_ ## a_size(fetchdat); \ + load_var = get(); if (abrt) return 1; \ + x87_div(ST(0), use_var, ST(0)); \ + cycles -= 73; \ +} \ +static int opFMUL ## name ## _a ## a_size(uint32_t fetchdat) \ +{ \ + optype t; \ + FP_ENTER(); \ + fetch_ea_ ## a_size(fetchdat); \ + load_var = get(); if (abrt) return 1; \ + ST(0) *= use_var; \ + cycles -= 11; \ +} \ +static int opFSUB ## name ## _a ## a_size(uint32_t fetchdat) \ +{ \ + optype t; \ + FP_ENTER(); \ + fetch_ea_ ## a_size(fetchdat); \ + load_var = get(); if (abrt) return 1; \ + ST(0) -= use_var; \ + cycles -= 8; \ +} \ +static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \ +{ \ + optype t; \ + FP_ENTER(); \ + fetch_ea_ ## a_size(fetchdat); \ + load_var = get(); if (abrt) return 1; \ + ST(0) = use_var - ST(0); \ + cycles -= 8; \ +} + + +opFPU(s, x87_ts, 16, t.i, geteal, t.s) +opFPU(s, x87_ts, 32, t.i, geteal, t.s) +opFPU(d, x87_td, 16, t.i, geteaq, t.d) +opFPU(d, x87_td, 32, t.i, geteaq, t.d) + +opFPU(iw, uint16_t, 16, t, geteaw, (double)(int16_t)t) +opFPU(iw, uint16_t, 32, t, geteaw, (double)(int16_t)t) +opFPU(il, uint32_t, 16, t, geteal, (double)(int32_t)t) +opFPU(il, uint32_t, 32, t, geteal, (double)(int32_t)t) + + + + +static int opFADD(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FADD\n"); + ST(0) = ST(0) + ST(fetchdat & 7); + cycles -= 8; + return 0; +} +static int opFADDr(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FADD\n"); + ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); + cycles -= 8; + return 0; +} +static int opFADDP(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FADDP\n"); + ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); + x87_pop(); + cycles -= 8; + return 0; +} + +static int opFCOM(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FCOM\n"); + npxs &= ~(C0|C2|C3); + if (ST(0) == ST(fetchdat & 7)) npxs |= C3; + else if (ST(0) < ST(fetchdat & 7)) npxs |= C0; + cycles -= 4; + return 0; +} + +static int opFCOMP(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FCOMP\n"); + npxs &= ~(C0|C2|C3); + if (ST(0) == ST(fetchdat & 7)) npxs |= C3; + else if (ST(0) < ST(fetchdat & 7)) npxs |= C0; + x87_pop(); + cycles -= 4; + return 0; +} + +static int opFCOMPP(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FCOMPP\n"); + npxs &= ~(C0|C2|C3); + if (ST(0) == ST(1)) npxs |= C3; + else if (ST(0) < ST(1)) npxs |= C0; + x87_pop(); + x87_pop(); + cycles -= 4; + return 0; +} +static int opFUCOMPP(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FUCOMPP\n", easeg, eaaddr); + npxs &= ~(C0|C2|C3); + if (ST(0) == ST(1)) npxs |= C3; + else if (ST(0) < ST(1)) npxs |= C0; + x87_pop(); + x87_pop(); + cycles -= 5; + return 0; +} + +static int opFDIV(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FDIV\n"); + x87_div(ST(0), ST(0), ST(fetchdat & 7)); + cycles -= 73; + return 0; +} +static int opFDIVr(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FDIV\n"); + x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); + cycles -= 73; + return 0; +} +static int opFDIVP(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FDIVP\n"); + x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); + x87_pop(); + cycles -= 73; + return 0; +} + +static int opFDIVR(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FDIVR\n"); + x87_div(ST(0), ST(fetchdat&7), ST(0)); + cycles -= 73; + return 0; +} +static int opFDIVRr(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FDIVR\n"); + x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); + cycles -= 73; + return 0; +} +static int opFDIVRP(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FDIVR\n"); + x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); + x87_pop(); + cycles -= 73; + return 0; +} + +static int opFMUL(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FMUL\n"); + ST(0) = ST(0) * ST(fetchdat & 7); + cycles -= 16; + return 0; +} +static int opFMULr(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FMUL\n"); + ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); + cycles -= 16; + return 0; +} +static int opFMULP(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FMULP\n"); + ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); + x87_pop(); + cycles -= 16; + return 0; +} + +static int opFSUB(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FSUB\n"); + ST(0) = ST(0) - ST(fetchdat & 7); + cycles -= 8; + return 0; +} +static int opFSUBr(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FSUB\n"); + ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); + cycles -= 8; + return 0; +} +static int opFSUBP(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FSUBP\n"); + ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); + x87_pop(); + cycles -= 8; + return 0; +} + +static int opFSUBR(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FSUBR\n"); + ST(0) = ST(fetchdat & 7) - ST(0); + cycles -= 8; + return 0; +} +static int opFSUBRr(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FSUBR\n"); + ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); + cycles -= 8; + return 0; +} +static int opFSUBRP(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FSUBRP\n"); + ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); + x87_pop(); + cycles -= 8; + return 0; +} + +static int opFUCOM(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FUCOM\n"); + npxs &= ~(C0|C2|C3); + if (ST(0) == ST(fetchdat&7)) npxs |= C3; + else if (ST(0) < ST(fetchdat&7)) npxs |= C0; + cycles -= 4; + return 0; +} + +static int opFUCOMP(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FUCOMP\n"); + npxs &= ~(C0|C2|C3); + if (ST(0) == ST(fetchdat&7)) npxs |= C3; + else if (ST(0) < ST(fetchdat&7)) npxs |= C0; + x87_pop(); + cycles -= 4; + return 0; +} diff --git a/src/x87_ops_loadstore.h b/src/x87_ops_loadstore.h new file mode 100644 index 0000000..9ac5f4f --- /dev/null +++ b/src/x87_ops_loadstore.h @@ -0,0 +1,456 @@ +static int opFILDiw_a16(uint32_t fetchdat) +{ + int16_t temp; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FILDw %08X:%08X\n", easeg, eaaddr); + temp = geteaw(); if (abrt) return 1; + if (fplog) pclog(" %f\n", (double)temp); + x87_push((double)temp); + cycles -= 13; + return 0; +} +static int opFILDiw_a32(uint32_t fetchdat) +{ + int16_t temp; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FILDw %08X:%08X\n", easeg, eaaddr); + temp = geteaw(); if (abrt) return 1; + if (fplog) pclog(" %f\n", (double)temp); + x87_push((double)temp); + cycles -= 13; + return 0; +} + +static int opFISTiw_a16(uint32_t fetchdat) +{ + int64_t temp64; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FISTw %08X:%08X\n", easeg, eaaddr); + temp64 = x87_fround(ST(0)); +/* if (temp64 > 32767 || temp64 < -32768) + fatal("FISTw overflow %i\n", temp64);*/ + seteaw((int16_t)temp64); + cycles -= 29; + return abrt; +} +static int opFISTiw_a32(uint32_t fetchdat) +{ + int64_t temp64; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FISTw %08X:%08X\n", easeg, eaaddr); + temp64 = x87_fround(ST(0)); +/* if (temp64 > 32767 || temp64 < -32768) + fatal("FISTw overflow %i\n", temp64);*/ + seteaw((int16_t)temp64); + cycles -= 29; + return abrt; +} + +static int opFISTPiw_a16(uint32_t fetchdat) +{ + int64_t temp64; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FISTw %08X:%08X\n", easeg, eaaddr); + temp64 = x87_fround(ST(0)); +/* if (temp64 > 32767 || temp64 < -32768) + fatal("FISTw overflow %i\n", temp64);*/ + seteaw((int16_t)temp64); if (abrt) return 1; + x87_pop(); + cycles -= 29; + return 0; +} +static int opFISTPiw_a32(uint32_t fetchdat) +{ + int64_t temp64; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FISTw %08X:%08X\n", easeg, eaaddr); + temp64 = x87_fround(ST(0)); +/* if (temp64 > 32767 || temp64 < -32768) + fatal("FISTw overflow %i\n", temp64);*/ + seteaw((int16_t)temp64); if (abrt) return 1; + x87_pop(); + cycles -= 29; + return 0; +} + +static int opFILDiq_a16(uint32_t fetchdat) +{ + int64_t temp64; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FILDl %08X:%08X\n", easeg, eaaddr); + temp64 = geteaq(); if (abrt) return 1; + if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,eaaddr), readmeml(easeg,eaaddr+4)); + x87_push((double)temp64); + cycles -= 10; + return 0; +} +static int opFILDiq_a32(uint32_t fetchdat) +{ + int64_t temp64; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FILDl %08X:%08X\n", easeg, eaaddr); + temp64 = geteaq(); if (abrt) return 1; + if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,eaaddr), readmeml(easeg,eaaddr+4)); + x87_push((double)temp64); + cycles -= 10; + return 0; +} + +static int FBSTP_a16(uint32_t fetchdat) +{ + double tempd; + int c; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FBSTP %08X:%08X\n", easeg, eaaddr); + tempd = ST(0); + if (tempd < 0.0) + tempd = -tempd; + for (c = 0; c < 9; c++) + { + uint8_t tempc = (uint8_t)floor(fmod(tempd, 10.0)); + tempd -= floor(fmod(tempd, 10.0)); + tempd /= 10.0; + tempc |= ((uint8_t)floor(fmod(tempd, 10.0))) << 4; + tempd -= floor(fmod(tempd, 10.0)); + tempd /= 10.0; + writememb(easeg, eaaddr + c, tempc); + } + tempc = (uint8_t)floor(fmod(tempd, 10.0)); + if (ST(0) < 0.0) tempc |= 0x80; + writememb(easeg, eaaddr + 9, tempc); if (abrt) return 1; + x87_pop(); + return 0; +} +static int FBSTP_a32(uint32_t fetchdat) +{ + double tempd; + int c; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FBSTP %08X:%08X\n", easeg, eaaddr); + tempd = ST(0); + if (tempd < 0.0) + tempd = -tempd; + for (c = 0; c < 9; c++) + { + uint8_t tempc = (uint8_t)floor(fmod(tempd, 10.0)); + tempd -= floor(fmod(tempd, 10.0)); + tempd /= 10.0; + tempc |= ((uint8_t)floor(fmod(tempd, 10.0))) << 4; + tempd -= floor(fmod(tempd, 10.0)); + tempd /= 10.0; + writememb(easeg, eaaddr + c, tempc); + } + tempc = (uint8_t)floor(fmod(tempd, 10.0)); + if (ST(0) < 0.0) tempc |= 0x80; + writememb(easeg, eaaddr + 9, tempc); if (abrt) return 1; + x87_pop(); + return 0; +} + +static int FISTPiq_a16(uint32_t fetchdat) +{ + int64_t temp64; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FISTPl %08X:%08X\n", easeg, eaaddr); + temp64 = x87_fround(ST(0)); + seteaq(temp64); if (abrt) return 1; + x87_pop(); + cycles -= 29; + return 1; +} +static int FISTPiq_a32(uint32_t fetchdat) +{ + int64_t temp64; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FISTPl %08X:%08X\n", easeg, eaaddr); + temp64 = x87_fround(ST(0)); + seteaq(temp64); if (abrt) return 1; + x87_pop(); + cycles -= 29; + return 1; +} + +static int opFILDil_a16(uint32_t fetchdat) +{ + int32_t templ; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FILDs %08X:%08X\n", easeg, eaaddr); + templ = geteal(); if (abrt) return 1; + if (fplog) pclog(" %f %08X %i\n", (double)templ, templ, templ); + x87_push((double)templ); + cycles -= 9; + return 0; +} +static int opFILDil_a32(uint32_t fetchdat) +{ + int32_t templ; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FILDs %08X:%08X\n", easeg, eaaddr); + templ = geteal(); if (abrt) return 1; + if (fplog) pclog(" %f %08X %i\n", (double)templ, templ, templ); + x87_push((double)templ); + cycles -= 9; + return 0; +} + +static int opFISTil_a16(uint32_t fetchdat) +{ + int64_t temp64; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FISTs %08X:%08X\n", easeg, eaaddr); + temp64 = x87_fround(ST(0)); +/* if (temp64 > 2147483647 || temp64 < -2147483647) + fatal("FISTl out of range! %i\n", temp64);*/ + seteal((int32_t)temp64); + cycles -= 28; + return abrt; +} +static int opFISTil_a32(uint32_t fetchdat) +{ + int64_t temp64; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FISTs %08X:%08X\n", easeg, eaaddr); + temp64 = x87_fround(ST(0)); +/* if (temp64 > 2147483647 || temp64 < -2147483647) + fatal("FISTl out of range! %i\n", temp64);*/ + seteal((int32_t)temp64); + cycles -= 28; + return abrt; +} + +static int opFISTPil_a16(uint32_t fetchdat) +{ + int64_t temp64; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FISTs %08X:%08X\n", easeg, eaaddr); + temp64 = x87_fround(ST(0)); +/* if (temp64 > 2147483647 || temp64 < -2147483647) + fatal("FISTl out of range! %i\n", temp64);*/ + seteal((int32_t)temp64); if (abrt) return 1; + x87_pop(); + cycles -= 28; + return 0; +} +static int opFISTPil_a32(uint32_t fetchdat) +{ + int64_t temp64; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FISTs %08X:%08X\n", easeg, eaaddr); + temp64 = x87_fround(ST(0)); +/* if (temp64 > 2147483647 || temp64 < -2147483647) + fatal("FISTl out of range! %i\n", temp64);*/ + seteal((int32_t)temp64); if (abrt) return 1; + x87_pop(); + cycles -= 28; + return 0; +} + +static int opFLDe_a16(uint32_t fetchdat) +{ + double t; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FLDe %08X:%08X\n", easeg, eaaddr); + t=x87_ld80(); if (abrt) return 1; + if (fplog) pclog(" %f\n", t); + x87_push(t); + cycles -= 6; + return 0; +} +static int opFLDe_a32(uint32_t fetchdat) +{ + double t; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FLDe %08X:%08X\n", easeg, eaaddr); + t=x87_ld80(); if (abrt) return 1; + if (fplog) pclog(" %f\n", t); + x87_push(t); + cycles -= 6; + return 0; +} + +static int opFSTPe_a16(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FSTPe %08X:%08X\n", easeg, eaaddr); + x87_st80(ST(0)); if (abrt) return 1; + x87_pop(); + cycles -= 6; + return 0; +} +static int opFSTPe_a32(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FSTPe %08X:%08X\n", easeg, eaaddr); + x87_st80(ST(0)); if (abrt) return 1; + x87_pop(); + cycles -= 6; + return 0; +} + +static int opFLDd_a16(uint32_t fetchdat) +{ + x87_td t; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FLDd %08X:%08X\n", easeg, eaaddr); + t.i = geteaq(); if (abrt) return 1; + if (fplog) pclog(" %f\n", t.d); + x87_push(t.d); + cycles -= 3; + return 0; +} +static int opFLDd_a32(uint32_t fetchdat) +{ + x87_td t; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FLDd %08X:%08X\n", easeg, eaaddr); + t.i = geteaq(); if (abrt) return 1; + if (fplog) pclog(" %f\n", t.d); + x87_push(t.d); + cycles -= 3; + return 0; +} + +static int opFSTd_a16(uint32_t fetchdat) +{ + x87_td t; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FSTd %08X:%08X\n", easeg, eaaddr); + t.d = ST(0); + seteaq(t.i); + cycles -= 8; + return abrt; +} +static int opFSTd_a32(uint32_t fetchdat) +{ + x87_td t; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FSTd %08X:%08X\n", easeg, eaaddr); + t.d = ST(0); + seteaq(t.i); + cycles -= 8; + return abrt; +} + +static int opFSTPd_a16(uint32_t fetchdat) +{ + x87_td t; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FSTd %08X:%08X\n", easeg, eaaddr); + t.d = ST(0); + seteaq(t.i); if (abrt) return 1; + x87_pop(); + cycles -= 8; + return 0; +} +static int opFSTPd_a32(uint32_t fetchdat) +{ + x87_td t; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FSTd %08X:%08X\n", easeg, eaaddr); + t.d = ST(0); + seteaq(t.i); if (abrt) return 1; + x87_pop(); + cycles -= 8; + return 0; +} + +static int opFLDs_a16(uint32_t fetchdat) +{ + x87_ts ts; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FLDs %08X:%08X\n", easeg, eaaddr); + ts.i = geteal(); if (abrt) return 1; + if (fplog) pclog(" %f\n", ts.s); + x87_push((double)ts.s); + cycles -= 3; + return 0; +} +static int opFLDs_a32(uint32_t fetchdat) +{ + x87_ts ts; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FLDs %08X:%08X\n", easeg, eaaddr); + ts.i = geteal(); if (abrt) return 1; + if (fplog) pclog(" %f\n", ts.s); + x87_push((double)ts.s); + cycles -= 3; + return 0; +} + +static int opFSTs_a16(uint32_t fetchdat) +{ + x87_ts ts; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FSTs %08X:%08X\n", easeg, eaaddr); + ts.s = (float)ST(0); + seteal(ts.i); + cycles -= 7; + return abrt; +} +static int opFSTs_a32(uint32_t fetchdat) +{ + x87_ts ts; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FSTs %08X:%08X\n", easeg, eaaddr); + ts.s = (float)ST(0); + seteal(ts.i); + cycles -= 7; + return abrt; +} + +static int opFSTPs_a16(uint32_t fetchdat) +{ + x87_ts ts; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FSTs %08X:%08X\n", easeg, eaaddr); + ts.s = (float)ST(0); + seteal(ts.i); if (abrt) return 1; + x87_pop(); + cycles -= 7; + return 0; +} +static int opFSTPs_a32(uint32_t fetchdat) +{ + x87_ts ts; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FSTs %08X:%08X\n", easeg, eaaddr); + ts.s = (float)ST(0); + seteal(ts.i); if (abrt) return 1; + x87_pop(); + cycles -= 7; + return 0; +} diff --git a/src/x87_ops_misc.h b/src/x87_ops_misc.h new file mode 100644 index 0000000..ec6d945 --- /dev/null +++ b/src/x87_ops_misc.h @@ -0,0 +1,738 @@ +static int opFSTSW_AX(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FSTSW\n"); + AX = npxs; + cycles -= 3; + return 0; +} + + + +static int opFNOP(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + cycles -= 4; + return 0; +} + +static int opFCLEX(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + npxs &= 0xff00; + cycles -= 4; + return 0; +} + +static int opFINIT(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + npxc = 0x37F; + npxs = 0; + tag = 0xFFFF; + TOP = 0; + cycles -= 17; + return 0; +} + + +static int opFFREE(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FFREE\n"); + tag |= (3 << (((TOP + fetchdat) & 7) << 1)); + cycles -= 3; + return 0; +} + +static int opFST(uint32_t fetchdat) +{ + int temp; + FP_ENTER(); + pc++; + if (fplog) pclog("FST\n"); + ST(fetchdat & 7) = ST(0); + temp = (tag >> ((TOP & 7) << 1)) & 3; + tag &= ~(3 << (((TOP + fetchdat) & 7) << 1)); + tag |= (temp << (((TOP + fetchdat) & 7) << 1)); + cycles -= 3; + return 0; +} + +static int opFSTP(uint32_t fetchdat) +{ + int temp; + FP_ENTER(); + pc++; + if (fplog) pclog("FSTP\n"); + ST(fetchdat & 7) = ST(0); + temp = (tag >> ((TOP & 7) << 1)) & 3; + tag &= ~(3 << (((TOP + fetchdat) & 7) << 1)); + tag |= (temp << (((TOP + fetchdat) & 7) << 1)); + x87_pop(); + cycles -= 3; + return 0; +} + + + + +static void FSTOR() +{ + switch ((cr0 & 1) | (op32 & 0x100)) + { + case 0x000: /*16-bit real mode*/ + case 0x001: /*16-bit protected mode*/ + npxc = readmemw(easeg, eaaddr); + npxs = readmemw(easeg, eaaddr+2); + tag = readmemw(easeg, eaaddr+4); + TOP = (npxs >> 11) & 7; + eaaddr += 14; + break; + case 0x100: /*32-bit real mode*/ + case 0x101: /*32-bit protected mode*/ + npxc = readmemw(easeg, eaaddr); + npxs = readmemw(easeg, eaaddr+4); + tag = readmemw(easeg, eaaddr+8); + TOP = (npxs >> 11) & 7; + eaaddr += 28; + break; + } + x87_ldmmx(&MM[0]); ST(0)=x87_ld80(); eaaddr += 10; + x87_ldmmx(&MM[1]); ST(1)=x87_ld80(); eaaddr += 10; + x87_ldmmx(&MM[2]); ST(2)=x87_ld80(); eaaddr += 10; + x87_ldmmx(&MM[3]); ST(3)=x87_ld80(); eaaddr += 10; + x87_ldmmx(&MM[4]); ST(4)=x87_ld80(); eaaddr += 10; + x87_ldmmx(&MM[5]); ST(5)=x87_ld80(); eaaddr += 10; + x87_ldmmx(&MM[6]); ST(6)=x87_ld80(); eaaddr += 10; + x87_ldmmx(&MM[7]); ST(7)=x87_ld80(); + ismmx = 0; + /*Horrible hack, but as PCem doesn't keep the FPU stack in 80-bit precision at all times + something like this is needed*/ + if (MM[0].w[4] == 0xffff && MM[1].w[4] == 0xffff && MM[2].w[4] == 0xffff && MM[3].w[4] == 0xffff && + MM[4].w[4] == 0xffff && MM[5].w[4] == 0xffff && MM[6].w[4] == 0xffff && MM[7].w[4] == 0xffff && + !TOP && !tag) + ismmx = 1; + + cycles -= (cr0 & 1) ? 34 : 44; + if (fplog) pclog("FRSTOR %08X:%08X %i %i %04X\n", easeg, eaaddr, ismmx, TOP, tag); +} +static int opFSTOR_a16(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_16(fetchdat); + FSTOR(); + return abrt; +} +static int opFSTOR_a32(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_32(fetchdat); + FSTOR(); + return abrt; +} + +static void FSAVE() +{ + if (fplog) pclog("FSAVE %08X:%08X %i\n", easeg, eaaddr, ismmx); + npxs = (npxs & ~(7 << 11)) | (TOP << 11); + + switch ((cr0&1)|(op32&0x100)) + { + case 0x000: /*16-bit real mode*/ + writememw(easeg,eaaddr,npxc); + writememw(easeg,eaaddr+2,npxs); + writememw(easeg,eaaddr+4,tag); + writememw(easeg,eaaddr+6,x87_pc_off); + writememw(easeg,eaaddr+10,x87_op_off); + eaaddr+=14; + if (ismmx) + { + x87_stmmx(MM[0]); eaaddr+=10; + x87_stmmx(MM[1]); eaaddr+=10; + x87_stmmx(MM[2]); eaaddr+=10; + x87_stmmx(MM[3]); eaaddr+=10; + x87_stmmx(MM[4]); eaaddr+=10; + x87_stmmx(MM[5]); eaaddr+=10; + x87_stmmx(MM[6]); eaaddr+=10; + x87_stmmx(MM[7]); + } + else + { + x87_st80(ST(0)); eaaddr+=10; + x87_st80(ST(1)); eaaddr+=10; + x87_st80(ST(2)); eaaddr+=10; + x87_st80(ST(3)); eaaddr+=10; + x87_st80(ST(4)); eaaddr+=10; + x87_st80(ST(5)); eaaddr+=10; + x87_st80(ST(6)); eaaddr+=10; + x87_st80(ST(7)); + } + break; + case 0x001: /*16-bit protected mode*/ + writememw(easeg,eaaddr,npxc); + writememw(easeg,eaaddr+2,npxs); + writememw(easeg,eaaddr+4,tag); + writememw(easeg,eaaddr+6,x87_pc_off); + writememw(easeg,eaaddr+8,x87_pc_seg); + writememw(easeg,eaaddr+10,x87_op_off); + writememw(easeg,eaaddr+12,x87_op_seg); + eaaddr+=14; + if (ismmx) + { + x87_stmmx(MM[0]); eaaddr+=10; + x87_stmmx(MM[1]); eaaddr+=10; + x87_stmmx(MM[2]); eaaddr+=10; + x87_stmmx(MM[3]); eaaddr+=10; + x87_stmmx(MM[4]); eaaddr+=10; + x87_stmmx(MM[5]); eaaddr+=10; + x87_stmmx(MM[6]); eaaddr+=10; + x87_stmmx(MM[7]); + } + else + { + x87_st80(ST(0)); eaaddr+=10; + x87_st80(ST(1)); eaaddr+=10; + x87_st80(ST(2)); eaaddr+=10; + x87_st80(ST(3)); eaaddr+=10; + x87_st80(ST(4)); eaaddr+=10; + x87_st80(ST(5)); eaaddr+=10; + x87_st80(ST(6)); eaaddr+=10; + x87_st80(ST(7)); + } + break; + case 0x100: /*32-bit real mode*/ + writememw(easeg,eaaddr,npxc); + writememw(easeg,eaaddr+4,npxs); + writememw(easeg,eaaddr+8,tag); + writememw(easeg,eaaddr+12,x87_pc_off); + writememw(easeg,eaaddr+20,x87_op_off); + writememl(easeg,eaaddr+24,(x87_op_off>>16)<<12); + eaaddr+=28; + if (ismmx) + { + x87_stmmx(MM[0]); eaaddr+=10; + x87_stmmx(MM[1]); eaaddr+=10; + x87_stmmx(MM[2]); eaaddr+=10; + x87_stmmx(MM[3]); eaaddr+=10; + x87_stmmx(MM[4]); eaaddr+=10; + x87_stmmx(MM[5]); eaaddr+=10; + x87_stmmx(MM[6]); eaaddr+=10; + x87_stmmx(MM[7]); + } + else + { + x87_st80(ST(0)); eaaddr+=10; + x87_st80(ST(1)); eaaddr+=10; + x87_st80(ST(2)); eaaddr+=10; + x87_st80(ST(3)); eaaddr+=10; + x87_st80(ST(4)); eaaddr+=10; + x87_st80(ST(5)); eaaddr+=10; + x87_st80(ST(6)); eaaddr+=10; + x87_st80(ST(7)); + } + break; + case 0x101: /*32-bit protected mode*/ + writememw(easeg,eaaddr,npxc); + writememw(easeg,eaaddr+4,npxs); + writememw(easeg,eaaddr+8,tag); + writememl(easeg,eaaddr+12,x87_pc_off); + writememl(easeg,eaaddr+16,x87_pc_seg); + writememl(easeg,eaaddr+20,x87_op_off); + writememl(easeg,eaaddr+24,x87_op_seg); + eaaddr+=28; + if (ismmx) + { + x87_stmmx(MM[0]); eaaddr+=10; + x87_stmmx(MM[1]); eaaddr+=10; + x87_stmmx(MM[2]); eaaddr+=10; + x87_stmmx(MM[3]); eaaddr+=10; + x87_stmmx(MM[4]); eaaddr+=10; + x87_stmmx(MM[5]); eaaddr+=10; + x87_stmmx(MM[6]); eaaddr+=10; + x87_stmmx(MM[7]); + } + else + { + x87_st80(ST(0)); eaaddr+=10; + x87_st80(ST(1)); eaaddr+=10; + x87_st80(ST(2)); eaaddr+=10; + x87_st80(ST(3)); eaaddr+=10; + x87_st80(ST(4)); eaaddr+=10; + x87_st80(ST(5)); eaaddr+=10; + x87_st80(ST(6)); eaaddr+=10; + x87_st80(ST(7)); + } + break; + } + cycles-=(cr0&1)?56:67; +} +static int opFSAVE_a16(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_16(fetchdat); + FSAVE(); + return abrt; +} +static int opFSAVE_a32(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_32(fetchdat); + FSAVE(); + return abrt; +} + +static int opFSTSW_a16(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FSTSW %08X:%08X\n", easeg, eaaddr); + seteaw((npxs & 0xC7FF) | (TOP << 11)); + cycles -= 3; + return abrt; +} +static int opFSTSW_a32(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FSTSW %08X:%08X\n", easeg, eaaddr); + seteaw((npxs & 0xC7FF) | (TOP << 11)); + cycles -= 3; + return abrt; +} + + +static int opFLD(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FLD %f\n", ST(fetchdat & 7)); + x87_push(ST(fetchdat&7)); + cycles -= 4; + return 0; +} + +static int opFXCH(uint32_t fetchdat) +{ + double td; + FP_ENTER(); + pc++; + if (fplog) pclog("FXCH\n"); + td = ST(0); + ST(0) = ST(fetchdat&7); + ST(fetchdat&7) = td; + cycles -= 4; + return 0; +} + +static int opFCHS(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FCHS\n"); + ST(0) = -ST(0); + cycles -= 6; + return 0; +} + +static int opFABS(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FABS %f\n", ST(0)); + ST(0) = fabs(ST(0)); + cycles -= 3; + return 0; +} + +static int opFTST(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FTST\n"); + npxs &= ~(C0|C2|C3); + if (ST(0) == 0.0) npxs |= C3; + else if (ST(0) < 0.0) npxs |= C0; + cycles -= 4; + return 0; +} + +static int opFXAM(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FXAM %i %f\n", ((tag>>((TOP&7)<<1))&3), ST(0)); + npxs &= ~(C0|C2|C3); + if (((tag>>((TOP&7)<<1))&3)==3) npxs |= (C0|C3); + else if (ST(0) == 0.0) npxs |= C3; + else npxs |= C2; + if (ST(0) < 0.0) npxs |= C1; + cycles -= 8; + return 0; +} + +static int opFLD1(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FLD1\n"); + x87_push(1.0); + cycles -= 4; + return 0; +} + +static int opFLDL2T(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FLDL2T\n"); + x87_push(3.3219280948873623); + cycles -= 8; + return 0; +} + +static int opFLDL2E(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FLDL2E\n"); + x87_push(1.4426950408889634); + cycles -= 8; + return 0; +} + +static int opFLDPI(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FLDPI\n"); + x87_push(3.141592653589793); + cycles -= 8; + return 0; +} + +static int opFLDEG2(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FLDEG2\n"); + x87_push(0.3010299956639812); + cycles -= 8; + return 0; +} + +static int opFLDLN2(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FLDLN2\n"); + x87_push(0.693147180559945); + cycles -= 8; + return 0; +} + +static int opFLDZ(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FLDZ\n"); + x87_push(0.0); + tag |= (1<<((TOP&7)<<1)); + cycles -= 4; + return 0; +} + +static int opF2XM1(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("F2XM1\n"); + ST(0) = pow(2.0, ST(0)) - 1.0; + cycles -= 200; + return 0; +} + +static int opFYL2X(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FYL2X\n"); + ST(1) = ST(1) * (log(ST(0)) / log(2.0)); + x87_pop(); + cycles -= 250; + return 0; +} + +static int opFPTAN(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FPTAN\n"); + ST(0) = tan(ST(0)); + x87_push(1.0); + npxs &= ~C2; + cycles -= 235; + return 0; +} + +static int opFPATAN(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FPATAN\n"); + ST(1) = atan2(ST(1), ST(0)); + x87_pop(); + cycles -= 250; + return 0; +} + +static int opFDECSTP(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FDECSTP\n"); + TOP = (TOP - 1) & 7; + cycles -= 4; + return 0; +} + +static int opFINCSTP(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FDECSTP\n"); + TOP = (TOP + 1) & 7; + cycles -= 4; + return 0; +} + +static int opFPREM(uint32_t fetchdat) +{ + int64_t temp64; + FP_ENTER(); + pc++; + if (fplog) pclog("FPREM %f %f ", ST(0), ST(1)); + temp64 = (int64_t)(ST(0) / ST(1)); + ST(0) = ST(0) - (ST(1) * (double)temp64); + if (fplog) pclog("%f\n", ST(0)); + npxs &= ~(C0|C1|C2|C3); + if (temp64 & 4) npxs|=C0; + if (temp64 & 2) npxs|=C3; + if (temp64 & 1) npxs|=C1; + cycles -= 100; + return 0; +} + +static int opFSQRT(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FSQRT\n"); + ST(0) = sqrt(ST(0)); + cycles -= 83; + return 0; +} + +static int opFSINCOS(uint32_t fetchdat) +{ + double td; + FP_ENTER(); + pc++; + if (fplog) pclog("FSINCOS\n"); + td = ST(0); + ST(0) = sin(td); + x87_push(cos(td)); + npxs &= ~C2; + cycles -= 330; + return 0; +} + +static int opFRNDINT(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FRNDINT %g ", ST(0)); + ST(0) = (double)x87_fround(ST(0)); + if (fplog) pclog("%g\n", ST(0)); + cycles -= 21; + return 0; +} + +static int opFSCALE(uint32_t fetchdat) +{ + int64_t temp64; + FP_ENTER(); + pc++; + if (fplog) pclog("FSCALE\n"); + temp64 = (int64_t)ST(1); + ST(0) = ST(0) * pow(2.0, (double)temp64); + cycles -= 30; + return 0; +} + +static int opFSIN(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FSIN\n"); + ST(0) = sin(ST(0)); + npxs &= ~C2; + cycles -= 300; + return 0; +} + +static int opFCOS(uint32_t fetchdat) +{ + FP_ENTER(); + pc++; + if (fplog) pclog("FCOS\n"); + ST(0) = cos(ST(0)); + npxs &= ~C2; + cycles -= 300; + return 0; +} + + +static void FLDENV() +{ + if (fplog) pclog("FLDENV %08X:%08X\n", easeg, eaaddr); + switch ((cr0 & 1) | (op32 & 0x100)) + { + case 0x000: /*16-bit real mode*/ + case 0x001: /*16-bit protected mode*/ + npxc = readmemw(easeg, eaaddr); + npxs = readmemw(easeg, eaaddr+2); + tag = readmemw(easeg, eaaddr+4); + TOP = (npxs >> 11) & 7; + break; + case 0x100: /*32-bit real mode*/ + case 0x101: /*32-bit protected mode*/ + npxc = readmemw(easeg, eaaddr); + npxs = readmemw(easeg, eaaddr+4); + tag = readmemw(easeg, eaaddr+8); + TOP = (npxs >> 11) & 7; + break; + } + cycles -= (cr0 & 1) ? 34 : 44; +} + +static int opFLDENV_a16(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_16(fetchdat); + FLDENV(); + return abrt; +} +static int opFLDENV_a32(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_32(fetchdat); + FLDENV(); + return abrt; +} + +static int opFLDCW_a16(uint32_t fetchdat) +{ + uint16_t tempw; + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FLDCW %08X:%08X\n", easeg, eaaddr); + tempw = geteaw(); + if (abrt) return 1; + npxc = tempw; + cycles -= 4; + return 0; +} +static int opFLDCW_a32(uint32_t fetchdat) +{ + uint16_t tempw; + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FLDCW %08X:%08X\n", easeg, eaaddr); + tempw = geteaw(); + if (abrt) return 1; + npxc = tempw; + cycles -= 4; + return 0; +} + +static void FSTENV() +{ + if (fplog) pclog("FSTENV %08X:%08X\n", easeg, eaaddr); + switch ((cr0 & 1) | (op32 & 0x100)) + { + case 0x000: /*16-bit real mode*/ + writememw(easeg,eaaddr,npxc); + writememw(easeg,eaaddr+2,npxs); + writememw(easeg,eaaddr+4,tag); + writememw(easeg,eaaddr+6,x87_pc_off); + writememw(easeg,eaaddr+10,x87_op_off); + break; + case 0x001: /*16-bit protected mode*/ + writememw(easeg,eaaddr,npxc); + writememw(easeg,eaaddr+2,npxs); + writememw(easeg,eaaddr+4,tag); + writememw(easeg,eaaddr+6,x87_pc_off); + writememw(easeg,eaaddr+8,x87_pc_seg); + writememw(easeg,eaaddr+10,x87_op_off); + writememw(easeg,eaaddr+12,x87_op_seg); + break; + case 0x100: /*32-bit real mode*/ + writememw(easeg,eaaddr,npxc); + writememw(easeg,eaaddr+4,npxs); + writememw(easeg,eaaddr+8,tag); + writememw(easeg,eaaddr+12,x87_pc_off); + writememw(easeg,eaaddr+20,x87_op_off); + writememl(easeg,eaaddr+24,(x87_op_off>>16)<<12); + break; + case 0x101: /*32-bit protected mode*/ + writememw(easeg,eaaddr,npxc); + writememw(easeg,eaaddr+4,npxs); + writememw(easeg,eaaddr+8,tag); + writememl(easeg,eaaddr+12,x87_pc_off); + writememl(easeg,eaaddr+16,x87_pc_seg); + writememl(easeg,eaaddr+20,x87_op_off); + writememl(easeg,eaaddr+24,x87_op_seg); + break; + } + cycles -= (cr0 & 1) ? 56 : 67; +} + +static int opFSTENV_a16(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_16(fetchdat); + FSTENV(); + return abrt; +} +static int opFSTENV_a32(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_32(fetchdat); + FSTENV(); + return abrt; +} + +static int opFSTCW_a16(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_16(fetchdat); + if (fplog) pclog("FSTCW %08X:%08X\n", easeg, eaaddr); + seteaw(npxc); + cycles -= 3; + return abrt; +} +static int opFSTCW_a32(uint32_t fetchdat) +{ + FP_ENTER(); + fetch_ea_32(fetchdat); + if (fplog) pclog("FSTCW %08X:%08X\n", easeg, eaaddr); + seteaw(npxc); + cycles -= 3; + return abrt; +}