diff --git a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp index 3c2540856478..dee50f685c16 100644 --- a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -605,7 +605,11 @@ void ARMConstantIslands::InitialFunctionScan(MachineFunction &MF, case ARM::LDRi12: case ARM::LDRcp: - case ARM::t2LDRpci: + case ARM::t2LDRi12: + case ARM::t2LDRHi12: + case ARM::t2LDRBi12: + case ARM::t2LDRSHi12: + case ARM::t2LDRSBi12: Bits = 12; // +-offset_12 NegOk = true; break; diff --git a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp index 1c02c34e8266..ca7a90aa12f3 100644 --- a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -699,16 +699,48 @@ bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) { MI.eraseFromParent(); break; } + 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(); + break; + } case ARM::tLDRpci_pic: case ARM::t2LDRpci_pic: { unsigned NewLdOpc = (Opcode == ARM::tLDRpci_pic) - ? ARM::tLDRpci : ARM::t2LDRpci; + ? ARM::tLDRpci : ARM::t2LDRi12; unsigned DstReg = MI.getOperand(0).getReg(); bool DstIsDead = MI.getOperand(0).isDead(); MachineInstrBuilder MIB1 = - AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), - TII->get(NewLdOpc), DstReg) - .addOperand(MI.getOperand(1))); + 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); (*MIB1).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); MachineInstrBuilder MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tPICADD)) diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td index 0adcba02d3bc..98b7d0671299 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb2.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -888,24 +888,8 @@ multiclass T2I_ld opcod, string opc, let Inst{5-4} = addr{1-0}; // imm } - // 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}; - } + def pci : tPseudoInst<(outs GPR:$Rt), (ins i32imm:$addr), Size4Bytes, iis, + [(set GPR:$Rt, (opnode (ARMWrapper tconstpool:$addr)))]>; } /// T2I_st - Defines a set of (op r, {imm12|imm8|so_reg}) store patterns. diff --git a/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp b/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp index b8939a1531c3..b0113476fa8f 100644 --- a/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -462,13 +462,18 @@ 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); - if (!MO.isReg()) { + const MCOperand &MO2 = MI.getOperand(OpIdx+1); + if (!MO.isReg() || (MO.getReg() == ARM::PC && MO2.isExpr())) { Reg = getARMRegisterNumbering(ARM::PC); // Rn is PC. Imm12 = 0; isAdd = false ; // 'U' bit is set as part of the fixup. - assert(MO.isExpr() && "Unexpected machine operand type!"); - const MCExpr *Expr = MO.getExpr(); + const MCExpr *Expr = 0; + if (!MO.isReg()) + Expr = MO.getExpr(); + else + Expr = MO2.getExpr(); + MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_ldst_pcrel_12); Fixups.push_back(MCFixup::Create(0, Expr, Kind)); diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index c3d24d2d70ec..4964c642424f 100644 --- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/llvm/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::t2LDRpci; + return ARM::t2LDRi12; case ARM::t2LDRB_POST: case ARM::t2LDRB_PRE: case ARM::t2LDRBi12: case ARM::t2LDRBi8: case ARM::t2LDRBs: case ARM::t2LDRBT: - return ARM::t2LDRBpci; + return ARM::t2LDRBi12; case ARM::t2LDRH_POST: case ARM::t2LDRH_PRE: case ARM::t2LDRHi12: case ARM::t2LDRHi8: case ARM::t2LDRHs: case ARM::t2LDRHT: - return ARM::t2LDRHpci; + return ARM::t2LDRHi12; case ARM::t2LDRSB_POST: case ARM::t2LDRSB_PRE: case ARM::t2LDRSBi12: case ARM::t2LDRSBi8: case ARM::t2LDRSBs: case ARM::t2LDRSBT: - return ARM::t2LDRSBpci; + return ARM::t2LDRSBi12; case ARM::t2LDRSH_POST: case ARM::t2LDRSH_PRE: case ARM::t2LDRSHi12: case ARM::t2LDRSHi8: case ARM::t2LDRSHs: case ARM::t2LDRSHT: - return ARM::t2LDRSHpci; + return ARM::t2LDRSHi12; } } diff --git a/llvm/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h b/llvm/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h index 2c8345c1d411..0418543f83fd 100644 --- a/llvm/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h +++ b/llvm/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h @@ -1777,37 +1777,6 @@ static bool DisassembleThumb2PreLoad(MCInst &MI, unsigned Opcode, uint32_t insn, return true; } -// 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.3.10 Store single data item // A6.3.9 Load byte, memory hints // A6.3.8 Load halfword, memory hints @@ -1843,10 +1812,6 @@ 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; diff --git a/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index 42f94ee5e348..4f401b9a8f5c 100644 --- a/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -560,6 +560,9 @@ 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/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp b/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp index a44ac07cd67d..68a781c18078 100644 --- a/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp +++ b/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp @@ -236,7 +236,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::t2LDMDB_UPD || Opc == ARM::t2LDRi12); 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) { @@ -270,10 +270,12 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI, return false; unsigned Scale = 1; + bool HasBaseReg = true; bool HasImmOffset = false; bool HasShift = false; bool HasOffReg = true; bool isLdStMul = false; + bool InsertImmOffset = true; unsigned Opc = Entry.NarrowOpc1; unsigned OpNum = 3; // First 'rest' of operands. uint8_t ImmLimit = Entry.Imm1Limit; @@ -290,17 +292,50 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI, HasOffReg = false; } Scale = 4; - HasImmOffset = true; + if (MI->getOperand(2).isImm()) + HasImmOffset = true; + else { + if (Entry.WideOpc == ARM::t2LDRi12) { + Opc = ARM::tLDRpci; + OpNum = 2; + } + HasImmOffset = false; + InsertImmOffset = false; + HasBaseReg = false; + HasOffReg = false; + } break; } case ARM::t2LDRBi12: case ARM::t2STRBi12: - HasImmOffset = true; + if (MI->getOperand(2).isImm()) + HasImmOffset = true; + else { + if (Entry.WideOpc == ARM::t2LDRBi12) { + Opc = ARM::tLDRpci; + OpNum = 2; + } + HasImmOffset = false; + InsertImmOffset = false; + HasBaseReg = false; + HasOffReg = false; + } break; case ARM::t2LDRHi12: case ARM::t2STRHi12: Scale = 2; - HasImmOffset = true; + if (MI->getOperand(2).isImm()) + HasImmOffset = true; + else { + if (Entry.WideOpc == ARM::t2LDRHi12) { + Opc = ARM::tLDRpci; + OpNum = 2; + } + HasImmOffset = false; + InsertImmOffset = false; + HasBaseReg = false; + HasOffReg = false; + } break; case ARM::t2LDRs: case ARM::t2LDRBs: @@ -388,8 +423,9 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI, DebugLoc dl = MI->getDebugLoc(); MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, TII->get(Opc)); if (!isLdStMul) { - MIB.addOperand(MI->getOperand(0)).addOperand(MI->getOperand(1)); - if (Opc != ARM::tLDRSB && Opc != ARM::tLDRSH) { + MIB.addOperand(MI->getOperand(0)); + if (HasBaseReg) MIB.addOperand(MI->getOperand(1)); + if (InsertImmOffset && Opc != ARM::tLDRSB && Opc != ARM::tLDRSH) { // tLDRSB and tLDRSH do not have an immediate offset field. On the other // hand, it must have an offset register. // FIXME: Remove this special case. diff --git a/llvm/test/MC/Disassembler/ARM/thumb-tests.txt b/llvm/test/MC/Disassembler/ARM/thumb-tests.txt index 29c67e7a0350..2870d500cea5 100644 --- a/llvm/test/MC/Disassembler/ARM/thumb-tests.txt +++ b/llvm/test/MC/Disassembler/ARM/thumb-tests.txt @@ -27,7 +27,7 @@ # CHECK: ldmia r0!, {r1} 0x02 0xc8 -# CHECK: ldrb.w r8, #-24 +# CHECK: ldrb.w r8, [pc, #-24] 0x1f 0xf8 0x18 0x80 # CHECK: ldrd r0, r1, [r7, #64]!