blob: c2980ffeea8daf7d5feaee34bef8694bb76510b4 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-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 Carterb4dbc172012-09-05 23:34:03 +000011#include "MipsRegisterInfo.h"
12#include "llvm/ADT/StringSwitch.h"
13#include "llvm/MC/MCContext.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCInst.h"
16#include "llvm/MC/MCStreamer.h"
17#include "llvm/MC/MCSubtargetInfo.h"
18#include "llvm/MC/MCSymbol.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000019#include "llvm/MC/MCParser/MCAsmLexer.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000020#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21#include "llvm/MC/MCTargetAsmParser.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000022#include "llvm/Support/TargetRegistry.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000023
24using namespace llvm;
25
26namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000027class MipsAssemblerOptions {
28public:
29 MipsAssemblerOptions():
30 aTReg(1), reorder(true), macro(true) {
31 }
Jack Carterb4dbc172012-09-05 23:34:03 +000032
Jack Carter0b744b32012-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 Espindola870c4e92012-01-11 03:56:41 +000052class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka7605630c2012-08-17 20:16:42 +000053
Jack Cartera63b16a2012-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 Carterb4dbc172012-09-05 23:34:03 +000062 MCSubtargetInfo &STI;
63 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000064 MipsAssemblerOptions Options;
Jack Carter0b744b32012-10-04 02:29:46 +000065
Jack Carterb4dbc172012-09-05 23:34:03 +000066
Akira Hatanaka7605630c2012-08-17 20:16:42 +000067#define GET_ASSEMBLER_HEADER
68#include "MipsGenAsmMatcher.inc"
69
Rafael Espindola870c4e92012-01-11 03:56:41 +000070 bool MatchAndEmitInstruction(SMLoc IDLoc,
71 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
72 MCStreamer &Out);
73
74 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
75
76 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Akira Hatanaka7605630c2012-08-17 20:16:42 +000077 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindola870c4e92012-01-11 03:56:41 +000078
Jack Cartera63b16a2012-09-07 00:23:42 +000079 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
80 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
81
Rafael Espindola870c4e92012-01-11 03:56:41 +000082 bool ParseDirective(AsmToken DirectiveID);
83
Jack Carterb4dbc172012-09-05 23:34:03 +000084 MipsAsmParser::OperandMatchResultTy
85 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
Chad Rosier391d29972012-09-03 18:47:45 +000086
Jack Carterb4dbc172012-09-05 23:34:03 +000087 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
88 StringRef Mnemonic);
89
90 int tryParseRegister(StringRef Mnemonic);
91
92 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
93 StringRef Mnemonic);
94
Jack Carter30a59822012-10-04 04:03:53 +000095 bool needsExpansion(MCInst &Inst);
96
97 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +000098 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +000099 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000100 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000101 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
102 SmallVectorImpl<MCInst> &Instructions);
103 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
104 SmallVectorImpl<MCInst> &Instructions);
Jack Carter0b744b32012-10-04 02:29:46 +0000105 bool reportParseError(StringRef ErrorMsg);
106
Jack Carterdc1e35d2012-09-06 20:00:02 +0000107 bool parseMemOffset(const MCExpr *&Res);
108 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000109
110 bool parseDirectiveSet();
111
112 bool parseSetAtDirective();
113 bool parseSetNoAtDirective();
114 bool parseSetMacroDirective();
115 bool parseSetNoMacroDirective();
116 bool parseSetReorderDirective();
117 bool parseSetNoReorderDirective();
118
Jack Carterdc1e35d2012-09-06 20:00:02 +0000119 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000120
Jack Carterb4dbc172012-09-05 23:34:03 +0000121 bool isMips64() const {
122 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
123 }
124
Jack Cartera63b16a2012-09-07 00:23:42 +0000125 bool isFP64() const {
126 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
127 }
128
Jack Carterb4dbc172012-09-05 23:34:03 +0000129 int matchRegisterName(StringRef Symbol);
130
131 int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
132
Jack Cartera63b16a2012-09-07 00:23:42 +0000133 void setFpFormat(FpFormatTy Format) {
134 FpFormat = Format;
135 }
136
137 void setDefaultFpFormat();
138
139 void setFpFormat(StringRef Format);
140
141 FpFormatTy getFpFormat() {return FpFormat;}
142
143 bool requestsDoubleOperand(StringRef Mnemonic);
144
Jack Carterb4dbc172012-09-05 23:34:03 +0000145 unsigned getReg(int RC,int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000146
Jack Carter0b744b32012-10-04 02:29:46 +0000147 unsigned getATReg();
Rafael Espindola870c4e92012-01-11 03:56:41 +0000148public:
149 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterb4dbc172012-09-05 23:34:03 +0000150 : MCTargetAsmParser(), STI(sti), Parser(parser) {
151 // Initialize the set of available features.
152 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindola870c4e92012-01-11 03:56:41 +0000153 }
154
Jack Carterb4dbc172012-09-05 23:34:03 +0000155 MCAsmParser &getParser() const { return Parser; }
156 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
157
Rafael Espindola870c4e92012-01-11 03:56:41 +0000158};
159}
160
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000161namespace {
162
163/// MipsOperand - Instances of this class represent a parsed Mips machine
164/// instruction.
165class MipsOperand : public MCParsedAsmOperand {
Jack Carterb4dbc172012-09-05 23:34:03 +0000166
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000167 enum KindTy {
168 k_CondCode,
169 k_CoprocNum,
170 k_Immediate,
171 k_Memory,
172 k_PostIndexRegister,
173 k_Register,
174 k_Token
175 } Kind;
176
177 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterb4dbc172012-09-05 23:34:03 +0000178
179 union {
180 struct {
181 const char *Data;
182 unsigned Length;
183 } Tok;
184
185 struct {
186 unsigned RegNum;
187 } Reg;
188
189 struct {
190 const MCExpr *Val;
191 } Imm;
Jack Carterdc1e35d2012-09-06 20:00:02 +0000192
193 struct {
194 unsigned Base;
195 const MCExpr *Off;
196 } Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000197 };
198
199 SMLoc StartLoc, EndLoc;
200
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000201public:
202 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000203 assert(N == 1 && "Invalid number of operands!");
204 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000205 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000206
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000207 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterb4dbc172012-09-05 23:34:03 +0000208 // Add as immediate when possible. Null MCExpr = 0.
209 if (Expr == 0)
210 Inst.addOperand(MCOperand::CreateImm(0));
211 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
212 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
213 else
214 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000215 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000216
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000217 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000218 assert(N == 1 && "Invalid number of operands!");
219 const MCExpr *Expr = getImm();
220 addExpr(Inst,Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000221 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000222
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000223 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000224 assert(N == 2 && "Invalid number of operands!");
225
226 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
227
228 const MCExpr *Expr = getMemOff();
229 addExpr(Inst,Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000230 }
231
232 bool isReg() const { return Kind == k_Register; }
233 bool isImm() const { return Kind == k_Immediate; }
234 bool isToken() const { return Kind == k_Token; }
235 bool isMem() const { return Kind == k_Memory; }
236
237 StringRef getToken() const {
238 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000239 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000240 }
241
242 unsigned getReg() const {
243 assert((Kind == k_Register) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000244 return Reg.RegNum;
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000245 }
246
Jack Carterb4dbc172012-09-05 23:34:03 +0000247 const MCExpr *getImm() const {
248 assert((Kind == k_Immediate) && "Invalid access!");
249 return Imm.Val;
250 }
251
Jack Carterdc1e35d2012-09-06 20:00:02 +0000252 unsigned getMemBase() const {
253 assert((Kind == k_Memory) && "Invalid access!");
254 return Mem.Base;
255 }
256
257 const MCExpr *getMemOff() const {
258 assert((Kind == k_Memory) && "Invalid access!");
259 return Mem.Off;
260 }
261
Jack Carterb4dbc172012-09-05 23:34:03 +0000262 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
263 MipsOperand *Op = new MipsOperand(k_Token);
264 Op->Tok.Data = Str.data();
265 Op->Tok.Length = Str.size();
266 Op->StartLoc = S;
267 Op->EndLoc = S;
268 return Op;
269 }
270
271 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
272 MipsOperand *Op = new MipsOperand(k_Register);
273 Op->Reg.RegNum = RegNum;
274 Op->StartLoc = S;
275 Op->EndLoc = E;
276 return Op;
277 }
278
279 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
280 MipsOperand *Op = new MipsOperand(k_Immediate);
281 Op->Imm.Val = Val;
282 Op->StartLoc = S;
283 Op->EndLoc = E;
284 return Op;
285 }
286
Jack Carterdc1e35d2012-09-06 20:00:02 +0000287 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
288 SMLoc S, SMLoc E) {
289 MipsOperand *Op = new MipsOperand(k_Memory);
290 Op->Mem.Base = Base;
291 Op->Mem.Off = Off;
292 Op->StartLoc = S;
293 Op->EndLoc = E;
294 return Op;
295 }
296
Jack Carterb4dbc172012-09-05 23:34:03 +0000297 /// getStartLoc - Get the location of the first token of this operand.
298 SMLoc getStartLoc() const { return StartLoc; }
299 /// getEndLoc - Get the location of the last token of this operand.
300 SMLoc getEndLoc() const { return EndLoc; }
301
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000302 virtual void print(raw_ostream &OS) const {
303 llvm_unreachable("unimplemented!");
304 }
305};
306}
307
Jack Carter30a59822012-10-04 04:03:53 +0000308bool MipsAsmParser::needsExpansion(MCInst &Inst) {
309
310 switch(Inst.getOpcode()) {
311 case Mips::LoadImm32Reg:
Jack Carter543fdf82012-10-09 23:29:45 +0000312 case Mips::LoadAddr32Imm:
313 case Mips::LoadAddr32Reg:
Jack Carter30a59822012-10-04 04:03:53 +0000314 return true;
315 default:
316 return false;
317 }
318}
Jack Carter92995f12012-10-06 00:53:28 +0000319
Jack Carter30a59822012-10-04 04:03:53 +0000320void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000321 SmallVectorImpl<MCInst> &Instructions){
Jack Carter30a59822012-10-04 04:03:53 +0000322 switch(Inst.getOpcode()) {
323 case Mips::LoadImm32Reg:
324 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000325 case Mips::LoadAddr32Imm:
326 return expandLoadAddressImm(Inst,IDLoc,Instructions);
327 case Mips::LoadAddr32Reg:
328 return expandLoadAddressReg(Inst,IDLoc,Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000329 }
Jack Carter30a59822012-10-04 04:03:53 +0000330}
Jack Carter92995f12012-10-06 00:53:28 +0000331
Jack Carter30a59822012-10-04 04:03:53 +0000332void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000333 SmallVectorImpl<MCInst> &Instructions){
Jack Carter92995f12012-10-06 00:53:28 +0000334 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000335 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000336 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000337 const MCOperand &RegOp = Inst.getOperand(0);
338 assert(RegOp.isReg() && "expected register operand kind");
339
340 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000341 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000342 if ( 0 <= ImmValue && ImmValue <= 65535) {
Jack Carter92995f12012-10-06 00:53:28 +0000343 // for 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000344 // li d,j => ori d,$zero,j
Jack Carter92995f12012-10-06 00:53:28 +0000345 tmpInst.setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
346 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
347 tmpInst.addOperand(
Jack Carter30a59822012-10-04 04:03:53 +0000348 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000349 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000350 Instructions.push_back(tmpInst);
351 } else if ( ImmValue < 0 && ImmValue >= -32768) {
Jack Carter92995f12012-10-06 00:53:28 +0000352 // for -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000353 // li d,j => addiu d,$zero,j
Jack Carter92995f12012-10-06 00:53:28 +0000354 tmpInst.setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
355 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
356 tmpInst.addOperand(
Jack Carter30a59822012-10-04 04:03:53 +0000357 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000358 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000359 Instructions.push_back(tmpInst);
360 } else {
361 // for any other value of j that is representable as a 32-bit integer.
362 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000363 // ori d,d,lo16(j)
Jack Carter92995f12012-10-06 00:53:28 +0000364 tmpInst.setOpcode(isMips64() ? Mips::LUi64 : Mips::LUi);
365 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
366 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000367 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000368 tmpInst.clear();
369 tmpInst.setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
370 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
371 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
372 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
373 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000374 Instructions.push_back(tmpInst);
375 }
376}
Jack Carter92995f12012-10-06 00:53:28 +0000377
Jack Carter543fdf82012-10-09 23:29:45 +0000378void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
379 SmallVectorImpl<MCInst> &Instructions){
380 MCInst tmpInst;
381 const MCOperand &ImmOp = Inst.getOperand(2);
382 assert(ImmOp.isImm() && "expected immediate operand kind");
383 const MCOperand &SrcRegOp = Inst.getOperand(1);
384 assert(SrcRegOp.isReg() && "expected register operand kind");
385 const MCOperand &DstRegOp = Inst.getOperand(0);
386 assert(DstRegOp.isReg() && "expected register operand kind");
387 int ImmValue = ImmOp.getImm();
388 if ( -32768 <= ImmValue && ImmValue <= 65535) {
389 //for -32768 <= j <= 65535.
390 //la d,j(s) => addiu d,s,j
391 tmpInst.setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
392 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
393 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
394 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
395 Instructions.push_back(tmpInst);
396 } else {
397 //for any other value of j that is representable as a 32-bit integer.
398 //la d,j(s) => lui d,hi16(j)
399 // ori d,d,lo16(j)
400 // addu d,d,s
401 tmpInst.setOpcode(isMips64()?Mips::LUi64:Mips::LUi);
402 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
403 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
404 Instructions.push_back(tmpInst);
405 tmpInst.clear();
406 tmpInst.setOpcode(isMips64()?Mips::ORi64:Mips::ORi);
407 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
408 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
409 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
410 Instructions.push_back(tmpInst);
411 tmpInst.clear();
412 tmpInst.setOpcode(Mips::ADDu);
413 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
414 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
415 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
416 Instructions.push_back(tmpInst);
417 }
418}
419
420void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
421 SmallVectorImpl<MCInst> &Instructions){
422 MCInst tmpInst;
423 const MCOperand &ImmOp = Inst.getOperand(1);
424 assert(ImmOp.isImm() && "expected immediate operand kind");
425 const MCOperand &RegOp = Inst.getOperand(0);
426 assert(RegOp.isReg() && "expected register operand kind");
427 int ImmValue = ImmOp.getImm();
428 if ( -32768 <= ImmValue && ImmValue <= 65535) {
429 //for -32768 <= j <= 65535.
430 //la d,j => addiu d,$zero,j
431 tmpInst.setOpcode(Mips::ADDiu);
432 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
433 tmpInst.addOperand(
434 MCOperand::CreateReg(isMips64()?Mips::ZERO_64:Mips::ZERO));
435 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
436 Instructions.push_back(tmpInst);
437 } else {
438 //for any other value of j that is representable as a 32-bit integer.
439 //la d,j => lui d,hi16(j)
440 // ori d,d,lo16(j)
441 tmpInst.setOpcode(isMips64()?Mips::LUi64:Mips::LUi);
442 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
443 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
444 Instructions.push_back(tmpInst);
445 tmpInst.clear();
446 tmpInst.setOpcode(isMips64()?Mips::ORi64:Mips::ORi);
447 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
448 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
449 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
450 Instructions.push_back(tmpInst);
451 }
452}
453
Rafael Espindola870c4e92012-01-11 03:56:41 +0000454bool MipsAsmParser::
455MatchAndEmitInstruction(SMLoc IDLoc,
456 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
457 MCStreamer &Out) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000458 MCInst Inst;
Jack Carterb4dbc172012-09-05 23:34:03 +0000459 unsigned Kind;
Chad Rosierf4e35dc2012-10-01 23:45:51 +0000460 unsigned ErrorInfo;
Chad Rosier8f06e7d2012-10-05 18:41:14 +0000461 MatchInstMapAndConstraints MapAndConstraints;
Chad Rosierf4e35dc2012-10-01 23:45:51 +0000462 unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst,
463 MapAndConstraints, ErrorInfo,
464 /*matchingInlineAsm*/ false);
Jack Carterb4dbc172012-09-05 23:34:03 +0000465
466 switch (MatchResult) {
467 default: break;
468 case Match_Success: {
Jack Carter30a59822012-10-04 04:03:53 +0000469 if (needsExpansion(Inst)) {
Jack Carter92995f12012-10-06 00:53:28 +0000470 SmallVector<MCInst, 4> Instructions;
Jack Carter30a59822012-10-04 04:03:53 +0000471 expandInstruction(Inst, IDLoc, Instructions);
472 for(unsigned i =0; i < Instructions.size(); i++){
Jack Carter92995f12012-10-06 00:53:28 +0000473 Out.EmitInstruction(Instructions[i]);
Jack Carter30a59822012-10-04 04:03:53 +0000474 }
475 } else {
476 Inst.setLoc(IDLoc);
477 Out.EmitInstruction(Inst);
478 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000479 return false;
480 }
481 case Match_MissingFeature:
482 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
483 return true;
484 case Match_InvalidOperand: {
485 SMLoc ErrorLoc = IDLoc;
486 if (ErrorInfo != ~0U) {
487 if (ErrorInfo >= Operands.size())
488 return Error(IDLoc, "too few operands for instruction");
489
490 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
491 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
492 }
493
494 return Error(ErrorLoc, "invalid operand for instruction");
495 }
496 case Match_MnemonicFail:
497 return Error(IDLoc, "invalid instruction");
498 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000499 return true;
500}
501
Jack Carterb4dbc172012-09-05 23:34:03 +0000502int MipsAsmParser::matchRegisterName(StringRef Name) {
503
David Chisnall37051252012-10-09 16:27:43 +0000504 int CC;
505 if (!isMips64())
506 CC = StringSwitch<unsigned>(Name)
507 .Case("zero", Mips::ZERO)
508 .Case("a0", Mips::A0)
509 .Case("a1", Mips::A1)
510 .Case("a2", Mips::A2)
511 .Case("a3", Mips::A3)
512 .Case("v0", Mips::V0)
513 .Case("v1", Mips::V1)
514 .Case("s0", Mips::S0)
515 .Case("s1", Mips::S1)
516 .Case("s2", Mips::S2)
517 .Case("s3", Mips::S3)
518 .Case("s4", Mips::S4)
519 .Case("s5", Mips::S5)
520 .Case("s6", Mips::S6)
521 .Case("s7", Mips::S7)
522 .Case("k0", Mips::K0)
523 .Case("k1", Mips::K1)
524 .Case("sp", Mips::SP)
525 .Case("fp", Mips::FP)
526 .Case("gp", Mips::GP)
527 .Case("ra", Mips::RA)
528 .Case("t0", Mips::T0)
529 .Case("t1", Mips::T1)
530 .Case("t2", Mips::T2)
531 .Case("t3", Mips::T3)
532 .Case("t4", Mips::T4)
533 .Case("t5", Mips::T5)
534 .Case("t6", Mips::T6)
535 .Case("t7", Mips::T7)
536 .Case("t8", Mips::T8)
537 .Case("t9", Mips::T9)
538 .Case("at", Mips::AT)
539 .Case("fcc0", Mips::FCC0)
540 .Default(-1);
541 else
542 CC = StringSwitch<unsigned>(Name)
543 .Case("zero", Mips::ZERO_64)
544 .Case("at", Mips::AT_64)
545 .Case("v0", Mips::V0_64)
546 .Case("v1", Mips::V1_64)
547 .Case("a0", Mips::A0_64)
548 .Case("a1", Mips::A1_64)
549 .Case("a2", Mips::A2_64)
550 .Case("a3", Mips::A3_64)
551 .Case("a4", Mips::T0_64)
552 .Case("a5", Mips::T1_64)
553 .Case("a6", Mips::T2_64)
554 .Case("a7", Mips::T3_64)
555 .Case("t4", Mips::T4_64)
556 .Case("t5", Mips::T5_64)
557 .Case("t6", Mips::T6_64)
558 .Case("t7", Mips::T7_64)
559 .Case("s0", Mips::S0_64)
560 .Case("s1", Mips::S1_64)
561 .Case("s2", Mips::S2_64)
562 .Case("s3", Mips::S3_64)
563 .Case("s4", Mips::S4_64)
564 .Case("s5", Mips::S5_64)
565 .Case("s6", Mips::S6_64)
566 .Case("s7", Mips::S7_64)
567 .Case("t8", Mips::T8_64)
568 .Case("t9", Mips::T9_64)
569 .Case("kt0", Mips::K0_64)
570 .Case("kt1", Mips::K1_64)
571 .Case("gp", Mips::GP_64)
572 .Case("sp", Mips::SP_64)
573 .Case("fp", Mips::FP_64)
574 .Case("s8", Mips::FP_64)
575 .Case("ra", Mips::RA_64)
576 .Default(-1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000577
David Chisnall37051252012-10-09 16:27:43 +0000578 if (CC != -1)
Jack Carterb4dbc172012-09-05 23:34:03 +0000579 return CC;
Jack Carterb4dbc172012-09-05 23:34:03 +0000580
Jack Cartera63b16a2012-09-07 00:23:42 +0000581 if (Name[0] == 'f') {
582 StringRef NumString = Name.substr(1);
583 unsigned IntVal;
584 if( NumString.getAsInteger(10, IntVal))
Jack Carter30a59822012-10-04 04:03:53 +0000585 return -1; // not integer
Jack Cartera63b16a2012-09-07 00:23:42 +0000586 if (IntVal > 31)
587 return -1;
588
589 FpFormatTy Format = getFpFormat();
590
591 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
592 return getReg(Mips::FGR32RegClassID, IntVal);
593 if (Format == FP_FORMAT_D) {
594 if(isFP64()) {
595 return getReg(Mips::FGR64RegClassID, IntVal);
596 }
Jack Carter30a59822012-10-04 04:03:53 +0000597 // only even numbers available as register pairs
Jack Cartera63b16a2012-09-07 00:23:42 +0000598 if (( IntVal > 31) || (IntVal%2 != 0))
599 return -1;
600 return getReg(Mips::AFGR64RegClassID, IntVal/2);
601 }
602 }
603
Jack Carterb4dbc172012-09-05 23:34:03 +0000604 return -1;
605}
Jack Cartera63b16a2012-09-07 00:23:42 +0000606void MipsAsmParser::setDefaultFpFormat() {
607
608 if (isMips64() || isFP64())
609 FpFormat = FP_FORMAT_D;
610 else
611 FpFormat = FP_FORMAT_S;
612}
613
614bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
615
616 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
617 .Case("ldxc1", true)
618 .Case("ldc1", true)
619 .Case("sdxc1", true)
620 .Case("sdc1", true)
621 .Default(false);
622
623 return IsDouble;
624}
625void MipsAsmParser::setFpFormat(StringRef Format) {
626
627 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
628 .Case(".s", FP_FORMAT_S)
629 .Case(".d", FP_FORMAT_D)
630 .Case(".l", FP_FORMAT_L)
631 .Case(".w", FP_FORMAT_W)
632 .Default(FP_FORMAT_NONE);
633}
Jack Carterb4dbc172012-09-05 23:34:03 +0000634
Jack Carter0b744b32012-10-04 02:29:46 +0000635bool MipsAssemblerOptions::setATReg(unsigned Reg) {
636 if (Reg > 31)
637 return false;
638
639 aTReg = Reg;
640 return true;
641}
642
643unsigned MipsAsmParser::getATReg() {
Jack Carter99d2afe2012-10-05 23:55:28 +0000644 unsigned Reg = Options.getATRegNum();
Jack Carter0b744b32012-10-04 02:29:46 +0000645 if (isMips64())
646 return getReg(Mips::CPU64RegsRegClassID,Reg);
Jack Carter99d2afe2012-10-05 23:55:28 +0000647
648 return getReg(Mips::CPURegsRegClassID,Reg);
Jack Carter0b744b32012-10-04 02:29:46 +0000649}
650
651unsigned MipsAsmParser::getReg(int RC,int RegNo) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000652 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
653}
654
Jack Carter0b744b32012-10-04 02:29:46 +0000655int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000656
657 if (Mnemonic.lower() == "rdhwr") {
Jack Carter30a59822012-10-04 04:03:53 +0000658 // at the moment only hwreg29 is supported
Jack Carterb4dbc172012-09-05 23:34:03 +0000659 if (RegNum != 29)
660 return -1;
661 return Mips::HWR29;
662 }
663
664 if (RegNum > 31)
665 return -1;
666
David Chisnall37051252012-10-09 16:27:43 +0000667 // MIPS64 registers are numbered 1 after the 32-bit equivalents
668 return getReg(Mips::CPURegsRegClassID, RegNum) + isMips64();
Jack Carterb4dbc172012-09-05 23:34:03 +0000669}
670
671int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
672 const AsmToken &Tok = Parser.getTok();
673 int RegNum = -1;
674
675 if (Tok.is(AsmToken::Identifier)) {
676 std::string lowerCase = Tok.getString().lower();
677 RegNum = matchRegisterName(lowerCase);
678 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +0000679 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carterdc1e35d2012-09-06 20:00:02 +0000680 Mnemonic.lower());
Jack Cartera63b16a2012-09-07 00:23:42 +0000681 else
682 return RegNum; //error
Jack Carter30a59822012-10-04 04:03:53 +0000683 // 64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
Jack Cartera63b16a2012-09-07 00:23:42 +0000684 if (isMips64() && RegNum == Mips::ZERO_64) {
685 if (Mnemonic.find("ddiv") != StringRef::npos)
686 RegNum = Mips::ZERO;
687 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000688 return RegNum;
689}
690
Rafael Espindola870c4e92012-01-11 03:56:41 +0000691bool MipsAsmParser::
Jack Carterb4dbc172012-09-05 23:34:03 +0000692 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
693 StringRef Mnemonic){
694
695 SMLoc S = Parser.getTok().getLoc();
696 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +0000697
Jack Carter30a59822012-10-04 04:03:53 +0000698 // FIXME: we should make a more generic method for CCR
Jack Cartera63b16a2012-09-07 00:23:42 +0000699 if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
700 && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
Jack Carter30a59822012-10-04 04:03:53 +0000701 RegNo = Parser.getTok().getIntVal(); // get the int value
702 // at the moment only fcc0 is supported
Jack Cartera63b16a2012-09-07 00:23:42 +0000703 if (RegNo == 0)
704 RegNo = Mips::FCC0;
705 } else
706 RegNo = tryParseRegister(Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000707 if (RegNo == -1)
708 return true;
709
710 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Cartera63b16a2012-09-07 00:23:42 +0000711 Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000712 Parser.Lex(); // Eat register token.
713 return false;
714}
715
716bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
717 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +0000718 // Check if the current operand has a custom associated parser, if so, try to
719 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +0000720 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
721 if (ResTy == MatchOperand_Success)
722 return false;
723 // If there wasn't a custom match, try the generic matcher below. Otherwise,
724 // there was a match, but an error occurred, in which case, just return that
725 // the operand parsing failed.
726 if (ResTy == MatchOperand_ParseFail)
727 return true;
728
729 switch (getLexer().getKind()) {
730 default:
731 Error(Parser.getTok().getLoc(), "unexpected token in operand");
732 return true;
733 case AsmToken::Dollar: {
Jack Carter30a59822012-10-04 04:03:53 +0000734 // parse register
Jack Carterb4dbc172012-09-05 23:34:03 +0000735 SMLoc S = Parser.getTok().getLoc();
736 Parser.Lex(); // Eat dollar token.
Jack Carter30a59822012-10-04 04:03:53 +0000737 // parse register operand
738 if (!tryParseRegisterOperand(Operands, Mnemonic)) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000739 if (getLexer().is(AsmToken::LParen)) {
Jack Carter30a59822012-10-04 04:03:53 +0000740 // check if it is indexed addressing operand
Jack Carterb4dbc172012-09-05 23:34:03 +0000741 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carter30a59822012-10-04 04:03:53 +0000742 Parser.Lex(); // eat parenthesis
Jack Carterb4dbc172012-09-05 23:34:03 +0000743 if (getLexer().isNot(AsmToken::Dollar))
744 return true;
745
Jack Carter30a59822012-10-04 04:03:53 +0000746 Parser.Lex(); // eat dollar
747 if (tryParseRegisterOperand(Operands, Mnemonic))
Jack Carterb4dbc172012-09-05 23:34:03 +0000748 return true;
749
750 if (!getLexer().is(AsmToken::RParen))
751 return true;
752
753 S = Parser.getTok().getLoc();
754 Operands.push_back(MipsOperand::CreateToken(")", S));
755 Parser.Lex();
756 }
757 return false;
758 }
Jack Carter30a59822012-10-04 04:03:53 +0000759 // maybe it is a symbol reference
Jack Carterb4dbc172012-09-05 23:34:03 +0000760 StringRef Identifier;
761 if (Parser.ParseIdentifier(Identifier))
762 return true;
763
Jack Carterdc1e35d2012-09-06 20:00:02 +0000764 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000765
Benjamin Kramerfa530572012-09-07 09:47:42 +0000766 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterb4dbc172012-09-05 23:34:03 +0000767
768 // Otherwise create a symbol ref.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000769 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterb4dbc172012-09-05 23:34:03 +0000770 getContext());
771
772 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
773 return false;
774 }
775 case AsmToken::Identifier:
776 case AsmToken::LParen:
777 case AsmToken::Minus:
778 case AsmToken::Plus:
779 case AsmToken::Integer:
780 case AsmToken::String: {
781 // quoted label names
782 const MCExpr *IdVal;
783 SMLoc S = Parser.getTok().getLoc();
784 if (getParser().ParseExpression(IdVal))
785 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +0000786 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000787 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
788 return false;
789 }
Jack Carterdc1e35d2012-09-06 20:00:02 +0000790 case AsmToken::Percent: {
Jack Carter30a59822012-10-04 04:03:53 +0000791 // it is a symbol reference or constant expression
Jack Carterdc1e35d2012-09-06 20:00:02 +0000792 const MCExpr *IdVal;
Jack Carter30a59822012-10-04 04:03:53 +0000793 SMLoc S = Parser.getTok().getLoc(); // start location of the operand
Jack Carterdc1e35d2012-09-06 20:00:02 +0000794 if (parseRelocOperand(IdVal))
795 return true;
796
797 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
798
799 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
800 return false;
Jack Carter0b744b32012-10-04 02:29:46 +0000801 } // case AsmToken::Percent
802 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +0000803 return true;
804}
805
Jack Carterdc1e35d2012-09-06 20:00:02 +0000806bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
807
Jack Carter0b744b32012-10-04 02:29:46 +0000808 Parser.Lex(); // eat % token
Jack Carter30a59822012-10-04 04:03:53 +0000809 const AsmToken &Tok = Parser.getTok(); // get next token, operation
Jack Carterdc1e35d2012-09-06 20:00:02 +0000810 if (Tok.isNot(AsmToken::Identifier))
811 return true;
812
Benjamin Kramerfa530572012-09-07 09:47:42 +0000813 std::string Str = Tok.getIdentifier().str();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000814
Jack Carter30a59822012-10-04 04:03:53 +0000815 Parser.Lex(); // eat identifier
Jack Carter0b744b32012-10-04 02:29:46 +0000816 // now make expression from the rest of the operand
Jack Carterdc1e35d2012-09-06 20:00:02 +0000817 const MCExpr *IdVal;
818 SMLoc EndLoc;
819
820 if (getLexer().getKind() == AsmToken::LParen) {
821 while (1) {
Jack Carter0b744b32012-10-04 02:29:46 +0000822 Parser.Lex(); // eat '(' token
Jack Carterdc1e35d2012-09-06 20:00:02 +0000823 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carter0b744b32012-10-04 02:29:46 +0000824 Parser.Lex(); // eat % token
Jack Carterdc1e35d2012-09-06 20:00:02 +0000825 const AsmToken &nextTok = Parser.getTok();
826 if (nextTok.isNot(AsmToken::Identifier))
827 return true;
Benjamin Kramerfa530572012-09-07 09:47:42 +0000828 Str += "(%";
829 Str += nextTok.getIdentifier();
Jack Carter0b744b32012-10-04 02:29:46 +0000830 Parser.Lex(); // eat identifier
Jack Carterdc1e35d2012-09-06 20:00:02 +0000831 if (getLexer().getKind() != AsmToken::LParen)
832 return true;
833 } else
834 break;
835 }
836 if (getParser().ParseParenExpression(IdVal,EndLoc))
837 return true;
838
839 while (getLexer().getKind() == AsmToken::RParen)
Jack Carter0b744b32012-10-04 02:29:46 +0000840 Parser.Lex(); // eat ')' token
Jack Carterdc1e35d2012-09-06 20:00:02 +0000841
842 } else
Jack Carter0b744b32012-10-04 02:29:46 +0000843 return true; // parenthesis must follow reloc operand
Jack Carterdc1e35d2012-09-06 20:00:02 +0000844
Jack Carter0b744b32012-10-04 02:29:46 +0000845 // Check the type of the expression
Benjamin Kramerfa530572012-09-07 09:47:42 +0000846 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carter30a59822012-10-04 04:03:53 +0000847 // it's a constant, evaluate lo or hi value
Benjamin Kramerfa530572012-09-07 09:47:42 +0000848 int Val = MCE->getValue();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000849 if (Str == "lo") {
850 Val = Val & 0xffff;
851 } else if (Str == "hi") {
852 Val = (Val & 0xffff0000) >> 16;
853 }
854 Res = MCConstantExpr::Create(Val, getContext());
855 return false;
856 }
857
Benjamin Kramerfa530572012-09-07 09:47:42 +0000858 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter0b744b32012-10-04 02:29:46 +0000859 // it's a symbol, create symbolic expression from symbol
Benjamin Kramerfa530572012-09-07 09:47:42 +0000860 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000861 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
862 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
863 return false;
864 }
865 return true;
866}
867
Jack Carterb4dbc172012-09-05 23:34:03 +0000868bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
869 SMLoc &EndLoc) {
870
871 StartLoc = Parser.getTok().getLoc();
872 RegNo = tryParseRegister("");
873 EndLoc = Parser.getTok().getLoc();
874 return (RegNo == (unsigned)-1);
875}
876
Jack Carterdc1e35d2012-09-06 20:00:02 +0000877bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
878
879 SMLoc S;
880
881 switch(getLexer().getKind()) {
882 default:
883 return true;
884 case AsmToken::Integer:
885 case AsmToken::Minus:
886 case AsmToken::Plus:
887 return (getParser().ParseExpression(Res));
Jack Cartera63b16a2012-09-07 00:23:42 +0000888 case AsmToken::Percent:
Jack Carterdc1e35d2012-09-06 20:00:02 +0000889 return parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +0000890 case AsmToken::LParen:
Jack Carter0b744b32012-10-04 02:29:46 +0000891 return false; // it's probably assuming 0
Jack Carterdc1e35d2012-09-06 20:00:02 +0000892 }
893 return true;
894}
895
Jack Carterb4dbc172012-09-05 23:34:03 +0000896MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
897 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000898
899 const MCExpr *IdVal = 0;
900 SMLoc S;
Jack Carter0b744b32012-10-04 02:29:46 +0000901 // first operand is the offset
Jack Carterdc1e35d2012-09-06 20:00:02 +0000902 S = Parser.getTok().getLoc();
903
904 if (parseMemOffset(IdVal))
905 return MatchOperand_ParseFail;
906
Jack Carter0b744b32012-10-04 02:29:46 +0000907 const AsmToken &Tok = Parser.getTok(); // get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +0000908 if (Tok.isNot(AsmToken::LParen)) {
Jack Carter543fdf82012-10-09 23:29:45 +0000909 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
910 if (Mnemonic->getToken() == "la") {
911 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
912 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
913 return MatchOperand_Success;
914 }
Jack Carterdc1e35d2012-09-06 20:00:02 +0000915 Error(Parser.getTok().getLoc(), "'(' expected");
916 return MatchOperand_ParseFail;
917 }
918
919 Parser.Lex(); // Eat '(' token.
920
Jack Carter543fdf82012-10-09 23:29:45 +0000921 const AsmToken &Tok1 = Parser.getTok(); // get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +0000922 if (Tok1.is(AsmToken::Dollar)) {
923 Parser.Lex(); // Eat '$' token.
924 if (tryParseRegisterOperand(Operands,"")) {
925 Error(Parser.getTok().getLoc(), "unexpected token in operand");
926 return MatchOperand_ParseFail;
927 }
928
929 } else {
Jack Carter0b744b32012-10-04 02:29:46 +0000930 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carterdc1e35d2012-09-06 20:00:02 +0000931 return MatchOperand_ParseFail;
932 }
933
Jack Carter0b744b32012-10-04 02:29:46 +0000934 const AsmToken &Tok2 = Parser.getTok(); // get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +0000935 if (Tok2.isNot(AsmToken::RParen)) {
936 Error(Parser.getTok().getLoc(), "')' expected");
937 return MatchOperand_ParseFail;
938 }
939
940 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
941
942 Parser.Lex(); // Eat ')' token.
943
944 if (IdVal == 0)
945 IdVal = MCConstantExpr::Create(0, getContext());
946
Jack Carter0b744b32012-10-04 02:29:46 +0000947 // now replace register operand with the mem operand
Jack Carterdc1e35d2012-09-06 20:00:02 +0000948 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
949 int RegNo = op->getReg();
Jack Carter0b744b32012-10-04 02:29:46 +0000950 // remove register from operands
Jack Carterdc1e35d2012-09-06 20:00:02 +0000951 Operands.pop_back();
Jack Carter0b744b32012-10-04 02:29:46 +0000952 // and add memory operand
Jack Carterdc1e35d2012-09-06 20:00:02 +0000953 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
954 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +0000955 return MatchOperand_Success;
956}
957
Jack Carterdc1e35d2012-09-06 20:00:02 +0000958MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
959
960 MCSymbolRefExpr::VariantKind VK
961 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
962 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
963 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
964 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
965 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
966 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
967 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
968 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
969 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
970 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
971 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
972 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
973 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
974 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
975 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
976 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
977 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
978 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
979 .Default(MCSymbolRefExpr::VK_None);
980
981 return VK;
982}
983
Benjamin Kramer47b5c572012-09-10 11:52:14 +0000984static int ConvertCcString(StringRef CondString) {
Jack Cartera63b16a2012-09-07 00:23:42 +0000985 int CC = StringSwitch<unsigned>(CondString)
986 .Case(".f", 0)
987 .Case(".un", 1)
988 .Case(".eq", 2)
989 .Case(".ueq", 3)
990 .Case(".olt", 4)
991 .Case(".ult", 5)
992 .Case(".ole", 6)
993 .Case(".ule", 7)
994 .Case(".sf", 8)
995 .Case(".ngle", 9)
996 .Case(".seq", 10)
997 .Case(".ngl", 11)
998 .Case(".lt", 12)
999 .Case(".nge", 13)
1000 .Case(".le", 14)
1001 .Case(".ngt", 15)
1002 .Default(-1);
1003
1004 return CC;
1005}
1006
1007bool MipsAsmParser::
1008parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter0b744b32012-10-04 02:29:46 +00001009 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1010 // split the format
Jack Cartera63b16a2012-09-07 00:23:42 +00001011 size_t Start = Name.find('.'), Next = Name.rfind('.');
1012 StringRef Format1 = Name.slice(Start, Next);
Jack Carter0b744b32012-10-04 02:29:46 +00001013 // and add the first format to the operands
Jack Cartera63b16a2012-09-07 00:23:42 +00001014 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carter0b744b32012-10-04 02:29:46 +00001015 // now for the second format
Jack Cartera63b16a2012-09-07 00:23:42 +00001016 StringRef Format2 = Name.slice(Next, StringRef::npos);
1017 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1018
Jack Carter0b744b32012-10-04 02:29:46 +00001019 // set the format for the first register
Jack Cartera63b16a2012-09-07 00:23:42 +00001020 setFpFormat(Format1);
1021
1022 // Read the remaining operands.
1023 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1024 // Read the first operand.
1025 if (ParseOperand(Operands, Name)) {
1026 SMLoc Loc = getLexer().getLoc();
1027 Parser.EatToEndOfStatement();
1028 return Error(Loc, "unexpected token in argument list");
1029 }
1030
1031 if (getLexer().isNot(AsmToken::Comma)) {
1032 SMLoc Loc = getLexer().getLoc();
1033 Parser.EatToEndOfStatement();
1034 return Error(Loc, "unexpected token in argument list");
1035
1036 }
1037 Parser.Lex(); // Eat the comma.
1038
1039 //set the format for the first register
1040 setFpFormat(Format2);
1041
1042 // Parse and remember the operand.
1043 if (ParseOperand(Operands, Name)) {
1044 SMLoc Loc = getLexer().getLoc();
1045 Parser.EatToEndOfStatement();
1046 return Error(Loc, "unexpected token in argument list");
1047 }
1048 }
1049
1050 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1051 SMLoc Loc = getLexer().getLoc();
1052 Parser.EatToEndOfStatement();
1053 return Error(Loc, "unexpected token in argument list");
1054 }
1055
1056 Parser.Lex(); // Consume the EndOfStatement
1057 return false;
1058}
1059
Rafael Espindola870c4e92012-01-11 03:56:41 +00001060bool MipsAsmParser::
1061ParseInstruction(StringRef Name, SMLoc NameLoc,
1062 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter0b744b32012-10-04 02:29:46 +00001063 // floating point instructions: should register be treated as double?
Jack Cartera63b16a2012-09-07 00:23:42 +00001064 if (requestsDoubleOperand(Name)) {
1065 setFpFormat(FP_FORMAT_D);
Jack Carterb4dbc172012-09-05 23:34:03 +00001066 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Cartera63b16a2012-09-07 00:23:42 +00001067 }
1068 else {
1069 setDefaultFpFormat();
1070 // Create the leading tokens for the mnemonic, split by '.' characters.
1071 size_t Start = 0, Next = Name.find('.');
1072 StringRef Mnemonic = Name.slice(Start, Next);
1073
1074 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1075
1076 if (Next != StringRef::npos) {
Jack Carter0b744b32012-10-04 02:29:46 +00001077 // there is a format token in mnemonic
1078 // StringRef Rest = Name.slice(Next, StringRef::npos);
Jack Cartera63b16a2012-09-07 00:23:42 +00001079 size_t Dot = Name.find('.', Next+1);
1080 StringRef Format = Name.slice(Next, Dot);
1081 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1082 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1083 else {
1084 if (Name.startswith("c.")){
1085 // floating point compare, add '.' and immediate represent for cc
1086 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1087 int Cc = ConvertCcString(Format);
1088 if (Cc == -1) {
1089 return Error(NameLoc, "Invalid conditional code");
1090 }
1091 SMLoc E = SMLoc::getFromPointer(
1092 Parser.getTok().getLoc().getPointer() -1 );
1093 Operands.push_back(MipsOperand::CreateImm(
1094 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1095 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001096 // trunc, ceil, floor ...
Jack Cartera63b16a2012-09-07 00:23:42 +00001097 return parseMathOperation(Name, NameLoc, Operands);
1098 }
1099
Jack Carter0b744b32012-10-04 02:29:46 +00001100 // the rest is a format
Jack Cartera63b16a2012-09-07 00:23:42 +00001101 Format = Name.slice(Dot, StringRef::npos);
1102 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1103 }
1104
1105 setFpFormat(Format);
1106 }
1107 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001108
1109 // Read the remaining operands.
1110 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1111 // Read the first operand.
1112 if (ParseOperand(Operands, Name)) {
1113 SMLoc Loc = getLexer().getLoc();
1114 Parser.EatToEndOfStatement();
1115 return Error(Loc, "unexpected token in argument list");
1116 }
1117
1118 while (getLexer().is(AsmToken::Comma) ) {
1119 Parser.Lex(); // Eat the comma.
1120
1121 // Parse and remember the operand.
1122 if (ParseOperand(Operands, Name)) {
1123 SMLoc Loc = getLexer().getLoc();
1124 Parser.EatToEndOfStatement();
1125 return Error(Loc, "unexpected token in argument list");
1126 }
1127 }
1128 }
1129
1130 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1131 SMLoc Loc = getLexer().getLoc();
1132 Parser.EatToEndOfStatement();
1133 return Error(Loc, "unexpected token in argument list");
1134 }
1135
1136 Parser.Lex(); // Consume the EndOfStatement
1137 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00001138}
1139
Jack Carter0b744b32012-10-04 02:29:46 +00001140bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1141 SMLoc Loc = getLexer().getLoc();
1142 Parser.EatToEndOfStatement();
1143 return Error(Loc, ErrorMsg);
1144}
1145
1146bool MipsAsmParser::parseSetNoAtDirective() {
1147 // line should look like:
1148 // .set noat
1149 // set at reg to 0
Jack Carter99d2afe2012-10-05 23:55:28 +00001150 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00001151 // eat noat
1152 Parser.Lex();
1153 // if this is not the end of the statement, report error
1154 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1155 reportParseError("unexpected token in statement");
1156 return false;
1157 }
1158 Parser.Lex(); // Consume the EndOfStatement
1159 return false;
1160}
1161bool MipsAsmParser::parseSetAtDirective() {
1162 // line can be
1163 // .set at - defaults to $1
1164 // or .set at=$reg
1165 getParser().Lex();
1166 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00001167 Options.setATReg(1);
Jack Carter0b744b32012-10-04 02:29:46 +00001168 Parser.Lex(); // Consume the EndOfStatement
1169 return false;
1170 } else if (getLexer().is(AsmToken::Equal)) {
1171 getParser().Lex(); //eat '='
1172 if (getLexer().isNot(AsmToken::Dollar)) {
1173 reportParseError("unexpected token in statement");
1174 return false;
1175 }
1176 Parser.Lex(); // eat '$'
1177 if (getLexer().isNot(AsmToken::Integer)) {
1178 reportParseError("unexpected token in statement");
1179 return false;
1180 }
1181 const AsmToken &Reg = Parser.getTok();
Jack Carter99d2afe2012-10-05 23:55:28 +00001182 if (!Options.setATReg(Reg.getIntVal())) {
Jack Carter0b744b32012-10-04 02:29:46 +00001183 reportParseError("unexpected token in statement");
1184 return false;
1185 }
1186 getParser().Lex(); //eat reg
1187
1188 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1189 reportParseError("unexpected token in statement");
1190 return false;
1191 }
1192 Parser.Lex(); // Consume the EndOfStatement
1193 return false;
1194 } else {
1195 reportParseError("unexpected token in statement");
1196 return false;
1197 }
1198}
1199
1200bool MipsAsmParser::parseSetReorderDirective() {
1201 Parser.Lex();
1202 // if this is not the end of the statement, report error
1203 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1204 reportParseError("unexpected token in statement");
1205 return false;
1206 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001207 Options.setReorder();
Jack Carter0b744b32012-10-04 02:29:46 +00001208 Parser.Lex(); // Consume the EndOfStatement
1209 return false;
1210}
1211
1212bool MipsAsmParser::parseSetNoReorderDirective() {
1213 Parser.Lex();
1214 // if this is not the end of the statement, report error
1215 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1216 reportParseError("unexpected token in statement");
1217 return false;
1218 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001219 Options.setNoreorder();
Jack Carter0b744b32012-10-04 02:29:46 +00001220 Parser.Lex(); // Consume the EndOfStatement
1221 return false;
1222}
1223
1224bool MipsAsmParser::parseSetMacroDirective() {
1225 Parser.Lex();
1226 // if this is not the end of the statement, report error
1227 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1228 reportParseError("unexpected token in statement");
1229 return false;
1230 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001231 Options.setMacro();
Jack Carter0b744b32012-10-04 02:29:46 +00001232 Parser.Lex(); // Consume the EndOfStatement
1233 return false;
1234}
1235
1236bool MipsAsmParser::parseSetNoMacroDirective() {
1237 Parser.Lex();
1238 // if this is not the end of the statement, report error
1239 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1240 reportParseError("`noreorder' must be set before `nomacro'");
1241 return false;
1242 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001243 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00001244 reportParseError("`noreorder' must be set before `nomacro'");
1245 return false;
1246 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001247 Options.setNomacro();
Jack Carter0b744b32012-10-04 02:29:46 +00001248 Parser.Lex(); // Consume the EndOfStatement
1249 return false;
1250}
1251bool MipsAsmParser::parseDirectiveSet() {
1252
1253 // get next token
1254 const AsmToken &Tok = Parser.getTok();
1255
1256 if (Tok.getString() == "noat") {
1257 return parseSetNoAtDirective();
1258 } else if (Tok.getString() == "at") {
1259 return parseSetAtDirective();
1260 } else if (Tok.getString() == "reorder") {
1261 return parseSetReorderDirective();
1262 } else if (Tok.getString() == "noreorder") {
1263 return parseSetNoReorderDirective();
1264 } else if (Tok.getString() == "macro") {
1265 return parseSetMacroDirective();
1266 } else if (Tok.getString() == "nomacro") {
1267 return parseSetNoMacroDirective();
1268 } else if (Tok.getString() == "nomips16") {
1269 // ignore this directive for now
1270 Parser.EatToEndOfStatement();
1271 return false;
1272 } else if (Tok.getString() == "nomicromips") {
1273 // ignore this directive for now
1274 Parser.EatToEndOfStatement();
1275 return false;
1276 }
1277 return true;
1278}
1279
1280bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +00001281
1282 if (DirectiveID.getString() == ".ent") {
Jack Carter0b744b32012-10-04 02:29:46 +00001283 // ignore this directive for now
Jack Carterbe332172012-09-07 00:48:02 +00001284 Parser.Lex();
1285 return false;
1286 }
1287
1288 if (DirectiveID.getString() == ".end") {
Jack Carter0b744b32012-10-04 02:29:46 +00001289 // ignore this directive for now
Jack Carterbe332172012-09-07 00:48:02 +00001290 Parser.Lex();
1291 return false;
1292 }
1293
1294 if (DirectiveID.getString() == ".frame") {
Jack Carter0b744b32012-10-04 02:29:46 +00001295 // ignore this directive for now
Jack Carterbe332172012-09-07 00:48:02 +00001296 Parser.EatToEndOfStatement();
1297 return false;
1298 }
1299
1300 if (DirectiveID.getString() == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00001301 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00001302 }
1303
1304 if (DirectiveID.getString() == ".fmask") {
Jack Carter0b744b32012-10-04 02:29:46 +00001305 // ignore this directive for now
Jack Carterbe332172012-09-07 00:48:02 +00001306 Parser.EatToEndOfStatement();
1307 return false;
1308 }
1309
1310 if (DirectiveID.getString() == ".mask") {
Jack Carter0b744b32012-10-04 02:29:46 +00001311 // ignore this directive for now
Jack Carterbe332172012-09-07 00:48:02 +00001312 Parser.EatToEndOfStatement();
1313 return false;
1314 }
1315
1316 if (DirectiveID.getString() == ".gpword") {
Jack Carter0b744b32012-10-04 02:29:46 +00001317 // ignore this directive for now
Jack Carterbe332172012-09-07 00:48:02 +00001318 Parser.EatToEndOfStatement();
1319 return false;
1320 }
1321
Rafael Espindola870c4e92012-01-11 03:56:41 +00001322 return true;
1323}
1324
Rafael Espindola870c4e92012-01-11 03:56:41 +00001325extern "C" void LLVMInitializeMipsAsmParser() {
1326 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1327 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1328 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1329 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1330}
Jack Carterb4dbc172012-09-05 23:34:03 +00001331
1332#define GET_REGISTER_MATCHER
1333#define GET_MATCHER_IMPLEMENTATION
1334#include "MipsGenAsmMatcher.inc"