blob: 41df9d462dffc0be4e613d30b174b93dd86fa1dc [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 {
335 return Reg.Kind == Kind_CPURegs;
336 }
337 void addCPURegsAsmOperands(MCInst &Inst, unsigned N) const {
338 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
339 }
340
341 bool isCPU64RegsAsm() const {
342 return Reg.Kind == Kind_CPU64Regs;
343 }
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
1048 // if the first token is not '$' we have error
1049 if (Parser.getTok().isNot(AsmToken::Dollar))
1050 return MatchOperand_NoMatch;
1051 SMLoc S = Parser.getTok().getLoc();
1052 Parser.Lex(); // Eat $
1053
1054 const AsmToken &Tok = Parser.getTok(); // get next token
1055 if (Tok.isNot(AsmToken::Integer))
1056 return MatchOperand_NoMatch;
1057
1058 unsigned RegNum = Tok.getIntVal();
1059 // at the moment only hwreg29 is supported
1060 if (RegNum != 29)
1061 return MatchOperand_ParseFail;
1062
1063 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
1064 Parser.getTok().getLoc());
1065 op->setRegKind(MipsOperand::Kind_HWRegs);
1066 Operands.push_back(op);
1067
1068 Parser.Lex(); // Eat reg number
1069 return MatchOperand_Success;
1070}
1071
1072MipsAsmParser::OperandMatchResultTy
1073MipsAsmParser::parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1074 //if the first token is not '$' we have error
1075 if (Parser.getTok().isNot(AsmToken::Dollar))
1076 return MatchOperand_NoMatch;
1077 SMLoc S = Parser.getTok().getLoc();
1078 Parser.Lex(); // Eat $
1079
1080 const AsmToken &Tok = Parser.getTok(); // get next token
1081 if (Tok.isNot(AsmToken::Integer))
1082 return MatchOperand_NoMatch;
1083
1084 unsigned RegNum = Tok.getIntVal();
1085 // at the moment only hwreg29 is supported
1086 if (RegNum != 29)
1087 return MatchOperand_ParseFail;
1088
1089 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
1090 Parser.getTok().getLoc());
1091 op->setRegKind(MipsOperand::Kind_HWRegs);
1092 Operands.push_back(op);
1093
1094 Parser.Lex(); // Eat reg number
1095 return MatchOperand_Success;
1096}
1097
1098MipsAsmParser::OperandMatchResultTy
1099MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1100 unsigned RegNum;
1101 //if the first token is not '$' we have error
1102 if (Parser.getTok().isNot(AsmToken::Dollar))
1103 return MatchOperand_NoMatch;
1104 SMLoc S = Parser.getTok().getLoc();
1105 Parser.Lex(); // Eat $
1106
1107 const AsmToken &Tok = Parser.getTok(); // get next token
1108 if (Tok.is(AsmToken::Integer)) {
1109 RegNum = Tok.getIntVal();
1110 // at the moment only fcc0 is supported
1111 if (RegNum != 0)
1112 return MatchOperand_ParseFail;
1113 } else if (Tok.is(AsmToken::Identifier)) {
1114 // at the moment only fcc0 is supported
1115 if (Tok.getIdentifier() != "fcc0")
1116 return MatchOperand_ParseFail;
1117 } else
1118 return MatchOperand_NoMatch;
1119
1120 MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
1121 Parser.getTok().getLoc());
1122 op->setRegKind(MipsOperand::Kind_CCRRegs);
1123 Operands.push_back(op);
1124
1125 Parser.Lex(); // Eat reg number
1126 return MatchOperand_Success;
1127}
1128
Jack Carter6b96c3f2012-09-06 20:00:02 +00001129MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1130
1131 MCSymbolRefExpr::VariantKind VK
1132 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1133 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1134 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1135 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1136 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1137 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1138 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1139 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1140 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1141 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1142 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1143 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1144 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1145 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1146 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1147 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1148 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1149 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1150 .Default(MCSymbolRefExpr::VK_None);
1151
1152 return VK;
1153}
1154
Benjamin Kramer1ac45872012-09-10 11:52:14 +00001155static int ConvertCcString(StringRef CondString) {
Jack Carterf740d6e2012-09-07 00:23:42 +00001156 int CC = StringSwitch<unsigned>(CondString)
1157 .Case(".f", 0)
1158 .Case(".un", 1)
1159 .Case(".eq", 2)
1160 .Case(".ueq", 3)
1161 .Case(".olt", 4)
1162 .Case(".ult", 5)
1163 .Case(".ole", 6)
1164 .Case(".ule", 7)
1165 .Case(".sf", 8)
1166 .Case(".ngle", 9)
1167 .Case(".seq", 10)
1168 .Case(".ngl", 11)
1169 .Case(".lt", 12)
1170 .Case(".nge", 13)
1171 .Case(".le", 14)
1172 .Case(".ngt", 15)
1173 .Default(-1);
1174
1175 return CC;
1176}
1177
1178bool MipsAsmParser::
1179parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter30116cd2012-10-04 02:29:46 +00001180 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1181 // split the format
Jack Carterf740d6e2012-09-07 00:23:42 +00001182 size_t Start = Name.find('.'), Next = Name.rfind('.');
1183 StringRef Format1 = Name.slice(Start, Next);
Jack Carter30116cd2012-10-04 02:29:46 +00001184 // and add the first format to the operands
Jack Carterf740d6e2012-09-07 00:23:42 +00001185 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carter30116cd2012-10-04 02:29:46 +00001186 // now for the second format
Jack Carterf740d6e2012-09-07 00:23:42 +00001187 StringRef Format2 = Name.slice(Next, StringRef::npos);
1188 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1189
Jack Carter30116cd2012-10-04 02:29:46 +00001190 // set the format for the first register
Jack Carterf740d6e2012-09-07 00:23:42 +00001191 setFpFormat(Format1);
1192
1193 // Read the remaining operands.
1194 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1195 // Read the first operand.
1196 if (ParseOperand(Operands, Name)) {
1197 SMLoc Loc = getLexer().getLoc();
1198 Parser.EatToEndOfStatement();
1199 return Error(Loc, "unexpected token in argument list");
1200 }
1201
1202 if (getLexer().isNot(AsmToken::Comma)) {
1203 SMLoc Loc = getLexer().getLoc();
1204 Parser.EatToEndOfStatement();
1205 return Error(Loc, "unexpected token in argument list");
1206
1207 }
1208 Parser.Lex(); // Eat the comma.
1209
1210 //set the format for the first register
1211 setFpFormat(Format2);
1212
1213 // Parse and remember the operand.
1214 if (ParseOperand(Operands, Name)) {
1215 SMLoc Loc = getLexer().getLoc();
1216 Parser.EatToEndOfStatement();
1217 return Error(Loc, "unexpected token in argument list");
1218 }
1219 }
1220
1221 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1222 SMLoc Loc = getLexer().getLoc();
1223 Parser.EatToEndOfStatement();
1224 return Error(Loc, "unexpected token in argument list");
1225 }
1226
1227 Parser.Lex(); // Consume the EndOfStatement
1228 return false;
1229}
1230
Rafael Espindolafddf8042012-01-11 03:56:41 +00001231bool MipsAsmParser::
Chad Rosier6a020a72012-10-25 20:41:34 +00001232ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindolafddf8042012-01-11 03:56:41 +00001233 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter30116cd2012-10-04 02:29:46 +00001234 // floating point instructions: should register be treated as double?
Jack Carterf740d6e2012-09-07 00:23:42 +00001235 if (requestsDoubleOperand(Name)) {
1236 setFpFormat(FP_FORMAT_D);
Jack Carterec65be82012-09-05 23:34:03 +00001237 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterf740d6e2012-09-07 00:23:42 +00001238 }
1239 else {
1240 setDefaultFpFormat();
1241 // Create the leading tokens for the mnemonic, split by '.' characters.
1242 size_t Start = 0, Next = Name.find('.');
1243 StringRef Mnemonic = Name.slice(Start, Next);
1244
1245 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1246
1247 if (Next != StringRef::npos) {
Jack Carter30116cd2012-10-04 02:29:46 +00001248 // there is a format token in mnemonic
1249 // StringRef Rest = Name.slice(Next, StringRef::npos);
Jack Carterf740d6e2012-09-07 00:23:42 +00001250 size_t Dot = Name.find('.', Next+1);
1251 StringRef Format = Name.slice(Next, Dot);
1252 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1253 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1254 else {
1255 if (Name.startswith("c.")){
1256 // floating point compare, add '.' and immediate represent for cc
1257 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1258 int Cc = ConvertCcString(Format);
1259 if (Cc == -1) {
1260 return Error(NameLoc, "Invalid conditional code");
1261 }
Jack Carterec3199f2013-01-12 01:03:14 +00001262 SMLoc E = SMLoc::getFromPointer(
1263 Parser.getTok().getLoc().getPointer() -1 );
Jack Carterf740d6e2012-09-07 00:23:42 +00001264 Operands.push_back(MipsOperand::CreateImm(
1265 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1266 } else {
Jack Carter30116cd2012-10-04 02:29:46 +00001267 // trunc, ceil, floor ...
Jack Carterf740d6e2012-09-07 00:23:42 +00001268 return parseMathOperation(Name, NameLoc, Operands);
1269 }
1270
Jack Carter30116cd2012-10-04 02:29:46 +00001271 // the rest is a format
Jack Carterf740d6e2012-09-07 00:23:42 +00001272 Format = Name.slice(Dot, StringRef::npos);
1273 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1274 }
1275
1276 setFpFormat(Format);
1277 }
1278 }
Jack Carterec65be82012-09-05 23:34:03 +00001279
1280 // Read the remaining operands.
1281 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1282 // Read the first operand.
1283 if (ParseOperand(Operands, Name)) {
1284 SMLoc Loc = getLexer().getLoc();
1285 Parser.EatToEndOfStatement();
1286 return Error(Loc, "unexpected token in argument list");
1287 }
1288
1289 while (getLexer().is(AsmToken::Comma) ) {
1290 Parser.Lex(); // Eat the comma.
1291
1292 // Parse and remember the operand.
1293 if (ParseOperand(Operands, Name)) {
1294 SMLoc Loc = getLexer().getLoc();
1295 Parser.EatToEndOfStatement();
1296 return Error(Loc, "unexpected token in argument list");
1297 }
1298 }
1299 }
1300
1301 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1302 SMLoc Loc = getLexer().getLoc();
1303 Parser.EatToEndOfStatement();
1304 return Error(Loc, "unexpected token in argument list");
1305 }
1306
1307 Parser.Lex(); // Consume the EndOfStatement
1308 return false;
Rafael Espindolafddf8042012-01-11 03:56:41 +00001309}
1310
Jack Carter30116cd2012-10-04 02:29:46 +00001311bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1312 SMLoc Loc = getLexer().getLoc();
1313 Parser.EatToEndOfStatement();
1314 return Error(Loc, ErrorMsg);
1315}
1316
1317bool MipsAsmParser::parseSetNoAtDirective() {
1318 // line should look like:
1319 // .set noat
1320 // set at reg to 0
Jack Carter10d5ff62012-10-05 23:55:28 +00001321 Options.setATReg(0);
Jack Carter30116cd2012-10-04 02:29:46 +00001322 // eat noat
1323 Parser.Lex();
1324 // if this is not the end of the statement, report error
1325 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1326 reportParseError("unexpected token in statement");
1327 return false;
1328 }
1329 Parser.Lex(); // Consume the EndOfStatement
1330 return false;
1331}
1332bool MipsAsmParser::parseSetAtDirective() {
1333 // line can be
1334 // .set at - defaults to $1
1335 // or .set at=$reg
1336 getParser().Lex();
1337 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter10d5ff62012-10-05 23:55:28 +00001338 Options.setATReg(1);
Jack Carter30116cd2012-10-04 02:29:46 +00001339 Parser.Lex(); // Consume the EndOfStatement
1340 return false;
1341 } else if (getLexer().is(AsmToken::Equal)) {
1342 getParser().Lex(); //eat '='
1343 if (getLexer().isNot(AsmToken::Dollar)) {
1344 reportParseError("unexpected token in statement");
1345 return false;
1346 }
1347 Parser.Lex(); // eat '$'
1348 if (getLexer().isNot(AsmToken::Integer)) {
1349 reportParseError("unexpected token in statement");
1350 return false;
1351 }
1352 const AsmToken &Reg = Parser.getTok();
Jack Carter10d5ff62012-10-05 23:55:28 +00001353 if (!Options.setATReg(Reg.getIntVal())) {
Jack Carter30116cd2012-10-04 02:29:46 +00001354 reportParseError("unexpected token in statement");
1355 return false;
1356 }
1357 getParser().Lex(); //eat reg
1358
1359 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1360 reportParseError("unexpected token in statement");
1361 return false;
1362 }
1363 Parser.Lex(); // Consume the EndOfStatement
1364 return false;
1365 } else {
1366 reportParseError("unexpected token in statement");
1367 return false;
1368 }
1369}
1370
1371bool MipsAsmParser::parseSetReorderDirective() {
1372 Parser.Lex();
1373 // if this is not the end of the statement, report error
1374 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1375 reportParseError("unexpected token in statement");
1376 return false;
1377 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001378 Options.setReorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001379 Parser.Lex(); // Consume the EndOfStatement
1380 return false;
1381}
1382
1383bool MipsAsmParser::parseSetNoReorderDirective() {
1384 Parser.Lex();
1385 // if this is not the end of the statement, report error
1386 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1387 reportParseError("unexpected token in statement");
1388 return false;
1389 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001390 Options.setNoreorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001391 Parser.Lex(); // Consume the EndOfStatement
1392 return false;
1393}
1394
1395bool MipsAsmParser::parseSetMacroDirective() {
1396 Parser.Lex();
1397 // if this is not the end of the statement, report error
1398 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1399 reportParseError("unexpected token in statement");
1400 return false;
1401 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001402 Options.setMacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001403 Parser.Lex(); // Consume the EndOfStatement
1404 return false;
1405}
1406
1407bool MipsAsmParser::parseSetNoMacroDirective() {
1408 Parser.Lex();
1409 // if this is not the end of the statement, report error
1410 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1411 reportParseError("`noreorder' must be set before `nomacro'");
1412 return false;
1413 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001414 if (Options.isReorder()) {
Jack Carter30116cd2012-10-04 02:29:46 +00001415 reportParseError("`noreorder' must be set before `nomacro'");
1416 return false;
1417 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001418 Options.setNomacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001419 Parser.Lex(); // Consume the EndOfStatement
1420 return false;
1421}
1422bool MipsAsmParser::parseDirectiveSet() {
1423
1424 // get next token
1425 const AsmToken &Tok = Parser.getTok();
1426
1427 if (Tok.getString() == "noat") {
1428 return parseSetNoAtDirective();
1429 } else if (Tok.getString() == "at") {
1430 return parseSetAtDirective();
1431 } else if (Tok.getString() == "reorder") {
1432 return parseSetReorderDirective();
1433 } else if (Tok.getString() == "noreorder") {
1434 return parseSetNoReorderDirective();
1435 } else if (Tok.getString() == "macro") {
1436 return parseSetMacroDirective();
1437 } else if (Tok.getString() == "nomacro") {
1438 return parseSetNoMacroDirective();
1439 } else if (Tok.getString() == "nomips16") {
1440 // ignore this directive for now
1441 Parser.EatToEndOfStatement();
1442 return false;
1443 } else if (Tok.getString() == "nomicromips") {
1444 // ignore this directive for now
1445 Parser.EatToEndOfStatement();
1446 return false;
1447 }
1448 return true;
1449}
1450
1451bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carteracbea452012-09-07 00:48:02 +00001452
1453 if (DirectiveID.getString() == ".ent") {
Jack Carter30116cd2012-10-04 02:29:46 +00001454 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001455 Parser.Lex();
1456 return false;
1457 }
1458
1459 if (DirectiveID.getString() == ".end") {
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() == ".frame") {
Jack Carter30116cd2012-10-04 02:29:46 +00001466 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001467 Parser.EatToEndOfStatement();
1468 return false;
1469 }
1470
1471 if (DirectiveID.getString() == ".set") {
Jack Carter30116cd2012-10-04 02:29:46 +00001472 return parseDirectiveSet();
Jack Carteracbea452012-09-07 00:48:02 +00001473 }
1474
1475 if (DirectiveID.getString() == ".fmask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001476 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001477 Parser.EatToEndOfStatement();
1478 return false;
1479 }
1480
1481 if (DirectiveID.getString() == ".mask") {
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() == ".gpword") {
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
Rafael Espindolafddf8042012-01-11 03:56:41 +00001493 return true;
1494}
1495
Rafael Espindolafddf8042012-01-11 03:56:41 +00001496extern "C" void LLVMInitializeMipsAsmParser() {
1497 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1498 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1499 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1500 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1501}
Jack Carterec65be82012-09-05 23:34:03 +00001502
1503#define GET_REGISTER_MATCHER
1504#define GET_MATCHER_IMPLEMENTATION
1505#include "MipsGenAsmMatcher.inc"