<div class="gmail_quote">On 30 March 2011 16:32, Bruno Cardoso Lopes <span dir="ltr"><<a href="mailto:bruno.cardoso@gmail.com">bruno.cardoso@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

Author: bruno<br>
Date: Wed Mar 30 18:32:32 2011<br>
New Revision: 128585<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=128585&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=128585&view=rev</a><br>
Log:<br>
- Implement asm parsing support for LDRT, LDRBT, STRT, STRBT and<br>
  {STR,LDC}{2}_PRE.<br>
- Fixed the encoding in some places.<br>
- Some of those instructions were using am2offset and now use addrmode2.<br>
Codegen isn't affected, instructions which use SelectAddrMode2Offset were not<br>
touched.<br>
- Teach printAddrMode2Operand to check by the addressing mode which index<br>
mode to print.<br>
- This is a work in progress, more work to come. The idea is to change places<br>
which use am2offset to use addrmode2 instead, as to unify assembly parser.<br>
- Add testcases for assembly parser<br>
<br>
Added:<br>
    llvm/trunk/test/MC/ARM/arm_addrmode2.s<br>
Modified:<br>
    llvm/trunk/lib/Target/ARM/ARMBaseInfo.h<br>
    llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h<br>
    llvm/trunk/lib/Target/ARM/ARMInstrFormats.td<br>
    llvm/trunk/lib/Target/ARM/ARMInstrInfo.td<br>
    llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp<br>
    llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp<br>
    llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h<br>
<br>
Modified: llvm/trunk/lib/Target/ARM/ARMBaseInfo.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInfo.h?rev=128585&r1=128584&r2=128585&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInfo.h?rev=128585&r1=128584&r2=128585&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Target/ARM/ARMBaseInfo.h (original)<br>
+++ llvm/trunk/lib/Target/ARM/ARMBaseInfo.h Wed Mar 30 18:32:32 2011<br>
@@ -200,6 +200,51 @@<br>
 }<br>
