blob: 088589fbfb13018a8a386292f6dcf7d4ef9eec65 [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 Carterb4dbc172012-09-05 23:34:03 +0000104 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
105 StringRef Mnemonic);
106
Jack Carter873c7242013-01-12 01:03:14 +0000107 int tryParseRegister(bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000108
109 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carter873c7242013-01-12 01:03:14 +0000110 bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000111
Jack Carter30a59822012-10-04 04:03:53 +0000112 bool needsExpansion(MCInst &Inst);
113
114 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000115 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000116 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000117 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000118 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
119 SmallVectorImpl<MCInst> &Instructions);
120 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
121 SmallVectorImpl<MCInst> &Instructions);
Jack Carter0b744b32012-10-04 02:29:46 +0000122 bool reportParseError(StringRef ErrorMsg);
123
Jack Carterdc1e35d2012-09-06 20:00:02 +0000124 bool parseMemOffset(const MCExpr *&Res);
Jack Carter873c7242013-01-12 01:03:14 +0000125 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000126
127 bool parseDirectiveSet();
128
129 bool parseSetAtDirective();
130 bool parseSetNoAtDirective();
131 bool parseSetMacroDirective();
132 bool parseSetNoMacroDirective();
133 bool parseSetReorderDirective();
134 bool parseSetNoReorderDirective();
135
Jack Carter07c818d2013-01-25 01:31:34 +0000136 bool parseDirectiveWord(unsigned Size, SMLoc L);
137
Jack Carterdc1e35d2012-09-06 20:00:02 +0000138 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000139
Jack Carterb4dbc172012-09-05 23:34:03 +0000140 bool isMips64() const {
141 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
142 }
143
Jack Cartera63b16a2012-09-07 00:23:42 +0000144 bool isFP64() const {
145 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
146 }
147
Jack Carter873c7242013-01-12 01:03:14 +0000148 int matchRegisterName(StringRef Symbol, bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000149
Jack Carter1ac53222013-02-20 23:11:17 +0000150 int matchCPURegisterName(StringRef Symbol);
151
Jack Carter873c7242013-01-12 01:03:14 +0000152 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000153
Jack Cartera63b16a2012-09-07 00:23:42 +0000154 void setFpFormat(FpFormatTy Format) {
155 FpFormat = Format;
156 }
157
158 void setDefaultFpFormat();
159
160 void setFpFormat(StringRef Format);
161
162 FpFormatTy getFpFormat() {return FpFormat;}
163
164 bool requestsDoubleOperand(StringRef Mnemonic);
165
Jack Carterb4dbc172012-09-05 23:34:03 +0000166 unsigned getReg(int RC,int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000167
Jack Carter1ac53222013-02-20 23:11:17 +0000168 int getATReg();
Rafael Espindola870c4e92012-01-11 03:56:41 +0000169public:
170 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterb4dbc172012-09-05 23:34:03 +0000171 : MCTargetAsmParser(), STI(sti), Parser(parser) {
172 // Initialize the set of available features.
173 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindola870c4e92012-01-11 03:56:41 +0000174 }
175
Jack Carterb4dbc172012-09-05 23:34:03 +0000176 MCAsmParser &getParser() const { return Parser; }
177 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
178
Rafael Espindola870c4e92012-01-11 03:56:41 +0000179};
180}
181
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000182namespace {
183
184/// MipsOperand - Instances of this class represent a parsed Mips machine
185/// instruction.
186class MipsOperand : public MCParsedAsmOperand {
Jack Carterb4dbc172012-09-05 23:34:03 +0000187
Jack Carter873c7242013-01-12 01:03:14 +0000188public:
189 enum RegisterKind {
190 Kind_None,
191 Kind_CPURegs,
192 Kind_CPU64Regs,
193 Kind_HWRegs,
194 Kind_HW64Regs,
195 Kind_FGR32Regs,
196 Kind_FGR64Regs,
Jack Carter1ac53222013-02-20 23:11:17 +0000197 Kind_AFGR64Regs,
Jack Carter873c7242013-01-12 01:03:14 +0000198 Kind_CCRRegs
199 };
200
201private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000202 enum KindTy {
203 k_CondCode,
204 k_CoprocNum,
205 k_Immediate,
206 k_Memory,
207 k_PostIndexRegister,
208 k_Register,
209 k_Token
210 } Kind;
211
212 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterb4dbc172012-09-05 23:34:03 +0000213
214 union {
215 struct {
216 const char *Data;
217 unsigned Length;
218 } Tok;
219
220 struct {
221 unsigned RegNum;
Jack Carter873c7242013-01-12 01:03:14 +0000222 RegisterKind Kind;
Jack Carterb4dbc172012-09-05 23:34:03 +0000223 } Reg;
224
225 struct {
226 const MCExpr *Val;
227 } Imm;
Jack Carterdc1e35d2012-09-06 20:00:02 +0000228
229 struct {
230 unsigned Base;
231 const MCExpr *Off;
232 } Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000233 };
234
235 SMLoc StartLoc, EndLoc;
236
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000237public:
238 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000239 assert(N == 1 && "Invalid number of operands!");
240 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000241 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000242
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000243 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterb4dbc172012-09-05 23:34:03 +0000244 // Add as immediate when possible. Null MCExpr = 0.
245 if (Expr == 0)
246 Inst.addOperand(MCOperand::CreateImm(0));
247 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
248 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
249 else
250 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000251 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000252
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000253 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000254 assert(N == 1 && "Invalid number of operands!");
255 const MCExpr *Expr = getImm();
256 addExpr(Inst,Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000257 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000258
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000259 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000260 assert(N == 2 && "Invalid number of operands!");
261
262 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
263
264 const MCExpr *Expr = getMemOff();
265 addExpr(Inst,Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000266 }
267
268 bool isReg() const { return Kind == k_Register; }
269 bool isImm() const { return Kind == k_Immediate; }
270 bool isToken() const { return Kind == k_Token; }
271 bool isMem() const { return Kind == k_Memory; }
272
273 StringRef getToken() const {
274 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000275 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000276 }
277
278 unsigned getReg() const {
279 assert((Kind == k_Register) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000280 return Reg.RegNum;
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000281 }
282
Jack Carter873c7242013-01-12 01:03:14 +0000283 void setRegKind(RegisterKind RegKind) {
284 assert((Kind == k_Register) && "Invalid access!");
285 Reg.Kind = RegKind;
286 }
287
Jack Carterb4dbc172012-09-05 23:34:03 +0000288 const MCExpr *getImm() const {
289 assert((Kind == k_Immediate) && "Invalid access!");
290 return Imm.Val;
291 }
292
Jack Carterdc1e35d2012-09-06 20:00:02 +0000293 unsigned getMemBase() const {
294 assert((Kind == k_Memory) && "Invalid access!");
295 return Mem.Base;
296 }
297
298 const MCExpr *getMemOff() const {
299 assert((Kind == k_Memory) && "Invalid access!");
300 return Mem.Off;
301 }
302
Jack Carterb4dbc172012-09-05 23:34:03 +0000303 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
304 MipsOperand *Op = new MipsOperand(k_Token);
305 Op->Tok.Data = Str.data();
306 Op->Tok.Length = Str.size();
307 Op->StartLoc = S;
308 Op->EndLoc = S;
309 return Op;
310 }
311
312 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
313 MipsOperand *Op = new MipsOperand(k_Register);
314 Op->Reg.RegNum = RegNum;
315 Op->StartLoc = S;
316 Op->EndLoc = E;
317 return Op;
318 }
319
320 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
321 MipsOperand *Op = new MipsOperand(k_Immediate);
322 Op->Imm.Val = Val;
323 Op->StartLoc = S;
324 Op->EndLoc = E;
325 return Op;
326 }
327
Jack Carterdc1e35d2012-09-06 20:00:02 +0000328 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
329 SMLoc S, SMLoc E) {
330 MipsOperand *Op = new MipsOperand(k_Memory);
331 Op->Mem.Base = Base;
332 Op->Mem.Off = Off;
333 Op->StartLoc = S;
334 Op->EndLoc = E;
335 return Op;
336 }
337
Jack Carter873c7242013-01-12 01:03:14 +0000338 bool isCPURegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000339 return Kind == k_Register && Reg.Kind == Kind_CPURegs;
Jack Carter873c7242013-01-12 01:03:14 +0000340 }
341 void addCPURegsAsmOperands(MCInst &Inst, unsigned N) const {
342 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
343 }
344
345 bool isCPU64RegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000346 return Kind == k_Register && Reg.Kind == Kind_CPU64Regs;
Jack Carter873c7242013-01-12 01:03:14 +0000347 }
348 void addCPU64RegsAsmOperands(MCInst &Inst, unsigned N) const {
349 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
350 }
351
352 bool isHWRegsAsm() const {
353 assert((Kind == k_Register) && "Invalid access!");
354 return Reg.Kind == Kind_HWRegs;
355 }
356 void addHWRegsAsmOperands(MCInst &Inst, unsigned N) const {
357 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
358 }
359
360 bool isHW64RegsAsm() const {
361 assert((Kind == k_Register) && "Invalid access!");
362 return Reg.Kind == Kind_HW64Regs;
363 }
364 void addHW64RegsAsmOperands(MCInst &Inst, unsigned N) const {
365 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
366 }
367
368 void addCCRAsmOperands(MCInst &Inst, unsigned N) const {
369 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
370 }
371
372 bool isCCRAsm() const {
373 assert((Kind == k_Register) && "Invalid access!");
374 return Reg.Kind == Kind_CCRRegs;
375 }
376
Jack Carterb4dbc172012-09-05 23:34:03 +0000377 /// getStartLoc - Get the location of the first token of this operand.
378 SMLoc getStartLoc() const { return StartLoc; }
379 /// getEndLoc - Get the location of the last token of this operand.
380 SMLoc getEndLoc() const { return EndLoc; }
381
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000382 virtual void print(raw_ostream &OS) const {
383 llvm_unreachable("unimplemented!");
384 }
385};
386}
387
Jack Carter30a59822012-10-04 04:03:53 +0000388bool MipsAsmParser::needsExpansion(MCInst &Inst) {
389
390 switch(Inst.getOpcode()) {
391 case Mips::LoadImm32Reg:
Jack Carter543fdf82012-10-09 23:29:45 +0000392 case Mips::LoadAddr32Imm:
393 case Mips::LoadAddr32Reg:
Jack Carter30a59822012-10-04 04:03:53 +0000394 return true;
395 default:
396 return false;
397 }
398}
Jack Carter92995f12012-10-06 00:53:28 +0000399
Jack Carter30a59822012-10-04 04:03:53 +0000400void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000401 SmallVectorImpl<MCInst> &Instructions){
Jack Carter30a59822012-10-04 04:03:53 +0000402 switch(Inst.getOpcode()) {
403 case Mips::LoadImm32Reg:
404 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000405 case Mips::LoadAddr32Imm:
406 return expandLoadAddressImm(Inst,IDLoc,Instructions);
407 case Mips::LoadAddr32Reg:
408 return expandLoadAddressReg(Inst,IDLoc,Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000409 }
Jack Carter30a59822012-10-04 04:03:53 +0000410}
Jack Carter92995f12012-10-06 00:53:28 +0000411
Jack Carter30a59822012-10-04 04:03:53 +0000412void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000413 SmallVectorImpl<MCInst> &Instructions){
Jack Carter92995f12012-10-06 00:53:28 +0000414 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000415 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000416 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000417 const MCOperand &RegOp = Inst.getOperand(0);
418 assert(RegOp.isReg() && "expected register operand kind");
419
420 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000421 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000422 if ( 0 <= ImmValue && ImmValue <= 65535) {
Jack Carter92995f12012-10-06 00:53:28 +0000423 // for 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000424 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000425 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000426 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
427 tmpInst.addOperand(
Jack Carter873c7242013-01-12 01:03:14 +0000428 MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000429 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000430 Instructions.push_back(tmpInst);
431 } else if ( ImmValue < 0 && ImmValue >= -32768) {
Jack Carter92995f12012-10-06 00:53:28 +0000432 // for -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000433 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000434 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000435 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
436 tmpInst.addOperand(
Jack Carter873c7242013-01-12 01:03:14 +0000437 MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000438 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000439 Instructions.push_back(tmpInst);
440 } else {
441 // for any other value of j that is representable as a 32-bit integer.
442 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000443 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000444 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000445 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
446 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000447 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000448 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000449 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000450 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
451 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
452 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
453 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000454 Instructions.push_back(tmpInst);
455 }
456}
Jack Carter92995f12012-10-06 00:53:28 +0000457
Jack Carter543fdf82012-10-09 23:29:45 +0000458void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
459 SmallVectorImpl<MCInst> &Instructions){
460 MCInst tmpInst;
461 const MCOperand &ImmOp = Inst.getOperand(2);
462 assert(ImmOp.isImm() && "expected immediate operand kind");
463 const MCOperand &SrcRegOp = Inst.getOperand(1);
464 assert(SrcRegOp.isReg() && "expected register operand kind");
465 const MCOperand &DstRegOp = Inst.getOperand(0);
466 assert(DstRegOp.isReg() && "expected register operand kind");
467 int ImmValue = ImmOp.getImm();
468 if ( -32768 <= ImmValue && ImmValue <= 65535) {
469 //for -32768 <= j <= 65535.
470 //la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000471 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000472 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
473 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
474 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
475 Instructions.push_back(tmpInst);
476 } else {
477 //for any other value of j that is representable as a 32-bit integer.
478 //la d,j(s) => lui d,hi16(j)
479 // ori d,d,lo16(j)
480 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000481 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000482 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
483 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
484 Instructions.push_back(tmpInst);
485 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000486 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000487 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
488 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
489 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
490 Instructions.push_back(tmpInst);
491 tmpInst.clear();
492 tmpInst.setOpcode(Mips::ADDu);
493 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
494 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
495 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
496 Instructions.push_back(tmpInst);
497 }
498}
499
500void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
501 SmallVectorImpl<MCInst> &Instructions){
502 MCInst tmpInst;
503 const MCOperand &ImmOp = Inst.getOperand(1);
504 assert(ImmOp.isImm() && "expected immediate operand kind");
505 const MCOperand &RegOp = Inst.getOperand(0);
506 assert(RegOp.isReg() && "expected register operand kind");
507 int ImmValue = ImmOp.getImm();
508 if ( -32768 <= ImmValue && ImmValue <= 65535) {
509 //for -32768 <= j <= 65535.
510 //la d,j => addiu d,$zero,j
511 tmpInst.setOpcode(Mips::ADDiu);
512 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
513 tmpInst.addOperand(
Jack Carter873c7242013-01-12 01:03:14 +0000514 MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +0000515 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
516 Instructions.push_back(tmpInst);
517 } else {
518 //for any other value of j that is representable as a 32-bit integer.
519 //la d,j => lui d,hi16(j)
520 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000521 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000522 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
523 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
524 Instructions.push_back(tmpInst);
525 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000526 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000527 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
528 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
529 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
530 Instructions.push_back(tmpInst);
531 }
532}
533
Rafael Espindola870c4e92012-01-11 03:56:41 +0000534bool MipsAsmParser::
Chad Rosier49963552012-10-13 00:26:04 +0000535MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +0000536 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +0000537 MCStreamer &Out, unsigned &ErrorInfo,
538 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000539 MCInst Inst;
Chad Rosier2f480a82012-10-12 22:53:36 +0000540 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier49963552012-10-13 00:26:04 +0000541 MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +0000542
543 switch (MatchResult) {
544 default: break;
545 case Match_Success: {
Jack Carter30a59822012-10-04 04:03:53 +0000546 if (needsExpansion(Inst)) {
Jack Carter92995f12012-10-06 00:53:28 +0000547 SmallVector<MCInst, 4> Instructions;
Jack Carter30a59822012-10-04 04:03:53 +0000548 expandInstruction(Inst, IDLoc, Instructions);
549 for(unsigned i =0; i < Instructions.size(); i++){
Jack Carter92995f12012-10-06 00:53:28 +0000550 Out.EmitInstruction(Instructions[i]);
Jack Carter30a59822012-10-04 04:03:53 +0000551 }
552 } else {
553 Inst.setLoc(IDLoc);
554 Out.EmitInstruction(Inst);
555 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000556 return false;
557 }
558 case Match_MissingFeature:
559 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
560 return true;
561 case Match_InvalidOperand: {
562 SMLoc ErrorLoc = IDLoc;
563 if (ErrorInfo != ~0U) {
564 if (ErrorInfo >= Operands.size())
565 return Error(IDLoc, "too few operands for instruction");
566
567 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
568 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
569 }
570
571 return Error(ErrorLoc, "invalid operand for instruction");
572 }
573 case Match_MnemonicFail:
574 return Error(IDLoc, "invalid instruction");
575 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000576 return true;
577}
578
Jack Carter1ac53222013-02-20 23:11:17 +0000579int MipsAsmParser::matchCPURegisterName(StringRef Name) {
580 int CC;
581
582 if (Name == "at")
583 return getATReg();
584
585 CC = StringSwitch<unsigned>(Name)
586 .Case("zero", 0)
587 .Case("a0", 4)
588 .Case("a1", 5)
589 .Case("a2", 6)
590 .Case("a3", 7)
591 .Case("v0", 2)
592 .Case("v1", 3)
593 .Case("s0", 16)
594 .Case("s1", 17)
595 .Case("s2", 18)
596 .Case("s3", 19)
597 .Case("s4", 20)
598 .Case("s5", 21)
599 .Case("s6", 22)
600 .Case("s7", 23)
601 .Case("k0", 26)
602 .Case("k1", 27)
603 .Case("sp", 29)
604 .Case("fp", 30)
605 .Case("gp", 28)
606 .Case("ra", 31)
607 .Case("t0", 8)
608 .Case("t1", 9)
609 .Case("t2", 10)
610 .Case("t3", 11)
611 .Case("t4", 12)
612 .Case("t5", 13)
613 .Case("t6", 14)
614 .Case("t7", 15)
615 .Case("t8", 24)
616 .Case("t9", 25)
617 .Default(-1);
618
619 // Although SGI documentation just cut out t0-t3 for n32/n64,
620 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
621 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
622 if (isMips64() && 8 <= CC && CC <= 11)
623 CC += 4;
624
625 if (CC == -1 && isMips64())
626 CC = StringSwitch<unsigned>(Name)
627 .Case("a4", 8)
628 .Case("a5", 9)
629 .Case("a6", 10)
630 .Case("a7", 11)
631 .Case("kt0", 26)
632 .Case("kt1", 27)
633 .Case("s8", 30)
634 .Default(-1);
635
636 return CC;
637}
Jack Carter873c7242013-01-12 01:03:14 +0000638int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000639
Jack Carter1ac53222013-02-20 23:11:17 +0000640 int CC;
641 CC = matchCPURegisterName(Name);
David Chisnall37051252012-10-09 16:27:43 +0000642 if (CC != -1)
Jack Carter1ac53222013-02-20 23:11:17 +0000643 return matchRegisterByNumber(CC,is64BitReg?Mips::CPU64RegsRegClassID:
644 Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000645
Jack Cartera63b16a2012-09-07 00:23:42 +0000646 if (Name[0] == 'f') {
647 StringRef NumString = Name.substr(1);
648 unsigned IntVal;
649 if( NumString.getAsInteger(10, IntVal))
Jack Carter30a59822012-10-04 04:03:53 +0000650 return -1; // not integer
Jack Cartera63b16a2012-09-07 00:23:42 +0000651 if (IntVal > 31)
652 return -1;
653
654 FpFormatTy Format = getFpFormat();
655
656 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
657 return getReg(Mips::FGR32RegClassID, IntVal);
658 if (Format == FP_FORMAT_D) {
659 if(isFP64()) {
660 return getReg(Mips::FGR64RegClassID, IntVal);
661 }
Jack Carter30a59822012-10-04 04:03:53 +0000662 // only even numbers available as register pairs
Jack Cartera63b16a2012-09-07 00:23:42 +0000663 if (( IntVal > 31) || (IntVal%2 != 0))
664 return -1;
665 return getReg(Mips::AFGR64RegClassID, IntVal/2);
666 }
667 }
668
Jack Carterb4dbc172012-09-05 23:34:03 +0000669 return -1;
670}
Jack Cartera63b16a2012-09-07 00:23:42 +0000671void MipsAsmParser::setDefaultFpFormat() {
672
673 if (isMips64() || isFP64())
674 FpFormat = FP_FORMAT_D;
675 else
676 FpFormat = FP_FORMAT_S;
677}
678
679bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
680
681 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
682 .Case("ldxc1", true)
683 .Case("ldc1", true)
684 .Case("sdxc1", true)
685 .Case("sdc1", true)
686 .Default(false);
687
688 return IsDouble;
689}
690void MipsAsmParser::setFpFormat(StringRef Format) {
691
692 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
693 .Case(".s", FP_FORMAT_S)
694 .Case(".d", FP_FORMAT_D)
695 .Case(".l", FP_FORMAT_L)
696 .Case(".w", FP_FORMAT_W)
697 .Default(FP_FORMAT_NONE);
698}
Jack Carterb4dbc172012-09-05 23:34:03 +0000699
Jack Carter0b744b32012-10-04 02:29:46 +0000700bool MipsAssemblerOptions::setATReg(unsigned Reg) {
701 if (Reg > 31)
702 return false;
703
704 aTReg = Reg;
705 return true;
706}
707
Jack Carter1ac53222013-02-20 23:11:17 +0000708int MipsAsmParser::getATReg() {
709 return Options.getATRegNum();
Jack Carter0b744b32012-10-04 02:29:46 +0000710}
711
712unsigned MipsAsmParser::getReg(int RC,int RegNo) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000713 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
714}
715
Jack Carter873c7242013-01-12 01:03:14 +0000716int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000717
718 if (RegNum > 31)
719 return -1;
720
Jack Carter873c7242013-01-12 01:03:14 +0000721 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +0000722}
723
Jack Carter873c7242013-01-12 01:03:14 +0000724int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000725 const AsmToken &Tok = Parser.getTok();
726 int RegNum = -1;
727
728 if (Tok.is(AsmToken::Identifier)) {
729 std::string lowerCase = Tok.getString().lower();
Jack Carter873c7242013-01-12 01:03:14 +0000730 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000731 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +0000732 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carter873c7242013-01-12 01:03:14 +0000733 is64BitReg ? Mips::CPU64RegsRegClassID
734 : Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000735 return RegNum;
736}
737
Rafael Espindola870c4e92012-01-11 03:56:41 +0000738bool MipsAsmParser::
Jack Carterb4dbc172012-09-05 23:34:03 +0000739 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carter873c7242013-01-12 01:03:14 +0000740 bool is64BitReg){
Jack Carterb4dbc172012-09-05 23:34:03 +0000741
742 SMLoc S = Parser.getTok().getLoc();
743 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +0000744
Jack Carter873c7242013-01-12 01:03:14 +0000745 RegNo = tryParseRegister(is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000746 if (RegNo == -1)
747 return true;
748
Jack Carter873c7242013-01-12 01:03:14 +0000749 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
750 Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000751 Parser.Lex(); // Eat register token.
752 return false;
753}
754
755bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
756 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +0000757 // Check if the current operand has a custom associated parser, if so, try to
758 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +0000759 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
760 if (ResTy == MatchOperand_Success)
761 return false;
762 // If there wasn't a custom match, try the generic matcher below. Otherwise,
763 // there was a match, but an error occurred, in which case, just return that
764 // the operand parsing failed.
765 if (ResTy == MatchOperand_ParseFail)
766 return true;
767
768 switch (getLexer().getKind()) {
769 default:
770 Error(Parser.getTok().getLoc(), "unexpected token in operand");
771 return true;
772 case AsmToken::Dollar: {
Jack Carter30a59822012-10-04 04:03:53 +0000773 // parse register
Jack Carterb4dbc172012-09-05 23:34:03 +0000774 SMLoc S = Parser.getTok().getLoc();
775 Parser.Lex(); // Eat dollar token.
Jack Carter30a59822012-10-04 04:03:53 +0000776 // parse register operand
Jack Carter873c7242013-01-12 01:03:14 +0000777 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000778 if (getLexer().is(AsmToken::LParen)) {
Jack Carter30a59822012-10-04 04:03:53 +0000779 // check if it is indexed addressing operand
Jack Carterb4dbc172012-09-05 23:34:03 +0000780 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carter30a59822012-10-04 04:03:53 +0000781 Parser.Lex(); // eat parenthesis
Jack Carterb4dbc172012-09-05 23:34:03 +0000782 if (getLexer().isNot(AsmToken::Dollar))
783 return true;
784
Jack Carter30a59822012-10-04 04:03:53 +0000785 Parser.Lex(); // eat dollar
Jack Carter873c7242013-01-12 01:03:14 +0000786 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterb4dbc172012-09-05 23:34:03 +0000787 return true;
788
789 if (!getLexer().is(AsmToken::RParen))
790 return true;
791
792 S = Parser.getTok().getLoc();
793 Operands.push_back(MipsOperand::CreateToken(")", S));
794 Parser.Lex();
795 }
796 return false;
797 }
Jack Carter30a59822012-10-04 04:03:53 +0000798 // maybe it is a symbol reference
Jack Carterb4dbc172012-09-05 23:34:03 +0000799 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000800 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +0000801 return true;
802
Jack Carter873c7242013-01-12 01:03:14 +0000803 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000804
Benjamin Kramerfa530572012-09-07 09:47:42 +0000805 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterb4dbc172012-09-05 23:34:03 +0000806
807 // Otherwise create a symbol ref.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000808 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterb4dbc172012-09-05 23:34:03 +0000809 getContext());
810
811 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
812 return false;
813 }
814 case AsmToken::Identifier:
815 case AsmToken::LParen:
816 case AsmToken::Minus:
817 case AsmToken::Plus:
818 case AsmToken::Integer:
819 case AsmToken::String: {
820 // quoted label names
821 const MCExpr *IdVal;
822 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000823 if (getParser().parseExpression(IdVal))
Jack Carterb4dbc172012-09-05 23:34:03 +0000824 return true;
Jack Carter873c7242013-01-12 01:03:14 +0000825 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000826 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
827 return false;
828 }
Jack Carterdc1e35d2012-09-06 20:00:02 +0000829 case AsmToken::Percent: {
Jack Carter30a59822012-10-04 04:03:53 +0000830 // it is a symbol reference or constant expression
Jack Carterdc1e35d2012-09-06 20:00:02 +0000831 const MCExpr *IdVal;
Jack Carter30a59822012-10-04 04:03:53 +0000832 SMLoc S = Parser.getTok().getLoc(); // start location of the operand
Jack Carter873c7242013-01-12 01:03:14 +0000833 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +0000834 return true;
835
Jack Carter873c7242013-01-12 01:03:14 +0000836 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
837
Jack Carterdc1e35d2012-09-06 20:00:02 +0000838 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
839 return false;
Jack Carter0b744b32012-10-04 02:29:46 +0000840 } // case AsmToken::Percent
841 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +0000842 return true;
843}
844
Jack Carter873c7242013-01-12 01:03:14 +0000845bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000846
Jack Carter0b744b32012-10-04 02:29:46 +0000847 Parser.Lex(); // eat % token
Jack Carter30a59822012-10-04 04:03:53 +0000848 const AsmToken &Tok = Parser.getTok(); // get next token, operation
Jack Carterdc1e35d2012-09-06 20:00:02 +0000849 if (Tok.isNot(AsmToken::Identifier))
850 return true;
851
Benjamin Kramerfa530572012-09-07 09:47:42 +0000852 std::string Str = Tok.getIdentifier().str();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000853
Jack Carter30a59822012-10-04 04:03:53 +0000854 Parser.Lex(); // eat identifier
Jack Carter0b744b32012-10-04 02:29:46 +0000855 // now make expression from the rest of the operand
Jack Carterdc1e35d2012-09-06 20:00:02 +0000856 const MCExpr *IdVal;
Jack Carter873c7242013-01-12 01:03:14 +0000857 SMLoc EndLoc;
Jack Carterdc1e35d2012-09-06 20:00:02 +0000858
859 if (getLexer().getKind() == AsmToken::LParen) {
860 while (1) {
Jack Carter0b744b32012-10-04 02:29:46 +0000861 Parser.Lex(); // eat '(' token
Jack Carterdc1e35d2012-09-06 20:00:02 +0000862 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carter0b744b32012-10-04 02:29:46 +0000863 Parser.Lex(); // eat % token
Jack Carterdc1e35d2012-09-06 20:00:02 +0000864 const AsmToken &nextTok = Parser.getTok();
865 if (nextTok.isNot(AsmToken::Identifier))
866 return true;
Benjamin Kramerfa530572012-09-07 09:47:42 +0000867 Str += "(%";
868 Str += nextTok.getIdentifier();
Jack Carter0b744b32012-10-04 02:29:46 +0000869 Parser.Lex(); // eat identifier
Jack Carterdc1e35d2012-09-06 20:00:02 +0000870 if (getLexer().getKind() != AsmToken::LParen)
871 return true;
872 } else
873 break;
874 }
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000875 if (getParser().parseParenExpression(IdVal,EndLoc))
Jack Carterdc1e35d2012-09-06 20:00:02 +0000876 return true;
877
Jack Carter873c7242013-01-12 01:03:14 +0000878 while (getLexer().getKind() == AsmToken::RParen)
Jack Carter0b744b32012-10-04 02:29:46 +0000879 Parser.Lex(); // eat ')' token
Jack Carterdc1e35d2012-09-06 20:00:02 +0000880
881 } else
Jack Carter0b744b32012-10-04 02:29:46 +0000882 return true; // parenthesis must follow reloc operand
Jack Carterdc1e35d2012-09-06 20:00:02 +0000883
Jack Carter0b744b32012-10-04 02:29:46 +0000884 // Check the type of the expression
Benjamin Kramerfa530572012-09-07 09:47:42 +0000885 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carter30a59822012-10-04 04:03:53 +0000886 // it's a constant, evaluate lo or hi value
Benjamin Kramerfa530572012-09-07 09:47:42 +0000887 int Val = MCE->getValue();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000888 if (Str == "lo") {
889 Val = Val & 0xffff;
890 } else if (Str == "hi") {
891 Val = (Val & 0xffff0000) >> 16;
892 }
893 Res = MCConstantExpr::Create(Val, getContext());
894 return false;
895 }
896
Benjamin Kramerfa530572012-09-07 09:47:42 +0000897 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter0b744b32012-10-04 02:29:46 +0000898 // it's a symbol, create symbolic expression from symbol
Benjamin Kramerfa530572012-09-07 09:47:42 +0000899 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000900 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
901 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
902 return false;
903 }
904 return true;
905}
906
Jack Carterb4dbc172012-09-05 23:34:03 +0000907bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
908 SMLoc &EndLoc) {
909
910 StartLoc = Parser.getTok().getLoc();
Jack Carter873c7242013-01-12 01:03:14 +0000911 RegNo = tryParseRegister(isMips64());
912 EndLoc = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +0000913 return (RegNo == (unsigned)-1);
914}
915
Jack Carterdc1e35d2012-09-06 20:00:02 +0000916bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
Jack Carter873c7242013-01-12 01:03:14 +0000917
918 SMLoc S;
919
Jack Carterdc1e35d2012-09-06 20:00:02 +0000920 switch(getLexer().getKind()) {
921 default:
922 return true;
923 case AsmToken::Integer:
924 case AsmToken::Minus:
925 case AsmToken::Plus:
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000926 return (getParser().parseExpression(Res));
Jack Carter873c7242013-01-12 01:03:14 +0000927 case AsmToken::Percent:
928 return parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +0000929 case AsmToken::LParen:
Jack Carter0b744b32012-10-04 02:29:46 +0000930 return false; // it's probably assuming 0
Jack Carterdc1e35d2012-09-06 20:00:02 +0000931 }
932 return true;
933}
934
Jack Carterb4dbc172012-09-05 23:34:03 +0000935MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
936 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000937
938 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +0000939 SMLoc S;
940 // first operand is the offset
941 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000942
943 if (parseMemOffset(IdVal))
944 return MatchOperand_ParseFail;
945
Jack Carter0b744b32012-10-04 02:29:46 +0000946 const AsmToken &Tok = Parser.getTok(); // get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +0000947 if (Tok.isNot(AsmToken::LParen)) {
Jack Carter543fdf82012-10-09 23:29:45 +0000948 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
949 if (Mnemonic->getToken() == "la") {
Jack Carter873c7242013-01-12 01:03:14 +0000950 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() -1);
Jack Carter543fdf82012-10-09 23:29:45 +0000951 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
952 return MatchOperand_Success;
953 }
Jack Carterdc1e35d2012-09-06 20:00:02 +0000954 Error(Parser.getTok().getLoc(), "'(' expected");
955 return MatchOperand_ParseFail;
956 }
957
958 Parser.Lex(); // Eat '(' token.
959
Jack Carter543fdf82012-10-09 23:29:45 +0000960 const AsmToken &Tok1 = Parser.getTok(); // get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +0000961 if (Tok1.is(AsmToken::Dollar)) {
962 Parser.Lex(); // Eat '$' token.
Jack Carter873c7242013-01-12 01:03:14 +0000963 if (tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000964 Error(Parser.getTok().getLoc(), "unexpected token in operand");
965 return MatchOperand_ParseFail;
966 }
967
968 } else {
Jack Carter0b744b32012-10-04 02:29:46 +0000969 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carterdc1e35d2012-09-06 20:00:02 +0000970 return MatchOperand_ParseFail;
971 }
972
Jack Carter0b744b32012-10-04 02:29:46 +0000973 const AsmToken &Tok2 = Parser.getTok(); // get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +0000974 if (Tok2.isNot(AsmToken::RParen)) {
975 Error(Parser.getTok().getLoc(), "')' expected");
976 return MatchOperand_ParseFail;
977 }
978
Jack Carter873c7242013-01-12 01:03:14 +0000979 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
980
Jack Carterdc1e35d2012-09-06 20:00:02 +0000981 Parser.Lex(); // Eat ')' token.
982
983 if (IdVal == 0)
984 IdVal = MCConstantExpr::Create(0, getContext());
985
Jack Carter0b744b32012-10-04 02:29:46 +0000986 // now replace register operand with the mem operand
Jack Carterdc1e35d2012-09-06 20:00:02 +0000987 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
988 int RegNo = op->getReg();
Jack Carter0b744b32012-10-04 02:29:46 +0000989 // remove register from operands
Jack Carterdc1e35d2012-09-06 20:00:02 +0000990 Operands.pop_back();
Jack Carter0b744b32012-10-04 02:29:46 +0000991 // and add memory operand
Jack Carterdc1e35d2012-09-06 20:00:02 +0000992 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
993 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +0000994 return MatchOperand_Success;
995}
996
Jack Carter873c7242013-01-12 01:03:14 +0000997MipsAsmParser::OperandMatchResultTy
998MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
999
1000 if (!isMips64())
1001 return MatchOperand_NoMatch;
1002 // if the first token is not '$' we have an error
1003 if (Parser.getTok().isNot(AsmToken::Dollar))
1004 return MatchOperand_NoMatch;
1005
1006 Parser.Lex(); // Eat $
1007 if(!tryParseRegisterOperand(Operands, true)) {
1008 // set the proper register kind
1009 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1010 op->setRegKind(MipsOperand::Kind_CPU64Regs);
1011 return MatchOperand_Success;
1012 }
1013 return MatchOperand_NoMatch;
1014}
1015
1016MipsAsmParser::OperandMatchResultTy
1017MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1018
1019 // if the first token is not '$' we have an error
1020 if (Parser.getTok().isNot(AsmToken::Dollar))
1021 return MatchOperand_NoMatch;
1022
1023 Parser.Lex(); // Eat $
1024 if(!tryParseRegisterOperand(Operands, false)) {
1025 // set the propper register kind
1026 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1027 op->setRegKind(MipsOperand::Kind_CPURegs);
1028 return MatchOperand_Success;
1029 }
1030 return MatchOperand_NoMatch;
1031}
1032
1033MipsAsmParser::OperandMatchResultTy
1034MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1035
Jack Carter2a74a87b2013-01-17 00:28:20 +00001036 if (isMips64())
1037 return MatchOperand_NoMatch;
1038
Jack Carter873c7242013-01-12 01:03:14 +00001039 // if the first token is not '$' we have error
1040 if (Parser.getTok().isNot(AsmToken::Dollar))
1041 return MatchOperand_NoMatch;
1042 SMLoc S = Parser.getTok().getLoc();
1043 Parser.Lex(); // Eat $
1044
1045 const AsmToken &Tok = Parser.getTok(); // get next token
1046 if (Tok.isNot(AsmToken::Integer))
1047 return MatchOperand_NoMatch;
1048
1049 unsigned RegNum = Tok.getIntVal();
1050 // at the moment only hwreg29 is supported
1051 if (RegNum != 29)
1052 return MatchOperand_ParseFail;
1053
1054 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
1055 Parser.getTok().getLoc());
1056 op->setRegKind(MipsOperand::Kind_HWRegs);
1057 Operands.push_back(op);
1058
1059 Parser.Lex(); // Eat reg number
1060 return MatchOperand_Success;
1061}
1062
1063MipsAsmParser::OperandMatchResultTy
1064MipsAsmParser::parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter2a74a87b2013-01-17 00:28:20 +00001065
1066 if (!isMips64())
1067 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001068 //if the first token is not '$' we have error
1069 if (Parser.getTok().isNot(AsmToken::Dollar))
1070 return MatchOperand_NoMatch;
1071 SMLoc S = Parser.getTok().getLoc();
1072 Parser.Lex(); // Eat $
1073
1074 const AsmToken &Tok = Parser.getTok(); // get next token
1075 if (Tok.isNot(AsmToken::Integer))
1076 return MatchOperand_NoMatch;
1077
1078 unsigned RegNum = Tok.getIntVal();
1079 // at the moment only hwreg29 is supported
1080 if (RegNum != 29)
1081 return MatchOperand_ParseFail;
1082
1083 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
1084 Parser.getTok().getLoc());
Jack Carter2a74a87b2013-01-17 00:28:20 +00001085 op->setRegKind(MipsOperand::Kind_HW64Regs);
Jack Carter873c7242013-01-12 01:03:14 +00001086 Operands.push_back(op);
1087
1088 Parser.Lex(); // Eat reg number
1089 return MatchOperand_Success;
1090}
1091
1092MipsAsmParser::OperandMatchResultTy
1093MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1094 unsigned RegNum;
1095 //if the first token is not '$' we have error
1096 if (Parser.getTok().isNot(AsmToken::Dollar))
1097 return MatchOperand_NoMatch;
1098 SMLoc S = Parser.getTok().getLoc();
1099 Parser.Lex(); // Eat $
1100
1101 const AsmToken &Tok = Parser.getTok(); // get next token
1102 if (Tok.is(AsmToken::Integer)) {
1103 RegNum = Tok.getIntVal();
1104 // at the moment only fcc0 is supported
1105 if (RegNum != 0)
1106 return MatchOperand_ParseFail;
1107 } else if (Tok.is(AsmToken::Identifier)) {
1108 // at the moment only fcc0 is supported
1109 if (Tok.getIdentifier() != "fcc0")
1110 return MatchOperand_ParseFail;
1111 } else
1112 return MatchOperand_NoMatch;
1113
1114 MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
1115 Parser.getTok().getLoc());
1116 op->setRegKind(MipsOperand::Kind_CCRRegs);
1117 Operands.push_back(op);
1118
1119 Parser.Lex(); // Eat reg number
1120 return MatchOperand_Success;
1121}
1122
Jack Carterdc1e35d2012-09-06 20:00:02 +00001123MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1124
1125 MCSymbolRefExpr::VariantKind VK
1126 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1127 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1128 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1129 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1130 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1131 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1132 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1133 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1134 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1135 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1136 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1137 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1138 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1139 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1140 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1141 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1142 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1143 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1144 .Default(MCSymbolRefExpr::VK_None);
1145
1146 return VK;
1147}
1148
Benjamin Kramer47b5c572012-09-10 11:52:14 +00001149static int ConvertCcString(StringRef CondString) {
Jack Cartera63b16a2012-09-07 00:23:42 +00001150 int CC = StringSwitch<unsigned>(CondString)
1151 .Case(".f", 0)
1152 .Case(".un", 1)
1153 .Case(".eq", 2)
1154 .Case(".ueq", 3)
1155 .Case(".olt", 4)
1156 .Case(".ult", 5)
1157 .Case(".ole", 6)
1158 .Case(".ule", 7)
1159 .Case(".sf", 8)
1160 .Case(".ngle", 9)
1161 .Case(".seq", 10)
1162 .Case(".ngl", 11)
1163 .Case(".lt", 12)
1164 .Case(".nge", 13)
1165 .Case(".le", 14)
1166 .Case(".ngt", 15)
1167 .Default(-1);
1168
1169 return CC;
1170}
1171
1172bool MipsAsmParser::
1173parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter0b744b32012-10-04 02:29:46 +00001174 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1175 // split the format
Jack Cartera63b16a2012-09-07 00:23:42 +00001176 size_t Start = Name.find('.'), Next = Name.rfind('.');
1177 StringRef Format1 = Name.slice(Start, Next);
Jack Carter0b744b32012-10-04 02:29:46 +00001178 // and add the first format to the operands
Jack Cartera63b16a2012-09-07 00:23:42 +00001179 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carter0b744b32012-10-04 02:29:46 +00001180 // now for the second format
Jack Cartera63b16a2012-09-07 00:23:42 +00001181 StringRef Format2 = Name.slice(Next, StringRef::npos);
1182 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1183
Jack Carter0b744b32012-10-04 02:29:46 +00001184 // set the format for the first register
Jack Cartera63b16a2012-09-07 00:23:42 +00001185 setFpFormat(Format1);
1186
1187 // Read the remaining operands.
1188 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1189 // Read the first operand.
1190 if (ParseOperand(Operands, Name)) {
1191 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001192 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001193 return Error(Loc, "unexpected token in argument list");
1194 }
1195
1196 if (getLexer().isNot(AsmToken::Comma)) {
1197 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001198 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001199 return Error(Loc, "unexpected token in argument list");
1200
1201 }
1202 Parser.Lex(); // Eat the comma.
1203
1204 //set the format for the first register
1205 setFpFormat(Format2);
1206
1207 // Parse and remember the operand.
1208 if (ParseOperand(Operands, Name)) {
1209 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001210 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001211 return Error(Loc, "unexpected token in argument list");
1212 }
1213 }
1214
1215 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1216 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001217 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001218 return Error(Loc, "unexpected token in argument list");
1219 }
1220
1221 Parser.Lex(); // Consume the EndOfStatement
1222 return false;
1223}
1224
Rafael Espindola870c4e92012-01-11 03:56:41 +00001225bool MipsAsmParser::
Chad Rosierf0e87202012-10-25 20:41:34 +00001226ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindola870c4e92012-01-11 03:56:41 +00001227 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter1ac53222013-02-20 23:11:17 +00001228 StringRef Mnemonic;
Jack Carter0b744b32012-10-04 02:29:46 +00001229 // floating point instructions: should register be treated as double?
Jack Cartera63b16a2012-09-07 00:23:42 +00001230 if (requestsDoubleOperand(Name)) {
1231 setFpFormat(FP_FORMAT_D);
Jack Carterb4dbc172012-09-05 23:34:03 +00001232 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carter1ac53222013-02-20 23:11:17 +00001233 Mnemonic = Name;
Jack Cartera63b16a2012-09-07 00:23:42 +00001234 }
1235 else {
1236 setDefaultFpFormat();
1237 // Create the leading tokens for the mnemonic, split by '.' characters.
1238 size_t Start = 0, Next = Name.find('.');
Jack Carter1ac53222013-02-20 23:11:17 +00001239 Mnemonic = Name.slice(Start, Next);
Jack Cartera63b16a2012-09-07 00:23:42 +00001240
1241 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1242
1243 if (Next != StringRef::npos) {
Jack Carter0b744b32012-10-04 02:29:46 +00001244 // there is a format token in mnemonic
1245 // StringRef Rest = Name.slice(Next, StringRef::npos);
Jack Cartera63b16a2012-09-07 00:23:42 +00001246 size_t Dot = Name.find('.', Next+1);
1247 StringRef Format = Name.slice(Next, Dot);
1248 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1249 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1250 else {
1251 if (Name.startswith("c.")){
1252 // floating point compare, add '.' and immediate represent for cc
1253 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1254 int Cc = ConvertCcString(Format);
1255 if (Cc == -1) {
1256 return Error(NameLoc, "Invalid conditional code");
1257 }
Jack Carter873c7242013-01-12 01:03:14 +00001258 SMLoc E = SMLoc::getFromPointer(
1259 Parser.getTok().getLoc().getPointer() -1 );
Jack Cartera63b16a2012-09-07 00:23:42 +00001260 Operands.push_back(MipsOperand::CreateImm(
1261 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1262 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001263 // trunc, ceil, floor ...
Jack Cartera63b16a2012-09-07 00:23:42 +00001264 return parseMathOperation(Name, NameLoc, Operands);
1265 }
1266
Jack Carter0b744b32012-10-04 02:29:46 +00001267 // the rest is a format
Jack Cartera63b16a2012-09-07 00:23:42 +00001268 Format = Name.slice(Dot, StringRef::npos);
1269 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1270 }
1271
1272 setFpFormat(Format);
1273 }
1274 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001275
1276 // Read the remaining operands.
1277 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1278 // Read the first operand.
Jack Carter1ac53222013-02-20 23:11:17 +00001279 if (ParseOperand(Operands, Mnemonic)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001280 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001281 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001282 return Error(Loc, "unexpected token in argument list");
1283 }
1284
1285 while (getLexer().is(AsmToken::Comma) ) {
1286 Parser.Lex(); // Eat the comma.
1287
1288 // Parse and remember the operand.
1289 if (ParseOperand(Operands, Name)) {
1290 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001291 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001292 return Error(Loc, "unexpected token in argument list");
1293 }
1294 }
1295 }
1296
1297 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1298 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001299 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001300 return Error(Loc, "unexpected token in argument list");
1301 }
1302
1303 Parser.Lex(); // Consume the EndOfStatement
1304 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00001305}
1306
Jack Carter0b744b32012-10-04 02:29:46 +00001307bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1308 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001309 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001310 return Error(Loc, ErrorMsg);
1311}
1312
1313bool MipsAsmParser::parseSetNoAtDirective() {
1314 // line should look like:
1315 // .set noat
1316 // set at reg to 0
Jack Carter99d2afe2012-10-05 23:55:28 +00001317 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00001318 // eat noat
1319 Parser.Lex();
1320 // if this is not the end of the statement, report error
1321 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1322 reportParseError("unexpected token in statement");
1323 return false;
1324 }
1325 Parser.Lex(); // Consume the EndOfStatement
1326 return false;
1327}
1328bool MipsAsmParser::parseSetAtDirective() {
1329 // line can be
1330 // .set at - defaults to $1
1331 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00001332 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00001333 getParser().Lex();
1334 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00001335 Options.setATReg(1);
Jack Carter0b744b32012-10-04 02:29:46 +00001336 Parser.Lex(); // Consume the EndOfStatement
1337 return false;
1338 } else if (getLexer().is(AsmToken::Equal)) {
1339 getParser().Lex(); //eat '='
1340 if (getLexer().isNot(AsmToken::Dollar)) {
1341 reportParseError("unexpected token in statement");
1342 return false;
1343 }
1344 Parser.Lex(); // eat '$'
Jack Carter1ac53222013-02-20 23:11:17 +00001345 const AsmToken &Reg = Parser.getTok();
1346 if (Reg.is(AsmToken::Identifier)) {
1347 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
1348 } else if (Reg.is(AsmToken::Integer)) {
1349 AtRegNo = Reg.getIntVal();
1350 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001351 reportParseError("unexpected token in statement");
1352 return false;
1353 }
Jack Carter1ac53222013-02-20 23:11:17 +00001354
1355 if ( AtRegNo < 1 || AtRegNo > 31) {
1356 reportParseError("unexpected token in statement");
1357 return false;
1358 }
1359
1360 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00001361 reportParseError("unexpected token in statement");
1362 return false;
1363 }
1364 getParser().Lex(); //eat reg
1365
1366 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1367 reportParseError("unexpected token in statement");
1368 return false;
1369 }
1370 Parser.Lex(); // Consume the EndOfStatement
1371 return false;
1372 } else {
1373 reportParseError("unexpected token in statement");
1374 return false;
1375 }
1376}
1377
1378bool MipsAsmParser::parseSetReorderDirective() {
1379 Parser.Lex();
1380 // if this is not the end of the statement, report error
1381 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1382 reportParseError("unexpected token in statement");
1383 return false;
1384 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001385 Options.setReorder();
Jack Carter0b744b32012-10-04 02:29:46 +00001386 Parser.Lex(); // Consume the EndOfStatement
1387 return false;
1388}
1389
1390bool MipsAsmParser::parseSetNoReorderDirective() {
1391 Parser.Lex();
1392 // if this is not the end of the statement, report error
1393 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1394 reportParseError("unexpected token in statement");
1395 return false;
1396 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001397 Options.setNoreorder();
Jack Carter0b744b32012-10-04 02:29:46 +00001398 Parser.Lex(); // Consume the EndOfStatement
1399 return false;
1400}
1401
1402bool MipsAsmParser::parseSetMacroDirective() {
1403 Parser.Lex();
1404 // if this is not the end of the statement, report error
1405 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1406 reportParseError("unexpected token in statement");
1407 return false;
1408 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001409 Options.setMacro();
Jack Carter0b744b32012-10-04 02:29:46 +00001410 Parser.Lex(); // Consume the EndOfStatement
1411 return false;
1412}
1413
1414bool MipsAsmParser::parseSetNoMacroDirective() {
1415 Parser.Lex();
1416 // if this is not the end of the statement, report error
1417 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1418 reportParseError("`noreorder' must be set before `nomacro'");
1419 return false;
1420 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001421 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00001422 reportParseError("`noreorder' must be set before `nomacro'");
1423 return false;
1424 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001425 Options.setNomacro();
Jack Carter0b744b32012-10-04 02:29:46 +00001426 Parser.Lex(); // Consume the EndOfStatement
1427 return false;
1428}
1429bool MipsAsmParser::parseDirectiveSet() {
1430
1431 // get next token
1432 const AsmToken &Tok = Parser.getTok();
1433
1434 if (Tok.getString() == "noat") {
1435 return parseSetNoAtDirective();
1436 } else if (Tok.getString() == "at") {
1437 return parseSetAtDirective();
1438 } else if (Tok.getString() == "reorder") {
1439 return parseSetReorderDirective();
1440 } else if (Tok.getString() == "noreorder") {
1441 return parseSetNoReorderDirective();
1442 } else if (Tok.getString() == "macro") {
1443 return parseSetMacroDirective();
1444 } else if (Tok.getString() == "nomacro") {
1445 return parseSetNoMacroDirective();
1446 } else if (Tok.getString() == "nomips16") {
1447 // ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001448 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001449 return false;
1450 } else if (Tok.getString() == "nomicromips") {
1451 // ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001452 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001453 return false;
1454 }
Jack Carter07c818d2013-01-25 01:31:34 +00001455
Jack Carter0b744b32012-10-04 02:29:46 +00001456 return true;
1457}
1458
Jack Carter07c818d2013-01-25 01:31:34 +00001459/// parseDirectiveWord
1460/// ::= .word [ expression (, expression)* ]
1461bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
1462 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1463 for (;;) {
1464 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001465 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00001466 return true;
1467
1468 getParser().getStreamer().EmitValue(Value, Size);
1469
1470 if (getLexer().is(AsmToken::EndOfStatement))
1471 break;
1472
1473 // FIXME: Improve diagnostic.
1474 if (getLexer().isNot(AsmToken::Comma))
1475 return Error(L, "unexpected token in directive");
1476 Parser.Lex();
1477 }
1478 }
1479
1480 Parser.Lex();
1481 return false;
1482}
1483
Jack Carter0b744b32012-10-04 02:29:46 +00001484bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +00001485
Jack Carter07c818d2013-01-25 01:31:34 +00001486 StringRef IDVal = DirectiveID.getString();
1487
1488 if ( IDVal == ".ent") {
Jack Carter0b744b32012-10-04 02:29:46 +00001489 // ignore this directive for now
Jack Carterbe332172012-09-07 00:48:02 +00001490 Parser.Lex();
1491 return false;
1492 }
1493
Jack Carter07c818d2013-01-25 01:31:34 +00001494 if (IDVal == ".end") {
Jack Carter0b744b32012-10-04 02:29:46 +00001495 // ignore this directive for now
Jack Carterbe332172012-09-07 00:48:02 +00001496 Parser.Lex();
1497 return false;
1498 }
1499
Jack Carter07c818d2013-01-25 01:31:34 +00001500 if (IDVal == ".frame") {
Jack Carter0b744b32012-10-04 02:29:46 +00001501 // ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001502 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001503 return false;
1504 }
1505
Jack Carter07c818d2013-01-25 01:31:34 +00001506 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00001507 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00001508 }
1509
Jack Carter07c818d2013-01-25 01:31:34 +00001510 if (IDVal == ".fmask") {
Jack Carter0b744b32012-10-04 02:29:46 +00001511 // ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001512 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001513 return false;
1514 }
1515
Jack Carter07c818d2013-01-25 01:31:34 +00001516 if (IDVal == ".mask") {
Jack Carter0b744b32012-10-04 02:29:46 +00001517 // ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001518 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001519 return false;
1520 }
1521
Jack Carter07c818d2013-01-25 01:31:34 +00001522 if (IDVal == ".gpword") {
Jack Carter0b744b32012-10-04 02:29:46 +00001523 // ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001524 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001525 return false;
1526 }
1527
Jack Carter07c818d2013-01-25 01:31:34 +00001528 if (IDVal == ".word") {
1529 parseDirectiveWord(4, DirectiveID.getLoc());
1530 return false;
1531 }
1532
Rafael Espindola870c4e92012-01-11 03:56:41 +00001533 return true;
1534}
1535
Rafael Espindola870c4e92012-01-11 03:56:41 +00001536extern "C" void LLVMInitializeMipsAsmParser() {
1537 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1538 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1539 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1540 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1541}
Jack Carterb4dbc172012-09-05 23:34:03 +00001542
1543#define GET_REGISTER_MATCHER
1544#define GET_MATCHER_IMPLEMENTATION
1545#include "MipsGenAsmMatcher.inc"