blob: f36bd5fda61669af83f88c14751c3601948560ad [file] [log] [blame]
Jia Liuc5707112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindolafddf8042012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterec65be82012-09-05 23:34:03 +000011#include "MipsRegisterInfo.h"
12#include "llvm/ADT/StringSwitch.h"
13#include "llvm/MC/MCContext.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCInst.h"
16#include "llvm/MC/MCStreamer.h"
17#include "llvm/MC/MCSubtargetInfo.h"
18#include "llvm/MC/MCSymbol.h"
Rafael Espindolafddf8042012-01-11 03:56:41 +000019#include "llvm/MC/MCParser/MCAsmLexer.h"
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000020#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21#include "llvm/MC/MCTargetAsmParser.h"
Jack Carterec65be82012-09-05 23:34:03 +000022#include "llvm/Support/TargetRegistry.h"
Rafael Espindolafddf8042012-01-11 03:56:41 +000023
24using namespace llvm;
25
26namespace {
Jack Carter30116cd2012-10-04 02:29:46 +000027class MipsAssemblerOptions {
28public:
29 MipsAssemblerOptions():
30 aTReg(1), reorder(true), macro(true) {
31 }
Jack Carterec65be82012-09-05 23:34:03 +000032
Jack Carter30116cd2012-10-04 02:29:46 +000033 unsigned getATRegNum() {return aTReg;}
34 bool setATReg(unsigned Reg);
35
36 bool isReorder() {return reorder;}
37 void setReorder() {reorder = true;}
38 void setNoreorder() {reorder = false;}
39
40 bool isMacro() {return macro;}
41 void setMacro() {macro = true;}
42 void setNomacro() {macro = false;}
43
44private:
45 unsigned aTReg;
46 bool reorder;
47 bool macro;
48};
49}
50
51namespace {
Rafael Espindolafddf8042012-01-11 03:56:41 +000052class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000053
Jack Carterf740d6e2012-09-07 00:23:42 +000054 enum FpFormatTy {
55 FP_FORMAT_NONE = -1,
56 FP_FORMAT_S,
57 FP_FORMAT_D,
58 FP_FORMAT_L,
59 FP_FORMAT_W
60 } FpFormat;
61
Jack Carterec65be82012-09-05 23:34:03 +000062 MCSubtargetInfo &STI;
63 MCAsmParser &Parser;
Jack Carter10d5ff62012-10-05 23:55:28 +000064 MipsAssemblerOptions Options;
Jack Carter30116cd2012-10-04 02:29:46 +000065
Jack Carterec65be82012-09-05 23:34:03 +000066
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000067#define GET_ASSEMBLER_HEADER
68#include "MipsGenAsmMatcher.inc"
69
Rafael Espindolafddf8042012-01-11 03:56:41 +000070 bool MatchAndEmitInstruction(SMLoc IDLoc,
71 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
72 MCStreamer &Out);
73
74 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
75
76 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000077 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindolafddf8042012-01-11 03:56:41 +000078
Jack Carterf740d6e2012-09-07 00:23:42 +000079 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
80 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
81
Rafael Espindolafddf8042012-01-11 03:56:41 +000082 bool ParseDirective(AsmToken DirectiveID);
83
Jack Carterec65be82012-09-05 23:34:03 +000084 MipsAsmParser::OperandMatchResultTy
85 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
Chad Rosier038f3e32012-09-03 18:47:45 +000086
Jack Carterec65be82012-09-05 23:34:03 +000087 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
88 StringRef Mnemonic);
89
90 int tryParseRegister(StringRef Mnemonic);
91
92 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
93 StringRef Mnemonic);
94
Jack Carter9d577c82012-10-04 04:03:53 +000095 bool needsExpansion(MCInst &Inst);
96
97 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
98 SmallVectorImpl<MCInst*> &Instructions);
99 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
100 SmallVectorImpl<MCInst*> &Instructions);
Jack Carter30116cd2012-10-04 02:29:46 +0000101 bool reportParseError(StringRef ErrorMsg);
102
Jack Carter6b96c3f2012-09-06 20:00:02 +0000103 bool parseMemOffset(const MCExpr *&Res);
104 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter30116cd2012-10-04 02:29:46 +0000105
106 bool parseDirectiveSet();
107
108 bool parseSetAtDirective();
109 bool parseSetNoAtDirective();
110 bool parseSetMacroDirective();
111 bool parseSetNoMacroDirective();
112 bool parseSetReorderDirective();
113 bool parseSetNoReorderDirective();
114
Jack Carter6b96c3f2012-09-06 20:00:02 +0000115 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Carterf740d6e2012-09-07 00:23:42 +0000116
Jack Carterec65be82012-09-05 23:34:03 +0000117 bool isMips64() const {
118 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
119 }
120
Jack Carterf740d6e2012-09-07 00:23:42 +0000121 bool isFP64() const {
122 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
123 }
124
Jack Carterec65be82012-09-05 23:34:03 +0000125 int matchRegisterName(StringRef Symbol);
126
127 int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
128
Jack Carterf740d6e2012-09-07 00:23:42 +0000129 void setFpFormat(FpFormatTy Format) {
130 FpFormat = Format;
131 }
132
133 void setDefaultFpFormat();
134
135 void setFpFormat(StringRef Format);
136
137 FpFormatTy getFpFormat() {return FpFormat;}
138
139 bool requestsDoubleOperand(StringRef Mnemonic);
140
Jack Carterec65be82012-09-05 23:34:03 +0000141 unsigned getReg(int RC,int RegNo);
Chad Rosier038f3e32012-09-03 18:47:45 +0000142
Jack Carter30116cd2012-10-04 02:29:46 +0000143 unsigned getATReg();
Rafael Espindolafddf8042012-01-11 03:56:41 +0000144public:
145 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterec65be82012-09-05 23:34:03 +0000146 : MCTargetAsmParser(), STI(sti), Parser(parser) {
147 // Initialize the set of available features.
148 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindolafddf8042012-01-11 03:56:41 +0000149 }
150
Jack Carterec65be82012-09-05 23:34:03 +0000151 MCAsmParser &getParser() const { return Parser; }
152 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
153
Rafael Espindolafddf8042012-01-11 03:56:41 +0000154};
155}
156
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000157namespace {
158
159/// MipsOperand - Instances of this class represent a parsed Mips machine
160/// instruction.
161class MipsOperand : public MCParsedAsmOperand {
Jack Carterec65be82012-09-05 23:34:03 +0000162
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000163 enum KindTy {
164 k_CondCode,
165 k_CoprocNum,
166 k_Immediate,
167 k_Memory,
168 k_PostIndexRegister,
169 k_Register,
170 k_Token
171 } Kind;
172
173 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterec65be82012-09-05 23:34:03 +0000174
175 union {
176 struct {
177 const char *Data;
178 unsigned Length;
179 } Tok;
180
181 struct {
182 unsigned RegNum;
183 } Reg;
184
185 struct {
186 const MCExpr *Val;
187 } Imm;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000188
189 struct {
190 unsigned Base;
191 const MCExpr *Off;
192 } Mem;
Jack Carterec65be82012-09-05 23:34:03 +0000193 };
194
195 SMLoc StartLoc, EndLoc;
196
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000197public:
198 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000199 assert(N == 1 && "Invalid number of operands!");
200 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000201 }
Jack Carterec65be82012-09-05 23:34:03 +0000202
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000203 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterec65be82012-09-05 23:34:03 +0000204 // Add as immediate when possible. Null MCExpr = 0.
205 if (Expr == 0)
206 Inst.addOperand(MCOperand::CreateImm(0));
207 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
208 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
209 else
210 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000211 }
Jack Carterec65be82012-09-05 23:34:03 +0000212
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000213 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000214 assert(N == 1 && "Invalid number of operands!");
215 const MCExpr *Expr = getImm();
216 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000217 }
Jack Carterec65be82012-09-05 23:34:03 +0000218
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000219 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000220 assert(N == 2 && "Invalid number of operands!");
221
222 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
223
224 const MCExpr *Expr = getMemOff();
225 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000226 }
227
228 bool isReg() const { return Kind == k_Register; }
229 bool isImm() const { return Kind == k_Immediate; }
230 bool isToken() const { return Kind == k_Token; }
231 bool isMem() const { return Kind == k_Memory; }
232
233 StringRef getToken() const {
234 assert(Kind == k_Token && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000235 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000236 }
237
238 unsigned getReg() const {
239 assert((Kind == k_Register) && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000240 return Reg.RegNum;
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000241 }
242
Jack Carterec65be82012-09-05 23:34:03 +0000243 const MCExpr *getImm() const {
244 assert((Kind == k_Immediate) && "Invalid access!");
245 return Imm.Val;
246 }
247
Jack Carter6b96c3f2012-09-06 20:00:02 +0000248 unsigned getMemBase() const {
249 assert((Kind == k_Memory) && "Invalid access!");
250 return Mem.Base;
251 }
252
253 const MCExpr *getMemOff() const {
254 assert((Kind == k_Memory) && "Invalid access!");
255 return Mem.Off;
256 }
257
Jack Carterec65be82012-09-05 23:34:03 +0000258 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
259 MipsOperand *Op = new MipsOperand(k_Token);
260 Op->Tok.Data = Str.data();
261 Op->Tok.Length = Str.size();
262 Op->StartLoc = S;
263 Op->EndLoc = S;
264 return Op;
265 }
266
267 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
268 MipsOperand *Op = new MipsOperand(k_Register);
269 Op->Reg.RegNum = RegNum;
270 Op->StartLoc = S;
271 Op->EndLoc = E;
272 return Op;
273 }
274
275 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
276 MipsOperand *Op = new MipsOperand(k_Immediate);
277 Op->Imm.Val = Val;
278 Op->StartLoc = S;
279 Op->EndLoc = E;
280 return Op;
281 }
282
Jack Carter6b96c3f2012-09-06 20:00:02 +0000283 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
284 SMLoc S, SMLoc E) {
285 MipsOperand *Op = new MipsOperand(k_Memory);
286 Op->Mem.Base = Base;
287 Op->Mem.Off = Off;
288 Op->StartLoc = S;
289 Op->EndLoc = E;
290 return Op;
291 }
292
Jack Carterec65be82012-09-05 23:34:03 +0000293 /// getStartLoc - Get the location of the first token of this operand.
294 SMLoc getStartLoc() const { return StartLoc; }
295 /// getEndLoc - Get the location of the last token of this operand.
296 SMLoc getEndLoc() const { return EndLoc; }
297
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000298 virtual void print(raw_ostream &OS) const {
299 llvm_unreachable("unimplemented!");
300 }
301};
302}
303
Jack Carter9d577c82012-10-04 04:03:53 +0000304bool MipsAsmParser::needsExpansion(MCInst &Inst) {
305
306 switch(Inst.getOpcode()) {
307 case Mips::LoadImm32Reg:
308 return true;
309 default:
310 return false;
311 }
312}
313void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
314 SmallVectorImpl<MCInst*> &Instructions){
315 switch(Inst.getOpcode()) {
316 case Mips::LoadImm32Reg:
317 return expandLoadImm(Inst, IDLoc, Instructions);
318 }
319 return;
320}
321void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
322 SmallVectorImpl<MCInst*> &Instructions){
323 MCInst *tmpInst = new MCInst();
324 const MCOperand &ImmOp = Inst.getOperand(1);
325 assert(ImmOp.isImm() && "expected imediate operand kind");
326 const MCOperand &RegOp = Inst.getOperand(0);
327 assert(RegOp.isReg() && "expected register operand kind");
328
329 int ImmValue = ImmOp.getImm();
330 tmpInst->setLoc(IDLoc);
331 if ( 0 <= ImmValue && ImmValue <= 65535) {
332 // for 0 = j = 65535.
333 // li d,j => ori d,$zero,j
334 tmpInst->setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
335 tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
336 tmpInst->addOperand(
337 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
338 tmpInst->addOperand(MCOperand::CreateImm(ImmValue));
339 Instructions.push_back(tmpInst);
340 } else if ( ImmValue < 0 && ImmValue >= -32768) {
341 // for -32768 = j < 0.
342 // li d,j => addiu d,$zero,j
343 tmpInst->setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
344 tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
345 tmpInst->addOperand(
346 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
347 tmpInst->addOperand(MCOperand::CreateImm(ImmValue));
348 Instructions.push_back(tmpInst);
349 } else {
350 // for any other value of j that is representable as a 32-bit integer.
351 // li d,j => lui d,hi16(j)
352 // ori d,d,lo16(j)
353 tmpInst->setOpcode(isMips64() ? Mips::LUi64 : Mips::LUi);
354 tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
355 tmpInst->addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
356 Instructions.push_back(tmpInst);
357 tmpInst = new MCInst();
358 tmpInst->setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
359 tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
360 tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
361 tmpInst->addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
362 tmpInst->setLoc(IDLoc);
363 Instructions.push_back(tmpInst);
364 }
365}
Rafael Espindolafddf8042012-01-11 03:56:41 +0000366bool MipsAsmParser::
367MatchAndEmitInstruction(SMLoc IDLoc,
368 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
369 MCStreamer &Out) {
Jack Carterec65be82012-09-05 23:34:03 +0000370 MCInst Inst;
Jack Carterec65be82012-09-05 23:34:03 +0000371 unsigned Kind;
Chad Rosier22685872012-10-01 23:45:51 +0000372 unsigned ErrorInfo;
Chad Rosier9ba9d4d2012-10-05 18:41:14 +0000373 MatchInstMapAndConstraints MapAndConstraints;
Chad Rosier22685872012-10-01 23:45:51 +0000374 unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst,
375 MapAndConstraints, ErrorInfo,
376 /*matchingInlineAsm*/ false);
Jack Carterec65be82012-09-05 23:34:03 +0000377
378 switch (MatchResult) {
379 default: break;
380 case Match_Success: {
Jack Carter9d577c82012-10-04 04:03:53 +0000381 if (needsExpansion(Inst)) {
382 SmallVector<MCInst*, 4> Instructions;
383 expandInstruction(Inst, IDLoc, Instructions);
384 for(unsigned i =0; i < Instructions.size(); i++){
385 Inst = *(Instructions[i]);
386 Out.EmitInstruction(Inst);
387 }
388 } else {
389 Inst.setLoc(IDLoc);
390 Out.EmitInstruction(Inst);
391 }
Jack Carterec65be82012-09-05 23:34:03 +0000392 return false;
393 }
394 case Match_MissingFeature:
395 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
396 return true;
397 case Match_InvalidOperand: {
398 SMLoc ErrorLoc = IDLoc;
399 if (ErrorInfo != ~0U) {
400 if (ErrorInfo >= Operands.size())
401 return Error(IDLoc, "too few operands for instruction");
402
403 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
404 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
405 }
406
407 return Error(ErrorLoc, "invalid operand for instruction");
408 }
409 case Match_MnemonicFail:
410 return Error(IDLoc, "invalid instruction");
411 }
Rafael Espindolafddf8042012-01-11 03:56:41 +0000412 return true;
413}
414
Jack Carterec65be82012-09-05 23:34:03 +0000415int MipsAsmParser::matchRegisterName(StringRef Name) {
416
417 int CC = StringSwitch<unsigned>(Name)
418 .Case("zero", Mips::ZERO)
419 .Case("a0", Mips::A0)
420 .Case("a1", Mips::A1)
421 .Case("a2", Mips::A2)
422 .Case("a3", Mips::A3)
423 .Case("v0", Mips::V0)
424 .Case("v1", Mips::V1)
425 .Case("s0", Mips::S0)
426 .Case("s1", Mips::S1)
427 .Case("s2", Mips::S2)
428 .Case("s3", Mips::S3)
429 .Case("s4", Mips::S4)
430 .Case("s5", Mips::S5)
431 .Case("s6", Mips::S6)
432 .Case("s7", Mips::S7)
433 .Case("k0", Mips::K0)
434 .Case("k1", Mips::K1)
435 .Case("sp", Mips::SP)
436 .Case("fp", Mips::FP)
437 .Case("gp", Mips::GP)
438 .Case("ra", Mips::RA)
439 .Case("t0", Mips::T0)
440 .Case("t1", Mips::T1)
441 .Case("t2", Mips::T2)
442 .Case("t3", Mips::T3)
443 .Case("t4", Mips::T4)
444 .Case("t5", Mips::T5)
445 .Case("t6", Mips::T6)
446 .Case("t7", Mips::T7)
447 .Case("t8", Mips::T8)
448 .Case("t9", Mips::T9)
449 .Case("at", Mips::AT)
450 .Case("fcc0", Mips::FCC0)
451 .Default(-1);
452
453 if (CC != -1) {
Jack Carter9d577c82012-10-04 04:03:53 +0000454 // 64 bit register in Mips are following 32 bit definitions.
Jack Carterec65be82012-09-05 23:34:03 +0000455 if (isMips64())
456 CC++;
457 return CC;
458 }
459
Jack Carterf740d6e2012-09-07 00:23:42 +0000460 if (Name[0] == 'f') {
461 StringRef NumString = Name.substr(1);
462 unsigned IntVal;
463 if( NumString.getAsInteger(10, IntVal))
Jack Carter9d577c82012-10-04 04:03:53 +0000464 return -1; // not integer
Jack Carterf740d6e2012-09-07 00:23:42 +0000465 if (IntVal > 31)
466 return -1;
467
468 FpFormatTy Format = getFpFormat();
469
470 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
471 return getReg(Mips::FGR32RegClassID, IntVal);
472 if (Format == FP_FORMAT_D) {
473 if(isFP64()) {
474 return getReg(Mips::FGR64RegClassID, IntVal);
475 }
Jack Carter9d577c82012-10-04 04:03:53 +0000476 // only even numbers available as register pairs
Jack Carterf740d6e2012-09-07 00:23:42 +0000477 if (( IntVal > 31) || (IntVal%2 != 0))
478 return -1;
479 return getReg(Mips::AFGR64RegClassID, IntVal/2);
480 }
481 }
482
Jack Carterec65be82012-09-05 23:34:03 +0000483 return -1;
484}
Jack Carterf740d6e2012-09-07 00:23:42 +0000485void MipsAsmParser::setDefaultFpFormat() {
486
487 if (isMips64() || isFP64())
488 FpFormat = FP_FORMAT_D;
489 else
490 FpFormat = FP_FORMAT_S;
491}
492
493bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
494
495 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
496 .Case("ldxc1", true)
497 .Case("ldc1", true)
498 .Case("sdxc1", true)
499 .Case("sdc1", true)
500 .Default(false);
501
502 return IsDouble;
503}
504void MipsAsmParser::setFpFormat(StringRef Format) {
505
506 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
507 .Case(".s", FP_FORMAT_S)
508 .Case(".d", FP_FORMAT_D)
509 .Case(".l", FP_FORMAT_L)
510 .Case(".w", FP_FORMAT_W)
511 .Default(FP_FORMAT_NONE);
512}
Jack Carterec65be82012-09-05 23:34:03 +0000513
Jack Carter30116cd2012-10-04 02:29:46 +0000514bool MipsAssemblerOptions::setATReg(unsigned Reg) {
515 if (Reg > 31)
516 return false;
517
518 aTReg = Reg;
519 return true;
520}
521
522unsigned MipsAsmParser::getATReg() {
Jack Carter10d5ff62012-10-05 23:55:28 +0000523 unsigned Reg = Options.getATRegNum();
Jack Carter30116cd2012-10-04 02:29:46 +0000524 if (isMips64())
525 return getReg(Mips::CPU64RegsRegClassID,Reg);
Jack Carter10d5ff62012-10-05 23:55:28 +0000526
527 return getReg(Mips::CPURegsRegClassID,Reg);
Jack Carter30116cd2012-10-04 02:29:46 +0000528}
529
530unsigned MipsAsmParser::getReg(int RC,int RegNo) {
Jack Carterec65be82012-09-05 23:34:03 +0000531 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
532}
533
Jack Carter30116cd2012-10-04 02:29:46 +0000534int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
Jack Carterec65be82012-09-05 23:34:03 +0000535
536 if (Mnemonic.lower() == "rdhwr") {
Jack Carter9d577c82012-10-04 04:03:53 +0000537 // at the moment only hwreg29 is supported
Jack Carterec65be82012-09-05 23:34:03 +0000538 if (RegNum != 29)
539 return -1;
540 return Mips::HWR29;
541 }
542
543 if (RegNum > 31)
544 return -1;
545
Jack Carter30116cd2012-10-04 02:29:46 +0000546 return getReg(Mips::CPURegsRegClassID, RegNum);
Jack Carterec65be82012-09-05 23:34:03 +0000547}
548
549int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
550 const AsmToken &Tok = Parser.getTok();
551 int RegNum = -1;
552
553 if (Tok.is(AsmToken::Identifier)) {
554 std::string lowerCase = Tok.getString().lower();
555 RegNum = matchRegisterName(lowerCase);
556 } else if (Tok.is(AsmToken::Integer))
Jack Carter9d577c82012-10-04 04:03:53 +0000557 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carter6b96c3f2012-09-06 20:00:02 +0000558 Mnemonic.lower());
Jack Carterf740d6e2012-09-07 00:23:42 +0000559 else
560 return RegNum; //error
Jack Carter9d577c82012-10-04 04:03:53 +0000561 // 64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
Jack Carterf740d6e2012-09-07 00:23:42 +0000562 if (isMips64() && RegNum == Mips::ZERO_64) {
563 if (Mnemonic.find("ddiv") != StringRef::npos)
564 RegNum = Mips::ZERO;
565 }
Jack Carterec65be82012-09-05 23:34:03 +0000566 return RegNum;
567}
568
Rafael Espindolafddf8042012-01-11 03:56:41 +0000569bool MipsAsmParser::
Jack Carterec65be82012-09-05 23:34:03 +0000570 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
571 StringRef Mnemonic){
572
573 SMLoc S = Parser.getTok().getLoc();
574 int RegNo = -1;
Jack Carterf740d6e2012-09-07 00:23:42 +0000575
Jack Carter9d577c82012-10-04 04:03:53 +0000576 // FIXME: we should make a more generic method for CCR
Jack Carterf740d6e2012-09-07 00:23:42 +0000577 if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
578 && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
Jack Carter9d577c82012-10-04 04:03:53 +0000579 RegNo = Parser.getTok().getIntVal(); // get the int value
580 // at the moment only fcc0 is supported
Jack Carterf740d6e2012-09-07 00:23:42 +0000581 if (RegNo == 0)
582 RegNo = Mips::FCC0;
583 } else
584 RegNo = tryParseRegister(Mnemonic);
Jack Carterec65be82012-09-05 23:34:03 +0000585 if (RegNo == -1)
586 return true;
587
588 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterf740d6e2012-09-07 00:23:42 +0000589 Parser.getTok().getLoc()));
Jack Carterec65be82012-09-05 23:34:03 +0000590 Parser.Lex(); // Eat register token.
591 return false;
592}
593
594bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
595 StringRef Mnemonic) {
Jack Carter9d577c82012-10-04 04:03:53 +0000596 // Check if the current operand has a custom associated parser, if so, try to
597 // custom parse the operand, or fallback to the general approach.
Jack Carterec65be82012-09-05 23:34:03 +0000598 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
599 if (ResTy == MatchOperand_Success)
600 return false;
601 // If there wasn't a custom match, try the generic matcher below. Otherwise,
602 // there was a match, but an error occurred, in which case, just return that
603 // the operand parsing failed.
604 if (ResTy == MatchOperand_ParseFail)
605 return true;
606
607 switch (getLexer().getKind()) {
608 default:
609 Error(Parser.getTok().getLoc(), "unexpected token in operand");
610 return true;
611 case AsmToken::Dollar: {
Jack Carter9d577c82012-10-04 04:03:53 +0000612 // parse register
Jack Carterec65be82012-09-05 23:34:03 +0000613 SMLoc S = Parser.getTok().getLoc();
614 Parser.Lex(); // Eat dollar token.
Jack Carter9d577c82012-10-04 04:03:53 +0000615 // parse register operand
616 if (!tryParseRegisterOperand(Operands, Mnemonic)) {
Jack Carterec65be82012-09-05 23:34:03 +0000617 if (getLexer().is(AsmToken::LParen)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000618 // check if it is indexed addressing operand
Jack Carterec65be82012-09-05 23:34:03 +0000619 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carter9d577c82012-10-04 04:03:53 +0000620 Parser.Lex(); // eat parenthesis
Jack Carterec65be82012-09-05 23:34:03 +0000621 if (getLexer().isNot(AsmToken::Dollar))
622 return true;
623
Jack Carter9d577c82012-10-04 04:03:53 +0000624 Parser.Lex(); // eat dollar
625 if (tryParseRegisterOperand(Operands, Mnemonic))
Jack Carterec65be82012-09-05 23:34:03 +0000626 return true;
627
628 if (!getLexer().is(AsmToken::RParen))
629 return true;
630
631 S = Parser.getTok().getLoc();
632 Operands.push_back(MipsOperand::CreateToken(")", S));
633 Parser.Lex();
634 }
635 return false;
636 }
Jack Carter9d577c82012-10-04 04:03:53 +0000637 // maybe it is a symbol reference
Jack Carterec65be82012-09-05 23:34:03 +0000638 StringRef Identifier;
639 if (Parser.ParseIdentifier(Identifier))
640 return true;
641
Jack Carter6b96c3f2012-09-06 20:00:02 +0000642 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000643
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000644 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterec65be82012-09-05 23:34:03 +0000645
646 // Otherwise create a symbol ref.
Jack Carter6b96c3f2012-09-06 20:00:02 +0000647 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterec65be82012-09-05 23:34:03 +0000648 getContext());
649
650 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
651 return false;
652 }
653 case AsmToken::Identifier:
654 case AsmToken::LParen:
655 case AsmToken::Minus:
656 case AsmToken::Plus:
657 case AsmToken::Integer:
658 case AsmToken::String: {
659 // quoted label names
660 const MCExpr *IdVal;
661 SMLoc S = Parser.getTok().getLoc();
662 if (getParser().ParseExpression(IdVal))
663 return true;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000664 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000665 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
666 return false;
667 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000668 case AsmToken::Percent: {
Jack Carter9d577c82012-10-04 04:03:53 +0000669 // it is a symbol reference or constant expression
Jack Carter6b96c3f2012-09-06 20:00:02 +0000670 const MCExpr *IdVal;
Jack Carter9d577c82012-10-04 04:03:53 +0000671 SMLoc S = Parser.getTok().getLoc(); // start location of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000672 if (parseRelocOperand(IdVal))
673 return true;
674
675 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
676
677 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
678 return false;
Jack Carter30116cd2012-10-04 02:29:46 +0000679 } // case AsmToken::Percent
680 } // switch(getLexer().getKind())
Rafael Espindolafddf8042012-01-11 03:56:41 +0000681 return true;
682}
683
Jack Carter6b96c3f2012-09-06 20:00:02 +0000684bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
685
Jack Carter30116cd2012-10-04 02:29:46 +0000686 Parser.Lex(); // eat % token
Jack Carter9d577c82012-10-04 04:03:53 +0000687 const AsmToken &Tok = Parser.getTok(); // get next token, operation
Jack Carter6b96c3f2012-09-06 20:00:02 +0000688 if (Tok.isNot(AsmToken::Identifier))
689 return true;
690
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000691 std::string Str = Tok.getIdentifier().str();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000692
Jack Carter9d577c82012-10-04 04:03:53 +0000693 Parser.Lex(); // eat identifier
Jack Carter30116cd2012-10-04 02:29:46 +0000694 // now make expression from the rest of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000695 const MCExpr *IdVal;
696 SMLoc EndLoc;
697
698 if (getLexer().getKind() == AsmToken::LParen) {
699 while (1) {
Jack Carter30116cd2012-10-04 02:29:46 +0000700 Parser.Lex(); // eat '(' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000701 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carter30116cd2012-10-04 02:29:46 +0000702 Parser.Lex(); // eat % token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000703 const AsmToken &nextTok = Parser.getTok();
704 if (nextTok.isNot(AsmToken::Identifier))
705 return true;
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000706 Str += "(%";
707 Str += nextTok.getIdentifier();
Jack Carter30116cd2012-10-04 02:29:46 +0000708 Parser.Lex(); // eat identifier
Jack Carter6b96c3f2012-09-06 20:00:02 +0000709 if (getLexer().getKind() != AsmToken::LParen)
710 return true;
711 } else
712 break;
713 }
714 if (getParser().ParseParenExpression(IdVal,EndLoc))
715 return true;
716
717 while (getLexer().getKind() == AsmToken::RParen)
Jack Carter30116cd2012-10-04 02:29:46 +0000718 Parser.Lex(); // eat ')' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000719
720 } else
Jack Carter30116cd2012-10-04 02:29:46 +0000721 return true; // parenthesis must follow reloc operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000722
Jack Carter30116cd2012-10-04 02:29:46 +0000723 // Check the type of the expression
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000724 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000725 // it's a constant, evaluate lo or hi value
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000726 int Val = MCE->getValue();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000727 if (Str == "lo") {
728 Val = Val & 0xffff;
729 } else if (Str == "hi") {
730 Val = (Val & 0xffff0000) >> 16;
731 }
732 Res = MCConstantExpr::Create(Val, getContext());
733 return false;
734 }
735
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000736 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter30116cd2012-10-04 02:29:46 +0000737 // it's a symbol, create symbolic expression from symbol
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000738 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000739 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
740 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
741 return false;
742 }
743 return true;
744}
745
Jack Carterec65be82012-09-05 23:34:03 +0000746bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
747 SMLoc &EndLoc) {
748
749 StartLoc = Parser.getTok().getLoc();
750 RegNo = tryParseRegister("");
751 EndLoc = Parser.getTok().getLoc();
752 return (RegNo == (unsigned)-1);
753}
754
Jack Carter6b96c3f2012-09-06 20:00:02 +0000755bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
756
757 SMLoc S;
758
759 switch(getLexer().getKind()) {
760 default:
761 return true;
762 case AsmToken::Integer:
763 case AsmToken::Minus:
764 case AsmToken::Plus:
765 return (getParser().ParseExpression(Res));
Jack Carterf740d6e2012-09-07 00:23:42 +0000766 case AsmToken::Percent:
Jack Carter6b96c3f2012-09-06 20:00:02 +0000767 return parseRelocOperand(Res);
Jack Carter6b96c3f2012-09-06 20:00:02 +0000768 case AsmToken::LParen:
Jack Carter30116cd2012-10-04 02:29:46 +0000769 return false; // it's probably assuming 0
Jack Carter6b96c3f2012-09-06 20:00:02 +0000770 }
771 return true;
772}
773
Jack Carterec65be82012-09-05 23:34:03 +0000774MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
775 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000776
777 const MCExpr *IdVal = 0;
778 SMLoc S;
Jack Carter30116cd2012-10-04 02:29:46 +0000779 // first operand is the offset
Jack Carter6b96c3f2012-09-06 20:00:02 +0000780 S = Parser.getTok().getLoc();
781
782 if (parseMemOffset(IdVal))
783 return MatchOperand_ParseFail;
784
Jack Carter30116cd2012-10-04 02:29:46 +0000785 const AsmToken &Tok = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000786 if (Tok.isNot(AsmToken::LParen)) {
787 Error(Parser.getTok().getLoc(), "'(' expected");
788 return MatchOperand_ParseFail;
789 }
790
791 Parser.Lex(); // Eat '(' token.
792
793 const AsmToken &Tok1 = Parser.getTok(); //get next token
794 if (Tok1.is(AsmToken::Dollar)) {
795 Parser.Lex(); // Eat '$' token.
796 if (tryParseRegisterOperand(Operands,"")) {
797 Error(Parser.getTok().getLoc(), "unexpected token in operand");
798 return MatchOperand_ParseFail;
799 }
800
801 } else {
Jack Carter30116cd2012-10-04 02:29:46 +0000802 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carter6b96c3f2012-09-06 20:00:02 +0000803 return MatchOperand_ParseFail;
804 }
805
Jack Carter30116cd2012-10-04 02:29:46 +0000806 const AsmToken &Tok2 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000807 if (Tok2.isNot(AsmToken::RParen)) {
808 Error(Parser.getTok().getLoc(), "')' expected");
809 return MatchOperand_ParseFail;
810 }
811
812 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
813
814 Parser.Lex(); // Eat ')' token.
815
816 if (IdVal == 0)
817 IdVal = MCConstantExpr::Create(0, getContext());
818
Jack Carter30116cd2012-10-04 02:29:46 +0000819 // now replace register operand with the mem operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000820 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
821 int RegNo = op->getReg();
Jack Carter30116cd2012-10-04 02:29:46 +0000822 // remove register from operands
Jack Carter6b96c3f2012-09-06 20:00:02 +0000823 Operands.pop_back();
Jack Carter30116cd2012-10-04 02:29:46 +0000824 // and add memory operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000825 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
826 delete op;
Jack Carterec65be82012-09-05 23:34:03 +0000827 return MatchOperand_Success;
828}
829
Jack Carter6b96c3f2012-09-06 20:00:02 +0000830MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
831
832 MCSymbolRefExpr::VariantKind VK
833 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
834 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
835 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
836 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
837 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
838 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
839 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
840 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
841 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
842 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
843 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
844 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
845 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
846 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
847 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
848 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
849 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
850 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
851 .Default(MCSymbolRefExpr::VK_None);
852
853 return VK;
854}
855
Benjamin Kramer1ac45872012-09-10 11:52:14 +0000856static int ConvertCcString(StringRef CondString) {
Jack Carterf740d6e2012-09-07 00:23:42 +0000857 int CC = StringSwitch<unsigned>(CondString)
858 .Case(".f", 0)
859 .Case(".un", 1)
860 .Case(".eq", 2)
861 .Case(".ueq", 3)
862 .Case(".olt", 4)
863 .Case(".ult", 5)
864 .Case(".ole", 6)
865 .Case(".ule", 7)
866 .Case(".sf", 8)
867 .Case(".ngle", 9)
868 .Case(".seq", 10)
869 .Case(".ngl", 11)
870 .Case(".lt", 12)
871 .Case(".nge", 13)
872 .Case(".le", 14)
873 .Case(".ngt", 15)
874 .Default(-1);
875
876 return CC;
877}
878
879bool MipsAsmParser::
880parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter30116cd2012-10-04 02:29:46 +0000881 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
882 // split the format
Jack Carterf740d6e2012-09-07 00:23:42 +0000883 size_t Start = Name.find('.'), Next = Name.rfind('.');
884 StringRef Format1 = Name.slice(Start, Next);
Jack Carter30116cd2012-10-04 02:29:46 +0000885 // and add the first format to the operands
Jack Carterf740d6e2012-09-07 00:23:42 +0000886 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carter30116cd2012-10-04 02:29:46 +0000887 // now for the second format
Jack Carterf740d6e2012-09-07 00:23:42 +0000888 StringRef Format2 = Name.slice(Next, StringRef::npos);
889 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
890
Jack Carter30116cd2012-10-04 02:29:46 +0000891 // set the format for the first register
Jack Carterf740d6e2012-09-07 00:23:42 +0000892 setFpFormat(Format1);
893
894 // Read the remaining operands.
895 if (getLexer().isNot(AsmToken::EndOfStatement)) {
896 // Read the first operand.
897 if (ParseOperand(Operands, Name)) {
898 SMLoc Loc = getLexer().getLoc();
899 Parser.EatToEndOfStatement();
900 return Error(Loc, "unexpected token in argument list");
901 }
902
903 if (getLexer().isNot(AsmToken::Comma)) {
904 SMLoc Loc = getLexer().getLoc();
905 Parser.EatToEndOfStatement();
906 return Error(Loc, "unexpected token in argument list");
907
908 }
909 Parser.Lex(); // Eat the comma.
910
911 //set the format for the first register
912 setFpFormat(Format2);
913
914 // Parse and remember the operand.
915 if (ParseOperand(Operands, Name)) {
916 SMLoc Loc = getLexer().getLoc();
917 Parser.EatToEndOfStatement();
918 return Error(Loc, "unexpected token in argument list");
919 }
920 }
921
922 if (getLexer().isNot(AsmToken::EndOfStatement)) {
923 SMLoc Loc = getLexer().getLoc();
924 Parser.EatToEndOfStatement();
925 return Error(Loc, "unexpected token in argument list");
926 }
927
928 Parser.Lex(); // Consume the EndOfStatement
929 return false;
930}
931
Rafael Espindolafddf8042012-01-11 03:56:41 +0000932bool MipsAsmParser::
933ParseInstruction(StringRef Name, SMLoc NameLoc,
934 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter30116cd2012-10-04 02:29:46 +0000935 // floating point instructions: should register be treated as double?
Jack Carterf740d6e2012-09-07 00:23:42 +0000936 if (requestsDoubleOperand(Name)) {
937 setFpFormat(FP_FORMAT_D);
Jack Carterec65be82012-09-05 23:34:03 +0000938 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterf740d6e2012-09-07 00:23:42 +0000939 }
940 else {
941 setDefaultFpFormat();
942 // Create the leading tokens for the mnemonic, split by '.' characters.
943 size_t Start = 0, Next = Name.find('.');
944 StringRef Mnemonic = Name.slice(Start, Next);
945
946 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
947
948 if (Next != StringRef::npos) {
Jack Carter30116cd2012-10-04 02:29:46 +0000949 // there is a format token in mnemonic
950 // StringRef Rest = Name.slice(Next, StringRef::npos);
Jack Carterf740d6e2012-09-07 00:23:42 +0000951 size_t Dot = Name.find('.', Next+1);
952 StringRef Format = Name.slice(Next, Dot);
953 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
954 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
955 else {
956 if (Name.startswith("c.")){
957 // floating point compare, add '.' and immediate represent for cc
958 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
959 int Cc = ConvertCcString(Format);
960 if (Cc == -1) {
961 return Error(NameLoc, "Invalid conditional code");
962 }
963 SMLoc E = SMLoc::getFromPointer(
964 Parser.getTok().getLoc().getPointer() -1 );
965 Operands.push_back(MipsOperand::CreateImm(
966 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
967 } else {
Jack Carter30116cd2012-10-04 02:29:46 +0000968 // trunc, ceil, floor ...
Jack Carterf740d6e2012-09-07 00:23:42 +0000969 return parseMathOperation(Name, NameLoc, Operands);
970 }
971
Jack Carter30116cd2012-10-04 02:29:46 +0000972 // the rest is a format
Jack Carterf740d6e2012-09-07 00:23:42 +0000973 Format = Name.slice(Dot, StringRef::npos);
974 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
975 }
976
977 setFpFormat(Format);
978 }
979 }
Jack Carterec65be82012-09-05 23:34:03 +0000980
981 // Read the remaining operands.
982 if (getLexer().isNot(AsmToken::EndOfStatement)) {
983 // Read the first operand.
984 if (ParseOperand(Operands, Name)) {
985 SMLoc Loc = getLexer().getLoc();
986 Parser.EatToEndOfStatement();
987 return Error(Loc, "unexpected token in argument list");
988 }
989
990 while (getLexer().is(AsmToken::Comma) ) {
991 Parser.Lex(); // Eat the comma.
992
993 // Parse and remember the operand.
994 if (ParseOperand(Operands, Name)) {
995 SMLoc Loc = getLexer().getLoc();
996 Parser.EatToEndOfStatement();
997 return Error(Loc, "unexpected token in argument list");
998 }
999 }
1000 }
1001
1002 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1003 SMLoc Loc = getLexer().getLoc();
1004 Parser.EatToEndOfStatement();
1005 return Error(Loc, "unexpected token in argument list");
1006 }
1007
1008 Parser.Lex(); // Consume the EndOfStatement
1009 return false;
Rafael Espindolafddf8042012-01-11 03:56:41 +00001010}
1011
Jack Carter30116cd2012-10-04 02:29:46 +00001012bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1013 SMLoc Loc = getLexer().getLoc();
1014 Parser.EatToEndOfStatement();
1015 return Error(Loc, ErrorMsg);
1016}
1017
1018bool MipsAsmParser::parseSetNoAtDirective() {
1019 // line should look like:
1020 // .set noat
1021 // set at reg to 0
Jack Carter10d5ff62012-10-05 23:55:28 +00001022 Options.setATReg(0);
Jack Carter30116cd2012-10-04 02:29:46 +00001023 // eat noat
1024 Parser.Lex();
1025 // if this is not the end of the statement, report error
1026 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1027 reportParseError("unexpected token in statement");
1028 return false;
1029 }
1030 Parser.Lex(); // Consume the EndOfStatement
1031 return false;
1032}
1033bool MipsAsmParser::parseSetAtDirective() {
1034 // line can be
1035 // .set at - defaults to $1
1036 // or .set at=$reg
1037 getParser().Lex();
1038 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter10d5ff62012-10-05 23:55:28 +00001039 Options.setATReg(1);
Jack Carter30116cd2012-10-04 02:29:46 +00001040 Parser.Lex(); // Consume the EndOfStatement
1041 return false;
1042 } else if (getLexer().is(AsmToken::Equal)) {
1043 getParser().Lex(); //eat '='
1044 if (getLexer().isNot(AsmToken::Dollar)) {
1045 reportParseError("unexpected token in statement");
1046 return false;
1047 }
1048 Parser.Lex(); // eat '$'
1049 if (getLexer().isNot(AsmToken::Integer)) {
1050 reportParseError("unexpected token in statement");
1051 return false;
1052 }
1053 const AsmToken &Reg = Parser.getTok();
Jack Carter10d5ff62012-10-05 23:55:28 +00001054 if (!Options.setATReg(Reg.getIntVal())) {
Jack Carter30116cd2012-10-04 02:29:46 +00001055 reportParseError("unexpected token in statement");
1056 return false;
1057 }
1058 getParser().Lex(); //eat reg
1059
1060 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1061 reportParseError("unexpected token in statement");
1062 return false;
1063 }
1064 Parser.Lex(); // Consume the EndOfStatement
1065 return false;
1066 } else {
1067 reportParseError("unexpected token in statement");
1068 return false;
1069 }
1070}
1071
1072bool MipsAsmParser::parseSetReorderDirective() {
1073 Parser.Lex();
1074 // if this is not the end of the statement, report error
1075 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1076 reportParseError("unexpected token in statement");
1077 return false;
1078 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001079 Options.setReorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001080 Parser.Lex(); // Consume the EndOfStatement
1081 return false;
1082}
1083
1084bool MipsAsmParser::parseSetNoReorderDirective() {
1085 Parser.Lex();
1086 // if this is not the end of the statement, report error
1087 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1088 reportParseError("unexpected token in statement");
1089 return false;
1090 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001091 Options.setNoreorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001092 Parser.Lex(); // Consume the EndOfStatement
1093 return false;
1094}
1095
1096bool MipsAsmParser::parseSetMacroDirective() {
1097 Parser.Lex();
1098 // if this is not the end of the statement, report error
1099 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1100 reportParseError("unexpected token in statement");
1101 return false;
1102 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001103 Options.setMacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001104 Parser.Lex(); // Consume the EndOfStatement
1105 return false;
1106}
1107
1108bool MipsAsmParser::parseSetNoMacroDirective() {
1109 Parser.Lex();
1110 // if this is not the end of the statement, report error
1111 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1112 reportParseError("`noreorder' must be set before `nomacro'");
1113 return false;
1114 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001115 if (Options.isReorder()) {
Jack Carter30116cd2012-10-04 02:29:46 +00001116 reportParseError("`noreorder' must be set before `nomacro'");
1117 return false;
1118 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001119 Options.setNomacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001120 Parser.Lex(); // Consume the EndOfStatement
1121 return false;
1122}
1123bool MipsAsmParser::parseDirectiveSet() {
1124
1125 // get next token
1126 const AsmToken &Tok = Parser.getTok();
1127
1128 if (Tok.getString() == "noat") {
1129 return parseSetNoAtDirective();
1130 } else if (Tok.getString() == "at") {
1131 return parseSetAtDirective();
1132 } else if (Tok.getString() == "reorder") {
1133 return parseSetReorderDirective();
1134 } else if (Tok.getString() == "noreorder") {
1135 return parseSetNoReorderDirective();
1136 } else if (Tok.getString() == "macro") {
1137 return parseSetMacroDirective();
1138 } else if (Tok.getString() == "nomacro") {
1139 return parseSetNoMacroDirective();
1140 } else if (Tok.getString() == "nomips16") {
1141 // ignore this directive for now
1142 Parser.EatToEndOfStatement();
1143 return false;
1144 } else if (Tok.getString() == "nomicromips") {
1145 // ignore this directive for now
1146 Parser.EatToEndOfStatement();
1147 return false;
1148 }
1149 return true;
1150}
1151
1152bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carteracbea452012-09-07 00:48:02 +00001153
1154 if (DirectiveID.getString() == ".ent") {
Jack Carter30116cd2012-10-04 02:29:46 +00001155 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001156 Parser.Lex();
1157 return false;
1158 }
1159
1160 if (DirectiveID.getString() == ".end") {
Jack Carter30116cd2012-10-04 02:29:46 +00001161 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001162 Parser.Lex();
1163 return false;
1164 }
1165
1166 if (DirectiveID.getString() == ".frame") {
Jack Carter30116cd2012-10-04 02:29:46 +00001167 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001168 Parser.EatToEndOfStatement();
1169 return false;
1170 }
1171
1172 if (DirectiveID.getString() == ".set") {
Jack Carter30116cd2012-10-04 02:29:46 +00001173 return parseDirectiveSet();
Jack Carteracbea452012-09-07 00:48:02 +00001174 }
1175
1176 if (DirectiveID.getString() == ".fmask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001177 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001178 Parser.EatToEndOfStatement();
1179 return false;
1180 }
1181
1182 if (DirectiveID.getString() == ".mask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001183 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001184 Parser.EatToEndOfStatement();
1185 return false;
1186 }
1187
1188 if (DirectiveID.getString() == ".gpword") {
Jack Carter30116cd2012-10-04 02:29:46 +00001189 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001190 Parser.EatToEndOfStatement();
1191 return false;
1192 }
1193
Rafael Espindolafddf8042012-01-11 03:56:41 +00001194 return true;
1195}
1196
Rafael Espindolafddf8042012-01-11 03:56:41 +00001197extern "C" void LLVMInitializeMipsAsmParser() {
1198 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1199 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1200 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1201 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1202}
Jack Carterec65be82012-09-05 23:34:03 +00001203
1204#define GET_REGISTER_MATCHER
1205#define GET_MATCHER_IMPLEMENTATION
1206#include "MipsGenAsmMatcher.inc"