<br>
 namespace ARMII {<br>
+<br>
+  /// ARM Addressing Modes<br>
+  enum AddrMode {<br>
+    AddrModeNone    = 0,<br>
+    AddrMode1       = 1,<br>
+    AddrMode2       = 2,<br>
+    AddrMode3       = 3,<br>
+    AddrMode4       = 4,<br>
+    AddrMode5       = 5,<br>
+    AddrMode6       = 6,<br>
+    AddrModeT1_1    = 7,<br>
+    AddrModeT1_2    = 8,<br>
+    AddrModeT1_4    = 9,<br>
+    AddrModeT1_s    = 10, // i8 * 4 for pc and sp relative data<br>
+    AddrModeT2_i12  = 11,<br>
+    AddrModeT2_i8   = 12,<br>
+    AddrModeT2_so   = 13,<br>
+    AddrModeT2_pc   = 14, // +/- i12 for pc relative data<br>
+    AddrModeT2_i8s4 = 15, // i8 * 4<br>
+    AddrMode_i12    = 16<br>
+  };<br>
+<br>
+  inline static const char *AddrModeToString(AddrMode addrmode) {<br>
+    switch (addrmode) {<br>
+    default: llvm_unreachable("Unknown memory operation");<br>
+    case AddrModeNone:    return "AddrModeNone";<br>
+    case AddrMode1:       return "AddrMode1";<br>
+    case AddrMode2:       return "AddrMode2";<br>
+    case AddrMode3:       return "AddrMode3";<br>
+    case AddrMode4:       return "AddrMode4";<br>
+    case AddrMode5:       return "AddrMode5";<br>
+    case AddrMode6:       return "AddrMode6";<br>
+    case AddrModeT1_1:    return "AddrModeT1_1";<br>
+    case AddrModeT1_2:    return "AddrModeT1_2";<br>
+    case AddrModeT1_4:    return "AddrModeT1_4";<br>
+    case AddrModeT1_s:    return "AddrModeT1_s";<br>
+    case AddrModeT2_i12:  return "AddrModeT2_i12";<br>
+    case AddrModeT2_i8:   return "AddrModeT2_i8";<br>
+    case AddrModeT2_so:   return "AddrModeT2_so";<br>
+    case AddrModeT2_pc:   return "AddrModeT2_pc";<br>
+    case AddrModeT2_i8s4: return "AddrModeT2_i8s4";<br>
+    case AddrMode_i12:    return "AddrMode_i12";<br>
+    }<br>
+  }<br>
+<br>
   /// Target Operand Flag enum.<br>
   enum TOF {<br>
     //===------------------------------------------------------------------===//<br>
<br>
Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h?rev=128585&r1=128584&r2=128585&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h?rev=128585&r1=128584&r2=128585&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h (original)<br>
+++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h Wed Mar 30 18:32:32 2011<br>
@@ -34,25 +34,7 @@<br>
<br>
     //===------------------------------------------------------------------===//<br>
     // This four-bit field describes the addressing mode used.<br>
-<br>
-    AddrModeMask  = 0x1f,<br>
-    AddrModeNone    = 0,<br>
-    AddrMode1       = 1,<br>
-    AddrMode2       = 2,<br>
-    AddrMode3       = 3,<br>
-    AddrMode4       = 4,<br>
-    AddrMode5       = 5,<br>
-    AddrMode6       = 6,<br>
-    AddrModeT1_1    = 7,<br>
-    AddrModeT1_2    = 8,<br>
-    AddrModeT1_4    = 9,<br>
-    AddrModeT1_s    = 10, // i8 * 4 for pc and sp relative data<br>
-    AddrModeT2_i12  = 11,<br>
-    AddrModeT2_i8   = 12,<br>
-    AddrModeT2_so   = 13,<br>
-    AddrModeT2_pc   = 14, // +/- i12 for pc relative data<br>
-    AddrModeT2_i8s4 = 15, // i8 * 4<br>
-    AddrMode_i12    = 16,<br>
+    AddrModeMask  = 0x1f, // The AddrMode enums are declared in ARMBaseInfo.h<br>
<br>
     // Size* - Flags to keep track of the size of an instruction.<br>
     SizeShift     = 5,<br>
<br>
Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=128585&r1=128584&r2=128585&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=128585&r1=128584&r2=128585&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td (original)<br>
+++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td Wed Mar 30 18:32:32 2011<br>
@@ -515,15 +515,15 @@<br>
   : AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr,<br>
                pattern> {<br>
   // AM2 store w/ two operands: (GPR, am2offset)<br>
+  // {17-14}  Rn<br>
   // {13}     1 == Rm, 0 == imm12<br>
   // {12}     isAdd<br>
   // {11-0}   imm12/Rm<br>
-  bits<14> offset;<br>
-  bits<4> Rn;<br>
-  let Inst{25} = offset{13};<br>
-  let Inst{23} = offset{12};<br>
-  let Inst{19-16} = Rn;<br>
-  let Inst{11-0} = offset{11-0};<br>
+  bits<18> addr;<br>
+  let Inst{25} = addr{13};<br>
+  let Inst{23} = addr{12};<br>
+  let Inst{19-16} = addr{17-14};<br>
+  let Inst{11-0} = addr{11-0};<br>
 }<br>
<br>
 // addrmode3 instructions<br>
<br>
Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=128585&r1=128584&r2=128585&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=128585&r1=128584&r2=128585&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)<br>
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Wed Mar 30 18:32:32 2011<br>
@@ -498,6 +498,12 @@<br>
   let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);<br>
 }<br>
<br>
+def MemMode2AsmOperand : AsmOperandClass {<br>
+  let Name = "MemMode2";<br>
+  let SuperClasses = [];<br>
+  let ParserMethod = "tryParseMemMode2Operand";<br>
+}<br>
+<br>
 // addrmode2 := reg +/- imm12<br>
 //           := reg +/- reg shop imm<br>
 //<br>
