]> git.proxmox.com Git - rustc.git/blob - src/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
Imported Upstream version 0.7
[rustc.git] / src / llvm / lib / Target / Mips / AsmParser / MipsAsmParser.cpp
1 //===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
2 //
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"
11 #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/MCParser/MCAsmLexer.h"
17 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
18 #include "llvm/MC/MCStreamer.h"
19 #include "llvm/MC/MCSubtargetInfo.h"
20 #include "llvm/MC/MCSymbol.h"
21 #include "llvm/MC/MCTargetAsmParser.h"
22 #include "llvm/Support/TargetRegistry.h"
23
24 using namespace llvm;
25
26 namespace {
27 class MipsAssemblerOptions {
28 public:
29 MipsAssemblerOptions():
30 aTReg(1), reorder(true), macro(true) {
31 }
32
33 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
44 private:
45 unsigned aTReg;
46 bool reorder;
47 bool macro;
48 };
49 }
50
51 namespace {
52 class MipsAsmParser : public MCTargetAsmParser {
53
54 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
62 MCSubtargetInfo &STI;
63 MCAsmParser &Parser;
64 MipsAssemblerOptions Options;
65
66
67 #define GET_ASSEMBLER_HEADER
68 #include "MipsGenAsmMatcher.inc"
69
70 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
71 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
72 MCStreamer &Out, unsigned &ErrorInfo,
73 bool MatchingInlineAsm);
74
75 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
76
77 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
78 SMLoc NameLoc,
79 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
80
81 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
82 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
83
84 bool ParseDirective(AsmToken DirectiveID);
85
86 MipsAsmParser::OperandMatchResultTy
87 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
88
89 MipsAsmParser::OperandMatchResultTy
90 parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
91
92 MipsAsmParser::OperandMatchResultTy
93 parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
94
95 MipsAsmParser::OperandMatchResultTy
96 parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
97
98 MipsAsmParser::OperandMatchResultTy
99 parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
100
101 MipsAsmParser::OperandMatchResultTy
102 parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
103
104 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
105 StringRef Mnemonic);
106
107 int tryParseRegister(bool is64BitReg);
108
109 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
110 bool is64BitReg);
111
112 bool needsExpansion(MCInst &Inst);
113
114 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
115 SmallVectorImpl<MCInst> &Instructions);
116 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
117 SmallVectorImpl<MCInst> &Instructions);
118 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
119 SmallVectorImpl<MCInst> &Instructions);
120 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
121 SmallVectorImpl<MCInst> &Instructions);
122 bool reportParseError(StringRef ErrorMsg);
123
124 bool parseMemOffset(const MCExpr *&Res);
125 bool parseRelocOperand(const MCExpr *&Res);
126
127 bool parseDirectiveSet();
128
129 bool parseSetAtDirective();
130 bool parseSetNoAtDirective();
131 bool parseSetMacroDirective();
132 bool parseSetNoMacroDirective();
133 bool parseSetReorderDirective();
134 bool parseSetNoReorderDirective();
135
136 bool parseDirectiveWord(unsigned Size, SMLoc L);
137
138 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
139
140 bool isMips64() const {
141 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
142 }
143
144 bool isFP64() const {
145 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
146 }
147
148 int matchRegisterName(StringRef Symbol, bool is64BitReg);
149
150 int matchCPURegisterName(StringRef Symbol);
151
152 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
153
154 void setFpFormat(FpFormatTy Format) {
155 FpFormat = Format;
156 }
157
158 void setDefaultFpFormat();
159
160 void setFpFormat(StringRef Format);
161
162 FpFormatTy getFpFormat() {return FpFormat;}
163
164 bool requestsDoubleOperand(StringRef Mnemonic);
165
166 unsigned getReg(int RC,int RegNo);
167
168 int getATReg();
169 public:
170 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
171 : MCTargetAsmParser(), STI(sti), Parser(parser) {
172 // Initialize the set of available features.
173 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
174 }
175
176 MCAsmParser &getParser() const { return Parser; }
177 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
178
179 };
180 }
181
182 namespace {
183
184 /// MipsOperand - Instances of this class represent a parsed Mips machine
185 /// instruction.
186 class MipsOperand : public MCParsedAsmOperand {
187
188 public:
189 enum RegisterKind {
190 Kind_None,
191 Kind_CPURegs,
192 Kind_CPU64Regs,
193 Kind_HWRegs,
194 Kind_HW64Regs,
195 Kind_FGR32Regs,
196 Kind_FGR64Regs,
197 Kind_AFGR64Regs,
198 Kind_CCRRegs
199 };
200
201 private:
202 enum KindTy {
203 k_CondCode,
204 k_CoprocNum,
205 k_Immediate,
206 k_Memory,
207 k_PostIndexRegister,
208 k_Register,
209 k_Token
210 } Kind;
211
212 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
213
214 struct Token {
215 const char *Data;
216 unsigned Length;
217 };
218
219 struct RegOp {
220 unsigned RegNum;
221 RegisterKind Kind;
222 };
223
224 struct ImmOp {
225 const MCExpr *Val;
226 };
227
228 struct MemOp {
229 unsigned Base;
230 const MCExpr *Off;
231 };
232
233 union {
234 struct Token Tok;
235 struct RegOp Reg;
236 struct ImmOp Imm;
237 struct MemOp Mem;
238 };
239
240 SMLoc StartLoc, EndLoc;
241
242 public:
243 void addRegOperands(MCInst &Inst, unsigned N) const {
244 assert(N == 1 && "Invalid number of operands!");
245 Inst.addOperand(MCOperand::CreateReg(getReg()));
246 }
247
248 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
249 // Add as immediate when possible. Null MCExpr = 0.
250 if (Expr == 0)
251 Inst.addOperand(MCOperand::CreateImm(0));
252 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
253 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
254 else
255 Inst.addOperand(MCOperand::CreateExpr(Expr));
256 }
257
258 void addImmOperands(MCInst &Inst, unsigned N) const {
259 assert(N == 1 && "Invalid number of operands!");
260 const MCExpr *Expr = getImm();
261 addExpr(Inst,Expr);
262 }
263
264 void addMemOperands(MCInst &Inst, unsigned N) const {
265 assert(N == 2 && "Invalid number of operands!");
266
267 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
268
269 const MCExpr *Expr = getMemOff();
270 addExpr(Inst,Expr);
271 }
272
273 bool isReg() const { return Kind == k_Register; }
274 bool isImm() const { return Kind == k_Immediate; }
275 bool isToken() const { return Kind == k_Token; }
276 bool isMem() const { return Kind == k_Memory; }
277
278 StringRef getToken() const {
279 assert(Kind == k_Token && "Invalid access!");
280 return StringRef(Tok.Data, Tok.Length);
281 }
282
283 unsigned getReg() const {
284 assert((Kind == k_Register) && "Invalid access!");
285 return Reg.RegNum;
286 }
287
288 void setRegKind(RegisterKind RegKind) {
289 assert((Kind == k_Register) && "Invalid access!");
290 Reg.Kind = RegKind;
291 }
292
293 const MCExpr *getImm() const {
294 assert((Kind == k_Immediate) && "Invalid access!");
295 return Imm.Val;
296 }
297
298 unsigned getMemBase() const {
299 assert((Kind == k_Memory) && "Invalid access!");
300 return Mem.Base;
301 }
302
303 const MCExpr *getMemOff() const {
304 assert((Kind == k_Memory) && "Invalid access!");
305 return Mem.Off;
306 }
307
308 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
309 MipsOperand *Op = new MipsOperand(k_Token);
310 Op->Tok.Data = Str.data();
311 Op->Tok.Length = Str.size();
312 Op->StartLoc = S;
313 Op->EndLoc = S;
314 return Op;
315 }
316
317 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
318 MipsOperand *Op = new MipsOperand(k_Register);
319 Op->Reg.RegNum = RegNum;
320 Op->StartLoc = S;
321 Op->EndLoc = E;
322 return Op;
323 }
324
325 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
326 MipsOperand *Op = new MipsOperand(k_Immediate);
327 Op->Imm.Val = Val;
328 Op->StartLoc = S;
329 Op->EndLoc = E;
330 return Op;
331 }
332
333 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
334 SMLoc S, SMLoc E) {
335 MipsOperand *Op = new MipsOperand(k_Memory);
336 Op->Mem.Base = Base;
337 Op->Mem.Off = Off;
338 Op->StartLoc = S;
339 Op->EndLoc = E;
340 return Op;
341 }
342
343 bool isCPURegsAsm() const {
344 return Kind == k_Register && Reg.Kind == Kind_CPURegs;
345 }
346 void addCPURegsAsmOperands(MCInst &Inst, unsigned N) const {
347 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
348 }
349
350 bool isCPU64RegsAsm() const {
351 return Kind == k_Register && Reg.Kind == Kind_CPU64Regs;
352 }
353 void addCPU64RegsAsmOperands(MCInst &Inst, unsigned N) const {
354 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
355 }
356
357 bool isHWRegsAsm() const {
358 assert((Kind == k_Register) && "Invalid access!");
359 return Reg.Kind == Kind_HWRegs;
360 }
361 void addHWRegsAsmOperands(MCInst &Inst, unsigned N) const {
362 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
363 }
364
365 bool isHW64RegsAsm() const {
366 assert((Kind == k_Register) && "Invalid access!");
367 return Reg.Kind == Kind_HW64Regs;
368 }
369 void addHW64RegsAsmOperands(MCInst &Inst, unsigned N) const {
370 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
371 }
372
373 void addCCRAsmOperands(MCInst &Inst, unsigned N) const {
374 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
375 }
376
377 bool isCCRAsm() const {
378 assert((Kind == k_Register) && "Invalid access!");
379 return Reg.Kind == Kind_CCRRegs;
380 }
381
382 /// getStartLoc - Get the location of the first token of this operand.
383 SMLoc getStartLoc() const { return StartLoc; }
384 /// getEndLoc - Get the location of the last token of this operand.
385 SMLoc getEndLoc() const { return EndLoc; }
386
387 virtual void print(raw_ostream &OS) const {
388 llvm_unreachable("unimplemented!");
389 }
390 };
391 }
392
393 bool MipsAsmParser::needsExpansion(MCInst &Inst) {
394
395 switch(Inst.getOpcode()) {
396 case Mips::LoadImm32Reg:
397 case Mips::LoadAddr32Imm:
398 case Mips::LoadAddr32Reg:
399 return true;
400 default:
401 return false;
402 }
403 }
404
405 void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
406 SmallVectorImpl<MCInst> &Instructions){
407 switch(Inst.getOpcode()) {
408 case Mips::LoadImm32Reg:
409 return expandLoadImm(Inst, IDLoc, Instructions);
410 case Mips::LoadAddr32Imm:
411 return expandLoadAddressImm(Inst,IDLoc,Instructions);
412 case Mips::LoadAddr32Reg:
413 return expandLoadAddressReg(Inst,IDLoc,Instructions);
414 }
415 }
416
417 void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
418 SmallVectorImpl<MCInst> &Instructions){
419 MCInst tmpInst;
420 const MCOperand &ImmOp = Inst.getOperand(1);
421 assert(ImmOp.isImm() && "expected immediate operand kind");
422 const MCOperand &RegOp = Inst.getOperand(0);
423 assert(RegOp.isReg() && "expected register operand kind");
424
425 int ImmValue = ImmOp.getImm();
426 tmpInst.setLoc(IDLoc);
427 if ( 0 <= ImmValue && ImmValue <= 65535) {
428 // for 0 <= j <= 65535.
429 // li d,j => ori d,$zero,j
430 tmpInst.setOpcode(Mips::ORi);
431 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
432 tmpInst.addOperand(
433 MCOperand::CreateReg(Mips::ZERO));
434 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
435 Instructions.push_back(tmpInst);
436 } else if ( ImmValue < 0 && ImmValue >= -32768) {
437 // for -32768 <= j < 0.
438 // li d,j => addiu d,$zero,j
439 tmpInst.setOpcode(Mips::ADDiu);
440 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
441 tmpInst.addOperand(
442 MCOperand::CreateReg(Mips::ZERO));
443 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
444 Instructions.push_back(tmpInst);
445 } else {
446 // for any other value of j that is representable as a 32-bit integer.
447 // li d,j => lui d,hi16(j)
448 // ori d,d,lo16(j)
449 tmpInst.setOpcode(Mips::LUi);
450 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
451 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
452 Instructions.push_back(tmpInst);
453 tmpInst.clear();
454 tmpInst.setOpcode(Mips::ORi);
455 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
456 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
457 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
458 tmpInst.setLoc(IDLoc);
459 Instructions.push_back(tmpInst);
460 }
461 }
462
463 void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
464 SmallVectorImpl<MCInst> &Instructions){
465 MCInst tmpInst;
466 const MCOperand &ImmOp = Inst.getOperand(2);
467 assert(ImmOp.isImm() && "expected immediate operand kind");
468 const MCOperand &SrcRegOp = Inst.getOperand(1);
469 assert(SrcRegOp.isReg() && "expected register operand kind");
470 const MCOperand &DstRegOp = Inst.getOperand(0);
471 assert(DstRegOp.isReg() && "expected register operand kind");
472 int ImmValue = ImmOp.getImm();
473 if ( -32768 <= ImmValue && ImmValue <= 65535) {
474 //for -32768 <= j <= 65535.
475 //la d,j(s) => addiu d,s,j
476 tmpInst.setOpcode(Mips::ADDiu);
477 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
478 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
479 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
480 Instructions.push_back(tmpInst);
481 } else {
482 //for any other value of j that is representable as a 32-bit integer.
483 //la d,j(s) => lui d,hi16(j)
484 // ori d,d,lo16(j)
485 // addu d,d,s
486 tmpInst.setOpcode(Mips::LUi);
487 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
488 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
489 Instructions.push_back(tmpInst);
490 tmpInst.clear();
491 tmpInst.setOpcode(Mips::ORi);
492 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
493 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
494 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
495 Instructions.push_back(tmpInst);
496 tmpInst.clear();
497 tmpInst.setOpcode(Mips::ADDu);
498 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
499 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
500 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
501 Instructions.push_back(tmpInst);
502 }
503 }
504
505 void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
506 SmallVectorImpl<MCInst> &Instructions){
507 MCInst tmpInst;
508 const MCOperand &ImmOp = Inst.getOperand(1);
509 assert(ImmOp.isImm() && "expected immediate operand kind");
510 const MCOperand &RegOp = Inst.getOperand(0);
511 assert(RegOp.isReg() && "expected register operand kind");
512 int ImmValue = ImmOp.getImm();
513 if ( -32768 <= ImmValue && ImmValue <= 65535) {
514 //for -32768 <= j <= 65535.
515 //la d,j => addiu d,$zero,j
516 tmpInst.setOpcode(Mips::ADDiu);
517 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
518 tmpInst.addOperand(
519 MCOperand::CreateReg(Mips::ZERO));
520 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
521 Instructions.push_back(tmpInst);
522 } else {
523 //for any other value of j that is representable as a 32-bit integer.
524 //la d,j => lui d,hi16(j)
525 // ori d,d,lo16(j)
526 tmpInst.setOpcode(Mips::LUi);
527 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
528 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
529 Instructions.push_back(tmpInst);
530 tmpInst.clear();
531 tmpInst.setOpcode(Mips::ORi);
532 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
533 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
534 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
535 Instructions.push_back(tmpInst);
536 }
537 }
538
539 bool MipsAsmParser::
540 MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
541 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
542 MCStreamer &Out, unsigned &ErrorInfo,
543 bool MatchingInlineAsm) {
544 MCInst Inst;
545 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
546 MatchingInlineAsm);
547
548 switch (MatchResult) {
549 default: break;
550 case Match_Success: {
551 if (needsExpansion(Inst)) {
552 SmallVector<MCInst, 4> Instructions;
553 expandInstruction(Inst, IDLoc, Instructions);
554 for(unsigned i =0; i < Instructions.size(); i++){
555 Out.EmitInstruction(Instructions[i]);
556 }
557 } else {
558 Inst.setLoc(IDLoc);
559 Out.EmitInstruction(Inst);
560 }
561 return false;
562 }
563 case Match_MissingFeature:
564 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
565 return true;
566 case Match_InvalidOperand: {
567 SMLoc ErrorLoc = IDLoc;
568 if (ErrorInfo != ~0U) {
569 if (ErrorInfo >= Operands.size())
570 return Error(IDLoc, "too few operands for instruction");
571
572 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
573 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
574 }
575
576 return Error(ErrorLoc, "invalid operand for instruction");
577 }
578 case Match_MnemonicFail:
579 return Error(IDLoc, "invalid instruction");
580 }
581 return true;
582 }
583
584 int MipsAsmParser::matchCPURegisterName(StringRef Name) {
585 int CC;
586
587 if (Name == "at")
588 return getATReg();
589
590 CC = StringSwitch<unsigned>(Name)
591 .Case("zero", 0)
592 .Case("a0", 4)
593 .Case("a1", 5)
594 .Case("a2", 6)
595 .Case("a3", 7)
596 .Case("v0", 2)
597 .Case("v1", 3)
598 .Case("s0", 16)
599 .Case("s1", 17)
600 .Case("s2", 18)
601 .Case("s3", 19)
602 .Case("s4", 20)
603 .Case("s5", 21)
604 .Case("s6", 22)
605 .Case("s7", 23)
606 .Case("k0", 26)
607 .Case("k1", 27)
608 .Case("sp", 29)
609 .Case("fp", 30)
610 .Case("gp", 28)
611 .Case("ra", 31)
612 .Case("t0", 8)
613 .Case("t1", 9)
614 .Case("t2", 10)
615 .Case("t3", 11)
616 .Case("t4", 12)
617 .Case("t5", 13)
618 .Case("t6", 14)
619 .Case("t7", 15)
620 .Case("t8", 24)
621 .Case("t9", 25)
622 .Default(-1);
623
624 // Although SGI documentation just cut out t0-t3 for n32/n64,
625 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
626 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
627 if (isMips64() && 8 <= CC && CC <= 11)
628 CC += 4;
629
630 if (CC == -1 && isMips64())
631 CC = StringSwitch<unsigned>(Name)
632 .Case("a4", 8)
633 .Case("a5", 9)
634 .Case("a6", 10)
635 .Case("a7", 11)
636 .Case("kt0", 26)
637 .Case("kt1", 27)
638 .Case("s8", 30)
639 .Default(-1);
640
641 return CC;
642 }
643 int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
644
645 int CC;
646 CC = matchCPURegisterName(Name);
647 if (CC != -1)
648 return matchRegisterByNumber(CC,is64BitReg?Mips::CPU64RegsRegClassID:
649 Mips::CPURegsRegClassID);
650
651 if (Name[0] == 'f') {
652 StringRef NumString = Name.substr(1);
653 unsigned IntVal;
654 if( NumString.getAsInteger(10, IntVal))
655 return -1; // not integer
656 if (IntVal > 31)
657 return -1;
658
659 FpFormatTy Format = getFpFormat();
660
661 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
662 return getReg(Mips::FGR32RegClassID, IntVal);
663 if (Format == FP_FORMAT_D) {
664 if(isFP64()) {
665 return getReg(Mips::FGR64RegClassID, IntVal);
666 }
667 // only even numbers available as register pairs
668 if (( IntVal > 31) || (IntVal%2 != 0))
669 return -1;
670 return getReg(Mips::AFGR64RegClassID, IntVal/2);
671 }
672 }
673
674 return -1;
675 }
676 void MipsAsmParser::setDefaultFpFormat() {
677
678 if (isMips64() || isFP64())
679 FpFormat = FP_FORMAT_D;
680 else
681 FpFormat = FP_FORMAT_S;
682 }
683
684 bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
685
686 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
687 .Case("ldxc1", true)
688 .Case("ldc1", true)
689 .Case("sdxc1", true)
690 .Case("sdc1", true)
691 .Default(false);
692
693 return IsDouble;
694 }
695 void MipsAsmParser::setFpFormat(StringRef Format) {
696
697 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
698 .Case(".s", FP_FORMAT_S)
699 .Case(".d", FP_FORMAT_D)
700 .Case(".l", FP_FORMAT_L)
701 .Case(".w", FP_FORMAT_W)
702 .Default(FP_FORMAT_NONE);
703 }
704
705 bool MipsAssemblerOptions::setATReg(unsigned Reg) {
706 if (Reg > 31)
707 return false;
708
709 aTReg = Reg;
710 return true;
711 }
712
713 int MipsAsmParser::getATReg() {
714 return Options.getATRegNum();
715 }
716
717 unsigned MipsAsmParser::getReg(int RC,int RegNo) {
718 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
719 }
720
721 int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
722
723 if (RegNum > 31)
724 return -1;
725
726 return getReg(RegClass, RegNum);
727 }
728
729 int MipsAsmParser::tryParseRegister(bool is64BitReg) {
730 const AsmToken &Tok = Parser.getTok();
731 int RegNum = -1;
732
733 if (Tok.is(AsmToken::Identifier)) {
734 std::string lowerCase = Tok.getString().lower();
735 RegNum = matchRegisterName(lowerCase, is64BitReg);
736 } else if (Tok.is(AsmToken::Integer))
737 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
738 is64BitReg ? Mips::CPU64RegsRegClassID
739 : Mips::CPURegsRegClassID);
740 return RegNum;
741 }
742
743 bool MipsAsmParser::
744 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
745 bool is64BitReg){
746
747 SMLoc S = Parser.getTok().getLoc();
748 int RegNo = -1;
749
750 RegNo = tryParseRegister(is64BitReg);
751 if (RegNo == -1)
752 return true;
753
754 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
755 Parser.getTok().getLoc()));
756 Parser.Lex(); // Eat register token.
757 return false;
758 }
759
760 bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
761 StringRef Mnemonic) {
762 // Check if the current operand has a custom associated parser, if so, try to
763 // custom parse the operand, or fallback to the general approach.
764 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
765 if (ResTy == MatchOperand_Success)
766 return false;
767 // If there wasn't a custom match, try the generic matcher below. Otherwise,
768 // there was a match, but an error occurred, in which case, just return that
769 // the operand parsing failed.
770 if (ResTy == MatchOperand_ParseFail)
771 return true;
772
773 switch (getLexer().getKind()) {
774 default:
775 Error(Parser.getTok().getLoc(), "unexpected token in operand");
776 return true;
777 case AsmToken::Dollar: {
778 // parse register
779 SMLoc S = Parser.getTok().getLoc();
780 Parser.Lex(); // Eat dollar token.
781 // parse register operand
782 if (!tryParseRegisterOperand(Operands, isMips64())) {
783 if (getLexer().is(AsmToken::LParen)) {
784 // check if it is indexed addressing operand
785 Operands.push_back(MipsOperand::CreateToken("(", S));
786 Parser.Lex(); // eat parenthesis
787 if (getLexer().isNot(AsmToken::Dollar))
788 return true;
789
790 Parser.Lex(); // eat dollar
791 if (tryParseRegisterOperand(Operands, isMips64()))
792 return true;
793
794 if (!getLexer().is(AsmToken::RParen))
795 return true;
796
797 S = Parser.getTok().getLoc();
798 Operands.push_back(MipsOperand::CreateToken(")", S));
799 Parser.Lex();
800 }
801 return false;
802 }
803 // maybe it is a symbol reference
804 StringRef Identifier;
805 if (Parser.parseIdentifier(Identifier))
806 return true;
807
808 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
809
810 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
811
812 // Otherwise create a symbol ref.
813 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
814 getContext());
815
816 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
817 return false;
818 }
819 case AsmToken::Identifier:
820 case AsmToken::LParen:
821 case AsmToken::Minus:
822 case AsmToken::Plus:
823 case AsmToken::Integer:
824 case AsmToken::String: {
825 // quoted label names
826 const MCExpr *IdVal;
827 SMLoc S = Parser.getTok().getLoc();
828 if (getParser().parseExpression(IdVal))
829 return true;
830 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
831 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
832 return false;
833 }
834 case AsmToken::Percent: {
835 // it is a symbol reference or constant expression
836 const MCExpr *IdVal;
837 SMLoc S = Parser.getTok().getLoc(); // start location of the operand
838 if (parseRelocOperand(IdVal))
839 return true;
840
841 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
842
843 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
844 return false;
845 } // case AsmToken::Percent
846 } // switch(getLexer().getKind())
847 return true;
848 }
849
850 bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
851
852 Parser.Lex(); // eat % token
853 const AsmToken &Tok = Parser.getTok(); // get next token, operation
854 if (Tok.isNot(AsmToken::Identifier))
855 return true;
856
857 std::string Str = Tok.getIdentifier().str();
858
859 Parser.Lex(); // eat identifier
860 // now make expression from the rest of the operand
861 const MCExpr *IdVal;
862 SMLoc EndLoc;
863
864 if (getLexer().getKind() == AsmToken::LParen) {
865 while (1) {
866 Parser.Lex(); // eat '(' token
867 if (getLexer().getKind() == AsmToken::Percent) {
868 Parser.Lex(); // eat % token
869 const AsmToken &nextTok = Parser.getTok();
870 if (nextTok.isNot(AsmToken::Identifier))
871 return true;
872 Str += "(%";
873 Str += nextTok.getIdentifier();
874 Parser.Lex(); // eat identifier
875 if (getLexer().getKind() != AsmToken::LParen)
876 return true;
877 } else
878 break;
879 }
880 if (getParser().parseParenExpression(IdVal,EndLoc))
881 return true;
882
883 while (getLexer().getKind() == AsmToken::RParen)
884 Parser.Lex(); // eat ')' token
885
886 } else
887 return true; // parenthesis must follow reloc operand
888
889 // Check the type of the expression
890 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
891 // it's a constant, evaluate lo or hi value
892 int Val = MCE->getValue();
893 if (Str == "lo") {
894 Val = Val & 0xffff;
895 } else if (Str == "hi") {
896 int LoSign = Val & 0x8000;
897 Val = (Val & 0xffff0000) >> 16;
898 //lower part is treated as signed int, so if it is negative
899 //we must add 1 to hi part to compensate
900 if (LoSign)
901 Val++;
902 }
903 Res = MCConstantExpr::Create(Val, getContext());
904 return false;
905 }
906
907 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
908 // it's a symbol, create symbolic expression from symbol
909 StringRef Symbol = MSRE->getSymbol().getName();
910 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
911 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
912 return false;
913 }
914 return true;
915 }
916
917 bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
918 SMLoc &EndLoc) {
919
920 StartLoc = Parser.getTok().getLoc();
921 RegNo = tryParseRegister(isMips64());
922 EndLoc = Parser.getTok().getLoc();
923 return (RegNo == (unsigned)-1);
924 }
925
926 bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
927
928 SMLoc S;
929
930 switch(getLexer().getKind()) {
931 default:
932 return true;
933 case AsmToken::Integer:
934 case AsmToken::Minus:
935 case AsmToken::Plus:
936 return (getParser().parseExpression(Res));
937 case AsmToken::Percent:
938 return parseRelocOperand(Res);
939 case AsmToken::LParen:
940 return false; // it's probably assuming 0
941 }
942 return true;
943 }
944
945 MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
946 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
947
948 const MCExpr *IdVal = 0;
949 SMLoc S;
950 // first operand is the offset
951 S = Parser.getTok().getLoc();
952
953 if (parseMemOffset(IdVal))
954 return MatchOperand_ParseFail;
955
956 const AsmToken &Tok = Parser.getTok(); // get next token
957 if (Tok.isNot(AsmToken::LParen)) {
958 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
959 if (Mnemonic->getToken() == "la") {
960 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() -1);
961 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
962 return MatchOperand_Success;
963 }
964 Error(Parser.getTok().getLoc(), "'(' expected");
965 return MatchOperand_ParseFail;
966 }
967
968 Parser.Lex(); // Eat '(' token.
969
970 const AsmToken &Tok1 = Parser.getTok(); // get next token
971 if (Tok1.is(AsmToken::Dollar)) {
972 Parser.Lex(); // Eat '$' token.
973 if (tryParseRegisterOperand(Operands, isMips64())) {
974 Error(Parser.getTok().getLoc(), "unexpected token in operand");
975 return MatchOperand_ParseFail;
976 }
977
978 } else {
979 Error(Parser.getTok().getLoc(), "unexpected token in operand");
980 return MatchOperand_ParseFail;
981 }
982
983 const AsmToken &Tok2 = Parser.getTok(); // get next token
984 if (Tok2.isNot(AsmToken::RParen)) {
985 Error(Parser.getTok().getLoc(), "')' expected");
986 return MatchOperand_ParseFail;
987 }
988
989 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
990
991 Parser.Lex(); // Eat ')' token.
992
993 if (IdVal == 0)
994 IdVal = MCConstantExpr::Create(0, getContext());
995
996 // now replace register operand with the mem operand
997 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
998 int RegNo = op->getReg();
999 // remove register from operands
1000 Operands.pop_back();
1001 // and add memory operand
1002 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1003 delete op;
1004 return MatchOperand_Success;
1005 }
1006
1007 MipsAsmParser::OperandMatchResultTy
1008 MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1009
1010 if (!isMips64())
1011 return MatchOperand_NoMatch;
1012 // if the first token is not '$' we have an error
1013 if (Parser.getTok().isNot(AsmToken::Dollar))
1014 return MatchOperand_NoMatch;
1015
1016 Parser.Lex(); // Eat $
1017 if(!tryParseRegisterOperand(Operands, true)) {
1018 // set the proper register kind
1019 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1020 op->setRegKind(MipsOperand::Kind_CPU64Regs);
1021 return MatchOperand_Success;
1022 }
1023 return MatchOperand_NoMatch;
1024 }
1025
1026 MipsAsmParser::OperandMatchResultTy
1027 MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1028
1029 // if the first token is not '$' we have an error
1030 if (Parser.getTok().isNot(AsmToken::Dollar))
1031 return MatchOperand_NoMatch;
1032
1033 Parser.Lex(); // Eat $
1034 if(!tryParseRegisterOperand(Operands, false)) {
1035 // set the propper register kind
1036 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1037 op->setRegKind(MipsOperand::Kind_CPURegs);
1038 return MatchOperand_Success;
1039 }
1040 return MatchOperand_NoMatch;
1041 }
1042
1043 MipsAsmParser::OperandMatchResultTy
1044 MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1045
1046 if (isMips64())
1047 return MatchOperand_NoMatch;
1048
1049 // if the first token is not '$' we have error
1050 if (Parser.getTok().isNot(AsmToken::Dollar))
1051 return MatchOperand_NoMatch;
1052 SMLoc S = Parser.getTok().getLoc();
1053 Parser.Lex(); // Eat $
1054
1055 const AsmToken &Tok = Parser.getTok(); // get next token
1056 if (Tok.isNot(AsmToken::Integer))
1057 return MatchOperand_NoMatch;
1058
1059 unsigned RegNum = Tok.getIntVal();
1060 // at the moment only hwreg29 is supported
1061 if (RegNum != 29)
1062 return MatchOperand_ParseFail;
1063
1064 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
1065 Parser.getTok().getLoc());
1066 op->setRegKind(MipsOperand::Kind_HWRegs);
1067 Operands.push_back(op);
1068
1069 Parser.Lex(); // Eat reg number
1070 return MatchOperand_Success;
1071 }
1072
1073 MipsAsmParser::OperandMatchResultTy
1074 MipsAsmParser::parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1075
1076 if (!isMips64())
1077 return MatchOperand_NoMatch;
1078 //if the first token is not '$' we have error
1079 if (Parser.getTok().isNot(AsmToken::Dollar))
1080 return MatchOperand_NoMatch;
1081 SMLoc S = Parser.getTok().getLoc();
1082 Parser.Lex(); // Eat $
1083
1084 const AsmToken &Tok = Parser.getTok(); // get next token
1085 if (Tok.isNot(AsmToken::Integer))
1086 return MatchOperand_NoMatch;
1087
1088 unsigned RegNum = Tok.getIntVal();
1089 // at the moment only hwreg29 is supported
1090 if (RegNum != 29)
1091 return MatchOperand_ParseFail;
1092
1093 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
1094 Parser.getTok().getLoc());
1095 op->setRegKind(MipsOperand::Kind_HW64Regs);
1096 Operands.push_back(op);
1097
1098 Parser.Lex(); // Eat reg number
1099 return MatchOperand_Success;
1100 }
1101
1102 MipsAsmParser::OperandMatchResultTy
1103 MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1104 unsigned RegNum;
1105 //if the first token is not '$' we have error
1106 if (Parser.getTok().isNot(AsmToken::Dollar))
1107 return MatchOperand_NoMatch;
1108 SMLoc S = Parser.getTok().getLoc();
1109 Parser.Lex(); // Eat $
1110
1111 const AsmToken &Tok = Parser.getTok(); // get next token
1112 if (Tok.is(AsmToken::Integer)) {
1113 RegNum = Tok.getIntVal();
1114 // at the moment only fcc0 is supported
1115 if (RegNum != 0)
1116 return MatchOperand_ParseFail;
1117 } else if (Tok.is(AsmToken::Identifier)) {
1118 // at the moment only fcc0 is supported
1119 if (Tok.getIdentifier() != "fcc0")
1120 return MatchOperand_ParseFail;
1121 } else
1122 return MatchOperand_NoMatch;
1123
1124 MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
1125 Parser.getTok().getLoc());
1126 op->setRegKind(MipsOperand::Kind_CCRRegs);
1127 Operands.push_back(op);
1128
1129 Parser.Lex(); // Eat reg number
1130 return MatchOperand_Success;
1131 }
1132
1133 MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1134
1135 MCSymbolRefExpr::VariantKind VK
1136 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1137 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1138 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1139 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1140 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1141 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1142 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1143 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1144 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1145 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1146 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1147 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1148 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1149 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1150 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1151 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1152 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1153 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1154 .Default(MCSymbolRefExpr::VK_None);
1155
1156 return VK;
1157 }
1158
1159 static int ConvertCcString(StringRef CondString) {
1160 int CC = StringSwitch<unsigned>(CondString)
1161 .Case(".f", 0)
1162 .Case(".un", 1)
1163 .Case(".eq", 2)
1164 .Case(".ueq", 3)
1165 .Case(".olt", 4)
1166 .Case(".ult", 5)
1167 .Case(".ole", 6)
1168 .Case(".ule", 7)
1169 .Case(".sf", 8)
1170 .Case(".ngle", 9)
1171 .Case(".seq", 10)
1172 .Case(".ngl", 11)
1173 .Case(".lt", 12)
1174 .Case(".nge", 13)
1175 .Case(".le", 14)
1176 .Case(".ngt", 15)
1177 .Default(-1);
1178
1179 return CC;
1180 }
1181
1182 bool MipsAsmParser::
1183 parseMathOperation(StringRef Name, SMLoc NameLoc,
1184 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1185 // split the format
1186 size_t Start = Name.find('.'), Next = Name.rfind('.');
1187 StringRef Format1 = Name.slice(Start, Next);
1188 // and add the first format to the operands
1189 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
1190 // now for the second format
1191 StringRef Format2 = Name.slice(Next, StringRef::npos);
1192 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1193
1194 // set the format for the first register
1195 setFpFormat(Format1);
1196
1197 // Read the remaining operands.
1198 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1199 // Read the first operand.
1200 if (ParseOperand(Operands, Name)) {
1201 SMLoc Loc = getLexer().getLoc();
1202 Parser.eatToEndOfStatement();
1203 return Error(Loc, "unexpected token in argument list");
1204 }
1205
1206 if (getLexer().isNot(AsmToken::Comma)) {
1207 SMLoc Loc = getLexer().getLoc();
1208 Parser.eatToEndOfStatement();
1209 return Error(Loc, "unexpected token in argument list");
1210
1211 }
1212 Parser.Lex(); // Eat the comma.
1213
1214 //set the format for the first register
1215 setFpFormat(Format2);
1216
1217 // Parse and remember the operand.
1218 if (ParseOperand(Operands, Name)) {
1219 SMLoc Loc = getLexer().getLoc();
1220 Parser.eatToEndOfStatement();
1221 return Error(Loc, "unexpected token in argument list");
1222 }
1223 }
1224
1225 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1226 SMLoc Loc = getLexer().getLoc();
1227 Parser.eatToEndOfStatement();
1228 return Error(Loc, "unexpected token in argument list");
1229 }
1230
1231 Parser.Lex(); // Consume the EndOfStatement
1232 return false;
1233 }
1234
1235 bool MipsAsmParser::
1236 ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
1237 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1238 StringRef Mnemonic;
1239 // floating point instructions: should register be treated as double?
1240 if (requestsDoubleOperand(Name)) {
1241 setFpFormat(FP_FORMAT_D);
1242 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
1243 Mnemonic = Name;
1244 }
1245 else {
1246 setDefaultFpFormat();
1247 // Create the leading tokens for the mnemonic, split by '.' characters.
1248 size_t Start = 0, Next = Name.find('.');
1249 Mnemonic = Name.slice(Start, Next);
1250
1251 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1252
1253 if (Next != StringRef::npos) {
1254 // there is a format token in mnemonic
1255 // StringRef Rest = Name.slice(Next, StringRef::npos);
1256 size_t Dot = Name.find('.', Next+1);
1257 StringRef Format = Name.slice(Next, Dot);
1258 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1259 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1260 else {
1261 if (Name.startswith("c.")){
1262 // floating point compare, add '.' and immediate represent for cc
1263 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1264 int Cc = ConvertCcString(Format);
1265 if (Cc == -1) {
1266 return Error(NameLoc, "Invalid conditional code");
1267 }
1268 SMLoc E = SMLoc::getFromPointer(
1269 Parser.getTok().getLoc().getPointer() -1 );
1270 Operands.push_back(MipsOperand::CreateImm(
1271 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1272 } else {
1273 // trunc, ceil, floor ...
1274 return parseMathOperation(Name, NameLoc, Operands);
1275 }
1276
1277 // the rest is a format
1278 Format = Name.slice(Dot, StringRef::npos);
1279 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1280 }
1281
1282 setFpFormat(Format);
1283 }
1284 }
1285
1286 // Read the remaining operands.
1287 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1288 // Read the first operand.
1289 if (ParseOperand(Operands, Mnemonic)) {
1290 SMLoc Loc = getLexer().getLoc();
1291 Parser.eatToEndOfStatement();
1292 return Error(Loc, "unexpected token in argument list");
1293 }
1294
1295 while (getLexer().is(AsmToken::Comma) ) {
1296 Parser.Lex(); // Eat the comma.
1297
1298 // Parse and remember the operand.
1299 if (ParseOperand(Operands, Name)) {
1300 SMLoc Loc = getLexer().getLoc();
1301 Parser.eatToEndOfStatement();
1302 return Error(Loc, "unexpected token in argument list");
1303 }
1304 }
1305 }
1306
1307 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1308 SMLoc Loc = getLexer().getLoc();
1309 Parser.eatToEndOfStatement();
1310 return Error(Loc, "unexpected token in argument list");
1311 }
1312
1313 Parser.Lex(); // Consume the EndOfStatement
1314 return false;
1315 }
1316
1317 bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1318 SMLoc Loc = getLexer().getLoc();
1319 Parser.eatToEndOfStatement();
1320 return Error(Loc, ErrorMsg);
1321 }
1322
1323 bool MipsAsmParser::parseSetNoAtDirective() {
1324 // line should look like:
1325 // .set noat
1326 // set at reg to 0
1327 Options.setATReg(0);
1328 // eat noat
1329 Parser.Lex();
1330 // if this is not the end of the statement, report error
1331 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1332 reportParseError("unexpected token in statement");
1333 return false;
1334 }
1335 Parser.Lex(); // Consume the EndOfStatement
1336 return false;
1337 }
1338 bool MipsAsmParser::parseSetAtDirective() {
1339 // line can be
1340 // .set at - defaults to $1
1341 // or .set at=$reg
1342 int AtRegNo;
1343 getParser().Lex();
1344 if (getLexer().is(AsmToken::EndOfStatement)) {
1345 Options.setATReg(1);
1346 Parser.Lex(); // Consume the EndOfStatement
1347 return false;
1348 } else if (getLexer().is(AsmToken::Equal)) {
1349 getParser().Lex(); //eat '='
1350 if (getLexer().isNot(AsmToken::Dollar)) {
1351 reportParseError("unexpected token in statement");
1352 return false;
1353 }
1354 Parser.Lex(); // eat '$'
1355 const AsmToken &Reg = Parser.getTok();
1356 if (Reg.is(AsmToken::Identifier)) {
1357 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
1358 } else if (Reg.is(AsmToken::Integer)) {
1359 AtRegNo = Reg.getIntVal();
1360 } else {
1361 reportParseError("unexpected token in statement");
1362 return false;
1363 }
1364
1365 if ( AtRegNo < 1 || AtRegNo > 31) {
1366 reportParseError("unexpected token in statement");
1367 return false;
1368 }
1369
1370 if (!Options.setATReg(AtRegNo)) {
1371 reportParseError("unexpected token in statement");
1372 return false;
1373 }
1374 getParser().Lex(); //eat reg
1375
1376 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1377 reportParseError("unexpected token in statement");
1378 return false;
1379 }
1380 Parser.Lex(); // Consume the EndOfStatement
1381 return false;
1382 } else {
1383 reportParseError("unexpected token in statement");
1384 return false;
1385 }
1386 }
1387
1388 bool MipsAsmParser::parseSetReorderDirective() {
1389 Parser.Lex();
1390 // if this is not the end of the statement, report error
1391 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1392 reportParseError("unexpected token in statement");
1393 return false;
1394 }
1395 Options.setReorder();
1396 Parser.Lex(); // Consume the EndOfStatement
1397 return false;
1398 }
1399
1400 bool MipsAsmParser::parseSetNoReorderDirective() {
1401 Parser.Lex();
1402 // if this is not the end of the statement, report error
1403 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1404 reportParseError("unexpected token in statement");
1405 return false;
1406 }
1407 Options.setNoreorder();
1408 Parser.Lex(); // Consume the EndOfStatement
1409 return false;
1410 }
1411
1412 bool MipsAsmParser::parseSetMacroDirective() {
1413 Parser.Lex();
1414 // if this is not the end of the statement, report error
1415 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1416 reportParseError("unexpected token in statement");
1417 return false;
1418 }
1419 Options.setMacro();
1420 Parser.Lex(); // Consume the EndOfStatement
1421 return false;
1422 }
1423
1424 bool MipsAsmParser::parseSetNoMacroDirective() {
1425 Parser.Lex();
1426 // if this is not the end of the statement, report error
1427 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1428 reportParseError("`noreorder' must be set before `nomacro'");
1429 return false;
1430 }
1431 if (Options.isReorder()) {
1432 reportParseError("`noreorder' must be set before `nomacro'");
1433 return false;
1434 }
1435 Options.setNomacro();
1436 Parser.Lex(); // Consume the EndOfStatement
1437 return false;
1438 }
1439 bool MipsAsmParser::parseDirectiveSet() {
1440
1441 // get next token
1442 const AsmToken &Tok = Parser.getTok();
1443
1444 if (Tok.getString() == "noat") {
1445 return parseSetNoAtDirective();
1446 } else if (Tok.getString() == "at") {
1447 return parseSetAtDirective();
1448 } else if (Tok.getString() == "reorder") {
1449 return parseSetReorderDirective();
1450 } else if (Tok.getString() == "noreorder") {
1451 return parseSetNoReorderDirective();
1452 } else if (Tok.getString() == "macro") {
1453 return parseSetMacroDirective();
1454 } else if (Tok.getString() == "nomacro") {
1455 return parseSetNoMacroDirective();
1456 } else if (Tok.getString() == "nomips16") {
1457 // ignore this directive for now
1458 Parser.eatToEndOfStatement();
1459 return false;
1460 } else if (Tok.getString() == "nomicromips") {
1461 // ignore this directive for now
1462 Parser.eatToEndOfStatement();
1463 return false;
1464 }
1465
1466 return true;
1467 }
1468
1469 /// parseDirectiveWord
1470 /// ::= .word [ expression (, expression)* ]
1471 bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
1472 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1473 for (;;) {
1474 const MCExpr *Value;
1475 if (getParser().parseExpression(Value))
1476 return true;
1477
1478 getParser().getStreamer().EmitValue(Value, Size);
1479
1480 if (getLexer().is(AsmToken::EndOfStatement))
1481 break;
1482
1483 // FIXME: Improve diagnostic.
1484 if (getLexer().isNot(AsmToken::Comma))
1485 return Error(L, "unexpected token in directive");
1486 Parser.Lex();
1487 }
1488 }
1489
1490 Parser.Lex();
1491 return false;
1492 }
1493
1494 bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
1495
1496 StringRef IDVal = DirectiveID.getString();
1497
1498 if ( IDVal == ".ent") {
1499 // ignore this directive for now
1500 Parser.Lex();
1501 return false;
1502 }
1503
1504 if (IDVal == ".end") {
1505 // ignore this directive for now
1506 Parser.Lex();
1507 return false;
1508 }
1509
1510 if (IDVal == ".frame") {
1511 // ignore this directive for now
1512 Parser.eatToEndOfStatement();
1513 return false;
1514 }
1515
1516 if (IDVal == ".set") {
1517 return parseDirectiveSet();
1518 }
1519
1520 if (IDVal == ".fmask") {
1521 // ignore this directive for now
1522 Parser.eatToEndOfStatement();
1523 return false;
1524 }
1525
1526 if (IDVal == ".mask") {
1527 // ignore this directive for now
1528 Parser.eatToEndOfStatement();
1529 return false;
1530 }
1531
1532 if (IDVal == ".gpword") {
1533 // ignore this directive for now
1534 Parser.eatToEndOfStatement();
1535 return false;
1536 }
1537
1538 if (IDVal == ".word") {
1539 parseDirectiveWord(4, DirectiveID.getLoc());
1540 return false;
1541 }
1542
1543 return true;
1544 }
1545
1546 extern "C" void LLVMInitializeMipsAsmParser() {
1547 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1548 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1549 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1550 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1551 }
1552
1553 #define GET_REGISTER_MATCHER
1554 #define GET_MATCHER_IMPLEMENTATION
1555 #include "MipsGenAsmMatcher.inc"