aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/ARM/ARMConstantIslandPass.cpp20
-rw-r--r--lib/Target/ARM/ARMExpandPseudoInsts.cpp43
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td19
-rw-r--r--lib/Target/ARM/ARMMCCodeEmitter.cpp22
-rw-r--r--lib/Target/ARM/Disassembler/ARMDisassembler.cpp14
-rw-r--r--lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h41
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp3
-rw-r--r--lib/Target/ARM/Thumb2SizeReduction.cpp52
-rw-r--r--test/MC/Disassembler/ARM/thumb-tests.txt2
9 files changed, 87 insertions, 129 deletions
diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp
index f8f717e4d4..934daba552 100644
--- a/lib/Target/ARM/ARMConstantIslandPass.cpp
+++ b/lib/Target/ARM/ARMConstantIslandPass.cpp
@@ -613,11 +613,7 @@ void ARMConstantIslands::InitialFunctionScan(MachineFunction &MF,
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;
@@ -1576,16 +1572,6 @@ bool ARMConstantIslands::OptimizeThumb2Instructions(MachineFunction &MF) {
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)
@@ -1596,10 +1582,6 @@ bool ARMConstantIslands::OptimizeThumb2Instructions(MachineFunction &MF) {
// 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);
diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp
index e0aeb920af..bd753d29ab 100644
--- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp
+++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp
@@ -780,7 +780,7 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
return true;
}
case ARM::TPsoft: {
- MachineInstrBuilder MIB =
+ MachineInstrBuilder MIB =
BuildMI(MBB, MBBI, MI.getDebugLoc(),
TII->get(ARM::BL))
.addExternalSymbol("__aeabi_read_tp", 0);
@@ -790,49 +790,16 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
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))
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index 60b6b1b331..c61c88f8cf 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -910,8 +910,23 @@ multiclass T2I_ld<bit signed, bits<2> opcod, string opc,
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.
diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp
index 94321ad57a..6d7b48587d 100644
--- a/lib/Target/ARM/ARMMCCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp
@@ -58,7 +58,7 @@ public:
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;
@@ -112,7 +112,7 @@ public:
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
-
+
/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
/// operand.
@@ -536,12 +536,12 @@ getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
Val &= ~0x400000;
else
Val |= 0x400000;
-
+
if (I ^ J2)
Val &= ~0x200000;
else
Val |= 0x200000;
-
+
return Val;
}
@@ -601,17 +601,13 @@ getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
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())
@@ -699,7 +695,7 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
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);
@@ -709,7 +705,7 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
: 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);
diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index 4964c64242..78d73d3a27 100644
--- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -256,27 +256,27 @@ static unsigned T2Morph2LoadLiteral(unsigned Opcode) {
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;
}
}
@@ -531,9 +531,9 @@ static MCDisassembler *createThumbDisassembler(const Target &T) {
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);
diff --git a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h
index 0418543f83..8a38507a5a 100644
--- a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h
+++ b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h
@@ -564,6 +564,38 @@ static bool DisassembleThumb1LdPC(MCInst &MI, unsigned Opcode, uint32_t insn,
// 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
@@ -1755,7 +1787,7 @@ static bool DisassembleThumb2PreLoad(MCInst &MI, unsigned Opcode, uint32_t insn,
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
@@ -1812,6 +1844,9 @@ static bool DisassembleThumb2LdSt(bool Load, MCInst &MI, unsigned Opcode,
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;
@@ -1858,7 +1893,7 @@ static bool DisassembleThumb2LdSt(bool Load, MCInst &MI, unsigned Opcode,
else
Imm = decodeImm8(insn);
}
-
+
MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
R0)));
++OpIdx;
@@ -2183,7 +2218,7 @@ static bool DisassembleThumbFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
}
// 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);
diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
index 941c69d14e..4f03b8497b 100644
--- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
+++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
@@ -574,9 +574,6 @@ void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
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());
diff --git a/lib/Target/ARM/Thumb2SizeReduction.cpp b/lib/Target/ARM/Thumb2SizeReduction.cpp
index 3d7bcb23f8..cc8f61cd72 100644
--- a/lib/Target/ARM/Thumb2SizeReduction.cpp
+++ b/lib/Target/ARM/Thumb2SizeReduction.cpp
@@ -234,7 +234,7 @@ static bool VerifyLowRegs(MachineInstr *MI) {
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) {
@@ -268,7 +268,6 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
return false;
unsigned Scale = 1;
- bool HasBaseReg = true;
bool HasImmOffset = false;
bool HasShift = false;
bool HasOffReg = true;
@@ -289,50 +288,19 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
}
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:
@@ -426,9 +394,7 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
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);
@@ -467,7 +433,7 @@ Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI,
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) {
diff --git a/test/MC/Disassembler/ARM/thumb-tests.txt b/test/MC/Disassembler/ARM/thumb-tests.txt
index 2870d500ce..29c67e7a03 100644
--- a/test/MC/Disassembler/ARM/thumb-tests.txt
+++ b/test/MC/Disassembler/ARM/thumb-tests.txt
@@ -27,7 +27,7 @@
# 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]!