blob: 085503eb0d4fbb8408c47b13ab08fbadb633e522 [file] [log] [blame]
Jia Liuc5707112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindolafddf8042012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterec65be82012-09-05 23:34:03 +000011#include "MipsRegisterInfo.h"
12#include "llvm/ADT/StringSwitch.h"
13#include "llvm/MC/MCContext.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCInst.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000016#include "llvm/MC/MCParser/MCAsmLexer.h"
17#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterec65be82012-09-05 23:34:03 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCSubtargetInfo.h"
20#include "llvm/MC/MCSymbol.h"
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000021#include "llvm/MC/MCTargetAsmParser.h"
Jack Carterec65be82012-09-05 23:34:03 +000022#include "llvm/Support/TargetRegistry.h"
Rafael Espindolafddf8042012-01-11 03:56:41 +000023
24using namespace llvm;
25
26namespace {
Jack Carter30116cd2012-10-04 02:29:46 +000027class MipsAssemblerOptions {
28public:
29 MipsAssemblerOptions():
30 aTReg(1), reorder(true), macro(true) {
31 }
Jack Carterec65be82012-09-05 23:34:03 +000032
Jack Carter30116cd2012-10-04 02:29:46 +000033 unsigned getATRegNum() {return aTReg;}
34 bool setATReg(unsigned Reg);
35
36 bool isReorder() {return reorder;}
37 void setReorder() {reorder = true;}
38 void setNoreorder() {reorder = false;}
39
40 bool isMacro() {return macro;}
41 void setMacro() {macro = true;}
42 void setNomacro() {macro = false;}
43
44private:
45 unsigned aTReg;
46 bool reorder;
47 bool macro;
48};
49}
50
51namespace {
Rafael Espindolafddf8042012-01-11 03:56:41 +000052class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000053
Jack Carterf740d6e2012-09-07 00:23:42 +000054 enum FpFormatTy {
55 FP_FORMAT_NONE = -1,
56 FP_FORMAT_S,
57 FP_FORMAT_D,
58 FP_FORMAT_L,
59 FP_FORMAT_W
60 } FpFormat;
61
Jack Carterec65be82012-09-05 23:34:03 +000062 MCSubtargetInfo &STI;
63 MCAsmParser &Parser;
Jack Carter10d5ff62012-10-05 23:55:28 +000064 MipsAssemblerOptions Options;
Jack Carter30116cd2012-10-04 02:29:46 +000065
Jack Carterec65be82012-09-05 23:34:03 +000066
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000067#define GET_ASSEMBLER_HEADER
68#include "MipsGenAsmMatcher.inc"
69
Chad Rosier84125ca2012-10-13 00:26:04 +000070 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindolafddf8042012-01-11 03:56:41 +000071 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier84125ca2012-10-13 00:26:04 +000072 MCStreamer &Out, unsigned &ErrorInfo,
73 bool MatchingInlineAsm);
Rafael Espindolafddf8042012-01-11 03:56:41 +000074
75 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
76
Chad Rosier6a020a72012-10-25 20:41:34 +000077 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
78 SMLoc NameLoc,
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000079 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindolafddf8042012-01-11 03:56:41 +000080
Jack Carterf740d6e2012-09-07 00:23:42 +000081 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
82 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
83
Rafael Espindolafddf8042012-01-11 03:56:41 +000084 bool ParseDirective(AsmToken DirectiveID);
85
Jack Carterec65be82012-09-05 23:34:03 +000086 MipsAsmParser::OperandMatchResultTy
87 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
Chad Rosier038f3e32012-09-03 18:47:45 +000088
Jack Carterec65be82012-09-05 23:34:03 +000089 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
90 StringRef Mnemonic);
91
92 int tryParseRegister(StringRef Mnemonic);
93
94 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
95 StringRef Mnemonic);
96
Jack Carter9d577c82012-10-04 04:03:53 +000097 bool needsExpansion(MCInst &Inst);
98
99 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000100 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9d577c82012-10-04 04:03:53 +0000101 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000102 SmallVectorImpl<MCInst> &Instructions);
Jack Carter2f68b312012-10-09 23:29:45 +0000103 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
104 SmallVectorImpl<MCInst> &Instructions);
105 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
106 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30116cd2012-10-04 02:29:46 +0000107 bool reportParseError(StringRef ErrorMsg);
108
Jack Carter6b96c3f2012-09-06 20:00:02 +0000109 bool parseMemOffset(const MCExpr *&Res);
Jordan Rose3ebe59c2013-01-07 19:00:49 +0000110 bool parseRelocOperand(const MCExpr *&Res, SMLoc &E);
Jack Carter30116cd2012-10-04 02:29:46 +0000111
112 bool parseDirectiveSet();
113
114 bool parseSetAtDirective();
115 bool parseSetNoAtDirective();
116 bool parseSetMacroDirective();
117 bool parseSetNoMacroDirective();
118 bool parseSetReorderDirective();
119 bool parseSetNoReorderDirective();
120
Jack Carter6b96c3f2012-09-06 20:00:02 +0000121 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Carterf740d6e2012-09-07 00:23:42 +0000122
Jack Carterec65be82012-09-05 23:34:03 +0000123 bool isMips64() const {
124 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
125 }
126
Jack Carterf740d6e2012-09-07 00:23:42 +0000127 bool isFP64() const {
128 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
129 }
130
Jack Carterec65be82012-09-05 23:34:03 +0000131 int matchRegisterName(StringRef Symbol);
132
133 int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
134
Jack Carterf740d6e2012-09-07 00:23:42 +0000135 void setFpFormat(FpFormatTy Format) {
136 FpFormat = Format;
137 }
138
139 void setDefaultFpFormat();
140
141 void setFpFormat(StringRef Format);
142
143 FpFormatTy getFpFormat() {return FpFormat;}
144
145 bool requestsDoubleOperand(StringRef Mnemonic);
146
Jack Carterec65be82012-09-05 23:34:03 +0000147 unsigned getReg(int RC,int RegNo);
Chad Rosier038f3e32012-09-03 18:47:45 +0000148
Jack Carter30116cd2012-10-04 02:29:46 +0000149 unsigned getATReg();
Rafael Espindolafddf8042012-01-11 03:56:41 +0000150public:
151 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterec65be82012-09-05 23:34:03 +0000152 : MCTargetAsmParser(), STI(sti), Parser(parser) {
153 // Initialize the set of available features.
154 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindolafddf8042012-01-11 03:56:41 +0000155 }
156
Jack Carterec65be82012-09-05 23:34:03 +0000157 MCAsmParser &getParser() const { return Parser; }
158 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
159
Rafael Espindolafddf8042012-01-11 03:56:41 +0000160};
161}
162
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000163namespace {
164
165/// MipsOperand - Instances of this class represent a parsed Mips machine
166/// instruction.
167class MipsOperand : public MCParsedAsmOperand {
Jack Carterec65be82012-09-05 23:34:03 +0000168
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000169 enum KindTy {
170 k_CondCode,
171 k_CoprocNum,
172 k_Immediate,
173 k_Memory,
174 k_PostIndexRegister,
175 k_Register,
176 k_Token
177 } Kind;
178
179 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterec65be82012-09-05 23:34:03 +0000180
181 union {
182 struct {
183 const char *Data;
184 unsigned Length;
185 } Tok;
186
187 struct {
188 unsigned RegNum;
189 } Reg;
190
191 struct {
192 const MCExpr *Val;
193 } Imm;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000194
195 struct {
196 unsigned Base;
197 const MCExpr *Off;
198 } Mem;
Jack Carterec65be82012-09-05 23:34:03 +0000199 };
200
201 SMLoc StartLoc, EndLoc;
202
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000203public:
204 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000205 assert(N == 1 && "Invalid number of operands!");
206 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000207 }
Jack Carterec65be82012-09-05 23:34:03 +0000208
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000209 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterec65be82012-09-05 23:34:03 +0000210 // Add as immediate when possible. Null MCExpr = 0.
211 if (Expr == 0)
212 Inst.addOperand(MCOperand::CreateImm(0));
213 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
214 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
215 else
216 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000217 }
Jack Carterec65be82012-09-05 23:34:03 +0000218
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000219 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000220 assert(N == 1 && "Invalid number of operands!");
221 const MCExpr *Expr = getImm();
222 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000223 }
Jack Carterec65be82012-09-05 23:34:03 +0000224
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000225 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000226 assert(N == 2 && "Invalid number of operands!");
227
228 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
229
230 const MCExpr *Expr = getMemOff();
231 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000232 }
233
234 bool isReg() const { return Kind == k_Register; }
235 bool isImm() const { return Kind == k_Immediate; }
236 bool isToken() const { return Kind == k_Token; }
237 bool isMem() const { return Kind == k_Memory; }
238
239 StringRef getToken() const {
240 assert(Kind == k_Token && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000241 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000242 }
243
244 unsigned getReg() const {
245 assert((Kind == k_Register) && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000246 return Reg.RegNum;
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000247 }
248
Jack Carterec65be82012-09-05 23:34:03 +0000249 const MCExpr *getImm() const {
250 assert((Kind == k_Immediate) && "Invalid access!");
251 return Imm.Val;
252 }
253
Jack Carter6b96c3f2012-09-06 20:00:02 +0000254 unsigned getMemBase() const {
255 assert((Kind == k_Memory) && "Invalid access!");
256 return Mem.Base;
257 }
258
259 const MCExpr *getMemOff() const {
260 assert((Kind == k_Memory) && "Invalid access!");
261 return Mem.Off;
262 }
263
Jack Carterec65be82012-09-05 23:34:03 +0000264 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
265 MipsOperand *Op = new MipsOperand(k_Token);
266 Op->Tok.Data = Str.data();
267 Op->Tok.Length = Str.size();
268 Op->StartLoc = S;
269 Op->EndLoc = S;
270 return Op;
271 }
272
273 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
274 MipsOperand *Op = new MipsOperand(k_Register);
275 Op->Reg.RegNum = RegNum;
276 Op->StartLoc = S;
277 Op->EndLoc = E;
278 return Op;
279 }
280
281 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
282 MipsOperand *Op = new MipsOperand(k_Immediate);
283 Op->Imm.Val = Val;
284 Op->StartLoc = S;
285 Op->EndLoc = E;
286 return Op;
287 }
288
Jack Carter6b96c3f2012-09-06 20:00:02 +0000289 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
290 SMLoc S, SMLoc E) {
291 MipsOperand *Op = new MipsOperand(k_Memory);
292 Op->Mem.Base = Base;
293 Op->Mem.Off = Off;
294 Op->StartLoc = S;
295 Op->EndLoc = E;
296 return Op;
297 }
298
Jack Carterec65be82012-09-05 23:34:03 +0000299 /// getStartLoc - Get the location of the first token of this operand.
300 SMLoc getStartLoc() const { return StartLoc; }
301 /// getEndLoc - Get the location of the last token of this operand.
302 SMLoc getEndLoc() const { return EndLoc; }
303
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000304 virtual void print(raw_ostream &OS) const {
305 llvm_unreachable("unimplemented!");
306 }
307};
308}
309
Jack Carter9d577c82012-10-04 04:03:53 +0000310bool MipsAsmParser::needsExpansion(MCInst &Inst) {
311
312 switch(Inst.getOpcode()) {
313 case Mips::LoadImm32Reg:
Jack Carter2f68b312012-10-09 23:29:45 +0000314 case Mips::LoadAddr32Imm:
315 case Mips::LoadAddr32Reg:
Jack Carter9d577c82012-10-04 04:03:53 +0000316 return true;
317 default:
318 return false;
319 }
320}
Jack Carter2490dc62012-10-06 00:53:28 +0000321
Jack Carter9d577c82012-10-04 04:03:53 +0000322void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000323 SmallVectorImpl<MCInst> &Instructions){
Jack Carter9d577c82012-10-04 04:03:53 +0000324 switch(Inst.getOpcode()) {
325 case Mips::LoadImm32Reg:
326 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carter2f68b312012-10-09 23:29:45 +0000327 case Mips::LoadAddr32Imm:
328 return expandLoadAddressImm(Inst,IDLoc,Instructions);
329 case Mips::LoadAddr32Reg:
330 return expandLoadAddressReg(Inst,IDLoc,Instructions);
Jack Carter9d577c82012-10-04 04:03:53 +0000331 }
Jack Carter9d577c82012-10-04 04:03:53 +0000332}
Jack Carter2490dc62012-10-06 00:53:28 +0000333
Jack Carter9d577c82012-10-04 04:03:53 +0000334void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter2f68b312012-10-09 23:29:45 +0000335 SmallVectorImpl<MCInst> &Instructions){
Jack Carter2490dc62012-10-06 00:53:28 +0000336 MCInst tmpInst;
Jack Carter9d577c82012-10-04 04:03:53 +0000337 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter2f68b312012-10-09 23:29:45 +0000338 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter9d577c82012-10-04 04:03:53 +0000339 const MCOperand &RegOp = Inst.getOperand(0);
340 assert(RegOp.isReg() && "expected register operand kind");
341
342 int ImmValue = ImmOp.getImm();
Jack Carter2490dc62012-10-06 00:53:28 +0000343 tmpInst.setLoc(IDLoc);
Jack Carter9d577c82012-10-04 04:03:53 +0000344 if ( 0 <= ImmValue && ImmValue <= 65535) {
Jack Carter2490dc62012-10-06 00:53:28 +0000345 // for 0 <= j <= 65535.
Jack Carter9d577c82012-10-04 04:03:53 +0000346 // li d,j => ori d,$zero,j
Jack Carter2490dc62012-10-06 00:53:28 +0000347 tmpInst.setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
348 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
349 tmpInst.addOperand(
Jack Carter9d577c82012-10-04 04:03:53 +0000350 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
Jack Carter2490dc62012-10-06 00:53:28 +0000351 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter9d577c82012-10-04 04:03:53 +0000352 Instructions.push_back(tmpInst);
353 } else if ( ImmValue < 0 && ImmValue >= -32768) {
Jack Carter2490dc62012-10-06 00:53:28 +0000354 // for -32768 <= j < 0.
Jack Carter9d577c82012-10-04 04:03:53 +0000355 // li d,j => addiu d,$zero,j
Jack Carter2490dc62012-10-06 00:53:28 +0000356 tmpInst.setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
357 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
358 tmpInst.addOperand(
Jack Carter9d577c82012-10-04 04:03:53 +0000359 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
Jack Carter2490dc62012-10-06 00:53:28 +0000360 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter9d577c82012-10-04 04:03:53 +0000361 Instructions.push_back(tmpInst);
362 } else {
363 // for any other value of j that is representable as a 32-bit integer.
364 // li d,j => lui d,hi16(j)
Jack Carter2f68b312012-10-09 23:29:45 +0000365 // ori d,d,lo16(j)
Jack Carter2490dc62012-10-06 00:53:28 +0000366 tmpInst.setOpcode(isMips64() ? Mips::LUi64 : Mips::LUi);
367 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
368 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter9d577c82012-10-04 04:03:53 +0000369 Instructions.push_back(tmpInst);
Jack Carter2490dc62012-10-06 00:53:28 +0000370 tmpInst.clear();
371 tmpInst.setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
372 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
373 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
374 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
375 tmpInst.setLoc(IDLoc);
Jack Carter9d577c82012-10-04 04:03:53 +0000376 Instructions.push_back(tmpInst);
377 }
378}
Jack Carter2490dc62012-10-06 00:53:28 +0000379
Jack Carter2f68b312012-10-09 23:29:45 +0000380void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
381 SmallVectorImpl<MCInst> &Instructions){
382 MCInst tmpInst;
383 const MCOperand &ImmOp = Inst.getOperand(2);
384 assert(ImmOp.isImm() && "expected immediate operand kind");
385 const MCOperand &SrcRegOp = Inst.getOperand(1);
386 assert(SrcRegOp.isReg() && "expected register operand kind");
387 const MCOperand &DstRegOp = Inst.getOperand(0);
388 assert(DstRegOp.isReg() && "expected register operand kind");
389 int ImmValue = ImmOp.getImm();
390 if ( -32768 <= ImmValue && ImmValue <= 65535) {
391 //for -32768 <= j <= 65535.
392 //la d,j(s) => addiu d,s,j
393 tmpInst.setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
394 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
395 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
396 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
397 Instructions.push_back(tmpInst);
398 } else {
399 //for any other value of j that is representable as a 32-bit integer.
400 //la d,j(s) => lui d,hi16(j)
401 // ori d,d,lo16(j)
402 // addu d,d,s
403 tmpInst.setOpcode(isMips64()?Mips::LUi64:Mips::LUi);
404 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
405 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
406 Instructions.push_back(tmpInst);
407 tmpInst.clear();
408 tmpInst.setOpcode(isMips64()?Mips::ORi64:Mips::ORi);
409 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
410 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
411 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
412 Instructions.push_back(tmpInst);
413 tmpInst.clear();
414 tmpInst.setOpcode(Mips::ADDu);
415 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
416 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
417 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
418 Instructions.push_back(tmpInst);
419 }
420}
421
422void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
423 SmallVectorImpl<MCInst> &Instructions){
424 MCInst tmpInst;
425 const MCOperand &ImmOp = Inst.getOperand(1);
426 assert(ImmOp.isImm() && "expected immediate operand kind");
427 const MCOperand &RegOp = Inst.getOperand(0);
428 assert(RegOp.isReg() && "expected register operand kind");
429 int ImmValue = ImmOp.getImm();
430 if ( -32768 <= ImmValue && ImmValue <= 65535) {
431 //for -32768 <= j <= 65535.
432 //la d,j => addiu d,$zero,j
433 tmpInst.setOpcode(Mips::ADDiu);
434 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
435 tmpInst.addOperand(
436 MCOperand::CreateReg(isMips64()?Mips::ZERO_64:Mips::ZERO));
437 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
438 Instructions.push_back(tmpInst);
439 } else {
440 //for any other value of j that is representable as a 32-bit integer.
441 //la d,j => lui d,hi16(j)
442 // ori d,d,lo16(j)
443 tmpInst.setOpcode(isMips64()?Mips::LUi64:Mips::LUi);
444 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
445 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
446 Instructions.push_back(tmpInst);
447 tmpInst.clear();
448 tmpInst.setOpcode(isMips64()?Mips::ORi64:Mips::ORi);
449 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
450 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
451 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
452 Instructions.push_back(tmpInst);
453 }
454}
455
Rafael Espindolafddf8042012-01-11 03:56:41 +0000456bool MipsAsmParser::
Chad Rosier84125ca2012-10-13 00:26:04 +0000457MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindolafddf8042012-01-11 03:56:41 +0000458 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier84125ca2012-10-13 00:26:04 +0000459 MCStreamer &Out, unsigned &ErrorInfo,
460 bool MatchingInlineAsm) {
Jack Carterec65be82012-09-05 23:34:03 +0000461 MCInst Inst;
Chad Rosier6e006d32012-10-12 22:53:36 +0000462 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier84125ca2012-10-13 00:26:04 +0000463 MatchingInlineAsm);
Jack Carterec65be82012-09-05 23:34:03 +0000464
465 switch (MatchResult) {
466 default: break;
467 case Match_Success: {
Jack Carter9d577c82012-10-04 04:03:53 +0000468 if (needsExpansion(Inst)) {
Jack Carter2490dc62012-10-06 00:53:28 +0000469 SmallVector<MCInst, 4> Instructions;
Jack Carter9d577c82012-10-04 04:03:53 +0000470 expandInstruction(Inst, IDLoc, Instructions);
471 for(unsigned i =0; i < Instructions.size(); i++){
Jack Carter2490dc62012-10-06 00:53:28 +0000472 Out.EmitInstruction(Instructions[i]);
Jack Carter9d577c82012-10-04 04:03:53 +0000473 }
474 } else {
475 Inst.setLoc(IDLoc);
476 Out.EmitInstruction(Inst);
477 }
Jack Carterec65be82012-09-05 23:34:03 +0000478 return false;
479 }
480 case Match_MissingFeature:
481 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
482 return true;
483 case Match_InvalidOperand: {
484 SMLoc ErrorLoc = IDLoc;
485 if (ErrorInfo != ~0U) {
486 if (ErrorInfo >= Operands.size())
487 return Error(IDLoc, "too few operands for instruction");
488
489 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
490 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
491 }
492
493 return Error(ErrorLoc, "invalid operand for instruction");
494 }
495 case Match_MnemonicFail:
496 return Error(IDLoc, "invalid instruction");
497 }
Rafael Espindolafddf8042012-01-11 03:56:41 +0000498 return true;
499}
500
Jack Carterec65be82012-09-05 23:34:03 +0000501int MipsAsmParser::matchRegisterName(StringRef Name) {
502
David Chisnall572e1bd2012-10-09 16:27:43 +0000503 int CC;
504 if (!isMips64())
505 CC = StringSwitch<unsigned>(Name)
506 .Case("zero", Mips::ZERO)
507 .Case("a0", Mips::A0)
508 .Case("a1", Mips::A1)
509 .Case("a2", Mips::A2)
510 .Case("a3", Mips::A3)
511 .Case("v0", Mips::V0)
512 .Case("v1", Mips::V1)
513 .Case("s0", Mips::S0)
514 .Case("s1", Mips::S1)
515 .Case("s2", Mips::S2)
516 .Case("s3", Mips::S3)
517 .Case("s4", Mips::S4)
518 .Case("s5", Mips::S5)
519 .Case("s6", Mips::S6)
520 .Case("s7", Mips::S7)
521 .Case("k0", Mips::K0)
522 .Case("k1", Mips::K1)
523 .Case("sp", Mips::SP)
524 .Case("fp", Mips::FP)
525 .Case("gp", Mips::GP)
526 .Case("ra", Mips::RA)
527 .Case("t0", Mips::T0)
528 .Case("t1", Mips::T1)
529 .Case("t2", Mips::T2)
530 .Case("t3", Mips::T3)
531 .Case("t4", Mips::T4)
532 .Case("t5", Mips::T5)
533 .Case("t6", Mips::T6)
534 .Case("t7", Mips::T7)
535 .Case("t8", Mips::T8)
536 .Case("t9", Mips::T9)
537 .Case("at", Mips::AT)
538 .Case("fcc0", Mips::FCC0)
539 .Default(-1);
540 else
541 CC = StringSwitch<unsigned>(Name)
542 .Case("zero", Mips::ZERO_64)
543 .Case("at", Mips::AT_64)
544 .Case("v0", Mips::V0_64)
545 .Case("v1", Mips::V1_64)
546 .Case("a0", Mips::A0_64)
547 .Case("a1", Mips::A1_64)
548 .Case("a2", Mips::A2_64)
549 .Case("a3", Mips::A3_64)
550 .Case("a4", Mips::T0_64)
551 .Case("a5", Mips::T1_64)
552 .Case("a6", Mips::T2_64)
553 .Case("a7", Mips::T3_64)
554 .Case("t4", Mips::T4_64)
555 .Case("t5", Mips::T5_64)
556 .Case("t6", Mips::T6_64)
557 .Case("t7", Mips::T7_64)
558 .Case("s0", Mips::S0_64)
559 .Case("s1", Mips::S1_64)
560 .Case("s2", Mips::S2_64)
561 .Case("s3", Mips::S3_64)
562 .Case("s4", Mips::S4_64)
563 .Case("s5", Mips::S5_64)
564 .Case("s6", Mips::S6_64)
565 .Case("s7", Mips::S7_64)
566 .Case("t8", Mips::T8_64)
567 .Case("t9", Mips::T9_64)
568 .Case("kt0", Mips::K0_64)
569 .Case("kt1", Mips::K1_64)
570 .Case("gp", Mips::GP_64)
571 .Case("sp", Mips::SP_64)
572 .Case("fp", Mips::FP_64)
573 .Case("s8", Mips::FP_64)
574 .Case("ra", Mips::RA_64)
575 .Default(-1);
Jack Carterec65be82012-09-05 23:34:03 +0000576
David Chisnall572e1bd2012-10-09 16:27:43 +0000577 if (CC != -1)
Jack Carterec65be82012-09-05 23:34:03 +0000578 return CC;
Jack Carterec65be82012-09-05 23:34:03 +0000579
Jack Carterf740d6e2012-09-07 00:23:42 +0000580 if (Name[0] == 'f') {
581 StringRef NumString = Name.substr(1);
582 unsigned IntVal;
583 if( NumString.getAsInteger(10, IntVal))
Jack Carter9d577c82012-10-04 04:03:53 +0000584 return -1; // not integer
Jack Carterf740d6e2012-09-07 00:23:42 +0000585 if (IntVal > 31)
586 return -1;
587
588 FpFormatTy Format = getFpFormat();
589
590 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
591 return getReg(Mips::FGR32RegClassID, IntVal);
592 if (Format == FP_FORMAT_D) {
593 if(isFP64()) {
594 return getReg(Mips::FGR64RegClassID, IntVal);
595 }
Jack Carter9d577c82012-10-04 04:03:53 +0000596 // only even numbers available as register pairs
Jack Carterf740d6e2012-09-07 00:23:42 +0000597 if (( IntVal > 31) || (IntVal%2 != 0))
598 return -1;
599 return getReg(Mips::AFGR64RegClassID, IntVal/2);
600 }
601 }
602
Jack Carterec65be82012-09-05 23:34:03 +0000603 return -1;
604}
Jack Carterf740d6e2012-09-07 00:23:42 +0000605void MipsAsmParser::setDefaultFpFormat() {
606
607 if (isMips64() || isFP64())
608 FpFormat = FP_FORMAT_D;
609 else
610 FpFormat = FP_FORMAT_S;
611}
612
613bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
614
615 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
616 .Case("ldxc1", true)
617 .Case("ldc1", true)
618 .Case("sdxc1", true)
619 .Case("sdc1", true)
620 .Default(false);
621
622 return IsDouble;
623}
624void MipsAsmParser::setFpFormat(StringRef Format) {
625
626 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
627 .Case(".s", FP_FORMAT_S)
628 .Case(".d", FP_FORMAT_D)
629 .Case(".l", FP_FORMAT_L)
630 .Case(".w", FP_FORMAT_W)
631 .Default(FP_FORMAT_NONE);
632}
Jack Carterec65be82012-09-05 23:34:03 +0000633
Jack Carter30116cd2012-10-04 02:29:46 +0000634bool MipsAssemblerOptions::setATReg(unsigned Reg) {
635 if (Reg > 31)
636 return false;
637
638 aTReg = Reg;
639 return true;
640}
641
642unsigned MipsAsmParser::getATReg() {
Jack Carter10d5ff62012-10-05 23:55:28 +0000643 unsigned Reg = Options.getATRegNum();
Jack Carter30116cd2012-10-04 02:29:46 +0000644 if (isMips64())
645 return getReg(Mips::CPU64RegsRegClassID,Reg);
Jack Carter10d5ff62012-10-05 23:55:28 +0000646
647 return getReg(Mips::CPURegsRegClassID,Reg);
Jack Carter30116cd2012-10-04 02:29:46 +0000648}
649
650unsigned MipsAsmParser::getReg(int RC,int RegNo) {
Jack Carterec65be82012-09-05 23:34:03 +0000651 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
652}
653
Jack Carter30116cd2012-10-04 02:29:46 +0000654int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
Jack Carterec65be82012-09-05 23:34:03 +0000655
656 if (Mnemonic.lower() == "rdhwr") {
Jack Carter9d577c82012-10-04 04:03:53 +0000657 // at the moment only hwreg29 is supported
Jack Carterec65be82012-09-05 23:34:03 +0000658 if (RegNum != 29)
659 return -1;
660 return Mips::HWR29;
661 }
662
663 if (RegNum > 31)
664 return -1;
665
David Chisnall572e1bd2012-10-09 16:27:43 +0000666 // MIPS64 registers are numbered 1 after the 32-bit equivalents
667 return getReg(Mips::CPURegsRegClassID, RegNum) + isMips64();
Jack Carterec65be82012-09-05 23:34:03 +0000668}
669
670int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
671 const AsmToken &Tok = Parser.getTok();
672 int RegNum = -1;
673
674 if (Tok.is(AsmToken::Identifier)) {
675 std::string lowerCase = Tok.getString().lower();
676 RegNum = matchRegisterName(lowerCase);
677 } else if (Tok.is(AsmToken::Integer))
Jack Carter9d577c82012-10-04 04:03:53 +0000678 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carter6b96c3f2012-09-06 20:00:02 +0000679 Mnemonic.lower());
Jack Carterf740d6e2012-09-07 00:23:42 +0000680 else
681 return RegNum; //error
Jack Carter9d577c82012-10-04 04:03:53 +0000682 // 64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
Jack Carterf740d6e2012-09-07 00:23:42 +0000683 if (isMips64() && RegNum == Mips::ZERO_64) {
684 if (Mnemonic.find("ddiv") != StringRef::npos)
685 RegNum = Mips::ZERO;
686 }
Jack Carterec65be82012-09-05 23:34:03 +0000687 return RegNum;
688}
689
Rafael Espindolafddf8042012-01-11 03:56:41 +0000690bool MipsAsmParser::
Jack Carterec65be82012-09-05 23:34:03 +0000691 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
692 StringRef Mnemonic){
693
694 SMLoc S = Parser.getTok().getLoc();
Jordan Rose3ebe59c2013-01-07 19:00:49 +0000695 SMLoc E = Parser.getTok().getEndLoc();
Jack Carterec65be82012-09-05 23:34:03 +0000696 int RegNo = -1;
Jack Carterf740d6e2012-09-07 00:23:42 +0000697
Jack Carter9d577c82012-10-04 04:03:53 +0000698 // FIXME: we should make a more generic method for CCR
Jack Carterf740d6e2012-09-07 00:23:42 +0000699 if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
700 && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
Jack Carter9d577c82012-10-04 04:03:53 +0000701 RegNo = Parser.getTok().getIntVal(); // get the int value
702 // at the moment only fcc0 is supported
Jack Carterf740d6e2012-09-07 00:23:42 +0000703 if (RegNo == 0)
704 RegNo = Mips::FCC0;
705 } else
706 RegNo = tryParseRegister(Mnemonic);
Jack Carterec65be82012-09-05 23:34:03 +0000707 if (RegNo == -1)
708 return true;
709
Jordan Rose3ebe59c2013-01-07 19:00:49 +0000710 Operands.push_back(MipsOperand::CreateReg(RegNo, S, E));
Jack Carterec65be82012-09-05 23:34:03 +0000711 Parser.Lex(); // Eat register token.
712 return false;
713}
714
715bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
716 StringRef Mnemonic) {
Jack Carter9d577c82012-10-04 04:03:53 +0000717 // Check if the current operand has a custom associated parser, if so, try to
718 // custom parse the operand, or fallback to the general approach.
Jack Carterec65be82012-09-05 23:34:03 +0000719 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
720 if (ResTy == MatchOperand_Success)
721 return false;
722 // If there wasn't a custom match, try the generic matcher below. Otherwise,
723 // there was a match, but an error occurred, in which case, just return that
724 // the operand parsing failed.
725 if (ResTy == MatchOperand_ParseFail)
726 return true;
727
728 switch (getLexer().getKind()) {
729 default:
730 Error(Parser.getTok().getLoc(), "unexpected token in operand");
731 return true;
732 case AsmToken::Dollar: {
Jack Carter9d577c82012-10-04 04:03:53 +0000733 // parse register
Jack Carterec65be82012-09-05 23:34:03 +0000734 SMLoc S = Parser.getTok().getLoc();
735 Parser.Lex(); // Eat dollar token.
Jack Carter9d577c82012-10-04 04:03:53 +0000736 // parse register operand
737 if (!tryParseRegisterOperand(Operands, Mnemonic)) {
Jack Carterec65be82012-09-05 23:34:03 +0000738 if (getLexer().is(AsmToken::LParen)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000739 // check if it is indexed addressing operand
Jack Carterec65be82012-09-05 23:34:03 +0000740 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carter9d577c82012-10-04 04:03:53 +0000741 Parser.Lex(); // eat parenthesis
Jack Carterec65be82012-09-05 23:34:03 +0000742 if (getLexer().isNot(AsmToken::Dollar))
743 return true;
744
Jack Carter9d577c82012-10-04 04:03:53 +0000745 Parser.Lex(); // eat dollar
746 if (tryParseRegisterOperand(Operands, Mnemonic))
Jack Carterec65be82012-09-05 23:34:03 +0000747 return true;
748
749 if (!getLexer().is(AsmToken::RParen))
750 return true;
751
752 S = Parser.getTok().getLoc();
753 Operands.push_back(MipsOperand::CreateToken(")", S));
754 Parser.Lex();
755 }
756 return false;
757 }
Jack Carter9d577c82012-10-04 04:03:53 +0000758 // maybe it is a symbol reference
Jack Carterec65be82012-09-05 23:34:03 +0000759 StringRef Identifier;
760 if (Parser.ParseIdentifier(Identifier))
761 return true;
762
Jordan Rose3ebe59c2013-01-07 19:00:49 +0000763 SMLoc E = SMLoc::getFromPointer(Identifier.end());
Jack Carterec65be82012-09-05 23:34:03 +0000764
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000765 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterec65be82012-09-05 23:34:03 +0000766
767 // Otherwise create a symbol ref.
Jack Carter6b96c3f2012-09-06 20:00:02 +0000768 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterec65be82012-09-05 23:34:03 +0000769 getContext());
770
771 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
772 return false;
773 }
774 case AsmToken::Identifier:
775 case AsmToken::LParen:
776 case AsmToken::Minus:
777 case AsmToken::Plus:
778 case AsmToken::Integer:
779 case AsmToken::String: {
780 // quoted label names
781 const MCExpr *IdVal;
782 SMLoc S = Parser.getTok().getLoc();
Jordan Rose3ebe59c2013-01-07 19:00:49 +0000783 SMLoc E;
784 if (getParser().ParseExpression(IdVal, E))
Jack Carterec65be82012-09-05 23:34:03 +0000785 return true;
Jack Carterec65be82012-09-05 23:34:03 +0000786 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
787 return false;
788 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000789 case AsmToken::Percent: {
Jack Carter9d577c82012-10-04 04:03:53 +0000790 // it is a symbol reference or constant expression
Jack Carter6b96c3f2012-09-06 20:00:02 +0000791 const MCExpr *IdVal;
Jack Carter9d577c82012-10-04 04:03:53 +0000792 SMLoc S = Parser.getTok().getLoc(); // start location of the operand
Jordan Rose3ebe59c2013-01-07 19:00:49 +0000793 SMLoc E;
794 if (parseRelocOperand(IdVal, E))
Jack Carter6b96c3f2012-09-06 20:00:02 +0000795 return true;
796
Jack Carter6b96c3f2012-09-06 20:00:02 +0000797 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
798 return false;
Jack Carter30116cd2012-10-04 02:29:46 +0000799 } // case AsmToken::Percent
800 } // switch(getLexer().getKind())
Rafael Espindolafddf8042012-01-11 03:56:41 +0000801 return true;
802}
803
Jordan Rose3ebe59c2013-01-07 19:00:49 +0000804bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res, SMLoc &EndLoc) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000805
Jack Carter30116cd2012-10-04 02:29:46 +0000806 Parser.Lex(); // eat % token
Jack Carter9d577c82012-10-04 04:03:53 +0000807 const AsmToken &Tok = Parser.getTok(); // get next token, operation
Jack Carter6b96c3f2012-09-06 20:00:02 +0000808 if (Tok.isNot(AsmToken::Identifier))
809 return true;
810
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000811 std::string Str = Tok.getIdentifier().str();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000812
Jack Carter9d577c82012-10-04 04:03:53 +0000813 Parser.Lex(); // eat identifier
Jack Carter30116cd2012-10-04 02:29:46 +0000814 // now make expression from the rest of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000815 const MCExpr *IdVal;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000816
817 if (getLexer().getKind() == AsmToken::LParen) {
818 while (1) {
Jack Carter30116cd2012-10-04 02:29:46 +0000819 Parser.Lex(); // eat '(' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000820 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carter30116cd2012-10-04 02:29:46 +0000821 Parser.Lex(); // eat % token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000822 const AsmToken &nextTok = Parser.getTok();
823 if (nextTok.isNot(AsmToken::Identifier))
824 return true;
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000825 Str += "(%";
826 Str += nextTok.getIdentifier();
Jack Carter30116cd2012-10-04 02:29:46 +0000827 Parser.Lex(); // eat identifier
Jack Carter6b96c3f2012-09-06 20:00:02 +0000828 if (getLexer().getKind() != AsmToken::LParen)
829 return true;
830 } else
831 break;
832 }
833 if (getParser().ParseParenExpression(IdVal,EndLoc))
834 return true;
835
Jordan Rose3ebe59c2013-01-07 19:00:49 +0000836 while (getLexer().getKind() == AsmToken::RParen) {
837 EndLoc = Parser.getTok().getEndLoc();
Jack Carter30116cd2012-10-04 02:29:46 +0000838 Parser.Lex(); // eat ')' token
Jordan Rose3ebe59c2013-01-07 19:00:49 +0000839 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000840
841 } else
Jack Carter30116cd2012-10-04 02:29:46 +0000842 return true; // parenthesis must follow reloc operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000843
Jack Carter30116cd2012-10-04 02:29:46 +0000844 // Check the type of the expression
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000845 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000846 // it's a constant, evaluate lo or hi value
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000847 int Val = MCE->getValue();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000848 if (Str == "lo") {
849 Val = Val & 0xffff;
850 } else if (Str == "hi") {
851 Val = (Val & 0xffff0000) >> 16;
852 }
853 Res = MCConstantExpr::Create(Val, getContext());
854 return false;
855 }
856
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000857 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter30116cd2012-10-04 02:29:46 +0000858 // it's a symbol, create symbolic expression from symbol
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000859 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000860 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
861 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
862 return false;
863 }
864 return true;
865}
866
Jack Carterec65be82012-09-05 23:34:03 +0000867bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
868 SMLoc &EndLoc) {
869
870 StartLoc = Parser.getTok().getLoc();
Jordan Rose3ebe59c2013-01-07 19:00:49 +0000871 EndLoc = Parser.getTok().getEndLoc();
Jack Carterec65be82012-09-05 23:34:03 +0000872 RegNo = tryParseRegister("");
Jack Carterec65be82012-09-05 23:34:03 +0000873 return (RegNo == (unsigned)-1);
874}
875
Jack Carter6b96c3f2012-09-06 20:00:02 +0000876bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000877 switch(getLexer().getKind()) {
878 default:
879 return true;
880 case AsmToken::Integer:
881 case AsmToken::Minus:
882 case AsmToken::Plus:
Jordan Rose3ebe59c2013-01-07 19:00:49 +0000883 return getParser().ParseExpression(Res);
884 case AsmToken::Percent: {
885 SMLoc E;
886 return parseRelocOperand(Res, E);
887 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000888 case AsmToken::LParen:
Jack Carter30116cd2012-10-04 02:29:46 +0000889 return false; // it's probably assuming 0
Jack Carter6b96c3f2012-09-06 20:00:02 +0000890 }
891 return true;
892}
893
Jack Carterec65be82012-09-05 23:34:03 +0000894MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
895 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000896
897 const MCExpr *IdVal = 0;
Jordan Rose3ebe59c2013-01-07 19:00:49 +0000898 SMLoc S = Parser.getTok().getLoc();
899 SMLoc E = Parser.getTok().getEndLoc();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000900
901 if (parseMemOffset(IdVal))
902 return MatchOperand_ParseFail;
903
Jack Carter30116cd2012-10-04 02:29:46 +0000904 const AsmToken &Tok = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000905 if (Tok.isNot(AsmToken::LParen)) {
Jack Carter2f68b312012-10-09 23:29:45 +0000906 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
907 if (Mnemonic->getToken() == "la") {
Jack Carter2f68b312012-10-09 23:29:45 +0000908 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
909 return MatchOperand_Success;
910 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000911 Error(Parser.getTok().getLoc(), "'(' expected");
912 return MatchOperand_ParseFail;
913 }
914
915 Parser.Lex(); // Eat '(' token.
916
Jack Carter2f68b312012-10-09 23:29:45 +0000917 const AsmToken &Tok1 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000918 if (Tok1.is(AsmToken::Dollar)) {
919 Parser.Lex(); // Eat '$' token.
920 if (tryParseRegisterOperand(Operands,"")) {
921 Error(Parser.getTok().getLoc(), "unexpected token in operand");
922 return MatchOperand_ParseFail;
923 }
924
925 } else {
Jack Carter30116cd2012-10-04 02:29:46 +0000926 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carter6b96c3f2012-09-06 20:00:02 +0000927 return MatchOperand_ParseFail;
928 }
929
Jack Carter30116cd2012-10-04 02:29:46 +0000930 const AsmToken &Tok2 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000931 if (Tok2.isNot(AsmToken::RParen)) {
932 Error(Parser.getTok().getLoc(), "')' expected");
933 return MatchOperand_ParseFail;
934 }
935
Jordan Rose3ebe59c2013-01-07 19:00:49 +0000936 E = Parser.getTok().getEndLoc();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000937 Parser.Lex(); // Eat ')' token.
938
939 if (IdVal == 0)
940 IdVal = MCConstantExpr::Create(0, getContext());
941
Jack Carter30116cd2012-10-04 02:29:46 +0000942 // now replace register operand with the mem operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000943 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
944 int RegNo = op->getReg();
Jack Carter30116cd2012-10-04 02:29:46 +0000945 // remove register from operands
Jack Carter6b96c3f2012-09-06 20:00:02 +0000946 Operands.pop_back();
Jack Carter30116cd2012-10-04 02:29:46 +0000947 // and add memory operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000948 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
949 delete op;
Jack Carterec65be82012-09-05 23:34:03 +0000950 return MatchOperand_Success;
951}
952
Jack Carter6b96c3f2012-09-06 20:00:02 +0000953MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
954
955 MCSymbolRefExpr::VariantKind VK
956 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
957 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
958 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
959 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
960 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
961 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
962 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
963 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
964 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
965 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
966 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
967 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
968 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
969 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
970 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
971 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
972 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
973 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
974 .Default(MCSymbolRefExpr::VK_None);
975
976 return VK;
977}
978
Benjamin Kramer1ac45872012-09-10 11:52:14 +0000979static int ConvertCcString(StringRef CondString) {
Jack Carterf740d6e2012-09-07 00:23:42 +0000980 int CC = StringSwitch<unsigned>(CondString)
981 .Case(".f", 0)
982 .Case(".un", 1)
983 .Case(".eq", 2)
984 .Case(".ueq", 3)
985 .Case(".olt", 4)
986 .Case(".ult", 5)
987 .Case(".ole", 6)
988 .Case(".ule", 7)
989 .Case(".sf", 8)
990 .Case(".ngle", 9)
991 .Case(".seq", 10)
992 .Case(".ngl", 11)
993 .Case(".lt", 12)
994 .Case(".nge", 13)
995 .Case(".le", 14)
996 .Case(".ngt", 15)
997 .Default(-1);
998
999 return CC;
1000}
1001
1002bool MipsAsmParser::
1003parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter30116cd2012-10-04 02:29:46 +00001004 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1005 // split the format
Jack Carterf740d6e2012-09-07 00:23:42 +00001006 size_t Start = Name.find('.'), Next = Name.rfind('.');
1007 StringRef Format1 = Name.slice(Start, Next);
Jack Carter30116cd2012-10-04 02:29:46 +00001008 // and add the first format to the operands
Jack Carterf740d6e2012-09-07 00:23:42 +00001009 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carter30116cd2012-10-04 02:29:46 +00001010 // now for the second format
Jack Carterf740d6e2012-09-07 00:23:42 +00001011 StringRef Format2 = Name.slice(Next, StringRef::npos);
1012 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1013
Jack Carter30116cd2012-10-04 02:29:46 +00001014 // set the format for the first register
Jack Carterf740d6e2012-09-07 00:23:42 +00001015 setFpFormat(Format1);
1016
1017 // Read the remaining operands.
1018 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1019 // Read the first operand.
1020 if (ParseOperand(Operands, Name)) {
1021 SMLoc Loc = getLexer().getLoc();
1022 Parser.EatToEndOfStatement();
1023 return Error(Loc, "unexpected token in argument list");
1024 }
1025
1026 if (getLexer().isNot(AsmToken::Comma)) {
1027 SMLoc Loc = getLexer().getLoc();
1028 Parser.EatToEndOfStatement();
1029 return Error(Loc, "unexpected token in argument list");
1030
1031 }
1032 Parser.Lex(); // Eat the comma.
1033
1034 //set the format for the first register
1035 setFpFormat(Format2);
1036
1037 // Parse and remember the operand.
1038 if (ParseOperand(Operands, Name)) {
1039 SMLoc Loc = getLexer().getLoc();
1040 Parser.EatToEndOfStatement();
1041 return Error(Loc, "unexpected token in argument list");
1042 }
1043 }
1044
1045 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1046 SMLoc Loc = getLexer().getLoc();
1047 Parser.EatToEndOfStatement();
1048 return Error(Loc, "unexpected token in argument list");
1049 }
1050
1051 Parser.Lex(); // Consume the EndOfStatement
1052 return false;
1053}
1054
Rafael Espindolafddf8042012-01-11 03:56:41 +00001055bool MipsAsmParser::
Chad Rosier6a020a72012-10-25 20:41:34 +00001056ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindolafddf8042012-01-11 03:56:41 +00001057 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter30116cd2012-10-04 02:29:46 +00001058 // floating point instructions: should register be treated as double?
Jack Carterf740d6e2012-09-07 00:23:42 +00001059 if (requestsDoubleOperand(Name)) {
1060 setFpFormat(FP_FORMAT_D);
Jack Carterec65be82012-09-05 23:34:03 +00001061 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterf740d6e2012-09-07 00:23:42 +00001062 }
1063 else {
1064 setDefaultFpFormat();
1065 // Create the leading tokens for the mnemonic, split by '.' characters.
1066 size_t Start = 0, Next = Name.find('.');
1067 StringRef Mnemonic = Name.slice(Start, Next);
1068
1069 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1070
1071 if (Next != StringRef::npos) {
Jack Carter30116cd2012-10-04 02:29:46 +00001072 // there is a format token in mnemonic
1073 // StringRef Rest = Name.slice(Next, StringRef::npos);
Jack Carterf740d6e2012-09-07 00:23:42 +00001074 size_t Dot = Name.find('.', Next+1);
1075 StringRef Format = Name.slice(Next, Dot);
1076 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1077 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1078 else {
1079 if (Name.startswith("c.")){
1080 // floating point compare, add '.' and immediate represent for cc
1081 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1082 int Cc = ConvertCcString(Format);
1083 if (Cc == -1) {
1084 return Error(NameLoc, "Invalid conditional code");
1085 }
Jordan Rose3ebe59c2013-01-07 19:00:49 +00001086 // FIXME: May include trailing whitespace...
1087 SMLoc E = Parser.getTok().getLoc();
Jack Carterf740d6e2012-09-07 00:23:42 +00001088 Operands.push_back(MipsOperand::CreateImm(
1089 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1090 } else {
Jack Carter30116cd2012-10-04 02:29:46 +00001091 // trunc, ceil, floor ...
Jack Carterf740d6e2012-09-07 00:23:42 +00001092 return parseMathOperation(Name, NameLoc, Operands);
1093 }
1094
Jack Carter30116cd2012-10-04 02:29:46 +00001095 // the rest is a format
Jack Carterf740d6e2012-09-07 00:23:42 +00001096 Format = Name.slice(Dot, StringRef::npos);
1097 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1098 }
1099
1100 setFpFormat(Format);
1101 }
1102 }
Jack Carterec65be82012-09-05 23:34:03 +00001103
1104 // Read the remaining operands.
1105 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1106 // Read the first operand.
1107 if (ParseOperand(Operands, Name)) {
1108 SMLoc Loc = getLexer().getLoc();
1109 Parser.EatToEndOfStatement();
1110 return Error(Loc, "unexpected token in argument list");
1111 }
1112
1113 while (getLexer().is(AsmToken::Comma) ) {
1114 Parser.Lex(); // Eat the comma.
1115
1116 // Parse and remember the operand.
1117 if (ParseOperand(Operands, Name)) {
1118 SMLoc Loc = getLexer().getLoc();
1119 Parser.EatToEndOfStatement();
1120 return Error(Loc, "unexpected token in argument list");
1121 }
1122 }
1123 }
1124
1125 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1126 SMLoc Loc = getLexer().getLoc();
1127 Parser.EatToEndOfStatement();
1128 return Error(Loc, "unexpected token in argument list");
1129 }
1130
1131 Parser.Lex(); // Consume the EndOfStatement
1132 return false;
Rafael Espindolafddf8042012-01-11 03:56:41 +00001133}
1134
Jack Carter30116cd2012-10-04 02:29:46 +00001135bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1136 SMLoc Loc = getLexer().getLoc();
1137 Parser.EatToEndOfStatement();
1138 return Error(Loc, ErrorMsg);
1139}
1140
1141bool MipsAsmParser::parseSetNoAtDirective() {
1142 // line should look like:
1143 // .set noat
1144 // set at reg to 0
Jack Carter10d5ff62012-10-05 23:55:28 +00001145 Options.setATReg(0);
Jack Carter30116cd2012-10-04 02:29:46 +00001146 // eat noat
1147 Parser.Lex();
1148 // if this is not the end of the statement, report error
1149 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1150 reportParseError("unexpected token in statement");
1151 return false;
1152 }
1153 Parser.Lex(); // Consume the EndOfStatement
1154 return false;
1155}
1156bool MipsAsmParser::parseSetAtDirective() {
1157 // line can be
1158 // .set at - defaults to $1
1159 // or .set at=$reg
1160 getParser().Lex();
1161 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter10d5ff62012-10-05 23:55:28 +00001162 Options.setATReg(1);
Jack Carter30116cd2012-10-04 02:29:46 +00001163 Parser.Lex(); // Consume the EndOfStatement
1164 return false;
1165 } else if (getLexer().is(AsmToken::Equal)) {
1166 getParser().Lex(); //eat '='
1167 if (getLexer().isNot(AsmToken::Dollar)) {
1168 reportParseError("unexpected token in statement");
1169 return false;
1170 }
1171 Parser.Lex(); // eat '$'
1172 if (getLexer().isNot(AsmToken::Integer)) {
1173 reportParseError("unexpected token in statement");
1174 return false;
1175 }
1176 const AsmToken &Reg = Parser.getTok();
Jack Carter10d5ff62012-10-05 23:55:28 +00001177 if (!Options.setATReg(Reg.getIntVal())) {
Jack Carter30116cd2012-10-04 02:29:46 +00001178 reportParseError("unexpected token in statement");
1179 return false;
1180 }
1181 getParser().Lex(); //eat reg
1182
1183 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1184 reportParseError("unexpected token in statement");
1185 return false;
1186 }
1187 Parser.Lex(); // Consume the EndOfStatement
1188 return false;
1189 } else {
1190 reportParseError("unexpected token in statement");
1191 return false;
1192 }
1193}
1194
1195bool MipsAsmParser::parseSetReorderDirective() {
1196 Parser.Lex();
1197 // if this is not the end of the statement, report error
1198 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1199 reportParseError("unexpected token in statement");
1200 return false;
1201 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001202 Options.setReorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001203 Parser.Lex(); // Consume the EndOfStatement
1204 return false;
1205}
1206
1207bool MipsAsmParser::parseSetNoReorderDirective() {
1208 Parser.Lex();
1209 // if this is not the end of the statement, report error
1210 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1211 reportParseError("unexpected token in statement");
1212 return false;
1213 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001214 Options.setNoreorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001215 Parser.Lex(); // Consume the EndOfStatement
1216 return false;
1217}
1218
1219bool MipsAsmParser::parseSetMacroDirective() {
1220 Parser.Lex();
1221 // if this is not the end of the statement, report error
1222 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1223 reportParseError("unexpected token in statement");
1224 return false;
1225 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001226 Options.setMacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001227 Parser.Lex(); // Consume the EndOfStatement
1228 return false;
1229}
1230
1231bool MipsAsmParser::parseSetNoMacroDirective() {
1232 Parser.Lex();
1233 // if this is not the end of the statement, report error
1234 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1235 reportParseError("`noreorder' must be set before `nomacro'");
1236 return false;
1237 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001238 if (Options.isReorder()) {
Jack Carter30116cd2012-10-04 02:29:46 +00001239 reportParseError("`noreorder' must be set before `nomacro'");
1240 return false;
1241 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001242 Options.setNomacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001243 Parser.Lex(); // Consume the EndOfStatement
1244 return false;
1245}
1246bool MipsAsmParser::parseDirectiveSet() {
1247
1248 // get next token
1249 const AsmToken &Tok = Parser.getTok();
1250
1251 if (Tok.getString() == "noat") {
1252 return parseSetNoAtDirective();
1253 } else if (Tok.getString() == "at") {
1254 return parseSetAtDirective();
1255 } else if (Tok.getString() == "reorder") {
1256 return parseSetReorderDirective();
1257 } else if (Tok.getString() == "noreorder") {
1258 return parseSetNoReorderDirective();
1259 } else if (Tok.getString() == "macro") {
1260 return parseSetMacroDirective();
1261 } else if (Tok.getString() == "nomacro") {
1262 return parseSetNoMacroDirective();
1263 } else if (Tok.getString() == "nomips16") {
1264 // ignore this directive for now
1265 Parser.EatToEndOfStatement();
1266 return false;
1267 } else if (Tok.getString() == "nomicromips") {
1268 // ignore this directive for now
1269 Parser.EatToEndOfStatement();
1270 return false;
1271 }
1272 return true;
1273}
1274
1275bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carteracbea452012-09-07 00:48:02 +00001276
1277 if (DirectiveID.getString() == ".ent") {
Jack Carter30116cd2012-10-04 02:29:46 +00001278 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001279 Parser.Lex();
1280 return false;
1281 }
1282
1283 if (DirectiveID.getString() == ".end") {
Jack Carter30116cd2012-10-04 02:29:46 +00001284 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001285 Parser.Lex();
1286 return false;
1287 }
1288
1289 if (DirectiveID.getString() == ".frame") {
Jack Carter30116cd2012-10-04 02:29:46 +00001290 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001291 Parser.EatToEndOfStatement();
1292 return false;
1293 }
1294
1295 if (DirectiveID.getString() == ".set") {
Jack Carter30116cd2012-10-04 02:29:46 +00001296 return parseDirectiveSet();
Jack Carteracbea452012-09-07 00:48:02 +00001297 }
1298
1299 if (DirectiveID.getString() == ".fmask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001300 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001301 Parser.EatToEndOfStatement();
1302 return false;
1303 }
1304
1305 if (DirectiveID.getString() == ".mask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001306 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001307 Parser.EatToEndOfStatement();
1308 return false;
1309 }
1310
1311 if (DirectiveID.getString() == ".gpword") {
Jack Carter30116cd2012-10-04 02:29:46 +00001312 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001313 Parser.EatToEndOfStatement();
1314 return false;
1315 }
1316
Rafael Espindolafddf8042012-01-11 03:56:41 +00001317 return true;
1318}
1319
Rafael Espindolafddf8042012-01-11 03:56:41 +00001320extern "C" void LLVMInitializeMipsAsmParser() {
1321 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1322 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1323 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1324 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1325}
Jack Carterec65be82012-09-05 23:34:03 +00001326
1327#define GET_REGISTER_MATCHER
1328#define GET_MATCHER_IMPLEMENTATION
1329#include "MipsGenAsmMatcher.inc"