uint32_t getAddrModePCOpValue(const MachineInstr &MI, unsigned Op)
const { return 0; }
uint32_t getAddrMode5OpValue(const MachineInstr &MI, unsigned Op) const {
- // {17-13} = reg
- // {12} = (U)nsigned (add == '1', sub == '0')
- // {11-0} = imm12
+ // {12-9} = reg
+ // {8} = (U)nsigned (add == '1', sub == '0')
+ // {7-0} = imm8
+ uint32_t Binary = 0;
const MachineOperand &MO = MI.getOperand(Op);
- uint32_t Reg = getMachineOpValue(MI, MO);
- Binary |= (Reg << 9);
-
- // If there is a non-zero immediate offset, encode it.
- if (MO.isReg()) {
- const MachineOperand &MO1 = MI.getOperand(Op + 1);
- if (uint32_t ImmOffs = ARM_AM::getAM5Offset(MO1.getImm())) {
- if (ARM_AM::getAM5Op(MO1.getImm()) == ARM_AM::add)
- Binary |= 1 << 8;
- Binary |= ImmOffs & 0xff;
- return Binary;
- }
+ const MachineOperand &MO1 = MI.getOperand(Op + 1);
+ if (!MO.isReg()) {
+ emitConstPoolAddress(MO.getIndex(), ARM::reloc_arm_cp_entry);
+ return 0;
+ }
+ unsigned Reg = II->getRegisterInfo().getEncodingValue(MO.getReg());
+ int32_t Imm12 = MO1.getImm();
+
+ // Special value for #-0
+ if (Imm12 == INT32_MIN)
+ Imm12 = 0;
+
+ // Immediate is always encoded as positive. The 'U' bit controls add vs
+ // sub.
+ bool isAdd = true;
+ if (Imm12 < 0) {
+ Imm12 = -Imm12;
+ isAdd = false;
}
- uint32_t Binary = Imm12 & 0xfff;
- if (isAdd)
- Binary |= (1 << 12);
- Binary |= (Reg << 13);
+ // If immediate offset is omitted, default to +0.
+ Binary |= 1 << 8;
return Binary;
}
unsigned getNEONVcvtImm32OpValue(const MachineInstr &MI, unsigned Op)
unsigned ARMCodeEmitter::getMachineOpValue(const MachineInstr &MI,
const MachineOperand &MO) const {
if (MO.isReg())
- return getARMRegisterNumbering(MO.getReg());
+ return II->getRegisterInfo().getEncodingValue(MO.getReg());
else if (MO.isImm())
return static_cast<unsigned>(MO.getImm());
+ else if (MO.isFPImm())
+ return static_cast<unsigned>(MO.getFPImm()->getValueAPF()
+ .bitcastToAPInt().getHiBits(32).getLimitedValue());
else if (MO.isGlobal())
emitGlobalAddress(MO.getGlobal(), ARM::reloc_arm_branch, true, false);
else if (MO.isSymbol())
emitWordLE(Binary);
}
- Binary |= getARMRegisterNumbering(ARM::PC) << ARMII::RegRnShift;
+void ARMCodeEmitter::emitLEApcrelInstruction(const MachineInstr &MI) {
+ // It's basically add r, pc, (LCPI - $+8)
+ const MCInstrDesc &MCID = MI.getDesc();
+
+ unsigned Binary = 0;
+
+ // Set the conditional execution predicate
+ Binary |= II->getPredicate(&MI) << ARMII::CondShift;
+
+ // Encode S bit if MI modifies CPSR.
+ Binary |= getAddrModeSBit(MI, MCID);
+
+ // Encode Rd.
+ Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift;
+
+ // Encode Rn which is PC.
++ Binary |= II->getRegisterInfo().getEncodingValue(ARM::PC) << ARMII::RegRnShift;
+
+ // Encode the displacement which is a so_imm.
+ // Set bit I(25) to identify this is the immediate form of <shifter_op>
+ Binary |= 1 << ARMII::I_BitShift;
+ emitConstPoolAddress(MI.getOperand(1).getIndex(), ARM::reloc_arm_so_imm_cp_entry);
+
+ emitWordLE(Binary);
+}
+
void ARMCodeEmitter::emitLEApcrelJTInstruction(const MachineInstr &MI) {
// It's basically add r, pc, (LJTI - $+8)
unsigned RegD = MI.getOperand(OpIdx).getReg();
unsigned Binary = 0;
bool isSPVFP = ARM::SPRRegClass.contains(RegD);
- RegD = getARMRegisterNumbering(RegD);
+ RegD = II->getRegisterInfo().getEncodingValue(RegD);
- if (!isSPVFP)
- Binary |= RegD << ARMII::RegRdShift;
- else {
+ if (!isSPVFP) {
+ Binary |= (RegD & 0x0F) << ARMII::RegRdShift;
+ Binary |= ((RegD & 0x10) >> 4) << ARMII::D_BitShift;
+ } else {
Binary |= ((RegD & 0x1E) >> 1) << ARMII::RegRdShift;
Binary |= (RegD & 0x01) << ARMII::D_BitShift;
}
unsigned RegN = MI.getOperand(OpIdx).getReg();
unsigned Binary = 0;
bool isSPVFP = ARM::SPRRegClass.contains(RegN);
- RegN = getARMRegisterNumbering(RegN);
+ RegN = II->getRegisterInfo().getEncodingValue(RegN);
- if (!isSPVFP)
- Binary |= RegN << ARMII::RegRnShift;
- else {
+ if (!isSPVFP) {
+ Binary |= (RegN & 0x0F) << ARMII::RegRnShift;
+ Binary |= ((RegN & 0x10) >> 4) << ARMII::N_BitShift;
+ } else {
Binary |= ((RegN & 0x1E) >> 1) << ARMII::RegRnShift;
Binary |= (RegN & 0x01) << ARMII::N_BitShift;
}
unsigned RegM = MI.getOperand(OpIdx).getReg();
unsigned Binary = 0;
bool isSPVFP = ARM::SPRRegClass.contains(RegM);
- RegM = getARMRegisterNumbering(RegM);
+ RegM = II->getRegisterInfo().getEncodingValue(RegM);
- if (!isSPVFP)
- Binary |= RegM;
- else {
+ if (!isSPVFP) {
+ Binary |= (RegM & 0x0F);
+ Binary |= ((RegM & 0x10) >> 4) << ARMII::M_BitShift;
+ } else {
Binary |= ((RegM & 0x1E) >> 1);
Binary |= (RegM & 0x01) << ARMII::M_BitShift;
}
emitWordLE(Binary);
}
- static unsigned encodeNEONRd(const MachineInstr &MI, unsigned OpIdx) {
+void ARMCodeEmitter::emitMiscInstruction(const MachineInstr &MI) {
+ unsigned Opcode = MI.getDesc().Opcode;
+ // Part of binary is determined by TableGn.
+ unsigned Binary = getBinaryCodeForInstr(MI);
+
+ if (Opcode == ARM::FCONSTS) {
+ unsigned Imm = getMachineOpValue(MI, 1);
+ Binary &= ~(0x780000 >> 19);
+ Binary |= (Imm & 0x780000) >> 19;
+ Binary &= ~(0x3800000 >> 7);
+ Binary |= (Imm & 0x3800000) >> 7;
+ Binary = VFPThumb2PostEncoder(MI, Binary);
+ }
+
+ // Set the conditional execution predicate
+ Binary |= II->getPredicate(&MI) << ARMII::CondShift;
+
+ emitWordLE(Binary);
+}
+
+ unsigned ARMCodeEmitter::encodeNEONRd(const MachineInstr &MI,
+ unsigned OpIdx) const {
unsigned RegD = MI.getOperand(OpIdx).getReg();
unsigned Binary = 0;
- RegD = getARMRegisterNumbering(RegD);
+ RegD = II->getRegisterInfo().getEncodingValue(RegD);
Binary |= (RegD & 0xf) << ARMII::RegRdShift;
Binary |= ((RegD >> 4) & 1) << ARMII::D_BitShift;
return Binary;
if (MR->getRelocationType() == ARM::reloc_arm_vfp_cp_entry)
ResultPtr = ResultPtr >> 2;
*((intptr_t*)RelocPos) |= ResultPtr;
- // Set register Rn to PC.
- *((intptr_t*)RelocPos) |=
- getARMRegisterNumbering(ARM::PC) << ARMII::RegRnShift;
+ // Set register Rn to PC (which is register 15 on all architectures).
+ // FIXME: This avoids the need for register info in the JIT class.
+ *((intptr_t*)RelocPos) |= 15 << ARMII::RegRnShift;
break;
}
+ case ARM::reloc_arm_so_imm_cp_entry: {
+ ResultPtr = ResultPtr - (intptr_t)RelocPos - 8;
+ // If the result is positive, set bit U(23) to 1.
+ if (ResultPtr >= 0)
+ *((intptr_t*)RelocPos) |= 1 << ARMII::U_BitShift;
+ else {
+ // Otherwise, obtain the absolute value and set bit U(23) to 0.
+ *((intptr_t*)RelocPos) &= ~(1 << ARMII::U_BitShift);
+ // FIXME: Also set bit 22 to 1 since 'sub' instruction is going to be used.
+ *((intptr_t*)RelocPos) |= 1 << 22;
+ ResultPtr = - ResultPtr;
+ }
+
+ int SoImmVal = ARM_AM::getSOImmVal(ResultPtr);
+ assert(SoImmVal != -1 && "Not a valid so_imm value!");
+ *((intptr_t*)RelocPos) |= (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1)
+ << ARMII::SoRotImmShift;
+ *((intptr_t*)RelocPos) |= ARM_AM::getSOImmValImm((unsigned)SoImmVal);
+ // Set register Rn to PC.
+ *((intptr_t*)RelocPos) |=
+ getARMRegisterNumbering(ARM::PC) << ARMII::RegRnShift;
+ break;
+ }
case ARM::reloc_arm_pic_jt:
case ARM::reloc_arm_machine_cp_entry:
case ARM::reloc_arm_absolute: {