1263320SdimPull in r198658 from upstream llvm trunk:
2263320Sdim
3263320Sdim  [Sparc] Add support for parsing memory operands in sparc AsmParser.
4263320Sdim
5269012SemasteIntroduced here: http://svnweb.freebsd.org/changeset/base/262261
6263320Sdim
7263320SdimIndex: test/MC/Sparc/sparc-ctrl-instructions.s
8263320Sdim===================================================================
9263320Sdim--- test/MC/Sparc/sparc-ctrl-instructions.s
10263320Sdim+++ test/MC/Sparc/sparc-ctrl-instructions.s
11263320Sdim@@ -0,0 +1,23 @@
12263320Sdim+! RUN: llvm-mc %s -arch=sparc   -show-encoding | FileCheck %s
13263320Sdim+! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
14263320Sdim+
15263320Sdim+        ! CHECK: call foo
16263320Sdim+        call foo
17263320Sdim+
18263320Sdim+        ! CHECK: call %g1+%i2
19263320Sdim+        call %g1 + %i2
20263320Sdim+
21263320Sdim+        ! CHECK: call %o1+8
22263320Sdim+        call %o1 + 8
23263320Sdim+
24263320Sdim+        ! CHECK: call %g1
25263320Sdim+        call %g1
26263320Sdim+
27263320Sdim+        ! CHECK: jmp %g1+%i2
28263320Sdim+        jmp %g1 + %i2
29263320Sdim+
30263320Sdim+        ! CHECK: jmp %o1+8
31263320Sdim+        jmp %o1 + 8
32263320Sdim+
33263320Sdim+        ! CHECK: jmp %g1
34263320Sdim+        jmp %g1
35263320SdimIndex: test/MC/Sparc/sparc-mem-instructions.s
36263320Sdim===================================================================
37263320Sdim--- test/MC/Sparc/sparc-mem-instructions.s
38263320Sdim+++ test/MC/Sparc/sparc-mem-instructions.s
39263320Sdim@@ -0,0 +1,58 @@
40263320Sdim+! RUN: llvm-mc %s -arch=sparc   -show-encoding | FileCheck %s
41263320Sdim+! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
42263320Sdim+
43263320Sdim+        ! CHECK: ldsb [%i0+%l6], %o2  ! encoding: [0xd4,0x4e,0x00,0x16]
44263320Sdim+        ldsb [%i0 + %l6], %o2
45263320Sdim+        ! CHECK: ldsb [%i0+32], %o2   ! encoding: [0xd4,0x4e,0x20,0x20]
46263320Sdim+        ldsb [%i0 + 32], %o2
47263320Sdim+        ! CHECK: ldsb [%g1], %o4      ! encoding: [0xd8,0x48,0x60,0x00]
48263320Sdim+        ldsb [%g1], %o4
49263320Sdim+
50263320Sdim+        ! CHECK: ldsh [%i0+%l6], %o2  ! encoding: [0xd4,0x56,0x00,0x16]
51263320Sdim+        ldsh [%i0 + %l6], %o2
52263320Sdim+        ! CHECK: ldsh [%i0+32], %o2   ! encoding: [0xd4,0x56,0x20,0x20]
53263320Sdim+        ldsh [%i0 + 32], %o2
54263320Sdim+        ! CHECK: ldsh [%g1], %o4      ! encoding: [0xd8,0x50,0x60,0x00]
55263320Sdim+        ldsh [%g1], %o4
56263320Sdim+
57263320Sdim+        ! CHECK: ldub [%i0+%l6], %o2  ! encoding: [0xd4,0x0e,0x00,0x16]
58263320Sdim+        ldub [%i0 + %l6], %o2
59263320Sdim+        ! CHECK: ldub [%i0+32], %o2   ! encoding: [0xd4,0x0e,0x20,0x20]
60263320Sdim+        ldub [%i0 + 32], %o2
61263320Sdim+        ! CHECK: ldub [%g1], %o2      ! encoding: [0xd4,0x08,0x60,0x00]
62263320Sdim+        ldub [%g1], %o2
63263320Sdim+
64263320Sdim+        ! CHECK: lduh [%i0+%l6], %o2  ! encoding: [0xd4,0x16,0x00,0x16]
65263320Sdim+        lduh [%i0 + %l6], %o2
66263320Sdim+        ! CHECK: lduh [%i0+32], %o2   ! encoding: [0xd4,0x16,0x20,0x20]
67263320Sdim+        lduh [%i0 + 32], %o2
68263320Sdim+        ! CHECK: lduh [%g1], %o2      ! encoding: [0xd4,0x10,0x60,0x00]
69263320Sdim+        lduh [%g1], %o2
70263320Sdim+
71263320Sdim+        ! CHECK: ld [%i0+%l6], %o2    ! encoding: [0xd4,0x06,0x00,0x16]
72263320Sdim+        ld [%i0 + %l6], %o2
73263320Sdim+        ! CHECK: ld [%i0+32], %o2     ! encoding: [0xd4,0x06,0x20,0x20]
74263320Sdim+        ld [%i0 + 32], %o2
75263320Sdim+        ! CHECK: ld [%g1], %o2        ! encoding: [0xd4,0x00,0x60,0x00]
76263320Sdim+        ld [%g1], %o2
77263320Sdim+
78263320Sdim+        ! CHECK: stb %o2, [%i0+%l6]   ! encoding: [0xd4,0x2e,0x00,0x16]
79263320Sdim+        stb %o2, [%i0 + %l6]
80263320Sdim+        ! CHECK: stb %o2, [%i0+32]    ! encoding: [0xd4,0x2e,0x20,0x20]
81263320Sdim+        stb %o2, [%i0 + 32]
82263320Sdim+        ! CHECK: stb %o2, [%g1]       ! encoding: [0xd4,0x28,0x60,0x00]
83263320Sdim+        stb %o2, [%g1]
84263320Sdim+
85263320Sdim+        ! CHECK: sth %o2, [%i0+%l6]   ! encoding: [0xd4,0x36,0x00,0x16]
86263320Sdim+        sth %o2, [%i0 + %l6]
87263320Sdim+        ! CHECK: sth %o2, [%i0+32]    ! encoding: [0xd4,0x36,0x20,0x20]
88263320Sdim+        sth %o2, [%i0 + 32]
89263320Sdim+        ! CHECK: sth %o2, [%g1]       ! encoding: [0xd4,0x30,0x60,0x00]
90263320Sdim+        sth %o2, [%g1]
91263320Sdim+
92263320Sdim+        ! CHECK: st %o2, [%i0+%l6]    ! encoding: [0xd4,0x26,0x00,0x16]
93263320Sdim+        st %o2, [%i0 + %l6]
94263320Sdim+        ! CHECK: st %o2, [%i0+32]     ! encoding: [0xd4,0x26,0x20,0x20]
95263320Sdim+        st %o2, [%i0 + 32]
96263320Sdim+        ! CHECK: st %o2, [%g1]        ! encoding: [0xd4,0x20,0x60,0x00]
97263320Sdim+        st %o2, [%g1]
98263320SdimIndex: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
99263320Sdim===================================================================
100263320Sdim--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
101263320Sdim+++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
102263320Sdim@@ -28,6 +28,7 @@ namespace llvm {
103263320Sdim }
104263320Sdim 
105263320Sdim namespace {
106263320Sdim+class SparcOperand;
107263320Sdim class SparcAsmParser : public MCTargetAsmParser {
108263320Sdim 
109263320Sdim   MCSubtargetInfo &STI;
110263320Sdim@@ -55,18 +56,15 @@ class SparcAsmParser : public MCTargetAsmParser {
111263320Sdim 
112263320Sdim   // Custom parse functions for Sparc specific operands.
113263320Sdim   OperandMatchResultTy
114263320Sdim-  parseMEMrrOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
115263320Sdim-  OperandMatchResultTy
116263320Sdim-  parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
117263320Sdim+  parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
118263320Sdim 
119263320Sdim   OperandMatchResultTy
120263320Sdim-  parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
121263320Sdim-                  int ImmOffsetOrReg);
122263320Sdim-
123263320Sdim-  OperandMatchResultTy
124263320Sdim   parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
125263320Sdim                StringRef Name);
126263320Sdim 
127263320Sdim+  OperandMatchResultTy
128263320Sdim+  parseSparcAsmOperand(SparcOperand *&Operand);
129263320Sdim+
130263320Sdim   // returns true if Tok is matched to a register and returns register in RegNo.
131263320Sdim   bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, bool isDFP,
132263320Sdim                          bool isQFP);
133263320Sdim@@ -298,7 +296,35 @@ class SparcOperand : public MCParsedAsmOperand {
134263320Sdim     return Op;
135263320Sdim   }
136263320Sdim 
137263320Sdim+  static SparcOperand *MorphToMEMrr(unsigned Base, SparcOperand *Op) {
138263320Sdim+    unsigned offsetReg = Op->getReg();
139263320Sdim+    Op->Kind = k_MemoryReg;
140263320Sdim+    Op->Mem.Base = Base;
141263320Sdim+    Op->Mem.OffsetReg = offsetReg;
142263320Sdim+    Op->Mem.Off = 0;
143263320Sdim+    return Op;
144263320Sdim+  }
145263320Sdim 
146263320Sdim+  static SparcOperand *CreateMEMri(unsigned Base,
147263320Sdim+                                 const MCExpr *Off,
148263320Sdim+                                 SMLoc S, SMLoc E) {
149263320Sdim+    SparcOperand *Op = new SparcOperand(k_MemoryImm);
150263320Sdim+    Op->Mem.Base = Base;
151263320Sdim+    Op->Mem.OffsetReg = 0;
152263320Sdim+    Op->Mem.Off = Off;
153263320Sdim+    Op->StartLoc = S;
154263320Sdim+    Op->EndLoc = E;
155263320Sdim+    return Op;
156263320Sdim+  }
157263320Sdim+
158263320Sdim+  static SparcOperand *MorphToMEMri(unsigned Base, SparcOperand *Op) {
159263320Sdim+    const MCExpr *Imm  = Op->getImm();
160263320Sdim+    Op->Kind = k_MemoryImm;
161263320Sdim+    Op->Mem.Base = Base;
162263320Sdim+    Op->Mem.OffsetReg = 0;
163263320Sdim+    Op->Mem.Off = Imm;
164263320Sdim+    return Op;
165263320Sdim+  }
166263320Sdim };
167263320Sdim 
168263320Sdim } // end namespace
169263320Sdim@@ -412,23 +438,42 @@ ParseDirective(AsmToken DirectiveID)
170263320Sdim }
171263320Sdim 
172263320Sdim SparcAsmParser::OperandMatchResultTy SparcAsmParser::
173263320Sdim-parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
174263320Sdim-                int ImmOffsetOrReg)
175263320Sdim+parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
176263320Sdim {
177263320Sdim-  // FIXME: Implement memory operand parsing here.
178263320Sdim-  return MatchOperand_NoMatch;
179263320Sdim-}
180263320Sdim 
181263320Sdim-SparcAsmParser::OperandMatchResultTy SparcAsmParser::
182263320Sdim-parseMEMrrOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
183263320Sdim-{
184263320Sdim-  return parseMEMOperand(Operands, 2);
185263320Sdim-}
186263320Sdim+  SMLoc S, E;
187263320Sdim+  unsigned BaseReg = 0;
188263320Sdim 
189263320Sdim-SparcAsmParser::OperandMatchResultTy SparcAsmParser::
190263320Sdim-parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
191263320Sdim-{
192263320Sdim-  return parseMEMOperand(Operands, 1);
193263320Sdim+  if (ParseRegister(BaseReg, S, E)) {
194263320Sdim+    return MatchOperand_NoMatch;
195263320Sdim+  }
196263320Sdim+
197263320Sdim+  switch (getLexer().getKind()) {
198263320Sdim+  default: return MatchOperand_NoMatch;
199263320Sdim+
200263320Sdim+  case AsmToken::RBrac:
201263320Sdim+  case AsmToken::EndOfStatement:
202263320Sdim+    Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E));
203263320Sdim+    return MatchOperand_Success;
204263320Sdim+
205263320Sdim+  case AsmToken:: Plus:
206263320Sdim+    Parser.Lex(); // Eat the '+'
207263320Sdim+    break;
208263320Sdim+  case AsmToken::Minus:
209263320Sdim+    break;
210263320Sdim+  }
211263320Sdim+
212263320Sdim+  SparcOperand *Offset = 0;
213263320Sdim+  OperandMatchResultTy ResTy = parseSparcAsmOperand(Offset);
214263320Sdim+  if (ResTy != MatchOperand_Success || !Offset)
215263320Sdim+    return MatchOperand_NoMatch;
216263320Sdim+
217263320Sdim+  Offset = (Offset->isImm()
218263320Sdim+            ? SparcOperand::MorphToMEMri(BaseReg, Offset)
219263320Sdim+            : SparcOperand::MorphToMEMrr(BaseReg, Offset));
220263320Sdim+
221263320Sdim+  Operands.push_back(Offset);
222263320Sdim+  return MatchOperand_Success;
223263320Sdim }
224263320Sdim 
225263320Sdim SparcAsmParser::OperandMatchResultTy SparcAsmParser::
226263320Sdim@@ -435,20 +480,57 @@ SparcAsmParser::OperandMatchResultTy SparcAsmParse
227263320Sdim parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
228263320Sdim              StringRef Mnemonic)
229263320Sdim {
230263320Sdim+
231263320Sdim   OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
232263320Sdim-  if (ResTy == MatchOperand_Success)
233263320Sdim-    return ResTy;
234263320Sdim+
235263320Sdim   // If there wasn't a custom match, try the generic matcher below. Otherwise,
236263320Sdim   // there was a match, but an error occurred, in which case, just return that
237263320Sdim   // the operand parsing failed.
238263320Sdim-  if (ResTy == MatchOperand_ParseFail)
239263320Sdim+  if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail)
240263320Sdim     return ResTy;
241263320Sdim 
242263320Sdim+  if (getLexer().is(AsmToken::LBrac)) {
243263320Sdim+    // Memory operand
244263320Sdim+    Operands.push_back(SparcOperand::CreateToken("[",
245263320Sdim+                                                 Parser.getTok().getLoc()));
246263320Sdim+    Parser.Lex(); // Eat the [
247263320Sdim+
248263320Sdim+    ResTy = parseMEMOperand(Operands);
249263320Sdim+    if (ResTy != MatchOperand_Success)
250263320Sdim+      return ResTy;
251263320Sdim+
252263320Sdim+    if (!getLexer().is(AsmToken::RBrac))
253263320Sdim+      return MatchOperand_ParseFail;
254263320Sdim+
255263320Sdim+    Operands.push_back(SparcOperand::CreateToken("]",
256263320Sdim+                                                 Parser.getTok().getLoc()));
257263320Sdim+    Parser.Lex(); // Eat the ]
258263320Sdim+    return MatchOperand_Success;
259263320Sdim+  }
260263320Sdim+
261263320Sdim+  SparcOperand *Op = 0;
262263320Sdim+  ResTy = parseSparcAsmOperand(Op);
263263320Sdim+  if (ResTy != MatchOperand_Success || !Op)
264263320Sdim+    return MatchOperand_ParseFail;
265263320Sdim+
266263320Sdim+  // Push the parsed operand into the list of operands
267263320Sdim+  Operands.push_back(Op);
268263320Sdim+
269263320Sdim+  return MatchOperand_Success;
270263320Sdim+}
271263320Sdim+
272263320Sdim+SparcAsmParser::OperandMatchResultTy
273263320Sdim+SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op)
274263320Sdim+{
275263320Sdim+
276263320Sdim   SMLoc S = Parser.getTok().getLoc();
277263320Sdim   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
278263320Sdim   const MCExpr *EVal;
279263320Sdim-  SparcOperand *Op;
280263320Sdim+
281263320Sdim+  Op = 0;
282263320Sdim   switch (getLexer().getKind()) {
283263320Sdim+  default:  break;
284263320Sdim+
285263320Sdim   case AsmToken::Percent:
286263320Sdim     Parser.Lex(); // Eat the '%'.
287263320Sdim     unsigned RegNo;
288263320Sdim@@ -458,40 +540,30 @@ parseOperand(SmallVectorImpl<MCParsedAsmOperand*>
289263320Sdim       break;
290263320Sdim     }
291263320Sdim     // FIXME: Handle modifiers like %hi, %lo etc.,
292263320Sdim-    return MatchOperand_ParseFail;
293263320Sdim+    break;
294263320Sdim 
295263320Sdim   case AsmToken::Minus:
296263320Sdim   case AsmToken::Integer:
297263320Sdim-    if (getParser().parseExpression(EVal))
298263320Sdim-      return MatchOperand_ParseFail;
299263320Sdim-
300263320Sdim-    Op = SparcOperand::CreateImm(EVal, S, E);
301263320Sdim+    if (!getParser().parseExpression(EVal))
302263320Sdim+      Op = SparcOperand::CreateImm(EVal, S, E);
303263320Sdim     break;
304263320Sdim 
305263320Sdim   case AsmToken::Identifier: {
306263320Sdim     StringRef Identifier;
307263320Sdim-    if (getParser().parseIdentifier(Identifier))
308263320Sdim-      return MatchOperand_ParseFail;
309263320Sdim-    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
310263320Sdim-    MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
311263320Sdim+    if (!getParser().parseIdentifier(Identifier)) {
312263320Sdim+      SMLoc E = SMLoc::getFromPointer(Parser.getTok().
313263320Sdim+                                      getLoc().getPointer() - 1);
314263320Sdim+      MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
315263320Sdim 
316263320Sdim-    // Otherwise create a symbol reference.
317263320Sdim-    const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
318263320Sdim-                                                getContext());
319263320Sdim+      const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
320263320Sdim+                                                  getContext());
321263320Sdim 
322263320Sdim-    Op = SparcOperand::CreateImm(Res, S, E);
323263320Sdim+      Op = SparcOperand::CreateImm(Res, S, E);
324263320Sdim+    }
325263320Sdim     break;
326263320Sdim   }
327263320Sdim-
328263320Sdim-  case AsmToken::LBrac:  // handle [
329263320Sdim-    return parseMEMOperand(Operands, 0);
330263320Sdim-
331263320Sdim-  default:
332263320Sdim-    return MatchOperand_ParseFail;
333263320Sdim   }
334263320Sdim-  // Push the parsed operand into the list of operands
335263320Sdim-  Operands.push_back(Op);
336263320Sdim-  return MatchOperand_Success;
337263320Sdim+  return (Op) ? MatchOperand_Success : MatchOperand_ParseFail;
338263320Sdim }
339263320Sdim 
340263320Sdim bool SparcAsmParser::matchRegisterName(const AsmToken &Tok,
341263320SdimIndex: lib/Target/Sparc/SparcInstrInfo.td
342263320Sdim===================================================================
343263320Sdim--- lib/Target/Sparc/SparcInstrInfo.td
344263320Sdim+++ lib/Target/Sparc/SparcInstrInfo.td
345263320Sdim@@ -78,12 +78,12 @@ def ADDRri : ComplexPattern<iPTR, 2, "SelectADDRri
346263320Sdim // Address operands
347263320Sdim def SparcMEMrrAsmOperand : AsmOperandClass {
348263320Sdim   let Name = "MEMrr";
349263320Sdim-  let ParserMethod = "parseMEMrrOperand";
350263320Sdim+  let ParserMethod = "parseMEMOperand";
351263320Sdim }
352263320Sdim 
353263320Sdim def SparcMEMriAsmOperand : AsmOperandClass {
354263320Sdim   let Name = "MEMri";
355263320Sdim-  let ParserMethod = "parseMEMriOperand";
356263320Sdim+  let ParserMethod = "parseMEMOperand";
357263320Sdim }
358263320Sdim 
359263320Sdim def MEMrr : Operand<iPTR> {
360