diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp index f8f717e4d4a..934daba5523 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 e0aeb920af8..bd753d29abd 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 60b6b1b331f..c61c88f8cff 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -910,8 +910,23 @@ multiclass T2I_ld 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 94321ad57ac..6d7b48587d1 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -58,7 +58,7 @@ public: SmallVectorImpl &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 &Fixups) const; @@ -112,7 +112,7 @@ public: SmallVectorImpl &Fixups) const; uint32_t getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &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 4964c642424..78d73d3a272 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 0418543f83f..8a38507a5a6 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 941c69d14ea..4f03b8497b9 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 3d7bcb23f8e..cc8f61cd72a 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 2870d500cea..29c67e7a035 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]!