diff options
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_0f.c | 11 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_66.c | 1 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_f0.c | 103 | ||||
| -rw-r--r-- | src/dynarec/la64/la64_emitter.h | 2 |
4 files changed, 117 insertions, 0 deletions
diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c index 7e415b72..87c51c81 100644 --- a/src/dynarec/la64/dynarec_la64_0f.c +++ b/src/dynarec/la64/dynarec_la64_0f.c @@ -104,6 +104,17 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni LOAD_XEMU_REM(); jump_to_epilog(dyn, 0, xRIP, ninst); break; + case 0x0B: + INST_NAME("UD2"); + SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state + GETIP(ip); + STORE_XEMU_CALL(); + CALL(native_ud, -1); + LOAD_XEMU_CALL(); + jump_to_epilog(dyn, 0, xRIP, ninst); + *need_epilog = 0; + *ok = 0; + break; case 0x10: INST_NAME("MOVUPS Gx,Ex"); nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_66.c b/src/dynarec/la64/dynarec_la64_66.c index 9f23ed8c..88d03ddc 100644 --- a/src/dynarec/la64/dynarec_la64_66.c +++ b/src/dynarec/la64/dynarec_la64_66.c @@ -527,6 +527,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni default: DEFAULT; } + break; default: DEFAULT; } diff --git a/src/dynarec/la64/dynarec_la64_f0.c b/src/dynarec/la64/dynarec_la64_f0.c index 63aa187d..550713c4 100644 --- a/src/dynarec/la64/dynarec_la64_f0.c +++ b/src/dynarec/la64/dynarec_la64_f0.c @@ -149,6 +149,109 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni DEFAULT; } break; + case 0xC7: + switch (rep) { + case 0: + if (rex.w) { + INST_NAME("LOCK CMPXCHG16B Gq, Eq"); + } else { + INST_NAME("LOCK CMPXCHG8B Gq, Eq"); + } + SETFLAGS(X_ZF, SF_SUBSET); + nextop = F8; + addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, LOCK_LOCK, 0, 0); + if (la64_lbt) { + X64_SET_EFLAGS(xZR, X_ZF); + } else { + ADDI_D(x2, xZR, ~(1 << F_ZF)); + AND(xFlags, xFlags, x2); + } + if (rex.w) { + if (la64_scq) { + MARKLOCK; + LL_D(x2, wback, 0); + LD_D(x3, wback, 8); + // compare RDX:RAX with x3:x2 + BNE_MARK(x2, xRAX); + BNE_MARK(x3, xRDX); + MV(x5, xRBX); + SC_Q(x5, xRCX, wback); + BEQZ_MARKLOCK(x5); + if (la64_lbt) { + ADDI_D(x5, xZR, -1); + X64_SET_EFLAGS(x5, X_ZF); + } else { + ORI(xFlags, xFlags, 1 << F_ZF); + } + B_MARK3_nocond; + MARK; + MV(xRAX, x2); + MV(xRDX, x3); + MARK3; + SMDMB(); + } else { + // if scq extension is not available, implement it with mutex + LD_D(x6, xEmu, offsetof(x64emu_t, context)); + ADDI_D(x6, x6, offsetof(box64context_t, mutex_16b)); + ADDI_D(x4, xZR, 1); + MARKLOCK; + AMSWAP_DB_W(x5, x4, x6); + // x4 == 1 if locked + BNEZ_MARKLOCK(x5); + + LD_D(x2, wback, 0); + LD_D(x3, wback, 8); + BNE_MARK(x2, xRAX); + BNE_MARK(x3, xRDX); + ST_D(xRBX, wback, 0); + ST_D(xRCX, wback, 8); + if (la64_lbt) { + ADDI_D(x5, xZR, -1); + X64_SET_EFLAGS(x5, X_ZF); + } else { + ORI(xFlags, xFlags, 1 << F_ZF); + } + B_MARK3_nocond; + MARK; + MV(xRAX, x2); + MV(xRDX, x3); + MARK3; + + // unlock + AMSWAP_DB_W(xZR, xZR, x6); + } + } else { + SMDMB(); + AND(x3, xRAX, xMASK); + SLLI_D(x2, xRDX, 32); + OR(x3, x3, x2); + AND(x4, xRBX, xMASK); + SLLI_D(x2, xRCX, 32); + OR(x4, x4, x2); + MARKLOCK; + LL_D(x2, wback, 0); + BNE_MARK(x2, x3); // EDX_EAX != Ed + MV(x5, x4); + SC_D(x5, wback, 0); + BEQZ_MARKLOCK(x5); + if (la64_lbt) { + ADDI_D(x5, xZR, -1); + X64_SET_EFLAGS(x5, X_ZF); + } else { + ORI(xFlags, xFlags, 1 << F_ZF); + } + B_MARK3_nocond; + MARK; + SLLI_D(xRDX, x2, 32); + AND(xRAX, x2, xMASK); + MARK3; + SMDMB(); + } + break; + default: + DEFAULT; + } + break; default: DEFAULT; } diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h index 6e2139e3..d5388f2c 100644 --- a/src/dynarec/la64/la64_emitter.h +++ b/src/dynarec/la64/la64_emitter.h @@ -253,6 +253,8 @@ f24-f31 fs0-fs7 Static registers Callee #define LL_D(rd, rj, imm) EMIT(type_2RI14(0b00100010, imm >> 2, rj, rd)) #define SC_D(rd, rj, imm) EMIT(type_2RI14(0b00100011, imm >> 2, rj, rd)) +#define SC_Q(rd, rk, rj) EMIT(type_3R(0b00111000010101110, rk, rj, rd)) + #define LLxw(rd, rj, imm) EMIT(type_2RI14(0b00100000 | (rex.w ? 0b10 : 0b00), imm >> 2, rj, rd)) #define SCxw(rd, rj, imm) EMIT(type_2RI14(0b00100001 | (rex.w ? 0b10 : 0b00), imm >> 2, rj, rd)) |