@@ -505,6 +511,7 @@<br>
                 ComplexPattern<i32, 3, "SelectAddrMode2", []> {<br>
   let EncoderMethod = "getAddrMode2OpValue";<br>
   let PrintMethod = "printAddrMode2Operand";<br>
+  let ParserMatchClass = MemMode2AsmOperand;<br>
   let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);<br>
 }<br>
<br>
@@ -1656,6 +1663,7 @@<br>
     let Inst{23} = addr{12};<br>
     let Inst{19-16} = addr{17-14};<br>
     let Inst{11-0} = addr{11-0};<br>
+    let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";<br>
   }<br>
   def _POST : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),<br>
                       (ins GPR:$Rn, am2offset:$offset),<br>
@@ -1714,17 +1722,35 @@<br>
<br>
 // LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT are for disassembly only.<br>
 let mayLoad = 1, neverHasSideEffects = 1 in {<br>
-def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$dst, GPR:$base_wb),<br>
-                   (ins GPR:$base, am2offset:$offset), IndexModePost,<br>
-                   LdFrm, IIC_iLoad_ru,<br>
-                   "ldrt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {<br>
+def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb),<br>
+                   (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_ru,<br>
+                   "ldrt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {<br>
+  // {17-14}  Rn<br>
+  // {13}     1 == Rm, 0 == imm12<br>
+  // {12}     isAdd<br>
+  // {11-0}   imm12/Rm<br>
+  bits<18> addr;<br>
+  let Inst{25} = addr{13};<br>
+  let Inst{23} = addr{12};<br>
   let Inst{21} = 1; // overwrite<br>
-}<br>
-def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$dst, GPR:$base_wb),<br>
-                  (ins GPR:$base, am2offset:$offset), IndexModePost,<br>
-                  LdFrm, IIC_iLoad_bh_ru,<br>
-                  "ldrbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {<br>
+  let Inst{19-16} = addr{17-14};<br>
+  let Inst{11-0} = addr{11-0};<br>
+  let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";<br>
+}<br>
+def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),<br>
+                  (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_bh_ru,<br>
+                  "ldrbt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {<br>
+  // {17-14}  Rn<br>
+  // {13}     1 == Rm, 0 == imm12<br>
+  // {12}     isAdd<br>
+  // {11-0}   imm12/Rm<br>
+  bits<18> addr;<br>
+  let Inst{25} = addr{13};<br>
+  let Inst{23} = addr{12};<br>
   let Inst{21} = 1; // overwrite<br>
+  let Inst{19-16} = addr{17-14};<br>
+  let Inst{11-0} = addr{11-0};<br>
+  let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";<br>
 }<br>
 def LDRSBT : AI3ldstidx<0b1101, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb),<br>
                  (ins GPR:$base, am3offset:$offset), IndexModePost,<br>
@@ -1818,20 +1844,20 @@<br>
<br>
 // STRT, STRBT, and STRHT are for disassembly only.<br>
<br>
-def STRT : AI2stridx<0, 0, (outs GPR:$Rn_wb),<br>
-                    (ins GPR:$Rt, GPR:$Rn,am2offset:$offset),<br>
+def STRT : AI2stridx<0, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr),<br>
                     IndexModePost, StFrm, IIC_iStore_ru,<br>
-                    "strt", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb",<br>
+                    "strt", "\t$Rt, $addr", "$addr.base = $Rn_wb",<br>
                     [/* For disassembly only; pattern left blank */]> {<br>
   let Inst{21} = 1; // overwrite<br>
+  let AsmMatchConverter = "CvtStWriteBackRegAddrMode2";<br>
 }<br>
<br>
-def STRBT : AI2stridx<1, 0, (outs GPR:$Rn_wb),<br>
-                     (ins GPR:$Rt, GPR:$Rn, am2offset:$offset),<br>
+def STRBT : AI2stridx<1, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr),<br>
                      IndexModePost, StFrm, IIC_iStore_bh_ru,<br>
-                     "strbt", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb",<br>
+                     "strbt", "\t$Rt, $addr", "$addr.base = $Rn_wb",<br>
                      [/* For disassembly only; pattern left blank */]> {<br>
   let Inst{21} = 1; // overwrite<br>
+  let AsmMatchConverter = "CvtStWriteBackRegAddrMode2";<br>
 }<br>
