Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
static bool
xorGeneric(PPCEmuAssembler& a, Instruction instr)
{
   a.mov(a.eax, a.ppcgpr[instr.rS]);

   if (flags & XorImmediate) {
      a.mov(a.ecx, instr.uimm);
   } else {
      a.mov(a.ecx, a.ppcgpr[instr.rB]);
   }

   if (flags & XorShifted) {
      a.shl(a.ecx, 16);
   }

   a.xor_(a.eax, a.ecx);
   a.mov(a.ppcgpr[instr.rA], a.eax);

   if (flags & XorCheckRecord) {
      if (instr.rc) {
         updateConditionRegister(a, a.eax, a.ecx, a.edx);
      }
   }

   return true;
}
Exemplo n.º 3
0
static bool
andGeneric(PPCEmuAssembler& a, Instruction instr)
{
   a.mov(a.eax, a.ppcgpr[instr.rS]);

   if (flags & AndImmediate) {
      a.mov(a.ecx, instr.uimm);
   } else {
      a.mov(a.ecx, a.ppcgpr[instr.rB]);
   }

   if (flags & AndShifted) {
      a.shl(a.ecx, 16);
   }

   if (flags & AndComplement) {
      a.not_(a.ecx);
   }

   a.and_(a.eax, a.ecx);

   a.mov(a.ppcgpr[instr.rA], a.eax);

   if (flags & AndAlwaysRecord) {
      updateConditionRegister(a, a.eax, a.ecx, a.edx);
   } else if (flags & AndCheckRecord) {
      if (instr.rc) {
         updateConditionRegister(a, a.eax, a.ecx, a.edx);
      }
   }

   return true;
}
Exemplo n.º 4
0
// 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;
}
Exemplo n.º 5
0
void setCRB(PPCEmuAssembler& a, uint32_t bit, const asmjit::X86GpReg& value, const asmjit::X86GpReg& tmp, const asmjit::X86GpReg& tmp2) {
   auto shift = 31 - bit;
   a.mov(tmp, a.ppccr);
   a.and_(tmp, ~(1 << shift));
   a.mov(tmp2, value);
   a.and_(tmp2, 1);
   a.shl(tmp2, shift);
   a.or_(tmp, tmp2);
   a.mov(a.ppccr, tmp);
}
Exemplo n.º 6
0
// 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);
}
Exemplo n.º 7
0
// 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;
}
Exemplo n.º 8
0
static bool
addGeneric(PPCEmuAssembler& a, Instruction instr)
{
   if (flags & AddSubtract) {
      return jit_fallback(a, instr);
   }

   bool recordCarry = false;
   bool recordOverflow = false;
   bool recordCond = false;

   if (flags & AddCarry) {
      recordCarry = true;
   }

   if (flags & AddAlwaysRecord) {
      recordOverflow = true;
      recordCond = true;
   } else if (flags & AddCheckRecord) {
      if (instr.oe) {
         recordOverflow = true;
      }

      if (instr.rc) {
         recordCond = true;
      }
   }

   if ((flags & AddZeroRA) && instr.rA == 0) {
      a.mov(a.eax, 0);
   } else {
      a.mov(a.eax, a.ppcgpr[instr.rA]);
   }

   if (flags & AddSubtract) {
      a.not_(a.eax);
   }

   if (flags & AddImmediate) {
      a.mov(a.ecx, sign_extend<16>(instr.simm));
   } else if (flags & AddToZero) {
      a.mov(a.ecx, 0);
   } else if (flags & AddToMinusOne) {
      a.mov(a.ecx, -1);
   } else {
      a.mov(a.ecx, a.ppcgpr[instr.rB]);
   }

   if (flags & AddShifted) {
      a.shl(a.ecx, 16);
   }

   // Mark x64 CF based on PPC CF
   if (flags & AddExtended) {
      a.mov(a.edx, a.ppcxer);
      a.and_(a.edx, XERegisterBits::Carry);
      a.add(a.edx, 0xffffffff);

      a.adc(a.eax, a.ecx);
   } else if (flags & AddSubtract) {
      a.stc();

      a.adc(a.eax, a.ecx);
   } else {
      a.add(a.eax, a.ecx);
   }

   if (recordCarry && recordOverflow) {
      a.mov(a.ecx, 0);
      a.setc(a.ecx.r8());
      a.mov(a.edx, 0);
      a.seto(a.edx.r8());

      a.shl(a.ecx, XERegisterBits::CarryShift);
      a.shl(a.edx, XERegisterBits::OverflowShift);
      a.or_(a.ecx, a.edx);
   } else if (recordCarry) {
      a.mov(a.ecx, 0);
      a.setc(a.ecx.r8());
      a.shl(a.ecx, XERegisterBits::CarryShift);
   } else if (recordOverflow) {
      a.mov(a.ecx, 0);
      a.seto(a.ecx.r8());
      a.shl(a.ecx, XERegisterBits::OverflowShift);
   }

   if (recordCarry || recordOverflow) {
      uint32_t mask = 0xFFFFFFFF;

      if (recordCarry) {
         mask &= ~XERegisterBits::Carry;
      }

      if (recordOverflow) {
         mask &= ~XERegisterBits::Overflow;
      }

      a.mov(a.edx, a.ppcxer);
      a.and_(a.edx, mask);
      a.or_(a.edx, a.ecx);
      a.mov(a.ppcxer, a.edx);
   }

   a.mov(a.ppcgpr[instr.rD], a.eax);

   if (recordCond) {
      updateConditionRegister(a, a.eax, a.ecx, a.edx);
   }

   return true;
}
Exemplo n.º 9
0
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;
}