blob: 2fa514f7fbd99855f7f1848bc0513712c615fdf3 [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 Carter801c5832013-01-25 01:31:34 +0000136 bool parseDirectiveWord(unsigned Size, SMLoc L);
137
Jack Carter6b96c3f2012-09-06 20:00:02 +0000138 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Carterf740d6e2012-09-07 00:23:42 +0000139
Jack Carterec65be82012-09-05 23:34:03 +0000140 bool isMips64() const {
141 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
142 }
143
Jack Carterf740d6e2012-09-07 00:23:42 +0000144 bool isFP64() const {
145 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
146 }
147
Jack Carterec3199f2013-01-12 01:03:14 +0000148 int matchRegisterName(StringRef Symbol, bool is64BitReg);
Jack Carterec65be82012-09-05 23:34:03 +0000149
Jack Carterec3199f2013-01-12 01:03:14 +0000150 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterec65be82012-09-05 23:34:03 +0000151
Jack Carterf740d6e2012-09-07 00:23:42 +0000152 void setFpFormat(FpFormatTy Format) {
153 FpFormat = Format;
154 }
155
156 void setDefaultFpFormat();
157
158 void setFpFormat(StringRef Format);
159
160 FpFormatTy getFpFormat() {return FpFormat;}
161
162 bool requestsDoubleOperand(StringRef Mnemonic);
163
Jack Carterec65be82012-09-05 23:34:03 +0000164 unsigned getReg(int RC,int RegNo);
Chad Rosier038f3e32012-09-03 18:47:45 +0000165
Jack Carter30116cd2012-10-04 02:29:46 +0000166 unsigned getATReg();
Rafael Espindolafddf8042012-01-11 03:56:41 +0000167public:
168 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterec65be82012-09-05 23:34:03 +0000169 : MCTargetAsmParser(), STI(sti), Parser(parser) {
170 // Initialize the set of available features.
171 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindolafddf8042012-01-11 03:56:41 +0000172 }
173
Jack Carterec65be82012-09-05 23:34:03 +0000174 MCAsmParser &getParser() const { return Parser; }
175 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
176
Rafael Espindolafddf8042012-01-11 03:56:41 +0000177};
178}
179
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000180namespace {
181
182/// MipsOperand - Instances of this class represent a parsed Mips machine
183/// instruction.
184class MipsOperand : public MCParsedAsmOperand {
Jack Carterec65be82012-09-05 23:34:03 +0000185
Jack Carterec3199f2013-01-12 01:03:14 +0000186public:
187 enum RegisterKind {
188 Kind_None,
189 Kind_CPURegs,
190 Kind_CPU64Regs,
191 Kind_HWRegs,
192 Kind_HW64Regs,
193 Kind_FGR32Regs,
194 Kind_FGR64Regs,
195 Kind_AFGR32Regs,
196 Kind_CCRRegs
197 };
198
199private:
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000200 enum KindTy {
201 k_CondCode,
202 k_CoprocNum,
203 k_Immediate,
204 k_Memory,
205 k_PostIndexRegister,
206 k_Register,
207 k_Token
208 } Kind;
209
210 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterec65be82012-09-05 23:34:03 +0000211
212 union {
213 struct {
214 const char *Data;
215 unsigned Length;
216 } Tok;
217
218 struct {
219 unsigned RegNum;
Jack Carterec3199f2013-01-12 01:03:14 +0000220 RegisterKind Kind;
Jack Carterec65be82012-09-05 23:34:03 +0000221 } Reg;
222
223 struct {
224 const MCExpr *Val;
225 } Imm;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000226
227 struct {
228 unsigned Base;
229 const MCExpr *Off;
230 } Mem;
Jack Carterec65be82012-09-05 23:34:03 +0000231 };
232
233 SMLoc StartLoc, EndLoc;
234
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000235public:
236 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000237 assert(N == 1 && "Invalid number of operands!");
238 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000239 }
Jack Carterec65be82012-09-05 23:34:03 +0000240
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000241 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterec65be82012-09-05 23:34:03 +0000242 // Add as immediate when possible. Null MCExpr = 0.
243 if (Expr == 0)
244 Inst.addOperand(MCOperand::CreateImm(0));
245 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
246 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
247 else
248 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000249 }
Jack Carterec65be82012-09-05 23:34:03 +0000250
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000251 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000252 assert(N == 1 && "Invalid number of operands!");
253 const MCExpr *Expr = getImm();
254 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000255 }
Jack Carterec65be82012-09-05 23:34:03 +0000256
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000257 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000258 assert(N == 2 && "Invalid number of operands!");
259
260 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
261
262 const MCExpr *Expr = getMemOff();
263 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000264 }
265
266 bool isReg() const { return Kind == k_Register; }
267 bool isImm() const { return Kind == k_Immediate; }
268 bool isToken() const { return Kind == k_Token; }
269 bool isMem() const { return Kind == k_Memory; }
270
271 StringRef getToken() const {
272 assert(Kind == k_Token && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000273 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000274 }
275
276 unsigned getReg() const {
277 assert((Kind == k_Register) && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000278 return Reg.RegNum;
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000279 }
280
Jack Carterec3199f2013-01-12 01:03:14 +0000281 void setRegKind(RegisterKind RegKind) {
282 assert((Kind == k_Register) && "Invalid access!");
283 Reg.Kind = RegKind;
284 }
285
Jack Carterec65be82012-09-05 23:34:03 +0000286 const MCExpr *getImm() const {
287 assert((Kind == k_Immediate) && "Invalid access!");
288 return Imm.Val;
289 }
290
Jack Carter6b96c3f2012-09-06 20:00:02 +0000291 unsigned getMemBase() const {
292 assert((Kind == k_Memory) && "Invalid access!");
293 return Mem.Base;
294 }
295
296 const MCExpr *getMemOff() const {
297 assert((Kind == k_Memory) && "Invalid access!");
298 return Mem.Off;
299 }
300
Jack Carterec65be82012-09-05 23:34:03 +0000301 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
302 MipsOperand *Op = new MipsOperand(k_Token);
303 Op->Tok.Data = Str.data();
304 Op->Tok.Length = Str.size();
305 Op->StartLoc = S;
306 Op->EndLoc = S;
307 return Op;
308 }
309
310 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
311 MipsOperand *Op = new MipsOperand(k_Register);
312 Op->Reg.RegNum = RegNum;
313 Op->StartLoc = S;
314 Op->EndLoc = E;
315 return Op;
316 }
317
318 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
319 MipsOperand *Op = new MipsOperand(k_Immediate);
320 Op->Imm.Val = Val;
321 Op->StartLoc = S;
322 Op->EndLoc = E;
323 return Op;
324 }
325
Jack Carter6b96c3f2012-09-06 20:00:02 +0000326 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
327 SMLoc S, SMLoc E) {
328 MipsOperand *Op = new MipsOperand(k_Memory);
329 Op->Mem.Base = Base;
330 Op->Mem.Off = Off;
331 Op->StartLoc = S;
332 Op->EndLoc = E;
333 return Op;
334 }
335
Jack Carterec3199f2013-01-12 01:03:14 +0000336 bool isCPURegsAsm() const {
NAKAMURA Takumia96a96c2013-01-12 15:19:10 +0000337 return Kind == k_Register && Reg.Kind == Kind_CPURegs;
Jack Carterec3199f2013-01-12 01:03:14 +0000338 }
339 void addCPURegsAsmOperands(MCInst &Inst, unsigned N) const {
340 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
341 }
342
343 bool isCPU64RegsAsm() const {
NAKAMURA Takumia96a96c2013-01-12 15:19:10 +0000344 return Kind == k_Register && Reg.Kind == Kind_CPU64Regs;
Jack Carterec3199f2013-01-12 01:03:14 +0000345 }
346 void addCPU64RegsAsmOperands(MCInst &Inst, unsigned N) const {
347 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
348 }
349
350 bool isHWRegsAsm() const {
351 assert((Kind == k_Register) && "Invalid access!");
352 return Reg.Kind == Kind_HWRegs;
353 }
354 void addHWRegsAsmOperands(MCInst &Inst, unsigned N) const {
355 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
356 }
357
358 bool isHW64RegsAsm() const {
359 assert((Kind == k_Register) && "Invalid access!");
360 return Reg.Kind == Kind_HW64Regs;
361 }
362 void addHW64RegsAsmOperands(MCInst &Inst, unsigned N) const {
363 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
364 }
365
366 void addCCRAsmOperands(MCInst &Inst, unsigned N) const {
367 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
368 }
369
370 bool isCCRAsm() const {
371 assert((Kind == k_Register) && "Invalid access!");
372 return Reg.Kind == Kind_CCRRegs;
373 }
374
Jack Carterec65be82012-09-05 23:34:03 +0000375 /// getStartLoc - Get the location of the first token of this operand.
376 SMLoc getStartLoc() const { return StartLoc; }
377 /// getEndLoc - Get the location of the last token of this operand.
378 SMLoc getEndLoc() const { return EndLoc; }
379
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000380 virtual void print(raw_ostream &OS) const {
381 llvm_unreachable("unimplemented!");
382 }
383};
384}
385
Jack Carter9d577c82012-10-04 04:03:53 +0000386bool MipsAsmParser::needsExpansion(MCInst &Inst) {
387
388 switch(Inst.getOpcode()) {
389 case Mips::LoadImm32Reg:
Jack Carter2f68b312012-10-09 23:29:45 +0000390 case Mips::LoadAddr32Imm:
391 case Mips::LoadAddr32Reg:
Jack Carter9d577c82012-10-04 04:03:53 +0000392 return true;
393 default:
394 return false;
395 }
396}
Jack Carter2490dc62012-10-06 00:53:28 +0000397
Jack Carter9d577c82012-10-04 04:03:53 +0000398void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000399 SmallVectorImpl<MCInst> &Instructions){
Jack Carter9d577c82012-10-04 04:03:53 +0000400 switch(Inst.getOpcode()) {
401 case Mips::LoadImm32Reg:
402 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carter2f68b312012-10-09 23:29:45 +0000403 case Mips::LoadAddr32Imm:
404 return expandLoadAddressImm(Inst,IDLoc,Instructions);
405 case Mips::LoadAddr32Reg:
406 return expandLoadAddressReg(Inst,IDLoc,Instructions);
Jack Carter9d577c82012-10-04 04:03:53 +0000407 }
Jack Carter9d577c82012-10-04 04:03:53 +0000408}
Jack Carter2490dc62012-10-06 00:53:28 +0000409
Jack Carter9d577c82012-10-04 04:03:53 +0000410void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter2f68b312012-10-09 23:29:45 +0000411 SmallVectorImpl<MCInst> &Instructions){
Jack Carter2490dc62012-10-06 00:53:28 +0000412 MCInst tmpInst;
Jack Carter9d577c82012-10-04 04:03:53 +0000413 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter2f68b312012-10-09 23:29:45 +0000414 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter9d577c82012-10-04 04:03:53 +0000415 const MCOperand &RegOp = Inst.getOperand(0);
416 assert(RegOp.isReg() && "expected register operand kind");
417
418 int ImmValue = ImmOp.getImm();
Jack Carter2490dc62012-10-06 00:53:28 +0000419 tmpInst.setLoc(IDLoc);
Jack Carter9d577c82012-10-04 04:03:53 +0000420 if ( 0 <= ImmValue && ImmValue <= 65535) {
Jack Carter2490dc62012-10-06 00:53:28 +0000421 // for 0 <= j <= 65535.
Jack Carter9d577c82012-10-04 04:03:53 +0000422 // li d,j => ori d,$zero,j
Jack Carterec3199f2013-01-12 01:03:14 +0000423 tmpInst.setOpcode(Mips::ORi);
Jack Carter2490dc62012-10-06 00:53:28 +0000424 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
425 tmpInst.addOperand(
Jack Carterec3199f2013-01-12 01:03:14 +0000426 MCOperand::CreateReg(Mips::ZERO));
Jack Carter2490dc62012-10-06 00:53:28 +0000427 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter9d577c82012-10-04 04:03:53 +0000428 Instructions.push_back(tmpInst);
429 } else if ( ImmValue < 0 && ImmValue >= -32768) {
Jack Carter2490dc62012-10-06 00:53:28 +0000430 // for -32768 <= j < 0.
Jack Carter9d577c82012-10-04 04:03:53 +0000431 // li d,j => addiu d,$zero,j
Jack Carterec3199f2013-01-12 01:03:14 +0000432 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter2490dc62012-10-06 00:53:28 +0000433 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
434 tmpInst.addOperand(
Jack Carterec3199f2013-01-12 01:03:14 +0000435 MCOperand::CreateReg(Mips::ZERO));
Jack Carter2490dc62012-10-06 00:53:28 +0000436 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter9d577c82012-10-04 04:03:53 +0000437 Instructions.push_back(tmpInst);
438 } else {
439 // for any other value of j that is representable as a 32-bit integer.
440 // li d,j => lui d,hi16(j)
Jack Carter2f68b312012-10-09 23:29:45 +0000441 // ori d,d,lo16(j)
Jack Carterec3199f2013-01-12 01:03:14 +0000442 tmpInst.setOpcode(Mips::LUi);
Jack Carter2490dc62012-10-06 00:53:28 +0000443 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
444 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter9d577c82012-10-04 04:03:53 +0000445 Instructions.push_back(tmpInst);
Jack Carter2490dc62012-10-06 00:53:28 +0000446 tmpInst.clear();
Jack Carterec3199f2013-01-12 01:03:14 +0000447 tmpInst.setOpcode(Mips::ORi);
Jack Carter2490dc62012-10-06 00:53:28 +0000448 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
449 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
450 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
451 tmpInst.setLoc(IDLoc);
Jack Carter9d577c82012-10-04 04:03:53 +0000452 Instructions.push_back(tmpInst);
453 }
454}
Jack Carter2490dc62012-10-06 00:53:28 +0000455
Jack Carter2f68b312012-10-09 23:29:45 +0000456void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
457 SmallVectorImpl<MCInst> &Instructions){
458 MCInst tmpInst;
459 const MCOperand &ImmOp = Inst.getOperand(2);
460 assert(ImmOp.isImm() && "expected immediate operand kind");
461 const MCOperand &SrcRegOp = Inst.getOperand(1);
462 assert(SrcRegOp.isReg() && "expected register operand kind");
463 const MCOperand &DstRegOp = Inst.getOperand(0);
464 assert(DstRegOp.isReg() && "expected register operand kind");
465 int ImmValue = ImmOp.getImm();
466 if ( -32768 <= ImmValue && ImmValue <= 65535) {
467 //for -32768 <= j <= 65535.
468 //la d,j(s) => addiu d,s,j
Jack Carterec3199f2013-01-12 01:03:14 +0000469 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter2f68b312012-10-09 23:29:45 +0000470 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
471 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
472 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
473 Instructions.push_back(tmpInst);
474 } else {
475 //for any other value of j that is representable as a 32-bit integer.
476 //la d,j(s) => lui d,hi16(j)
477 // ori d,d,lo16(j)
478 // addu d,d,s
Jack Carterec3199f2013-01-12 01:03:14 +0000479 tmpInst.setOpcode(Mips::LUi);
Jack Carter2f68b312012-10-09 23:29:45 +0000480 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
481 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
482 Instructions.push_back(tmpInst);
483 tmpInst.clear();
Jack Carterec3199f2013-01-12 01:03:14 +0000484 tmpInst.setOpcode(Mips::ORi);
Jack Carter2f68b312012-10-09 23:29:45 +0000485 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
486 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
487 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
488 Instructions.push_back(tmpInst);
489 tmpInst.clear();
490 tmpInst.setOpcode(Mips::ADDu);
491 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
492 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
493 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
494 Instructions.push_back(tmpInst);
495 }
496}
497
498void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
499 SmallVectorImpl<MCInst> &Instructions){
500 MCInst tmpInst;
501 const MCOperand &ImmOp = Inst.getOperand(1);
502 assert(ImmOp.isImm() && "expected immediate operand kind");
503 const MCOperand &RegOp = Inst.getOperand(0);
504 assert(RegOp.isReg() && "expected register operand kind");
505 int ImmValue = ImmOp.getImm();
506 if ( -32768 <= ImmValue && ImmValue <= 65535) {
507 //for -32768 <= j <= 65535.
508 //la d,j => addiu d,$zero,j
509 tmpInst.setOpcode(Mips::ADDiu);
510 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
511 tmpInst.addOperand(
Jack Carterec3199f2013-01-12 01:03:14 +0000512 MCOperand::CreateReg(Mips::ZERO));
Jack Carter2f68b312012-10-09 23:29:45 +0000513 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
514 Instructions.push_back(tmpInst);
515 } else {
516 //for any other value of j that is representable as a 32-bit integer.
517 //la d,j => lui d,hi16(j)
518 // ori d,d,lo16(j)
Jack Carterec3199f2013-01-12 01:03:14 +0000519 tmpInst.setOpcode(Mips::LUi);
Jack Carter2f68b312012-10-09 23:29:45 +0000520 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
521 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
522 Instructions.push_back(tmpInst);
523 tmpInst.clear();
Jack Carterec3199f2013-01-12 01:03:14 +0000524 tmpInst.setOpcode(Mips::ORi);
Jack Carter2f68b312012-10-09 23:29:45 +0000525 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
526 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
527 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
528 Instructions.push_back(tmpInst);
529 }
530}
531
Rafael Espindolafddf8042012-01-11 03:56:41 +0000532bool MipsAsmParser::
Chad Rosier84125ca2012-10-13 00:26:04 +0000533MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindolafddf8042012-01-11 03:56:41 +0000534 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier84125ca2012-10-13 00:26:04 +0000535 MCStreamer &Out, unsigned &ErrorInfo,
536 bool MatchingInlineAsm) {
Jack Carterec65be82012-09-05 23:34:03 +0000537 MCInst Inst;
Chad Rosier6e006d32012-10-12 22:53:36 +0000538 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier84125ca2012-10-13 00:26:04 +0000539 MatchingInlineAsm);
Jack Carterec65be82012-09-05 23:34:03 +0000540
541 switch (MatchResult) {
542 default: break;
543 case Match_Success: {
Jack Carter9d577c82012-10-04 04:03:53 +0000544 if (needsExpansion(Inst)) {
Jack Carter2490dc62012-10-06 00:53:28 +0000545 SmallVector<MCInst, 4> Instructions;
Jack Carter9d577c82012-10-04 04:03:53 +0000546 expandInstruction(Inst, IDLoc, Instructions);
547 for(unsigned i =0; i < Instructions.size(); i++){
Jack Carter2490dc62012-10-06 00:53:28 +0000548 Out.EmitInstruction(Instructions[i]);
Jack Carter9d577c82012-10-04 04:03:53 +0000549 }
550 } else {
551 Inst.setLoc(IDLoc);
552 Out.EmitInstruction(Inst);
553 }
Jack Carterec65be82012-09-05 23:34:03 +0000554 return false;
555 }
556 case Match_MissingFeature:
557 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
558 return true;
559 case Match_InvalidOperand: {
560 SMLoc ErrorLoc = IDLoc;
561 if (ErrorInfo != ~0U) {
562 if (ErrorInfo >= Operands.size())
563 return Error(IDLoc, "too few operands for instruction");
564
565 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
566 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
567 }
568
569 return Error(ErrorLoc, "invalid operand for instruction");
570 }
571 case Match_MnemonicFail:
572 return Error(IDLoc, "invalid instruction");
573 }
Rafael Espindolafddf8042012-01-11 03:56:41 +0000574 return true;
575}
576
Jack Carterec3199f2013-01-12 01:03:14 +0000577int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
Jack Carterec65be82012-09-05 23:34:03 +0000578
David Chisnall572e1bd2012-10-09 16:27:43 +0000579 int CC;
Jack Carterec3199f2013-01-12 01:03:14 +0000580 if (!is64BitReg)
David Chisnall572e1bd2012-10-09 16:27:43 +0000581 CC = StringSwitch<unsigned>(Name)
582 .Case("zero", Mips::ZERO)
583 .Case("a0", Mips::A0)
584 .Case("a1", Mips::A1)
585 .Case("a2", Mips::A2)
586 .Case("a3", Mips::A3)
587 .Case("v0", Mips::V0)
588 .Case("v1", Mips::V1)
589 .Case("s0", Mips::S0)
590 .Case("s1", Mips::S1)
591 .Case("s2", Mips::S2)
592 .Case("s3", Mips::S3)
593 .Case("s4", Mips::S4)
594 .Case("s5", Mips::S5)
595 .Case("s6", Mips::S6)
596 .Case("s7", Mips::S7)
597 .Case("k0", Mips::K0)
598 .Case("k1", Mips::K1)
599 .Case("sp", Mips::SP)
600 .Case("fp", Mips::FP)
601 .Case("gp", Mips::GP)
602 .Case("ra", Mips::RA)
603 .Case("t0", Mips::T0)
604 .Case("t1", Mips::T1)
605 .Case("t2", Mips::T2)
606 .Case("t3", Mips::T3)
607 .Case("t4", Mips::T4)
608 .Case("t5", Mips::T5)
609 .Case("t6", Mips::T6)
610 .Case("t7", Mips::T7)
611 .Case("t8", Mips::T8)
612 .Case("t9", Mips::T9)
613 .Case("at", Mips::AT)
614 .Case("fcc0", Mips::FCC0)
615 .Default(-1);
616 else
617 CC = StringSwitch<unsigned>(Name)
618 .Case("zero", Mips::ZERO_64)
619 .Case("at", Mips::AT_64)
620 .Case("v0", Mips::V0_64)
621 .Case("v1", Mips::V1_64)
622 .Case("a0", Mips::A0_64)
623 .Case("a1", Mips::A1_64)
624 .Case("a2", Mips::A2_64)
625 .Case("a3", Mips::A3_64)
626 .Case("a4", Mips::T0_64)
627 .Case("a5", Mips::T1_64)
628 .Case("a6", Mips::T2_64)
629 .Case("a7", Mips::T3_64)
630 .Case("t4", Mips::T4_64)
631 .Case("t5", Mips::T5_64)
632 .Case("t6", Mips::T6_64)
633 .Case("t7", Mips::T7_64)
634 .Case("s0", Mips::S0_64)
635 .Case("s1", Mips::S1_64)
636 .Case("s2", Mips::S2_64)
637 .Case("s3", Mips::S3_64)
638 .Case("s4", Mips::S4_64)
639 .Case("s5", Mips::S5_64)
640 .Case("s6", Mips::S6_64)
641 .Case("s7", Mips::S7_64)
642 .Case("t8", Mips::T8_64)
643 .Case("t9", Mips::T9_64)
644 .Case("kt0", Mips::K0_64)
645 .Case("kt1", Mips::K1_64)
646 .Case("gp", Mips::GP_64)
647 .Case("sp", Mips::SP_64)
648 .Case("fp", Mips::FP_64)
649 .Case("s8", Mips::FP_64)
650 .Case("ra", Mips::RA_64)
651 .Default(-1);
Jack Carterec65be82012-09-05 23:34:03 +0000652
David Chisnall572e1bd2012-10-09 16:27:43 +0000653 if (CC != -1)
Jack Carterec65be82012-09-05 23:34:03 +0000654 return CC;
Jack Carterec65be82012-09-05 23:34:03 +0000655
Jack Carterf740d6e2012-09-07 00:23:42 +0000656 if (Name[0] == 'f') {
657 StringRef NumString = Name.substr(1);
658 unsigned IntVal;
659 if( NumString.getAsInteger(10, IntVal))
Jack Carter9d577c82012-10-04 04:03:53 +0000660 return -1; // not integer
Jack Carterf740d6e2012-09-07 00:23:42 +0000661 if (IntVal > 31)
662 return -1;
663
664 FpFormatTy Format = getFpFormat();
665
666 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
667 return getReg(Mips::FGR32RegClassID, IntVal);
668 if (Format == FP_FORMAT_D) {
669 if(isFP64()) {
670 return getReg(Mips::FGR64RegClassID, IntVal);
671 }
Jack Carter9d577c82012-10-04 04:03:53 +0000672 // only even numbers available as register pairs
Jack Carterf740d6e2012-09-07 00:23:42 +0000673 if (( IntVal > 31) || (IntVal%2 != 0))
674 return -1;
675 return getReg(Mips::AFGR64RegClassID, IntVal/2);
676 }
677 }
678
Jack Carterec65be82012-09-05 23:34:03 +0000679 return -1;
680}
Jack Carterf740d6e2012-09-07 00:23:42 +0000681void MipsAsmParser::setDefaultFpFormat() {
682
683 if (isMips64() || isFP64())
684 FpFormat = FP_FORMAT_D;
685 else
686 FpFormat = FP_FORMAT_S;
687}
688
689bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
690
691 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
692 .Case("ldxc1", true)
693 .Case("ldc1", true)
694 .Case("sdxc1", true)
695 .Case("sdc1", true)
696 .Default(false);
697
698 return IsDouble;
699}
700void MipsAsmParser::setFpFormat(StringRef Format) {
701
702 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
703 .Case(".s", FP_FORMAT_S)
704 .Case(".d", FP_FORMAT_D)
705 .Case(".l", FP_FORMAT_L)
706 .Case(".w", FP_FORMAT_W)
707 .Default(FP_FORMAT_NONE);
708}
Jack Carterec65be82012-09-05 23:34:03 +0000709
Jack Carter30116cd2012-10-04 02:29:46 +0000710bool MipsAssemblerOptions::setATReg(unsigned Reg) {
711 if (Reg > 31)
712 return false;
713
714 aTReg = Reg;
715 return true;
716}
717
718unsigned MipsAsmParser::getATReg() {
Jack Carter10d5ff62012-10-05 23:55:28 +0000719 unsigned Reg = Options.getATRegNum();
Jack Carter30116cd2012-10-04 02:29:46 +0000720 if (isMips64())
721 return getReg(Mips::CPU64RegsRegClassID,Reg);
Jack Carterec3199f2013-01-12 01:03:14 +0000722
Jack Carter10d5ff62012-10-05 23:55:28 +0000723 return getReg(Mips::CPURegsRegClassID,Reg);
Jack Carter30116cd2012-10-04 02:29:46 +0000724}
725
726unsigned MipsAsmParser::getReg(int RC,int RegNo) {
Jack Carterec65be82012-09-05 23:34:03 +0000727 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
728}
729
Jack Carterec3199f2013-01-12 01:03:14 +0000730int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Jack Carterec65be82012-09-05 23:34:03 +0000731
732 if (RegNum > 31)
733 return -1;
734
Jack Carterec3199f2013-01-12 01:03:14 +0000735 return getReg(RegClass, RegNum);
Jack Carterec65be82012-09-05 23:34:03 +0000736}
737
Jack Carterec3199f2013-01-12 01:03:14 +0000738int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterec65be82012-09-05 23:34:03 +0000739 const AsmToken &Tok = Parser.getTok();
740 int RegNum = -1;
741
742 if (Tok.is(AsmToken::Identifier)) {
743 std::string lowerCase = Tok.getString().lower();
Jack Carterec3199f2013-01-12 01:03:14 +0000744 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterec65be82012-09-05 23:34:03 +0000745 } else if (Tok.is(AsmToken::Integer))
Jack Carter9d577c82012-10-04 04:03:53 +0000746 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carterec3199f2013-01-12 01:03:14 +0000747 is64BitReg ? Mips::CPU64RegsRegClassID
748 : Mips::CPURegsRegClassID);
Jack Carterec65be82012-09-05 23:34:03 +0000749 return RegNum;
750}
751
Rafael Espindolafddf8042012-01-11 03:56:41 +0000752bool MipsAsmParser::
Jack Carterec65be82012-09-05 23:34:03 +0000753 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carterec3199f2013-01-12 01:03:14 +0000754 bool is64BitReg){
Jack Carterec65be82012-09-05 23:34:03 +0000755
756 SMLoc S = Parser.getTok().getLoc();
757 int RegNo = -1;
Jack Carterf740d6e2012-09-07 00:23:42 +0000758
Jack Carterec3199f2013-01-12 01:03:14 +0000759 RegNo = tryParseRegister(is64BitReg);
Jack Carterec65be82012-09-05 23:34:03 +0000760 if (RegNo == -1)
761 return true;
762
Jack Carterec3199f2013-01-12 01:03:14 +0000763 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
764 Parser.getTok().getLoc()));
Jack Carterec65be82012-09-05 23:34:03 +0000765 Parser.Lex(); // Eat register token.
766 return false;
767}
768
769bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
770 StringRef Mnemonic) {
Jack Carter9d577c82012-10-04 04:03:53 +0000771 // Check if the current operand has a custom associated parser, if so, try to
772 // custom parse the operand, or fallback to the general approach.
Jack Carterec65be82012-09-05 23:34:03 +0000773 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
774 if (ResTy == MatchOperand_Success)
775 return false;
776 // If there wasn't a custom match, try the generic matcher below. Otherwise,
777 // there was a match, but an error occurred, in which case, just return that
778 // the operand parsing failed.
779 if (ResTy == MatchOperand_ParseFail)
780 return true;
781
782 switch (getLexer().getKind()) {
783 default:
784 Error(Parser.getTok().getLoc(), "unexpected token in operand");
785 return true;
786 case AsmToken::Dollar: {
Jack Carter9d577c82012-10-04 04:03:53 +0000787 // parse register
Jack Carterec65be82012-09-05 23:34:03 +0000788 SMLoc S = Parser.getTok().getLoc();
789 Parser.Lex(); // Eat dollar token.
Jack Carter9d577c82012-10-04 04:03:53 +0000790 // parse register operand
Jack Carterec3199f2013-01-12 01:03:14 +0000791 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterec65be82012-09-05 23:34:03 +0000792 if (getLexer().is(AsmToken::LParen)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000793 // check if it is indexed addressing operand
Jack Carterec65be82012-09-05 23:34:03 +0000794 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carter9d577c82012-10-04 04:03:53 +0000795 Parser.Lex(); // eat parenthesis
Jack Carterec65be82012-09-05 23:34:03 +0000796 if (getLexer().isNot(AsmToken::Dollar))
797 return true;
798
Jack Carter9d577c82012-10-04 04:03:53 +0000799 Parser.Lex(); // eat dollar
Jack Carterec3199f2013-01-12 01:03:14 +0000800 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterec65be82012-09-05 23:34:03 +0000801 return true;
802
803 if (!getLexer().is(AsmToken::RParen))
804 return true;
805
806 S = Parser.getTok().getLoc();
807 Operands.push_back(MipsOperand::CreateToken(")", S));
808 Parser.Lex();
809 }
810 return false;
811 }
Jack Carter9d577c82012-10-04 04:03:53 +0000812 // maybe it is a symbol reference
Jack Carterec65be82012-09-05 23:34:03 +0000813 StringRef Identifier;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000814 if (Parser.parseIdentifier(Identifier))
Jack Carterec65be82012-09-05 23:34:03 +0000815 return true;
816
Jack Carterec3199f2013-01-12 01:03:14 +0000817 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000818
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000819 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterec65be82012-09-05 23:34:03 +0000820
821 // Otherwise create a symbol ref.
Jack Carter6b96c3f2012-09-06 20:00:02 +0000822 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterec65be82012-09-05 23:34:03 +0000823 getContext());
824
825 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
826 return false;
827 }
828 case AsmToken::Identifier:
829 case AsmToken::LParen:
830 case AsmToken::Minus:
831 case AsmToken::Plus:
832 case AsmToken::Integer:
833 case AsmToken::String: {
834 // quoted label names
835 const MCExpr *IdVal;
836 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000837 if (getParser().parseExpression(IdVal))
Jack Carterec65be82012-09-05 23:34:03 +0000838 return true;
Jack Carterec3199f2013-01-12 01:03:14 +0000839 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000840 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
841 return false;
842 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000843 case AsmToken::Percent: {
Jack Carter9d577c82012-10-04 04:03:53 +0000844 // it is a symbol reference or constant expression
Jack Carter6b96c3f2012-09-06 20:00:02 +0000845 const MCExpr *IdVal;
Jack Carter9d577c82012-10-04 04:03:53 +0000846 SMLoc S = Parser.getTok().getLoc(); // start location of the operand
Jack Carterec3199f2013-01-12 01:03:14 +0000847 if (parseRelocOperand(IdVal))
Jack Carter6b96c3f2012-09-06 20:00:02 +0000848 return true;
849
Jack Carterec3199f2013-01-12 01:03:14 +0000850 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
851
Jack Carter6b96c3f2012-09-06 20:00:02 +0000852 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
853 return false;
Jack Carter30116cd2012-10-04 02:29:46 +0000854 } // case AsmToken::Percent
855 } // switch(getLexer().getKind())
Rafael Espindolafddf8042012-01-11 03:56:41 +0000856 return true;
857}
858
Jack Carterec3199f2013-01-12 01:03:14 +0000859bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000860
Jack Carter30116cd2012-10-04 02:29:46 +0000861 Parser.Lex(); // eat % token
Jack Carter9d577c82012-10-04 04:03:53 +0000862 const AsmToken &Tok = Parser.getTok(); // get next token, operation
Jack Carter6b96c3f2012-09-06 20:00:02 +0000863 if (Tok.isNot(AsmToken::Identifier))
864 return true;
865
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000866 std::string Str = Tok.getIdentifier().str();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000867
Jack Carter9d577c82012-10-04 04:03:53 +0000868 Parser.Lex(); // eat identifier
Jack Carter30116cd2012-10-04 02:29:46 +0000869 // now make expression from the rest of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000870 const MCExpr *IdVal;
Jack Carterec3199f2013-01-12 01:03:14 +0000871 SMLoc EndLoc;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000872
873 if (getLexer().getKind() == AsmToken::LParen) {
874 while (1) {
Jack Carter30116cd2012-10-04 02:29:46 +0000875 Parser.Lex(); // eat '(' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000876 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carter30116cd2012-10-04 02:29:46 +0000877 Parser.Lex(); // eat % token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000878 const AsmToken &nextTok = Parser.getTok();
879 if (nextTok.isNot(AsmToken::Identifier))
880 return true;
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000881 Str += "(%";
882 Str += nextTok.getIdentifier();
Jack Carter30116cd2012-10-04 02:29:46 +0000883 Parser.Lex(); // eat identifier
Jack Carter6b96c3f2012-09-06 20:00:02 +0000884 if (getLexer().getKind() != AsmToken::LParen)
885 return true;
886 } else
887 break;
888 }
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000889 if (getParser().parseParenExpression(IdVal,EndLoc))
Jack Carter6b96c3f2012-09-06 20:00:02 +0000890 return true;
891
Jack Carterec3199f2013-01-12 01:03:14 +0000892 while (getLexer().getKind() == AsmToken::RParen)
Jack Carter30116cd2012-10-04 02:29:46 +0000893 Parser.Lex(); // eat ')' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000894
895 } else
Jack Carter30116cd2012-10-04 02:29:46 +0000896 return true; // parenthesis must follow reloc operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000897
Jack Carter30116cd2012-10-04 02:29:46 +0000898 // Check the type of the expression
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000899 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000900 // it's a constant, evaluate lo or hi value
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000901 int Val = MCE->getValue();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000902 if (Str == "lo") {
903 Val = Val & 0xffff;
904 } else if (Str == "hi") {
905 Val = (Val & 0xffff0000) >> 16;
906 }
907 Res = MCConstantExpr::Create(Val, getContext());
908 return false;
909 }
910
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000911 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter30116cd2012-10-04 02:29:46 +0000912 // it's a symbol, create symbolic expression from symbol
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000913 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000914 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
915 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
916 return false;
917 }
918 return true;
919}
920
Jack Carterec65be82012-09-05 23:34:03 +0000921bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
922 SMLoc &EndLoc) {
923
924 StartLoc = Parser.getTok().getLoc();
Jack Carterec3199f2013-01-12 01:03:14 +0000925 RegNo = tryParseRegister(isMips64());
926 EndLoc = Parser.getTok().getLoc();
Jack Carterec65be82012-09-05 23:34:03 +0000927 return (RegNo == (unsigned)-1);
928}
929
Jack Carter6b96c3f2012-09-06 20:00:02 +0000930bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
Jack Carterec3199f2013-01-12 01:03:14 +0000931
932 SMLoc S;
933
Jack Carter6b96c3f2012-09-06 20:00:02 +0000934 switch(getLexer().getKind()) {
935 default:
936 return true;
937 case AsmToken::Integer:
938 case AsmToken::Minus:
939 case AsmToken::Plus:
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +0000940 return (getParser().parseExpression(Res));
Jack Carterec3199f2013-01-12 01:03:14 +0000941 case AsmToken::Percent:
942 return parseRelocOperand(Res);
Jack Carter6b96c3f2012-09-06 20:00:02 +0000943 case AsmToken::LParen:
Jack Carter30116cd2012-10-04 02:29:46 +0000944 return false; // it's probably assuming 0
Jack Carter6b96c3f2012-09-06 20:00:02 +0000945 }
946 return true;
947}
948
Jack Carterec65be82012-09-05 23:34:03 +0000949MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
950 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000951
952 const MCExpr *IdVal = 0;
Jack Carterec3199f2013-01-12 01:03:14 +0000953 SMLoc S;
954 // first operand is the offset
955 S = Parser.getTok().getLoc();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000956
957 if (parseMemOffset(IdVal))
958 return MatchOperand_ParseFail;
959
Jack Carter30116cd2012-10-04 02:29:46 +0000960 const AsmToken &Tok = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000961 if (Tok.isNot(AsmToken::LParen)) {
Jack Carter2f68b312012-10-09 23:29:45 +0000962 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
963 if (Mnemonic->getToken() == "la") {
Jack Carterec3199f2013-01-12 01:03:14 +0000964 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() -1);
Jack Carter2f68b312012-10-09 23:29:45 +0000965 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
966 return MatchOperand_Success;
967 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000968 Error(Parser.getTok().getLoc(), "'(' expected");
969 return MatchOperand_ParseFail;
970 }
971
972 Parser.Lex(); // Eat '(' token.
973
Jack Carter2f68b312012-10-09 23:29:45 +0000974 const AsmToken &Tok1 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000975 if (Tok1.is(AsmToken::Dollar)) {
976 Parser.Lex(); // Eat '$' token.
Jack Carterec3199f2013-01-12 01:03:14 +0000977 if (tryParseRegisterOperand(Operands, isMips64())) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000978 Error(Parser.getTok().getLoc(), "unexpected token in operand");
979 return MatchOperand_ParseFail;
980 }
981
982 } else {
Jack Carter30116cd2012-10-04 02:29:46 +0000983 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carter6b96c3f2012-09-06 20:00:02 +0000984 return MatchOperand_ParseFail;
985 }
986
Jack Carter30116cd2012-10-04 02:29:46 +0000987 const AsmToken &Tok2 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000988 if (Tok2.isNot(AsmToken::RParen)) {
989 Error(Parser.getTok().getLoc(), "')' expected");
990 return MatchOperand_ParseFail;
991 }
992
Jack Carterec3199f2013-01-12 01:03:14 +0000993 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
994
Jack Carter6b96c3f2012-09-06 20:00:02 +0000995 Parser.Lex(); // Eat ')' token.
996
997 if (IdVal == 0)
998 IdVal = MCConstantExpr::Create(0, getContext());
999
Jack Carter30116cd2012-10-04 02:29:46 +00001000 // now replace register operand with the mem operand
Jack Carter6b96c3f2012-09-06 20:00:02 +00001001 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1002 int RegNo = op->getReg();
Jack Carter30116cd2012-10-04 02:29:46 +00001003 // remove register from operands
Jack Carter6b96c3f2012-09-06 20:00:02 +00001004 Operands.pop_back();
Jack Carter30116cd2012-10-04 02:29:46 +00001005 // and add memory operand
Jack Carter6b96c3f2012-09-06 20:00:02 +00001006 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1007 delete op;
Jack Carterec65be82012-09-05 23:34:03 +00001008 return MatchOperand_Success;
1009}
1010
Jack Carterec3199f2013-01-12 01:03:14 +00001011MipsAsmParser::OperandMatchResultTy
1012MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1013
1014 if (!isMips64())
1015 return MatchOperand_NoMatch;
1016 // if the first token is not '$' we have an error
1017 if (Parser.getTok().isNot(AsmToken::Dollar))
1018 return MatchOperand_NoMatch;
1019
1020 Parser.Lex(); // Eat $
1021 if(!tryParseRegisterOperand(Operands, true)) {
1022 // set the proper register kind
1023 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1024 op->setRegKind(MipsOperand::Kind_CPU64Regs);
1025 return MatchOperand_Success;
1026 }
1027 return MatchOperand_NoMatch;
1028}
1029
1030MipsAsmParser::OperandMatchResultTy
1031MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1032
1033 // if the first token is not '$' we have an error
1034 if (Parser.getTok().isNot(AsmToken::Dollar))
1035 return MatchOperand_NoMatch;
1036
1037 Parser.Lex(); // Eat $
1038 if(!tryParseRegisterOperand(Operands, false)) {
1039 // set the propper register kind
1040 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1041 op->setRegKind(MipsOperand::Kind_CPURegs);
1042 return MatchOperand_Success;
1043 }
1044 return MatchOperand_NoMatch;
1045}
1046
1047MipsAsmParser::OperandMatchResultTy
1048MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1049
Jack Carterc147b672013-01-17 00:28:20 +00001050 if (isMips64())
1051 return MatchOperand_NoMatch;
1052
Jack Carterec3199f2013-01-12 01:03:14 +00001053 // if the first token is not '$' we have error
1054 if (Parser.getTok().isNot(AsmToken::Dollar))
1055 return MatchOperand_NoMatch;
1056 SMLoc S = Parser.getTok().getLoc();
1057 Parser.Lex(); // Eat $
1058
1059 const AsmToken &Tok = Parser.getTok(); // get next token
1060 if (Tok.isNot(AsmToken::Integer))
1061 return MatchOperand_NoMatch;
1062
1063 unsigned RegNum = Tok.getIntVal();
1064 // at the moment only hwreg29 is supported
1065 if (RegNum != 29)
1066 return MatchOperand_ParseFail;
1067
1068 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
1069 Parser.getTok().getLoc());
1070 op->setRegKind(MipsOperand::Kind_HWRegs);
1071 Operands.push_back(op);
1072
1073 Parser.Lex(); // Eat reg number
1074 return MatchOperand_Success;
1075}
1076
1077MipsAsmParser::OperandMatchResultTy
1078MipsAsmParser::parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carterc147b672013-01-17 00:28:20 +00001079
1080 if (!isMips64())
1081 return MatchOperand_NoMatch;
Jack Carterec3199f2013-01-12 01:03:14 +00001082 //if the first token is not '$' we have error
1083 if (Parser.getTok().isNot(AsmToken::Dollar))
1084 return MatchOperand_NoMatch;
1085 SMLoc S = Parser.getTok().getLoc();
1086 Parser.Lex(); // Eat $
1087
1088 const AsmToken &Tok = Parser.getTok(); // get next token
1089 if (Tok.isNot(AsmToken::Integer))
1090 return MatchOperand_NoMatch;
1091
1092 unsigned RegNum = Tok.getIntVal();
1093 // at the moment only hwreg29 is supported
1094 if (RegNum != 29)
1095 return MatchOperand_ParseFail;
1096
1097 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
1098 Parser.getTok().getLoc());
Jack Carterc147b672013-01-17 00:28:20 +00001099 op->setRegKind(MipsOperand::Kind_HW64Regs);
Jack Carterec3199f2013-01-12 01:03:14 +00001100 Operands.push_back(op);
1101
1102 Parser.Lex(); // Eat reg number
1103 return MatchOperand_Success;
1104}
1105
1106MipsAsmParser::OperandMatchResultTy
1107MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1108 unsigned RegNum;
1109 //if the first token is not '$' we have error
1110 if (Parser.getTok().isNot(AsmToken::Dollar))
1111 return MatchOperand_NoMatch;
1112 SMLoc S = Parser.getTok().getLoc();
1113 Parser.Lex(); // Eat $
1114
1115 const AsmToken &Tok = Parser.getTok(); // get next token
1116 if (Tok.is(AsmToken::Integer)) {
1117 RegNum = Tok.getIntVal();
1118 // at the moment only fcc0 is supported
1119 if (RegNum != 0)
1120 return MatchOperand_ParseFail;
1121 } else if (Tok.is(AsmToken::Identifier)) {
1122 // at the moment only fcc0 is supported
1123 if (Tok.getIdentifier() != "fcc0")
1124 return MatchOperand_ParseFail;
1125 } else
1126 return MatchOperand_NoMatch;
1127
1128 MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
1129 Parser.getTok().getLoc());
1130 op->setRegKind(MipsOperand::Kind_CCRRegs);
1131 Operands.push_back(op);
1132
1133 Parser.Lex(); // Eat reg number
1134 return MatchOperand_Success;
1135}
1136
Jack Carter6b96c3f2012-09-06 20:00:02 +00001137MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1138
1139 MCSymbolRefExpr::VariantKind VK
1140 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1141 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1142 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1143 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1144 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1145 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1146 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1147 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1148 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1149 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1150 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1151 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1152 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1153 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1154 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1155 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1156 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1157 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1158 .Default(MCSymbolRefExpr::VK_None);
1159
1160 return VK;
1161}
1162
Benjamin Kramer1ac45872012-09-10 11:52:14 +00001163static int ConvertCcString(StringRef CondString) {
Jack Carterf740d6e2012-09-07 00:23:42 +00001164 int CC = StringSwitch<unsigned>(CondString)
1165 .Case(".f", 0)
1166 .Case(".un", 1)
1167 .Case(".eq", 2)
1168 .Case(".ueq", 3)
1169 .Case(".olt", 4)
1170 .Case(".ult", 5)
1171 .Case(".ole", 6)
1172 .Case(".ule", 7)
1173 .Case(".sf", 8)
1174 .Case(".ngle", 9)
1175 .Case(".seq", 10)
1176 .Case(".ngl", 11)
1177 .Case(".lt", 12)
1178 .Case(".nge", 13)
1179 .Case(".le", 14)
1180 .Case(".ngt", 15)
1181 .Default(-1);
1182
1183 return CC;
1184}
1185
1186bool MipsAsmParser::
1187parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter30116cd2012-10-04 02:29:46 +00001188 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1189 // split the format
Jack Carterf740d6e2012-09-07 00:23:42 +00001190 size_t Start = Name.find('.'), Next = Name.rfind('.');
1191 StringRef Format1 = Name.slice(Start, Next);
Jack Carter30116cd2012-10-04 02:29:46 +00001192 // and add the first format to the operands
Jack Carterf740d6e2012-09-07 00:23:42 +00001193 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carter30116cd2012-10-04 02:29:46 +00001194 // now for the second format
Jack Carterf740d6e2012-09-07 00:23:42 +00001195 StringRef Format2 = Name.slice(Next, StringRef::npos);
1196 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1197
Jack Carter30116cd2012-10-04 02:29:46 +00001198 // set the format for the first register
Jack Carterf740d6e2012-09-07 00:23:42 +00001199 setFpFormat(Format1);
1200
1201 // Read the remaining operands.
1202 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1203 // Read the first operand.
1204 if (ParseOperand(Operands, Name)) {
1205 SMLoc Loc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +00001206 Parser.eatToEndOfStatement();
Jack Carterf740d6e2012-09-07 00:23:42 +00001207 return Error(Loc, "unexpected token in argument list");
1208 }
1209
1210 if (getLexer().isNot(AsmToken::Comma)) {
1211 SMLoc Loc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +00001212 Parser.eatToEndOfStatement();
Jack Carterf740d6e2012-09-07 00:23:42 +00001213 return Error(Loc, "unexpected token in argument list");
1214
1215 }
1216 Parser.Lex(); // Eat the comma.
1217
1218 //set the format for the first register
1219 setFpFormat(Format2);
1220
1221 // Parse and remember the operand.
1222 if (ParseOperand(Operands, Name)) {
1223 SMLoc Loc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +00001224 Parser.eatToEndOfStatement();
Jack Carterf740d6e2012-09-07 00:23:42 +00001225 return Error(Loc, "unexpected token in argument list");
1226 }
1227 }
1228
1229 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1230 SMLoc Loc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +00001231 Parser.eatToEndOfStatement();
Jack Carterf740d6e2012-09-07 00:23:42 +00001232 return Error(Loc, "unexpected token in argument list");
1233 }
1234
1235 Parser.Lex(); // Consume the EndOfStatement
1236 return false;
1237}
1238
Rafael Espindolafddf8042012-01-11 03:56:41 +00001239bool MipsAsmParser::
Chad Rosier6a020a72012-10-25 20:41:34 +00001240ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindolafddf8042012-01-11 03:56:41 +00001241 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter30116cd2012-10-04 02:29:46 +00001242 // floating point instructions: should register be treated as double?
Jack Carterf740d6e2012-09-07 00:23:42 +00001243 if (requestsDoubleOperand(Name)) {
1244 setFpFormat(FP_FORMAT_D);
Jack Carterec65be82012-09-05 23:34:03 +00001245 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterf740d6e2012-09-07 00:23:42 +00001246 }
1247 else {
1248 setDefaultFpFormat();
1249 // Create the leading tokens for the mnemonic, split by '.' characters.
1250 size_t Start = 0, Next = Name.find('.');
1251 StringRef Mnemonic = Name.slice(Start, Next);
1252
1253 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1254
1255 if (Next != StringRef::npos) {
Jack Carter30116cd2012-10-04 02:29:46 +00001256 // there is a format token in mnemonic
1257 // StringRef Rest = Name.slice(Next, StringRef::npos);
Jack Carterf740d6e2012-09-07 00:23:42 +00001258 size_t Dot = Name.find('.', Next+1);
1259 StringRef Format = Name.slice(Next, Dot);
1260 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1261 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1262 else {
1263 if (Name.startswith("c.")){
1264 // floating point compare, add '.' and immediate represent for cc
1265 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1266 int Cc = ConvertCcString(Format);
1267 if (Cc == -1) {
1268 return Error(NameLoc, "Invalid conditional code");
1269 }
Jack Carterec3199f2013-01-12 01:03:14 +00001270 SMLoc E = SMLoc::getFromPointer(
1271 Parser.getTok().getLoc().getPointer() -1 );
Jack Carterf740d6e2012-09-07 00:23:42 +00001272 Operands.push_back(MipsOperand::CreateImm(
1273 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1274 } else {
Jack Carter30116cd2012-10-04 02:29:46 +00001275 // trunc, ceil, floor ...
Jack Carterf740d6e2012-09-07 00:23:42 +00001276 return parseMathOperation(Name, NameLoc, Operands);
1277 }
1278
Jack Carter30116cd2012-10-04 02:29:46 +00001279 // the rest is a format
Jack Carterf740d6e2012-09-07 00:23:42 +00001280 Format = Name.slice(Dot, StringRef::npos);
1281 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1282 }
1283
1284 setFpFormat(Format);
1285 }
1286 }
Jack Carterec65be82012-09-05 23:34:03 +00001287
1288 // Read the remaining operands.
1289 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1290 // Read the first operand.
1291 if (ParseOperand(Operands, Name)) {
1292 SMLoc Loc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +00001293 Parser.eatToEndOfStatement();
Jack Carterec65be82012-09-05 23:34:03 +00001294 return Error(Loc, "unexpected token in argument list");
1295 }
1296
1297 while (getLexer().is(AsmToken::Comma) ) {
1298 Parser.Lex(); // Eat the comma.
1299
1300 // Parse and remember the operand.
1301 if (ParseOperand(Operands, Name)) {
1302 SMLoc Loc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +00001303 Parser.eatToEndOfStatement();
Jack Carterec65be82012-09-05 23:34:03 +00001304 return Error(Loc, "unexpected token in argument list");
1305 }
1306 }
1307 }
1308
1309 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1310 SMLoc Loc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +00001311 Parser.eatToEndOfStatement();
Jack Carterec65be82012-09-05 23:34:03 +00001312 return Error(Loc, "unexpected token in argument list");
1313 }
1314
1315 Parser.Lex(); // Consume the EndOfStatement
1316 return false;
Rafael Espindolafddf8042012-01-11 03:56:41 +00001317}
1318
Jack Carter30116cd2012-10-04 02:29:46 +00001319bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1320 SMLoc Loc = getLexer().getLoc();
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +00001321 Parser.eatToEndOfStatement();
Jack Carter30116cd2012-10-04 02:29:46 +00001322 return Error(Loc, ErrorMsg);
1323}
1324
1325bool MipsAsmParser::parseSetNoAtDirective() {
1326 // line should look like:
1327 // .set noat
1328 // set at reg to 0
Jack Carter10d5ff62012-10-05 23:55:28 +00001329 Options.setATReg(0);
Jack Carter30116cd2012-10-04 02:29:46 +00001330 // eat noat
1331 Parser.Lex();
1332 // if this is not the end of the statement, report error
1333 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1334 reportParseError("unexpected token in statement");
1335 return false;
1336 }
1337 Parser.Lex(); // Consume the EndOfStatement
1338 return false;
1339}
1340bool MipsAsmParser::parseSetAtDirective() {
1341 // line can be
1342 // .set at - defaults to $1
1343 // or .set at=$reg
1344 getParser().Lex();
1345 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter10d5ff62012-10-05 23:55:28 +00001346 Options.setATReg(1);
Jack Carter30116cd2012-10-04 02:29:46 +00001347 Parser.Lex(); // Consume the EndOfStatement
1348 return false;
1349 } else if (getLexer().is(AsmToken::Equal)) {
1350 getParser().Lex(); //eat '='
1351 if (getLexer().isNot(AsmToken::Dollar)) {
1352 reportParseError("unexpected token in statement");
1353 return false;
1354 }
1355 Parser.Lex(); // eat '$'
1356 if (getLexer().isNot(AsmToken::Integer)) {
1357 reportParseError("unexpected token in statement");
1358 return false;
1359 }
1360 const AsmToken &Reg = Parser.getTok();
Jack Carter10d5ff62012-10-05 23:55:28 +00001361 if (!Options.setATReg(Reg.getIntVal())) {
Jack Carter30116cd2012-10-04 02:29:46 +00001362 reportParseError("unexpected token in statement");
1363 return false;
1364 }
1365 getParser().Lex(); //eat reg
1366
1367 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1368 reportParseError("unexpected token in statement");
1369 return false;
1370 }
1371 Parser.Lex(); // Consume the EndOfStatement
1372 return false;
1373 } else {
1374 reportParseError("unexpected token in statement");
1375 return false;
1376 }
1377}
1378
1379bool MipsAsmParser::parseSetReorderDirective() {
1380 Parser.Lex();
1381 // if this is not the end of the statement, report error
1382 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1383 reportParseError("unexpected token in statement");
1384 return false;
1385 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001386 Options.setReorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001387 Parser.Lex(); // Consume the EndOfStatement
1388 return false;
1389}
1390
1391bool MipsAsmParser::parseSetNoReorderDirective() {
1392 Parser.Lex();
1393 // if this is not the end of the statement, report error
1394 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1395 reportParseError("unexpected token in statement");
1396 return false;
1397 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001398 Options.setNoreorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001399 Parser.Lex(); // Consume the EndOfStatement
1400 return false;
1401}
1402
1403bool MipsAsmParser::parseSetMacroDirective() {
1404 Parser.Lex();
1405 // if this is not the end of the statement, report error
1406 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1407 reportParseError("unexpected token in statement");
1408 return false;
1409 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001410 Options.setMacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001411 Parser.Lex(); // Consume the EndOfStatement
1412 return false;
1413}
1414
1415bool MipsAsmParser::parseSetNoMacroDirective() {
1416 Parser.Lex();
1417 // if this is not the end of the statement, report error
1418 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1419 reportParseError("`noreorder' must be set before `nomacro'");
1420 return false;
1421 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001422 if (Options.isReorder()) {
Jack Carter30116cd2012-10-04 02:29:46 +00001423 reportParseError("`noreorder' must be set before `nomacro'");
1424 return false;
1425 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001426 Options.setNomacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001427 Parser.Lex(); // Consume the EndOfStatement
1428 return false;
1429}
1430bool MipsAsmParser::parseDirectiveSet() {
1431
1432 // get next token
1433 const AsmToken &Tok = Parser.getTok();
1434
1435 if (Tok.getString() == "noat") {
1436 return parseSetNoAtDirective();
1437 } else if (Tok.getString() == "at") {
1438 return parseSetAtDirective();
1439 } else if (Tok.getString() == "reorder") {
1440 return parseSetReorderDirective();
1441 } else if (Tok.getString() == "noreorder") {
1442 return parseSetNoReorderDirective();
1443 } else if (Tok.getString() == "macro") {
1444 return parseSetMacroDirective();
1445 } else if (Tok.getString() == "nomacro") {
1446 return parseSetNoMacroDirective();
1447 } else if (Tok.getString() == "nomips16") {
1448 // ignore this directive for now
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +00001449 Parser.eatToEndOfStatement();
Jack Carter30116cd2012-10-04 02:29:46 +00001450 return false;
1451 } else if (Tok.getString() == "nomicromips") {
1452 // ignore this directive for now
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +00001453 Parser.eatToEndOfStatement();
Jack Carter30116cd2012-10-04 02:29:46 +00001454 return false;
1455 }
Jack Carter801c5832013-01-25 01:31:34 +00001456
Jack Carter30116cd2012-10-04 02:29:46 +00001457 return true;
1458}
1459
Jack Carter801c5832013-01-25 01:31:34 +00001460/// parseDirectiveWord
1461/// ::= .word [ expression (, expression)* ]
1462bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
1463 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1464 for (;;) {
1465 const MCExpr *Value;
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +00001466 if (getParser().parseExpression(Value))
Jack Carter801c5832013-01-25 01:31:34 +00001467 return true;
1468
1469 getParser().getStreamer().EmitValue(Value, Size);
1470
1471 if (getLexer().is(AsmToken::EndOfStatement))
1472 break;
1473
1474 // FIXME: Improve diagnostic.
1475 if (getLexer().isNot(AsmToken::Comma))
1476 return Error(L, "unexpected token in directive");
1477 Parser.Lex();
1478 }
1479 }
1480
1481 Parser.Lex();
1482 return false;
1483}
1484
Jack Carter30116cd2012-10-04 02:29:46 +00001485bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carteracbea452012-09-07 00:48:02 +00001486
Jack Carter801c5832013-01-25 01:31:34 +00001487 StringRef IDVal = DirectiveID.getString();
1488
1489 if ( IDVal == ".ent") {
Jack Carter30116cd2012-10-04 02:29:46 +00001490 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001491 Parser.Lex();
1492 return false;
1493 }
1494
Jack Carter801c5832013-01-25 01:31:34 +00001495 if (IDVal == ".end") {
Jack Carter30116cd2012-10-04 02:29:46 +00001496 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001497 Parser.Lex();
1498 return false;
1499 }
1500
Jack Carter801c5832013-01-25 01:31:34 +00001501 if (IDVal == ".frame") {
Jack Carter30116cd2012-10-04 02:29:46 +00001502 // ignore this directive for now
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +00001503 Parser.eatToEndOfStatement();
Jack Carteracbea452012-09-07 00:48:02 +00001504 return false;
1505 }
1506
Jack Carter801c5832013-01-25 01:31:34 +00001507 if (IDVal == ".set") {
Jack Carter30116cd2012-10-04 02:29:46 +00001508 return parseDirectiveSet();
Jack Carteracbea452012-09-07 00:48:02 +00001509 }
1510
Jack Carter801c5832013-01-25 01:31:34 +00001511 if (IDVal == ".fmask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001512 // ignore this directive for now
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +00001513 Parser.eatToEndOfStatement();
Jack Carteracbea452012-09-07 00:48:02 +00001514 return false;
1515 }
1516
Jack Carter801c5832013-01-25 01:31:34 +00001517 if (IDVal == ".mask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001518 // ignore this directive for now
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +00001519 Parser.eatToEndOfStatement();
Jack Carteracbea452012-09-07 00:48:02 +00001520 return false;
1521 }
1522
Jack Carter801c5832013-01-25 01:31:34 +00001523 if (IDVal == ".gpword") {
Jack Carter30116cd2012-10-04 02:29:46 +00001524 // ignore this directive for now
Jim Grosbachcb2ae3d2013-02-20 22:21:35 +00001525 Parser.eatToEndOfStatement();
Jack Carteracbea452012-09-07 00:48:02 +00001526 return false;
1527 }
1528
Jack Carter801c5832013-01-25 01:31:34 +00001529 if (IDVal == ".word") {
1530 parseDirectiveWord(4, DirectiveID.getLoc());
1531 return false;
1532 }
1533
Rafael Espindolafddf8042012-01-11 03:56:41 +00001534 return true;
1535}
1536
Rafael Espindolafddf8042012-01-11 03:56:41 +00001537extern "C" void LLVMInitializeMipsAsmParser() {
1538 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1539 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1540 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1541 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1542}
Jack Carterec65be82012-09-05 23:34:03 +00001543
1544#define GET_REGISTER_MATCHER
1545#define GET_MATCHER_IMPLEMENTATION
1546#include "MipsGenAsmMatcher.inc"