Refactor LEApcrelJT as a pseudo-instructionlowered to a cannonical ADR
authorJim Grosbach <grosbach@apple.com>
Wed, 1 Dec 2010 19:47:31 +0000 (19:47 +0000)
committerJim Grosbach <grosbach@apple.com>
Wed, 1 Dec 2010 19:47:31 +0000 (19:47 +0000)
instruction at MC lowering. Add binary encoding information for the ADR,
including fixup data for the label operand.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120594 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMAsmPrinter.cpp
lib/Target/ARM/ARMCodeEmitter.cpp
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/ARMMCCodeEmitter.cpp
utils/TableGen/EDEmitter.cpp

index 51d576ccee1b780781ed6c4fb0f072288ecd7af2..de6e068b5099ebf13717f497a7e9beea44084fd4 100644 (file)
@@ -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);
index ab554f3916de3c8db3620565cac41e5d18f9ab5e..797bedd2c64b01568b84b7b2a2ba473d68cdb504 100644 (file)
@@ -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)
index 9b291dfdb4ccc07124af4c45065de45b05a21fc8..a78cf7e82e4b36c9b452b5fecf2b8b7d2b6aaacb 100644 (file)
@@ -338,6 +338,11 @@ def pclabel : Operand<i32> {
   let PrintMethod = "printPCLabel";
 }
 
+// ADR instruction labels.
+def adrlabel : Operand<i32> {
+  let EncoderMethod = "getAdrLabelOpValue";
+}
+
 def neon_vcvt_imm32 : Operand<i32> {
   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.
index 207332fba729081a2423a14df90e5a33bff42815..d35a1c6fb33b782ab7b2714dcb328037a6361be8 100644 (file)
@@ -85,6 +85,11 @@ public:
   uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
                                   SmallVectorImpl<MCFixup> &Fixups) const;
 
+  /// getAdrLabelOpValue - Return encoding info for 12-bit immediate
+  /// ADR label target.
+  uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
+                              SmallVectorImpl<MCFixup> &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<MCFixup> &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,
index 61d4ccdda9e07cc81355164b269623d015bf7f13..f3056e05317c1e110615311777268adde35f3e4f 100644 (file)
@@ -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");