case ARM::LDRi12:
case ARM::LDRcp:
- case ARM::t2LDRi12:
- case ARM::t2LDRHi12:
- case ARM::t2LDRBi12:
- case ARM::t2LDRSHi12:
- case ARM::t2LDRSBi12:
+ case ARM::t2LDRpci:
Bits = 12; // +-offset_12
NegOk = true;
break;
Scale = 4;
}
break;
- case ARM::t2LDRi12:
- // FIXME: Temporary workaround for a bug introduced by r121082.
- // We should use t2LDRpci for loads from constantpools.
- if (isARMLowRegister(U.MI->getOperand(0).getReg()) &&
- U.MI->getOperand(1).getReg() == ARM::PC) {
- NewOpc = ARM::tLDRpci;
- Bits = 8;
- Scale = 4;
- }
- break;
}
if (!NewOpc)
// FIXME: Check if offset is multiple of scale if scale is not 4.
if (CPEIsInRange(U.MI, UserOffset, U.CPEMI, MaxOffs, false, true)) {
U.MI->setDesc(TII->get(NewOpc));
- if (NewOpc == ARM::tLDRpci)
- // FIXME: Temporary workaround.
- // PC is now an implicit operand.
- U.MI->RemoveOperand(1);
MachineBasicBlock *MBB = U.MI->getParent();
BBSizes[MBB->getNumber()] -= 2;
AdjustBBOffsetsAfter(MBB, -2);
return true;
}
case ARM::TPsoft: {
- MachineInstrBuilder MIB =
+ MachineInstrBuilder MIB =
BuildMI(MBB, MBBI, MI.getDebugLoc(),
TII->get(ARM::BL))
.addExternalSymbol("__aeabi_read_tp", 0);
MI.eraseFromParent();
return true;
}
- case ARM::t2LDRHpci:
- case ARM::t2LDRBpci:
- case ARM::t2LDRSHpci:
- case ARM::t2LDRSBpci:
- case ARM::t2LDRpci: {
- unsigned NewLdOpc;
- if (Opcode == ARM::t2LDRpci)
- NewLdOpc = ARM::t2LDRi12;
- else if (Opcode == ARM::t2LDRHpci)
- NewLdOpc = ARM::t2LDRHi12;
- else if (Opcode == ARM::t2LDRBpci)
- NewLdOpc = ARM::t2LDRBi12;
- else if (Opcode == ARM::t2LDRSHpci)
- NewLdOpc = ARM::t2LDRSHi12;
- else if (Opcode == ARM::t2LDRSBpci)
- NewLdOpc = ARM::t2LDRSBi12;
- else
- llvm_unreachable("Not a known opcode?");
-
- unsigned DstReg = MI.getOperand(0).getReg();
- MachineInstrBuilder MIB =
- AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
- TII->get(NewLdOpc), DstReg)
- .addReg(ARM::PC)
- .addOperand(MI.getOperand(1)));
- (*MIB).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
- TransferImpOps(MI, MIB, MIB);
- MI.eraseFromParent();
- return true;
- }
-
case ARM::tLDRpci_pic:
case ARM::t2LDRpci_pic: {
unsigned NewLdOpc = (Opcode == ARM::tLDRpci_pic)
- ? ARM::tLDRpci : ARM::t2LDRi12;
+ ? ARM::tLDRpci : ARM::t2LDRpci;
unsigned DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
MachineInstrBuilder MIB1 =
- BuildMI(MBB, MBBI, MI.getDebugLoc(),
- TII->get(NewLdOpc), DstReg);
- if (Opcode == ARM::t2LDRpci_pic) MIB1.addReg(ARM::PC);
- MIB1.addOperand(MI.getOperand(1));
- AddDefaultPred(MIB1);
+ AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),
+ TII->get(NewLdOpc), DstReg)
+ .addOperand(MI.getOperand(1)));
(*MIB1).setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
MachineInstrBuilder MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
TII->get(ARM::tPICADD))
let Inst{5-4} = addr{1-0}; // imm
}
- def pci : t2PseudoInst<(outs GPR:$Rt), (ins i32imm:$addr), Size4Bytes, iis,
- [(set GPR:$Rt, (opnode (ARMWrapper tconstpool:$addr)))]>;
+ // FIXME: Is the pci variant actually needed?
+ def pci : T2Ipc <(outs GPR:$Rt), (ins i32imm:$addr), iii,
+ opc, ".w\t$Rt, $addr",
+ [(set GPR:$Rt, (opnode (ARMWrapper tconstpool:$addr)))]> {
+ let isReMaterializable = 1;
+ let Inst{31-27} = 0b11111;
+ let Inst{26-25} = 0b00;
+ let Inst{24} = signed;
+ let Inst{23} = ?; // add = (U == '1')
+ let Inst{22-21} = opcod;
+ let Inst{20} = 1; // load
+ let Inst{19-16} = 0b1111; // Rn
+ bits<4> Rt;
+ bits<12> addr;
+ let Inst{15-12} = Rt{3-0};
+ let Inst{11-0} = addr{11-0};
+ }
}
/// T2I_st - Defines a set of (op r, {imm12|imm8|so_reg}) store patterns.
SmallVectorImpl<MCFixup> &Fixups) const;
/// getHiLo16ImmOpValue - Return the encoding for the hi / low 16-bit of
- /// the specified operand. This is used for operands with :lower16: and
+ /// the specified operand. This is used for operands with :lower16: and
/// :upper16: prefixes.
uint32_t getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
-
+
/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
/// operand.
Val &= ~0x400000;
else
Val |= 0x400000;
-
+
if (I ^ J2)
Val &= ~0x200000;
else
Val |= 0x200000;
-
+
return Val;
}
bool isAdd = true;
// If The first operand isn't a register, we have a label reference.
const MCOperand &MO = MI.getOperand(OpIdx);
- const MCOperand &MO2 = MI.getOperand(OpIdx+1);
- if (!MO.isReg() || (MO.getReg() == ARM::PC && MO2.isExpr())) {
+ if (!MO.isReg()) {
Reg = getARMRegisterNumbering(ARM::PC); // Rn is PC.
Imm12 = 0;
isAdd = false ; // 'U' bit is set as part of the fixup.
- const MCExpr *Expr = 0;
- if (!MO.isReg())
- Expr = MO.getExpr();
- else
- Expr = MO2.getExpr();
+ assert(MO.isExpr() && "Unexpected machine operand type!");
+ const MCExpr *Expr = MO.getExpr();
MCFixupKind Kind;
if (Subtarget->isThumb2())
switch (ARM16Expr->getKind()) {
default: assert(0 && "Unsupported ARMFixup");
case ARMMCExpr::VK_ARM_HI16:
- if (!Subtarget->isTargetDarwin() && EvaluateAsPCRel(E))
+ if (!Subtarget->isTargetDarwin() && EvaluateAsPCRel(E))
Kind = MCFixupKind(Subtarget->isThumb2()
? ARM::fixup_t2_movt_hi16_pcrel
: ARM::fixup_arm_movt_hi16_pcrel);
: ARM::fixup_arm_movt_hi16);
break;
case ARMMCExpr::VK_ARM_LO16:
- if (!Subtarget->isTargetDarwin() && EvaluateAsPCRel(E))
+ if (!Subtarget->isTargetDarwin() && EvaluateAsPCRel(E))
Kind = MCFixupKind(Subtarget->isThumb2()
? ARM::fixup_t2_movw_lo16_pcrel
: ARM::fixup_arm_movw_lo16_pcrel);
case ARM::t2LDR_POST: case ARM::t2LDR_PRE:
case ARM::t2LDRi12: case ARM::t2LDRi8:
case ARM::t2LDRs: case ARM::t2LDRT:
- return ARM::t2LDRi12;
+ return ARM::t2LDRpci;
case ARM::t2LDRB_POST: case ARM::t2LDRB_PRE:
case ARM::t2LDRBi12: case ARM::t2LDRBi8:
case ARM::t2LDRBs: case ARM::t2LDRBT:
- return ARM::t2LDRBi12;
+ return ARM::t2LDRBpci;
case ARM::t2LDRH_POST: case ARM::t2LDRH_PRE:
case ARM::t2LDRHi12: case ARM::t2LDRHi8:
case ARM::t2LDRHs: case ARM::t2LDRHT:
- return ARM::t2LDRHi12;
+ return ARM::t2LDRHpci;
case ARM::t2LDRSB_POST: case ARM::t2LDRSB_PRE:
case ARM::t2LDRSBi12: case ARM::t2LDRSBi8:
case ARM::t2LDRSBs: case ARM::t2LDRSBT:
- return ARM::t2LDRSBi12;
+ return ARM::t2LDRSBpci;
case ARM::t2LDRSH_POST: case ARM::t2LDRSH_PRE:
case ARM::t2LDRSHi12: case ARM::t2LDRSHi8:
case ARM::t2LDRSHs: case ARM::t2LDRSHT:
- return ARM::t2LDRSHi12;
+ return ARM::t2LDRSHpci;
}
}
return new ThumbDisassembler;
}
-extern "C" void LLVMInitializeARMDisassembler() {
+extern "C" void LLVMInitializeARMDisassembler() {
// Register the disassembler.
- TargetRegistry::RegisterMCDisassembler(TheARMTarget,
+ TargetRegistry::RegisterMCDisassembler(TheARMTarget,
createARMDisassembler);
TargetRegistry::RegisterMCDisassembler(TheThumbTarget,
createThumbDisassembler);
// t_addrmode_sp := sp + imm8 * 4
//
+// A8.6.63 LDRB (literal)
+// A8.6.79 LDRSB (literal)
+// A8.6.75 LDRH (literal)
+// A8.6.83 LDRSH (literal)
+// A8.6.59 LDR (literal)
+//
+// These instrs calculate an address from the PC value and an immediate offset.
+// Rd Rn=PC (+/-)imm12 (+ if Inst{23} == 0b1)
+static bool DisassembleThumb2Ldpci(MCInst &MI, unsigned Opcode,
+ uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
+
+ const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
+ if (!OpInfo) return false;
+
+ assert(NumOps >= 2 &&
+ OpInfo[0].RegClass == ARM::GPRRegClassID &&
+ OpInfo[1].RegClass < 0 &&
+ "Expect >= 2 operands, first as reg, and second as imm operand");
+
+ // Build the register operand, followed by the (+/-)imm12 immediate.
+
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
+ decodeRd(insn))));
+
+ MI.addOperand(MCOperand::CreateImm(decodeImm12(insn)));
+
+ NumOpsAdded = 2;
+
+ return true;
+}
+
+
// A6.2.4 Load/store single data item
//
// Load/Store Register (reg|imm): tRd tRn imm5 tRm
if (slice(insn, 19, 16) == 0xFF) {
bool Negative = slice(insn, 23, 23) == 0;
unsigned Imm12 = getImm12(insn);
- Offset = Negative ? -1 - Imm12 : 1 * Imm12;
+ Offset = Negative ? -1 - Imm12 : 1 * Imm12;
} else if (Opcode == ARM::t2PLDi8 || Opcode == ARM::t2PLDWi8 ||
Opcode == ARM::t2PLIi8) {
// A8.6.117 Encoding T2: add = FALSE
if (Thumb2PreloadOpcode(Opcode))
return DisassembleThumb2PreLoad(MI, Opcode, insn, NumOps, NumOpsAdded, B);
+ // See, for example, A6.3.7 Load word: Table A6-18 Load word.
+ if (Load && Rn == 15)
+ return DisassembleThumb2Ldpci(MI, Opcode, insn, NumOps, NumOpsAdded, B);
const TargetInstrDesc &TID = ARMInsts[Opcode];
const TargetOperandInfo *OpInfo = TID.OpInfo;
unsigned &OpIdx = NumOpsAdded;
else
Imm = decodeImm8(insn);
}
-
+
MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
R0)));
++OpIdx;
}
// A6.3 32-bit Thumb instruction encoding
-
+
uint16_t op1 = slice(HalfWord, 12, 11);
uint16_t op2 = slice(HalfWord, 10, 4);
uint16_t op = slice(insn, 15, 15);
if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
printOperand(MI, OpNum, O);
return;
- } else if (MO1.getReg() == ARM::PC && MO2.isExpr()) {
- printOperand(MI, OpNum+1, O);
- return;
}
O << "[" << getRegisterName(MO1.getReg());
unsigned Opc = MI->getOpcode();
bool isPCOk = (Opc == ARM::t2LDMIA_RET || Opc == ARM::t2LDMIA ||
Opc == ARM::t2LDMDB || Opc == ARM::t2LDMIA_UPD ||
- Opc == ARM::t2LDMDB_UPD || Opc == ARM::t2LDRi12);
+ Opc == ARM::t2LDMDB_UPD);
bool isLROk = (Opc == ARM::t2STMIA_UPD || Opc == ARM::t2STMDB_UPD);
bool isSPOk = isPCOk || isLROk || (Opc == ARM::t2ADDrSPi);
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
return false;
unsigned Scale = 1;
- bool HasBaseReg = true;
bool HasImmOffset = false;
bool HasShift = false;
bool HasOffReg = true;
}
Scale = 4;
-
- if (MI->getOperand(2).isImm()) {
- HasImmOffset = true;
- HasOffReg = false;
- } else {
- // FIXME: Temporary workaround for a bug introduced by r121082.
- // We should use t2LDRpci for loads from constantpools.
- // We don't want to narrow this to tLDRpci until constant island pass
- // for fear of pessimizing code.
- return false;
- }
+ HasImmOffset = true;
+ HasOffReg = false;
break;
case ARM::t2LDRBi12:
case ARM::t2STRBi12:
- if (MI->getOperand(2).isImm()) {
- HasImmOffset = true;
- HasOffReg = false;
- } else {
- if (Entry.WideOpc == ARM::t2LDRBi12) {
- Opc = ARM::tLDRpci;
- OpNum = 2;
- }
-
- HasImmOffset = false;
- HasBaseReg = false;
- HasOffReg = false;
- }
+ HasImmOffset = true;
+ HasOffReg = false;
break;
case ARM::t2LDRHi12:
case ARM::t2STRHi12:
Scale = 2;
- if (MI->getOperand(2).isImm()) {
- HasImmOffset = true;
- HasOffReg = false;
- } else {
- if (Entry.WideOpc == ARM::t2LDRHi12) {
- Opc = ARM::tLDRpci;
- OpNum = 2;
- }
-
- HasImmOffset = false;
- HasBaseReg = false;
- HasOffReg = false;
- }
+ HasImmOffset = true;
+ HasOffReg = false;
break;
case ARM::t2LDRs:
case ARM::t2LDRBs:
MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, TII->get(Opc));
if (!isLdStMul) {
MIB.addOperand(MI->getOperand(0));
-
- if (HasBaseReg)
- MIB.addOperand(MI->getOperand(1));
+ MIB.addOperand(MI->getOperand(1));
if (HasImmOffset)
MIB.addImm(OffsetImm / Scale);
unsigned Opc = MI->getOpcode();
switch (Opc) {
default: break;
- case ARM::t2ADDSri:
+ case ARM::t2ADDSri:
case ARM::t2ADDSrr: {
unsigned PredReg = 0;
if (getInstrPredicate(MI, PredReg) == ARMCC::AL) {
# CHECK: ldmia r0!, {r1}
0x02 0xc8
-# CHECK: ldrb.w r8, [pc, #-24]
+# CHECK: ldrb.w r8, #-24
0x1f 0xf8 0x18 0x80
# CHECK: ldrd r0, r1, [r7, #64]!