Skip to content

Commit

Permalink
[INTERPRETER] Improved x87 emulation a bit ([ARM64_DYNAREC] too)
Browse files Browse the repository at this point in the history
  • Loading branch information
ptitSeb committed Jan 8, 2025
1 parent c65910f commit 82105a1
Show file tree
Hide file tree
Showing 10 changed files with 628 additions and 935 deletions.
2 changes: 2 additions & 0 deletions src/dynarec/arm64/arm64_emitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -1150,7 +1150,9 @@ int convert_bitmask(uint64_t bitmask);
#define VFMOVDQ_8(Vd, u8) EMIT(FMOV_vector_imm(1, 1, ((u8)>>5)&0b111, (u8)&0b11111, Vd))

#define FMOV_scalar_imm(type, imm8, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | (imm8)<<13 | 0b100<<10 | (Rd))
// FMOV to Sd, imm=7 :~6:6:6:6:6:6:5:4 :3:2:1:0....
#define FMOVS_8(Sd, u8) EMIT(FMOV_scalar_imm(0b00, u8, Sd))
// FMOV to Dd, imm=7 :~6:6:6:6:6:6:6:6:6:5:4 :3:2:1:0....
#define FMOVD_8(Dd, u8) EMIT(FMOV_scalar_imm(0b01, u8, Dd))

// VMOV
Expand Down
13 changes: 11 additions & 2 deletions src/dynarec/arm64/arm64_printer.c
Original file line number Diff line number Diff line change
Expand Up @@ -743,8 +743,12 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "BFC %s, %d, %d", sf?Xt[Rd]:Wt[Rd], lsb, width);
else
snprintf(buff, sizeof(buff), "BFI %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], lsb, width);
} else
snprintf(buff, sizeof(buff), "BFXIL %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], immr, imms-immr+1);
} else {
if(Rn==31 && immr==0)
snprintf(buff, sizeof(buff), "BFC %s, %d, %d", sf?Xt[Rd]:Wt[Rd], immr, imms-immr+1);
else
snprintf(buff, sizeof(buff), "BFXIL %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], immr, imms-immr+1);
}
return buff;
}
// ---- BRANCH / TEST
Expand Down Expand Up @@ -1643,6 +1647,11 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "%cQXTN%s V%d.%s, V%d.%s", a.U?'U':'S', a.Q?"2":"", Rd, Vd, Rn, Va);
return buff;
}
if(isMask(opcode, "01U11110ff100001010010nnnnnddddd", &a)) {
const char Z[] = {'B', 'H', 'S', 'D', '?'};
snprintf(buff, sizeof(buff), "SQXT%sN %c%d, %c%d", a.U?"U":"", Z[sf], Rn, Z[sf+1], Rm);
return buff;
}

// (S/U)SSHL(2) / (U/S)XTL(2)
if(isMask(opcode, "0QU011110hhhhiii101001nnnnnddddd", &a)) {
Expand Down
9 changes: 5 additions & 4 deletions src/dynarec/arm64/dynarec_arm64_dd.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,19 +161,20 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
s0 = fpu_get_scratch(dyn, ninst);
if(arm64_frintts) {
FRINT64ZD(s0, v1);
FCVTZSxD(x2, s0);
STx(x2, ed, fixedaddress);
VFCVTZSd(s0, s0);
VST64(s0, ed, fixedaddress);
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTRRD(s0, v1, 3);
FCVTZSxD(x2, s0);
VFCVTZSd(s0, s0);
VST64(s0, ed, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
ORRx_mask(x2, xZR, 1, 1, 0); //0x8000000000000000
MARK3;
STx(x2, ed, fixedaddress);
MARK3;
}
}
X87_POP_OR_FAIL(dyn, ninst, x3);
Expand Down
26 changes: 16 additions & 10 deletions src/dynarec/arm64/dynarec_arm64_df.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,16 +356,22 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
B_MARK3(c__);
MARK2;
}
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
VST64(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
STx(x5, wback, fixedaddress);
if(arm64_frintts) {
FRINT64XD(s0, v1);
VFCVTZSd(s0, s0);
VST64(s0, wback, fixedaddress);
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
VST64(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
STx(x5, wback, fixedaddress);
}
MARK3;
#endif
x87_restoreround(dyn, ninst, u8);
Expand Down
8 changes: 4 additions & 4 deletions src/dynarec/arm64/dynarec_arm64_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -926,9 +926,9 @@ uint8_t mark_natflag(dynarec_arm_t* dyn, int ninst, uint8_t flag, int before)
{
if(dyn->insts[ninst].x64.set_flags && !before) {
dyn->insts[ninst].set_nat_flags |= flag;
if(dyn->insts[ninst].x64.use_flags) {
dyn->insts[ninst].use_nat_flags |= flag;
}
//if(dyn->insts[ninst].x64.use_flags) {
// dyn->insts[ninst].use_nat_flags |= flag;
//}
} else {
if(before)
dyn->insts[ninst].use_nat_flags_before |= flag;
Expand Down Expand Up @@ -1098,7 +1098,7 @@ void updateNativeFlags(dynarec_native_t* dyn)
{
if(!box64_dynarec_nativeflags)
return;
// backward check if native flags are used
// forward check if native flags are used
for(int ninst=0; ninst<dyn->size; ++ninst)
if(flag2native(dyn->insts[ninst].x64.gen_flags) && (dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH)) {
propagateNativeFlags(dyn, ninst);
Expand Down
6 changes: 4 additions & 2 deletions src/dynarec/arm64/dynarec_arm64_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,8 @@
MOV32w(s2, 0b01000101); /* unordered */ \
CSELw(s1, s2, s1, cVS); \
if(v1||v2) { \
Bcond(cVS, 10*4); \
Bcond(cVS, 11*4); \
Bcond(cEQ, 10*4); \
if(is_f) { \
ORRw_mask(s4, xZR, 12, 10); /*+inf*/ \
FMOVwS(s2, v1); \
Expand Down Expand Up @@ -996,7 +997,8 @@
CSELw(s1, s2, s1, cEQ); \
/* greater than leave 0 */ \
if(s4) { \
Bcond(cVS, 10*4); \
Bcond(cVS, 11*4); \
Bcond(cEQ, 10*4); \
if(is_f) { \
ORRw_mask(s4, xZR, 12, 10); /*+inf*/ \
FMOVwS(s2, v1); \
Expand Down
4 changes: 2 additions & 2 deletions src/emu/x87emu_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ static inline void fpu_fcom(x64emu_t* emu, double b)
emu->sw.f.F87_C0 = 1;
emu->sw.f.F87_C2 = 1;
emu->sw.f.F87_C3 = 1;
} else if ((b==-INFINITY) || (ST0.d==INFINITY)) {
} else if (((b==-INFINITY) || (ST0.d==INFINITY)) && ST0.d!=b) {
emu->sw.f.F87_C0 = 0;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C3 = 0;
Expand Down Expand Up @@ -104,7 +104,7 @@ static inline void fpu_fcomi(x64emu_t* emu, double b)
SET_FLAG(F_CF);
SET_FLAG(F_PF);
SET_FLAG(F_ZF);
} else if ((b==-INFINITY) || (ST0.d==INFINITY)) {
} else if (((b==-INFINITY) || (ST0.d==INFINITY)) && ST0.d!=b) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_PF);
CLEAR_FLAG(F_ZF);
Expand Down
Loading

0 comments on commit 82105a1

Please sign in to comment.