From 69ebedb43f80751c32772f8c71f6cfede9d0e987 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Fri, 24 May 2013 19:10:54 -0700 Subject: [PATCH] addic + subfex. --- src/xenia/cpu/x64/x64_emit_alu.cc | 50 ++++++++++++++++++------------- src/xenia/cpu/x64/x64_emitter.cc | 19 +++++------- 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/src/xenia/cpu/x64/x64_emit_alu.cc b/src/xenia/cpu/x64/x64_emit_alu.cc index d5dd7c5e9..819297191 100644 --- a/src/xenia/cpu/x64/x64_emit_alu.cc +++ b/src/xenia/cpu/x64/x64_emit_alu.cc @@ -73,20 +73,20 @@ XEEMITTER(addi, 0x38000000, D )(X64Emitter& e, X86Compiler& c, InstrDat return 0; } -#if 0 XEEMITTER(addic, 0x30000000, D )(X64Emitter& e, X86Compiler& c, InstrData& i) { // RT <- (RA) + EXTS(SI) - // TODO(benvanik): track exception - jit_value_t v = jit_insn_add_ovf(f, e.make_signed(e.gpr_value(i.D.RA)), - e.get_int64(XEEXTS16(i.D.DS))); + GpVar v(c.newGpVar()); + c.mov(v, e.gpr_value(i.D.RA)); + c.add(v, imm(XEEXTS16(i.D.DS))); + GpVar cc(c.newGpVar()); + c.setc(cc); e.update_gpr_value(i.D.RT, v); - // e.update_xer_with_carry(b.CreateExtractValue(v, 1)); + e.update_xer_with_carry(cc); return 0; } -#endif XEEMITTER(addicx, 0x34000000, D )(X64Emitter& e, X86Compiler& c, InstrData& i) { XEINSTRNOTIMPLEMENTED(); @@ -426,27 +426,36 @@ XEEMITTER(subficx, 0x20000000, D )(X64Emitter& e, X86Compiler& c, InstrDat } #endif -#if 0 XEEMITTER(subfex, 0x7C000110, XO )(X64Emitter& e, X86Compiler& c, InstrData& i) { // RT <- ¬(RA) + (RB) + CA - // TODO(benvanik): possible that the add of rb+ca needs to also check for - // overflow! + GpVar v(c.newGpVar()); + c.mov(v, e.gpr_value(i.XO.RA)); + c.neg(v); + + // Add in carry flag from XER, only if needed. + // It may be possible to do this much more efficiently. + GpVar xer(c.newGpVar()); + c.mov(xer, e.xer_value()); + c.shr(xer, imm(29)); + c.and_(xer, imm(1)); + Label post_stc_label = c.newLabel(); + c.jz(post_stc_label, kCondHintLikely); + c.stc(); + c.bind(post_stc_label); + + c.adc(v, e.gpr_value(i.XO.RB)); + GpVar cc(c.newGpVar()); + c.setc(cc); - // TODO(benvanik): handle overflow exception - jit_value_t ca = jit_insn_and(f, jit_insn_ushr(f, e.xer_value(), - e.get_uint32(29)), - e.get_uint64(0x1)); - jit_value_t v = jit_insn_add_ovf(f, - e.make_unsigned(jit_insn_neg(f, e.gpr_value(i.XO.RA))), - e.make_unsigned(jit_insn_add(f, e.gpr_value(i.XO.RB), ca))); e.update_gpr_value(i.XO.RT, v); if (i.XO.OE) { // With XER update. - e.update_xer_with_overflow_and_carry(b.CreateExtractValue(v, 1)); + XEASSERTALWAYS(); + //e.update_xer_with_overflow_and_carry(b.CreateExtractValue(v, 1)); } else { - e.update_xer_with_carry(b.CreateExtractValue(v, 1)); + e.update_xer_with_carry(cc); } if (i.XO.Rc) { @@ -456,7 +465,6 @@ XEEMITTER(subfex, 0x7C000110, XO )(X64Emitter& e, X86Compiler& c, InstrDat return 0; } -#endif XEEMITTER(subfmex, 0x7C0001D0, XO )(X64Emitter& e, X86Compiler& c, InstrData& i) { XEINSTRNOTIMPLEMENTED(); @@ -1077,7 +1085,7 @@ void X64RegisterEmitCategoryALU() { XEREGISTERINSTR(addcx, 0X7C000014); XEREGISTERINSTR(addex, 0x7C000114); XEREGISTERINSTR(addi, 0x38000000); - // XEREGISTERINSTR(addic, 0x30000000); + XEREGISTERINSTR(addic, 0x30000000); XEREGISTERINSTR(addicx, 0x34000000); XEREGISTERINSTR(addis, 0x3C000000); XEREGISTERINSTR(addmex, 0x7C0001D4); @@ -1097,7 +1105,7 @@ void X64RegisterEmitCategoryALU() { // XEREGISTERINSTR(subfx, 0x7C000050); XEREGISTERINSTR(subfcx, 0x7C000010); // XEREGISTERINSTR(subficx, 0x20000000); - // XEREGISTERINSTR(subfex, 0x7C000110); + XEREGISTERINSTR(subfex, 0x7C000110); XEREGISTERINSTR(subfmex, 0x7C0001D0); XEREGISTERINSTR(subfzex, 0x7C000190); // XEREGISTERINSTR(cmp, 0x7C000000); diff --git a/src/xenia/cpu/x64/x64_emitter.cc b/src/xenia/cpu/x64/x64_emitter.cc index 9d699d3fa..c1cb05e24 100644 --- a/src/xenia/cpu/x64/x64_emitter.cc +++ b/src/xenia/cpu/x64/x64_emitter.cc @@ -1186,21 +1186,16 @@ void X64Emitter::update_xer_with_overflow(GpVar& value) { } #endif -#if 0 +// Set with a byte value indicating carry. void X64Emitter::update_xer_with_carry(GpVar& value) { X86Compiler& c = compiler_; - XEASSERT(locals_.xer.getId() != kInvalidValue); - - // Expects a i1 indicating carry. - // Trust the caller that if it's larger than that it's already truncated. - value = zero_extend(value, jit_type_nuint); - - GpVar& xer = xer_value(); - xer = jit_insn_and(fn_, xer, get_uint64(0xFFFFFFFFDFFFFFFF)); // clear bit 29 - xer = jit_insn_or(fn_, xer, jit_insn_shl(fn_, value, get_uint32(29))); - jit_insn_store(fn_, locals_.xer, value); + GpVar xer(c.newGpVar()); + c.mov(xer, xer_value()); + c.and_(xer, imm(0xDFFFFFFF)); // clear bit 29 + c.shl(value, imm(29)); + c.or_(xer, value); + update_xer_value(xer); } -#endif #if 0 void X64Emitter::update_xer_with_overflow_and_carry(GpVar& value) {