static bool shiftLogical(PPCEmuAssembler& a, Instruction instr) { a.mov(a.eax, a.ppcgpr[instr.rS]); if (flags & ShiftImmediate) { if (flags & ShiftLeft) { a.shl(a.eax, instr.sh); } else if (flags & ShiftRight) { a.shr(a.eax, instr.sh); } else { assert(0); } } else { a.mov(a.ecx, a.ppcgpr[instr.rB]); if (flags & ShiftLeft) { a.shl(a.eax, a.ecx.r8()); } else if (flags & ShiftRight) { a.shr(a.eax, a.ecx.r8()); } else { assert(0); } } a.mov(a.ppcgpr[instr.rA], a.eax); if (instr.rc) { updateConditionRegister(a, a.eax, a.ecx, a.edx); } return true; }
// Move to Condition Register from XER static bool mcrxr(PPCEmuAssembler& a, Instruction instr) { uint32_t crshift = (7 - instr.crfD) * 4; a.mov(a.eax, a.ppcxer); a.mov(a.ecx, a.eax); // Grab CRXR a.shr(a.ecx, XERegisterBits::XRShift); a.and_(a.ecx, 0xF); // Clear XER CRXR a.and_(a.eax, ~XERegisterBits::XR); a.mov(a.ppcxer, a.eax); // Set CRF a.shl(a.ecx, crshift); a.mov(a.eax, a.ppccr); a.and_(a.eax, ~(0xF << crshift)); a.or_(a.eax, a.ecx); a.mov(a.ppccr, a.eax); return true; }
void getTwoCRB(PPCEmuAssembler& a, uint32_t bita, const asmjit::X86GpReg& da, uint32_t bitb, const asmjit::X86GpReg& db) { auto shifta = 31 - bita; auto shiftb = 31 - bitb; a.mov(da, a.ppccr); a.mov(db, da); if (shifta > 0) { a.shr(da, shifta); } if (shiftb > 0) { a.shr(db, shiftb); } a.and_(da, 1); a.and_(db, 1); }
// Move Condition Register Field static bool mcrf(PPCEmuAssembler& a, Instruction instr) { uint32_t crshifts = (7 - instr.crfS) * 4; uint32_t crshiftd = (7 - instr.crfD) * 4; a.mov(a.eax, a.ppccr); a.mov(a.ecx, a.eax); a.and_(a.ecx, ~(0xF << crshifts)); a.shr(a.ecx, crshifts); a.shl(a.ecx, crshiftd); a.and_(a.eax, ~(0xF << crshiftd)); a.or_(a.eax, a.ecx); a.mov(a.ppccr, a.eax); return true; }
static bool cmpGeneric(PPCEmuAssembler& a, Instruction instr) { uint32_t crshift = (7 - instr.crfD) * 4; // Load CRF a.mov(a.edx, a.ppccr); // Mask CRF uint32_t mask = 0xFFFFFFFF; mask &= ~(0xF << crshift); a.and_(a.edx, mask); // Summary Overflow a.mov(a.eax, a.ppcxer); a.and_(a.eax, XERegisterBits::StickyOV); a.shr(a.eax, XERegisterBits::StickyOVShift); a.shl(a.eax, ConditionRegisterFlag::SummaryOverflowShift << crshift); a.or_(a.edx, a.eax); // Perform Comparison a.mov(a.eax, a.ppcgpr[instr.rA]); if (flags & CmpImmediate) { if (std::is_signed<Type>::value) { a.mov(a.ecx, sign_extend<16>(instr.simm)); } else { a.mov(a.ecx, instr.uimm); } } else { a.mov(a.ecx, a.ppcgpr[instr.rB]); } a.cmp(a.eax, a.ecx); a.mov(a.r8d, 0); if (std::is_unsigned<Type>::value) { a.seta(a.r8d.r8()); } else { a.setg(a.r8d.r8()); } a.mov(a.r9d, 0); if (std::is_unsigned<Type>::value) { a.setb(a.r9d.r8()); } else { a.setl(a.r9d.r8()); } a.mov(a.ecx, 0); a.sete(a.ecx.r8()); a.shl(a.ecx, crshift + ConditionRegisterFlag::ZeroShift); a.or_(a.edx, a.ecx); a.mov(a.ecx, a.r8d); a.shl(a.ecx, crshift + ConditionRegisterFlag::PositiveShift); a.or_(a.edx, a.ecx); a.mov(a.ecx, a.r9d); a.shl(a.ecx, crshift + ConditionRegisterFlag::NegativeShift); a.or_(a.edx, a.ecx); a.mov(a.ppccr, a.edx); return true; }