blob: 39a53aeba72f3c67f5a802b9c32a456ce3b6ccca [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"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000016#include "llvm/MC/MCParser/MCAsmLexer.h"
17#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterec65be82012-09-05 23:34:03 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCSubtargetInfo.h"
20#include "llvm/MC/MCSymbol.h"
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000021#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
Chad Rosier84125ca2012-10-13 00:26:04 +000070 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindolafddf8042012-01-11 03:56:41 +000071 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier84125ca2012-10-13 00:26:04 +000072 MCStreamer &Out, unsigned &ErrorInfo,
73 bool MatchingInlineAsm);
Rafael Espindolafddf8042012-01-11 03:56:41 +000074
75 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
76
Chad Rosier6a020a72012-10-25 20:41:34 +000077 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
78 SMLoc NameLoc,
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000079 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindolafddf8042012-01-11 03:56:41 +000080
Jack Carterf740d6e2012-09-07 00:23:42 +000081 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
82 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
83
Rafael Espindolafddf8042012-01-11 03:56:41 +000084 bool ParseDirective(AsmToken DirectiveID);
85
Jack Carterec65be82012-09-05 23:34:03 +000086 MipsAsmParser::OperandMatchResultTy
Jack Carterec3199f2013-01-12 01:03:14 +000087 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
88
89 MipsAsmParser::OperandMatchResultTy
90 parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
91
92 MipsAsmParser::OperandMatchResultTy
93 parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
94
95 MipsAsmParser::OperandMatchResultTy
96 parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
97
98 MipsAsmParser::OperandMatchResultTy
99 parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
100
101 MipsAsmParser::OperandMatchResultTy
102 parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Chad Rosier038f3e32012-09-03 18:47:45 +0000103
Jack Carterec65be82012-09-05 23:34:03 +0000104 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
105 StringRef Mnemonic);
106
Jack Carterec3199f2013-01-12 01:03:14 +0000107 int tryParseRegister(bool is64BitReg);
Jack Carterec65be82012-09-05 23:34:03 +0000108
109 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carterec3199f2013-01-12 01:03:14 +0000110 bool is64BitReg);
Jack Carterec65be82012-09-05 23:34:03 +0000111
Jack Carter9d577c82012-10-04 04:03:53 +0000112 bool needsExpansion(MCInst &Inst);
113
114 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000115 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9d577c82012-10-04 04:03:53 +0000116 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000117 SmallVectorImpl<MCInst> &Instructions);
Jack Carter2f68b312012-10-09 23:29:45 +0000118 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
119 SmallVectorImpl<MCInst> &Instructions);
120 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
121 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30116cd2012-10-04 02:29:46 +0000122 bool reportParseError(StringRef ErrorMsg);
123
Jack Carter6b96c3f2012-09-06 20:00:02 +0000124 bool parseMemOffset(const MCExpr *&Res);
Jack Carterec3199f2013-01-12 01:03:14 +0000125 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter30116cd2012-10-04 02:29:46 +0000126
127 bool parseDirectiveSet();
128
129 bool parseSetAtDirective();
130 bool parseSetNoAtDirective();
131 bool parseSetMacroDirective();
132 bool parseSetNoMacroDirective();
133 bool parseSetReorderDirective();
134 bool parseSetNoReorderDirective();
135
Jack Carter6b96c3f2012-09-06 20:00:02 +0000136 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Carterf740d6e2012-09-07 00:23:42 +0000137
Jack Carterec65be82012-09-05 23:34:03 +0000138 bool isMips64() const {
139 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
140 }
141
Jack Carterf740d6e2012-09-07 00:23:42 +0000142 bool isFP64() const {
143 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
144 }
145
Jack Carterec3199f2013-01-12 01:03:14 +0000146 int matchRegisterName(StringRef Symbol, bool is64BitReg);
Jack Carterec65be82012-09-05 23:34:03 +0000147
Jack Carterec3199f2013-01-12 01:03:14 +0000148 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterec65be82012-09-05 23:34:03 +0000149
Jack Carterf740d6e2012-09-07 00:23:42 +0000150 void setFpFormat(FpFormatTy Format) {
151 FpFormat = Format;
152 }
153
154 void setDefaultFpFormat();
155
156 void setFpFormat(StringRef Format);
157
158 FpFormatTy getFpFormat() {return FpFormat;}
159
160 bool requestsDoubleOperand(StringRef Mnemonic);
161
Jack Carterec65be82012-09-05 23:34:03 +0000162 unsigned getReg(int RC,int RegNo);
Chad Rosier038f3e32012-09-03 18:47:45 +0000163
Jack Carter30116cd2012-10-04 02:29:46 +0000164 unsigned getATReg();
Rafael Espindolafddf8042012-01-11 03:56:41 +0000165public:
166 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterec65be82012-09-05 23:34:03 +0000167 : MCTargetAsmParser(), STI(sti), Parser(parser) {
168 // Initialize the set of available features.
169 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindolafddf8042012-01-11 03:56:41 +0000170 }
171
Jack Carterec65be82012-09-05 23:34:03 +0000172 MCAsmParser &getParser() const { return Parser; }
173 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
174
Rafael Espindolafddf8042012-01-11 03:56:41 +0000175};
176}
177
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000178namespace {
179
180/// MipsOperand - Instances of this class represent a parsed Mips machine
181/// instruction.
182class MipsOperand : public MCParsedAsmOperand {
Jack Carterec65be82012-09-05 23:34:03 +0000183
Jack Carterec3199f2013-01-12 01:03:14 +0000184public:
185 enum RegisterKind {
186 Kind_None,
187 Kind_CPURegs,
188 Kind_CPU64Regs,
189 Kind_HWRegs,
190 Kind_HW64Regs,
191 Kind_FGR32Regs,
192 Kind_FGR64Regs,
193 Kind_AFGR32Regs,
194 Kind_CCRRegs
195 };
196
197private:
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000198 enum KindTy {
199 k_CondCode,
200 k_CoprocNum,
201 k_Immediate,
202 k_Memory,
203 k_PostIndexRegister,
204 k_Register,
205 k_Token
206 } Kind;
207
208 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterec65be82012-09-05 23:34:03 +0000209
210 union {
211 struct {
212 const char *Data;
213 unsigned Length;
214 } Tok;
215
216 struct {
217 unsigned RegNum;
Jack Carterec3199f2013-01-12 01:03:14 +0000218 RegisterKind Kind;
Jack Carterec65be82012-09-05 23:34:03 +0000219 } Reg;
220
221 struct {
222 const MCExpr *Val;
223 } Imm;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000224
225 struct {
226 unsigned Base;
227 const MCExpr *Off;
228 } Mem;
Jack Carterec65be82012-09-05 23:34:03 +0000229 };
230
231 SMLoc StartLoc, EndLoc;
232
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000233public:
234 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000235 assert(N == 1 && "Invalid number of operands!");
236 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000237 }
Jack Carterec65be82012-09-05 23:34:03 +0000238
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000239 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterec65be82012-09-05 23:34:03 +0000240 // Add as immediate when possible. Null MCExpr = 0.
241 if (Expr == 0)
242 Inst.addOperand(MCOperand::CreateImm(0));
243 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
244 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
245 else
246 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000247 }
Jack Carterec65be82012-09-05 23:34:03 +0000248
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000249 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000250 assert(N == 1 && "Invalid number of operands!");
251 const MCExpr *Expr = getImm();
252 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000253 }
Jack Carterec65be82012-09-05 23:34:03 +0000254
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000255 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000256 assert(N == 2 && "Invalid number of operands!");
257
258 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
259
260 const MCExpr *Expr = getMemOff();
261 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000262 }
263
264 bool isReg() const { return Kind == k_Register; }
265 bool isImm() const { return Kind == k_Immediate; }
266 bool isToken() const { return Kind == k_Token; }
267 bool isMem() const { return Kind == k_Memory; }
268
269 StringRef getToken() const {
270 assert(Kind == k_Token && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000271 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000272 }
273
274 unsigned getReg() const {
275 assert((Kind == k_Register) && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000276 return Reg.RegNum;
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000277 }
278
Jack Carterec3199f2013-01-12 01:03:14 +0000279 void setRegKind(RegisterKind RegKind) {
280 assert((Kind == k_Register) && "Invalid access!");
281 Reg.Kind = RegKind;
282 }
283
Jack Carterec65be82012-09-05 23:34:03 +0000284 const MCExpr *getImm() const {
285 assert((Kind == k_Immediate) && "Invalid access!");
286 return Imm.Val;
287 }
288
Jack Carter6b96c3f2012-09-06 20:00:02 +0000289 unsigned getMemBase() const {
290 assert((Kind == k_Memory) && "Invalid access!");
291 return Mem.Base;
292 }
293
294 const MCExpr *getMemOff() const {
295 assert((Kind == k_Memory) && "Invalid access!");
296 return Mem.Off;
297 }
298
Jack Carterec65be82012-09-05 23:34:03 +0000299 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
300 MipsOperand *Op = new MipsOperand(k_Token);
301 Op->Tok.Data = Str.data();
302 Op->Tok.Length = Str.size();
303 Op->StartLoc = S;
304 Op->EndLoc = S;
305 return Op;
306 }
307
308 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
309 MipsOperand *Op = new MipsOperand(k_Register);
310 Op->Reg.RegNum = RegNum;
311 Op->StartLoc = S;
312 Op->EndLoc = E;
313 return Op;
314 }
315
316 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
317 MipsOperand *Op = new MipsOperand(k_Immediate);
318 Op->Imm.Val = Val;
319 Op->StartLoc = S;
320 Op->EndLoc = E;
321 return Op;
322 }
323
Jack Carter6b96c3f2012-09-06 20:00:02 +0000324 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
325 SMLoc S, SMLoc E) {
326 MipsOperand *Op = new MipsOperand(k_Memory);
327 Op->Mem.Base = Base;
328 Op->Mem.Off = Off;
329 Op->StartLoc = S;
330 Op->EndLoc = E;
331 return Op;
332 }
333
Jack Carterec3199f2013-01-12 01:03:14 +0000334 bool isCPURegsAsm() const {
NAKAMURA Takumia96a96c2013-01-12 15:19:10 +0000335 return Kind == k_Register && Reg.Kind == Kind_CPURegs;
Jack Carterec3199f2013-01-12 01:03:14 +0000336 }
337 void addCPURegsAsmOperands(MCInst &Inst, unsigned N) const {
338 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
339 }
340
341 bool isCPU64RegsAsm() const {
NAKAMURA Takumia96a96c2013-01-12 15:19:10 +0000342 return Kind == k_Register && Reg.Kind == Kind_CPU64Regs;
Jack Carterec3199f2013-01-12 01:03:14 +0000343 }
344 void addCPU64RegsAsmOperands(MCInst &Inst, unsigned N) const {
345 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
346 }
347
348 bool isHWRegsAsm() const {
349 assert((Kind == k_Register) && "Invalid access!");
350 return Reg.Kind == Kind_HWRegs;
351 }
352 void addHWRegsAsmOperands(MCInst &Inst, unsigned N) const {
353 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
354 }
355
356 bool isHW64RegsAsm() const {
357 assert((Kind == k_Register) && "Invalid access!");
358 return Reg.Kind == Kind_HW64Regs;
359 }
360 void addHW64RegsAsmOperands(MCInst &Inst, unsigned N) const {
361 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
362 }
363
364 void addCCRAsmOperands(MCInst &Inst, unsigned N) const {
365 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
366 }
367
368 bool isCCRAsm() const {
369 assert((Kind == k_Register) && "Invalid access!");
370 return Reg.Kind == Kind_CCRRegs;
371 }
372
Jack Carterec65be82012-09-05 23:34:03 +0000373 /// getStartLoc - Get the location of the first token of this operand.
374 SMLoc getStartLoc() const { return StartLoc; }
375 /// getEndLoc - Get the location of the last token of this operand.
376 SMLoc getEndLoc() const { return EndLoc; }
377
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000378 virtual void print(raw_ostream &OS) const {
379 llvm_unreachable("unimplemented!");
380 }
381};
382}
383
Jack Carter9d577c82012-10-04 04:03:53 +0000384bool MipsAsmParser::needsExpansion(MCInst &Inst) {
385
386 switch(Inst.getOpcode()) {
387 case Mips::LoadImm32Reg:
Jack Carter2f68b312012-10-09 23:29:45 +0000388 case Mips::LoadAddr32Imm:
389 case Mips::LoadAddr32Reg:
Jack Carter9d577c82012-10-04 04:03:53 +0000390 return true;
391 default:
392 return false;
393 }
394}
Jack Carter2490dc62012-10-06 00:53:28 +0000395
Jack Carter9d577c82012-10-04 04:03:53 +0000396void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000397 SmallVectorImpl<MCInst> &Instructions){
Jack Carter9d577c82012-10-04 04:03:53 +0000398 switch(Inst.getOpcode()) {
399 case Mips::LoadImm32Reg:
400 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carter2f68b312012-10-09 23:29:45 +0000401 case Mips::LoadAddr32Imm:
402 return expandLoadAddressImm(Inst,IDLoc,Instructions);
403 case Mips::LoadAddr32Reg:
404 return expandLoadAddressReg(Inst,IDLoc,Instructions);
Jack Carter9d577c82012-10-04 04:03:53 +0000405 }
Jack Carter9d577c82012-10-04 04:03:53 +0000406}
Jack Carter2490dc62012-10-06 00:53:28 +0000407
Jack Carter9d577c82012-10-04 04:03:53 +0000408void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter2f68b312012-10-09 23:29:45 +0000409 SmallVectorImpl<MCInst> &Instructions){
Jack Carter2490dc62012-10-06 00:53:28 +0000410 MCInst tmpInst;
Jack Carter9d577c82012-10-04 04:03:53 +0000411 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter2f68b312012-10-09 23:29:45 +0000412 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter9d577c82012-10-04 04:03:53 +0000413 const MCOperand &RegOp = Inst.getOperand(0);
414 assert(RegOp.isReg() && "expected register operand kind");
415
416 int ImmValue = ImmOp.getImm();
Jack Carter2490dc62012-10-06 00:53:28 +0000417 tmpInst.setLoc(IDLoc);
Jack Carter9d577c82012-10-04 04:03:53 +0000418 if ( 0 <= ImmValue && ImmValue <= 65535) {
Jack Carter2490dc62012-10-06 00:53:28 +0000419 // for 0 <= j <= 65535.
Jack Carter9d577c82012-10-04 04:03:53 +0000420 // li d,j => ori d,$zero,j
Jack Carterec3199f2013-01-12 01:03:14 +0000421 tmpInst.setOpcode(Mips::ORi);
Jack Carter2490dc62012-10-06 00:53:28 +0000422 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
423 tmpInst.addOperand(
Jack Carterec3199f2013-01-12 01:03:14 +0000424 MCOperand::CreateReg(Mips::ZERO));
Jack Carter2490dc62012-10-06 00:53:28 +0000425 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter9d577c82012-10-04 04:03:53 +0000426 Instructions.push_back(tmpInst);
427 } else if ( ImmValue < 0 && ImmValue >= -32768) {
Jack Carter2490dc62012-10-06 00:53:28 +0000428 // for -32768 <= j < 0.
Jack Carter9d577c82012-10-04 04:03:53 +0000429 // li d,j => addiu d,$zero,j
Jack Carterec3199f2013-01-12 01:03:14 +0000430 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter2490dc62012-10-06 00:53:28 +0000431 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
432 tmpInst.addOperand(
Jack Carterec3199f2013-01-12 01:03:14 +0000433 MCOperand::CreateReg(Mips::ZERO));
Jack Carter2490dc62012-10-06 00:53:28 +0000434 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter9d577c82012-10-04 04:03:53 +0000435 Instructions.push_back(tmpInst);
436 } else {
437 // for any other value of j that is representable as a 32-bit integer.
438 // li d,j => lui d,hi16(j)
Jack Carter2f68b312012-10-09 23:29:45 +0000439 // ori d,d,lo16(j)
Jack Carterec3199f2013-01-12 01:03:14 +0000440 tmpInst.setOpcode(Mips::LUi);
Jack Carter2490dc62012-10-06 00:53:28 +0000441 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
442 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter9d577c82012-10-04 04:03:53 +0000443 Instructions.push_back(tmpInst);
Jack Carter2490dc62012-10-06 00:53:28 +0000444 tmpInst.clear();
Jack Carterec3199f2013-01-12 01:03:14 +0000445 tmpInst.setOpcode(Mips::ORi);
Jack Carter2490dc62012-10-06 00:53:28 +0000446 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
447 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
448 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
449 tmpInst.setLoc(IDLoc);
Jack Carter9d577c82012-10-04 04:03:53 +0000450 Instructions.push_back(tmpInst);
451 }
452}
Jack Carter2490dc62012-10-06 00:53:28 +0000453
Jack Carter2f68b312012-10-09 23:29:45 +0000454void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
455 SmallVectorImpl<MCInst> &Instructions){
456 MCInst tmpInst;
457 const MCOperand &ImmOp = Inst.getOperand(2);
458 assert(ImmOp.isImm() && "expected immediate operand kind");
459 const MCOperand &SrcRegOp = Inst.getOperand(1);
460 assert(SrcRegOp.isReg() && "expected register operand kind");
461 const MCOperand &DstRegOp = Inst.getOperand(0);
462 assert(DstRegOp.isReg() && "expected register operand kind");
463 int ImmValue = ImmOp.getImm();
464 if ( -32768 <= ImmValue && ImmValue <= 65535) {
465 //for -32768 <= j <= 65535.
466 //la d,j(s) => addiu d,s,j
Jack Carterec3199f2013-01-12 01:03:14 +0000467 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter2f68b312012-10-09 23:29:45 +0000468 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
469 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
470 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
471 Instructions.push_back(tmpInst);
472 } else {
473 //for any other value of j that is representable as a 32-bit integer.
474 //la d,j(s) => lui d,hi16(j)
475 // ori d,d,lo16(j)
476 // addu d,d,s
Jack Carterec3199f2013-01-12 01:03:14 +0000477 tmpInst.setOpcode(Mips::LUi);
Jack Carter2f68b312012-10-09 23:29:45 +0000478 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
479 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
480 Instructions.push_back(tmpInst);
481 tmpInst.clear();
Jack Carterec3199f2013-01-12 01:03:14 +0000482 tmpInst.setOpcode(Mips::ORi);
Jack Carter2f68b312012-10-09 23:29:45 +0000483 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
484 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
485 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
486 Instructions.push_back(tmpInst);
487 tmpInst.clear();
488 tmpInst.setOpcode(Mips::ADDu);
489 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
490 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
491 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
492 Instructions.push_back(tmpInst);
493 }
494}
495
496void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
497 SmallVectorImpl<MCInst> &Instructions){
498 MCInst tmpInst;
499 const MCOperand &ImmOp = Inst.getOperand(1);
500 assert(ImmOp.isImm() && "expected immediate operand kind");
501 const MCOperand &RegOp = Inst.getOperand(0);
502 assert(RegOp.isReg() && "expected register operand kind");
503 int ImmValue = ImmOp.getImm();
504 if ( -32768 <= ImmValue && ImmValue <= 65535) {
505 //for -32768 <= j <= 65535.
506 //la d,j => addiu d,$zero,j
507 tmpInst.setOpcode(Mips::ADDiu);
508 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
509 tmpInst.addOperand(
Jack Carterec3199f2013-01-12 01:03:14 +0000510 MCOperand::CreateReg(Mips::ZERO));
Jack Carter2f68b312012-10-09 23:29:45 +0000511 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
512 Instructions.push_back(tmpInst);
513 } else {
514 //for any other value of j that is representable as a 32-bit integer.
515 //la d,j => lui d,hi16(j)
516 // ori d,d,lo16(j)
Jack Carterec3199f2013-01-12 01:03:14 +0000517 tmpInst.setOpcode(Mips::LUi);
Jack Carter2f68b312012-10-09 23:29:45 +0000518 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
519 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
520 Instructions.push_back(tmpInst);
521 tmpInst.clear();
Jack Carterec3199f2013-01-12 01:03:14 +0000522 tmpInst.setOpcode(Mips::ORi);
Jack Carter2f68b312012-10-09 23:29:45 +0000523 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
524 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
525 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
526 Instructions.push_back(tmpInst);
527 }
528}
529
Rafael Espindolafddf8042012-01-11 03:56:41 +0000530bool MipsAsmParser::
Chad Rosier84125ca2012-10-13 00:26:04 +0000531MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindolafddf8042012-01-11 03:56:41 +0000532 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier84125ca2012-10-13 00:26:04 +0000533 MCStreamer &Out, unsigned &ErrorInfo,
534 bool MatchingInlineAsm) {
Jack Carterec65be82012-09-05 23:34:03 +0000535 MCInst Inst;
Chad Rosier6e006d32012-10-12 22:53:36 +0000536 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier84125ca2012-10-13 00:26:04 +0000537 MatchingInlineAsm);
Jack Carterec65be82012-09-05 23:34:03 +0000538
539 switch (MatchResult) {
540 default: break;
541 case Match_Success: {
Jack Carter9d577c82012-10-04 04:03:53 +0000542 if (needsExpansion(Inst)) {
Jack Carter2490dc62012-10-06 00:53:28 +0000543 SmallVector<MCInst, 4> Instructions;
Jack Carter9d577c82012-10-04 04:03:53 +0000544 expandInstruction(Inst, IDLoc, Instructions);
545 for(unsigned i =0; i < Instructions.size(); i++){
Jack Carter2490dc62012-10-06 00:53:28 +0000546 Out.EmitInstruction(Instructions[i]);
Jack Carter9d577c82012-10-04 04:03:53 +0000547 }
548 } else {
549 Inst.setLoc(IDLoc);
550 Out.EmitInstruction(Inst);
551 }
Jack Carterec65be82012-09-05 23:34:03 +0000552 return false;
553 }
554 case Match_MissingFeature:
555 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
556 return true;
557 case Match_InvalidOperand: {
558 SMLoc ErrorLoc = IDLoc;
559 if (ErrorInfo != ~0U) {
560 if (ErrorInfo >= Operands.size())
561 return Error(IDLoc, "too few operands for instruction");
562
563 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
564 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
565 }
566
567 return Error(ErrorLoc, "invalid operand for instruction");
568 }
569 case Match_MnemonicFail:
570 return Error(IDLoc, "invalid instruction");
571 }
Rafael Espindolafddf8042012-01-11 03:56:41 +0000572 return true;
573}
574
Jack Carterec3199f2013-01-12 01:03:14 +0000575int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
Jack Carterec65be82012-09-05 23:34:03 +0000576
David Chisnall572e1bd2012-10-09 16:27:43 +0000577 int CC;
Jack Carterec3199f2013-01-12 01:03:14 +0000578 if (!is64BitReg)
David Chisnall572e1bd2012-10-09 16:27:43 +0000579 CC = StringSwitch<unsigned>(Name)
580 .Case("zero", Mips::ZERO)
581 .Case("a0", Mips::A0)
582 .Case("a1", Mips::A1)
583 .Case("a2", Mips::A2)
584 .Case("a3", Mips::A3)
585 .Case("v0", Mips::V0)
586 .Case("v1", Mips::V1)
587 .Case("s0", Mips::S0)
588 .Case("s1", Mips::S1)
589 .Case("s2", Mips::S2)
590 .Case("s3", Mips::S3)
591 .Case("s4", Mips::S4)
592 .Case("s5", Mips::S5)
593 .Case("s6", Mips::S6)
594 .Case("s7", Mips::S7)
595 .Case("k0", Mips::K0)
596 .Case("k1", Mips::K1)
597 .Case("sp", Mips::SP)
598 .Case("fp", Mips::FP)
599 .Case("gp", Mips::GP)
600 .Case("ra", Mips::RA)
601 .Case("t0", Mips::T0)
602 .Case("t1", Mips::T1)
603 .Case("t2", Mips::T2)
604 .Case("t3", Mips::T3)
605 .Case("t4", Mips::T4)
606 .Case("t5", Mips::T5)
607 .Case("t6", Mips::T6)
608 .Case("t7", Mips::T7)
609 .Case("t8", Mips::T8)
610 .Case("t9", Mips::T9)
611 .Case("at", Mips::AT)
612 .Case("fcc0", Mips::FCC0)
613 .Default(-1);
614 else
615 CC = StringSwitch<unsigned>(Name)
616 .Case("zero", Mips::ZERO_64)
617 .Case("at", Mips::AT_64)
618 .Case("v0", Mips::V0_64)
619 .Case("v1", Mips::V1_64)
620 .Case("a0", Mips::A0_64)
621 .Case("a1", Mips::A1_64)
622 .Case("a2", Mips::A2_64)
623 .Case("a3", Mips::A3_64)
624 .Case("a4", Mips::T0_64)
625 .Case("a5", Mips::T1_64)
626 .Case("a6", Mips::T2_64)
627 .Case("a7", Mips::T3_64)
628 .Case("t4", Mips::T4_64)
629 .Case("t5", Mips::T5_64)
630 .Case("t6", Mips::T6_64)
631 .Case("t7", Mips::T7_64)
632 .Case("s0", Mips::S0_64)
633 .Case("s1", Mips::S1_64)
634 .Case("s2", Mips::S2_64)
635 .Case("s3", Mips::S3_64)
636 .Case("s4", Mips::S4_64)
637 .Case("s5", Mips::S5_64)
638 .Case("s6", Mips::S6_64)
639 .Case("s7", Mips::S7_64)
640 .Case("t8", Mips::T8_64)
641 .Case("t9", Mips::T9_64)
642 .Case("kt0", Mips::K0_64)
643 .Case("kt1", Mips::K1_64)
644 .Case("gp", Mips::GP_64)
645 .Case("sp", Mips::SP_64)
646 .Case("fp", Mips::FP_64)
647 .Case("s8", Mips::FP_64)
648 .Case("ra", Mips::RA_64)
649 .Default(-1);
Jack Carterec65be82012-09-05 23:34:03 +0000650
David Chisnall572e1bd2012-10-09 16:27:43 +0000651 if (CC != -1)
Jack Carterec65be82012-09-05 23:34:03 +0000652 return CC;
Jack Carterec65be82012-09-05 23:34:03 +0000653
Jack Carterf740d6e2012-09-07 00:23:42 +0000654 if (Name[0] == 'f') {
655 StringRef NumString = Name.substr(1);
656 unsigned IntVal;
657 if( NumString.getAsInteger(10, IntVal))
Jack Carter9d577c82012-10-04 04:03:53 +0000658 return -1; // not integer
Jack Carterf740d6e2012-09-07 00:23:42 +0000659 if (IntVal > 31)
660 return -1;
661
662 FpFormatTy Format = getFpFormat();
663
664 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
665 return getReg(Mips::FGR32RegClassID, IntVal);
666 if (Format == FP_FORMAT_D) {
667 if(isFP64()) {
668 return getReg(Mips::FGR64RegClassID, IntVal);
669 }
Jack Carter9d577c82012-10-04 04:03:53 +0000670 // only even numbers available as register pairs
Jack Carterf740d6e2012-09-07 00:23:42 +0000671 if (( IntVal > 31) || (IntVal%2 != 0))
672 return -1;
673 return getReg(Mips::AFGR64RegClassID, IntVal/2);
674 }
675 }
676
Jack Carterec65be82012-09-05 23:34:03 +0000677 return -1;
678}
Jack Carterf740d6e2012-09-07 00:23:42 +0000679void MipsAsmParser::setDefaultFpFormat() {
680
681 if (isMips64() || isFP64())
682 FpFormat = FP_FORMAT_D;
683 else
684 FpFormat = FP_FORMAT_S;
685}
686
687bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
688
689 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
690 .Case("ldxc1", true)
691 .Case("ldc1", true)
692 .Case("sdxc1", true)
693 .Case("sdc1", true)
694 .Default(false);
695
696 return IsDouble;
697}
698void MipsAsmParser::setFpFormat(StringRef Format) {
699
700 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
701 .Case(".s", FP_FORMAT_S)
702 .Case(".d", FP_FORMAT_D)
703 .Case(".l", FP_FORMAT_L)
704 .Case(".w", FP_FORMAT_W)
705 .Default(FP_FORMAT_NONE);
706}
Jack Carterec65be82012-09-05 23:34:03 +0000707
Jack Carter30116cd2012-10-04 02:29:46 +0000708bool MipsAssemblerOptions::setATReg(unsigned Reg) {
709 if (Reg > 31)
710 return false;
711
712 aTReg = Reg;
713 return true;
714}
715
716unsigned MipsAsmParser::getATReg() {
Jack Carter10d5ff62012-10-05 23:55:28 +0000717 unsigned Reg = Options.getATRegNum();
Jack Carter30116cd2012-10-04 02:29:46 +0000718 if (isMips64())
719 return getReg(Mips::CPU64RegsRegClassID,Reg);
Jack Carterec3199f2013-01-12 01:03:14 +0000720
Jack Carter10d5ff62012-10-05 23:55:28 +0000721 return getReg(Mips::CPURegsRegClassID,Reg);
Jack Carter30116cd2012-10-04 02:29:46 +0000722}
723
724unsigned MipsAsmParser::getReg(int RC,int RegNo) {
Jack Carterec65be82012-09-05 23:34:03 +0000725 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
726}
727
Jack Carterec3199f2013-01-12 01:03:14 +0000728int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Jack Carterec65be82012-09-05 23:34:03 +0000729
730 if (RegNum > 31)
731 return -1;
732
Jack Carterec3199f2013-01-12 01:03:14 +0000733 return getReg(RegClass, RegNum);
Jack Carterec65be82012-09-05 23:34:03 +0000734}
735
Jack Carterec3199f2013-01-12 01:03:14 +0000736int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterec65be82012-09-05 23:34:03 +0000737 const AsmToken &Tok = Parser.getTok();
738 int RegNum = -1;
739
740 if (Tok.is(AsmToken::Identifier)) {
741 std::string lowerCase = Tok.getString().lower();
Jack Carterec3199f2013-01-12 01:03:14 +0000742 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterec65be82012-09-05 23:34:03 +0000743 } else if (Tok.is(AsmToken::Integer))
Jack Carter9d577c82012-10-04 04:03:53 +0000744 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carterec3199f2013-01-12 01:03:14 +0000745 is64BitReg ? Mips::CPU64RegsRegClassID
746 : Mips::CPURegsRegClassID);
Jack Carterec65be82012-09-05 23:34:03 +0000747 return RegNum;
748}
749
Rafael Espindolafddf8042012-01-11 03:56:41 +0000750bool MipsAsmParser::
Jack Carterec65be82012-09-05 23:34:03 +0000751 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carterec3199f2013-01-12 01:03:14 +0000752 bool is64BitReg){
Jack Carterec65be82012-09-05 23:34:03 +0000753
754 SMLoc S = Parser.getTok().getLoc();
755 int RegNo = -1;
Jack Carterf740d6e2012-09-07 00:23:42 +0000756
Jack Carterec3199f2013-01-12 01:03:14 +0000757 RegNo = tryParseRegister(is64BitReg);
Jack Carterec65be82012-09-05 23:34:03 +0000758 if (RegNo == -1)
759 return true;
760
Jack Carterec3199f2013-01-12 01:03:14 +0000761 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
762 Parser.getTok().getLoc()));
Jack Carterec65be82012-09-05 23:34:03 +0000763 Parser.Lex(); // Eat register token.
764 return false;
765}
766
767bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
768 StringRef Mnemonic) {
Jack Carter9d577c82012-10-04 04:03:53 +0000769 // Check if the current operand has a custom associated parser, if so, try to
770 // custom parse the operand, or fallback to the general approach.
Jack Carterec65be82012-09-05 23:34:03 +0000771 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
772 if (ResTy == MatchOperand_Success)
773 return false;
774 // If there wasn't a custom match, try the generic matcher below. Otherwise,
775 // there was a match, but an error occurred, in which case, just return that
776 // the operand parsing failed.
777 if (ResTy == MatchOperand_ParseFail)
778 return true;
779
780 switch (getLexer().getKind()) {
781 default:
782 Error(Parser.getTok().getLoc(), "unexpected token in operand");
783 return true;
784 case AsmToken::Dollar: {
Jack Carter9d577c82012-10-04 04:03:53 +0000785 // parse register
Jack Carterec65be82012-09-05 23:34:03 +0000786 SMLoc S = Parser.getTok().getLoc();
787 Parser.Lex(); // Eat dollar token.
Jack Carter9d577c82012-10-04 04:03:53 +0000788 // parse register operand
Jack Carterec3199f2013-01-12 01:03:14 +0000789 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterec65be82012-09-05 23:34:03 +0000790 if (getLexer().is(AsmToken::LParen)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000791 // check if it is indexed addressing operand
Jack Carterec65be82012-09-05 23:34:03 +0000792 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carter9d577c82012-10-04 04:03:53 +0000793 Parser.Lex(); // eat parenthesis
Jack Carterec65be82012-09-05 23:34:03 +0000794 if (getLexer().isNot(AsmToken::Dollar))
795 return true;
796
Jack Carter9d577c82012-10-04 04:03:53 +0000797 Parser.Lex(); // eat dollar
Jack Carterec3199f2013-01-12 01:03:14 +0000798 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterec65be82012-09-05 23:34:03 +0000799 return true;
800
801 if (!getLexer().is(AsmToken::RParen))
802 return true;
803
804 S = Parser.getTok().getLoc();
805 Operands.push_back(MipsOperand::CreateToken(")", S));
806 Parser.Lex();
807 }
808 return false;
809 }
Jack Carter9d577c82012-10-04 04:03:53 +0000810 // maybe it is a symbol reference
Jack Carterec65be82012-09-05 23:34:03 +0000811 StringRef Identifier;
812 if (Parser.ParseIdentifier(Identifier))
813 return true;
814
Jack Carterec3199f2013-01-12 01:03:14 +0000815 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000816
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000817 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterec65be82012-09-05 23:34:03 +0000818
819 // Otherwise create a symbol ref.
Jack Carter6b96c3f2012-09-06 20:00:02 +0000820 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterec65be82012-09-05 23:34:03 +0000821 getContext());
822
823 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
824 return false;
825 }
826 case AsmToken::Identifier:
827 case AsmToken::LParen:
828 case AsmToken::Minus:
829 case AsmToken::Plus:
830 case AsmToken::Integer:
831 case AsmToken::String: {
832 // quoted label names
833 const MCExpr *IdVal;
834 SMLoc S = Parser.getTok().getLoc();
Jack Carterec3199f2013-01-12 01:03:14 +0000835 if (getParser().ParseExpression(IdVal))
Jack Carterec65be82012-09-05 23:34:03 +0000836 return true;
Jack Carterec3199f2013-01-12 01:03:14 +0000837 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000838 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
839 return false;
840 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000841 case AsmToken::Percent: {
Jack Carter9d577c82012-10-04 04:03:53 +0000842 // it is a symbol reference or constant expression
Jack Carter6b96c3f2012-09-06 20:00:02 +0000843 const MCExpr *IdVal;
Jack Carter9d577c82012-10-04 04:03:53 +0000844 SMLoc S = Parser.getTok().getLoc(); // start location of the operand
Jack Carterec3199f2013-01-12 01:03:14 +0000845 if (parseRelocOperand(IdVal))
Jack Carter6b96c3f2012-09-06 20:00:02 +0000846 return true;
847
Jack Carterec3199f2013-01-12 01:03:14 +0000848 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
849
Jack Carter6b96c3f2012-09-06 20:00:02 +0000850 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
851 return false;
Jack Carter30116cd2012-10-04 02:29:46 +0000852 } // case AsmToken::Percent
853 } // switch(getLexer().getKind())
Rafael Espindolafddf8042012-01-11 03:56:41 +0000854 return true;
855}
856
Jack Carterec3199f2013-01-12 01:03:14 +0000857bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000858
Jack Carter30116cd2012-10-04 02:29:46 +0000859 Parser.Lex(); // eat % token
Jack Carter9d577c82012-10-04 04:03:53 +0000860 const AsmToken &Tok = Parser.getTok(); // get next token, operation
Jack Carter6b96c3f2012-09-06 20:00:02 +0000861 if (Tok.isNot(AsmToken::Identifier))
862 return true;
863
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000864 std::string Str = Tok.getIdentifier().str();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000865
Jack Carter9d577c82012-10-04 04:03:53 +0000866 Parser.Lex(); // eat identifier
Jack Carter30116cd2012-10-04 02:29:46 +0000867 // now make expression from the rest of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000868 const MCExpr *IdVal;
Jack Carterec3199f2013-01-12 01:03:14 +0000869 SMLoc EndLoc;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000870
871 if (getLexer().getKind() == AsmToken::LParen) {
872 while (1) {
Jack Carter30116cd2012-10-04 02:29:46 +0000873 Parser.Lex(); // eat '(' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000874 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carter30116cd2012-10-04 02:29:46 +0000875 Parser.Lex(); // eat % token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000876 const AsmToken &nextTok = Parser.getTok();
877 if (nextTok.isNot(AsmToken::Identifier))
878 return true;
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000879 Str += "(%";
880 Str += nextTok.getIdentifier();
Jack Carter30116cd2012-10-04 02:29:46 +0000881 Parser.Lex(); // eat identifier
Jack Carter6b96c3f2012-09-06 20:00:02 +0000882 if (getLexer().getKind() != AsmToken::LParen)
883 return true;
884 } else
885 break;
886 }
887 if (getParser().ParseParenExpression(IdVal,EndLoc))
888 return true;
889
Jack Carterec3199f2013-01-12 01:03:14 +0000890 while (getLexer().getKind() == AsmToken::RParen)
Jack Carter30116cd2012-10-04 02:29:46 +0000891 Parser.Lex(); // eat ')' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000892
893 } else
Jack Carter30116cd2012-10-04 02:29:46 +0000894 return true; // parenthesis must follow reloc operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000895
Jack Carter30116cd2012-10-04 02:29:46 +0000896 // Check the type of the expression
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000897 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000898 // it's a constant, evaluate lo or hi value
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000899 int Val = MCE->getValue();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000900 if (Str == "lo") {
901 Val = Val & 0xffff;
902 } else if (Str == "hi") {
903 Val = (Val & 0xffff0000) >> 16;
904 }
905 Res = MCConstantExpr::Create(Val, getContext());
906 return false;
907 }
908
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000909 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter30116cd2012-10-04 02:29:46 +0000910 // it's a symbol, create symbolic expression from symbol
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000911 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000912 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
913 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
914 return false;
915 }
916 return true;
917}
918
Jack Carterec65be82012-09-05 23:34:03 +0000919bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
920 SMLoc &EndLoc) {
921
922 StartLoc = Parser.getTok().getLoc();
Jack Carterec3199f2013-01-12 01:03:14 +0000923 RegNo = tryParseRegister(isMips64());
924 EndLoc = Parser.getTok().getLoc();
Jack Carterec65be82012-09-05 23:34:03 +0000925 return (RegNo == (unsigned)-1);
926}
927
Jack Carter6b96c3f2012-09-06 20:00:02 +0000928bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
Jack Carterec3199f2013-01-12 01:03:14 +0000929
930 SMLoc S;
931
Jack Carter6b96c3f2012-09-06 20:00:02 +0000932 switch(getLexer().getKind()) {
933 default:
934 return true;
935 case AsmToken::Integer:
936 case AsmToken::Minus:
937 case AsmToken::Plus:
Jack Carterec3199f2013-01-12 01:03:14 +0000938 return (getParser().ParseExpression(Res));
939 case AsmToken::Percent:
940 return parseRelocOperand(Res);
Jack Carter6b96c3f2012-09-06 20:00:02 +0000941 case AsmToken::LParen:
Jack Carter30116cd2012-10-04 02:29:46 +0000942 return false; // it's probably assuming 0
Jack Carter6b96c3f2012-09-06 20:00:02 +0000943 }
944 return true;
945}
946
Jack Carterec65be82012-09-05 23:34:03 +0000947MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
948 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000949
950 const MCExpr *IdVal = 0;
Jack Carterec3199f2013-01-12 01:03:14 +0000951 SMLoc S;
952 // first operand is the offset
953 S = Parser.getTok().getLoc();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000954
955 if (parseMemOffset(IdVal))
956 return MatchOperand_ParseFail;
957
Jack Carter30116cd2012-10-04 02:29:46 +0000958 const AsmToken &Tok = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000959 if (Tok.isNot(AsmToken::LParen)) {
Jack Carter2f68b312012-10-09 23:29:45 +0000960 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
961 if (Mnemonic->getToken() == "la") {
Jack Carterec3199f2013-01-12 01:03:14 +0000962 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() -1);
Jack Carter2f68b312012-10-09 23:29:45 +0000963 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
964 return MatchOperand_Success;
965 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000966 Error(Parser.getTok().getLoc(), "'(' expected");
967 return MatchOperand_ParseFail;
968 }
969
970 Parser.Lex(); // Eat '(' token.
971
Jack Carter2f68b312012-10-09 23:29:45 +0000972 const AsmToken &Tok1 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000973 if (Tok1.is(AsmToken::Dollar)) {
974 Parser.Lex(); // Eat '$' token.
Jack Carterec3199f2013-01-12 01:03:14 +0000975 if (tryParseRegisterOperand(Operands, isMips64())) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000976 Error(Parser.getTok().getLoc(), "unexpected token in operand");
977 return MatchOperand_ParseFail;
978 }
979
980 } else {
Jack Carter30116cd2012-10-04 02:29:46 +0000981 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carter6b96c3f2012-09-06 20:00:02 +0000982 return MatchOperand_ParseFail;
983 }
984
Jack Carter30116cd2012-10-04 02:29:46 +0000985 const AsmToken &Tok2 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000986 if (Tok2.isNot(AsmToken::RParen)) {
987 Error(Parser.getTok().getLoc(), "')' expected");
988 return MatchOperand_ParseFail;
989 }
990
Jack Carterec3199f2013-01-12 01:03:14 +0000991 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
992
Jack Carter6b96c3f2012-09-06 20:00:02 +0000993 Parser.Lex(); // Eat ')' token.
994
995 if (IdVal == 0)
996 IdVal = MCConstantExpr::Create(0, getContext());
997
Jack Carter30116cd2012-10-04 02:29:46 +0000998 // now replace register operand with the mem operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000999 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1000 int RegNo = op->getReg();
Jack Carter30116cd2012-10-04 02:29:46 +00001001 // remove register from operands
Jack Carter6b96c3f2012-09-06 20:00:02 +00001002 Operands.pop_back();
Jack Carter30116cd2012-10-04 02:29:46 +00001003 // and add memory operand
Jack Carter6b96c3f2012-09-06 20:00:02 +00001004 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1005 delete op;
Jack Carterec65be82012-09-05 23:34:03 +00001006 return MatchOperand_Success;
1007}
1008
Jack Carterec3199f2013-01-12 01:03:14 +00001009MipsAsmParser::OperandMatchResultTy
1010MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1011
1012 if (!isMips64())
1013 return MatchOperand_NoMatch;
1014 // if the first token is not '$' we have an error
1015 if (Parser.getTok().isNot(AsmToken::Dollar))
1016 return MatchOperand_NoMatch;
1017
1018 Parser.Lex(); // Eat $
1019 if(!tryParseRegisterOperand(Operands, true)) {
1020 // set the proper register kind
1021 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1022 op->setRegKind(MipsOperand::Kind_CPU64Regs);
1023 return MatchOperand_Success;
1024 }
1025 return MatchOperand_NoMatch;
1026}
1027
1028MipsAsmParser::OperandMatchResultTy
1029MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1030
1031 // if the first token is not '$' we have an error
1032 if (Parser.getTok().isNot(AsmToken::Dollar))
1033 return MatchOperand_NoMatch;
1034
1035 Parser.Lex(); // Eat $
1036 if(!tryParseRegisterOperand(Operands, false)) {
1037 // set the propper register kind
1038 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1039 op->setRegKind(MipsOperand::Kind_CPURegs);
1040 return MatchOperand_Success;
1041 }
1042 return MatchOperand_NoMatch;
1043}
1044
1045MipsAsmParser::OperandMatchResultTy
1046MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1047
Jack Carterc147b672013-01-17 00:28:20 +00001048 if (isMips64())
1049 return MatchOperand_NoMatch;
1050
Jack Carterec3199f2013-01-12 01:03:14 +00001051 // if the first token is not '$' we have error
1052 if (Parser.getTok().isNot(AsmToken::Dollar))
1053 return MatchOperand_NoMatch;
1054 SMLoc S = Parser.getTok().getLoc();
1055 Parser.Lex(); // Eat $
1056
1057 const AsmToken &Tok = Parser.getTok(); // get next token
1058 if (Tok.isNot(AsmToken::Integer))
1059 return MatchOperand_NoMatch;
1060
1061 unsigned RegNum = Tok.getIntVal();
1062 // at the moment only hwreg29 is supported
1063 if (RegNum != 29)
1064 return MatchOperand_ParseFail;
1065
1066 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
1067 Parser.getTok().getLoc());
1068 op->setRegKind(MipsOperand::Kind_HWRegs);
1069 Operands.push_back(op);
1070
1071 Parser.Lex(); // Eat reg number
1072 return MatchOperand_Success;
1073}
1074
1075MipsAsmParser::OperandMatchResultTy
1076MipsAsmParser::parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carterc147b672013-01-17 00:28:20 +00001077
1078 if (!isMips64())
1079 return MatchOperand_NoMatch;
Jack Carterec3199f2013-01-12 01:03:14 +00001080 //if the first token is not '$' we have error
1081 if (Parser.getTok().isNot(AsmToken::Dollar))
1082 return MatchOperand_NoMatch;
1083 SMLoc S = Parser.getTok().getLoc();
1084 Parser.Lex(); // Eat $
1085
1086 const AsmToken &Tok = Parser.getTok(); // get next token
1087 if (Tok.isNot(AsmToken::Integer))
1088 return MatchOperand_NoMatch;
1089
1090 unsigned RegNum = Tok.getIntVal();
1091 // at the moment only hwreg29 is supported
1092 if (RegNum != 29)
1093 return MatchOperand_ParseFail;
1094
1095 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
1096 Parser.getTok().getLoc());
Jack Carterc147b672013-01-17 00:28:20 +00001097 op->setRegKind(MipsOperand::Kind_HW64Regs);
Jack Carterec3199f2013-01-12 01:03:14 +00001098 Operands.push_back(op);
1099
1100 Parser.Lex(); // Eat reg number
1101 return MatchOperand_Success;
1102}
1103
1104MipsAsmParser::OperandMatchResultTy
1105MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1106 unsigned RegNum;
1107 //if the first token is not '$' we have error
1108 if (Parser.getTok().isNot(AsmToken::Dollar))
1109 return MatchOperand_NoMatch;
1110 SMLoc S = Parser.getTok().getLoc();
1111 Parser.Lex(); // Eat $
1112
1113 const AsmToken &Tok = Parser.getTok(); // get next token
1114 if (Tok.is(AsmToken::Integer)) {
1115 RegNum = Tok.getIntVal();
1116 // at the moment only fcc0 is supported
1117 if (RegNum != 0)
1118 return MatchOperand_ParseFail;
1119 } else if (Tok.is(AsmToken::Identifier)) {
1120 // at the moment only fcc0 is supported
1121 if (Tok.getIdentifier() != "fcc0")
1122 return MatchOperand_ParseFail;
1123 } else
1124 return MatchOperand_NoMatch;
1125
1126 MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
1127 Parser.getTok().getLoc());
1128 op->setRegKind(MipsOperand::Kind_CCRRegs);
1129 Operands.push_back(op);
1130
1131 Parser.Lex(); // Eat reg number
1132 return MatchOperand_Success;
1133}
1134
Jack Carter6b96c3f2012-09-06 20:00:02 +00001135MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1136
1137 MCSymbolRefExpr::VariantKind VK
1138 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1139 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1140 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1141 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1142 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1143 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1144 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1145 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1146 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1147 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1148 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1149 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1150 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1151 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1152 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1153 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1154 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1155 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1156 .Default(MCSymbolRefExpr::VK_None);
1157
1158 return VK;
1159}
1160
Benjamin Kramer1ac45872012-09-10 11:52:14 +00001161static int ConvertCcString(StringRef CondString) {
Jack Carterf740d6e2012-09-07 00:23:42 +00001162 int CC = StringSwitch<unsigned>(CondString)
1163 .Case(".f", 0)
1164 .Case(".un", 1)
1165 .Case(".eq", 2)
1166 .Case(".ueq", 3)
1167 .Case(".olt", 4)
1168 .Case(".ult", 5)
1169 .Case(".ole", 6)
1170 .Case(".ule", 7)
1171 .Case(".sf", 8)
1172 .Case(".ngle", 9)
1173 .Case(".seq", 10)
1174 .Case(".ngl", 11)
1175 .Case(".lt", 12)
1176 .Case(".nge", 13)
1177 .Case(".le", 14)
1178 .Case(".ngt", 15)
1179 .Default(-1);
1180
1181 return CC;
1182}
1183
1184bool MipsAsmParser::
1185parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter30116cd2012-10-04 02:29:46 +00001186 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1187 // split the format
Jack Carterf740d6e2012-09-07 00:23:42 +00001188 size_t Start = Name.find('.'), Next = Name.rfind('.');
1189 StringRef Format1 = Name.slice(Start, Next);
Jack Carter30116cd2012-10-04 02:29:46 +00001190 // and add the first format to the operands
Jack Carterf740d6e2012-09-07 00:23:42 +00001191 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carter30116cd2012-10-04 02:29:46 +00001192 // now for the second format
Jack Carterf740d6e2012-09-07 00:23:42 +00001193 StringRef Format2 = Name.slice(Next, StringRef::npos);
1194 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1195
Jack Carter30116cd2012-10-04 02:29:46 +00001196 // set the format for the first register
Jack Carterf740d6e2012-09-07 00:23:42 +00001197 setFpFormat(Format1);
1198
1199 // Read the remaining operands.
1200 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1201 // Read the first operand.
1202 if (ParseOperand(Operands, Name)) {
1203 SMLoc Loc = getLexer().getLoc();
1204 Parser.EatToEndOfStatement();
1205 return Error(Loc, "unexpected token in argument list");
1206 }
1207
1208 if (getLexer().isNot(AsmToken::Comma)) {
1209 SMLoc Loc = getLexer().getLoc();
1210 Parser.EatToEndOfStatement();
1211 return Error(Loc, "unexpected token in argument list");
1212
1213 }
1214 Parser.Lex(); // Eat the comma.
1215
1216 //set the format for the first register
1217 setFpFormat(Format2);
1218
1219 // Parse and remember the operand.
1220 if (ParseOperand(Operands, Name)) {
1221 SMLoc Loc = getLexer().getLoc();
1222 Parser.EatToEndOfStatement();
1223 return Error(Loc, "unexpected token in argument list");
1224 }
1225 }
1226
1227 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1228 SMLoc Loc = getLexer().getLoc();
1229 Parser.EatToEndOfStatement();
1230 return Error(Loc, "unexpected token in argument list");
1231 }
1232
1233 Parser.Lex(); // Consume the EndOfStatement
1234 return false;
1235}
1236
Rafael Espindolafddf8042012-01-11 03:56:41 +00001237bool MipsAsmParser::
Chad Rosier6a020a72012-10-25 20:41:34 +00001238ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindolafddf8042012-01-11 03:56:41 +00001239 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter30116cd2012-10-04 02:29:46 +00001240 // floating point instructions: should register be treated as double?
Jack Carterf740d6e2012-09-07 00:23:42 +00001241 if (requestsDoubleOperand(Name)) {
1242 setFpFormat(FP_FORMAT_D);
Jack Carterec65be82012-09-05 23:34:03 +00001243 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterf740d6e2012-09-07 00:23:42 +00001244 }
1245 else {
1246 setDefaultFpFormat();
1247 // Create the leading tokens for the mnemonic, split by '.' characters.
1248 size_t Start = 0, Next = Name.find('.');
1249 StringRef Mnemonic = Name.slice(Start, Next);
1250
1251 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1252
1253 if (Next != StringRef::npos) {
Jack Carter30116cd2012-10-04 02:29:46 +00001254 // there is a format token in mnemonic
1255 // StringRef Rest = Name.slice(Next, StringRef::npos);
Jack Carterf740d6e2012-09-07 00:23:42 +00001256 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 }
Jack Carterec3199f2013-01-12 01:03:14 +00001268 SMLoc E = SMLoc::getFromPointer(
1269 Parser.getTok().getLoc().getPointer() -1 );
Jack Carterf740d6e2012-09-07 00:23:42 +00001270 Operands.push_back(MipsOperand::CreateImm(
1271 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1272 } else {
Jack Carter30116cd2012-10-04 02:29:46 +00001273 // trunc, ceil, floor ...
Jack Carterf740d6e2012-09-07 00:23:42 +00001274 return parseMathOperation(Name, NameLoc, Operands);
1275 }
1276
Jack Carter30116cd2012-10-04 02:29:46 +00001277 // the rest is a format
Jack Carterf740d6e2012-09-07 00:23:42 +00001278 Format = Name.slice(Dot, StringRef::npos);
1279 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1280 }
1281
1282 setFpFormat(Format);
1283 }
1284 }
Jack Carterec65be82012-09-05 23:34:03 +00001285
1286 // Read the remaining operands.
1287 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1288 // Read the first operand.
1289 if (ParseOperand(Operands, Name)) {
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;
Rafael Espindolafddf8042012-01-11 03:56:41 +00001315}
1316
Jack Carter30116cd2012-10-04 02:29:46 +00001317bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1318 SMLoc Loc = getLexer().getLoc();
1319 Parser.EatToEndOfStatement();
1320 return Error(Loc, ErrorMsg);
1321}
1322
1323bool MipsAsmParser::parseSetNoAtDirective() {
1324 // line should look like:
1325 // .set noat
1326 // set at reg to 0
Jack Carter10d5ff62012-10-05 23:55:28 +00001327 Options.setATReg(0);
Jack Carter30116cd2012-10-04 02:29:46 +00001328 // 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}
1338bool MipsAsmParser::parseSetAtDirective() {
1339 // line can be
1340 // .set at - defaults to $1
1341 // or .set at=$reg
1342 getParser().Lex();
1343 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter10d5ff62012-10-05 23:55:28 +00001344 Options.setATReg(1);
Jack Carter30116cd2012-10-04 02:29:46 +00001345 Parser.Lex(); // Consume the EndOfStatement
1346 return false;
1347 } else if (getLexer().is(AsmToken::Equal)) {
1348 getParser().Lex(); //eat '='
1349 if (getLexer().isNot(AsmToken::Dollar)) {
1350 reportParseError("unexpected token in statement");
1351 return false;
1352 }
1353 Parser.Lex(); // eat '$'
1354 if (getLexer().isNot(AsmToken::Integer)) {
1355 reportParseError("unexpected token in statement");
1356 return false;
1357 }
1358 const AsmToken &Reg = Parser.getTok();
Jack Carter10d5ff62012-10-05 23:55:28 +00001359 if (!Options.setATReg(Reg.getIntVal())) {
Jack Carter30116cd2012-10-04 02:29:46 +00001360 reportParseError("unexpected token in statement");
1361 return false;
1362 }
1363 getParser().Lex(); //eat reg
1364
1365 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1366 reportParseError("unexpected token in statement");
1367 return false;
1368 }
1369 Parser.Lex(); // Consume the EndOfStatement
1370 return false;
1371 } else {
1372 reportParseError("unexpected token in statement");
1373 return false;
1374 }
1375}
1376
1377bool MipsAsmParser::parseSetReorderDirective() {
1378 Parser.Lex();
1379 // if this is not the end of the statement, report error
1380 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1381 reportParseError("unexpected token in statement");
1382 return false;
1383 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001384 Options.setReorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001385 Parser.Lex(); // Consume the EndOfStatement
1386 return false;
1387}
1388
1389bool MipsAsmParser::parseSetNoReorderDirective() {
1390 Parser.Lex();
1391 // if this is not the end of the statement, report error
1392 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1393 reportParseError("unexpected token in statement");
1394 return false;
1395 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001396 Options.setNoreorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001397 Parser.Lex(); // Consume the EndOfStatement
1398 return false;
1399}
1400
1401bool MipsAsmParser::parseSetMacroDirective() {
1402 Parser.Lex();
1403 // if this is not the end of the statement, report error
1404 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1405 reportParseError("unexpected token in statement");
1406 return false;
1407 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001408 Options.setMacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001409 Parser.Lex(); // Consume the EndOfStatement
1410 return false;
1411}
1412
1413bool MipsAsmParser::parseSetNoMacroDirective() {
1414 Parser.Lex();
1415 // if this is not the end of the statement, report error
1416 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1417 reportParseError("`noreorder' must be set before `nomacro'");
1418 return false;
1419 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001420 if (Options.isReorder()) {
Jack Carter30116cd2012-10-04 02:29:46 +00001421 reportParseError("`noreorder' must be set before `nomacro'");
1422 return false;
1423 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001424 Options.setNomacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001425 Parser.Lex(); // Consume the EndOfStatement
1426 return false;
1427}
1428bool MipsAsmParser::parseDirectiveSet() {
1429
1430 // get next token
1431 const AsmToken &Tok = Parser.getTok();
1432
1433 if (Tok.getString() == "noat") {
1434 return parseSetNoAtDirective();
1435 } else if (Tok.getString() == "at") {
1436 return parseSetAtDirective();
1437 } else if (Tok.getString() == "reorder") {
1438 return parseSetReorderDirective();
1439 } else if (Tok.getString() == "noreorder") {
1440 return parseSetNoReorderDirective();
1441 } else if (Tok.getString() == "macro") {
1442 return parseSetMacroDirective();
1443 } else if (Tok.getString() == "nomacro") {
1444 return parseSetNoMacroDirective();
1445 } else if (Tok.getString() == "nomips16") {
1446 // ignore this directive for now
1447 Parser.EatToEndOfStatement();
1448 return false;
1449 } else if (Tok.getString() == "nomicromips") {
1450 // ignore this directive for now
1451 Parser.EatToEndOfStatement();
1452 return false;
1453 }
1454 return true;
1455}
1456
1457bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carteracbea452012-09-07 00:48:02 +00001458
1459 if (DirectiveID.getString() == ".ent") {
Jack Carter30116cd2012-10-04 02:29:46 +00001460 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001461 Parser.Lex();
1462 return false;
1463 }
1464
1465 if (DirectiveID.getString() == ".end") {
Jack Carter30116cd2012-10-04 02:29:46 +00001466 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001467 Parser.Lex();
1468 return false;
1469 }
1470
1471 if (DirectiveID.getString() == ".frame") {
Jack Carter30116cd2012-10-04 02:29:46 +00001472 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001473 Parser.EatToEndOfStatement();
1474 return false;
1475 }
1476
1477 if (DirectiveID.getString() == ".set") {
Jack Carter30116cd2012-10-04 02:29:46 +00001478 return parseDirectiveSet();
Jack Carteracbea452012-09-07 00:48:02 +00001479 }
1480
1481 if (DirectiveID.getString() == ".fmask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001482 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001483 Parser.EatToEndOfStatement();
1484 return false;
1485 }
1486
1487 if (DirectiveID.getString() == ".mask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001488 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001489 Parser.EatToEndOfStatement();
1490 return false;
1491 }
1492
1493 if (DirectiveID.getString() == ".gpword") {
Jack Carter30116cd2012-10-04 02:29:46 +00001494 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001495 Parser.EatToEndOfStatement();
1496 return false;
1497 }
1498
Rafael Espindolafddf8042012-01-11 03:56:41 +00001499 return true;
1500}
1501
Rafael Espindolafddf8042012-01-11 03:56:41 +00001502extern "C" void LLVMInitializeMipsAsmParser() {
1503 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1504 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1505 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1506 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1507}
Jack Carterec65be82012-09-05 23:34:03 +00001508
1509#define GET_REGISTER_MATCHER
1510#define GET_MATCHER_IMPLEMENTATION
1511#include "MipsGenAsmMatcher.inc"