<br>
 def STRHT: AI3sthpo<(outs GPR:$base_wb),<br>
@@ -3391,8 +3417,9 @@<br>
   let Inst{23-20} = opc1;<br>
 }<br>
<br>
-class ACI<dag oops, dag iops, string opc, string asm><br>
-  : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, BrFrm, NoItinerary,<br>
+class ACI<dag oops, dag iops, string opc, string asm,<br>
+          IndexMode im = IndexModeNone><br>
+  : I<oops, iops, AddrModeNone, Size4Bytes, im, BrFrm, NoItinerary,<br>
       opc, asm, "", [/* For disassembly only; pattern left blank */]> {<br>
   let Inst{27-25} = 0b110;<br>
 }<br>
@@ -3411,7 +3438,7 @@<br>
<br>
   def _PRE : ACI<(outs),<br>
       (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),<br>
-      opc, "\tp$cop, cr$CRd, $addr!"> {<br>
+      opc, "\tp$cop, cr$CRd, $addr!", IndexModePre> {<br>
     let Inst{31-28} = op31_28;<br>
     let Inst{24} = 1; // P = 1<br>
     let Inst{21} = 1; // W = 1<br>
@@ -3452,7 +3479,7 @@<br>
<br>
   def L_PRE : ACI<(outs),<br>
       (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),<br>
-      !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr!"> {<br>
+      !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr!", IndexModePre> {<br>
     let Inst{31-28} = op31_28;<br>
     let Inst{24} = 1; // P = 1<br>
     let Inst{21} = 1; // W = 1<br>
<br>
Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=128585&r1=128584&r2=128585&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=128585&r1=128584&r2=128585&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)<br>
+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Wed Mar 30 18:32:32 2011<br>
@@ -48,7 +48,8 @@<br>
   bool TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);<br>
   bool TryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);<br>
   bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);<br>
-  bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);<br>
+  bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &,<br>
+                   ARMII::AddrMode AddrMode);<br>
   bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);<br>
   bool ParsePrefix(ARMMCExpr::VariantKind &RefKind);<br>
   const MCExpr *ApplyPrefixToExpr(const MCExpr *E,<br>
@@ -95,6 +96,14 @@<br>
     SmallVectorImpl<MCParsedAsmOperand*>&);<br>
   OperandMatchResultTy tryParseMSRMaskOperand(<br>
     SmallVectorImpl<MCParsedAsmOperand*>&);<br>
+  OperandMatchResultTy tryParseMemMode2Operand(<br>
+    SmallVectorImpl<MCParsedAsmOperand*>&);<br>
+<br>
+  // Asm Match Converter Methods<br>
+  bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,<br>
+                                  const SmallVectorImpl<MCParsedAsmOperand*> &);<br>
+  bool CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,<br>
+                                  const SmallVectorImpl<MCParsedAsmOperand*> &);<br>
<br>
 public:<br>
   ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)<br>
@@ -172,6 +181,7 @@<br>
<br>
     /// Combined record for all forms of ARM address expressions.<br>
     struct {<br>
+      ARMII::AddrMode AddrMode;<br>
       unsigned BaseRegNum;<br>
       union {<br>
         unsigned RegNum;     ///< Offset register num, when OffsetIsReg.<br>
@@ -293,7 +303,9 @@<br>
<br>
   /// @name Memory Operand Accessors<br>
   /// @{<br>
-<br>
+  ARMII::AddrMode getMemAddrMode() const {<br>
+    return Mem.AddrMode;<br>
+  }<br>
   unsigned getMemBaseRegNum() const {<br>
     return Mem.BaseRegNum;<br>
   }<br>
@@ -338,6 +350,27 @@<br>
   bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; }<br>
   bool isMemory() const { return Kind == Memory; }<br>
   bool isShifter() const { return Kind == Shifter; }<br>
+  bool isMemMode2() const {<br>
+    if (getMemAddrMode() != ARMII::AddrMode2)<br>
+      return false;<br>
+<br>
+    if (getMemOffsetIsReg())<br>
+      return true;<br>
+<br>
+    if (getMemNegative() &&<br>
+        !(getMemPostindexed() || getMemPreindexed()))<br>
+      return false;<br>
+<br>
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());<br>
+    if (!CE) return false;<br>
+    int64_t Value = CE->getValue();<br>
+<br>
+    // The offset must be in the range 0-4095 (imm12).<br>
+    if (Value > 4095 || Value < -4095)<br>
+      return false;<br>
+<br>
+    return true;<br>
+  }<br>
   bool isMemMode5() const {<br>
     if (!isMemory() || getMemOffsetIsReg() || getMemWriteback() ||<br>
         getMemNegative())<br>
@@ -465,6 +498,46 @@<br>
            "No offset operand support in mode 7");<br>
   }<br>
