[llvm-commits] [llvm] r118144 - in /llvm/trunk: lib/Target/ARM/ARMCodeEmitter.cpp lib/Target/ARM/ARMInstrInfo.td lib/Target/ARM/ARMInstrVFP.td lib/Target/ARM/ARMMCCodeEmitter.cpp lib/Target/ARM/AsmParser/ARMAsmParser.cpp lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp test/MC/ARM/simple-fp-encoding.s

Bill Wendling isanbard at gmail.com
Tue Nov 2 18:49:29 PDT 2010


Author: void
Date: Tue Nov  2 20:49:29 2010
New Revision: 118144

URL: http://llvm.org/viewvc/llvm-project?rev=118144&view=rev
Log:
The MC code couldn't handle ARM LDR instructions with negative offsets:

    vldr.64 d1, [r0, #-32]

The problem was with how the addressing mode 5 encodes the offsets. This change
makes sure that the way offsets are handled in addressing mode 5 is consistent
throughout the MC code. It involves re-refactoring the "getAddrModeImmOpValue"
method into an "Imm12" and "addressing mode 5" version. But not to worry! The
majority of the duplicated code has been unified.

Modified:
    llvm/trunk/lib/Target/ARM/ARMCodeEmitter.cpp
    llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    llvm/trunk/lib/Target/ARM/ARMInstrVFP.td
    llvm/trunk/lib/Target/ARM/ARMMCCodeEmitter.cpp
    llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
    llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
    llvm/trunk/test/MC/ARM/simple-fp-encoding.s

Modified: llvm/trunk/lib/Target/ARM/ARMCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMCodeEmitter.cpp?rev=118144&r1=118143&r2=118144&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMCodeEmitter.cpp Tue Nov  2 20:49:29 2010
@@ -177,25 +177,44 @@
       const { return 0; }
     unsigned getBitfieldInvertedMaskOpValue(const MachineInstr &MI,
                                             unsigned Op) const { return 0; }
-    uint32_t getAddrModeImmOpValue(const MachineInstr &MI, unsigned Op) const {
-      // {20-17} = reg
-      // {16}    = (U)nsigned (add == '1', sub == '0')
-      // {15-0}  = imm
+
+    unsigned getAddrModeImm12OpValue(const MachineInstr &MI, unsigned Op)
+      const {
+      // {17-13} = reg
+      // {12}    = (U)nsigned (add == '1', sub == '0')
+      // {11-0}  = imm12
       const MachineOperand &MO  = MI.getOperand(Op);
       const MachineOperand &MO1 = MI.getOperand(Op + 1);
       if (!MO.isReg()) {
         emitConstPoolAddress(MO.getIndex(), ARM::reloc_arm_cp_entry);
         return 0;
       }
-
       unsigned Reg = getARMRegisterNumbering(MO.getReg());
-      int32_t Imm = MO1.getImm();
+      int32_t Imm12 = MO1.getImm();
       uint32_t Binary;
-      Binary = Imm & 0xffff;
-      if (Imm >= 0)
-        Binary |= (1 << 16);
-
-      Binary |= (Reg << 17);
+      Binary = Imm12 & 0xfff;
+      if (Imm12 >= 0)
+        Binary |= (1 << 12);
+      Binary |= (Reg << 13);
+      return Binary;
+    }
+    uint32_t getAddrMode5OpValue(const MachineInstr &MI, unsigned Op) const {
+      // {12-9}  = reg
+      // {8}     = (U)nsigned (add == '1', sub == '0')
+      // {7-0}   = imm12
+      const MachineOperand &MO  = MI.getOperand(Op);
+      const MachineOperand &MO1 = MI.getOperand(Op + 1);
+      if (!MO.isReg()) {
+        emitConstPoolAddress(MO.getIndex(), ARM::reloc_arm_cp_entry);
+        return 0;
+      }
+      unsigned Reg = getARMRegisterNumbering(MO.getReg());
+      int32_t Imm8 = MO1.getImm();
+      uint32_t Binary;
+      Binary = Imm8 & 0xff;
+      if (Imm8 >= 0)
+        Binary |= (1 << 8);
+      Binary |= (Reg << 9);
       return Binary;
     }
     unsigned getNEONVcvtImm32OpValue(const MachineInstr &MI, unsigned Op)

Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=118144&r1=118143&r2=118144&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue Nov  2 20:49:29 2010
@@ -398,7 +398,7 @@
   // #0 and #-0 differently. We flag #-0 as the magic value INT32_MIN. All other
   // immediate values are as normal.
 
-  string EncoderMethod = "getAddrModeImmOpValue";
+  string EncoderMethod = "getAddrModeImm12OpValue";
   let PrintMethod = "printAddrModeImm12Operand";
   let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
 }
@@ -462,7 +462,7 @@
   let PrintMethod = "printAddrMode5Operand";
   let MIOperandInfo = (ops GPR:$base, i32imm);
   let ParserMatchClass = ARMMemMode5AsmOperand;
-  string EncoderMethod = "getAddrModeImmOpValue";
+  string EncoderMethod = "getAddrMode5OpValue";
 }
 
 // addrmode6 := reg with optional writeback
