blob: 26fce6a75e32aa2370d1df2784268a34a846e0ec [file] [log] [blame]
Jia Liuc5707112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindolafddf8042012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterec65be82012-09-05 23:34:03 +000011#include "MipsRegisterInfo.h"
12#include "llvm/ADT/StringSwitch.h"
13#include "llvm/MC/MCContext.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCInst.h"
16#include "llvm/MC/MCStreamer.h"
17#include "llvm/MC/MCSubtargetInfo.h"
18#include "llvm/MC/MCSymbol.h"
Rafael Espindolafddf8042012-01-11 03:56:41 +000019#include "llvm/MC/MCParser/MCAsmLexer.h"
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000020#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21#include "llvm/MC/MCTargetAsmParser.h"
Jack Carterec65be82012-09-05 23:34:03 +000022#include "llvm/Support/TargetRegistry.h"
Rafael Espindolafddf8042012-01-11 03:56:41 +000023
24using namespace llvm;
25
26namespace {
Jack Carter30116cd2012-10-04 02:29:46 +000027class MipsAssemblerOptions {
28public:
29 MipsAssemblerOptions():
30 aTReg(1), reorder(true), macro(true) {
31 }
Jack Carterec65be82012-09-05 23:34:03 +000032
Jack Carter30116cd2012-10-04 02:29:46 +000033 unsigned getATRegNum() {return aTReg;}
34 bool setATReg(unsigned Reg);
35
36 bool isReorder() {return reorder;}
37 void setReorder() {reorder = true;}
38 void setNoreorder() {reorder = false;}
39
40 bool isMacro() {return macro;}
41 void setMacro() {macro = true;}
42 void setNomacro() {macro = false;}
43
44private:
45 unsigned aTReg;
46 bool reorder;
47 bool macro;
48};
49}
50
51namespace {
Rafael Espindolafddf8042012-01-11 03:56:41 +000052class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000053
Jack Carterf740d6e2012-09-07 00:23:42 +000054 enum FpFormatTy {
55 FP_FORMAT_NONE = -1,
56 FP_FORMAT_S,
57 FP_FORMAT_D,
58 FP_FORMAT_L,
59 FP_FORMAT_W
60 } FpFormat;
61
Jack Carterec65be82012-09-05 23:34:03 +000062 MCSubtargetInfo &STI;
63 MCAsmParser &Parser;
Jack Carter10d5ff62012-10-05 23:55:28 +000064 MipsAssemblerOptions Options;
Jack Carter30116cd2012-10-04 02:29:46 +000065
Jack Carterec65be82012-09-05 23:34:03 +000066
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000067#define GET_ASSEMBLER_HEADER
68#include "MipsGenAsmMatcher.inc"
69
Rafael Espindolafddf8042012-01-11 03:56:41 +000070 bool MatchAndEmitInstruction(SMLoc IDLoc,
71 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
72 MCStreamer &Out);
73
74 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
75
76 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000077 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindolafddf8042012-01-11 03:56:41 +000078
Jack Carterf740d6e2012-09-07 00:23:42 +000079 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
80 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
81
Rafael Espindolafddf8042012-01-11 03:56:41 +000082 bool ParseDirective(AsmToken DirectiveID);
83
Jack Carterec65be82012-09-05 23:34:03 +000084 MipsAsmParser::OperandMatchResultTy
85 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
Chad Rosier038f3e32012-09-03 18:47:45 +000086
Jack Carterec65be82012-09-05 23:34:03 +000087 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
88 StringRef Mnemonic);
89
90 int tryParseRegister(StringRef Mnemonic);
91
92 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
93 StringRef Mnemonic);
94
Jack Carter9d577c82012-10-04 04:03:53 +000095 bool needsExpansion(MCInst &Inst);
96
97 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +000098 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9d577c82012-10-04 04:03:53 +000099 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000100 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30116cd2012-10-04 02:29:46 +0000101 bool reportParseError(StringRef ErrorMsg);
102
Jack Carter6b96c3f2012-09-06 20:00:02 +0000103 bool parseMemOffset(const MCExpr *&Res);
104 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter30116cd2012-10-04 02:29:46 +0000105
106 bool parseDirectiveSet();
107
108 bool parseSetAtDirective();
109 bool parseSetNoAtDirective();
110 bool parseSetMacroDirective();
111 bool parseSetNoMacroDirective();
112 bool parseSetReorderDirective();
113 bool parseSetNoReorderDirective();
114
Jack Carter6b96c3f2012-09-06 20:00:02 +0000115 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Carterf740d6e2012-09-07 00:23:42 +0000116
Jack Carterec65be82012-09-05 23:34:03 +0000117 bool isMips64() const {
118 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
119 }
120
Jack Carterf740d6e2012-09-07 00:23:42 +0000121 bool isFP64() const {
122 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
123 }
124
Jack Carterec65be82012-09-05 23:34:03 +0000125 int matchRegisterName(StringRef Symbol);
126
127 int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
128
Jack Carterf740d6e2012-09-07 00:23:42 +0000129 void setFpFormat(FpFormatTy Format) {
130 FpFormat = Format;
131 }
132
133 void setDefaultFpFormat();
134
135 void setFpFormat(StringRef Format);
136
137 FpFormatTy getFpFormat() {return FpFormat;}
138
139 bool requestsDoubleOperand(StringRef Mnemonic);
140
Jack Carterec65be82012-09-05 23:34:03 +0000141 unsigned getReg(int RC,int RegNo);
Chad Rosier038f3e32012-09-03 18:47:45 +0000142
Jack Carter30116cd2012-10-04 02:29:46 +0000143 unsigned getATReg();
Rafael Espindolafddf8042012-01-11 03:56:41 +0000144public:
145 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterec65be82012-09-05 23:34:03 +0000146 : MCTargetAsmParser(), STI(sti), Parser(parser) {
147 // Initialize the set of available features.
148 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindolafddf8042012-01-11 03:56:41 +0000149 }
150
Jack Carterec65be82012-09-05 23:34:03 +0000151 MCAsmParser &getParser() const { return Parser; }
152 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
153
Rafael Espindolafddf8042012-01-11 03:56:41 +0000154};
155}
156
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000157namespace {
158
159/// MipsOperand - Instances of this class represent a parsed Mips machine
160/// instruction.
161class MipsOperand : public MCParsedAsmOperand {
Jack Carterec65be82012-09-05 23:34:03 +0000162
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000163 enum KindTy {
164 k_CondCode,
165 k_CoprocNum,
166 k_Immediate,
167 k_Memory,
168 k_PostIndexRegister,
169 k_Register,
170 k_Token
171 } Kind;
172
173 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterec65be82012-09-05 23:34:03 +0000174
175 union {
176 struct {
177 const char *Data;
178 unsigned Length;
179 } Tok;
180
181 struct {
182 unsigned RegNum;
183 } Reg;
184
185 struct {
186 const MCExpr *Val;
187 } Imm;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000188
189 struct {
190 unsigned Base;
191 const MCExpr *Off;
192 } Mem;
Jack Carterec65be82012-09-05 23:34:03 +0000193 };
194
195 SMLoc StartLoc, EndLoc;
196
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000197public:
198 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000199 assert(N == 1 && "Invalid number of operands!");
200 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000201 }
Jack Carterec65be82012-09-05 23:34:03 +0000202
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000203 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterec65be82012-09-05 23:34:03 +0000204 // Add as immediate when possible. Null MCExpr = 0.
205 if (Expr == 0)
206 Inst.addOperand(MCOperand::CreateImm(0));
207 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
208 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
209 else
210 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000211 }
Jack Carterec65be82012-09-05 23:34:03 +0000212
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000213 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000214 assert(N == 1 && "Invalid number of operands!");
215 const MCExpr *Expr = getImm();
216 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000217 }
Jack Carterec65be82012-09-05 23:34:03 +0000218
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000219 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000220 assert(N == 2 && "Invalid number of operands!");
221
222 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
223
224 const MCExpr *Expr = getMemOff();
225 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000226 }
227
228 bool isReg() const { return Kind == k_Register; }
229 bool isImm() const { return Kind == k_Immediate; }
230 bool isToken() const { return Kind == k_Token; }
231 bool isMem() const { return Kind == k_Memory; }
232
233 StringRef getToken() const {
234 assert(Kind == k_Token && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000235 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000236 }
237
238 unsigned getReg() const {
239 assert((Kind == k_Register) && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000240 return Reg.RegNum;
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000241 }
242
Jack Carterec65be82012-09-05 23:34:03 +0000243 const MCExpr *getImm() const {
244 assert((Kind == k_Immediate) && "Invalid access!");
245 return Imm.Val;
246 }
247
Jack Carter6b96c3f2012-09-06 20:00:02 +0000248 unsigned getMemBase() const {
249 assert((Kind == k_Memory) && "Invalid access!");
250 return Mem.Base;
251 }
252
253 const MCExpr *getMemOff() const {
254 assert((Kind == k_Memory) && "Invalid access!");
255 return Mem.Off;
256 }
257
Jack Carterec65be82012-09-05 23:34:03 +0000258 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
259 MipsOperand *Op = new MipsOperand(k_Token);
260 Op->Tok.Data = Str.data();
261 Op->Tok.Length = Str.size();
262 Op->StartLoc = S;
263 Op->EndLoc = S;
264 return Op;
265 }
266
267 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
268 MipsOperand *Op = new MipsOperand(k_Register);
269 Op->Reg.RegNum = RegNum;
270 Op->StartLoc = S;
271 Op->EndLoc = E;
272 return Op;
273 }
274
275 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
276 MipsOperand *Op = new MipsOperand(k_Immediate);
277 Op->Imm.Val = Val;
278 Op->StartLoc = S;
279 Op->EndLoc = E;
280 return Op;
281 }
282
Jack Carter6b96c3f2012-09-06 20:00:02 +0000283 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
284 SMLoc S, SMLoc E) {
285 MipsOperand *Op = new MipsOperand(k_Memory);
286 Op->Mem.Base = Base;
287 Op->Mem.Off = Off;
288 Op->StartLoc = S;
289 Op->EndLoc = E;
290 return Op;
291 }
292
Jack Carterec65be82012-09-05 23:34:03 +0000293 /// getStartLoc - Get the location of the first token of this operand.
294 SMLoc getStartLoc() const { return StartLoc; }
295 /// getEndLoc - Get the location of the last token of this operand.
296 SMLoc getEndLoc() const { return EndLoc; }
297
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000298 virtual void print(raw_ostream &OS) const {
299 llvm_unreachable("unimplemented!");
300 }
301};
302}
303
Jack Carter9d577c82012-10-04 04:03:53 +0000304bool MipsAsmParser::needsExpansion(MCInst &Inst) {
305
306 switch(Inst.getOpcode()) {
307 case Mips::LoadImm32Reg:
308 return true;
309 default:
310 return false;
311 }
312}
Jack Carter2490dc62012-10-06 00:53:28 +0000313
Jack Carter9d577c82012-10-04 04:03:53 +0000314void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000315 SmallVectorImpl<MCInst> &Instructions){
Jack Carter9d577c82012-10-04 04:03:53 +0000316 switch(Inst.getOpcode()) {
317 case Mips::LoadImm32Reg:
318 return expandLoadImm(Inst, IDLoc, Instructions);
319 }
Jack Carter9d577c82012-10-04 04:03:53 +0000320}
Jack Carter2490dc62012-10-06 00:53:28 +0000321
Jack Carter9d577c82012-10-04 04:03:53 +0000322void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000323 SmallVectorImpl<MCInst> &Instructions){
324 MCInst tmpInst;
Jack Carter9d577c82012-10-04 04:03:53 +0000325 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();
Jack Carter2490dc62012-10-06 00:53:28 +0000331 tmpInst.setLoc(IDLoc);
Jack Carter9d577c82012-10-04 04:03:53 +0000332 if ( 0 <= ImmValue && ImmValue <= 65535) {
Jack Carter2490dc62012-10-06 00:53:28 +0000333 // for 0 <= j <= 65535.
Jack Carter9d577c82012-10-04 04:03:53 +0000334 // li d,j => ori d,$zero,j
Jack Carter2490dc62012-10-06 00:53:28 +0000335 tmpInst.setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
336 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
337 tmpInst.addOperand(
Jack Carter9d577c82012-10-04 04:03:53 +0000338 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
Jack Carter2490dc62012-10-06 00:53:28 +0000339 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter9d577c82012-10-04 04:03:53 +0000340 Instructions.push_back(tmpInst);
341 } else if ( ImmValue < 0 && ImmValue >= -32768) {
Jack Carter2490dc62012-10-06 00:53:28 +0000342 // for -32768 <= j < 0.
Jack Carter9d577c82012-10-04 04:03:53 +0000343 // li d,j => addiu d,$zero,j
Jack Carter2490dc62012-10-06 00:53:28 +0000344 tmpInst.setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
345 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
346 tmpInst.addOperand(
Jack Carter9d577c82012-10-04 04:03:53 +0000347 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
Jack Carter2490dc62012-10-06 00:53:28 +0000348 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter9d577c82012-10-04 04:03:53 +0000349 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)
Jack Carter2490dc62012-10-06 00:53:28 +0000354 tmpInst.setOpcode(isMips64() ? Mips::LUi64 : Mips::LUi);
355 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
356 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter9d577c82012-10-04 04:03:53 +0000357 Instructions.push_back(tmpInst);
Jack Carter2490dc62012-10-06 00:53:28 +0000358 tmpInst.clear();
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);
Jack Carter9d577c82012-10-04 04:03:53 +0000364 Instructions.push_back(tmpInst);
365 }
366}
Jack Carter2490dc62012-10-06 00:53:28 +0000367
Rafael Espindolafddf8042012-01-11 03:56:41 +0000368bool MipsAsmParser::
369MatchAndEmitInstruction(SMLoc IDLoc,
370 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
371 MCStreamer &Out) {
Jack Carterec65be82012-09-05 23:34:03 +0000372 MCInst Inst;
Jack Carterec65be82012-09-05 23:34:03 +0000373 unsigned Kind;
Chad Rosier22685872012-10-01 23:45:51 +0000374 unsigned ErrorInfo;
Chad Rosier9ba9d4d2012-10-05 18:41:14 +0000375 MatchInstMapAndConstraints MapAndConstraints;
Chad Rosier22685872012-10-01 23:45:51 +0000376 unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst,
377 MapAndConstraints, ErrorInfo,
378 /*matchingInlineAsm*/ false);
Jack Carterec65be82012-09-05 23:34:03 +0000379
380 switch (MatchResult) {
381 default: break;
382 case Match_Success: {
Jack Carter9d577c82012-10-04 04:03:53 +0000383 if (needsExpansion(Inst)) {
Jack Carter2490dc62012-10-06 00:53:28 +0000384 SmallVector<MCInst, 4> Instructions;
Jack Carter9d577c82012-10-04 04:03:53 +0000385 expandInstruction(Inst, IDLoc, Instructions);
386 for(unsigned i =0; i < Instructions.size(); i++){
Jack Carter2490dc62012-10-06 00:53:28 +0000387 Out.EmitInstruction(Instructions[i]);
Jack Carter9d577c82012-10-04 04:03:53 +0000388 }
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
David Chisnall572e1bd2012-10-09 16:27:43 +0000418 int CC;
419 if (!isMips64())
420 CC = StringSwitch<unsigned>(Name)
421 .Case("zero", Mips::ZERO)
422 .Case("a0", Mips::A0)
423 .Case("a1", Mips::A1)
424 .Case("a2", Mips::A2)
425 .Case("a3", Mips::A3)
426 .Case("v0", Mips::V0)
427 .Case("v1", Mips::V1)
428 .Case("s0", Mips::S0)
429 .Case("s1", Mips::S1)
430 .Case("s2", Mips::S2)
431 .Case("s3", Mips::S3)
432 .Case("s4", Mips::S4)
433 .Case("s5", Mips::S5)
434 .Case("s6", Mips::S6)
435 .Case("s7", Mips::S7)
436 .Case("k0", Mips::K0)
437 .Case("k1", Mips::K1)
438 .Case("sp", Mips::SP)
439 .Case("fp", Mips::FP)
440 .Case("gp", Mips::GP)
441 .Case("ra", Mips::RA)
442 .Case("t0", Mips::T0)
443 .Case("t1", Mips::T1)
444 .Case("t2", Mips::T2)
445 .Case("t3", Mips::T3)
446 .Case("t4", Mips::T4)
447 .Case("t5", Mips::T5)
448 .Case("t6", Mips::T6)
449 .Case("t7", Mips::T7)
450 .Case("t8", Mips::T8)
451 .Case("t9", Mips::T9)
452 .Case("at", Mips::AT)
453 .Case("fcc0", Mips::FCC0)
454 .Default(-1);
455 else
456 CC = StringSwitch<unsigned>(Name)
457 .Case("zero", Mips::ZERO_64)
458 .Case("at", Mips::AT_64)
459 .Case("v0", Mips::V0_64)
460 .Case("v1", Mips::V1_64)
461 .Case("a0", Mips::A0_64)
462 .Case("a1", Mips::A1_64)
463 .Case("a2", Mips::A2_64)
464 .Case("a3", Mips::A3_64)
465 .Case("a4", Mips::T0_64)
466 .Case("a5", Mips::T1_64)
467 .Case("a6", Mips::T2_64)
468 .Case("a7", Mips::T3_64)
469 .Case("t4", Mips::T4_64)
470 .Case("t5", Mips::T5_64)
471 .Case("t6", Mips::T6_64)
472 .Case("t7", Mips::T7_64)
473 .Case("s0", Mips::S0_64)
474 .Case("s1", Mips::S1_64)
475 .Case("s2", Mips::S2_64)
476 .Case("s3", Mips::S3_64)
477 .Case("s4", Mips::S4_64)
478 .Case("s5", Mips::S5_64)
479 .Case("s6", Mips::S6_64)
480 .Case("s7", Mips::S7_64)
481 .Case("t8", Mips::T8_64)
482 .Case("t9", Mips::T9_64)
483 .Case("kt0", Mips::K0_64)
484 .Case("kt1", Mips::K1_64)
485 .Case("gp", Mips::GP_64)
486 .Case("sp", Mips::SP_64)
487 .Case("fp", Mips::FP_64)
488 .Case("s8", Mips::FP_64)
489 .Case("ra", Mips::RA_64)
490 .Default(-1);
Jack Carterec65be82012-09-05 23:34:03 +0000491
David Chisnall572e1bd2012-10-09 16:27:43 +0000492 if (CC != -1)
Jack Carterec65be82012-09-05 23:34:03 +0000493 return CC;
Jack Carterec65be82012-09-05 23:34:03 +0000494
Jack Carterf740d6e2012-09-07 00:23:42 +0000495 if (Name[0] == 'f') {
496 StringRef NumString = Name.substr(1);
497 unsigned IntVal;
498 if( NumString.getAsInteger(10, IntVal))
Jack Carter9d577c82012-10-04 04:03:53 +0000499 return -1; // not integer
Jack Carterf740d6e2012-09-07 00:23:42 +0000500 if (IntVal > 31)
501 return -1;
502
503 FpFormatTy Format = getFpFormat();
504
505 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
506 return getReg(Mips::FGR32RegClassID, IntVal);
507 if (Format == FP_FORMAT_D) {
508 if(isFP64()) {
509 return getReg(Mips::FGR64RegClassID, IntVal);
510 }
Jack Carter9d577c82012-10-04 04:03:53 +0000511 // only even numbers available as register pairs
Jack Carterf740d6e2012-09-07 00:23:42 +0000512 if (( IntVal > 31) || (IntVal%2 != 0))
513 return -1;
514 return getReg(Mips::AFGR64RegClassID, IntVal/2);
515 }
516 }
517
Jack Carterec65be82012-09-05 23:34:03 +0000518 return -1;
519}
Jack Carterf740d6e2012-09-07 00:23:42 +0000520void MipsAsmParser::setDefaultFpFormat() {
521
522 if (isMips64() || isFP64())
523 FpFormat = FP_FORMAT_D;
524 else
525 FpFormat = FP_FORMAT_S;
526}
527
528bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
529
530 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
531 .Case("ldxc1", true)
532 .Case("ldc1", true)
533 .Case("sdxc1", true)
534 .Case("sdc1", true)
535 .Default(false);
536
537 return IsDouble;
538}
539void MipsAsmParser::setFpFormat(StringRef Format) {
540
541 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
542 .Case(".s", FP_FORMAT_S)
543 .Case(".d", FP_FORMAT_D)
544 .Case(".l", FP_FORMAT_L)
545 .Case(".w", FP_FORMAT_W)
546 .Default(FP_FORMAT_NONE);
547}
Jack Carterec65be82012-09-05 23:34:03 +0000548
Jack Carter30116cd2012-10-04 02:29:46 +0000549bool MipsAssemblerOptions::setATReg(unsigned Reg) {
550 if (Reg > 31)
551 return false;
552
553 aTReg = Reg;
554 return true;
555}
556
557unsigned MipsAsmParser::getATReg() {
Jack Carter10d5ff62012-10-05 23:55:28 +0000558 unsigned Reg = Options.getATRegNum();
Jack Carter30116cd2012-10-04 02:29:46 +0000559 if (isMips64())
560 return getReg(Mips::CPU64RegsRegClassID,Reg);
Jack Carter10d5ff62012-10-05 23:55:28 +0000561
562 return getReg(Mips::CPURegsRegClassID,Reg);
Jack Carter30116cd2012-10-04 02:29:46 +0000563}
564
565unsigned MipsAsmParser::getReg(int RC,int RegNo) {
Jack Carterec65be82012-09-05 23:34:03 +0000566 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
567}
568
Jack Carter30116cd2012-10-04 02:29:46 +0000569int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
Jack Carterec65be82012-09-05 23:34:03 +0000570
571 if (Mnemonic.lower() == "rdhwr") {
Jack Carter9d577c82012-10-04 04:03:53 +0000572 // at the moment only hwreg29 is supported
Jack Carterec65be82012-09-05 23:34:03 +0000573 if (RegNum != 29)
574 return -1;
575 return Mips::HWR29;
576 }
577
578 if (RegNum > 31)
579 return -1;
580
David Chisnall572e1bd2012-10-09 16:27:43 +0000581 // MIPS64 registers are numbered 1 after the 32-bit equivalents
582 return getReg(Mips::CPURegsRegClassID, RegNum) + isMips64();
Jack Carterec65be82012-09-05 23:34:03 +0000583}
584
585int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
586 const AsmToken &Tok = Parser.getTok();
587 int RegNum = -1;
588
589 if (Tok.is(AsmToken::Identifier)) {
590 std::string lowerCase = Tok.getString().lower();
591 RegNum = matchRegisterName(lowerCase);
592 } else if (Tok.is(AsmToken::Integer))
Jack Carter9d577c82012-10-04 04:03:53 +0000593 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carter6b96c3f2012-09-06 20:00:02 +0000594 Mnemonic.lower());
Jack Carterf740d6e2012-09-07 00:23:42 +0000595 else
596 return RegNum; //error
Jack Carter9d577c82012-10-04 04:03:53 +0000597 // 64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
Jack Carterf740d6e2012-09-07 00:23:42 +0000598 if (isMips64() && RegNum == Mips::ZERO_64) {
599 if (Mnemonic.find("ddiv") != StringRef::npos)
600 RegNum = Mips::ZERO;
601 }
Jack Carterec65be82012-09-05 23:34:03 +0000602 return RegNum;
603}
604
Rafael Espindolafddf8042012-01-11 03:56:41 +0000605bool MipsAsmParser::
Jack Carterec65be82012-09-05 23:34:03 +0000606 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
607 StringRef Mnemonic){
608
609 SMLoc S = Parser.getTok().getLoc();
610 int RegNo = -1;
Jack Carterf740d6e2012-09-07 00:23:42 +0000611
Jack Carter9d577c82012-10-04 04:03:53 +0000612 // FIXME: we should make a more generic method for CCR
Jack Carterf740d6e2012-09-07 00:23:42 +0000613 if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
614 && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
Jack Carter9d577c82012-10-04 04:03:53 +0000615 RegNo = Parser.getTok().getIntVal(); // get the int value
616 // at the moment only fcc0 is supported
Jack Carterf740d6e2012-09-07 00:23:42 +0000617 if (RegNo == 0)
618 RegNo = Mips::FCC0;
619 } else
620 RegNo = tryParseRegister(Mnemonic);
Jack Carterec65be82012-09-05 23:34:03 +0000621 if (RegNo == -1)
622 return true;
623
624 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterf740d6e2012-09-07 00:23:42 +0000625 Parser.getTok().getLoc()));
Jack Carterec65be82012-09-05 23:34:03 +0000626 Parser.Lex(); // Eat register token.
627 return false;
628}
629
630bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
631 StringRef Mnemonic) {
Jack Carter9d577c82012-10-04 04:03:53 +0000632 // Check if the current operand has a custom associated parser, if so, try to
633 // custom parse the operand, or fallback to the general approach.
Jack Carterec65be82012-09-05 23:34:03 +0000634 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
635 if (ResTy == MatchOperand_Success)
636 return false;
637 // If there wasn't a custom match, try the generic matcher below. Otherwise,
638 // there was a match, but an error occurred, in which case, just return that
639 // the operand parsing failed.
640 if (ResTy == MatchOperand_ParseFail)
641 return true;
642
643 switch (getLexer().getKind()) {
644 default:
645 Error(Parser.getTok().getLoc(), "unexpected token in operand");
646 return true;
647 case AsmToken::Dollar: {
Jack Carter9d577c82012-10-04 04:03:53 +0000648 // parse register
Jack Carterec65be82012-09-05 23:34:03 +0000649 SMLoc S = Parser.getTok().getLoc();
650 Parser.Lex(); // Eat dollar token.
Jack Carter9d577c82012-10-04 04:03:53 +0000651 // parse register operand
652 if (!tryParseRegisterOperand(Operands, Mnemonic)) {
Jack Carterec65be82012-09-05 23:34:03 +0000653 if (getLexer().is(AsmToken::LParen)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000654 // check if it is indexed addressing operand
Jack Carterec65be82012-09-05 23:34:03 +0000655 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carter9d577c82012-10-04 04:03:53 +0000656 Parser.Lex(); // eat parenthesis
Jack Carterec65be82012-09-05 23:34:03 +0000657 if (getLexer().isNot(AsmToken::Dollar))
658 return true;
659
Jack Carter9d577c82012-10-04 04:03:53 +0000660 Parser.Lex(); // eat dollar
661 if (tryParseRegisterOperand(Operands, Mnemonic))
Jack Carterec65be82012-09-05 23:34:03 +0000662 return true;
663
664 if (!getLexer().is(AsmToken::RParen))
665 return true;
666
667 S = Parser.getTok().getLoc();
668 Operands.push_back(MipsOperand::CreateToken(")", S));
669 Parser.Lex();
670 }
671 return false;
672 }
Jack Carter9d577c82012-10-04 04:03:53 +0000673 // maybe it is a symbol reference
Jack Carterec65be82012-09-05 23:34:03 +0000674 StringRef Identifier;
675 if (Parser.ParseIdentifier(Identifier))
676 return true;
677
Jack Carter6b96c3f2012-09-06 20:00:02 +0000678 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000679
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000680 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterec65be82012-09-05 23:34:03 +0000681
682 // Otherwise create a symbol ref.
Jack Carter6b96c3f2012-09-06 20:00:02 +0000683 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterec65be82012-09-05 23:34:03 +0000684 getContext());
685
686 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
687 return false;
688 }
689 case AsmToken::Identifier:
690 case AsmToken::LParen:
691 case AsmToken::Minus:
692 case AsmToken::Plus:
693 case AsmToken::Integer:
694 case AsmToken::String: {
695 // quoted label names
696 const MCExpr *IdVal;
697 SMLoc S = Parser.getTok().getLoc();
698 if (getParser().ParseExpression(IdVal))
699 return true;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000700 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000701 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
702 return false;
703 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000704 case AsmToken::Percent: {
Jack Carter9d577c82012-10-04 04:03:53 +0000705 // it is a symbol reference or constant expression
Jack Carter6b96c3f2012-09-06 20:00:02 +0000706 const MCExpr *IdVal;
Jack Carter9d577c82012-10-04 04:03:53 +0000707 SMLoc S = Parser.getTok().getLoc(); // start location of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000708 if (parseRelocOperand(IdVal))
709 return true;
710
711 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
712
713 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
714 return false;
Jack Carter30116cd2012-10-04 02:29:46 +0000715 } // case AsmToken::Percent
716 } // switch(getLexer().getKind())
Rafael Espindolafddf8042012-01-11 03:56:41 +0000717 return true;
718}
719
Jack Carter6b96c3f2012-09-06 20:00:02 +0000720bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
721
Jack Carter30116cd2012-10-04 02:29:46 +0000722 Parser.Lex(); // eat % token
Jack Carter9d577c82012-10-04 04:03:53 +0000723 const AsmToken &Tok = Parser.getTok(); // get next token, operation
Jack Carter6b96c3f2012-09-06 20:00:02 +0000724 if (Tok.isNot(AsmToken::Identifier))
725 return true;
726
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000727 std::string Str = Tok.getIdentifier().str();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000728
Jack Carter9d577c82012-10-04 04:03:53 +0000729 Parser.Lex(); // eat identifier
Jack Carter30116cd2012-10-04 02:29:46 +0000730 // now make expression from the rest of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000731 const MCExpr *IdVal;
732 SMLoc EndLoc;
733
734 if (getLexer().getKind() == AsmToken::LParen) {
735 while (1) {
Jack Carter30116cd2012-10-04 02:29:46 +0000736 Parser.Lex(); // eat '(' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000737 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carter30116cd2012-10-04 02:29:46 +0000738 Parser.Lex(); // eat % token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000739 const AsmToken &nextTok = Parser.getTok();
740 if (nextTok.isNot(AsmToken::Identifier))
741 return true;
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000742 Str += "(%";
743 Str += nextTok.getIdentifier();
Jack Carter30116cd2012-10-04 02:29:46 +0000744 Parser.Lex(); // eat identifier
Jack Carter6b96c3f2012-09-06 20:00:02 +0000745 if (getLexer().getKind() != AsmToken::LParen)
746 return true;
747 } else
748 break;
749 }
750 if (getParser().ParseParenExpression(IdVal,EndLoc))
751 return true;
752
753 while (getLexer().getKind() == AsmToken::RParen)
Jack Carter30116cd2012-10-04 02:29:46 +0000754 Parser.Lex(); // eat ')' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000755
756 } else
Jack Carter30116cd2012-10-04 02:29:46 +0000757 return true; // parenthesis must follow reloc operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000758
Jack Carter30116cd2012-10-04 02:29:46 +0000759 // Check the type of the expression
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000760 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000761 // it's a constant, evaluate lo or hi value
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000762 int Val = MCE->getValue();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000763 if (Str == "lo") {
764 Val = Val & 0xffff;
765 } else if (Str == "hi") {
766 Val = (Val & 0xffff0000) >> 16;
767 }
768 Res = MCConstantExpr::Create(Val, getContext());
769 return false;
770 }
771
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000772 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter30116cd2012-10-04 02:29:46 +0000773 // it's a symbol, create symbolic expression from symbol
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000774 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000775 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
776 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
777 return false;
778 }
779 return true;
780}
781
Jack Carterec65be82012-09-05 23:34:03 +0000782bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
783 SMLoc &EndLoc) {
784
785 StartLoc = Parser.getTok().getLoc();
786 RegNo = tryParseRegister("");
787 EndLoc = Parser.getTok().getLoc();
788 return (RegNo == (unsigned)-1);
789}
790
Jack Carter6b96c3f2012-09-06 20:00:02 +0000791bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
792
793 SMLoc S;
794
795 switch(getLexer().getKind()) {
796 default:
797 return true;
798 case AsmToken::Integer:
799 case AsmToken::Minus:
800 case AsmToken::Plus:
801 return (getParser().ParseExpression(Res));
Jack Carterf740d6e2012-09-07 00:23:42 +0000802 case AsmToken::Percent:
Jack Carter6b96c3f2012-09-06 20:00:02 +0000803 return parseRelocOperand(Res);
Jack Carter6b96c3f2012-09-06 20:00:02 +0000804 case AsmToken::LParen:
Jack Carter30116cd2012-10-04 02:29:46 +0000805 return false; // it's probably assuming 0
Jack Carter6b96c3f2012-09-06 20:00:02 +0000806 }
807 return true;
808}
809
Jack Carterec65be82012-09-05 23:34:03 +0000810MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
811 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000812
813 const MCExpr *IdVal = 0;
814 SMLoc S;
Jack Carter30116cd2012-10-04 02:29:46 +0000815 // first operand is the offset
Jack Carter6b96c3f2012-09-06 20:00:02 +0000816 S = Parser.getTok().getLoc();
817
818 if (parseMemOffset(IdVal))
819 return MatchOperand_ParseFail;
820
Jack Carter30116cd2012-10-04 02:29:46 +0000821 const AsmToken &Tok = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000822 if (Tok.isNot(AsmToken::LParen)) {
823 Error(Parser.getTok().getLoc(), "'(' expected");
824 return MatchOperand_ParseFail;
825 }
826
827 Parser.Lex(); // Eat '(' token.
828
829 const AsmToken &Tok1 = Parser.getTok(); //get next token
830 if (Tok1.is(AsmToken::Dollar)) {
831 Parser.Lex(); // Eat '$' token.
832 if (tryParseRegisterOperand(Operands,"")) {
833 Error(Parser.getTok().getLoc(), "unexpected token in operand");
834 return MatchOperand_ParseFail;
835 }
836
837 } else {
Jack Carter30116cd2012-10-04 02:29:46 +0000838 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carter6b96c3f2012-09-06 20:00:02 +0000839 return MatchOperand_ParseFail;
840 }
841
Jack Carter30116cd2012-10-04 02:29:46 +0000842 const AsmToken &Tok2 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000843 if (Tok2.isNot(AsmToken::RParen)) {
844 Error(Parser.getTok().getLoc(), "')' expected");
845 return MatchOperand_ParseFail;
846 }
847
848 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
849
850 Parser.Lex(); // Eat ')' token.
851
852 if (IdVal == 0)
853 IdVal = MCConstantExpr::Create(0, getContext());
854
Jack Carter30116cd2012-10-04 02:29:46 +0000855 // now replace register operand with the mem operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000856 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
857 int RegNo = op->getReg();
Jack Carter30116cd2012-10-04 02:29:46 +0000858 // remove register from operands
Jack Carter6b96c3f2012-09-06 20:00:02 +0000859 Operands.pop_back();
Jack Carter30116cd2012-10-04 02:29:46 +0000860 // and add memory operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000861 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
862 delete op;
Jack Carterec65be82012-09-05 23:34:03 +0000863 return MatchOperand_Success;
864}
865
Jack Carter6b96c3f2012-09-06 20:00:02 +0000866MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
867
868 MCSymbolRefExpr::VariantKind VK
869 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
870 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
871 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
872 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
873 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
874 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
875 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
876 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
877 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
878 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
879 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
880 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
881 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
882 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
883 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
884 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
885 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
886 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
887 .Default(MCSymbolRefExpr::VK_None);
888
889 return VK;
890}
891
Benjamin Kramer1ac45872012-09-10 11:52:14 +0000892static int ConvertCcString(StringRef CondString) {
Jack Carterf740d6e2012-09-07 00:23:42 +0000893 int CC = StringSwitch<unsigned>(CondString)
894 .Case(".f", 0)
895 .Case(".un", 1)
896 .Case(".eq", 2)
897 .Case(".ueq", 3)
898 .Case(".olt", 4)
899 .Case(".ult", 5)
900 .Case(".ole", 6)
901 .Case(".ule", 7)
902 .Case(".sf", 8)
903 .Case(".ngle", 9)
904 .Case(".seq", 10)
905 .Case(".ngl", 11)
906 .Case(".lt", 12)
907 .Case(".nge", 13)
908 .Case(".le", 14)
909 .Case(".ngt", 15)
910 .Default(-1);
911
912 return CC;
913}
914
915bool MipsAsmParser::
916parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter30116cd2012-10-04 02:29:46 +0000917 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
918 // split the format
Jack Carterf740d6e2012-09-07 00:23:42 +0000919 size_t Start = Name.find('.'), Next = Name.rfind('.');
920 StringRef Format1 = Name.slice(Start, Next);
Jack Carter30116cd2012-10-04 02:29:46 +0000921 // and add the first format to the operands
Jack Carterf740d6e2012-09-07 00:23:42 +0000922 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carter30116cd2012-10-04 02:29:46 +0000923 // now for the second format
Jack Carterf740d6e2012-09-07 00:23:42 +0000924 StringRef Format2 = Name.slice(Next, StringRef::npos);
925 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
926
Jack Carter30116cd2012-10-04 02:29:46 +0000927 // set the format for the first register
Jack Carterf740d6e2012-09-07 00:23:42 +0000928 setFpFormat(Format1);
929
930 // Read the remaining operands.
931 if (getLexer().isNot(AsmToken::EndOfStatement)) {
932 // Read the first operand.
933 if (ParseOperand(Operands, Name)) {
934 SMLoc Loc = getLexer().getLoc();
935 Parser.EatToEndOfStatement();
936 return Error(Loc, "unexpected token in argument list");
937 }
938
939 if (getLexer().isNot(AsmToken::Comma)) {
940 SMLoc Loc = getLexer().getLoc();
941 Parser.EatToEndOfStatement();
942 return Error(Loc, "unexpected token in argument list");
943
944 }
945 Parser.Lex(); // Eat the comma.
946
947 //set the format for the first register
948 setFpFormat(Format2);
949
950 // Parse and remember the operand.
951 if (ParseOperand(Operands, Name)) {
952 SMLoc Loc = getLexer().getLoc();
953 Parser.EatToEndOfStatement();
954 return Error(Loc, "unexpected token in argument list");
955 }
956 }
957
958 if (getLexer().isNot(AsmToken::EndOfStatement)) {
959 SMLoc Loc = getLexer().getLoc();
960 Parser.EatToEndOfStatement();
961 return Error(Loc, "unexpected token in argument list");
962 }
963
964 Parser.Lex(); // Consume the EndOfStatement
965 return false;
966}
967
Rafael Espindolafddf8042012-01-11 03:56:41 +0000968bool MipsAsmParser::
969ParseInstruction(StringRef Name, SMLoc NameLoc,
970 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter30116cd2012-10-04 02:29:46 +0000971 // floating point instructions: should register be treated as double?
Jack Carterf740d6e2012-09-07 00:23:42 +0000972 if (requestsDoubleOperand(Name)) {
973 setFpFormat(FP_FORMAT_D);
Jack Carterec65be82012-09-05 23:34:03 +0000974 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterf740d6e2012-09-07 00:23:42 +0000975 }
976 else {
977 setDefaultFpFormat();
978 // Create the leading tokens for the mnemonic, split by '.' characters.
979 size_t Start = 0, Next = Name.find('.');
980 StringRef Mnemonic = Name.slice(Start, Next);
981
982 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
983
984 if (Next != StringRef::npos) {
Jack Carter30116cd2012-10-04 02:29:46 +0000985 // there is a format token in mnemonic
986 // StringRef Rest = Name.slice(Next, StringRef::npos);
Jack Carterf740d6e2012-09-07 00:23:42 +0000987 size_t Dot = Name.find('.', Next+1);
988 StringRef Format = Name.slice(Next, Dot);
989 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
990 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
991 else {
992 if (Name.startswith("c.")){
993 // floating point compare, add '.' and immediate represent for cc
994 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
995 int Cc = ConvertCcString(Format);
996 if (Cc == -1) {
997 return Error(NameLoc, "Invalid conditional code");
998 }
999 SMLoc E = SMLoc::getFromPointer(
1000 Parser.getTok().getLoc().getPointer() -1 );
1001 Operands.push_back(MipsOperand::CreateImm(
1002 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1003 } else {
Jack Carter30116cd2012-10-04 02:29:46 +00001004 // trunc, ceil, floor ...
Jack Carterf740d6e2012-09-07 00:23:42 +00001005 return parseMathOperation(Name, NameLoc, Operands);
1006 }
1007
Jack Carter30116cd2012-10-04 02:29:46 +00001008 // the rest is a format
Jack Carterf740d6e2012-09-07 00:23:42 +00001009 Format = Name.slice(Dot, StringRef::npos);
1010 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1011 }
1012
1013 setFpFormat(Format);
1014 }
1015 }
Jack Carterec65be82012-09-05 23:34:03 +00001016
1017 // Read the remaining operands.
1018 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1019 // Read the first operand.
1020 if (ParseOperand(Operands, Name)) {
1021 SMLoc Loc = getLexer().getLoc();
1022 Parser.EatToEndOfStatement();
1023 return Error(Loc, "unexpected token in argument list");
1024 }
1025
1026 while (getLexer().is(AsmToken::Comma) ) {
1027 Parser.Lex(); // Eat the comma.
1028
1029 // Parse and remember the operand.
1030 if (ParseOperand(Operands, Name)) {
1031 SMLoc Loc = getLexer().getLoc();
1032 Parser.EatToEndOfStatement();
1033 return Error(Loc, "unexpected token in argument list");
1034 }
1035 }
1036 }
1037
1038 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1039 SMLoc Loc = getLexer().getLoc();
1040 Parser.EatToEndOfStatement();
1041 return Error(Loc, "unexpected token in argument list");
1042 }
1043
1044 Parser.Lex(); // Consume the EndOfStatement
1045 return false;
Rafael Espindolafddf8042012-01-11 03:56:41 +00001046}
1047
Jack Carter30116cd2012-10-04 02:29:46 +00001048bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1049 SMLoc Loc = getLexer().getLoc();
1050 Parser.EatToEndOfStatement();
1051 return Error(Loc, ErrorMsg);
1052}
1053
1054bool MipsAsmParser::parseSetNoAtDirective() {
1055 // line should look like:
1056 // .set noat
1057 // set at reg to 0
Jack Carter10d5ff62012-10-05 23:55:28 +00001058 Options.setATReg(0);
Jack Carter30116cd2012-10-04 02:29:46 +00001059 // eat noat
1060 Parser.Lex();
1061 // if this is not the end of the statement, report error
1062 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1063 reportParseError("unexpected token in statement");
1064 return false;
1065 }
1066 Parser.Lex(); // Consume the EndOfStatement
1067 return false;
1068}
1069bool MipsAsmParser::parseSetAtDirective() {
1070 // line can be
1071 // .set at - defaults to $1
1072 // or .set at=$reg
1073 getParser().Lex();
1074 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter10d5ff62012-10-05 23:55:28 +00001075 Options.setATReg(1);
Jack Carter30116cd2012-10-04 02:29:46 +00001076 Parser.Lex(); // Consume the EndOfStatement
1077 return false;
1078 } else if (getLexer().is(AsmToken::Equal)) {
1079 getParser().Lex(); //eat '='
1080 if (getLexer().isNot(AsmToken::Dollar)) {
1081 reportParseError("unexpected token in statement");
1082 return false;
1083 }
1084 Parser.Lex(); // eat '$'
1085 if (getLexer().isNot(AsmToken::Integer)) {
1086 reportParseError("unexpected token in statement");
1087 return false;
1088 }
1089 const AsmToken &Reg = Parser.getTok();
Jack Carter10d5ff62012-10-05 23:55:28 +00001090 if (!Options.setATReg(Reg.getIntVal())) {
Jack Carter30116cd2012-10-04 02:29:46 +00001091 reportParseError("unexpected token in statement");
1092 return false;
1093 }
1094 getParser().Lex(); //eat reg
1095
1096 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1097 reportParseError("unexpected token in statement");
1098 return false;
1099 }
1100 Parser.Lex(); // Consume the EndOfStatement
1101 return false;
1102 } else {
1103 reportParseError("unexpected token in statement");
1104 return false;
1105 }
1106}
1107
1108bool MipsAsmParser::parseSetReorderDirective() {
1109 Parser.Lex();
1110 // if this is not the end of the statement, report error
1111 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1112 reportParseError("unexpected token in statement");
1113 return false;
1114 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001115 Options.setReorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001116 Parser.Lex(); // Consume the EndOfStatement
1117 return false;
1118}
1119
1120bool MipsAsmParser::parseSetNoReorderDirective() {
1121 Parser.Lex();
1122 // if this is not the end of the statement, report error
1123 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1124 reportParseError("unexpected token in statement");
1125 return false;
1126 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001127 Options.setNoreorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001128 Parser.Lex(); // Consume the EndOfStatement
1129 return false;
1130}
1131
1132bool MipsAsmParser::parseSetMacroDirective() {
1133 Parser.Lex();
1134 // if this is not the end of the statement, report error
1135 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1136 reportParseError("unexpected token in statement");
1137 return false;
1138 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001139 Options.setMacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001140 Parser.Lex(); // Consume the EndOfStatement
1141 return false;
1142}
1143
1144bool MipsAsmParser::parseSetNoMacroDirective() {
1145 Parser.Lex();
1146 // if this is not the end of the statement, report error
1147 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1148 reportParseError("`noreorder' must be set before `nomacro'");
1149 return false;
1150 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001151 if (Options.isReorder()) {
Jack Carter30116cd2012-10-04 02:29:46 +00001152 reportParseError("`noreorder' must be set before `nomacro'");
1153 return false;
1154 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001155 Options.setNomacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001156 Parser.Lex(); // Consume the EndOfStatement
1157 return false;
1158}
1159bool MipsAsmParser::parseDirectiveSet() {
1160
1161 // get next token
1162 const AsmToken &Tok = Parser.getTok();
1163
1164 if (Tok.getString() == "noat") {
1165 return parseSetNoAtDirective();
1166 } else if (Tok.getString() == "at") {
1167 return parseSetAtDirective();
1168 } else if (Tok.getString() == "reorder") {
1169 return parseSetReorderDirective();
1170 } else if (Tok.getString() == "noreorder") {
1171 return parseSetNoReorderDirective();
1172 } else if (Tok.getString() == "macro") {
1173 return parseSetMacroDirective();
1174 } else if (Tok.getString() == "nomacro") {
1175 return parseSetNoMacroDirective();
1176 } else if (Tok.getString() == "nomips16") {
1177 // ignore this directive for now
1178 Parser.EatToEndOfStatement();
1179 return false;
1180 } else if (Tok.getString() == "nomicromips") {
1181 // ignore this directive for now
1182 Parser.EatToEndOfStatement();
1183 return false;
1184 }
1185 return true;
1186}
1187
1188bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carteracbea452012-09-07 00:48:02 +00001189
1190 if (DirectiveID.getString() == ".ent") {
Jack Carter30116cd2012-10-04 02:29:46 +00001191 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001192 Parser.Lex();
1193 return false;
1194 }
1195
1196 if (DirectiveID.getString() == ".end") {
Jack Carter30116cd2012-10-04 02:29:46 +00001197 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001198 Parser.Lex();
1199 return false;
1200 }
1201
1202 if (DirectiveID.getString() == ".frame") {
Jack Carter30116cd2012-10-04 02:29:46 +00001203 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001204 Parser.EatToEndOfStatement();
1205 return false;
1206 }
1207
1208 if (DirectiveID.getString() == ".set") {
Jack Carter30116cd2012-10-04 02:29:46 +00001209 return parseDirectiveSet();
Jack Carteracbea452012-09-07 00:48:02 +00001210 }
1211
1212 if (DirectiveID.getString() == ".fmask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001213 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001214 Parser.EatToEndOfStatement();
1215 return false;
1216 }
1217
1218 if (DirectiveID.getString() == ".mask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001219 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001220 Parser.EatToEndOfStatement();
1221 return false;
1222 }
1223
1224 if (DirectiveID.getString() == ".gpword") {
Jack Carter30116cd2012-10-04 02:29:46 +00001225 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001226 Parser.EatToEndOfStatement();
1227 return false;
1228 }
1229
Rafael Espindolafddf8042012-01-11 03:56:41 +00001230 return true;
1231}
1232
Rafael Espindolafddf8042012-01-11 03:56:41 +00001233extern "C" void LLVMInitializeMipsAsmParser() {
1234 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1235 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1236 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1237 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1238}
Jack Carterec65be82012-09-05 23:34:03 +00001239
1240#define GET_REGISTER_MATCHER
1241#define GET_MATCHER_IMPLEMENTATION
1242#include "MipsGenAsmMatcher.inc"