#include #include #include #include #include "debug.h" #include "box64context.h" #include "dynarec.h" #include "emu/x64emu_private.h" #include "emu/x64run_private.h" #include "x64run.h" #include "x64emu.h" #include "box64stack.h" #include "callback.h" #include "emu/x64run_private.h" #include "x64trace.h" #include "emu/x87emu_private.h" #include "dynarec_native.h" #include "rv64_printer.h" #include "dynarec_rv64_private.h" #include "dynarec_rv64_helper.h" #include "dynarec_rv64_functions.h" uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog) { (void)ip; (void)rep; (void)need_epilog; uint8_t nextop = F8; uint8_t ed; uint8_t wback; uint8_t u8; int64_t fixedaddress; int unscaled; int v1, v2; int s0; int64_t j64; MAYUSE(s0); MAYUSE(v2); MAYUSE(v1); MAYUSE(j64); switch(nextop) { case 0xC0: case 0xC1: case 0xC2: case 0xC3: case 0xC4: case 0xC5: case 0xC6: case 0xC7: INST_NAME("FCMOVNB ST0, STx"); READFLAGS(X_CF); 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)); ANDI(x1, xFlags, 1<>3)&7) { case 0: INST_NAME("FILD ST0, Ed"); X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_D); addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); LW(x1, ed, fixedaddress); FCVTDW(v1, x1, RD_RNE); // i32 -> double break; case 1: INST_NAME("FISTTP Ed, ST0"); v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); addr = geted(dyn, addr, ninst, nextop, &wback, x3, x4, &fixedaddress, rex, NULL, 1, 0); if (!box64_dynarec_fastround) { FSFLAGSI(0); // reset all bits } FCVTWD(x4, v1, RD_RTZ); if (!box64_dynarec_fastround) { FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, 1 << FR_NV); BEQZ_MARK(x5); MOV32w(x4, 0x80000000); MARK; } SW(x4, wback, fixedaddress); X87_POP_OR_FAIL(dyn, ninst, x3); break; case 2: INST_NAME("FIST Ed, ST0"); DEFAULT; break; case 3: INST_NAME("FISTP Ed, ST0"); v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); u8 = x87_setround(dyn, ninst, x1, x2); addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0); v2 = fpu_get_scratch(dyn); if(!box64_dynarec_fastround) { FSFLAGSI(0); // reset all bits } FCVTWD(x4, v1, RD_DYN); x87_restoreround(dyn, ninst, u8); if(!box64_dynarec_fastround) { FRFLAGS(x5); // get back FPSR to check the IOC bit ANDI(x5, x5, 1<>3)&7)==7) || (PK(0)>=0x40 && PK(0)<=0x4f && PK(1)==0xDB && ((PK(2)>>3)&7)==7)) { // the FLD is immediatly followed by an FSTP LD(x5, ed, fixedaddress+0); LH(x6, ed, fixedaddress+8); // no persistant scratch register, so unrool both instruction here... MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n"); nextop = F8; // 0xDB or rex if(nextop>=0x40 && nextop<=0x4f) { rex.rex = nextop; nextop = F8; //0xDB } else rex.rex = 0; nextop = F8; //modrm addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 8, 0); SD(x5, ed, fixedaddress+0); SH(x6, ed, fixedaddress+8); } else { if(box64_x87_no80bits) { X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_D); FLD(v1, ed, fixedaddress); } else { if(ed!=x1) { ADDI(x1, ed, fixedaddress); } X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x3); CALL(native_fld, -1); } } break; case 7: INST_NAME("FSTP tbyte"); if(box64_x87_no80bits) { v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D); addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0); FSD(v1, wback, fixedaddress); } else { x87_forget(dyn, ninst, x1, x3, 0); addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0); if(ed!=x1) { MV(x1, ed); } s0 = x87_stackcount(dyn, ninst, x3); CALL(native_fstp, -1); x87_unstackcount(dyn, ninst, x3, s0); } X87_POP_OR_FAIL(dyn, ninst, x3); break; default: DEFAULT; } } return addr; }