@@ -828,20 +828,20 @@
   def i12 : AIldst1<0b010, opc22, 1, (outs GPR:$Rt), (ins addrmode_imm12:$addr),
                    AddrMode_i12, LdFrm, iii, opc, "\t$Rt, $addr",
                   [(set GPR:$Rt, (opnode addrmode_imm12:$addr))]> {
-    bits<4> Rt;
-    bits<32> addr;
-    let Inst{23}    = addr{16};     // U (add = ('U' == 1))
-    let Inst{19-16} = addr{20-17};  // Rn
+    bits<4>  Rt;
+    bits<17> addr;
+    let Inst{23}    = addr{12};     // U (add = ('U' == 1))
+    let Inst{19-16} = addr{16-13};  // Rn
     let Inst{15-12} = Rt;
     let Inst{11-0}  = addr{11-0};   // imm12
   }
   def rs : AIldst1<0b011, opc22, 1, (outs GPR:$Rt), (ins ldst_so_reg:$shift),
                   AddrModeNone, LdFrm, iir, opc, "\t$Rt, $shift",
                  [(set GPR:$Rt, (opnode ldst_so_reg:$shift))]> {
-    bits<4> Rt;
-    bits<32> shift;
-    let Inst{23}    = shift{16};    // U (add = ('U' == 1))
-    let Inst{19-16} = shift{20-17}; // Rn
+    bits<4>  Rt;
+    bits<17> shift;
+    let Inst{23}    = shift{12};    // U (add = ('U' == 1))
+    let Inst{19-16} = shift{16-13}; // Rn
     let Inst{11-0}  = shift{11-0};
   }
 }

Modified: llvm/trunk/lib/Target/ARM/ARMInstrVFP.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrVFP.td?rev=118144&r1=118143&r2=118144&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrVFP.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrVFP.td Tue Nov  2 20:49:29 2010
@@ -51,25 +51,38 @@
 //
 
 let canFoldAsLoad = 1, isReMaterializable = 1 in {
+
 def VLDRD : ADI5<0b1101, 0b01, (outs DPR:$Dd), (ins addrmode5:$addr),
                  IIC_fpLoad64, "vldr", ".64\t$Dd, $addr",
                  [(set DPR:$Dd, (f64 (load addrmode5:$addr)))]> {
   // Instruction operands.
-  bits<5> Dd;
-  bits<32> addr;
+  bits<5>  Dd;
+  bits<13> addr;
 
   // Encode instruction operands.
-  let Inst{23}    = addr{16};     // U (add = (U == '1'))
+  let Inst{23}    = addr{8};      // U (add = (U == '1'))
   let Inst{22}    = Dd{4};
-  let Inst{19-16} = addr{20-17};  // Rn
+  let Inst{19-16} = addr{12-9};   // Rn
   let Inst{15-12} = Dd{3-0};
   let Inst{7-0}   = addr{7-0};    // imm8
 }
 
-def VLDRS : ASI5<0b1101, 0b01, (outs SPR:$dst), (ins addrmode5:$addr),
-                 IIC_fpLoad32, "vldr", ".32\t$dst, $addr",
-                 [(set SPR:$dst, (load addrmode5:$addr))]>;
-} // canFoldAsLoad
+def VLDRS : ASI5<0b1101, 0b01, (outs SPR:$Sd), (ins addrmode5:$addr),
+                 IIC_fpLoad32, "vldr", ".32\t$Sd, $addr",
+                 [(set SPR:$Sd, (load addrmode5:$addr))]> {
+  // Instruction operands.
+  bits<5>  Sd;
+  bits<13> addr;
+
+  // Encode instruction operands.
+  let Inst{23}    = addr{8};      // U (add = (U == '1'))
+  let Inst{22}    = Sd{0};
+  let Inst{19-16} = addr{12-9};   // Rn
+  let Inst{15-12} = Sd{4-1};
+  let Inst{7-0}   = addr{7-0};    // imm8
+}
+
+} // End of 'let canFoldAsLoad = 1, isReMaterializable = 1 in'
 
 def VSTRD : ADI5<0b1101, 0b00, (outs), (ins DPR:$src, addrmode5:$addr),
                  IIC_fpStore64, "vstr", ".64\t$src, $addr",

