// Negate static bool neg(PPCEmuAssembler& a, Instruction instr) { a.mov(a.eax, a.ppcgpr[instr.rA]); a.neg(a.eax); a.mov(a.ppcgpr[instr.rD], a.eax); if (instr.oe) { a.mov(a.ecx, 0); a.seto(a.ecx.r8()); // Reset overflow a.mov(a.edx, a.ppcxer); a.and_(a.edx, ~XERegisterBits::Overflow); a.shiftTo(a.ecx, 0, XERegisterBits::Overflow); a.or_(a.edx, a.ecx); a.shiftTo(a.ecx, XERegisterBits::Overflow, XERegisterBits::StickyOV); a.or_(a.edx, a.ecx); a.mov(a.ppcxer, a.edx); } if (instr.rc) { updateConditionRegister(a, a.eax, a.ecx, a.edx); } return true; }
// Update cr0 with value static void updateConditionRegister(PPCEmuAssembler& a, const asmjit::X86GpReg& value, const asmjit::X86GpReg& tmp, const asmjit::X86GpReg& tmp2) { auto crtarget = 0; auto crshift = (7 - crtarget) * 4; a.mov(tmp, a.ppccr); a.and_(tmp, ~(0xF << crshift)); a.cmp(value, 0); a.lahf(); a.mov(tmp2, 0); a.sete(tmp2.r8()); a.shl(tmp2, crshift + ConditionRegisterFlag::ZeroShift); a.or_(tmp, tmp2); a.sahf(); a.mov(tmp2, 0); a.setg(tmp2.r8()); a.shl(tmp2, crshift + ConditionRegisterFlag::PositiveShift); a.or_(tmp, tmp2); a.sahf(); a.mov(tmp2, 0); a.setl(tmp2.r8()); a.shl(tmp2, crshift + ConditionRegisterFlag::NegativeShift); a.or_(tmp, tmp2); a.mov(tmp2, a.ppcxer); a.and_(tmp2, XERegisterBits::StickyOV); a.shiftTo(tmp2, XERegisterBits::StickyOVShift, crshift + ConditionRegisterFlag::SummaryOverflowShift); a.or_(tmp, tmp2); a.mov(a.ppccr, tmp); }