aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/ARM/ARMCodeEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/ARM/ARMCodeEmitter.cpp')
-rw-r--r--lib/Target/ARM/ARMCodeEmitter.cpp204
1 files changed, 146 insertions, 58 deletions
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp
index c6ba65c551..8a2f034007 100644
--- a/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMCodeEmitter.cpp
@@ -88,9 +88,11 @@ namespace {
void emitWordLE(unsigned Binary);
void emitDWordLE(uint64_t Binary);
+ void emitConstantToMemory(unsigned CPI, const Constant *CV);
void emitConstPoolInstruction(const MachineInstr &MI);
void emitMOVi32immInstruction(const MachineInstr &MI);
void emitMOVi2piecesInstruction(const MachineInstr &MI);
+ void emitLEApcrelInstruction(const MachineInstr &MI);
void emitLEApcrelJTInstruction(const MachineInstr &MI);
void emitPseudoMoveInstruction(const MachineInstr &MI);
void addPCLabel(unsigned LabelID);
@@ -139,6 +141,8 @@ namespace {
void emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI);
+ void emitMiscInstruction(const MachineInstr &MI);
+
void emitNEONLaneInstruction(const MachineInstr &MI);
void emitNEONDupInstruction(const MachineInstr &MI);
void emitNEON1RegModImmInstruction(const MachineInstr &MI);
@@ -225,20 +229,25 @@ namespace {
uint32_t getAddrMode5OpValue(const MachineInstr &MI, unsigned Op) const {
// {12-9} = reg
// {8} = (U)nsigned (add == '1', sub == '0')
- // {7-0} = imm12
- const MachineOperand &MO = MI.getOperand(Op);
- const MachineOperand &MO1 = MI.getOperand(Op + 1);
- if (!MO.isReg()) {
- emitConstPoolAddress(MO.getIndex(), ARM::reloc_arm_cp_entry);
- return 0;
- }
- unsigned Reg = getARMRegisterNumbering(MO.getReg());
- int32_t Imm8 = MO1.getImm();
+ // {7-0} = imm8
uint32_t Binary;
- Binary = Imm8 & 0xff;
- if (Imm8 >= 0)
- Binary |= (1 << 8);
+ 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;
+ }
+ }
+
+ // If immediate offset is omitted, default to +0.
+ Binary |= 1 << 8;
return Binary;
}
unsigned getNEONVcvtImm32OpValue(const MachineInstr &MI, unsigned Op)
@@ -359,6 +368,9 @@ unsigned ARMCodeEmitter::getMachineOpValue(const MachineInstr &MI,
return getARMRegisterNumbering(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())
@@ -509,7 +521,9 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
case ARMII::VFPLdStMulFrm:
emitVFPLoadStoreMultipleInstruction(MI);
break;
-
+ case ARMII::VFPMiscFrm:
+ emitMiscInstruction(MI);
+ break;
// NEON instructions.
case ARMII::NGetLnFrm:
case ARMII::NSetLnFrm:
@@ -531,6 +545,61 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
MCE.processDebugLoc(MI.getDebugLoc(), false);
}
+void ARMCodeEmitter::emitConstantToMemory(unsigned CPI, const Constant *C) {
+ DEBUG({
+ errs() << " ** Constant pool #" << CPI << " @ "
+ << (void*)MCE.getCurrentPCValue() << " ";
+ if (const Function *F = dyn_cast<Function>(C))
+ errs() << F->getName();
+ else
+ errs() << *C;
+ errs() << '\n';
+ });
+
+ switch (C->getValueID()) {
+ default: {
+ llvm_unreachable("Unable to handle this constantpool entry!");
+ break;
+ }
+ case Value::GlobalVariableVal: {
+ emitGlobalAddress(static_cast<const GlobalValue*>(C),
+ ARM::reloc_arm_absolute, isa<Function>(C), false);
+ emitWordLE(0);
+ break;
+ }
+ case Value::ConstantIntVal: {
+ const ConstantInt *CI = static_cast<const ConstantInt*>(C);
+ uint32_t Val = *(uint32_t*)CI->getValue().getRawData();
+ emitWordLE(Val);
+ break;
+ }
+ case Value::ConstantFPVal: {
+ const ConstantFP *CFP = static_cast<const ConstantFP*>(C);
+ if (CFP->getType()->isFloatTy())
+ emitWordLE(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
+ else if (CFP->getType()->isDoubleTy())
+ emitDWordLE(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
+ else {
+ llvm_unreachable("Unable to handle this constantpool entry!");
+ }
+ break;
+ }
+ case Value::ConstantArrayVal: {
+ const ConstantArray *CA = static_cast<const ConstantArray*>(C);
+ for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
+ emitConstantToMemory(CPI, CA->getOperand(i));
+ break;
+ }
+ case Value::ConstantVectorVal:{
+ //FIXME:emit vector
+ const ConstantVector *CV = static_cast<const ConstantVector*>(C);
+ break;
+ }
+ }
+
+ return;
+}
+
void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) {
unsigned CPI = MI.getOperand(0).getImm(); // CP instruction index.
unsigned CPIndex = MI.getOperand(1).getIndex(); // Actual cp entry index.
@@ -561,35 +630,7 @@ void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) {
}
emitWordLE(0);
} else {
- const Constant *CV = MCPE.Val.ConstVal;
-
- DEBUG({
- errs() << " ** Constant pool #" << CPI << " @ "
- << (void*)MCE.getCurrentPCValue() << " ";
- if (const Function *F = dyn_cast<Function>(CV))
- errs() << F->getName();
- else
- errs() << *CV;
- errs() << '\n';
- });
-
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
- emitGlobalAddress(GV, ARM::reloc_arm_absolute, isa<Function>(GV), false);
- emitWordLE(0);
- } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
- uint32_t Val = uint32_t(*CI->getValue().getRawData());
- emitWordLE(Val);
- } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
- if (CFP->getType()->isFloatTy())
- emitWordLE(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
- else if (CFP->getType()->isDoubleTy())
- emitDWordLE(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
- else {
- llvm_unreachable("Unable to handle this constantpool entry!");
- }
- } else {
- llvm_unreachable("Unable to handle this constantpool entry!");
- }
+ emitConstantToMemory(CPI, MCPE.Val.ConstVal);
}
}
@@ -671,13 +712,39 @@ void ARMCodeEmitter::emitMOVi2piecesInstruction(const MachineInstr &MI) {
emitWordLE(Binary);
}
+void ARMCodeEmitter::emitLEApcrelInstruction(const MachineInstr &MI) {
+ // It's basically add r, pc, (LCPI - $+8)
+ const TargetInstrDesc &TID = 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, TID);
+
+ // Encode Rd.
+ Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift;
+
+ // Encode Rn which is PC.
+ Binary |= getARMRegisterNumbering(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)
const TargetInstrDesc &TID = MI.getDesc();
// Emit the 'add' instruction.
- unsigned Binary = 0x4 << 21; // add: Insts{24-31} = 0b0100
+ unsigned Binary = 0x4 << 21; // add: Insts{21-24} = 0b0100
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
@@ -815,7 +882,10 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) {
else
emitMOVi2piecesInstruction(MI);
break;
-
+ case ARM::LEApcrel:
+ // Materialize constantpool index address.
+ emitLEApcrelInstruction(MI);
+ break;
case ARM::LEApcrelJT:
// Materialize jumptable address.
emitLEApcrelJTInstruction(MI);
@@ -900,7 +970,7 @@ unsigned ARMCodeEmitter::getMachineSoImmOpValue(unsigned SoImm) {
unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI,
const TargetInstrDesc &TID) const {
- for (unsigned i = MI.getNumOperands(), e = TID.getNumOperands(); i != e; --i){
+ for (unsigned i = MI.getNumOperands(), e = TID.getNumOperands(); i >= e; --i){
const MachineOperand &MO = MI.getOperand(i-1);
if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR)
return 1 << ARMII::S_BitShift;
@@ -1018,7 +1088,8 @@ void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI,
// If this is an LDRi12, STRi12 or LDRcp, nothing more needs be done.
if (MI.getOpcode() == ARM::LDRi12 || MI.getOpcode() == ARM::LDRcp ||
- MI.getOpcode() == ARM::STRi12) {
+ MI.getOpcode() == ARM::STRi12 || MI.getOpcode() == ARM::LDRBi12 ||
+ MI.getOpcode() == ARM::STRBi12) {
emitWordLE(Binary);
return;
}
@@ -1452,9 +1523,10 @@ static unsigned encodeVFPRd(const MachineInstr &MI, unsigned OpIdx) {
unsigned Binary = 0;
bool isSPVFP = ARM::SPRRegisterClass->contains(RegD);
RegD = getARMRegisterNumbering(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;
}
@@ -1466,9 +1538,10 @@ static unsigned encodeVFPRn(const MachineInstr &MI, unsigned OpIdx) {
unsigned Binary = 0;
bool isSPVFP = ARM::SPRRegisterClass->contains(RegN);
RegN = getARMRegisterNumbering(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;
}
@@ -1480,9 +1553,10 @@ static unsigned encodeVFPRm(const MachineInstr &MI, unsigned OpIdx) {
unsigned Binary = 0;
bool isSPVFP = ARM::SPRRegisterClass->contains(RegM);
RegM = getARMRegisterNumbering(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;
}
@@ -1499,9 +1573,6 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) {
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
unsigned OpIdx = 0;
- assert((Binary & ARMII::D_BitShift) == 0 &&
- (Binary & ARMII::N_BitShift) == 0 &&
- (Binary & ARMII::M_BitShift) == 0 && "VFP encoding bug!");
// Encode Dd / Sd.
Binary |= encodeVFPRd(MI, OpIdx++);
@@ -1591,6 +1662,12 @@ void ARMCodeEmitter::emitVFPLoadStoreInstruction(const MachineInstr &MI) {
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
+ if (MI.getOpcode() == ARM::VLDRS || MI.getOpcode() == ARM::VLDRD ||
+ MI.getOpcode() == ARM::VSTRS || MI.getOpcode() == ARM::VSTRD){
+ emitWordLE(Binary);
+ return;
+ }
+
unsigned OpIdx = 0;
// Encode Dd / Sd.
@@ -1666,6 +1743,17 @@ ARMCodeEmitter::emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI) {
emitWordLE(Binary);
}
+void ARMCodeEmitter::emitMiscInstruction(const MachineInstr &MI) {
+ unsigned Opcode = MI.getDesc().Opcode;
+ // Part of binary is determined by TableGn.
+ unsigned Binary = getBinaryCodeForInstr(MI);
+
+ // Set the conditional execution predicate
+ Binary |= II->getPredicate(&MI) << ARMII::CondShift;
+
+ emitWordLE(Binary);
+}
+
static unsigned encodeNEONRd(const MachineInstr &MI, unsigned OpIdx) {
unsigned RegD = MI.getOperand(OpIdx).getReg();
unsigned Binary = 0;