Modified: llvm/trunk/lib/Target/ARM/ARMMCCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMMCCodeEmitter.cpp?rev=118144&r1=118143&r2=118144&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMMCCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMMCCodeEmitter.cpp Tue Nov  2 20:49:29 2010
@@ -49,8 +49,15 @@
   /// operand requires relocation, record the relocation and return zero.
   unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO) const;
 
-  /// getAddrModeImmOpValue - Return encoding info for 'reg +/- imm' operand.
-  uint32_t getAddrModeImmOpValue(const MCInst &MI, unsigned Op) const;
+  bool EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx,
+                              unsigned &Reg, unsigned &Imm) const;
+
+  /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
+  /// operand.
+  uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx) const;
+
+  /// getAddrMode5OpValue - Return encoding info for 'reg +/- imm8' operand.
+  uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx) const;
 
   /// getCCOutOpValue - Return encoding of the 's' bit.
   unsigned getCCOutOpValue(const MCInst &MI, unsigned Op) const {
@@ -170,37 +177,76 @@
 }
 
 /// getAddrModeImmOpValue - Return encoding info for 'reg +/- imm' operand.
-uint32_t ARMMCCodeEmitter::getAddrModeImmOpValue(const MCInst &MI,
-                                                 unsigned OpIdx) const {
-  // {20-17} = reg
-  // {16}    = (U)nsigned (add == '1', sub == '0')
-  // {15-0}  = imm
+bool ARMMCCodeEmitter::EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx,
+                                              unsigned &Reg,
+                                              unsigned &Imm) const {
   const MCOperand &MO  = MI.getOperand(OpIdx);
   const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
-  uint32_t Binary = 0;
 
   // If The first operand isn't a register, we have a label reference.
   if (!MO.isReg()) {
-    Binary |= ARM::PC << 17;     // Rn is PC.
+    Reg = ARM::PC;              // Rn is PC.
+    Imm = 0;
     // FIXME: Add a fixup referencing the label.
-    return Binary;
+    return true;
   }
 
-  unsigned Reg = getARMRegisterNumbering(MO.getReg());
-  int32_t Imm = MO1.getImm();
-  bool isAdd = Imm >= 0;
+  Reg = getARMRegisterNumbering(MO.getReg());
+
+  int32_t SImm = MO1.getImm();
+  bool isAdd = true;
 
   // Special value for #-0
-  if (Imm == INT32_MIN)
-    Imm = 0;
+  if (SImm == INT32_MIN)
+    SImm = 0;
 
   // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
-  if (Imm < 0) Imm = -Imm;
+  if (SImm < 0) {
+    SImm = -SImm;
+    isAdd = false;
+  }
+
+  Imm = SImm;
+  return isAdd;
+}
 
-  Binary = Imm & 0xffff;
+/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' operand.
+uint32_t ARMMCCodeEmitter::getAddrModeImm12OpValue(const MCInst &MI,
+                                                   unsigned OpIdx) const {
+  // {17-13} = reg
+  // {12}    = (U)nsigned (add == '1', sub == '0')
+  // {11-0}  = imm12
+  unsigned Reg, Imm12;
+  bool isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm12);
+
+  if (Reg == ARM::PC)
+    return ARM::PC << 13;       // Rn is PC;
+
+  uint32_t Binary = Imm12 & 0xfff;
+  // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
   if (isAdd)
