diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2025-02-09 01:01:53 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-08 18:01:53 +0100 |
| commit | 3e2c6987106b9cd8775618a0f3a7f31e0936821b (patch) | |
| tree | e7d933d4dcacb376aa5ef9a4fc0f7d7ce6b52c35 /src | |
| parent | 58b24c85a2407a6c2ab6dfc2f18555dd929ad7e1 (diff) | |
| download | box64-3e2c6987106b9cd8775618a0f3a7f31e0936821b.tar.gz box64-3e2c6987106b9cd8775618a0f3a7f31e0936821b.zip | |
[LA64_DYNAREC] Added more opcodes (#2330)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_00.c | 72 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_66.c | 16 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_660f.c | 30 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_emit_shift.c | 58 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.h | 2 |
5 files changed, 178 insertions, 0 deletions
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c index ba30e983..49e9bece 100644 --- a/src/dynarec/la64/dynarec_la64_00.c +++ b/src/dynarec/la64/dynarec_la64_00.c @@ -1927,6 +1927,62 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } } break; + case 0xCD: + u8 = F8; + if (box64_wine && (u8 == 0x2D || u8 == 0x2C || u8 == 0x29)) { + INST_NAME("INT 29/2c/2d"); + // lets do nothing + MESSAGE(LOG_INFO, "INT 29/2c/2d Windows interruption\n"); + GETIP(ip); // priviledged instruction, IP not updated + STORE_XEMU_CALL(); + MOV32w(x1, u8); + CALL(native_int, -1); + LOAD_XEMU_CALL(); + } else if (u8 == 0x80) { + INST_NAME("32bits SYSCALL"); + NOTEST(x1); + SMEND(); + GETIP(addr); + STORE_XEMU_CALL(); + CALL_S(x86Syscall, -1); + LOAD_XEMU_CALL(); + TABLE64(x3, addr); // expected return address + BNE_MARK(xRIP, x3); + LD_W(x1, xEmu, offsetof(x64emu_t, quit)); + BEQ_NEXT(x1, xZR); + MARK; + LOAD_XEMU_REM(); + jump_to_epilog(dyn, 0, xRIP, ninst); + } else if (u8 == 0x03) { + INST_NAME("INT 3"); + if (BOX64DRENV(dynarec_safeflags) > 1) { + READFLAGS(X_PEND); + } else { + SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state + } + GETIP(addr); + STORE_XEMU_CALL(); + CALL(native_int3, -1); + LOAD_XEMU_CALL(); + jump_to_epilog(dyn, 0, xRIP, ninst); + *need_epilog = 0; + *ok = 0; + } else { + INST_NAME("INT n"); + if (BOX64DRENV(dynarec_safeflags) > 1) { + READFLAGS(X_PEND); + } else { + SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state + } + GETIP(ip); // priviledged instruction, IP not updated + STORE_XEMU_CALL(); + CALL(native_priv, -1); + LOAD_XEMU_CALL(); + jump_to_epilog(dyn, 0, xRIP, ninst); + *need_epilog = 0; + *ok = 0; + } + break; case 0xCF: INST_NAME("IRET"); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Not a hack, EFLAGS are restored @@ -1987,6 +2043,22 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_shr8(dyn, ninst, x1, x2, x5, x4, x6); EBBACK(); break; + case 7: + if (opcode == 0xD0) { + INST_NAME("SAR Eb, 1"); + GETSEB(x1, 0); + MOV32w(x2, 1); + } else { + INST_NAME("SAR Eb, CL"); + GETSEB(x1, 0); + ANDI(x2, xRCX, 0x1f); + BEQ_NEXT(x2, xZR); + } + SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined + if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS(); + emit_sar8(dyn, ninst, x1, x2, x5, x4, x6); + EBBACK(); + break; default: DEFAULT; } diff --git a/src/dynarec/la64/dynarec_la64_66.c b/src/dynarec/la64/dynarec_la64_66.c index bf9cc495..548f01bf 100644 --- a/src/dynarec/la64/dynarec_la64_66.c +++ b/src/dynarec/la64/dynarec_la64_66.c @@ -791,6 +791,22 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xD3: nextop = F8; switch ((nextop >> 3) & 7) { + case 0: + if (opcode == 0xD1) { + INST_NAME("ROL Ew, 1"); + MOV32w(x2, 1); + } else { + INST_NAME("ROL Ew, CL"); + ANDI(x2, xRCX, 0x1f); + BEQ_NEXT(x2, xZR); + } + MESSAGE(LOG_DUMP, "Need Optimization\n"); + SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION); + if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS(); + GETEW(x1, 1); + CALL_(rol16, x1, x3); + EWBACK; + break; case 5: if (opcode == 0xD1) { INST_NAME("SHR Ew, 1"); diff --git a/src/dynarec/la64/dynarec_la64_660f.c b/src/dynarec/la64/dynarec_la64_660f.c index b5fbce5b..861de379 100644 --- a/src/dynarec/la64/dynarec_la64_660f.c +++ b/src/dynarec/la64/dynarec_la64_660f.c @@ -847,6 +847,17 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int GOCOND(0x40, "CMOV", "Gd, Ed"); #undef GO + case 0x50: + nextop = F8; + INST_NAME("PMOVMSKD Gd, Ex"); + GETEX(q0, 0, 0); + GETGD; + VPICKVE2GR_D(x1, q0, 0); + VPICKVE2GR_D(gd, q0, 1); + SRLI_D(gd, gd, 62); + SRLI_D(x1, x1, 63); + BSTRINS_D(gd, x1, 0, 0); + break; case 0x51: INST_NAME("SQRTPD Gx, Ex"); nextop = F8; @@ -1441,6 +1452,25 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)); BSTRINS_D(gd, x1, 15, 0); // insert in Gw break; + case 0xBA: + nextop = F8; + switch ((nextop >> 3) & 7) { + case 4: + INST_NAME("BT Ew, Ib"); + SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION); + SET_DFNONE(); + GETED(1); + u8 = F8; + u8 &= rex.w ? 0x3f : 15; + IFX (X_CF) { + BSTRPICK_D(x3, ed, u8, u8); + BSTRINS_D(xFlags, x3, 0, 0); + } + break; + default: + DEFAULT; + } + break; case 0xBE: INST_NAME("MOVSX Gw, Eb"); nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_emit_shift.c b/src/dynarec/la64/dynarec_la64_emit_shift.c index 9c7845dd..0125c1ae 100644 --- a/src/dynarec/la64/dynarec_la64_emit_shift.c +++ b/src/dynarec/la64/dynarec_la64_emit_shift.c @@ -461,6 +461,64 @@ void emit_shr8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i } } +// emit SAR8 instruction, from s1 , shift s2 (!0 and and'd already), store result in s1 using s3, s4 and s5 as scratch +void emit_sar8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) +{ + int64_t j64; + + if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR); + + IFX (X_PEND) { + ST_B(s2, xEmu, offsetof(x64emu_t, op2)); + ST_B(s1, xEmu, offsetof(x64emu_t, op1)); + SET_DF(s4, d_sar8); + } else IFXORNAT (X_ALL) { + SET_DFNONE(); + } + + if (la64_lbt) { + IFX (X_ALL) { + X64_SRA_B(s1, s2); + } + SRA_D(s1, s1, s2); + ANDI(s1, s1, 0xff); + + IFX (X_PEND) { + ST_B(s1, xEmu, offsetof(x64emu_t, res)); + } + return; + } + + CLEAR_FLAGS(s3); + IFX (X_CF) { + ADDI_D(s3, s2, -1); + SRA_D(s3, s1, s3); + ANDI(s3, s3, 1); // LSB == F_CF + OR(xFlags, xFlags, s3); + } + // For the SAR instruction, the OF flag is cleared for all 1-bit shifts. + // OF nop + IFX (X_SF) { + // SF is the same as the original operand + BGE(s1, xZR, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + + SRA_D(s1, s1, s2); + ANDI(s1, s1, 0xff); + + IFX (X_PEND) { + ST_B(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX (X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX (X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + // emit SHR16 instruction, from s1 , shift s2 (!0 and and'd already), store result in s1 using s3 and s4 as scratch void emit_shr16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) { diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index 4653759d..4bad8557 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -902,6 +902,7 @@ void* la64_next(x64emu_t* emu, uintptr_t addr); #define emit_shl32c STEPNAME(emit_shl32c) #define emit_shl8 STEPNAME(emit_shl8) #define emit_shr8 STEPNAME(emit_shr8) +#define emit_sar8 STEPNAME(emit_sar8) #define emit_shr16 STEPNAME(emit_shr16) #define emit_shr16c STEPNAME(emit_shr16c) #define emit_shr32 STEPNAME(emit_shr32) @@ -1012,6 +1013,7 @@ void emit_shl32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s void emit_shl32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4, int s5); void emit_shl8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); void emit_shr8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); +void emit_sar8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); void emit_shr16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); void emit_shr16c(dynarec_la64_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5); void emit_shr32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); |