blob: ade60847528e0360e14ec8d8603e13c7116fadda [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") {
Jack Carterdc463382013-02-21 02:09:31 +0000891 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +0000892 Val = (Val & 0xffff0000) >> 16;
Jack Carterdc463382013-02-21 02:09:31 +0000893 //lower part is treated as signed int, so if it is negative
894 //we must add 1 to hi part to compensate
895 if (LoSign)
896 Val++;
Jack Carterdc1e35d2012-09-06 20:00:02 +0000897 }
898 Res = MCConstantExpr::Create(Val, getContext());
899 return false;
900 }
901
Benjamin Kramerfa530572012-09-07 09:47:42 +0000902 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter0b744b32012-10-04 02:29:46 +0000903 // it's a symbol, create symbolic expression from symbol
Benjamin Kramerfa530572012-09-07 09:47:42 +0000904 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000905 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
906 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
907 return false;
908 }
909 return true;
910}
911
Jack Carterb4dbc172012-09-05 23:34:03 +0000912bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
913 SMLoc &EndLoc) {
914
915 StartLoc = Parser.getTok().getLoc();
Jack Carter873c7242013-01-12 01:03:14 +0000916 RegNo = tryParseRegister(isMips64());
917 EndLoc = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +0000918 return (RegNo == (unsigned)-1);
919}
920
Jack Carterdc1e35d2012-09-06 20:00:02 +0000921bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
Jack Carter873c7242013-01-12 01:03:14 +0000922
923 SMLoc S;
924
Jack Carterdc1e35d2012-09-06 20:00:02 +0000925 switch(getLexer().getKind()) {
926 default:
927 return true;
928 case AsmToken::Integer:
929 case AsmToken::Minus:
930 case AsmToken::Plus:
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000931 return (getParser().parseExpression(Res));
Jack Carter873c7242013-01-12 01:03:14 +0000932 case AsmToken::Percent:
933 return parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +0000934 case AsmToken::LParen:
Jack Carter0b744b32012-10-04 02:29:46 +0000935 return false; // it's probably assuming 0
Jack Carterdc1e35d2012-09-06 20:00:02 +0000936 }
937 return true;
938}
939
Jack Carterb4dbc172012-09-05 23:34:03 +0000940MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
941 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000942
943 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +0000944 SMLoc S;
945 // first operand is the offset
946 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000947
948 if (parseMemOffset(IdVal))
949 return MatchOperand_ParseFail;
950
Jack Carter0b744b32012-10-04 02:29:46 +0000951 const AsmToken &Tok = Parser.getTok(); // get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +0000952 if (Tok.isNot(AsmToken::LParen)) {
Jack Carter543fdf82012-10-09 23:29:45 +0000953 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
954 if (Mnemonic->getToken() == "la") {
Jack Carter873c7242013-01-12 01:03:14 +0000955 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() -1);
Jack Carter543fdf82012-10-09 23:29:45 +0000956 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
957 return MatchOperand_Success;
958 }
Jack Carterdc1e35d2012-09-06 20:00:02 +0000959 Error(Parser.getTok().getLoc(), "'(' expected");
960 return MatchOperand_ParseFail;
961 }
962
963 Parser.Lex(); // Eat '(' token.
964
Jack Carter543fdf82012-10-09 23:29:45 +0000965 const AsmToken &Tok1 = Parser.getTok(); // get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +0000966 if (Tok1.is(AsmToken::Dollar)) {
967 Parser.Lex(); // Eat '$' token.
Jack Carter873c7242013-01-12 01:03:14 +0000968 if (tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000969 Error(Parser.getTok().getLoc(), "unexpected token in operand");
970 return MatchOperand_ParseFail;
971 }
972
973 } else {
Jack Carter0b744b32012-10-04 02:29:46 +0000974 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carterdc1e35d2012-09-06 20:00:02 +0000975 return MatchOperand_ParseFail;
976 }
977
Jack Carter0b744b32012-10-04 02:29:46 +0000978 const AsmToken &Tok2 = Parser.getTok(); // get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +0000979 if (Tok2.isNot(AsmToken::RParen)) {
980 Error(Parser.getTok().getLoc(), "')' expected");
981 return MatchOperand_ParseFail;
982 }
983
Jack Carter873c7242013-01-12 01:03:14 +0000984 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
985
Jack Carterdc1e35d2012-09-06 20:00:02 +0000986 Parser.Lex(); // Eat ')' token.
987
988 if (IdVal == 0)
989 IdVal = MCConstantExpr::Create(0, getContext());
990
Jack Carter0b744b32012-10-04 02:29:46 +0000991 // now replace register operand with the mem operand
Jack Carterdc1e35d2012-09-06 20:00:02 +0000992 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
993 int RegNo = op->getReg();
Jack Carter0b744b32012-10-04 02:29:46 +0000994 // remove register from operands
Jack Carterdc1e35d2012-09-06 20:00:02 +0000995 Operands.pop_back();
Jack Carter0b744b32012-10-04 02:29:46 +0000996 // and add memory operand
Jack Carterdc1e35d2012-09-06 20:00:02 +0000997 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
998 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +0000999 return MatchOperand_Success;
1000}
1001
Jack Carter873c7242013-01-12 01:03:14 +00001002MipsAsmParser::OperandMatchResultTy
1003MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1004
1005 if (!isMips64())
1006 return MatchOperand_NoMatch;
1007 // if the first token is not '$' we have an error
1008 if (Parser.getTok().isNot(AsmToken::Dollar))
1009 return MatchOperand_NoMatch;
1010
1011 Parser.Lex(); // Eat $
1012 if(!tryParseRegisterOperand(Operands, true)) {
1013 // set the proper register kind
1014 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1015 op->setRegKind(MipsOperand::Kind_CPU64Regs);
1016 return MatchOperand_Success;
1017 }
1018 return MatchOperand_NoMatch;
1019}
1020
1021MipsAsmParser::OperandMatchResultTy
1022MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1023
1024 // if the first token is not '$' we have an error
1025 if (Parser.getTok().isNot(AsmToken::Dollar))
1026 return MatchOperand_NoMatch;
1027
1028 Parser.Lex(); // Eat $
1029 if(!tryParseRegisterOperand(Operands, false)) {
1030 // set the propper register kind
1031 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1032 op->setRegKind(MipsOperand::Kind_CPURegs);
1033 return MatchOperand_Success;
1034 }
1035 return MatchOperand_NoMatch;
1036}
1037
1038MipsAsmParser::OperandMatchResultTy
1039MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1040
Jack Carter2a74a87b2013-01-17 00:28:20 +00001041 if (isMips64())
1042 return MatchOperand_NoMatch;
1043
Jack Carter873c7242013-01-12 01:03:14 +00001044 // if the first token is not '$' we have error
1045 if (Parser.getTok().isNot(AsmToken::Dollar))
1046 return MatchOperand_NoMatch;
1047 SMLoc S = Parser.getTok().getLoc();
1048 Parser.Lex(); // Eat $
1049
1050 const AsmToken &Tok = Parser.getTok(); // get next token
1051 if (Tok.isNot(AsmToken::Integer))
1052 return MatchOperand_NoMatch;
1053
1054 unsigned RegNum = Tok.getIntVal();
1055 // at the moment only hwreg29 is supported
1056 if (RegNum != 29)
1057 return MatchOperand_ParseFail;
1058
1059 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
1060 Parser.getTok().getLoc());
1061 op->setRegKind(MipsOperand::Kind_HWRegs);
1062 Operands.push_back(op);
1063
1064 Parser.Lex(); // Eat reg number
1065 return MatchOperand_Success;
1066}
1067
1068MipsAsmParser::OperandMatchResultTy
1069MipsAsmParser::parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter2a74a87b2013-01-17 00:28:20 +00001070
1071 if (!isMips64())
1072 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001073 //if the first token is not '$' we have error
1074 if (Parser.getTok().isNot(AsmToken::Dollar))
1075 return MatchOperand_NoMatch;
1076 SMLoc S = Parser.getTok().getLoc();
1077 Parser.Lex(); // Eat $
1078
1079 const AsmToken &Tok = Parser.getTok(); // get next token
1080 if (Tok.isNot(AsmToken::Integer))
1081 return MatchOperand_NoMatch;
1082
1083 unsigned RegNum = Tok.getIntVal();
1084 // at the moment only hwreg29 is supported
1085 if (RegNum != 29)
1086 return MatchOperand_ParseFail;
1087
1088 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
1089 Parser.getTok().getLoc());
Jack Carter2a74a87b2013-01-17 00:28:20 +00001090 op->setRegKind(MipsOperand::Kind_HW64Regs);
Jack Carter873c7242013-01-12 01:03:14 +00001091 Operands.push_back(op);
1092
1093 Parser.Lex(); // Eat reg number
1094 return MatchOperand_Success;
1095}
1096
1097MipsAsmParser::OperandMatchResultTy
1098MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1099 unsigned RegNum;
1100 //if the first token is not '$' we have error
1101 if (Parser.getTok().isNot(AsmToken::Dollar))
1102 return MatchOperand_NoMatch;
1103 SMLoc S = Parser.getTok().getLoc();
1104 Parser.Lex(); // Eat $
1105
1106 const AsmToken &Tok = Parser.getTok(); // get next token
1107 if (Tok.is(AsmToken::Integer)) {
1108 RegNum = Tok.getIntVal();
1109 // at the moment only fcc0 is supported
1110 if (RegNum != 0)
1111 return MatchOperand_ParseFail;
1112 } else if (Tok.is(AsmToken::Identifier)) {
1113 // at the moment only fcc0 is supported
1114 if (Tok.getIdentifier() != "fcc0")
1115 return MatchOperand_ParseFail;
1116 } else
1117 return MatchOperand_NoMatch;
1118
1119 MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
1120 Parser.getTok().getLoc());
1121 op->setRegKind(MipsOperand::Kind_CCRRegs);
1122 Operands.push_back(op);
1123
1124 Parser.Lex(); // Eat reg number
1125 return MatchOperand_Success;
1126}
1127
Jack Carterdc1e35d2012-09-06 20:00:02 +00001128MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1129
1130 MCSymbolRefExpr::VariantKind VK
1131 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1132 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1133 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1134 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1135 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1136 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1137 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1138 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1139 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1140 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1141 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1142 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1143 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1144 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1145 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1146 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1147 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1148 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1149 .Default(MCSymbolRefExpr::VK_None);
1150
1151 return VK;
1152}
1153
Benjamin Kramer47b5c572012-09-10 11:52:14 +00001154static int ConvertCcString(StringRef CondString) {
Jack Cartera63b16a2012-09-07 00:23:42 +00001155 int CC = StringSwitch<unsigned>(CondString)
1156 .Case(".f", 0)
1157 .Case(".un", 1)
1158 .Case(".eq", 2)
1159 .Case(".ueq", 3)
1160 .Case(".olt", 4)
1161 .Case(".ult", 5)
1162 .Case(".ole", 6)
1163 .Case(".ule", 7)
1164 .Case(".sf", 8)
1165 .Case(".ngle", 9)
1166 .Case(".seq", 10)
1167 .Case(".ngl", 11)
1168 .Case(".lt", 12)
1169 .Case(".nge", 13)
1170 .Case(".le", 14)
1171 .Case(".ngt", 15)
1172 .Default(-1);
1173
1174 return CC;
1175}
1176
1177bool MipsAsmParser::
1178parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter0b744b32012-10-04 02:29:46 +00001179 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1180 // split the format
Jack Cartera63b16a2012-09-07 00:23:42 +00001181 size_t Start = Name.find('.'), Next = Name.rfind('.');
1182 StringRef Format1 = Name.slice(Start, Next);
Jack Carter0b744b32012-10-04 02:29:46 +00001183 // and add the first format to the operands
Jack Cartera63b16a2012-09-07 00:23:42 +00001184 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carter0b744b32012-10-04 02:29:46 +00001185 // now for the second format
Jack Cartera63b16a2012-09-07 00:23:42 +00001186 StringRef Format2 = Name.slice(Next, StringRef::npos);
1187 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1188
Jack Carter0b744b32012-10-04 02:29:46 +00001189 // set the format for the first register
Jack Cartera63b16a2012-09-07 00:23:42 +00001190 setFpFormat(Format1);
1191
1192 // Read the remaining operands.
1193 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1194 // Read the first operand.
1195 if (ParseOperand(Operands, Name)) {
1196 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001197 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001198 return Error(Loc, "unexpected token in argument list");
1199 }
1200
1201 if (getLexer().isNot(AsmToken::Comma)) {
1202 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001203 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001204 return Error(Loc, "unexpected token in argument list");
1205
1206 }
1207 Parser.Lex(); // Eat the comma.
1208
1209 //set the format for the first register
1210 setFpFormat(Format2);
1211
1212 // Parse and remember the operand.
1213 if (ParseOperand(Operands, Name)) {
1214 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001215 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001216 return Error(Loc, "unexpected token in argument list");
1217 }
1218 }
1219
1220 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1221 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001222 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001223 return Error(Loc, "unexpected token in argument list");
1224 }
1225
1226 Parser.Lex(); // Consume the EndOfStatement
1227 return false;
1228}
1229
Rafael Espindola870c4e92012-01-11 03:56:41 +00001230bool MipsAsmParser::
Chad Rosierf0e87202012-10-25 20:41:34 +00001231ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindola870c4e92012-01-11 03:56:41 +00001232 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter1ac53222013-02-20 23:11:17 +00001233 StringRef Mnemonic;
Jack Carter0b744b32012-10-04 02:29:46 +00001234 // floating point instructions: should register be treated as double?
Jack Cartera63b16a2012-09-07 00:23:42 +00001235 if (requestsDoubleOperand(Name)) {
1236 setFpFormat(FP_FORMAT_D);
Jack Carterb4dbc172012-09-05 23:34:03 +00001237 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carter1ac53222013-02-20 23:11:17 +00001238 Mnemonic = Name;
Jack Cartera63b16a2012-09-07 00:23:42 +00001239 }
1240 else {
1241 setDefaultFpFormat();
1242 // Create the leading tokens for the mnemonic, split by '.' characters.
1243 size_t Start = 0, Next = Name.find('.');
Jack Carter1ac53222013-02-20 23:11:17 +00001244 Mnemonic = Name.slice(Start, Next);
Jack Cartera63b16a2012-09-07 00:23:42 +00001245
1246 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1247
1248 if (Next != StringRef::npos) {
Jack Carter0b744b32012-10-04 02:29:46 +00001249 // there is a format token in mnemonic
1250 // StringRef Rest = Name.slice(Next, StringRef::npos);
Jack Cartera63b16a2012-09-07 00:23:42 +00001251 size_t Dot = Name.find('.', Next+1);
1252 StringRef Format = Name.slice(Next, Dot);
1253 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1254 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1255 else {
1256 if (Name.startswith("c.")){
1257 // floating point compare, add '.' and immediate represent for cc
1258 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1259 int Cc = ConvertCcString(Format);
1260 if (Cc == -1) {
1261 return Error(NameLoc, "Invalid conditional code");
1262 }
Jack Carter873c7242013-01-12 01:03:14 +00001263 SMLoc E = SMLoc::getFromPointer(
1264 Parser.getTok().getLoc().getPointer() -1 );
Jack Cartera63b16a2012-09-07 00:23:42 +00001265 Operands.push_back(MipsOperand::CreateImm(
1266 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1267 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001268 // trunc, ceil, floor ...
Jack Cartera63b16a2012-09-07 00:23:42 +00001269 return parseMathOperation(Name, NameLoc, Operands);
1270 }
1271
Jack Carter0b744b32012-10-04 02:29:46 +00001272 // the rest is a format
Jack Cartera63b16a2012-09-07 00:23:42 +00001273 Format = Name.slice(Dot, StringRef::npos);
1274 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1275 }
1276
1277 setFpFormat(Format);
1278 }
1279 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001280
1281 // Read the remaining operands.
1282 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1283 // Read the first operand.
Jack Carter1ac53222013-02-20 23:11:17 +00001284 if (ParseOperand(Operands, Mnemonic)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001285 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001286 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001287 return Error(Loc, "unexpected token in argument list");
1288 }
1289
1290 while (getLexer().is(AsmToken::Comma) ) {
1291 Parser.Lex(); // Eat the comma.
1292
1293 // Parse and remember the operand.
1294 if (ParseOperand(Operands, Name)) {
1295 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001296 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001297 return Error(Loc, "unexpected token in argument list");
1298 }
1299 }
1300 }
1301
1302 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1303 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001304 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001305 return Error(Loc, "unexpected token in argument list");
1306 }
1307
1308 Parser.Lex(); // Consume the EndOfStatement
1309 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00001310}
1311
Jack Carter0b744b32012-10-04 02:29:46 +00001312bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1313 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001314 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001315 return Error(Loc, ErrorMsg);
1316}
1317
1318bool MipsAsmParser::parseSetNoAtDirective() {
1319 // line should look like:
1320 // .set noat
1321 // set at reg to 0
Jack Carter99d2afe2012-10-05 23:55:28 +00001322 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00001323 // eat noat
1324 Parser.Lex();
1325 // if this is not the end of the statement, report error
1326 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1327 reportParseError("unexpected token in statement");
1328 return false;
1329 }
1330 Parser.Lex(); // Consume the EndOfStatement
1331 return false;
1332}
1333bool MipsAsmParser::parseSetAtDirective() {
1334 // line can be
1335 // .set at - defaults to $1
1336 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00001337 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00001338 getParser().Lex();
1339 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00001340 Options.setATReg(1);
Jack Carter0b744b32012-10-04 02:29:46 +00001341 Parser.Lex(); // Consume the EndOfStatement
1342 return false;
1343 } else if (getLexer().is(AsmToken::Equal)) {
1344 getParser().Lex(); //eat '='
1345 if (getLexer().isNot(AsmToken::Dollar)) {
1346 reportParseError("unexpected token in statement");
1347 return false;
1348 }
1349 Parser.Lex(); // eat '$'
Jack Carter1ac53222013-02-20 23:11:17 +00001350 const AsmToken &Reg = Parser.getTok();
1351 if (Reg.is(AsmToken::Identifier)) {
1352 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
1353 } else if (Reg.is(AsmToken::Integer)) {
1354 AtRegNo = Reg.getIntVal();
1355 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001356 reportParseError("unexpected token in statement");
1357 return false;
1358 }
Jack Carter1ac53222013-02-20 23:11:17 +00001359
1360 if ( AtRegNo < 1 || AtRegNo > 31) {
1361 reportParseError("unexpected token in statement");
1362 return false;
1363 }
1364
1365 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00001366 reportParseError("unexpected token in statement");
1367 return false;
1368 }
1369 getParser().Lex(); //eat reg
1370
1371 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1372 reportParseError("unexpected token in statement");
1373 return false;
1374 }
1375 Parser.Lex(); // Consume the EndOfStatement
1376 return false;
1377 } else {
1378 reportParseError("unexpected token in statement");
1379 return false;
1380 }
1381}
1382
1383bool MipsAsmParser::parseSetReorderDirective() {
1384 Parser.Lex();
1385 // if this is not the end of the statement, report error
1386 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1387 reportParseError("unexpected token in statement");
1388 return false;
1389 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001390 Options.setReorder();
Jack Carter0b744b32012-10-04 02:29:46 +00001391 Parser.Lex(); // Consume the EndOfStatement
1392 return false;
1393}
1394
1395bool MipsAsmParser::parseSetNoReorderDirective() {
1396 Parser.Lex();
1397 // if this is not the end of the statement, report error
1398 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1399 reportParseError("unexpected token in statement");
1400 return false;
1401 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001402 Options.setNoreorder();
Jack Carter0b744b32012-10-04 02:29:46 +00001403 Parser.Lex(); // Consume the EndOfStatement
1404 return false;
1405}
1406
1407bool MipsAsmParser::parseSetMacroDirective() {
1408 Parser.Lex();
1409 // if this is not the end of the statement, report error
1410 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1411 reportParseError("unexpected token in statement");
1412 return false;
1413 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001414 Options.setMacro();
Jack Carter0b744b32012-10-04 02:29:46 +00001415 Parser.Lex(); // Consume the EndOfStatement
1416 return false;
1417}
1418
1419bool MipsAsmParser::parseSetNoMacroDirective() {
1420 Parser.Lex();
1421 // if this is not the end of the statement, report error
1422 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1423 reportParseError("`noreorder' must be set before `nomacro'");
1424 return false;
1425 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001426 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00001427 reportParseError("`noreorder' must be set before `nomacro'");
1428 return false;
1429 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001430 Options.setNomacro();
Jack Carter0b744b32012-10-04 02:29:46 +00001431 Parser.Lex(); // Consume the EndOfStatement
1432 return false;
1433}
1434bool MipsAsmParser::parseDirectiveSet() {
1435
1436 // get next token
1437 const AsmToken &Tok = Parser.getTok();
1438
1439 if (Tok.getString() == "noat") {
1440 return parseSetNoAtDirective();
1441 } else if (Tok.getString() == "at") {
1442 return parseSetAtDirective();
1443 } else if (Tok.getString() == "reorder") {
1444 return parseSetReorderDirective();
1445 } else if (Tok.getString() == "noreorder") {
1446 return parseSetNoReorderDirective();
1447 } else if (Tok.getString() == "macro") {
1448 return parseSetMacroDirective();
1449 } else if (Tok.getString() == "nomacro") {
1450 return parseSetNoMacroDirective();
1451 } else if (Tok.getString() == "nomips16") {
1452 // ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001453 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001454 return false;
1455 } else if (Tok.getString() == "nomicromips") {
1456 // ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001457 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001458 return false;
1459 }
Jack Carter07c818d2013-01-25 01:31:34 +00001460
Jack Carter0b744b32012-10-04 02:29:46 +00001461 return true;
1462}
1463
Jack Carter07c818d2013-01-25 01:31:34 +00001464/// parseDirectiveWord
1465/// ::= .word [ expression (, expression)* ]
1466bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
1467 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1468 for (;;) {
1469 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001470 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00001471 return true;
1472
1473 getParser().getStreamer().EmitValue(Value, Size);
1474
1475 if (getLexer().is(AsmToken::EndOfStatement))
1476 break;
1477
1478 // FIXME: Improve diagnostic.
1479 if (getLexer().isNot(AsmToken::Comma))
1480 return Error(L, "unexpected token in directive");
1481 Parser.Lex();
1482 }
1483 }
1484
1485 Parser.Lex();
1486 return false;
1487}
1488
Jack Carter0b744b32012-10-04 02:29:46 +00001489bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +00001490
Jack Carter07c818d2013-01-25 01:31:34 +00001491 StringRef IDVal = DirectiveID.getString();
1492
1493 if ( IDVal == ".ent") {
Jack Carter0b744b32012-10-04 02:29:46 +00001494 // ignore this directive for now
Jack Carterbe332172012-09-07 00:48:02 +00001495 Parser.Lex();
1496 return false;
1497 }
1498
Jack Carter07c818d2013-01-25 01:31:34 +00001499 if (IDVal == ".end") {
Jack Carter0b744b32012-10-04 02:29:46 +00001500 // ignore this directive for now
Jack Carterbe332172012-09-07 00:48:02 +00001501 Parser.Lex();
1502 return false;
1503 }
1504
Jack Carter07c818d2013-01-25 01:31:34 +00001505 if (IDVal == ".frame") {
Jack Carter0b744b32012-10-04 02:29:46 +00001506 // ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001507 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001508 return false;
1509 }
1510
Jack Carter07c818d2013-01-25 01:31:34 +00001511 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00001512 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00001513 }
1514
Jack Carter07c818d2013-01-25 01:31:34 +00001515 if (IDVal == ".fmask") {
Jack Carter0b744b32012-10-04 02:29:46 +00001516 // ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001517 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001518 return false;
1519 }
1520
Jack Carter07c818d2013-01-25 01:31:34 +00001521 if (IDVal == ".mask") {
Jack Carter0b744b32012-10-04 02:29:46 +00001522 // ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001523 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001524 return false;
1525 }
1526
Jack Carter07c818d2013-01-25 01:31:34 +00001527 if (IDVal == ".gpword") {
Jack Carter0b744b32012-10-04 02:29:46 +00001528 // ignore this directive for now
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001529 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001530 return false;
1531 }
1532
Jack Carter07c818d2013-01-25 01:31:34 +00001533 if (IDVal == ".word") {
1534 parseDirectiveWord(4, DirectiveID.getLoc());
1535 return false;
1536 }
1537
Rafael Espindola870c4e92012-01-11 03:56:41 +00001538 return true;
1539}
1540
Rafael Espindola870c4e92012-01-11 03:56:41 +00001541extern "C" void LLVMInitializeMipsAsmParser() {
1542 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1543 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1544 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1545 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1546}
Jack Carterb4dbc172012-09-05 23:34:03 +00001547
1548#define GET_REGISTER_MATCHER
1549#define GET_MATCHER_IMPLEMENTATION
1550#include "MipsGenAsmMatcher.inc"