blob: f2800d3b613253ffb4357703421925c1977a2095 [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 Carter30116cd2012-10-04 02:29:46 +000064 MipsAssemblerOptions *Options;
65
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()));
Jack Carter30116cd2012-10-04 02:29:46 +0000149 Options = new MipsAssemblerOptions();
Rafael Espindolafddf8042012-01-11 03:56:41 +0000150 }
151
Jack Carterec65be82012-09-05 23:34:03 +0000152 MCAsmParser &getParser() const { return Parser; }
153 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
154
Rafael Espindolafddf8042012-01-11 03:56:41 +0000155};
156}
157
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000158namespace {
159
160/// MipsOperand - Instances of this class represent a parsed Mips machine
161/// instruction.
162class MipsOperand : public MCParsedAsmOperand {
Jack Carterec65be82012-09-05 23:34:03 +0000163
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000164 enum KindTy {
165 k_CondCode,
166 k_CoprocNum,
167 k_Immediate,
168 k_Memory,
169 k_PostIndexRegister,
170 k_Register,
171 k_Token
172 } Kind;
173
174 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterec65be82012-09-05 23:34:03 +0000175
176 union {
177 struct {
178 const char *Data;
179 unsigned Length;
180 } Tok;
181
182 struct {
183 unsigned RegNum;
184 } Reg;
185
186 struct {
187 const MCExpr *Val;
188 } Imm;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000189
190 struct {
191 unsigned Base;
192 const MCExpr *Off;
193 } Mem;
Jack Carterec65be82012-09-05 23:34:03 +0000194 };
195
196 SMLoc StartLoc, EndLoc;
197
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000198public:
199 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000200 assert(N == 1 && "Invalid number of operands!");
201 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000202 }
Jack Carterec65be82012-09-05 23:34:03 +0000203
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000204 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterec65be82012-09-05 23:34:03 +0000205 // Add as immediate when possible. Null MCExpr = 0.
206 if (Expr == 0)
207 Inst.addOperand(MCOperand::CreateImm(0));
208 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
209 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
210 else
211 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000212 }
Jack Carterec65be82012-09-05 23:34:03 +0000213
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000214 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000215 assert(N == 1 && "Invalid number of operands!");
216 const MCExpr *Expr = getImm();
217 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000218 }
Jack Carterec65be82012-09-05 23:34:03 +0000219
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000220 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000221 assert(N == 2 && "Invalid number of operands!");
222
223 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
224
225 const MCExpr *Expr = getMemOff();
226 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000227 }
228
229 bool isReg() const { return Kind == k_Register; }
230 bool isImm() const { return Kind == k_Immediate; }
231 bool isToken() const { return Kind == k_Token; }
232 bool isMem() const { return Kind == k_Memory; }
233
234 StringRef getToken() const {
235 assert(Kind == k_Token && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000236 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000237 }
238
239 unsigned getReg() const {
240 assert((Kind == k_Register) && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000241 return Reg.RegNum;
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000242 }
243
Jack Carterec65be82012-09-05 23:34:03 +0000244 const MCExpr *getImm() const {
245 assert((Kind == k_Immediate) && "Invalid access!");
246 return Imm.Val;
247 }
248
Jack Carter6b96c3f2012-09-06 20:00:02 +0000249 unsigned getMemBase() const {
250 assert((Kind == k_Memory) && "Invalid access!");
251 return Mem.Base;
252 }
253
254 const MCExpr *getMemOff() const {
255 assert((Kind == k_Memory) && "Invalid access!");
256 return Mem.Off;
257 }
258
Jack Carterec65be82012-09-05 23:34:03 +0000259 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
260 MipsOperand *Op = new MipsOperand(k_Token);
261 Op->Tok.Data = Str.data();
262 Op->Tok.Length = Str.size();
263 Op->StartLoc = S;
264 Op->EndLoc = S;
265 return Op;
266 }
267
268 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
269 MipsOperand *Op = new MipsOperand(k_Register);
270 Op->Reg.RegNum = RegNum;
271 Op->StartLoc = S;
272 Op->EndLoc = E;
273 return Op;
274 }
275
276 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
277 MipsOperand *Op = new MipsOperand(k_Immediate);
278 Op->Imm.Val = Val;
279 Op->StartLoc = S;
280 Op->EndLoc = E;
281 return Op;
282 }
283
Jack Carter6b96c3f2012-09-06 20:00:02 +0000284 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
285 SMLoc S, SMLoc E) {
286 MipsOperand *Op = new MipsOperand(k_Memory);
287 Op->Mem.Base = Base;
288 Op->Mem.Off = Off;
289 Op->StartLoc = S;
290 Op->EndLoc = E;
291 return Op;
292 }
293
Jack Carterec65be82012-09-05 23:34:03 +0000294 /// getStartLoc - Get the location of the first token of this operand.
295 SMLoc getStartLoc() const { return StartLoc; }
296 /// getEndLoc - Get the location of the last token of this operand.
297 SMLoc getEndLoc() const { return EndLoc; }
298
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000299 virtual void print(raw_ostream &OS) const {
300 llvm_unreachable("unimplemented!");
301 }
302};
303}
304
Jack Carter9d577c82012-10-04 04:03:53 +0000305bool MipsAsmParser::needsExpansion(MCInst &Inst) {
306
307 switch(Inst.getOpcode()) {
308 case Mips::LoadImm32Reg:
309 return true;
310 default:
311 return false;
312 }
313}
314void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
315 SmallVectorImpl<MCInst*> &Instructions){
316 switch(Inst.getOpcode()) {
317 case Mips::LoadImm32Reg:
318 return expandLoadImm(Inst, IDLoc, Instructions);
319 }
320 return;
321}
322void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
323 SmallVectorImpl<MCInst*> &Instructions){
324 MCInst *tmpInst = new MCInst();
325 const MCOperand &ImmOp = Inst.getOperand(1);
326 assert(ImmOp.isImm() && "expected imediate operand kind");
327 const MCOperand &RegOp = Inst.getOperand(0);
328 assert(RegOp.isReg() && "expected register operand kind");
329
330 int ImmValue = ImmOp.getImm();
331 tmpInst->setLoc(IDLoc);
332 if ( 0 <= ImmValue && ImmValue <= 65535) {
333 // for 0 = j = 65535.
334 // li d,j => ori d,$zero,j
335 tmpInst->setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
336 tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
337 tmpInst->addOperand(
338 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
339 tmpInst->addOperand(MCOperand::CreateImm(ImmValue));
340 Instructions.push_back(tmpInst);
341 } else if ( ImmValue < 0 && ImmValue >= -32768) {
342 // for -32768 = j < 0.
343 // li d,j => addiu d,$zero,j
344 tmpInst->setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
345 tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
346 tmpInst->addOperand(
347 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
348 tmpInst->addOperand(MCOperand::CreateImm(ImmValue));
349 Instructions.push_back(tmpInst);
350 } else {
351 // for any other value of j that is representable as a 32-bit integer.
352 // li d,j => lui d,hi16(j)
353 // ori d,d,lo16(j)
354 tmpInst->setOpcode(isMips64() ? Mips::LUi64 : Mips::LUi);
355 tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
356 tmpInst->addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
357 Instructions.push_back(tmpInst);
358 tmpInst = new MCInst();
359 tmpInst->setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
360 tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
361 tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg()));
362 tmpInst->addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
363 tmpInst->setLoc(IDLoc);
364 Instructions.push_back(tmpInst);
365 }
366}
Rafael Espindolafddf8042012-01-11 03:56:41 +0000367bool MipsAsmParser::
368MatchAndEmitInstruction(SMLoc IDLoc,
369 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
370 MCStreamer &Out) {
Jack Carterec65be82012-09-05 23:34:03 +0000371 MCInst Inst;
Jack Carterec65be82012-09-05 23:34:03 +0000372 unsigned Kind;
Chad Rosier22685872012-10-01 23:45:51 +0000373 unsigned ErrorInfo;
374 SmallVector<std::pair< unsigned, std::string >, 4> MapAndConstraints;
375 unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst,
376 MapAndConstraints, ErrorInfo,
377 /*matchingInlineAsm*/ false);
Jack Carterec65be82012-09-05 23:34:03 +0000378
379 switch (MatchResult) {
380 default: break;
381 case Match_Success: {
Jack Carter9d577c82012-10-04 04:03:53 +0000382 if (needsExpansion(Inst)) {
383 SmallVector<MCInst*, 4> Instructions;
384 expandInstruction(Inst, IDLoc, Instructions);
385 for(unsigned i =0; i < Instructions.size(); i++){
386 Inst = *(Instructions[i]);
387 Out.EmitInstruction(Inst);
388 }
389 } else {
390 Inst.setLoc(IDLoc);
391 Out.EmitInstruction(Inst);
392 }
Jack Carterec65be82012-09-05 23:34:03 +0000393 return false;
394 }
395 case Match_MissingFeature:
396 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
397 return true;
398 case Match_InvalidOperand: {
399 SMLoc ErrorLoc = IDLoc;
400 if (ErrorInfo != ~0U) {
401 if (ErrorInfo >= Operands.size())
402 return Error(IDLoc, "too few operands for instruction");
403
404 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
405 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
406 }
407
408 return Error(ErrorLoc, "invalid operand for instruction");
409 }
410 case Match_MnemonicFail:
411 return Error(IDLoc, "invalid instruction");
412 }
Rafael Espindolafddf8042012-01-11 03:56:41 +0000413 return true;
414}
415
Jack Carterec65be82012-09-05 23:34:03 +0000416int MipsAsmParser::matchRegisterName(StringRef Name) {
417
418 int CC = StringSwitch<unsigned>(Name)
419 .Case("zero", Mips::ZERO)
420 .Case("a0", Mips::A0)
421 .Case("a1", Mips::A1)
422 .Case("a2", Mips::A2)
423 .Case("a3", Mips::A3)
424 .Case("v0", Mips::V0)
425 .Case("v1", Mips::V1)
426 .Case("s0", Mips::S0)
427 .Case("s1", Mips::S1)
428 .Case("s2", Mips::S2)
429 .Case("s3", Mips::S3)
430 .Case("s4", Mips::S4)
431 .Case("s5", Mips::S5)
432 .Case("s6", Mips::S6)
433 .Case("s7", Mips::S7)
434 .Case("k0", Mips::K0)
435 .Case("k1", Mips::K1)
436 .Case("sp", Mips::SP)
437 .Case("fp", Mips::FP)
438 .Case("gp", Mips::GP)
439 .Case("ra", Mips::RA)
440 .Case("t0", Mips::T0)
441 .Case("t1", Mips::T1)
442 .Case("t2", Mips::T2)
443 .Case("t3", Mips::T3)
444 .Case("t4", Mips::T4)
445 .Case("t5", Mips::T5)
446 .Case("t6", Mips::T6)
447 .Case("t7", Mips::T7)
448 .Case("t8", Mips::T8)
449 .Case("t9", Mips::T9)
450 .Case("at", Mips::AT)
451 .Case("fcc0", Mips::FCC0)
452 .Default(-1);
453
454 if (CC != -1) {
Jack Carter9d577c82012-10-04 04:03:53 +0000455 // 64 bit register in Mips are following 32 bit definitions.
Jack Carterec65be82012-09-05 23:34:03 +0000456 if (isMips64())
457 CC++;
458 return CC;
459 }
460
Jack Carterf740d6e2012-09-07 00:23:42 +0000461 if (Name[0] == 'f') {
462 StringRef NumString = Name.substr(1);
463 unsigned IntVal;
464 if( NumString.getAsInteger(10, IntVal))
Jack Carter9d577c82012-10-04 04:03:53 +0000465 return -1; // not integer
Jack Carterf740d6e2012-09-07 00:23:42 +0000466 if (IntVal > 31)
467 return -1;
468
469 FpFormatTy Format = getFpFormat();
470
471 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
472 return getReg(Mips::FGR32RegClassID, IntVal);
473 if (Format == FP_FORMAT_D) {
474 if(isFP64()) {
475 return getReg(Mips::FGR64RegClassID, IntVal);
476 }
Jack Carter9d577c82012-10-04 04:03:53 +0000477 // only even numbers available as register pairs
Jack Carterf740d6e2012-09-07 00:23:42 +0000478 if (( IntVal > 31) || (IntVal%2 != 0))
479 return -1;
480 return getReg(Mips::AFGR64RegClassID, IntVal/2);
481 }
482 }
483
Jack Carterec65be82012-09-05 23:34:03 +0000484 return -1;
485}
Jack Carterf740d6e2012-09-07 00:23:42 +0000486void MipsAsmParser::setDefaultFpFormat() {
487
488 if (isMips64() || isFP64())
489 FpFormat = FP_FORMAT_D;
490 else
491 FpFormat = FP_FORMAT_S;
492}
493
494bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
495
496 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
497 .Case("ldxc1", true)
498 .Case("ldc1", true)
499 .Case("sdxc1", true)
500 .Case("sdc1", true)
501 .Default(false);
502
503 return IsDouble;
504}
505void MipsAsmParser::setFpFormat(StringRef Format) {
506
507 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
508 .Case(".s", FP_FORMAT_S)
509 .Case(".d", FP_FORMAT_D)
510 .Case(".l", FP_FORMAT_L)
511 .Case(".w", FP_FORMAT_W)
512 .Default(FP_FORMAT_NONE);
513}
Jack Carterec65be82012-09-05 23:34:03 +0000514
Jack Carter30116cd2012-10-04 02:29:46 +0000515bool MipsAssemblerOptions::setATReg(unsigned Reg) {
516 if (Reg > 31)
517 return false;
518
519 aTReg = Reg;
520 return true;
521}
522
523unsigned MipsAsmParser::getATReg() {
524 unsigned Reg = Options->getATRegNum();
525 if (isMips64())
526 return getReg(Mips::CPU64RegsRegClassID,Reg);
527 else
528 return getReg(Mips::CPURegsRegClassID,Reg);
529}
530
531unsigned MipsAsmParser::getReg(int RC,int RegNo) {
Jack Carterec65be82012-09-05 23:34:03 +0000532 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
533}
534
Jack Carter30116cd2012-10-04 02:29:46 +0000535int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
Jack Carterec65be82012-09-05 23:34:03 +0000536
537 if (Mnemonic.lower() == "rdhwr") {
Jack Carter9d577c82012-10-04 04:03:53 +0000538 // at the moment only hwreg29 is supported
Jack Carterec65be82012-09-05 23:34:03 +0000539 if (RegNum != 29)
540 return -1;
541 return Mips::HWR29;
542 }
543
544 if (RegNum > 31)
545 return -1;
546
Jack Carter30116cd2012-10-04 02:29:46 +0000547 return getReg(Mips::CPURegsRegClassID, RegNum);
Jack Carterec65be82012-09-05 23:34:03 +0000548}
549
550int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
551 const AsmToken &Tok = Parser.getTok();
552 int RegNum = -1;
553
554 if (Tok.is(AsmToken::Identifier)) {
555 std::string lowerCase = Tok.getString().lower();
556 RegNum = matchRegisterName(lowerCase);
557 } else if (Tok.is(AsmToken::Integer))
Jack Carter9d577c82012-10-04 04:03:53 +0000558 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carter6b96c3f2012-09-06 20:00:02 +0000559 Mnemonic.lower());
Jack Carterf740d6e2012-09-07 00:23:42 +0000560 else
561 return RegNum; //error
Jack Carter9d577c82012-10-04 04:03:53 +0000562 // 64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
Jack Carterf740d6e2012-09-07 00:23:42 +0000563 if (isMips64() && RegNum == Mips::ZERO_64) {
564 if (Mnemonic.find("ddiv") != StringRef::npos)
565 RegNum = Mips::ZERO;
566 }
Jack Carterec65be82012-09-05 23:34:03 +0000567 return RegNum;
568}
569
Rafael Espindolafddf8042012-01-11 03:56:41 +0000570bool MipsAsmParser::
Jack Carterec65be82012-09-05 23:34:03 +0000571 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
572 StringRef Mnemonic){
573
574 SMLoc S = Parser.getTok().getLoc();
575 int RegNo = -1;
Jack Carterf740d6e2012-09-07 00:23:42 +0000576
Jack Carter9d577c82012-10-04 04:03:53 +0000577 // FIXME: we should make a more generic method for CCR
Jack Carterf740d6e2012-09-07 00:23:42 +0000578 if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
579 && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
Jack Carter9d577c82012-10-04 04:03:53 +0000580 RegNo = Parser.getTok().getIntVal(); // get the int value
581 // at the moment only fcc0 is supported
Jack Carterf740d6e2012-09-07 00:23:42 +0000582 if (RegNo == 0)
583 RegNo = Mips::FCC0;
584 } else
585 RegNo = tryParseRegister(Mnemonic);
Jack Carterec65be82012-09-05 23:34:03 +0000586 if (RegNo == -1)
587 return true;
588
589 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterf740d6e2012-09-07 00:23:42 +0000590 Parser.getTok().getLoc()));
Jack Carterec65be82012-09-05 23:34:03 +0000591 Parser.Lex(); // Eat register token.
592 return false;
593}
594
595bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
596 StringRef Mnemonic) {
Jack Carter9d577c82012-10-04 04:03:53 +0000597 // Check if the current operand has a custom associated parser, if so, try to
598 // custom parse the operand, or fallback to the general approach.
Jack Carterec65be82012-09-05 23:34:03 +0000599 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
600 if (ResTy == MatchOperand_Success)
601 return false;
602 // If there wasn't a custom match, try the generic matcher below. Otherwise,
603 // there was a match, but an error occurred, in which case, just return that
604 // the operand parsing failed.
605 if (ResTy == MatchOperand_ParseFail)
606 return true;
607
608 switch (getLexer().getKind()) {
609 default:
610 Error(Parser.getTok().getLoc(), "unexpected token in operand");
611 return true;
612 case AsmToken::Dollar: {
Jack Carter9d577c82012-10-04 04:03:53 +0000613 // parse register
Jack Carterec65be82012-09-05 23:34:03 +0000614 SMLoc S = Parser.getTok().getLoc();
615 Parser.Lex(); // Eat dollar token.
Jack Carter9d577c82012-10-04 04:03:53 +0000616 // parse register operand
617 if (!tryParseRegisterOperand(Operands, Mnemonic)) {
Jack Carterec65be82012-09-05 23:34:03 +0000618 if (getLexer().is(AsmToken::LParen)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000619 // check if it is indexed addressing operand
Jack Carterec65be82012-09-05 23:34:03 +0000620 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carter9d577c82012-10-04 04:03:53 +0000621 Parser.Lex(); // eat parenthesis
Jack Carterec65be82012-09-05 23:34:03 +0000622 if (getLexer().isNot(AsmToken::Dollar))
623 return true;
624
Jack Carter9d577c82012-10-04 04:03:53 +0000625 Parser.Lex(); // eat dollar
626 if (tryParseRegisterOperand(Operands, Mnemonic))
Jack Carterec65be82012-09-05 23:34:03 +0000627 return true;
628
629 if (!getLexer().is(AsmToken::RParen))
630 return true;
631
632 S = Parser.getTok().getLoc();
633 Operands.push_back(MipsOperand::CreateToken(")", S));
634 Parser.Lex();
635 }
636 return false;
637 }
Jack Carter9d577c82012-10-04 04:03:53 +0000638 // maybe it is a symbol reference
Jack Carterec65be82012-09-05 23:34:03 +0000639 StringRef Identifier;
640 if (Parser.ParseIdentifier(Identifier))
641 return true;
642
Jack Carter6b96c3f2012-09-06 20:00:02 +0000643 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000644
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000645 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterec65be82012-09-05 23:34:03 +0000646
647 // Otherwise create a symbol ref.
Jack Carter6b96c3f2012-09-06 20:00:02 +0000648 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterec65be82012-09-05 23:34:03 +0000649 getContext());
650
651 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
652 return false;
653 }
654 case AsmToken::Identifier:
655 case AsmToken::LParen:
656 case AsmToken::Minus:
657 case AsmToken::Plus:
658 case AsmToken::Integer:
659 case AsmToken::String: {
660 // quoted label names
661 const MCExpr *IdVal;
662 SMLoc S = Parser.getTok().getLoc();
663 if (getParser().ParseExpression(IdVal))
664 return true;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000665 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000666 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
667 return false;
668 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000669 case AsmToken::Percent: {
Jack Carter9d577c82012-10-04 04:03:53 +0000670 // it is a symbol reference or constant expression
Jack Carter6b96c3f2012-09-06 20:00:02 +0000671 const MCExpr *IdVal;
Jack Carter9d577c82012-10-04 04:03:53 +0000672 SMLoc S = Parser.getTok().getLoc(); // start location of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000673 if (parseRelocOperand(IdVal))
674 return true;
675
676 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
677
678 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
679 return false;
Jack Carter30116cd2012-10-04 02:29:46 +0000680 } // case AsmToken::Percent
681 } // switch(getLexer().getKind())
Rafael Espindolafddf8042012-01-11 03:56:41 +0000682 return true;
683}
684
Jack Carter6b96c3f2012-09-06 20:00:02 +0000685bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
686
Jack Carter30116cd2012-10-04 02:29:46 +0000687 Parser.Lex(); // eat % token
Jack Carter9d577c82012-10-04 04:03:53 +0000688 const AsmToken &Tok = Parser.getTok(); // get next token, operation
Jack Carter6b96c3f2012-09-06 20:00:02 +0000689 if (Tok.isNot(AsmToken::Identifier))
690 return true;
691
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000692 std::string Str = Tok.getIdentifier().str();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000693
Jack Carter9d577c82012-10-04 04:03:53 +0000694 Parser.Lex(); // eat identifier
Jack Carter30116cd2012-10-04 02:29:46 +0000695 // now make expression from the rest of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000696 const MCExpr *IdVal;
697 SMLoc EndLoc;
698
699 if (getLexer().getKind() == AsmToken::LParen) {
700 while (1) {
Jack Carter30116cd2012-10-04 02:29:46 +0000701 Parser.Lex(); // eat '(' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000702 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carter30116cd2012-10-04 02:29:46 +0000703 Parser.Lex(); // eat % token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000704 const AsmToken &nextTok = Parser.getTok();
705 if (nextTok.isNot(AsmToken::Identifier))
706 return true;
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000707 Str += "(%";
708 Str += nextTok.getIdentifier();
Jack Carter30116cd2012-10-04 02:29:46 +0000709 Parser.Lex(); // eat identifier
Jack Carter6b96c3f2012-09-06 20:00:02 +0000710 if (getLexer().getKind() != AsmToken::LParen)
711 return true;
712 } else
713 break;
714 }
715 if (getParser().ParseParenExpression(IdVal,EndLoc))
716 return true;
717
718 while (getLexer().getKind() == AsmToken::RParen)
Jack Carter30116cd2012-10-04 02:29:46 +0000719 Parser.Lex(); // eat ')' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000720
721 } else
Jack Carter30116cd2012-10-04 02:29:46 +0000722 return true; // parenthesis must follow reloc operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000723
Jack Carter30116cd2012-10-04 02:29:46 +0000724 // Check the type of the expression
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000725 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000726 // it's a constant, evaluate lo or hi value
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000727 int Val = MCE->getValue();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000728 if (Str == "lo") {
729 Val = Val & 0xffff;
730 } else if (Str == "hi") {
731 Val = (Val & 0xffff0000) >> 16;
732 }
733 Res = MCConstantExpr::Create(Val, getContext());
734 return false;
735 }
736
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000737 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter30116cd2012-10-04 02:29:46 +0000738 // it's a symbol, create symbolic expression from symbol
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000739 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000740 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
741 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
742 return false;
743 }
744 return true;
745}
746
Jack Carterec65be82012-09-05 23:34:03 +0000747bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
748 SMLoc &EndLoc) {
749
750 StartLoc = Parser.getTok().getLoc();
751 RegNo = tryParseRegister("");
752 EndLoc = Parser.getTok().getLoc();
753 return (RegNo == (unsigned)-1);
754}
755
Jack Carter6b96c3f2012-09-06 20:00:02 +0000756bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
757
758 SMLoc S;
759
760 switch(getLexer().getKind()) {
761 default:
762 return true;
763 case AsmToken::Integer:
764 case AsmToken::Minus:
765 case AsmToken::Plus:
766 return (getParser().ParseExpression(Res));
Jack Carterf740d6e2012-09-07 00:23:42 +0000767 case AsmToken::Percent:
Jack Carter6b96c3f2012-09-06 20:00:02 +0000768 return parseRelocOperand(Res);
Jack Carter6b96c3f2012-09-06 20:00:02 +0000769 case AsmToken::LParen:
Jack Carter30116cd2012-10-04 02:29:46 +0000770 return false; // it's probably assuming 0
Jack Carter6b96c3f2012-09-06 20:00:02 +0000771 }
772 return true;
773}
774
Jack Carterec65be82012-09-05 23:34:03 +0000775MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
776 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000777
778 const MCExpr *IdVal = 0;
779 SMLoc S;
Jack Carter30116cd2012-10-04 02:29:46 +0000780 // first operand is the offset
Jack Carter6b96c3f2012-09-06 20:00:02 +0000781 S = Parser.getTok().getLoc();
782
783 if (parseMemOffset(IdVal))
784 return MatchOperand_ParseFail;
785
Jack Carter30116cd2012-10-04 02:29:46 +0000786 const AsmToken &Tok = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000787 if (Tok.isNot(AsmToken::LParen)) {
788 Error(Parser.getTok().getLoc(), "'(' expected");
789 return MatchOperand_ParseFail;
790 }
791
792 Parser.Lex(); // Eat '(' token.
793
794 const AsmToken &Tok1 = Parser.getTok(); //get next token
795 if (Tok1.is(AsmToken::Dollar)) {
796 Parser.Lex(); // Eat '$' token.
797 if (tryParseRegisterOperand(Operands,"")) {
798 Error(Parser.getTok().getLoc(), "unexpected token in operand");
799 return MatchOperand_ParseFail;
800 }
801
802 } else {
Jack Carter30116cd2012-10-04 02:29:46 +0000803 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carter6b96c3f2012-09-06 20:00:02 +0000804 return MatchOperand_ParseFail;
805 }
806
Jack Carter30116cd2012-10-04 02:29:46 +0000807 const AsmToken &Tok2 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000808 if (Tok2.isNot(AsmToken::RParen)) {
809 Error(Parser.getTok().getLoc(), "')' expected");
810 return MatchOperand_ParseFail;
811 }
812
813 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
814
815 Parser.Lex(); // Eat ')' token.
816
817 if (IdVal == 0)
818 IdVal = MCConstantExpr::Create(0, getContext());
819
Jack Carter30116cd2012-10-04 02:29:46 +0000820 // now replace register operand with the mem operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000821 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
822 int RegNo = op->getReg();
Jack Carter30116cd2012-10-04 02:29:46 +0000823 // remove register from operands
Jack Carter6b96c3f2012-09-06 20:00:02 +0000824 Operands.pop_back();
Jack Carter30116cd2012-10-04 02:29:46 +0000825 // and add memory operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000826 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
827 delete op;
Jack Carterec65be82012-09-05 23:34:03 +0000828 return MatchOperand_Success;
829}
830
Jack Carter6b96c3f2012-09-06 20:00:02 +0000831MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
832
833 MCSymbolRefExpr::VariantKind VK
834 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
835 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
836 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
837 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
838 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
839 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
840 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
841 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
842 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
843 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
844 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
845 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
846 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
847 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
848 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
849 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
850 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
851 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
852 .Default(MCSymbolRefExpr::VK_None);
853
854 return VK;
855}
856
Benjamin Kramer1ac45872012-09-10 11:52:14 +0000857static int ConvertCcString(StringRef CondString) {
Jack Carterf740d6e2012-09-07 00:23:42 +0000858 int CC = StringSwitch<unsigned>(CondString)
859 .Case(".f", 0)
860 .Case(".un", 1)
861 .Case(".eq", 2)
862 .Case(".ueq", 3)
863 .Case(".olt", 4)
864 .Case(".ult", 5)
865 .Case(".ole", 6)
866 .Case(".ule", 7)
867 .Case(".sf", 8)
868 .Case(".ngle", 9)
869 .Case(".seq", 10)
870 .Case(".ngl", 11)
871 .Case(".lt", 12)
872 .Case(".nge", 13)
873 .Case(".le", 14)
874 .Case(".ngt", 15)
875 .Default(-1);
876
877 return CC;
878}
879
880bool MipsAsmParser::
881parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter30116cd2012-10-04 02:29:46 +0000882 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
883 // split the format
Jack Carterf740d6e2012-09-07 00:23:42 +0000884 size_t Start = Name.find('.'), Next = Name.rfind('.');
885 StringRef Format1 = Name.slice(Start, Next);
Jack Carter30116cd2012-10-04 02:29:46 +0000886 // and add the first format to the operands
Jack Carterf740d6e2012-09-07 00:23:42 +0000887 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carter30116cd2012-10-04 02:29:46 +0000888 // now for the second format
Jack Carterf740d6e2012-09-07 00:23:42 +0000889 StringRef Format2 = Name.slice(Next, StringRef::npos);
890 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
891
Jack Carter30116cd2012-10-04 02:29:46 +0000892 // set the format for the first register
Jack Carterf740d6e2012-09-07 00:23:42 +0000893 setFpFormat(Format1);
894
895 // Read the remaining operands.
896 if (getLexer().isNot(AsmToken::EndOfStatement)) {
897 // Read the first operand.
898 if (ParseOperand(Operands, Name)) {
899 SMLoc Loc = getLexer().getLoc();
900 Parser.EatToEndOfStatement();
901 return Error(Loc, "unexpected token in argument list");
902 }
903
904 if (getLexer().isNot(AsmToken::Comma)) {
905 SMLoc Loc = getLexer().getLoc();
906 Parser.EatToEndOfStatement();
907 return Error(Loc, "unexpected token in argument list");
908
909 }
910 Parser.Lex(); // Eat the comma.
911
912 //set the format for the first register
913 setFpFormat(Format2);
914
915 // Parse and remember the operand.
916 if (ParseOperand(Operands, Name)) {
917 SMLoc Loc = getLexer().getLoc();
918 Parser.EatToEndOfStatement();
919 return Error(Loc, "unexpected token in argument list");
920 }
921 }
922
923 if (getLexer().isNot(AsmToken::EndOfStatement)) {
924 SMLoc Loc = getLexer().getLoc();
925 Parser.EatToEndOfStatement();
926 return Error(Loc, "unexpected token in argument list");
927 }
928
929 Parser.Lex(); // Consume the EndOfStatement
930 return false;
931}
932
Rafael Espindolafddf8042012-01-11 03:56:41 +0000933bool MipsAsmParser::
934ParseInstruction(StringRef Name, SMLoc NameLoc,
935 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter30116cd2012-10-04 02:29:46 +0000936 // floating point instructions: should register be treated as double?
Jack Carterf740d6e2012-09-07 00:23:42 +0000937 if (requestsDoubleOperand(Name)) {
938 setFpFormat(FP_FORMAT_D);
Jack Carterec65be82012-09-05 23:34:03 +0000939 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterf740d6e2012-09-07 00:23:42 +0000940 }
941 else {
942 setDefaultFpFormat();
943 // Create the leading tokens for the mnemonic, split by '.' characters.
944 size_t Start = 0, Next = Name.find('.');
945 StringRef Mnemonic = Name.slice(Start, Next);
946
947 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
948
949 if (Next != StringRef::npos) {
Jack Carter30116cd2012-10-04 02:29:46 +0000950 // there is a format token in mnemonic
951 // StringRef Rest = Name.slice(Next, StringRef::npos);
Jack Carterf740d6e2012-09-07 00:23:42 +0000952 size_t Dot = Name.find('.', Next+1);
953 StringRef Format = Name.slice(Next, Dot);
954 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
955 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
956 else {
957 if (Name.startswith("c.")){
958 // floating point compare, add '.' and immediate represent for cc
959 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
960 int Cc = ConvertCcString(Format);
961 if (Cc == -1) {
962 return Error(NameLoc, "Invalid conditional code");
963 }
964 SMLoc E = SMLoc::getFromPointer(
965 Parser.getTok().getLoc().getPointer() -1 );
966 Operands.push_back(MipsOperand::CreateImm(
967 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
968 } else {
Jack Carter30116cd2012-10-04 02:29:46 +0000969 // trunc, ceil, floor ...
Jack Carterf740d6e2012-09-07 00:23:42 +0000970 return parseMathOperation(Name, NameLoc, Operands);
971 }
972
Jack Carter30116cd2012-10-04 02:29:46 +0000973 // the rest is a format
Jack Carterf740d6e2012-09-07 00:23:42 +0000974 Format = Name.slice(Dot, StringRef::npos);
975 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
976 }
977
978 setFpFormat(Format);
979 }
980 }
Jack Carterec65be82012-09-05 23:34:03 +0000981
982 // Read the remaining operands.
983 if (getLexer().isNot(AsmToken::EndOfStatement)) {
984 // Read the first operand.
985 if (ParseOperand(Operands, Name)) {
986 SMLoc Loc = getLexer().getLoc();
987 Parser.EatToEndOfStatement();
988 return Error(Loc, "unexpected token in argument list");
989 }
990
991 while (getLexer().is(AsmToken::Comma) ) {
992 Parser.Lex(); // Eat the comma.
993
994 // Parse and remember the operand.
995 if (ParseOperand(Operands, Name)) {
996 SMLoc Loc = getLexer().getLoc();
997 Parser.EatToEndOfStatement();
998 return Error(Loc, "unexpected token in argument list");
999 }
1000 }
1001 }
1002
1003 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1004 SMLoc Loc = getLexer().getLoc();
1005 Parser.EatToEndOfStatement();
1006 return Error(Loc, "unexpected token in argument list");
1007 }
1008
1009 Parser.Lex(); // Consume the EndOfStatement
1010 return false;
Rafael Espindolafddf8042012-01-11 03:56:41 +00001011}
1012
Jack Carter30116cd2012-10-04 02:29:46 +00001013bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1014 SMLoc Loc = getLexer().getLoc();
1015 Parser.EatToEndOfStatement();
1016 return Error(Loc, ErrorMsg);
1017}
1018
1019bool MipsAsmParser::parseSetNoAtDirective() {
1020 // line should look like:
1021 // .set noat
1022 // set at reg to 0
1023 Options->setATReg(0);
1024 // eat noat
1025 Parser.Lex();
1026 // if this is not the end of the statement, report error
1027 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1028 reportParseError("unexpected token in statement");
1029 return false;
1030 }
1031 Parser.Lex(); // Consume the EndOfStatement
1032 return false;
1033}
1034bool MipsAsmParser::parseSetAtDirective() {
1035 // line can be
1036 // .set at - defaults to $1
1037 // or .set at=$reg
1038 getParser().Lex();
1039 if (getLexer().is(AsmToken::EndOfStatement)) {
1040 Options->setATReg(1);
1041 Parser.Lex(); // Consume the EndOfStatement
1042 return false;
1043 } else if (getLexer().is(AsmToken::Equal)) {
1044 getParser().Lex(); //eat '='
1045 if (getLexer().isNot(AsmToken::Dollar)) {
1046 reportParseError("unexpected token in statement");
1047 return false;
1048 }
1049 Parser.Lex(); // eat '$'
1050 if (getLexer().isNot(AsmToken::Integer)) {
1051 reportParseError("unexpected token in statement");
1052 return false;
1053 }
1054 const AsmToken &Reg = Parser.getTok();
1055 if (!Options->setATReg(Reg.getIntVal())) {
1056 reportParseError("unexpected token in statement");
1057 return false;
1058 }
1059 getParser().Lex(); //eat reg
1060
1061 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1062 reportParseError("unexpected token in statement");
1063 return false;
1064 }
1065 Parser.Lex(); // Consume the EndOfStatement
1066 return false;
1067 } else {
1068 reportParseError("unexpected token in statement");
1069 return false;
1070 }
1071}
1072
1073bool MipsAsmParser::parseSetReorderDirective() {
1074 Parser.Lex();
1075 // if this is not the end of the statement, report error
1076 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1077 reportParseError("unexpected token in statement");
1078 return false;
1079 }
1080 Options->setReorder();
1081 Parser.Lex(); // Consume the EndOfStatement
1082 return false;
1083}
1084
1085bool MipsAsmParser::parseSetNoReorderDirective() {
1086 Parser.Lex();
1087 // if this is not the end of the statement, report error
1088 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1089 reportParseError("unexpected token in statement");
1090 return false;
1091 }
1092 Options->setNoreorder();
1093 Parser.Lex(); // Consume the EndOfStatement
1094 return false;
1095}
1096
1097bool MipsAsmParser::parseSetMacroDirective() {
1098 Parser.Lex();
1099 // if this is not the end of the statement, report error
1100 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1101 reportParseError("unexpected token in statement");
1102 return false;
1103 }
1104 Options->setMacro();
1105 Parser.Lex(); // Consume the EndOfStatement
1106 return false;
1107}
1108
1109bool MipsAsmParser::parseSetNoMacroDirective() {
1110 Parser.Lex();
1111 // if this is not the end of the statement, report error
1112 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1113 reportParseError("`noreorder' must be set before `nomacro'");
1114 return false;
1115 }
1116 if (Options->isReorder()) {
1117 reportParseError("`noreorder' must be set before `nomacro'");
1118 return false;
1119 }
1120 Options->setNomacro();
1121 Parser.Lex(); // Consume the EndOfStatement
1122 return false;
1123}
1124bool MipsAsmParser::parseDirectiveSet() {
1125
1126 // get next token
1127 const AsmToken &Tok = Parser.getTok();
1128
1129 if (Tok.getString() == "noat") {
1130 return parseSetNoAtDirective();
1131 } else if (Tok.getString() == "at") {
1132 return parseSetAtDirective();
1133 } else if (Tok.getString() == "reorder") {
1134 return parseSetReorderDirective();
1135 } else if (Tok.getString() == "noreorder") {
1136 return parseSetNoReorderDirective();
1137 } else if (Tok.getString() == "macro") {
1138 return parseSetMacroDirective();
1139 } else if (Tok.getString() == "nomacro") {
1140 return parseSetNoMacroDirective();
1141 } else if (Tok.getString() == "nomips16") {
1142 // ignore this directive for now
1143 Parser.EatToEndOfStatement();
1144 return false;
1145 } else if (Tok.getString() == "nomicromips") {
1146 // ignore this directive for now
1147 Parser.EatToEndOfStatement();
1148 return false;
1149 }
1150 return true;
1151}
1152
1153bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carteracbea452012-09-07 00:48:02 +00001154
1155 if (DirectiveID.getString() == ".ent") {
Jack Carter30116cd2012-10-04 02:29:46 +00001156 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001157 Parser.Lex();
1158 return false;
1159 }
1160
1161 if (DirectiveID.getString() == ".end") {
Jack Carter30116cd2012-10-04 02:29:46 +00001162 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001163 Parser.Lex();
1164 return false;
1165 }
1166
1167 if (DirectiveID.getString() == ".frame") {
Jack Carter30116cd2012-10-04 02:29:46 +00001168 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001169 Parser.EatToEndOfStatement();
1170 return false;
1171 }
1172
1173 if (DirectiveID.getString() == ".set") {
Jack Carter30116cd2012-10-04 02:29:46 +00001174 return parseDirectiveSet();
Jack Carteracbea452012-09-07 00:48:02 +00001175 }
1176
1177 if (DirectiveID.getString() == ".fmask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001178 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001179 Parser.EatToEndOfStatement();
1180 return false;
1181 }
1182
1183 if (DirectiveID.getString() == ".mask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001184 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001185 Parser.EatToEndOfStatement();
1186 return false;
1187 }
1188
1189 if (DirectiveID.getString() == ".gpword") {
Jack Carter30116cd2012-10-04 02:29:46 +00001190 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001191 Parser.EatToEndOfStatement();
1192 return false;
1193 }
1194
Rafael Espindolafddf8042012-01-11 03:56:41 +00001195 return true;
1196}
1197
Rafael Espindolafddf8042012-01-11 03:56:41 +00001198extern "C" void LLVMInitializeMipsAsmParser() {
1199 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1200 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1201 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1202 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1203}
Jack Carterec65be82012-09-05 23:34:03 +00001204
1205#define GET_REGISTER_MATCHER
1206#define GET_MATCHER_IMPLEMENTATION
1207#include "MipsGenAsmMatcher.inc"