<br>
+  void addMemMode2Operands(MCInst &Inst, unsigned N) const {<br>
+    assert(isMemMode2() && "Invalid mode or number of operands!");<br>
+    Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));<br>
+<br>
+    if (getMemOffsetIsReg()) {<br>
+      Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum()));<br>
+<br>
+      ARM_AM::AddrOpc AMOpc = getMemNegative() ? ARM_AM::sub : ARM_AM::add;<br>
+      ARM_AM::ShiftOpc ShOpc = ARM_AM::no_shift;<br>
+      int64_t ShiftAmount = 0;<br>
+<br>
+      if (getMemOffsetRegShifted()) {<br>
+        ShOpc = getMemShiftType();<br>
+        const MCConstantExpr *CE =<br>
+                   dyn_cast<MCConstantExpr>(getMemShiftAmount());<br>
+        ShiftAmount = CE->getValue();<br>
+      }<br>
+<br>
+      Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(AMOpc, ShiftAmount,<br>
+                                           ShOpc)));<br>
+      return;<br>
+    }<br>
+<br>
+    // Create a operand placeholder to always yield the same number of operands.<br>
+    Inst.addOperand(MCOperand::CreateReg(0));<br>
+<br>
+    // FIXME: #-0 is encoded differently than #0. Does the parser preserve<br>
+    // the difference?<br>
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());<br>
+    assert(CE && "Non-constant mode 2 offset operand!");<br>
+    int64_t Offset = CE->getValue();<br>
+<br>
+    if (Offset >= 0)<br>
+      Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::add,<br>
+                                           Offset, ARM_AM::no_shift)));<br>
+    else<br>
+      Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::sub,<br>
+                                           -Offset, ARM_AM::no_shift)));<br>
+  }<br>
+<br>
   void addMemMode5Operands(MCInst &Inst, unsigned N) const {<br>
     assert(N == 2 && isMemMode5() && "Invalid number of operands!");<br>
<br>
@@ -599,9 +672,9 @@<br>
     return Op;<br>
   }<br>
