Skip to content

Commit

Permalink
Fix rounding of some x87 instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
Hagb committed Apr 14, 2024
1 parent ba01765 commit c5460aa
Show file tree
Hide file tree
Showing 21 changed files with 1,285 additions and 40 deletions.
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1007,5 +1007,10 @@ add_test(sse4_2 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test25 -D TEST_OUTPUT=tmpfile25.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref25.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )

add_test(fpu_rounding ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test26 -D TEST_OUTPUT=tmpfile26.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref26.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )

endif(BOX86LIB)
3 changes: 3 additions & 0 deletions src/dynarec/arm_emitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ Op is 20-27
// and dst, src1, #imm ror rot*2
#define AND_IMM8_ROR(dst, src, imm8, rot) \
EMIT(0xe2000000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
// and.c dst, src, #(imm8)
#define AND_IMM8_COND(cond, dst, src, imm8) \
EMIT((cond) | 0x02000000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// and.s dst, src, #(imm8)
#define ANDS_IMM8(dst, src, imm8) \
EMIT(0xe2100000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
Expand Down
26 changes: 26 additions & 0 deletions src/dynarec/dynarec_arm_d8.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
Expand Down Expand Up @@ -33,6 +34,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int d1;
int fixedaddress;
int parity;
uint8_t u8;

MAYUSE(d1);
MAYUSE(s0);
Expand All @@ -52,11 +54,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FADD ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VADD_F32(v1, v1, v2);
} else {
VADD_F64(v1, v1, v2);
}
x87_restoreround(dyn, ninst, u8);
break;
case 0xC8:
case 0xC9:
Expand All @@ -69,11 +73,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FMUL ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VMUL_F32(v1, v1, v2);
} else {
VMUL_F64(v1, v1, v2);
}
x87_restoreround(dyn, ninst, u8);
break;
case 0xD0:
case 0xD1:
Expand Down Expand Up @@ -123,11 +129,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FSUB ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VSUB_F32(v1, v1, v2);
} else {
VSUB_F64(v1, v1, v2);
}
x87_restoreround(dyn, ninst, u8);
break;
case 0xE8:
case 0xE9:
Expand All @@ -140,11 +148,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FSUBR ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VSUB_F32(v1, v2, v1);
} else {
VSUB_F64(v1, v2, v1);
}
x87_restoreround(dyn, ninst, u8);
break;
case 0xF0:
case 0xF1:
Expand All @@ -157,11 +167,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FDIV ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VDIV_F32(v1, v1, v2);
} else {
VDIV_F64(v1, v1, v2);
}
x87_restoreround(dyn, ninst, u8);
break;
case 0xF8:
case 0xF9:
Expand All @@ -174,11 +186,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FDIVR ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VDIV_F32(v1, v2, v1);
} else {
VDIV_F64(v1, v2, v1);
}
x87_restoreround(dyn, ninst, u8);
break;

default:
Expand All @@ -196,12 +210,14 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETED;
VMOVtoV(s0, ed);
}
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VADD_F32(v1, v1, s0);
} else {
VCVT_F64_F32(d1, s0);
VADD_F64(v1, v1, d1);
}
x87_restoreround(dyn, ninst, u8);
break;
case 1:
INST_NAME("FMUL ST0, float[ED]");
Expand All @@ -216,12 +232,14 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETED;
VMOVtoV(s0, ed);
}
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VMUL_F32(v1, v1, s0);
} else {
VCVT_F64_F32(d1, s0);
VMUL_F64(v1, v1, d1);
}
x87_restoreround(dyn, ninst, u8);
break;
case 2:
INST_NAME("FCOM ST0, float[ED]");
Expand Down Expand Up @@ -279,12 +297,14 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETED;
VMOVtoV(s0, ed);
}
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VSUB_F32(v1, v1, s0);
} else {
VCVT_F64_F32(d1, s0);
VSUB_F64(v1, v1, d1);
}
x87_restoreround(dyn, ninst, u8);
break;
case 5:
INST_NAME("FSUBR ST0, float[ED]");
Expand All @@ -299,12 +319,14 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETED;
VMOVtoV(s0, ed);
}
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VSUB_F32(v1, s0, v1);
} else {
VCVT_F64_F32(d1, s0);
VSUB_F64(v1, d1, v1);
}
x87_restoreround(dyn, ninst, u8);
break;
case 6:
INST_NAME("FDIV ST0, float[ED]");
Expand All @@ -319,12 +341,14 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETED;
VMOVtoV(s0, ed);
}
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VDIV_F32(v1, v1, s0);
} else {
VCVT_F64_F32(d1, s0);
VDIV_F64(v1, v1, d1);
}
x87_restoreround(dyn, ninst, u8);
break;
case 7:
INST_NAME("FDIVR ST0, float[ED]");
Expand All @@ -339,12 +363,14 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETED;
VMOVtoV(s0, ed);
}
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VDIV_F32(v1, s0, v1);
} else {
VCVT_F64_F32(d1, s0);
VDIV_F64(v1, d1, v1);
}
x87_restoreround(dyn, ninst, u8);
break;
default:
DEFAULT;
Expand Down
Loading

0 comments on commit c5460aa

Please sign in to comment.