blob: d06877f9453d8f4a78c89a14d54d75e68995e309 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-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 Carterb4dbc172012-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 Carruthed0881b2012-12-03 16:50:05 +000016#include "llvm/MC/MCParser/MCAsmLexer.h"
17#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCSubtargetInfo.h"
20#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000021#include "llvm/MC/MCTargetAsmParser.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000022#include "llvm/Support/TargetRegistry.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000023
24using namespace llvm;
25
26namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000027class MipsAssemblerOptions {
28public:
29 MipsAssemblerOptions():
30 aTReg(1), reorder(true), macro(true) {
31 }
Jack Carterb4dbc172012-09-05 23:34:03 +000032
Jack Carter0b744b32012-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 Espindola870c4e92012-01-11 03:56:41 +000052class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka7605630c2012-08-17 20:16:42 +000053
Jack Cartera63b16a2012-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 Carterb4dbc172012-09-05 23:34:03 +000062 MCSubtargetInfo &STI;
63 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000064 MipsAssemblerOptions Options;
Jack Carter0b744b32012-10-04 02:29:46 +000065
Jack Carterb4dbc172012-09-05 23:34:03 +000066
Akira Hatanaka7605630c2012-08-17 20:16:42 +000067#define GET_ASSEMBLER_HEADER
68#include "MipsGenAsmMatcher.inc"
69
Chad Rosier49963552012-10-13 00:26:04 +000070 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +000071 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +000072 MCStreamer &Out, unsigned &ErrorInfo,
73 bool MatchingInlineAsm);
Rafael Espindola870c4e92012-01-11 03:56:41 +000074
75 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
76
Chad Rosierf0e87202012-10-25 20:41:34 +000077 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
78 SMLoc NameLoc,
Akira Hatanaka7605630c2012-08-17 20:16:42 +000079 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindola870c4e92012-01-11 03:56:41 +000080
Jack Cartera63b16a2012-09-07 00:23:42 +000081 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
82 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
83
Rafael Espindola870c4e92012-01-11 03:56:41 +000084 bool ParseDirective(AsmToken DirectiveID);
85
Jack Carterb4dbc172012-09-05 23:34:03 +000086 MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +000087 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
88
89 MipsAsmParser::OperandMatchResultTy
90 parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
91
92 MipsAsmParser::OperandMatchResultTy
93 parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
94
95 MipsAsmParser::OperandMatchResultTy
96 parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
97
98 MipsAsmParser::OperandMatchResultTy
99 parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
100
101 MipsAsmParser::OperandMatchResultTy
102 parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Chad Rosier391d29972012-09-03 18:47:45 +0000103
Jack Carterd76b2372013-03-21 21:44:16 +0000104 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
105 unsigned RegisterClass);
106
Jack Carterb4dbc172012-09-05 23:34:03 +0000107 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
108 StringRef Mnemonic);
109
Jack Carter873c7242013-01-12 01:03:14 +0000110 int tryParseRegister(bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000111
112 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carter873c7242013-01-12 01:03:14 +0000113 bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000114
Jack Carter30a59822012-10-04 04:03:53 +0000115 bool needsExpansion(MCInst &Inst);
116
117 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000118 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000119 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000120 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000121 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
122 SmallVectorImpl<MCInst> &Instructions);
123 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
124 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000125 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
126 SmallVectorImpl<MCInst> &Instructions,
127 bool isLoad,bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000128 bool reportParseError(StringRef ErrorMsg);
129
Jack Carterb5cf5902013-04-17 00:18:04 +0000130 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000131 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000132
Jack Carterb5cf5902013-04-17 00:18:04 +0000133 const MCExpr* evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
134
135 bool isEvaluated(const MCExpr *Expr);
Jack Carter0b744b32012-10-04 02:29:46 +0000136 bool parseDirectiveSet();
137
138 bool parseSetAtDirective();
139 bool parseSetNoAtDirective();
140 bool parseSetMacroDirective();
141 bool parseSetNoMacroDirective();
142 bool parseSetReorderDirective();
143 bool parseSetNoReorderDirective();
144
Jack Carterd76b2372013-03-21 21:44:16 +0000145 bool parseSetAssignment();
146
Jack Carter07c818d2013-01-25 01:31:34 +0000147 bool parseDirectiveWord(unsigned Size, SMLoc L);
148
Jack Carterdc1e35d2012-09-06 20:00:02 +0000149 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000150
Jack Carterb4dbc172012-09-05 23:34:03 +0000151 bool isMips64() const {
152 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
153 }
154
Jack Cartera63b16a2012-09-07 00:23:42 +0000155 bool isFP64() const {
156 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
157 }
158
Jack Carter873c7242013-01-12 01:03:14 +0000159 int matchRegisterName(StringRef Symbol, bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000160
Jack Carter1ac53222013-02-20 23:11:17 +0000161 int matchCPURegisterName(StringRef Symbol);
162
Jack Carter873c7242013-01-12 01:03:14 +0000163 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000164
Jack Cartera63b16a2012-09-07 00:23:42 +0000165 void setFpFormat(FpFormatTy Format) {
166 FpFormat = Format;
167 }
168
169 void setDefaultFpFormat();
170
171 void setFpFormat(StringRef Format);
172
173 FpFormatTy getFpFormat() {return FpFormat;}
174
175 bool requestsDoubleOperand(StringRef Mnemonic);
176
Jack Carterb4dbc172012-09-05 23:34:03 +0000177 unsigned getReg(int RC,int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000178
Jack Carter1ac53222013-02-20 23:11:17 +0000179 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000180
181 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
182 SmallVectorImpl<MCInst> &Instructions);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000183public:
184 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterb4dbc172012-09-05 23:34:03 +0000185 : MCTargetAsmParser(), STI(sti), Parser(parser) {
186 // Initialize the set of available features.
187 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindola870c4e92012-01-11 03:56:41 +0000188 }
189
Jack Carterb4dbc172012-09-05 23:34:03 +0000190 MCAsmParser &getParser() const { return Parser; }
191 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
192
Rafael Espindola870c4e92012-01-11 03:56:41 +0000193};
194}
195
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000196namespace {
197
198/// MipsOperand - Instances of this class represent a parsed Mips machine
199/// instruction.
200class MipsOperand : public MCParsedAsmOperand {
Jack Carterb4dbc172012-09-05 23:34:03 +0000201
Jack Carter873c7242013-01-12 01:03:14 +0000202public:
203 enum RegisterKind {
204 Kind_None,
205 Kind_CPURegs,
206 Kind_CPU64Regs,
207 Kind_HWRegs,
208 Kind_HW64Regs,
209 Kind_FGR32Regs,
210 Kind_FGR64Regs,
Jack Carter1ac53222013-02-20 23:11:17 +0000211 Kind_AFGR64Regs,
Jack Carter873c7242013-01-12 01:03:14 +0000212 Kind_CCRRegs
213 };
214
215private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000216 enum KindTy {
217 k_CondCode,
218 k_CoprocNum,
219 k_Immediate,
220 k_Memory,
221 k_PostIndexRegister,
222 k_Register,
223 k_Token
224 } Kind;
225
226 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterb4dbc172012-09-05 23:34:03 +0000227
Eric Christopher8996c5d2013-03-15 00:42:55 +0000228 struct Token {
229 const char *Data;
230 unsigned Length;
231 };
232
233 struct RegOp {
234 unsigned RegNum;
235 RegisterKind Kind;
236 };
237
238 struct ImmOp {
239 const MCExpr *Val;
240 };
241
242 struct MemOp {
243 unsigned Base;
244 const MCExpr *Off;
245 };
246
Jack Carterb4dbc172012-09-05 23:34:03 +0000247 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000248 struct Token Tok;
249 struct RegOp Reg;
250 struct ImmOp Imm;
251 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000252 };
253
254 SMLoc StartLoc, EndLoc;
255
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000256public:
257 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000258 assert(N == 1 && "Invalid number of operands!");
259 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000260 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000261
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000262 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterb4dbc172012-09-05 23:34:03 +0000263 // Add as immediate when possible. Null MCExpr = 0.
264 if (Expr == 0)
265 Inst.addOperand(MCOperand::CreateImm(0));
266 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
267 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
268 else
269 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000270 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000271
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000272 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000273 assert(N == 1 && "Invalid number of operands!");
274 const MCExpr *Expr = getImm();
275 addExpr(Inst,Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000276 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000277
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000278 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000279 assert(N == 2 && "Invalid number of operands!");
280
281 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
282
283 const MCExpr *Expr = getMemOff();
284 addExpr(Inst,Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000285 }
286
287 bool isReg() const { return Kind == k_Register; }
288 bool isImm() const { return Kind == k_Immediate; }
289 bool isToken() const { return Kind == k_Token; }
290 bool isMem() const { return Kind == k_Memory; }
291
292 StringRef getToken() const {
293 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000294 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000295 }
296
297 unsigned getReg() const {
298 assert((Kind == k_Register) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000299 return Reg.RegNum;
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000300 }
301
Jack Carter873c7242013-01-12 01:03:14 +0000302 void setRegKind(RegisterKind RegKind) {
303 assert((Kind == k_Register) && "Invalid access!");
304 Reg.Kind = RegKind;
305 }
306
Jack Carterb4dbc172012-09-05 23:34:03 +0000307 const MCExpr *getImm() const {
308 assert((Kind == k_Immediate) && "Invalid access!");
309 return Imm.Val;
310 }
311
Jack Carterdc1e35d2012-09-06 20:00:02 +0000312 unsigned getMemBase() const {
313 assert((Kind == k_Memory) && "Invalid access!");
314 return Mem.Base;
315 }
316
317 const MCExpr *getMemOff() const {
318 assert((Kind == k_Memory) && "Invalid access!");
319 return Mem.Off;
320 }
321
Jack Carterb4dbc172012-09-05 23:34:03 +0000322 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
323 MipsOperand *Op = new MipsOperand(k_Token);
324 Op->Tok.Data = Str.data();
325 Op->Tok.Length = Str.size();
326 Op->StartLoc = S;
327 Op->EndLoc = S;
328 return Op;
329 }
330
331 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
332 MipsOperand *Op = new MipsOperand(k_Register);
333 Op->Reg.RegNum = RegNum;
334 Op->StartLoc = S;
335 Op->EndLoc = E;
336 return Op;
337 }
338
339 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
340 MipsOperand *Op = new MipsOperand(k_Immediate);
341 Op->Imm.Val = Val;
342 Op->StartLoc = S;
343 Op->EndLoc = E;
344 return Op;
345 }
346
Jack Carterdc1e35d2012-09-06 20:00:02 +0000347 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
348 SMLoc S, SMLoc E) {
349 MipsOperand *Op = new MipsOperand(k_Memory);
350 Op->Mem.Base = Base;
351 Op->Mem.Off = Off;
352 Op->StartLoc = S;
353 Op->EndLoc = E;
354 return Op;
355 }
356
Jack Carter873c7242013-01-12 01:03:14 +0000357 bool isCPURegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000358 return Kind == k_Register && Reg.Kind == Kind_CPURegs;
Jack Carter873c7242013-01-12 01:03:14 +0000359 }
360 void addCPURegsAsmOperands(MCInst &Inst, unsigned N) const {
361 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
362 }
363
364 bool isCPU64RegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000365 return Kind == k_Register && Reg.Kind == Kind_CPU64Regs;
Jack Carter873c7242013-01-12 01:03:14 +0000366 }
367 void addCPU64RegsAsmOperands(MCInst &Inst, unsigned N) const {
368 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
369 }
370
371 bool isHWRegsAsm() const {
372 assert((Kind == k_Register) && "Invalid access!");
373 return Reg.Kind == Kind_HWRegs;
374 }
375 void addHWRegsAsmOperands(MCInst &Inst, unsigned N) const {
376 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
377 }
378
379 bool isHW64RegsAsm() const {
380 assert((Kind == k_Register) && "Invalid access!");
381 return Reg.Kind == Kind_HW64Regs;
382 }
383 void addHW64RegsAsmOperands(MCInst &Inst, unsigned N) const {
384 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
385 }
386
387 void addCCRAsmOperands(MCInst &Inst, unsigned N) const {
388 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
389 }
390
391 bool isCCRAsm() const {
392 assert((Kind == k_Register) && "Invalid access!");
393 return Reg.Kind == Kind_CCRRegs;
394 }
395
Jack Carterb4dbc172012-09-05 23:34:03 +0000396 /// getStartLoc - Get the location of the first token of this operand.
397 SMLoc getStartLoc() const { return StartLoc; }
398 /// getEndLoc - Get the location of the last token of this operand.
399 SMLoc getEndLoc() const { return EndLoc; }
400
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000401 virtual void print(raw_ostream &OS) const {
402 llvm_unreachable("unimplemented!");
403 }
404};
405}
406
Jack Carter9e65aa32013-03-22 00:05:30 +0000407namespace llvm {
408extern const MCInstrDesc MipsInsts[];
409}
410static const MCInstrDesc &getInstDesc(unsigned Opcode) {
411 return MipsInsts[Opcode];
412}
413
414bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000415 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000416 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
417 Inst.setLoc(IDLoc);
418 if (MCID.mayLoad() || MCID.mayStore()) {
419 // Check the offset of memory operand, if it is a symbol
420 // reference or immediate we may have to expand instructions
421 for (unsigned i=0;i<MCID.getNumOperands();i++) {
422 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
423 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
424 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
425 MCOperand &Op = Inst.getOperand(i);
426 if (Op.isImm()) {
427 int MemOffset = Op.getImm();
428 if (MemOffset < -32768 || MemOffset > 32767) {
429 // Offset can't exceed 16bit value
430 expandMemInst(Inst,IDLoc,Instructions,MCID.mayLoad(),true);
431 return false;
432 }
433 } else if (Op.isExpr()) {
434 const MCExpr *Expr = Op.getExpr();
435 if (Expr->getKind() == MCExpr::SymbolRef){
436 const MCSymbolRefExpr *SR =
Jack Carterb5cf5902013-04-17 00:18:04 +0000437 static_cast<const MCSymbolRefExpr*>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000438 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
439 // Expand symbol
440 expandMemInst(Inst,IDLoc,Instructions,MCID.mayLoad(),false);
441 return false;
442 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000443 } else if (!isEvaluated(Expr)) {
444 expandMemInst(Inst,IDLoc,Instructions,MCID.mayLoad(),false);
445 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000446 }
447 }
448 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000449 }// For
450 }// If load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000451
452 if (needsExpansion(Inst))
453 expandInstruction(Inst, IDLoc, Instructions);
454 else
455 Instructions.push_back(Inst);
456
457 return false;
458}
459
Jack Carter30a59822012-10-04 04:03:53 +0000460bool MipsAsmParser::needsExpansion(MCInst &Inst) {
461
462 switch(Inst.getOpcode()) {
463 case Mips::LoadImm32Reg:
Jack Carter543fdf82012-10-09 23:29:45 +0000464 case Mips::LoadAddr32Imm:
465 case Mips::LoadAddr32Reg:
Jack Carter30a59822012-10-04 04:03:53 +0000466 return true;
467 default:
468 return false;
469 }
470}
Jack Carter92995f12012-10-06 00:53:28 +0000471
Jack Carter30a59822012-10-04 04:03:53 +0000472void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000473 SmallVectorImpl<MCInst> &Instructions){
Jack Carter30a59822012-10-04 04:03:53 +0000474 switch(Inst.getOpcode()) {
475 case Mips::LoadImm32Reg:
476 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000477 case Mips::LoadAddr32Imm:
478 return expandLoadAddressImm(Inst,IDLoc,Instructions);
479 case Mips::LoadAddr32Reg:
480 return expandLoadAddressReg(Inst,IDLoc,Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000481 }
Jack Carter30a59822012-10-04 04:03:53 +0000482}
Jack Carter92995f12012-10-06 00:53:28 +0000483
Jack Carter30a59822012-10-04 04:03:53 +0000484void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000485 SmallVectorImpl<MCInst> &Instructions){
Jack Carter92995f12012-10-06 00:53:28 +0000486 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000487 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000488 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000489 const MCOperand &RegOp = Inst.getOperand(0);
490 assert(RegOp.isReg() && "expected register operand kind");
491
492 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000493 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000494 if ( 0 <= ImmValue && ImmValue <= 65535) {
Jack Carter92995f12012-10-06 00:53:28 +0000495 // for 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000496 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000497 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000498 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
499 tmpInst.addOperand(
Jack Carter873c7242013-01-12 01:03:14 +0000500 MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000501 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000502 Instructions.push_back(tmpInst);
503 } else if ( ImmValue < 0 && ImmValue >= -32768) {
Jack Carter92995f12012-10-06 00:53:28 +0000504 // for -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000505 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000506 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000507 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
508 tmpInst.addOperand(
Jack Carter873c7242013-01-12 01:03:14 +0000509 MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000510 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000511 Instructions.push_back(tmpInst);
512 } else {
513 // for any other value of j that is representable as a 32-bit integer.
514 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000515 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000516 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000517 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
518 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000519 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000520 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000521 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000522 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
523 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
524 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
525 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000526 Instructions.push_back(tmpInst);
527 }
528}
Jack Carter92995f12012-10-06 00:53:28 +0000529
Jack Carter543fdf82012-10-09 23:29:45 +0000530void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
531 SmallVectorImpl<MCInst> &Instructions){
532 MCInst tmpInst;
533 const MCOperand &ImmOp = Inst.getOperand(2);
534 assert(ImmOp.isImm() && "expected immediate operand kind");
535 const MCOperand &SrcRegOp = Inst.getOperand(1);
536 assert(SrcRegOp.isReg() && "expected register operand kind");
537 const MCOperand &DstRegOp = Inst.getOperand(0);
538 assert(DstRegOp.isReg() && "expected register operand kind");
539 int ImmValue = ImmOp.getImm();
540 if ( -32768 <= ImmValue && ImmValue <= 65535) {
541 //for -32768 <= j <= 65535.
542 //la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000543 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000544 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
545 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
546 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
547 Instructions.push_back(tmpInst);
548 } else {
549 //for any other value of j that is representable as a 32-bit integer.
550 //la d,j(s) => lui d,hi16(j)
551 // ori d,d,lo16(j)
552 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000553 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000554 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
555 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
556 Instructions.push_back(tmpInst);
557 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000558 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000559 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
560 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
561 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
562 Instructions.push_back(tmpInst);
563 tmpInst.clear();
564 tmpInst.setOpcode(Mips::ADDu);
565 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
566 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
567 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
568 Instructions.push_back(tmpInst);
569 }
570}
571
572void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
573 SmallVectorImpl<MCInst> &Instructions){
574 MCInst tmpInst;
575 const MCOperand &ImmOp = Inst.getOperand(1);
576 assert(ImmOp.isImm() && "expected immediate operand kind");
577 const MCOperand &RegOp = Inst.getOperand(0);
578 assert(RegOp.isReg() && "expected register operand kind");
579 int ImmValue = ImmOp.getImm();
580 if ( -32768 <= ImmValue && ImmValue <= 65535) {
581 //for -32768 <= j <= 65535.
582 //la d,j => addiu d,$zero,j
583 tmpInst.setOpcode(Mips::ADDiu);
584 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
585 tmpInst.addOperand(
Jack Carter873c7242013-01-12 01:03:14 +0000586 MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +0000587 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
588 Instructions.push_back(tmpInst);
589 } else {
590 //for any other value of j that is representable as a 32-bit integer.
591 //la d,j => lui d,hi16(j)
592 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000593 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000594 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
595 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
596 Instructions.push_back(tmpInst);
597 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000598 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000599 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
600 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
601 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
602 Instructions.push_back(tmpInst);
603 }
604}
605
Jack Carter9e65aa32013-03-22 00:05:30 +0000606void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
607 SmallVectorImpl<MCInst> &Instructions,
608 bool isLoad,bool isImmOpnd) {
609 const MCSymbolRefExpr *SR;
610 MCInst TempInst;
611 unsigned ImmOffset,HiOffset,LoOffset;
612 const MCExpr *ExprOffset;
613 unsigned TmpRegNum;
614 unsigned AtRegNum = getReg((isMips64()) ? Mips::CPU64RegsRegClassID:
615 Mips::CPURegsRegClassID,
616 getATReg());
617 // 1st operand is either source or dst register
618 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
619 unsigned RegOpNum = Inst.getOperand(0).getReg();
620 // 2nd operand is base register
621 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
622 unsigned BaseRegNum = Inst.getOperand(1).getReg();
623 // 3rd operand is either immediate or expression
624 if (isImmOpnd) {
625 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
626 ImmOffset = Inst.getOperand(2).getImm();
627 LoOffset = ImmOffset & 0x0000ffff;
628 HiOffset = (ImmOffset & 0xffff0000) >> 16;
629 // If msb of LoOffset is 1(negative number) we must increment HiOffset
630 if (LoOffset & 0x8000)
631 HiOffset++;
632 }
633 else
634 ExprOffset = Inst.getOperand(2).getExpr();
635 // All instructions will have the same location
636 TempInst.setLoc(IDLoc);
637 // 1st instruction in expansion is LUi. For load instruction we can use
638 // the dst register as a temporary if base and dst are different,
639 // but for stores we must use $at
640 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum))?RegOpNum:AtRegNum;
641 TempInst.setOpcode(Mips::LUi);
642 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
643 if (isImmOpnd)
644 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
645 else {
646 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
647 SR = static_cast<const MCSymbolRefExpr*>(ExprOffset);
648 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::
649 Create(SR->getSymbol().getName(),
650 MCSymbolRefExpr::VK_Mips_ABS_HI,
651 getContext());
652 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000653 } else {
654 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset,"hi");
655 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000656 }
657 }
658 // Add the instruction to the list
659 Instructions.push_back(TempInst);
Jack Carterb5cf5902013-04-17 00:18:04 +0000660 // And prepare TempInst for next instruction
Jack Carter9e65aa32013-03-22 00:05:30 +0000661 TempInst.clear();
Jack Carterb5cf5902013-04-17 00:18:04 +0000662 // Which is add temp register to base
Jack Carter9e65aa32013-03-22 00:05:30 +0000663 TempInst.setOpcode(Mips::ADDu);
664 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
665 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
666 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
667 Instructions.push_back(TempInst);
668 TempInst.clear();
Jack Carterb5cf5902013-04-17 00:18:04 +0000669 // And finaly, create original instruction with low part
Jack Carter9e65aa32013-03-22 00:05:30 +0000670 // of offset and new base
671 TempInst.setOpcode(Inst.getOpcode());
672 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
673 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
674 if (isImmOpnd)
675 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
676 else {
677 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
678 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::
679 Create(SR->getSymbol().getName(),
680 MCSymbolRefExpr::VK_Mips_ABS_LO,
681 getContext());
682 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000683 } else {
684 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset,"lo");
685 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000686 }
687 }
688 Instructions.push_back(TempInst);
689 TempInst.clear();
690}
691
Rafael Espindola870c4e92012-01-11 03:56:41 +0000692bool MipsAsmParser::
Chad Rosier49963552012-10-13 00:26:04 +0000693MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +0000694 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +0000695 MCStreamer &Out, unsigned &ErrorInfo,
696 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000697 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +0000698 SmallVector<MCInst, 8> Instructions;
Chad Rosier2f480a82012-10-12 22:53:36 +0000699 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier49963552012-10-13 00:26:04 +0000700 MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +0000701
702 switch (MatchResult) {
703 default: break;
704 case Match_Success: {
Jack Carter9e65aa32013-03-22 00:05:30 +0000705 if (processInstruction(Inst,IDLoc,Instructions))
706 return true;
707 for(unsigned i =0; i < Instructions.size(); i++)
708 Out.EmitInstruction(Instructions[i]);
Jack Carterb4dbc172012-09-05 23:34:03 +0000709 return false;
710 }
711 case Match_MissingFeature:
712 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
713 return true;
714 case Match_InvalidOperand: {
715 SMLoc ErrorLoc = IDLoc;
716 if (ErrorInfo != ~0U) {
717 if (ErrorInfo >= Operands.size())
718 return Error(IDLoc, "too few operands for instruction");
719
720 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
721 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
722 }
723
724 return Error(ErrorLoc, "invalid operand for instruction");
725 }
726 case Match_MnemonicFail:
727 return Error(IDLoc, "invalid instruction");
728 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000729 return true;
730}
731
Jack Carter1ac53222013-02-20 23:11:17 +0000732int MipsAsmParser::matchCPURegisterName(StringRef Name) {
733 int CC;
734
735 if (Name == "at")
736 return getATReg();
737
738 CC = StringSwitch<unsigned>(Name)
739 .Case("zero", 0)
740 .Case("a0", 4)
741 .Case("a1", 5)
742 .Case("a2", 6)
743 .Case("a3", 7)
744 .Case("v0", 2)
745 .Case("v1", 3)
746 .Case("s0", 16)
747 .Case("s1", 17)
748 .Case("s2", 18)
749 .Case("s3", 19)
750 .Case("s4", 20)
751 .Case("s5", 21)
752 .Case("s6", 22)
753 .Case("s7", 23)
754 .Case("k0", 26)
755 .Case("k1", 27)
756 .Case("sp", 29)
757 .Case("fp", 30)
758 .Case("gp", 28)
759 .Case("ra", 31)
760 .Case("t0", 8)
761 .Case("t1", 9)
762 .Case("t2", 10)
763 .Case("t3", 11)
764 .Case("t4", 12)
765 .Case("t5", 13)
766 .Case("t6", 14)
767 .Case("t7", 15)
768 .Case("t8", 24)
769 .Case("t9", 25)
770 .Default(-1);
771
772 // Although SGI documentation just cut out t0-t3 for n32/n64,
773 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
774 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
775 if (isMips64() && 8 <= CC && CC <= 11)
776 CC += 4;
777
778 if (CC == -1 && isMips64())
779 CC = StringSwitch<unsigned>(Name)
780 .Case("a4", 8)
781 .Case("a5", 9)
782 .Case("a6", 10)
783 .Case("a7", 11)
784 .Case("kt0", 26)
785 .Case("kt1", 27)
786 .Case("s8", 30)
787 .Default(-1);
788
789 return CC;
790}
Jack Carter873c7242013-01-12 01:03:14 +0000791int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000792
Jack Carter2ad73da2013-04-15 22:21:55 +0000793 if (Name.equals("fcc0"))
794 return Mips::FCC0;
795
Jack Carter1ac53222013-02-20 23:11:17 +0000796 int CC;
797 CC = matchCPURegisterName(Name);
David Chisnall37051252012-10-09 16:27:43 +0000798 if (CC != -1)
Jack Carter1ac53222013-02-20 23:11:17 +0000799 return matchRegisterByNumber(CC,is64BitReg?Mips::CPU64RegsRegClassID:
800 Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000801
Jack Cartera63b16a2012-09-07 00:23:42 +0000802 if (Name[0] == 'f') {
803 StringRef NumString = Name.substr(1);
804 unsigned IntVal;
805 if( NumString.getAsInteger(10, IntVal))
Jack Carter30a59822012-10-04 04:03:53 +0000806 return -1; // not integer
Jack Cartera63b16a2012-09-07 00:23:42 +0000807 if (IntVal > 31)
808 return -1;
809
810 FpFormatTy Format = getFpFormat();
811
812 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
813 return getReg(Mips::FGR32RegClassID, IntVal);
814 if (Format == FP_FORMAT_D) {
815 if(isFP64()) {
816 return getReg(Mips::FGR64RegClassID, IntVal);
817 }
Jack Carter30a59822012-10-04 04:03:53 +0000818 // only even numbers available as register pairs
Jack Cartera63b16a2012-09-07 00:23:42 +0000819 if (( IntVal > 31) || (IntVal%2 != 0))
820 return -1;
821 return getReg(Mips::AFGR64RegClassID, IntVal/2);
822 }
823 }
824
Jack Carterb4dbc172012-09-05 23:34:03 +0000825 return -1;
826}
Jack Cartera63b16a2012-09-07 00:23:42 +0000827void MipsAsmParser::setDefaultFpFormat() {
828
829 if (isMips64() || isFP64())
830 FpFormat = FP_FORMAT_D;
831 else
832 FpFormat = FP_FORMAT_S;
833}
834
835bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
836
837 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
838 .Case("ldxc1", true)
839 .Case("ldc1", true)
840 .Case("sdxc1", true)
841 .Case("sdc1", true)
842 .Default(false);
843
844 return IsDouble;
845}
846void MipsAsmParser::setFpFormat(StringRef Format) {
847
848 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
849 .Case(".s", FP_FORMAT_S)
850 .Case(".d", FP_FORMAT_D)
851 .Case(".l", FP_FORMAT_L)
852 .Case(".w", FP_FORMAT_W)
853 .Default(FP_FORMAT_NONE);
854}
Jack Carterb4dbc172012-09-05 23:34:03 +0000855
Jack Carter0b744b32012-10-04 02:29:46 +0000856bool MipsAssemblerOptions::setATReg(unsigned Reg) {
857 if (Reg > 31)
858 return false;
859
860 aTReg = Reg;
861 return true;
862}
863
Jack Carter1ac53222013-02-20 23:11:17 +0000864int MipsAsmParser::getATReg() {
865 return Options.getATRegNum();
Jack Carter0b744b32012-10-04 02:29:46 +0000866}
867
868unsigned MipsAsmParser::getReg(int RC,int RegNo) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000869 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
870}
871
Jack Carter873c7242013-01-12 01:03:14 +0000872int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000873
874 if (RegNum > 31)
875 return -1;
876
Jack Carter873c7242013-01-12 01:03:14 +0000877 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +0000878}
879
Jack Carter873c7242013-01-12 01:03:14 +0000880int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000881 const AsmToken &Tok = Parser.getTok();
882 int RegNum = -1;
883
884 if (Tok.is(AsmToken::Identifier)) {
885 std::string lowerCase = Tok.getString().lower();
Jack Carter873c7242013-01-12 01:03:14 +0000886 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000887 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +0000888 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carter873c7242013-01-12 01:03:14 +0000889 is64BitReg ? Mips::CPU64RegsRegClassID
890 : Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000891 return RegNum;
892}
893
Rafael Espindola870c4e92012-01-11 03:56:41 +0000894bool MipsAsmParser::
Jack Carterb4dbc172012-09-05 23:34:03 +0000895 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carter873c7242013-01-12 01:03:14 +0000896 bool is64BitReg){
Jack Carterb4dbc172012-09-05 23:34:03 +0000897
898 SMLoc S = Parser.getTok().getLoc();
899 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +0000900
Jack Carter873c7242013-01-12 01:03:14 +0000901 RegNo = tryParseRegister(is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000902 if (RegNo == -1)
903 return true;
904
Jack Carter873c7242013-01-12 01:03:14 +0000905 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
906 Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000907 Parser.Lex(); // Eat register token.
908 return false;
909}
910
911bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
912 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +0000913 // Check if the current operand has a custom associated parser, if so, try to
914 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +0000915 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
916 if (ResTy == MatchOperand_Success)
917 return false;
918 // If there wasn't a custom match, try the generic matcher below. Otherwise,
919 // there was a match, but an error occurred, in which case, just return that
920 // the operand parsing failed.
921 if (ResTy == MatchOperand_ParseFail)
922 return true;
923
924 switch (getLexer().getKind()) {
925 default:
926 Error(Parser.getTok().getLoc(), "unexpected token in operand");
927 return true;
928 case AsmToken::Dollar: {
Jack Carter30a59822012-10-04 04:03:53 +0000929 // parse register
Jack Carterb4dbc172012-09-05 23:34:03 +0000930 SMLoc S = Parser.getTok().getLoc();
931 Parser.Lex(); // Eat dollar token.
Jack Carter30a59822012-10-04 04:03:53 +0000932 // parse register operand
Jack Carter873c7242013-01-12 01:03:14 +0000933 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000934 if (getLexer().is(AsmToken::LParen)) {
Jack Carter30a59822012-10-04 04:03:53 +0000935 // check if it is indexed addressing operand
Jack Carterb4dbc172012-09-05 23:34:03 +0000936 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carter30a59822012-10-04 04:03:53 +0000937 Parser.Lex(); // eat parenthesis
Jack Carterb4dbc172012-09-05 23:34:03 +0000938 if (getLexer().isNot(AsmToken::Dollar))
939 return true;
940
Jack Carter30a59822012-10-04 04:03:53 +0000941 Parser.Lex(); // eat dollar
Jack Carter873c7242013-01-12 01:03:14 +0000942 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterb4dbc172012-09-05 23:34:03 +0000943 return true;
944
945 if (!getLexer().is(AsmToken::RParen))
946 return true;
947
948 S = Parser.getTok().getLoc();
949 Operands.push_back(MipsOperand::CreateToken(")", S));
950 Parser.Lex();
951 }
952 return false;
953 }
Jack Carter30a59822012-10-04 04:03:53 +0000954 // maybe it is a symbol reference
Jack Carterb4dbc172012-09-05 23:34:03 +0000955 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000956 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +0000957 return true;
958
Jack Carter873c7242013-01-12 01:03:14 +0000959 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000960
Benjamin Kramerfa530572012-09-07 09:47:42 +0000961 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterb4dbc172012-09-05 23:34:03 +0000962
963 // Otherwise create a symbol ref.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000964 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterb4dbc172012-09-05 23:34:03 +0000965 getContext());
966
967 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
968 return false;
969 }
970 case AsmToken::Identifier:
Jack Carterd76b2372013-03-21 21:44:16 +0000971 // Look for the existing symbol, we should check if
972 // we need to assigne the propper RegisterKind
973 if (searchSymbolAlias(Operands,MipsOperand::Kind_None))
974 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +0000975 // Else drop to expression parsing
Jack Carterb4dbc172012-09-05 23:34:03 +0000976 case AsmToken::LParen:
977 case AsmToken::Minus:
978 case AsmToken::Plus:
979 case AsmToken::Integer:
980 case AsmToken::String: {
Jack Carterb5cf5902013-04-17 00:18:04 +0000981 // Quoted label names
Jack Carterb4dbc172012-09-05 23:34:03 +0000982 const MCExpr *IdVal;
983 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000984 if (getParser().parseExpression(IdVal))
Jack Carterb4dbc172012-09-05 23:34:03 +0000985 return true;
Jack Carter873c7242013-01-12 01:03:14 +0000986 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000987 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
988 return false;
989 }
Jack Carterdc1e35d2012-09-06 20:00:02 +0000990 case AsmToken::Percent: {
Jack Carterb5cf5902013-04-17 00:18:04 +0000991 // It is a symbol reference or constant expression
Jack Carterdc1e35d2012-09-06 20:00:02 +0000992 const MCExpr *IdVal;
Jack Carterb5cf5902013-04-17 00:18:04 +0000993 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand
Jack Carter873c7242013-01-12 01:03:14 +0000994 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +0000995 return true;
996
Jack Carter873c7242013-01-12 01:03:14 +0000997 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
998
Jack Carterdc1e35d2012-09-06 20:00:02 +0000999 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1000 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001001 } // case AsmToken::Percent
1002 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001003 return true;
1004}
1005
Jack Carterb5cf5902013-04-17 00:18:04 +00001006const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
1007 StringRef RelocStr) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001008
Jack Carterb5cf5902013-04-17 00:18:04 +00001009 const MCExpr *Res;
Jack Carter0b744b32012-10-04 02:29:46 +00001010 // Check the type of the expression
Jack Carterb5cf5902013-04-17 00:18:04 +00001011 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001012 // It's a constant, evaluate lo or hi value
Jack Carterb5cf5902013-04-17 00:18:04 +00001013 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001014 short Val = MCE->getValue();
1015 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001016 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001017 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001018 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001019 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001020 // Lower part is treated as a signed int, so if it is negative
1021 // we must add 1 to the hi part to compensate
Jack Carterdc463382013-02-21 02:09:31 +00001022 if (LoSign)
1023 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001024 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001025 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001026 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001027 }
1028
Jack Carterb5cf5902013-04-17 00:18:04 +00001029 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001030 // It's a symbol, create symbolic expression from symbol
Benjamin Kramerfa530572012-09-07 09:47:42 +00001031 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001032 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001033 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001034 return Res;
1035 }
1036
1037 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1038 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(),RelocStr);
1039 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(),RelocStr);
1040 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1041 return Res;
1042 }
1043
1044 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
1045 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(),RelocStr);
1046 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1047 return Res;
1048 }
1049 // Just return the original expr
1050 return Expr;
1051}
1052
1053bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1054
1055 switch (Expr->getKind()) {
1056 case MCExpr::Constant:
1057 return true;
1058 case MCExpr::SymbolRef:
1059 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1060 case MCExpr::Binary:
1061 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1062 if (!isEvaluated(BE->getLHS()))
1063 return false;
1064 return isEvaluated(BE->getRHS());
1065 }
1066 case MCExpr::Unary:
1067 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1068 default:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001069 return false;
1070 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001071 return false;
1072
1073}
1074bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
1075
1076
1077 Parser.Lex(); // Eat % token
1078 const AsmToken &Tok = Parser.getTok(); // Get next token, operation
1079 if (Tok.isNot(AsmToken::Identifier))
1080 return true;
1081
1082 std::string Str = Tok.getIdentifier().str();
1083
1084 Parser.Lex(); // Eat identifier
1085 // Now make expression from the rest of the operand
1086 const MCExpr *IdVal;
1087 SMLoc EndLoc;
1088
1089 if (getLexer().getKind() == AsmToken::LParen) {
1090 while (1) {
1091 Parser.Lex(); // Eat '(' token
1092 if (getLexer().getKind() == AsmToken::Percent) {
1093 Parser.Lex(); // Eat % token
1094 const AsmToken &nextTok = Parser.getTok();
1095 if (nextTok.isNot(AsmToken::Identifier))
1096 return true;
1097 Str += "(%";
1098 Str += nextTok.getIdentifier();
1099 Parser.Lex(); // Eat identifier
1100 if (getLexer().getKind() != AsmToken::LParen)
1101 return true;
1102 } else
1103 break;
1104 }
1105 if (getParser().parseParenExpression(IdVal,EndLoc))
1106 return true;
1107
1108 while (getLexer().getKind() == AsmToken::RParen)
1109 Parser.Lex(); // Eat ')' token
1110
1111 } else
1112 return true; // Parenthesis must follow reloc operand
1113
1114 Res = evaluateRelocExpr(IdVal,Str);
1115 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001116}
1117
Jack Carterb4dbc172012-09-05 23:34:03 +00001118bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1119 SMLoc &EndLoc) {
1120
1121 StartLoc = Parser.getTok().getLoc();
Jack Carter873c7242013-01-12 01:03:14 +00001122 RegNo = tryParseRegister(isMips64());
1123 EndLoc = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001124 return (RegNo == (unsigned)-1);
1125}
1126
Jack Carterb5cf5902013-04-17 00:18:04 +00001127bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001128
1129 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001130 bool Result = true;
1131
1132 while (getLexer().getKind() == AsmToken::LParen)
1133 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001134
Jack Carterdc1e35d2012-09-06 20:00:02 +00001135 switch(getLexer().getKind()) {
1136 default:
1137 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001138 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001139 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001140 case AsmToken::Integer:
1141 case AsmToken::Minus:
1142 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001143 if (isParenExpr)
1144 Result = getParser().parseParenExpression(Res,S);
1145 else
1146 Result = (getParser().parseExpression(Res));
1147 while (getLexer().getKind() == AsmToken::RParen)
1148 Parser.Lex();
1149 break;
Jack Carter873c7242013-01-12 01:03:14 +00001150 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001151 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001152 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001153 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001154}
1155
Jack Carterb4dbc172012-09-05 23:34:03 +00001156MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
1157 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001158
1159 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001160 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001161 bool isParenExpr = false;
1162 // First operand is the offset
Jack Carter873c7242013-01-12 01:03:14 +00001163 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001164
Jack Carterb5cf5902013-04-17 00:18:04 +00001165 if (getLexer().getKind() == AsmToken::LParen) {
1166 Parser.Lex();
1167 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001168 }
1169
Jack Carterb5cf5902013-04-17 00:18:04 +00001170 if (getLexer().getKind() != AsmToken::Dollar) {
1171 if (parseMemOffset(IdVal,isParenExpr))
1172 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001173
Jack Carterb5cf5902013-04-17 00:18:04 +00001174 const AsmToken &Tok = Parser.getTok(); // Get next token
1175 if (Tok.isNot(AsmToken::LParen)) {
1176 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
1177 if (Mnemonic->getToken() == "la") {
1178 SMLoc E = SMLoc::getFromPointer(
1179 Parser.getTok().getLoc().getPointer() -1);
1180 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1181 return MatchOperand_Success;
1182 }
1183 if (Tok.is(AsmToken::EndOfStatement)) {
1184 SMLoc E = SMLoc::getFromPointer(
1185 Parser.getTok().getLoc().getPointer() -1);
1186
1187 // Zero register assumed, add memory operand with ZERO as base
1188 Operands.push_back(MipsOperand::CreateMem(isMips64()?
1189 Mips::ZERO_64:Mips::ZERO,
1190 IdVal, S, E));
1191 return MatchOperand_Success;
1192 }
1193 Error(Parser.getTok().getLoc(), "'(' expected");
1194 return MatchOperand_ParseFail;
1195 }
1196
1197 Parser.Lex(); // Eat '(' token.
1198 }
1199
1200 const AsmToken &Tok1 = Parser.getTok(); // Get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +00001201 if (Tok1.is(AsmToken::Dollar)) {
1202 Parser.Lex(); // Eat '$' token.
Jack Carter873c7242013-01-12 01:03:14 +00001203 if (tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001204 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1205 return MatchOperand_ParseFail;
1206 }
1207
1208 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001209 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001210 return MatchOperand_ParseFail;
1211 }
1212
Jack Carterb5cf5902013-04-17 00:18:04 +00001213 const AsmToken &Tok2 = Parser.getTok(); // Get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +00001214 if (Tok2.isNot(AsmToken::RParen)) {
1215 Error(Parser.getTok().getLoc(), "')' expected");
1216 return MatchOperand_ParseFail;
1217 }
1218
Jack Carter873c7242013-01-12 01:03:14 +00001219 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1220
Jack Carterdc1e35d2012-09-06 20:00:02 +00001221 Parser.Lex(); // Eat ')' token.
1222
1223 if (IdVal == 0)
1224 IdVal = MCConstantExpr::Create(0, getContext());
1225
Jack Carterb5cf5902013-04-17 00:18:04 +00001226 // Now replace register operand with the mem operand
Jack Carterdc1e35d2012-09-06 20:00:02 +00001227 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1228 int RegNo = op->getReg();
Jack Carterb5cf5902013-04-17 00:18:04 +00001229 // Remove register from operands
Jack Carterdc1e35d2012-09-06 20:00:02 +00001230 Operands.pop_back();
Jack Carterb5cf5902013-04-17 00:18:04 +00001231 // And add memory operand
1232 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1233 int64_t Imm;
1234 if (IdVal->EvaluateAsAbsolute(Imm))
1235 IdVal = MCConstantExpr::Create(Imm, getContext());
1236 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1237 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1238 getContext());
1239 }
1240
Jack Carterdc1e35d2012-09-06 20:00:02 +00001241 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1242 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +00001243 return MatchOperand_Success;
1244}
1245
Jack Carter873c7242013-01-12 01:03:14 +00001246MipsAsmParser::OperandMatchResultTy
1247MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1248
1249 if (!isMips64())
1250 return MatchOperand_NoMatch;
Jack Carterd76b2372013-03-21 21:44:16 +00001251 if (getLexer().getKind() == AsmToken::Identifier) {
1252 if (searchSymbolAlias(Operands,MipsOperand::Kind_CPU64Regs))
1253 return MatchOperand_Success;
1254 return MatchOperand_NoMatch;
1255 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001256 // If the first token is not '$' we have an error
Jack Carter873c7242013-01-12 01:03:14 +00001257 if (Parser.getTok().isNot(AsmToken::Dollar))
1258 return MatchOperand_NoMatch;
1259
1260 Parser.Lex(); // Eat $
1261 if(!tryParseRegisterOperand(Operands, true)) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001262 // Set the proper register kind
Jack Carter873c7242013-01-12 01:03:14 +00001263 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1264 op->setRegKind(MipsOperand::Kind_CPU64Regs);
1265 return MatchOperand_Success;
1266 }
1267 return MatchOperand_NoMatch;
1268}
1269
Jack Carterd76b2372013-03-21 21:44:16 +00001270bool MipsAsmParser::
1271searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
1272 unsigned RegisterKind) {
1273
1274 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1275 if (Sym) {
1276 SMLoc S = Parser.getTok().getLoc();
1277 const MCExpr *Expr;
1278 if (Sym->isVariable())
1279 Expr = Sym->getVariableValue();
1280 else
1281 return false;
1282 if (Expr->getKind() == MCExpr::SymbolRef) {
1283 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
1284 const StringRef DefSymbol = Ref->getSymbol().getName();
1285 if (DefSymbol.startswith("$")) {
1286 // Lookup for the register with corresponding name
1287 int RegNum = matchRegisterName(DefSymbol.substr(1),isMips64());
1288 if (RegNum > -1) {
1289 Parser.Lex();
1290 MipsOperand *op = MipsOperand::CreateReg(RegNum,S,
1291 Parser.getTok().getLoc());
1292 op->setRegKind((MipsOperand::RegisterKind)RegisterKind);
1293 Operands.push_back(op);
1294 return true;
1295 }
1296 }
1297 } else if (Expr->getKind() == MCExpr::Constant) {
1298 Parser.Lex();
1299 const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr);
1300 MipsOperand *op = MipsOperand::CreateImm(Const,S,
1301 Parser.getTok().getLoc());
1302 Operands.push_back(op);
1303 return true;
1304 }
1305 }
1306 return false;
1307}
Jack Carter873c7242013-01-12 01:03:14 +00001308MipsAsmParser::OperandMatchResultTy
1309MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1310
Jack Carterd76b2372013-03-21 21:44:16 +00001311 if (getLexer().getKind() == AsmToken::Identifier) {
1312 if (searchSymbolAlias(Operands,MipsOperand::Kind_CPURegs))
1313 return MatchOperand_Success;
1314 return MatchOperand_NoMatch;
1315 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001316 // If the first token is not '$' we have an error
Jack Carter873c7242013-01-12 01:03:14 +00001317 if (Parser.getTok().isNot(AsmToken::Dollar))
1318 return MatchOperand_NoMatch;
1319
1320 Parser.Lex(); // Eat $
1321 if(!tryParseRegisterOperand(Operands, false)) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001322 // Set the propper register kind
Jack Carter873c7242013-01-12 01:03:14 +00001323 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1324 op->setRegKind(MipsOperand::Kind_CPURegs);
1325 return MatchOperand_Success;
1326 }
1327 return MatchOperand_NoMatch;
1328}
1329
1330MipsAsmParser::OperandMatchResultTy
1331MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1332
Jack Carter2a74a87b2013-01-17 00:28:20 +00001333 if (isMips64())
1334 return MatchOperand_NoMatch;
1335
Jack Carterb5cf5902013-04-17 00:18:04 +00001336 // If the first token is not '$' we have error
Jack Carter873c7242013-01-12 01:03:14 +00001337 if (Parser.getTok().isNot(AsmToken::Dollar))
1338 return MatchOperand_NoMatch;
1339 SMLoc S = Parser.getTok().getLoc();
1340 Parser.Lex(); // Eat $
1341
Jack Carterb5cf5902013-04-17 00:18:04 +00001342 const AsmToken &Tok = Parser.getTok(); // Get next token
Jack Carter873c7242013-01-12 01:03:14 +00001343 if (Tok.isNot(AsmToken::Integer))
1344 return MatchOperand_NoMatch;
1345
1346 unsigned RegNum = Tok.getIntVal();
Jack Carterb5cf5902013-04-17 00:18:04 +00001347 // At the moment only hwreg29 is supported
Jack Carter873c7242013-01-12 01:03:14 +00001348 if (RegNum != 29)
1349 return MatchOperand_ParseFail;
1350
1351 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
1352 Parser.getTok().getLoc());
1353 op->setRegKind(MipsOperand::Kind_HWRegs);
1354 Operands.push_back(op);
1355
1356 Parser.Lex(); // Eat reg number
1357 return MatchOperand_Success;
1358}
1359
1360MipsAsmParser::OperandMatchResultTy
1361MipsAsmParser::parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter2a74a87b2013-01-17 00:28:20 +00001362
1363 if (!isMips64())
1364 return MatchOperand_NoMatch;
Jack Carterb5cf5902013-04-17 00:18:04 +00001365 // If the first token is not '$' we have error
Jack Carter873c7242013-01-12 01:03:14 +00001366 if (Parser.getTok().isNot(AsmToken::Dollar))
1367 return MatchOperand_NoMatch;
1368 SMLoc S = Parser.getTok().getLoc();
1369 Parser.Lex(); // Eat $
1370
Jack Carterb5cf5902013-04-17 00:18:04 +00001371 const AsmToken &Tok = Parser.getTok(); // Get next token
Jack Carter873c7242013-01-12 01:03:14 +00001372 if (Tok.isNot(AsmToken::Integer))
1373 return MatchOperand_NoMatch;
1374
1375 unsigned RegNum = Tok.getIntVal();
Jack Carterb5cf5902013-04-17 00:18:04 +00001376 // At the moment only hwreg29 is supported
Jack Carter873c7242013-01-12 01:03:14 +00001377 if (RegNum != 29)
1378 return MatchOperand_ParseFail;
1379
1380 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
1381 Parser.getTok().getLoc());
Jack Carter2a74a87b2013-01-17 00:28:20 +00001382 op->setRegKind(MipsOperand::Kind_HW64Regs);
Jack Carter873c7242013-01-12 01:03:14 +00001383 Operands.push_back(op);
1384
1385 Parser.Lex(); // Eat reg number
1386 return MatchOperand_Success;
1387}
1388
1389MipsAsmParser::OperandMatchResultTy
1390MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1391 unsigned RegNum;
Jack Carterb5cf5902013-04-17 00:18:04 +00001392 // If the first token is not '$' we have error
Jack Carter873c7242013-01-12 01:03:14 +00001393 if (Parser.getTok().isNot(AsmToken::Dollar))
1394 return MatchOperand_NoMatch;
1395 SMLoc S = Parser.getTok().getLoc();
1396 Parser.Lex(); // Eat $
1397
Jack Carterb5cf5902013-04-17 00:18:04 +00001398 const AsmToken &Tok = Parser.getTok(); // Get next token
Jack Carter873c7242013-01-12 01:03:14 +00001399 if (Tok.is(AsmToken::Integer)) {
1400 RegNum = Tok.getIntVal();
Jack Carterb5cf5902013-04-17 00:18:04 +00001401 // At the moment only fcc0 is supported
Jack Carter873c7242013-01-12 01:03:14 +00001402 if (RegNum != 0)
1403 return MatchOperand_ParseFail;
1404 } else if (Tok.is(AsmToken::Identifier)) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001405 // At the moment only fcc0 is supported
Jack Carter873c7242013-01-12 01:03:14 +00001406 if (Tok.getIdentifier() != "fcc0")
1407 return MatchOperand_ParseFail;
1408 } else
1409 return MatchOperand_NoMatch;
1410
1411 MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
1412 Parser.getTok().getLoc());
1413 op->setRegKind(MipsOperand::Kind_CCRRegs);
1414 Operands.push_back(op);
1415
1416 Parser.Lex(); // Eat reg number
1417 return MatchOperand_Success;
1418}
1419
Jack Carterdc1e35d2012-09-06 20:00:02 +00001420MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1421
1422 MCSymbolRefExpr::VariantKind VK
1423 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1424 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1425 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1426 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1427 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1428 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1429 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1430 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1431 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1432 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1433 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1434 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1435 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1436 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1437 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1438 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1439 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1440 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1441 .Default(MCSymbolRefExpr::VK_None);
1442
1443 return VK;
1444}
1445
Benjamin Kramer47b5c572012-09-10 11:52:14 +00001446static int ConvertCcString(StringRef CondString) {
Jack Cartera63b16a2012-09-07 00:23:42 +00001447 int CC = StringSwitch<unsigned>(CondString)
1448 .Case(".f", 0)
1449 .Case(".un", 1)
1450 .Case(".eq", 2)
1451 .Case(".ueq", 3)
1452 .Case(".olt", 4)
1453 .Case(".ult", 5)
1454 .Case(".ole", 6)
1455 .Case(".ule", 7)
1456 .Case(".sf", 8)
1457 .Case(".ngle", 9)
1458 .Case(".seq", 10)
1459 .Case(".ngl", 11)
1460 .Case(".lt", 12)
1461 .Case(".nge", 13)
1462 .Case(".le", 14)
1463 .Case(".ngt", 15)
1464 .Default(-1);
1465
1466 return CC;
1467}
1468
1469bool MipsAsmParser::
1470parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter0b744b32012-10-04 02:29:46 +00001471 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001472 // Split the format
Jack Cartera63b16a2012-09-07 00:23:42 +00001473 size_t Start = Name.find('.'), Next = Name.rfind('.');
1474 StringRef Format1 = Name.slice(Start, Next);
Jack Carterb5cf5902013-04-17 00:18:04 +00001475 // And add the first format to the operands
Jack Cartera63b16a2012-09-07 00:23:42 +00001476 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carterb5cf5902013-04-17 00:18:04 +00001477 // Now for the second format
Jack Cartera63b16a2012-09-07 00:23:42 +00001478 StringRef Format2 = Name.slice(Next, StringRef::npos);
1479 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1480
Jack Carterb5cf5902013-04-17 00:18:04 +00001481 // Set the format for the first register
Jack Cartera63b16a2012-09-07 00:23:42 +00001482 setFpFormat(Format1);
1483
1484 // Read the remaining operands.
1485 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1486 // Read the first operand.
1487 if (ParseOperand(Operands, Name)) {
1488 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001489 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001490 return Error(Loc, "unexpected token in argument list");
1491 }
1492
1493 if (getLexer().isNot(AsmToken::Comma)) {
1494 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001495 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001496 return Error(Loc, "unexpected token in argument list");
1497
1498 }
1499 Parser.Lex(); // Eat the comma.
1500
Jack Carterb5cf5902013-04-17 00:18:04 +00001501 // Set the format for the first register
Jack Cartera63b16a2012-09-07 00:23:42 +00001502 setFpFormat(Format2);
1503
1504 // Parse and remember the operand.
1505 if (ParseOperand(Operands, Name)) {
1506 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001507 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001508 return Error(Loc, "unexpected token in argument list");
1509 }
1510 }
1511
1512 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1513 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001514 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001515 return Error(Loc, "unexpected token in argument list");
1516 }
1517
1518 Parser.Lex(); // Consume the EndOfStatement
1519 return false;
1520}
1521
Rafael Espindola870c4e92012-01-11 03:56:41 +00001522bool MipsAsmParser::
Chad Rosierf0e87202012-10-25 20:41:34 +00001523ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindola870c4e92012-01-11 03:56:41 +00001524 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter1ac53222013-02-20 23:11:17 +00001525 StringRef Mnemonic;
Jack Carterb5cf5902013-04-17 00:18:04 +00001526 // Floating point instructions: should register be treated as double?
Jack Cartera63b16a2012-09-07 00:23:42 +00001527 if (requestsDoubleOperand(Name)) {
1528 setFpFormat(FP_FORMAT_D);
Jack Carterb4dbc172012-09-05 23:34:03 +00001529 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carter1ac53222013-02-20 23:11:17 +00001530 Mnemonic = Name;
Jack Cartera63b16a2012-09-07 00:23:42 +00001531 }
1532 else {
1533 setDefaultFpFormat();
1534 // Create the leading tokens for the mnemonic, split by '.' characters.
1535 size_t Start = 0, Next = Name.find('.');
Jack Carter1ac53222013-02-20 23:11:17 +00001536 Mnemonic = Name.slice(Start, Next);
Jack Cartera63b16a2012-09-07 00:23:42 +00001537
1538 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1539
1540 if (Next != StringRef::npos) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001541 // There is a format token in mnemonic
Jack Cartera63b16a2012-09-07 00:23:42 +00001542 size_t Dot = Name.find('.', Next+1);
1543 StringRef Format = Name.slice(Next, Dot);
Jack Carterb5cf5902013-04-17 00:18:04 +00001544 if (Dot == StringRef::npos) // Only one '.' in a string, it's a format
Jack Cartera63b16a2012-09-07 00:23:42 +00001545 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1546 else {
1547 if (Name.startswith("c.")){
Jack Carterb5cf5902013-04-17 00:18:04 +00001548 // Floating point compare, add '.' and immediate represent for cc
Jack Cartera63b16a2012-09-07 00:23:42 +00001549 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1550 int Cc = ConvertCcString(Format);
1551 if (Cc == -1) {
1552 return Error(NameLoc, "Invalid conditional code");
1553 }
Jack Carter873c7242013-01-12 01:03:14 +00001554 SMLoc E = SMLoc::getFromPointer(
1555 Parser.getTok().getLoc().getPointer() -1 );
Jack Cartera63b16a2012-09-07 00:23:42 +00001556 Operands.push_back(MipsOperand::CreateImm(
1557 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1558 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001559 // trunc, ceil, floor ...
Jack Cartera63b16a2012-09-07 00:23:42 +00001560 return parseMathOperation(Name, NameLoc, Operands);
1561 }
1562
Jack Carter0b744b32012-10-04 02:29:46 +00001563 // the rest is a format
Jack Cartera63b16a2012-09-07 00:23:42 +00001564 Format = Name.slice(Dot, StringRef::npos);
1565 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1566 }
1567
1568 setFpFormat(Format);
1569 }
1570 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001571
1572 // Read the remaining operands.
1573 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1574 // Read the first operand.
Jack Carter1ac53222013-02-20 23:11:17 +00001575 if (ParseOperand(Operands, Mnemonic)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001576 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001577 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001578 return Error(Loc, "unexpected token in argument list");
1579 }
1580
1581 while (getLexer().is(AsmToken::Comma) ) {
1582 Parser.Lex(); // Eat the comma.
1583
1584 // Parse and remember the operand.
1585 if (ParseOperand(Operands, Name)) {
1586 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001587 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001588 return Error(Loc, "unexpected token in argument list");
1589 }
1590 }
1591 }
1592
1593 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1594 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001595 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001596 return Error(Loc, "unexpected token in argument list");
1597 }
1598
1599 Parser.Lex(); // Consume the EndOfStatement
1600 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00001601}
1602
Jack Carter0b744b32012-10-04 02:29:46 +00001603bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1604 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001605 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001606 return Error(Loc, ErrorMsg);
1607}
1608
1609bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd76b2372013-03-21 21:44:16 +00001610 // Line should look like:
Jack Carter0b744b32012-10-04 02:29:46 +00001611 // .set noat
1612 // set at reg to 0
Jack Carter99d2afe2012-10-05 23:55:28 +00001613 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00001614 // eat noat
1615 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001616 // If this is not the end of the statement, report error
Jack Carter0b744b32012-10-04 02:29:46 +00001617 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1618 reportParseError("unexpected token in statement");
1619 return false;
1620 }
1621 Parser.Lex(); // Consume the EndOfStatement
1622 return false;
1623}
1624bool MipsAsmParser::parseSetAtDirective() {
1625 // line can be
1626 // .set at - defaults to $1
1627 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00001628 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00001629 getParser().Lex();
1630 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00001631 Options.setATReg(1);
Jack Carter0b744b32012-10-04 02:29:46 +00001632 Parser.Lex(); // Consume the EndOfStatement
1633 return false;
1634 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd76b2372013-03-21 21:44:16 +00001635 getParser().Lex(); // eat '='
Jack Carter0b744b32012-10-04 02:29:46 +00001636 if (getLexer().isNot(AsmToken::Dollar)) {
1637 reportParseError("unexpected token in statement");
1638 return false;
1639 }
Jack Carterd76b2372013-03-21 21:44:16 +00001640 Parser.Lex(); // Eat '$'
Jack Carter1ac53222013-02-20 23:11:17 +00001641 const AsmToken &Reg = Parser.getTok();
1642 if (Reg.is(AsmToken::Identifier)) {
1643 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
1644 } else if (Reg.is(AsmToken::Integer)) {
1645 AtRegNo = Reg.getIntVal();
1646 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001647 reportParseError("unexpected token in statement");
1648 return false;
1649 }
Jack Carter1ac53222013-02-20 23:11:17 +00001650
1651 if ( AtRegNo < 1 || AtRegNo > 31) {
1652 reportParseError("unexpected token in statement");
1653 return false;
1654 }
1655
1656 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00001657 reportParseError("unexpected token in statement");
1658 return false;
1659 }
Jack Carterd76b2372013-03-21 21:44:16 +00001660 getParser().Lex(); // Eat reg
Jack Carter0b744b32012-10-04 02:29:46 +00001661
1662 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1663 reportParseError("unexpected token in statement");
1664 return false;
1665 }
1666 Parser.Lex(); // Consume the EndOfStatement
1667 return false;
1668 } else {
1669 reportParseError("unexpected token in statement");
1670 return false;
1671 }
1672}
1673
1674bool MipsAsmParser::parseSetReorderDirective() {
1675 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001676 // If this is not the end of the statement, report error
Jack Carter0b744b32012-10-04 02:29:46 +00001677 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1678 reportParseError("unexpected token in statement");
1679 return false;
1680 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001681 Options.setReorder();
Jack Carter0b744b32012-10-04 02:29:46 +00001682 Parser.Lex(); // Consume the EndOfStatement
1683 return false;
1684}
1685
1686bool MipsAsmParser::parseSetNoReorderDirective() {
1687 Parser.Lex();
1688 // if this is not the end of the statement, report error
1689 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1690 reportParseError("unexpected token in statement");
1691 return false;
1692 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001693 Options.setNoreorder();
Jack Carter0b744b32012-10-04 02:29:46 +00001694 Parser.Lex(); // Consume the EndOfStatement
1695 return false;
1696}
1697
1698bool MipsAsmParser::parseSetMacroDirective() {
1699 Parser.Lex();
1700 // if this is not the end of the statement, report error
1701 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1702 reportParseError("unexpected token in statement");
1703 return false;
1704 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001705 Options.setMacro();
Jack Carter0b744b32012-10-04 02:29:46 +00001706 Parser.Lex(); // Consume the EndOfStatement
1707 return false;
1708}
1709
1710bool MipsAsmParser::parseSetNoMacroDirective() {
1711 Parser.Lex();
1712 // if this is not the end of the statement, report error
1713 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1714 reportParseError("`noreorder' must be set before `nomacro'");
1715 return false;
1716 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001717 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00001718 reportParseError("`noreorder' must be set before `nomacro'");
1719 return false;
1720 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001721 Options.setNomacro();
Jack Carter0b744b32012-10-04 02:29:46 +00001722 Parser.Lex(); // Consume the EndOfStatement
1723 return false;
1724}
Jack Carterd76b2372013-03-21 21:44:16 +00001725
1726bool MipsAsmParser::parseSetAssignment() {
1727 StringRef Name;
1728 const MCExpr *Value;
1729
1730 if (Parser.parseIdentifier(Name))
1731 reportParseError("expected identifier after .set");
1732
1733 if (getLexer().isNot(AsmToken::Comma))
1734 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00001735 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00001736
1737 if (Parser.parseExpression(Value))
1738 reportParseError("expected valid expression after comma");
1739
Jack Carterb5cf5902013-04-17 00:18:04 +00001740 // Check if the Name already exists as a symbol
Jack Carterd76b2372013-03-21 21:44:16 +00001741 MCSymbol *Sym = getContext().LookupSymbol(Name);
1742 if (Sym) {
1743 return reportParseError("symbol already defined");
1744 }
1745 Sym = getContext().GetOrCreateSymbol(Name);
1746 Sym->setVariableValue(Value);
1747
1748 return false;
1749}
Jack Carter0b744b32012-10-04 02:29:46 +00001750bool MipsAsmParser::parseDirectiveSet() {
1751
Jack Carterb5cf5902013-04-17 00:18:04 +00001752 // Get next token
Jack Carter0b744b32012-10-04 02:29:46 +00001753 const AsmToken &Tok = Parser.getTok();
1754
1755 if (Tok.getString() == "noat") {
1756 return parseSetNoAtDirective();
1757 } else if (Tok.getString() == "at") {
1758 return parseSetAtDirective();
1759 } else if (Tok.getString() == "reorder") {
1760 return parseSetReorderDirective();
1761 } else if (Tok.getString() == "noreorder") {
1762 return parseSetNoReorderDirective();
1763 } else if (Tok.getString() == "macro") {
1764 return parseSetMacroDirective();
1765 } else if (Tok.getString() == "nomacro") {
1766 return parseSetNoMacroDirective();
1767 } else if (Tok.getString() == "nomips16") {
Jack Carterb5cf5902013-04-17 00:18:04 +00001768 // Ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001769 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001770 return false;
1771 } else if (Tok.getString() == "nomicromips") {
Jack Carterb5cf5902013-04-17 00:18:04 +00001772 // Ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001773 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001774 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001775 } else {
1776 // it is just an identifier, look for assignment
1777 parseSetAssignment();
1778 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001779 }
Jack Carter07c818d2013-01-25 01:31:34 +00001780
Jack Carter0b744b32012-10-04 02:29:46 +00001781 return true;
1782}
1783
Jack Carter07c818d2013-01-25 01:31:34 +00001784/// parseDirectiveWord
1785/// ::= .word [ expression (, expression)* ]
1786bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
1787 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1788 for (;;) {
1789 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001790 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00001791 return true;
1792
1793 getParser().getStreamer().EmitValue(Value, Size);
1794
1795 if (getLexer().is(AsmToken::EndOfStatement))
1796 break;
1797
1798 // FIXME: Improve diagnostic.
1799 if (getLexer().isNot(AsmToken::Comma))
1800 return Error(L, "unexpected token in directive");
1801 Parser.Lex();
1802 }
1803 }
1804
1805 Parser.Lex();
1806 return false;
1807}
1808
Jack Carter0b744b32012-10-04 02:29:46 +00001809bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +00001810
Jack Carter07c818d2013-01-25 01:31:34 +00001811 StringRef IDVal = DirectiveID.getString();
1812
1813 if ( IDVal == ".ent") {
Jack Carterb5cf5902013-04-17 00:18:04 +00001814 // Ignore this directive for now
Jack Carterbe332172012-09-07 00:48:02 +00001815 Parser.Lex();
1816 return false;
1817 }
1818
Jack Carter07c818d2013-01-25 01:31:34 +00001819 if (IDVal == ".end") {
Jack Carterb5cf5902013-04-17 00:18:04 +00001820 // Ignore this directive for now
Jack Carterbe332172012-09-07 00:48:02 +00001821 Parser.Lex();
1822 return false;
1823 }
1824
Jack Carter07c818d2013-01-25 01:31:34 +00001825 if (IDVal == ".frame") {
Jack Carterb5cf5902013-04-17 00:18:04 +00001826 // Ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001827 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001828 return false;
1829 }
1830
Jack Carter07c818d2013-01-25 01:31:34 +00001831 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00001832 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00001833 }
1834
Jack Carter07c818d2013-01-25 01:31:34 +00001835 if (IDVal == ".fmask") {
Jack Carterb5cf5902013-04-17 00:18:04 +00001836 // Ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001837 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001838 return false;
1839 }
1840
Jack Carter07c818d2013-01-25 01:31:34 +00001841 if (IDVal == ".mask") {
Jack Carterb5cf5902013-04-17 00:18:04 +00001842 // Ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001843 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001844 return false;
1845 }
1846
Jack Carter07c818d2013-01-25 01:31:34 +00001847 if (IDVal == ".gpword") {
Jack Carterb5cf5902013-04-17 00:18:04 +00001848 // Ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001849 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001850 return false;
1851 }
1852
Jack Carter07c818d2013-01-25 01:31:34 +00001853 if (IDVal == ".word") {
1854 parseDirectiveWord(4, DirectiveID.getLoc());
1855 return false;
1856 }
1857
Rafael Espindola870c4e92012-01-11 03:56:41 +00001858 return true;
1859}
1860
Rafael Espindola870c4e92012-01-11 03:56:41 +00001861extern "C" void LLVMInitializeMipsAsmParser() {
1862 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1863 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1864 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1865 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1866}
Jack Carterb4dbc172012-09-05 23:34:03 +00001867
1868#define GET_REGISTER_MATCHER
1869#define GET_MATCHER_IMPLEMENTATION
1870#include "MipsGenAsmMatcher.inc"