<br>
-  static ARMOperand *CreateMem(unsigned BaseRegNum, bool OffsetIsReg,<br>
-                               const MCExpr *Offset, int OffsetRegNum,<br>
-                               bool OffsetRegShifted,<br>
+  static ARMOperand *CreateMem(ARMII::AddrMode AddrMode, unsigned BaseRegNum,<br>
+                               bool OffsetIsReg, const MCExpr *Offset,<br>
+                               int OffsetRegNum, bool OffsetRegShifted,<br>
                                enum ARM_AM::ShiftOpc ShiftType,<br>
                                const MCExpr *ShiftAmount, bool Preindexed,<br>
                                bool Postindexed, bool Negative, bool Writeback,<br>
@@ -618,6 +691,7 @@<br>
            "Cannot have expression offset and register offset!");<br>
<br>
     ARMOperand *Op = new ARMOperand(Memory);<br>
+    Op->Mem.AddrMode = AddrMode;<br>
     Op->Mem.BaseRegNum = BaseRegNum;<br>
     Op->Mem.OffsetIsReg = OffsetIsReg;<br>
     if (OffsetIsReg)<br>
@@ -689,7 +763,8 @@<br>
     break;<br>
   case Memory:<br>
     OS << "<memory "<br>
-       << "base:" << getMemBaseRegNum();<br>
+       << "am:" << ARMII::AddrModeToString(getMemAddrMode())<br>
+       << " base:" << getMemBaseRegNum();<br>
     if (getMemOffsetIsReg()) {<br>
       OS << " offset:<register " << getMemOffsetRegNum();<br>
       if (getMemOffsetRegShifted()) {<br>
@@ -1132,13 +1207,57 @@<br>
   return MatchOperand_Success;<br>
 }<br>
<br>
+/// tryParseMemMode2Operand - Try to parse memory addressing mode 2 operand.<br>
+ARMAsmParser::OperandMatchResultTy ARMAsmParser::<br>
+tryParseMemMode2Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {<br>
+  SMLoc S = Parser.getTok().getLoc();<br>
+  const AsmToken &Tok = Parser.getTok();<br>
+  assert(Tok.is(AsmToken::LBrac) && "Token is not a \"[\"");<br>
+<br>
+  if (ParseMemory(Operands, ARMII::AddrMode2))<br>
+    return MatchOperand_NoMatch;<br>
+<br>
+  return MatchOperand_Success;<br>
+}<br>
+<br>
+/// CvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.<br>
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands<br>
+/// when they refer multiple MIOperands inside a single one.<br>
+bool ARMAsmParser::<br>
+CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,<br>
+                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {<br>
+  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);<br>
+<br>
+  // Create a writeback register dummy placeholder.<br>
+  Inst.addOperand(MCOperand::CreateImm(0));<br>
+<br>
+  ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3);<br>
+  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);<br>
+  return true;<br>
+}<br>
+<br>
+/// CvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.<br>
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands<br>
+/// when they refer multiple MIOperands inside a single one.<br>
+bool ARMAsmParser::<br>
+CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,<br>
+                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {<br>
+  // Create a writeback register dummy placeholder.<br>
+  Inst.addOperand(MCOperand::CreateImm(0));<br>
+  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);<br>
+  ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3);<br>
+  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);<br>
+  return true;<br>
+}<br>
+<br>
 /// Parse an ARM memory expression, return false if successful else return true<br>
 /// or an error.  The first token must be a '[' when called.<br>
 ///<br>
 /// TODO Only preindexing and postindexing addressing are started, unindexed<br>
 /// with option, etc are still to do.<br>
 bool ARMAsmParser::<br>
-ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {<br>
+ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands,<br>
+            ARMII::AddrMode AddrMode = ARMII::AddrModeNone) {<br>
   SMLoc S, E;<br>
   assert(Parser.getTok().is(AsmToken::LBrac) &&<br>
          "Token is not a Left Bracket");<br>
@@ -1231,11 +1350,10 @@<br>
       Offset = MCConstantExpr::Create(0, getContext());<br>
   }<br>
<br>
-  Operands.push_back(ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset,<br>
-                                           OffsetRegNum, OffsetRegShifted,<br>
-                                           ShiftType, ShiftAmount, Preindexed,<br>
-                                           Postindexed, Negative, Writeback,<br>
-                                           S, E));<br>
+  Operands.push_back(ARMOperand::CreateMem(AddrMode, BaseRegNum, OffsetIsReg,<br>
+                                     Offset, OffsetRegNum, OffsetRegShifted,<br>
+                                     ShiftType, ShiftAmount, Preindexed,<br>
+                                     Postindexed, Negative, Writeback, S, E));<br>
   if (WBOp)<br>
     Operands.push_back(WBOp);<br>
<br>
<br>
Modified: llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp?rev=128585&r1=128584&r2=128585&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp?rev=128585&r1=128584&r2=128585&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp (original)<br>
+++ llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp Wed Mar 30 18:32:32 2011<br>
@@ -14,6 +14,7 @@<br>
 #define DEBUG_TYPE "asm-printer"<br>
 #include "ARMBaseInfo.h"<br>
 #include "ARMInstPrinter.h"<br>
