diff --git a/src/xenia/cpu/x64/x64_emit_alu.cc b/src/xenia/cpu/x64/x64_emit_alu.cc index 101d53ff2..30966d8d6 100644 --- a/src/xenia/cpu/x64/x64_emit_alu.cc +++ b/src/xenia/cpu/x64/x64_emit_alu.cc @@ -214,7 +214,7 @@ XEEMITTER(divwx, 0x7C0003D6, XO )(X64Emitter& e, X86Compiler& c, InstrDat if (i.XO.Rc) { // With cr0 update. - e.update_cr_with_cond(0, dividend); + e.update_cr_with_cond(0, dividend, true); } #if 0 @@ -272,7 +272,7 @@ XEEMITTER(divwux, 0x7C000396, XO )(X64Emitter& e, X86Compiler& c, InstrDat if (i.XO.Rc) { // With cr0 update. - e.update_cr_with_cond(0, dividend); + e.update_cr_with_cond(0, dividend, false); } c.unuse(dividend_hi); @@ -581,7 +581,7 @@ XEEMITTER(cmpl, 0x7C000040, X )(X64Emitter& e, X86Compiler& c, InstrDat c.mov(rhs.r32(), rhs.r32()); } - e.update_cr_with_cond(BF, lhs, rhs); + e.update_cr_with_cond(BF, lhs, rhs, false); return 0; } @@ -609,7 +609,7 @@ XEEMITTER(cmpli, 0x28000000, D )(X64Emitter& e, X86Compiler& c, InstrDat c.mov(lhs.r32(), lhs.r32()); } - e.update_cr_with_cond(BF, lhs, e.get_uint64(i.D.DS)); + e.update_cr_with_cond(BF, lhs, e.get_uint64(i.D.DS), false); return 0; } diff --git a/src/xenia/cpu/x64/x64_emitter.cc b/src/xenia/cpu/x64/x64_emitter.cc index 5707a944c..094cf8567 100644 --- a/src/xenia/cpu/x64/x64_emitter.cc +++ b/src/xenia/cpu/x64/x64_emitter.cc @@ -1393,7 +1393,7 @@ void X64Emitter::update_cr_value(uint32_t n, GpVar& value) { } } -void X64Emitter::update_cr_with_cond(uint32_t n, GpVar& lhs) { +void X64Emitter::update_cr_with_cond(uint32_t n, GpVar& lhs, bool is_signed) { X86Compiler& c = compiler_; // bit0 = RA < 0 // bit1 = RA > 0 @@ -1405,8 +1405,13 @@ void X64Emitter::update_cr_with_cond(uint32_t n, GpVar& lhs) { GpVar v_g(c.newGpVar()); GpVar v_e(c.newGpVar()); c.cmp(lhs, imm(0)); - c.setl(v_l.r8()); - c.setg(v_g.r8()); + if (is_signed) { + c.setl(v_l.r8()); + c.setg(v_g.r8()); + } else { + c.setb(v_l.r8()); + c.seta(v_g.r8()); + } c.sete(v_e.r8()); GpVar v(c.newGpVar()); c.shl(v_g, imm(1)); @@ -1422,7 +1427,8 @@ void X64Emitter::update_cr_with_cond(uint32_t n, GpVar& lhs) { update_cr_value(n, v); } -void X64Emitter::update_cr_with_cond(uint32_t n, GpVar& lhs, GpVar& rhs) { +void X64Emitter::update_cr_with_cond(uint32_t n, GpVar& lhs, GpVar& rhs, + bool is_signed) { X86Compiler& c = compiler_; // bit0 = RA < RB // bit1 = RA > RB @@ -1434,8 +1440,13 @@ void X64Emitter::update_cr_with_cond(uint32_t n, GpVar& lhs, GpVar& rhs) { GpVar v_g(c.newGpVar()); GpVar v_e(c.newGpVar()); c.cmp(lhs, rhs); - c.setl(v_l.r8()); - c.setg(v_g.r8()); + if (is_signed) { + c.setl(v_l.r8()); + c.setg(v_g.r8()); + } else { + c.setb(v_l.r8()); + c.seta(v_g.r8()); + } c.sete(v_e.r8()); GpVar v(c.newGpVar()); c.shl(v_g, imm(1)); diff --git a/src/xenia/cpu/x64/x64_emitter.h b/src/xenia/cpu/x64/x64_emitter.h index a350d56f6..d084436a8 100644 --- a/src/xenia/cpu/x64/x64_emitter.h +++ b/src/xenia/cpu/x64/x64_emitter.h @@ -73,8 +73,10 @@ public: AsmJit::GpVar cr_value(uint32_t n); void update_cr_value(uint32_t n, AsmJit::GpVar& value); - void update_cr_with_cond(uint32_t n, AsmJit::GpVar& lhs); - void update_cr_with_cond(uint32_t n, AsmJit::GpVar& lhs, AsmJit::GpVar& rhs); + void update_cr_with_cond(uint32_t n, AsmJit::GpVar& lhs, + bool is_signed = true); + void update_cr_with_cond(uint32_t n, AsmJit::GpVar& lhs, AsmJit::GpVar& rhs, + bool is_signed = true); AsmJit::GpVar gpr_value(uint32_t n); void update_gpr_value(uint32_t n, AsmJit::GpVar& value);