diff --git a/src/codegen_ops.c b/src/codegen_ops.c index c1c0982..e552024 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -188,7 +188,7 @@ RecompOpFn recomp_opcodes_d9[512] = /*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*32-bit data*/ @@ -210,7 +210,7 @@ RecompOpFn recomp_opcodes_d9[512] = /*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, /*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL, /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; @@ -422,7 +422,7 @@ RecompOpFn recomp_opcodes_de[512] = /*b0*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, /*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, /*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, @@ -444,7 +444,7 @@ RecompOpFn recomp_opcodes_de[512] = /*b0*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, /*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL, /*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, /*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, }; diff --git a/src/codegen_ops_fpu.h b/src/codegen_ops_fpu.h index eca1587..47a7a03 100644 --- a/src/codegen_ops_fpu.h +++ b/src/codegen_ops_fpu.h @@ -477,6 +477,15 @@ static uint32_t ropFSUBRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin return op_pc; } +static uint32_t ropFCOMPP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + FP_ENTER(); + FP_COMPARE_REG(0, 1); + FP_POP(); + FP_POP(); + + return op_pc; +} static uint32_t ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { @@ -600,3 +609,31 @@ static uint32_t ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint return op_pc + 1; } + + +static uint32_t ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + FP_ENTER(); + FP_FCHS(); + + return op_pc; +} + +#define opFLDimm(name, v) \ + static uint32_t ropFLD ## name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ + { \ + static double fp_imm = v; \ + \ + FP_ENTER(); \ + FP_LOAD_IMM_Q(*(uint64_t *)&fp_imm); \ + \ + return op_pc; \ + } + +opFLDimm(1, 1.0) +opFLDimm(L2T, 3.3219280948873623) +opFLDimm(L2E, 1.4426950408889634); +opFLDimm(PI, 3.141592653589793); +opFLDimm(EG2, 0.3010299956639812); +opFLDimm(LN2, 0.693147180559945); +opFLDimm(Z, 0.0) diff --git a/src/codegen_ops_x86-64.h b/src/codegen_ops_x86-64.h index 03c4ba5..951a25b 100644 --- a/src/codegen_ops_x86-64.h +++ b/src/codegen_ops_x86-64.h @@ -4074,6 +4074,65 @@ static void FP_LOAD_IQ() addbyte(cpu_state_offset(tag)); } +static void FP_LOAD_IMM_Q(uint64_t v) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0xc7); /*MOV ST[EBP+EBX*8], v*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addlong(v & 0xffffffff); + addbyte(0xc7); /*MOV ST[EBP+EBX*8]+4, v*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST) + 4); + addlong(v >> 32); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0xc6); /*MOV [tag+EBX], (v ? 0 : 1)*/ + addbyte(0x44); + addbyte(0x1d); + addbyte(cpu_state_offset(tag)); + addbyte(v ? 0 : 1); +} + +static void FP_FCHS() +{ + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte(0xf2); /*SUBSD XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x5c); + addbyte(0xc0); + addbyte(0xf2); /*SUBSD XMM0, ST[EAX*8]*/ + addbyte(0x0f); + addbyte(0x5c); + addbyte(0x44); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x05); + addbyte(cpu_state_offset(tag[0])); + addbyte(~TAG_UINT64); + addbyte(0xf2); /*MOVSD ST[EAX*8], XMM0*/ + addbyte(0x0f); + addbyte(0x11); + addbyte(0x44); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); +} + static int FP_LOAD_REG(int reg) { addbyte(0x8b); /*MOV EBX, TOP*/ diff --git a/src/codegen_ops_x86.h b/src/codegen_ops_x86.h index e61b3d5..62888ed 100644 --- a/src/codegen_ops_x86.h +++ b/src/codegen_ops_x86.h @@ -2169,6 +2169,59 @@ static void FP_LOAD_IQ() } } +static void FP_LOAD_IMM_Q(uint64_t v) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0xc7); /*MOV ST[reg][EBP], v*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + addlong(v & 0xffffffff); + addbyte(0xc7); /*MOV ST[reg][EBP]+4, v*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]) + 4); + addlong(v >> 32); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0xc6); /*MOVB tag[reg][EBP], 1:0*/ + addbyte(0x45); + addbyte(cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(v ? 0 : 1); + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0xc7); /*MOV ST[EBP+EBX*8], v*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addlong(v & 0xffffffff); + addbyte(0xc7); /*MOV ST[EBP+EBX*8]+4, v*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST) + 4); + addlong(v >> 32); + addbyte(0xc6); /*MOVB tag[reg][EBP], 1:0*/ + addbyte(0x44); + addbyte(0x1d); + addbyte(cpu_state_offset(tag[0])); + addbyte(v ? 0 : 1); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + } +} + static int FP_LOAD_REG(int reg) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) @@ -3162,6 +3215,47 @@ static void FP_COMPARE_REG(int dst, int src) } } +static void FP_FCHS() +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0xd9); /*FCHS*/ + addbyte(0xe0); + addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte(cpu_state_offset(tag[cpu_state.TOP])); + addbyte(~TAG_UINT64); + addbyte(0xdd); /*FSTP ST[dst][EBP]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + } + else + { + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + + addbyte(0xdd); /*FLD [ESI+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x05); + addbyte(cpu_state_offset(tag[0])); + addbyte(~TAG_UINT64); + addbyte(0xd9); /*FCHS*/ + addbyte(0xe0); + addbyte(0xdd); /*FSTP ST[EAX*8]*/ + addbyte(0x5c); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + } +} + static void UPDATE_NPXC(int reg) { addbyte(0x66); /*AND cpu_state.new_npxc, ~0xc00*/