+#include "ARMInstrInfo.h"<br></blockquote><div><br></div><div>No, you can not do this. This will transitively #include ARMGenRegisterInfo.h.inc which declares "extern QQQQPRClass QQQQPRRegClass;". That causes ARMInstPrinter to have a dependency on ARMCodeGen, causing a cycle.</div>

<div><br></div><div>We'll probably revert this patch shortly. Please re-commit once you fix this!</div><div><br></div><div>Nick</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">


 #include "ARMAddressingModes.h"<br>
 #include "llvm/MC/MCInst.h"<br>
 #include "llvm/MC/MCAsmInfo.h"<br>
@@ -181,18 +182,12 @@<br>
   }<br>
 }<br>
<br>
-<br>
-void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,<br>
-                                           raw_ostream &O) {<br>
+void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,<br>
+                                                raw_ostream &O) {<br>
   const MCOperand &MO1 = MI->getOperand(Op);<br>
   const MCOperand &MO2 = MI->getOperand(Op+1);<br>
   const MCOperand &MO3 = MI->getOperand(Op+2);<br>
<br>
-  if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.<br>
-    printOperand(MI, Op, O);<br>
-    return;<br>
-  }<br>
-<br>
   O << "[" << getRegisterName(MO1.getReg());<br>
<br>
   if (!MO2.getReg()) {<br>
@@ -215,6 +210,52 @@<br>
   O << "]";<br>
 }<br>
<br>
+void ARMInstPrinter::printAM2PostIndexOp(const MCInst *MI, unsigned Op,<br>
+                                         raw_ostream &O) {<br>
+  const MCOperand &MO1 = MI->getOperand(Op);<br>
+  const MCOperand &MO2 = MI->getOperand(Op+1);<br>
+  const MCOperand &MO3 = MI->getOperand(Op+2);<br>
+<br>
+  O << "[" << getRegisterName(MO1.getReg()) << "], ";<br>
+<br>
+  if (!MO2.getReg()) {<br>
+    unsigned ImmOffs = ARM_AM::getAM2Offset(MO3.getImm());<br>
+    O << '#'<br>
+      << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))<br>
+      << ImmOffs;<br>
+    return;<br>
+  }<br>
+<br>
+  O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))<br>
+    << getRegisterName(MO2.getReg());<br>
+<br>
+  if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))<br>
+    O << ", "<br>
+    << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))<br>
+    << " #" << ShImm;<br>
+}<br>
+<br>
+void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,<br>
+                                           raw_ostream &O) {<br>
+  const MCOperand &MO1 = MI->getOperand(Op);<br>
+<br>
+  if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.<br>
+    printOperand(MI, Op, O);<br>
+    return;<br>
+  }<br>
+<br>
+  unsigned Opcode = MI->getOpcode();<br>
+  const TargetInstrDesc &Desc = TM.getInstrInfo()->get(Opcode);<br>
+  uint64_t TSFlags = Desc.TSFlags;<br>
+  unsigned IdxMode = (TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;<br>
+<br>
+  if (IdxMode == ARMII::IndexModePost) {<br>
+    printAM2PostIndexOp(MI, Op, O);<br>
+    return;<br>
+  }<br>
+  printAM2PreOrOffsetIndexOp(MI, Op, O);<br>
+}<br>
+<br>
 void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,<br>
                                                  unsigned OpNum,<br>
                                                  raw_ostream &O) {<br>
<br>
Modified: llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h?rev=128585&r1=128584&r2=128585&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h?rev=128585&r1=128584&r2=128585&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h (original)<br>
+++ llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.h Wed Mar 30 18:32:32 2011<br>
@@ -22,9 +22,11 @@<br>
 class TargetMachine;<br>
<br>
 class ARMInstPrinter : public MCInstPrinter {<br>
+private:<br>
+  TargetMachine &TM;<br>
 public:<br>
-  ARMInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI)<br>
-    : MCInstPrinter(MAI) {}<br>
+  ARMInstPrinter(TargetMachine &_TM, const MCAsmInfo &MAI)<br>
+    : MCInstPrinter(MAI), TM(_TM) {}<br>
<br>
   virtual void printInst(const MCInst *MI, raw_ostream &O);<br>
   virtual StringRef getOpcodeName(unsigned Opcode) const;<br>
@@ -42,7 +44,11 @@<br>
   void printSOImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);<br>