-    Binary |= (1 << 16);
-  Binary |= (Reg << 17);
+    Binary |= (1 << 12);
+  Binary |= (Reg << 13);
+  return Binary;
+}
+
+/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm12' operand.
+uint32_t ARMMCCodeEmitter::getAddrMode5OpValue(const MCInst &MI,
+                                               unsigned OpIdx) const {
+  // {12-9} = reg
+  // {8}    = (U)nsigned (add == '1', sub == '0')
+  // {7-0}  = imm8
+  unsigned Reg, Imm8;
+  EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8);
+
+  if (Reg == ARM::PC)
+    return ARM::PC << 13;       // Rn is PC;
+
+  uint32_t Binary = ARM_AM::getAM5Offset(Imm8);
+  // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
+  if (ARM_AM::getAM5Op(Imm8) == ARM_AM::add)
+    Binary |= (1 << 8);
+  Binary |= (Reg << 9);
   return Binary;
 }
 

Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=118144&r1=118143&r2=118144&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Tue Nov  2 20:49:29 2010
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "ARM.h"
+#include "ARMAddressingModes.h"
 #include "ARMSubtarget.h"
 #include "llvm/MC/MCParser/MCAsmLexer.h"
 #include "llvm/MC/MCParser/MCAsmParser.h"
@@ -260,16 +261,25 @@
 
     Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
     assert(!Mem.OffsetIsReg && "invalid mode 5 operand");
+
     // FIXME: #-0 is encoded differently than #0. Does the parser preserve
     // the difference?
     if (Mem.Offset) {
       const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
-      assert(CE && "non-constant mode 5 offset operand!");
+      assert(CE && "Non-constant mode 5 offset operand!");
+
       // The MCInst offset operand doesn't include the low two bits (like
       // the instruction encoding).
-      Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
-    } else
+      int64_t Offset = CE->getValue() / 4;
+      if (Offset >= 0)
+        Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::add,
+                                                               Offset)));
+      else
+        Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::sub,
+                                                               -Offset)));
+    } else {
       Inst.addOperand(MCOperand::CreateImm(0));
+    }
   }
 
   virtual void dump(raw_ostream &OS) const;

Modified: llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp?rev=118144&r1=118143&r2=118144&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp Tue Nov  2 20:49:29 2010
@@ -310,7 +310,7 @@
   if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
     O << ", #"
       << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
-      << ImmOffs*4;
+      << ImmOffs * 4;
   }
   O << "]";
 }

Modified: llvm/trunk/test/MC/ARM/simple-fp-encoding.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/simple-fp-encoding.s?rev=118144&r1=118143&r2=118144&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/simple-fp-encoding.s (original)
+++ llvm/trunk/test/MC/ARM/simple-fp-encoding.s Tue Nov  2 20:49:29 2010
@@ -162,8 +162,9 @@
         vldr.64	d17, [r0]
 
 @ CHECK: vldr.64 d1, [r2, #32]       @ encoding: [0x08,0x1b,0x92,0xed]
+@ CHECK: vldr.64 d1, [r2, #-32]      @ encoding: [0x08,0x1b,0x12,0xed]
         vldr.64	d1, [r2, #32]
-
+        vldr.64	d1, [r2, #-32]
         
 @ CHECK: vldr.64 d2, [r3]            @ encoding: [0x00,0x2b,0x93,0xed]
         vldr.64 d2, [r3]
@@ -174,3 +175,21 @@
         vldr.64 d3, [pc]
         vldr.64 d3, [pc,#0]
         vldr.64 d3, [pc,#-0]
+
+@ CHECK: vldr.32 s13, [r0]           @ encoding: [0x00,0x6a,0xd0,0xed]
+        vldr.32	s13, [r0]
+
+@ CHECK: vldr.32 s1, [r2, #32]       @ encoding: [0x08,0x0a,0xd2,0xed]
+@ CHECK: vldr.32 s1, [r2, #-32]      @ encoding: [0x08,0x0a,0x52,0xed]
+        vldr.32	s1, [r2, #32]
+        vldr.32	s1, [r2, #-32]
+        
+@ CHECK: vldr.32 s2, [r3]            @ encoding: [0x00,0x1a,0x93,0xed]
+        vldr.32 s2, [r3]
+
+@ CHECK: vldr.32 s5, [pc]            @ encoding: [0x00,0x2a,0xdf,0xed]
+@ CHECK: vldr.32 s5, [pc]            @ encoding: [0x00,0x2a,0xdf,0xed]
+@ CHECK: vldr.32 s5, [pc]            @ encoding: [0x00,0x2a,0xdf,0xed]
+        vldr.32 s5, [pc]
+        vldr.32 s5, [pc,#0]
+        vldr.32 s5, [pc,#-0]





More information about the llvm-commits mailing list