diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 51d576ccee1..de6e068b509 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -726,6 +726,21 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { } return; } + case ARM::LEApcrelJT: { + unsigned JTI = MI->getOperand(1).getIndex(); + unsigned Id = MI->getOperand(2).getImm(); + MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, Id); + const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(JTISymbol, OutContext); + MCInst TmpInst; + TmpInst.setOpcode(ARM::ADRadd); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + TmpInst.addOperand(MCOperand::CreateExpr(SymbolExpr)); + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + return; + } case ARM::MOVPCRX: { MCInst TmpInst; TmpInst.setOpcode(ARM::MOVr); diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index ab554f3916d..797bedd2c64 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -167,6 +167,8 @@ namespace { const { return 0; } unsigned NEONThumb2DupPostEncoder(const MachineInstr &MI,unsigned Val) const { return 0; } + unsigned getAdrLabelOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } unsigned getCCOutOpValue(const MachineInstr &MI, unsigned Op) diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 9b291dfdb4c..a78cf7e82e4 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -338,6 +338,11 @@ def pclabel : Operand { let PrintMethod = "printPCLabel"; } +// ADR instruction labels. +def adrlabel : Operand { + let EncoderMethod = "getAdrLabelOpValue"; +} + def neon_vcvt_imm32 : Operand { let EncoderMethod = "getNEONVcvtImm32OpValue"; } @@ -1178,28 +1183,39 @@ def PICSTRB : ARMPseudoInst<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p), // LEApcrel - Load a pc-relative address into a register without offending the // assembler. let neverHasSideEffects = 1, isReMaterializable = 1 in -// FIXME: We want one cannonical LEApcrel instruction and to express one or -// both of these as pseudo-instructions that get expanded to it. In particular, -// the cannonical "adr" pattern should take a single label operand, and the -// JT version should be a pseudo that when lowered to MC, xforms the insn -// to the canonical form referencing the correct symbol. -def LEApcrel : AXI1<0, (outs GPR:$Rd), (ins i32imm:$label, pred:$p), - MiscFrm, IIC_iALUi, - "adr${p}\t$Rd, #$label", []>; - -def LEApcrelJT : AXI1<0b0100, (outs GPR:$Rd), - (ins i32imm:$label, nohash_imm:$id, pred:$p), - MiscFrm, IIC_iALUi, - "adr${p}\t$Rd, #${label}_${id}", []> { - bits<4> p; +// The 'adr' mnemonic encodes differently if the label is before or after +// the instruction. +def ADRadd : AI1<0b0100, (outs GPR:$Rd), (ins adrlabel:$label), + MiscFrm, IIC_iALUi, "adr", "\t$Rd, #$label", []> { bits<4> Rd; - let Inst{31-28} = p; + bits<12> label; let Inst{27-25} = 0b001; let Inst{20} = 0; let Inst{19-16} = 0b1111; let Inst{15-12} = Rd; - // FIXME: Add label encoding/fixup + let Inst{11-0} = label; } +def ADRsub : AI1<0b0010, (outs GPR:$Rd), (ins adrlabel:$label), + MiscFrm, IIC_iALUi, "adr", "\t$Rd, #$label", []> { + bits<4> Rd; + bits<12> label; + let Inst{27-25} = 0b001; + let Inst{20} = 0; + let Inst{19-16} = 0b1111; + let Inst{15-12} = Rd; + let Inst{11-0} = label; +} + +// FIXME: This should be a pseudo lowered to one of the above at MC lowering +// time. It may be interesting determining which of the two. Perhaps a fixup +// will be needed to do so? That would be kinda fugly. +def LEApcrel : AXI1<0, (outs GPR:$Rd), (ins i32imm:$label, pred:$p), + MiscFrm, IIC_iALUi, + "adr${p}\t$Rd, #$label", []>; + +def LEApcrelJT : ARMPseudoInst<(outs GPR:$Rd), + (ins i32imm:$label, nohash_imm:$id, pred:$p), + Size4Bytes, IIC_iALUi, []>; //===----------------------------------------------------------------------===// // Control Flow Instructions. diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index 207332fba72..d35a1c6fb33 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -85,6 +85,11 @@ public: uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups) const; + /// getAdrLabelOpValue - Return encoding info for 12-bit immediate + /// ADR label target. + uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups) const; + /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' /// operand. uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, @@ -395,6 +400,24 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, return 0; } +/// getAdrLabelOpValue - Return encoding info for 12-bit immediate +/// ADR label target. +uint32_t ARMMCCodeEmitter:: +getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups) const { + const MCOperand &MO = MI.getOperand(OpIdx); + + // If the destination is an immediate, we have nothing to do. + if (MO.isImm()) return MO.getImm(); + assert (MO.isExpr() && "Unexpected branch target type!"); + const MCExpr *Expr = MO.getExpr(); + MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_12); + Fixups.push_back(MCFixup::Create(0, Expr, Kind)); + + // All of the information is in the fixup. + return 0; +} + /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' operand. uint32_t ARMMCCodeEmitter:: getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index 61d4ccdda9e..f3056e05317 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -582,6 +582,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("jt2block_operand"); IMM("t_imm_s4"); IMM("pclabel"); + IMM("adrlabel"); IMM("shift_imm"); IMM("neon_vcvt_imm32");