<br>
   void printSORegOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);<br>
+<br>
   void printAddrMode2Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);<br>
+  void printAM2PostIndexOp(const MCInst *MI, unsigned OpNum, raw_ostream &O);<br>
+  void printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned OpNum,<br>
+                                  raw_ostream &O);<br>
   void printAddrMode2OffsetOperand(const MCInst *MI, unsigned OpNum,<br>
                                    raw_ostream &O);<br>
   void printAddrMode3Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);<br>
<br>
Added: llvm/trunk/test/MC/ARM/arm_addrmode2.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/arm_addrmode2.s?rev=128585&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/arm_addrmode2.s?rev=128585&view=auto</a><br>


==============================================================================<br>
--- llvm/trunk/test/MC/ARM/arm_addrmode2.s (added)<br>
+++ llvm/trunk/test/MC/ARM/arm_addrmode2.s Wed Mar 30 18:32:32 2011<br>
@@ -0,0 +1,34 @@<br>
+@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding %s | FileCheck %s<br>
+<br>
+@ Post-indexed<br>
+@ CHECK: ldrt  r1, [r0], r2 @ encoding: [0x02,0x10,0xb0,0xe6]<br>
+@ CHECK: ldrt  r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xb0,0xe6]<br>
+@ CHECK: ldrt  r1, [r0], #4 @ encoding: [0x04,0x10,0xb0,0xe4]<br>
+@ CHECK: ldrbt  r1, [r0], r2 @ encoding: [0x02,0x10,0xf0,0xe6]<br>
+@ CHECK: ldrbt  r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xf0,0xe6]<br>
+@ CHECK: ldrbt  r1, [r0], #4 @ encoding: [0x04,0x10,0xf0,0xe4]<br>
+@ CHECK: strt  r1, [r0], r2 @ encoding: [0x02,0x10,0xa0,0xe6]<br>
+@ CHECK: strt  r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xa0,0xe6]<br>
+@ CHECK: strt  r1, [r0], #4 @ encoding: [0x04,0x10,0xa0,0xe4]<br>
+@ CHECK: strbt  r1, [r0], r2 @ encoding: [0x02,0x10,0xe0,0xe6]<br>
+@ CHECK: strbt  r1, [r0], r2, lsr #3 @ encoding: [0xa2,0x11,0xe0,0xe6]<br>
+@ CHECK: strbt  r1, [r0], #4 @ encoding: [0x04,0x10,0xe0,0xe4]<br>
+        ldrt  r1, [r0], r2<br>
+        ldrt  r1, [r0], r2, lsr #3<br>
+        ldrt  r1, [r0], #4<br>
+        ldrbt  r1, [r0], r2<br>
+        ldrbt  r1, [r0], r2, lsr #3<br>
+        ldrbt  r1, [r0], #4<br>
+        strt  r1, [r0], r2<br>
+        strt  r1, [r0], r2, lsr #3<br>
+        strt  r1, [r0], #4<br>
+        strbt  r1, [r0], r2<br>
+        strbt  r1, [r0], r2, lsr #3<br>
+        strbt  r1, [r0], #4<br>
+<br>
+@ Pre-indexed<br>
+@ CHECK: ldr  r1, [r0, r2, lsr #3]! @ encoding: [0xa2,0x11,0xb0,0xe7]<br>
+@ CHECK: ldrb  r1, [r0, r2, lsr #3]! @ encoding: [0xa2,0x11,0xf0,0xe7]<br>
+        ldr  r1, [r0, r2, lsr #3]!<br>
+        ldrb  r1, [r0, r2, lsr #3]!<br>
+<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br>