blob: 00649d2f18771f5c130028ac57be5db1ab37254f [file] [log] [blame]
Jia Liuc5707112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindolafddf8042012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterec65be82012-09-05 23:34:03 +000011#include "MipsRegisterInfo.h"
12#include "llvm/ADT/StringSwitch.h"
13#include "llvm/MC/MCContext.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCInst.h"
16#include "llvm/MC/MCStreamer.h"
17#include "llvm/MC/MCSubtargetInfo.h"
18#include "llvm/MC/MCSymbol.h"
Rafael Espindolafddf8042012-01-11 03:56:41 +000019#include "llvm/MC/MCParser/MCAsmLexer.h"
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000020#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21#include "llvm/MC/MCTargetAsmParser.h"
Jack Carterec65be82012-09-05 23:34:03 +000022#include "llvm/Support/TargetRegistry.h"
Rafael Espindolafddf8042012-01-11 03:56:41 +000023
24using namespace llvm;
25
26namespace {
Jack Carter30116cd2012-10-04 02:29:46 +000027class MipsAssemblerOptions {
28public:
29 MipsAssemblerOptions():
30 aTReg(1), reorder(true), macro(true) {
31 }
Jack Carterec65be82012-09-05 23:34:03 +000032
Jack Carter30116cd2012-10-04 02:29:46 +000033 unsigned getATRegNum() {return aTReg;}
34 bool setATReg(unsigned Reg);
35
36 bool isReorder() {return reorder;}
37 void setReorder() {reorder = true;}
38 void setNoreorder() {reorder = false;}
39
40 bool isMacro() {return macro;}
41 void setMacro() {macro = true;}
42 void setNomacro() {macro = false;}
43
44private:
45 unsigned aTReg;
46 bool reorder;
47 bool macro;
48};
49}
50
51namespace {
Rafael Espindolafddf8042012-01-11 03:56:41 +000052class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000053
Jack Carterf740d6e2012-09-07 00:23:42 +000054 enum FpFormatTy {
55 FP_FORMAT_NONE = -1,
56 FP_FORMAT_S,
57 FP_FORMAT_D,
58 FP_FORMAT_L,
59 FP_FORMAT_W
60 } FpFormat;
61
Jack Carterec65be82012-09-05 23:34:03 +000062 MCSubtargetInfo &STI;
63 MCAsmParser &Parser;
Jack Carter10d5ff62012-10-05 23:55:28 +000064 MipsAssemblerOptions Options;
Jack Carter30116cd2012-10-04 02:29:46 +000065
Jack Carterec65be82012-09-05 23:34:03 +000066
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000067#define GET_ASSEMBLER_HEADER
68#include "MipsGenAsmMatcher.inc"
69
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
77 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000078 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindolafddf8042012-01-11 03:56:41 +000079
Jack Carterf740d6e2012-09-07 00:23:42 +000080 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
81 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
82
Rafael Espindolafddf8042012-01-11 03:56:41 +000083 bool ParseDirective(AsmToken DirectiveID);
84
Jack Carterec65be82012-09-05 23:34:03 +000085 MipsAsmParser::OperandMatchResultTy
86 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
Chad Rosier038f3e32012-09-03 18:47:45 +000087
Jack Carterec65be82012-09-05 23:34:03 +000088 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
89 StringRef Mnemonic);
90
91 int tryParseRegister(StringRef Mnemonic);
92
93 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
94 StringRef Mnemonic);
95
Jack Carter9d577c82012-10-04 04:03:53 +000096 bool needsExpansion(MCInst &Inst);
97
98 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +000099 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9d577c82012-10-04 04:03:53 +0000100 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000101 SmallVectorImpl<MCInst> &Instructions);
Jack Carter2f68b312012-10-09 23:29:45 +0000102 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
103 SmallVectorImpl<MCInst> &Instructions);
104 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
105 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30116cd2012-10-04 02:29:46 +0000106 bool reportParseError(StringRef ErrorMsg);
107
Jack Carter6b96c3f2012-09-06 20:00:02 +0000108 bool parseMemOffset(const MCExpr *&Res);
109 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter30116cd2012-10-04 02:29:46 +0000110
111 bool parseDirectiveSet();
112
113 bool parseSetAtDirective();
114 bool parseSetNoAtDirective();
115 bool parseSetMacroDirective();
116 bool parseSetNoMacroDirective();
117 bool parseSetReorderDirective();
118 bool parseSetNoReorderDirective();
119
Jack Carter6b96c3f2012-09-06 20:00:02 +0000120 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Carterf740d6e2012-09-07 00:23:42 +0000121
Jack Carterec65be82012-09-05 23:34:03 +0000122 bool isMips64() const {
123 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
124 }
125
Jack Carterf740d6e2012-09-07 00:23:42 +0000126 bool isFP64() const {
127 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
128 }
129
Jack Carterec65be82012-09-05 23:34:03 +0000130 int matchRegisterName(StringRef Symbol);
131
132 int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
133
Jack Carterf740d6e2012-09-07 00:23:42 +0000134 void setFpFormat(FpFormatTy Format) {
135 FpFormat = Format;
136 }
137
138 void setDefaultFpFormat();
139
140 void setFpFormat(StringRef Format);
141
142 FpFormatTy getFpFormat() {return FpFormat;}
143
144 bool requestsDoubleOperand(StringRef Mnemonic);
145
Jack Carterec65be82012-09-05 23:34:03 +0000146 unsigned getReg(int RC,int RegNo);
Chad Rosier038f3e32012-09-03 18:47:45 +0000147
Jack Carter30116cd2012-10-04 02:29:46 +0000148 unsigned getATReg();
Rafael Espindolafddf8042012-01-11 03:56:41 +0000149public:
150 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterec65be82012-09-05 23:34:03 +0000151 : MCTargetAsmParser(), STI(sti), Parser(parser) {
152 // Initialize the set of available features.
153 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindolafddf8042012-01-11 03:56:41 +0000154 }
155
Jack Carterec65be82012-09-05 23:34:03 +0000156 MCAsmParser &getParser() const { return Parser; }
157 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
158
Rafael Espindolafddf8042012-01-11 03:56:41 +0000159};
160}
161
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000162namespace {
163
164/// MipsOperand - Instances of this class represent a parsed Mips machine
165/// instruction.
166class MipsOperand : public MCParsedAsmOperand {
Jack Carterec65be82012-09-05 23:34:03 +0000167
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000168 enum KindTy {
169 k_CondCode,
170 k_CoprocNum,
171 k_Immediate,
172 k_Memory,
173 k_PostIndexRegister,
174 k_Register,
175 k_Token
176 } Kind;
177
178 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterec65be82012-09-05 23:34:03 +0000179
180 union {
181 struct {
182 const char *Data;
183 unsigned Length;
184 } Tok;
185
186 struct {
187 unsigned RegNum;
188 } Reg;
189
190 struct {
191 const MCExpr *Val;
192 } Imm;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000193
194 struct {
195 unsigned Base;
196 const MCExpr *Off;
197 } Mem;
Jack Carterec65be82012-09-05 23:34:03 +0000198 };
199
200 SMLoc StartLoc, EndLoc;
201
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000202public:
203 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000204 assert(N == 1 && "Invalid number of operands!");
205 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000206 }
Jack Carterec65be82012-09-05 23:34:03 +0000207
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000208 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterec65be82012-09-05 23:34:03 +0000209 // Add as immediate when possible. Null MCExpr = 0.
210 if (Expr == 0)
211 Inst.addOperand(MCOperand::CreateImm(0));
212 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
213 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
214 else
215 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000216 }
Jack Carterec65be82012-09-05 23:34:03 +0000217
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000218 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000219 assert(N == 1 && "Invalid number of operands!");
220 const MCExpr *Expr = getImm();
221 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000222 }
Jack Carterec65be82012-09-05 23:34:03 +0000223
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000224 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000225 assert(N == 2 && "Invalid number of operands!");
226
227 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
228
229 const MCExpr *Expr = getMemOff();
230 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000231 }
232
233 bool isReg() const { return Kind == k_Register; }
234 bool isImm() const { return Kind == k_Immediate; }
235 bool isToken() const { return Kind == k_Token; }
236 bool isMem() const { return Kind == k_Memory; }
237
238 StringRef getToken() const {
239 assert(Kind == k_Token && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000240 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000241 }
242
243 unsigned getReg() const {
244 assert((Kind == k_Register) && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000245 return Reg.RegNum;
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000246 }
247
Jack Carterec65be82012-09-05 23:34:03 +0000248 const MCExpr *getImm() const {
249 assert((Kind == k_Immediate) && "Invalid access!");
250 return Imm.Val;
251 }
252
Jack Carter6b96c3f2012-09-06 20:00:02 +0000253 unsigned getMemBase() const {
254 assert((Kind == k_Memory) && "Invalid access!");
255 return Mem.Base;
256 }
257
258 const MCExpr *getMemOff() const {
259 assert((Kind == k_Memory) && "Invalid access!");
260 return Mem.Off;
261 }
262
Jack Carterec65be82012-09-05 23:34:03 +0000263 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
264 MipsOperand *Op = new MipsOperand(k_Token);
265 Op->Tok.Data = Str.data();
266 Op->Tok.Length = Str.size();
267 Op->StartLoc = S;
268 Op->EndLoc = S;
269 return Op;
270 }
271
272 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
273 MipsOperand *Op = new MipsOperand(k_Register);
274 Op->Reg.RegNum = RegNum;
275 Op->StartLoc = S;
276 Op->EndLoc = E;
277 return Op;
278 }
279
280 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
281 MipsOperand *Op = new MipsOperand(k_Immediate);
282 Op->Imm.Val = Val;
283 Op->StartLoc = S;
284 Op->EndLoc = E;
285 return Op;
286 }
287
Jack Carter6b96c3f2012-09-06 20:00:02 +0000288 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
289 SMLoc S, SMLoc E) {
290 MipsOperand *Op = new MipsOperand(k_Memory);
291 Op->Mem.Base = Base;
292 Op->Mem.Off = Off;
293 Op->StartLoc = S;
294 Op->EndLoc = E;
295 return Op;
296 }
297
Jack Carterec65be82012-09-05 23:34:03 +0000298 /// getStartLoc - Get the location of the first token of this operand.
299 SMLoc getStartLoc() const { return StartLoc; }
300 /// getEndLoc - Get the location of the last token of this operand.
301 SMLoc getEndLoc() const { return EndLoc; }
302
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000303 virtual void print(raw_ostream &OS) const {
304 llvm_unreachable("unimplemented!");
305 }
306};
307}
308
Jack Carter9d577c82012-10-04 04:03:53 +0000309bool MipsAsmParser::needsExpansion(MCInst &Inst) {
310
311 switch(Inst.getOpcode()) {
312 case Mips::LoadImm32Reg:
Jack Carter2f68b312012-10-09 23:29:45 +0000313 case Mips::LoadAddr32Imm:
314 case Mips::LoadAddr32Reg:
Jack Carter9d577c82012-10-04 04:03:53 +0000315 return true;
316 default:
317 return false;
318 }
319}
Jack Carter2490dc62012-10-06 00:53:28 +0000320
Jack Carter9d577c82012-10-04 04:03:53 +0000321void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000322 SmallVectorImpl<MCInst> &Instructions){
Jack Carter9d577c82012-10-04 04:03:53 +0000323 switch(Inst.getOpcode()) {
324 case Mips::LoadImm32Reg:
325 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carter2f68b312012-10-09 23:29:45 +0000326 case Mips::LoadAddr32Imm:
327 return expandLoadAddressImm(Inst,IDLoc,Instructions);
328 case Mips::LoadAddr32Reg:
329 return expandLoadAddressReg(Inst,IDLoc,Instructions);
Jack Carter9d577c82012-10-04 04:03:53 +0000330 }
Jack Carter9d577c82012-10-04 04:03:53 +0000331}
Jack Carter2490dc62012-10-06 00:53:28 +0000332
Jack Carter9d577c82012-10-04 04:03:53 +0000333void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter2f68b312012-10-09 23:29:45 +0000334 SmallVectorImpl<MCInst> &Instructions){
Jack Carter2490dc62012-10-06 00:53:28 +0000335 MCInst tmpInst;
Jack Carter9d577c82012-10-04 04:03:53 +0000336 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter2f68b312012-10-09 23:29:45 +0000337 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter9d577c82012-10-04 04:03:53 +0000338 const MCOperand &RegOp = Inst.getOperand(0);
339 assert(RegOp.isReg() && "expected register operand kind");
340
341 int ImmValue = ImmOp.getImm();
Jack Carter2490dc62012-10-06 00:53:28 +0000342 tmpInst.setLoc(IDLoc);
Jack Carter9d577c82012-10-04 04:03:53 +0000343 if ( 0 <= ImmValue && ImmValue <= 65535) {
Jack Carter2490dc62012-10-06 00:53:28 +0000344 // for 0 <= j <= 65535.
Jack Carter9d577c82012-10-04 04:03:53 +0000345 // li d,j => ori d,$zero,j
Jack Carter2490dc62012-10-06 00:53:28 +0000346 tmpInst.setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
347 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
348 tmpInst.addOperand(
Jack Carter9d577c82012-10-04 04:03:53 +0000349 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
Jack Carter2490dc62012-10-06 00:53:28 +0000350 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter9d577c82012-10-04 04:03:53 +0000351 Instructions.push_back(tmpInst);
352 } else if ( ImmValue < 0 && ImmValue >= -32768) {
Jack Carter2490dc62012-10-06 00:53:28 +0000353 // for -32768 <= j < 0.
Jack Carter9d577c82012-10-04 04:03:53 +0000354 // li d,j => addiu d,$zero,j
Jack Carter2490dc62012-10-06 00:53:28 +0000355 tmpInst.setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
356 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
357 tmpInst.addOperand(
Jack Carter9d577c82012-10-04 04:03:53 +0000358 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
Jack Carter2490dc62012-10-06 00:53:28 +0000359 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter9d577c82012-10-04 04:03:53 +0000360 Instructions.push_back(tmpInst);
361 } else {
362 // for any other value of j that is representable as a 32-bit integer.
363 // li d,j => lui d,hi16(j)
Jack Carter2f68b312012-10-09 23:29:45 +0000364 // ori d,d,lo16(j)
Jack Carter2490dc62012-10-06 00:53:28 +0000365 tmpInst.setOpcode(isMips64() ? Mips::LUi64 : Mips::LUi);
366 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
367 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter9d577c82012-10-04 04:03:53 +0000368 Instructions.push_back(tmpInst);
Jack Carter2490dc62012-10-06 00:53:28 +0000369 tmpInst.clear();
370 tmpInst.setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
371 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
372 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
373 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
374 tmpInst.setLoc(IDLoc);
Jack Carter9d577c82012-10-04 04:03:53 +0000375 Instructions.push_back(tmpInst);
376 }
377}
Jack Carter2490dc62012-10-06 00:53:28 +0000378
Jack Carter2f68b312012-10-09 23:29:45 +0000379void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
380 SmallVectorImpl<MCInst> &Instructions){
381 MCInst tmpInst;
382 const MCOperand &ImmOp = Inst.getOperand(2);
383 assert(ImmOp.isImm() && "expected immediate operand kind");
384 const MCOperand &SrcRegOp = Inst.getOperand(1);
385 assert(SrcRegOp.isReg() && "expected register operand kind");
386 const MCOperand &DstRegOp = Inst.getOperand(0);
387 assert(DstRegOp.isReg() && "expected register operand kind");
388 int ImmValue = ImmOp.getImm();
389 if ( -32768 <= ImmValue && ImmValue <= 65535) {
390 //for -32768 <= j <= 65535.
391 //la d,j(s) => addiu d,s,j
392 tmpInst.setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
393 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
394 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
395 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
396 Instructions.push_back(tmpInst);
397 } else {
398 //for any other value of j that is representable as a 32-bit integer.
399 //la d,j(s) => lui d,hi16(j)
400 // ori d,d,lo16(j)
401 // addu d,d,s
402 tmpInst.setOpcode(isMips64()?Mips::LUi64:Mips::LUi);
403 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
404 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
405 Instructions.push_back(tmpInst);
406 tmpInst.clear();
407 tmpInst.setOpcode(isMips64()?Mips::ORi64:Mips::ORi);
408 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
409 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
410 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
411 Instructions.push_back(tmpInst);
412 tmpInst.clear();
413 tmpInst.setOpcode(Mips::ADDu);
414 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
415 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
416 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
417 Instructions.push_back(tmpInst);
418 }
419}
420
421void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
422 SmallVectorImpl<MCInst> &Instructions){
423 MCInst tmpInst;
424 const MCOperand &ImmOp = Inst.getOperand(1);
425 assert(ImmOp.isImm() && "expected immediate operand kind");
426 const MCOperand &RegOp = Inst.getOperand(0);
427 assert(RegOp.isReg() && "expected register operand kind");
428 int ImmValue = ImmOp.getImm();
429 if ( -32768 <= ImmValue && ImmValue <= 65535) {
430 //for -32768 <= j <= 65535.
431 //la d,j => addiu d,$zero,j
432 tmpInst.setOpcode(Mips::ADDiu);
433 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
434 tmpInst.addOperand(
435 MCOperand::CreateReg(isMips64()?Mips::ZERO_64:Mips::ZERO));
436 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
437 Instructions.push_back(tmpInst);
438 } else {
439 //for any other value of j that is representable as a 32-bit integer.
440 //la d,j => lui d,hi16(j)
441 // ori d,d,lo16(j)
442 tmpInst.setOpcode(isMips64()?Mips::LUi64:Mips::LUi);
443 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
444 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
445 Instructions.push_back(tmpInst);
446 tmpInst.clear();
447 tmpInst.setOpcode(isMips64()?Mips::ORi64:Mips::ORi);
448 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
449 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
450 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
451 Instructions.push_back(tmpInst);
452 }
453}
454
Rafael Espindolafddf8042012-01-11 03:56:41 +0000455bool MipsAsmParser::
Chad Rosier84125ca2012-10-13 00:26:04 +0000456MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindolafddf8042012-01-11 03:56:41 +0000457 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier84125ca2012-10-13 00:26:04 +0000458 MCStreamer &Out, unsigned &ErrorInfo,
459 bool MatchingInlineAsm) {
Jack Carterec65be82012-09-05 23:34:03 +0000460 MCInst Inst;
Chad Rosier6e006d32012-10-12 22:53:36 +0000461 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier84125ca2012-10-13 00:26:04 +0000462 MatchingInlineAsm);
Jack Carterec65be82012-09-05 23:34:03 +0000463
464 switch (MatchResult) {
465 default: break;
466 case Match_Success: {
Jack Carter9d577c82012-10-04 04:03:53 +0000467 if (needsExpansion(Inst)) {
Jack Carter2490dc62012-10-06 00:53:28 +0000468 SmallVector<MCInst, 4> Instructions;
Jack Carter9d577c82012-10-04 04:03:53 +0000469 expandInstruction(Inst, IDLoc, Instructions);
470 for(unsigned i =0; i < Instructions.size(); i++){
Jack Carter2490dc62012-10-06 00:53:28 +0000471 Out.EmitInstruction(Instructions[i]);
Jack Carter9d577c82012-10-04 04:03:53 +0000472 }
473 } else {
474 Inst.setLoc(IDLoc);
475 Out.EmitInstruction(Inst);
476 }
Jack Carterec65be82012-09-05 23:34:03 +0000477 return false;
478 }
479 case Match_MissingFeature:
480 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
481 return true;
482 case Match_InvalidOperand: {
483 SMLoc ErrorLoc = IDLoc;
484 if (ErrorInfo != ~0U) {
485 if (ErrorInfo >= Operands.size())
486 return Error(IDLoc, "too few operands for instruction");
487
488 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
489 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
490 }
491
492 return Error(ErrorLoc, "invalid operand for instruction");
493 }
494 case Match_MnemonicFail:
495 return Error(IDLoc, "invalid instruction");
496 }
Rafael Espindolafddf8042012-01-11 03:56:41 +0000497 return true;
498}
499
Jack Carterec65be82012-09-05 23:34:03 +0000500int MipsAsmParser::matchRegisterName(StringRef Name) {
501
David Chisnall572e1bd2012-10-09 16:27:43 +0000502 int CC;
503 if (!isMips64())
504 CC = StringSwitch<unsigned>(Name)
505 .Case("zero", Mips::ZERO)
506 .Case("a0", Mips::A0)
507 .Case("a1", Mips::A1)
508 .Case("a2", Mips::A2)
509 .Case("a3", Mips::A3)
510 .Case("v0", Mips::V0)
511 .Case("v1", Mips::V1)
512 .Case("s0", Mips::S0)
513 .Case("s1", Mips::S1)
514 .Case("s2", Mips::S2)
515 .Case("s3", Mips::S3)
516 .Case("s4", Mips::S4)
517 .Case("s5", Mips::S5)
518 .Case("s6", Mips::S6)
519 .Case("s7", Mips::S7)
520 .Case("k0", Mips::K0)
521 .Case("k1", Mips::K1)
522 .Case("sp", Mips::SP)
523 .Case("fp", Mips::FP)
524 .Case("gp", Mips::GP)
525 .Case("ra", Mips::RA)
526 .Case("t0", Mips::T0)
527 .Case("t1", Mips::T1)
528 .Case("t2", Mips::T2)
529 .Case("t3", Mips::T3)
530 .Case("t4", Mips::T4)
531 .Case("t5", Mips::T5)
532 .Case("t6", Mips::T6)
533 .Case("t7", Mips::T7)
534 .Case("t8", Mips::T8)
535 .Case("t9", Mips::T9)
536 .Case("at", Mips::AT)
537 .Case("fcc0", Mips::FCC0)
538 .Default(-1);
539 else
540 CC = StringSwitch<unsigned>(Name)
541 .Case("zero", Mips::ZERO_64)
542 .Case("at", Mips::AT_64)
543 .Case("v0", Mips::V0_64)
544 .Case("v1", Mips::V1_64)
545 .Case("a0", Mips::A0_64)
546 .Case("a1", Mips::A1_64)
547 .Case("a2", Mips::A2_64)
548 .Case("a3", Mips::A3_64)
549 .Case("a4", Mips::T0_64)
550 .Case("a5", Mips::T1_64)
551 .Case("a6", Mips::T2_64)
552 .Case("a7", Mips::T3_64)
553 .Case("t4", Mips::T4_64)
554 .Case("t5", Mips::T5_64)
555 .Case("t6", Mips::T6_64)
556 .Case("t7", Mips::T7_64)
557 .Case("s0", Mips::S0_64)
558 .Case("s1", Mips::S1_64)
559 .Case("s2", Mips::S2_64)
560 .Case("s3", Mips::S3_64)
561 .Case("s4", Mips::S4_64)
562 .Case("s5", Mips::S5_64)
563 .Case("s6", Mips::S6_64)
564 .Case("s7", Mips::S7_64)
565 .Case("t8", Mips::T8_64)
566 .Case("t9", Mips::T9_64)
567 .Case("kt0", Mips::K0_64)
568 .Case("kt1", Mips::K1_64)
569 .Case("gp", Mips::GP_64)
570 .Case("sp", Mips::SP_64)
571 .Case("fp", Mips::FP_64)
572 .Case("s8", Mips::FP_64)
573 .Case("ra", Mips::RA_64)
574 .Default(-1);
Jack Carterec65be82012-09-05 23:34:03 +0000575
David Chisnall572e1bd2012-10-09 16:27:43 +0000576 if (CC != -1)
Jack Carterec65be82012-09-05 23:34:03 +0000577 return CC;
Jack Carterec65be82012-09-05 23:34:03 +0000578
Jack Carterf740d6e2012-09-07 00:23:42 +0000579 if (Name[0] == 'f') {
580 StringRef NumString = Name.substr(1);
581 unsigned IntVal;
582 if( NumString.getAsInteger(10, IntVal))
Jack Carter9d577c82012-10-04 04:03:53 +0000583 return -1; // not integer
Jack Carterf740d6e2012-09-07 00:23:42 +0000584 if (IntVal > 31)
585 return -1;
586
587 FpFormatTy Format = getFpFormat();
588
589 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
590 return getReg(Mips::FGR32RegClassID, IntVal);
591 if (Format == FP_FORMAT_D) {
592 if(isFP64()) {
593 return getReg(Mips::FGR64RegClassID, IntVal);
594 }
Jack Carter9d577c82012-10-04 04:03:53 +0000595 // only even numbers available as register pairs
Jack Carterf740d6e2012-09-07 00:23:42 +0000596 if (( IntVal > 31) || (IntVal%2 != 0))
597 return -1;
598 return getReg(Mips::AFGR64RegClassID, IntVal/2);
599 }
600 }
601
Jack Carterec65be82012-09-05 23:34:03 +0000602 return -1;
603}
Jack Carterf740d6e2012-09-07 00:23:42 +0000604void MipsAsmParser::setDefaultFpFormat() {
605
606 if (isMips64() || isFP64())
607 FpFormat = FP_FORMAT_D;
608 else
609 FpFormat = FP_FORMAT_S;
610}
611
612bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
613
614 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
615 .Case("ldxc1", true)
616 .Case("ldc1", true)
617 .Case("sdxc1", true)
618 .Case("sdc1", true)
619 .Default(false);
620
621 return IsDouble;
622}
623void MipsAsmParser::setFpFormat(StringRef Format) {
624
625 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
626 .Case(".s", FP_FORMAT_S)
627 .Case(".d", FP_FORMAT_D)
628 .Case(".l", FP_FORMAT_L)
629 .Case(".w", FP_FORMAT_W)
630 .Default(FP_FORMAT_NONE);
631}
Jack Carterec65be82012-09-05 23:34:03 +0000632
Jack Carter30116cd2012-10-04 02:29:46 +0000633bool MipsAssemblerOptions::setATReg(unsigned Reg) {
634 if (Reg > 31)
635 return false;
636
637 aTReg = Reg;
638 return true;
639}
640
641unsigned MipsAsmParser::getATReg() {
Jack Carter10d5ff62012-10-05 23:55:28 +0000642 unsigned Reg = Options.getATRegNum();
Jack Carter30116cd2012-10-04 02:29:46 +0000643 if (isMips64())
644 return getReg(Mips::CPU64RegsRegClassID,Reg);
Jack Carter10d5ff62012-10-05 23:55:28 +0000645
646 return getReg(Mips::CPURegsRegClassID,Reg);
Jack Carter30116cd2012-10-04 02:29:46 +0000647}
648
649unsigned MipsAsmParser::getReg(int RC,int RegNo) {
Jack Carterec65be82012-09-05 23:34:03 +0000650 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
651}
652
Jack Carter30116cd2012-10-04 02:29:46 +0000653int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
Jack Carterec65be82012-09-05 23:34:03 +0000654
655 if (Mnemonic.lower() == "rdhwr") {
Jack Carter9d577c82012-10-04 04:03:53 +0000656 // at the moment only hwreg29 is supported
Jack Carterec65be82012-09-05 23:34:03 +0000657 if (RegNum != 29)
658 return -1;
659 return Mips::HWR29;
660 }
661
662 if (RegNum > 31)
663 return -1;
664
David Chisnall572e1bd2012-10-09 16:27:43 +0000665 // MIPS64 registers are numbered 1 after the 32-bit equivalents
666 return getReg(Mips::CPURegsRegClassID, RegNum) + isMips64();
Jack Carterec65be82012-09-05 23:34:03 +0000667}
668
669int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
670 const AsmToken &Tok = Parser.getTok();
671 int RegNum = -1;
672
673 if (Tok.is(AsmToken::Identifier)) {
674 std::string lowerCase = Tok.getString().lower();
675 RegNum = matchRegisterName(lowerCase);
676 } else if (Tok.is(AsmToken::Integer))
Jack Carter9d577c82012-10-04 04:03:53 +0000677 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carter6b96c3f2012-09-06 20:00:02 +0000678 Mnemonic.lower());
Jack Carterf740d6e2012-09-07 00:23:42 +0000679 else
680 return RegNum; //error
Jack Carter9d577c82012-10-04 04:03:53 +0000681 // 64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
Jack Carterf740d6e2012-09-07 00:23:42 +0000682 if (isMips64() && RegNum == Mips::ZERO_64) {
683 if (Mnemonic.find("ddiv") != StringRef::npos)
684 RegNum = Mips::ZERO;
685 }
Jack Carterec65be82012-09-05 23:34:03 +0000686 return RegNum;
687}
688
Rafael Espindolafddf8042012-01-11 03:56:41 +0000689bool MipsAsmParser::
Jack Carterec65be82012-09-05 23:34:03 +0000690 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
691 StringRef Mnemonic){
692
693 SMLoc S = Parser.getTok().getLoc();
694 int RegNo = -1;
Jack Carterf740d6e2012-09-07 00:23:42 +0000695
Jack Carter9d577c82012-10-04 04:03:53 +0000696 // FIXME: we should make a more generic method for CCR
Jack Carterf740d6e2012-09-07 00:23:42 +0000697 if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
698 && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
Jack Carter9d577c82012-10-04 04:03:53 +0000699 RegNo = Parser.getTok().getIntVal(); // get the int value
700 // at the moment only fcc0 is supported
Jack Carterf740d6e2012-09-07 00:23:42 +0000701 if (RegNo == 0)
702 RegNo = Mips::FCC0;
703 } else
704 RegNo = tryParseRegister(Mnemonic);
Jack Carterec65be82012-09-05 23:34:03 +0000705 if (RegNo == -1)
706 return true;
707
708 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterf740d6e2012-09-07 00:23:42 +0000709 Parser.getTok().getLoc()));
Jack Carterec65be82012-09-05 23:34:03 +0000710 Parser.Lex(); // Eat register token.
711 return false;
712}
713
714bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
715 StringRef Mnemonic) {
Jack Carter9d577c82012-10-04 04:03:53 +0000716 // Check if the current operand has a custom associated parser, if so, try to
717 // custom parse the operand, or fallback to the general approach.
Jack Carterec65be82012-09-05 23:34:03 +0000718 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
719 if (ResTy == MatchOperand_Success)
720 return false;
721 // If there wasn't a custom match, try the generic matcher below. Otherwise,
722 // there was a match, but an error occurred, in which case, just return that
723 // the operand parsing failed.
724 if (ResTy == MatchOperand_ParseFail)
725 return true;
726
727 switch (getLexer().getKind()) {
728 default:
729 Error(Parser.getTok().getLoc(), "unexpected token in operand");
730 return true;
731 case AsmToken::Dollar: {
Jack Carter9d577c82012-10-04 04:03:53 +0000732 // parse register
Jack Carterec65be82012-09-05 23:34:03 +0000733 SMLoc S = Parser.getTok().getLoc();
734 Parser.Lex(); // Eat dollar token.
Jack Carter9d577c82012-10-04 04:03:53 +0000735 // parse register operand
736 if (!tryParseRegisterOperand(Operands, Mnemonic)) {
Jack Carterec65be82012-09-05 23:34:03 +0000737 if (getLexer().is(AsmToken::LParen)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000738 // check if it is indexed addressing operand
Jack Carterec65be82012-09-05 23:34:03 +0000739 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carter9d577c82012-10-04 04:03:53 +0000740 Parser.Lex(); // eat parenthesis
Jack Carterec65be82012-09-05 23:34:03 +0000741 if (getLexer().isNot(AsmToken::Dollar))
742 return true;
743
Jack Carter9d577c82012-10-04 04:03:53 +0000744 Parser.Lex(); // eat dollar
745 if (tryParseRegisterOperand(Operands, Mnemonic))
Jack Carterec65be82012-09-05 23:34:03 +0000746 return true;
747
748 if (!getLexer().is(AsmToken::RParen))
749 return true;
750
751 S = Parser.getTok().getLoc();
752 Operands.push_back(MipsOperand::CreateToken(")", S));
753 Parser.Lex();
754 }
755 return false;
756 }
Jack Carter9d577c82012-10-04 04:03:53 +0000757 // maybe it is a symbol reference
Jack Carterec65be82012-09-05 23:34:03 +0000758 StringRef Identifier;
759 if (Parser.ParseIdentifier(Identifier))
760 return true;
761
Jack Carter6b96c3f2012-09-06 20:00:02 +0000762 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000763
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000764 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterec65be82012-09-05 23:34:03 +0000765
766 // Otherwise create a symbol ref.
Jack Carter6b96c3f2012-09-06 20:00:02 +0000767 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterec65be82012-09-05 23:34:03 +0000768 getContext());
769
770 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
771 return false;
772 }
773 case AsmToken::Identifier:
774 case AsmToken::LParen:
775 case AsmToken::Minus:
776 case AsmToken::Plus:
777 case AsmToken::Integer:
778 case AsmToken::String: {
779 // quoted label names
780 const MCExpr *IdVal;
781 SMLoc S = Parser.getTok().getLoc();
782 if (getParser().ParseExpression(IdVal))
783 return true;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000784 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000785 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
786 return false;
787 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000788 case AsmToken::Percent: {
Jack Carter9d577c82012-10-04 04:03:53 +0000789 // it is a symbol reference or constant expression
Jack Carter6b96c3f2012-09-06 20:00:02 +0000790 const MCExpr *IdVal;
Jack Carter9d577c82012-10-04 04:03:53 +0000791 SMLoc S = Parser.getTok().getLoc(); // start location of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000792 if (parseRelocOperand(IdVal))
793 return true;
794
795 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
796
797 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
798 return false;
Jack Carter30116cd2012-10-04 02:29:46 +0000799 } // case AsmToken::Percent
800 } // switch(getLexer().getKind())
Rafael Espindolafddf8042012-01-11 03:56:41 +0000801 return true;
802}
803
Jack Carter6b96c3f2012-09-06 20:00:02 +0000804bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
805
Jack Carter30116cd2012-10-04 02:29:46 +0000806 Parser.Lex(); // eat % token
Jack Carter9d577c82012-10-04 04:03:53 +0000807 const AsmToken &Tok = Parser.getTok(); // get next token, operation
Jack Carter6b96c3f2012-09-06 20:00:02 +0000808 if (Tok.isNot(AsmToken::Identifier))
809 return true;
810
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000811 std::string Str = Tok.getIdentifier().str();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000812
Jack Carter9d577c82012-10-04 04:03:53 +0000813 Parser.Lex(); // eat identifier
Jack Carter30116cd2012-10-04 02:29:46 +0000814 // now make expression from the rest of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000815 const MCExpr *IdVal;
816 SMLoc EndLoc;
817
818 if (getLexer().getKind() == AsmToken::LParen) {
819 while (1) {
Jack Carter30116cd2012-10-04 02:29:46 +0000820 Parser.Lex(); // eat '(' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000821 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carter30116cd2012-10-04 02:29:46 +0000822 Parser.Lex(); // eat % token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000823 const AsmToken &nextTok = Parser.getTok();
824 if (nextTok.isNot(AsmToken::Identifier))
825 return true;
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000826 Str += "(%";
827 Str += nextTok.getIdentifier();
Jack Carter30116cd2012-10-04 02:29:46 +0000828 Parser.Lex(); // eat identifier
Jack Carter6b96c3f2012-09-06 20:00:02 +0000829 if (getLexer().getKind() != AsmToken::LParen)
830 return true;
831 } else
832 break;
833 }
834 if (getParser().ParseParenExpression(IdVal,EndLoc))
835 return true;
836
837 while (getLexer().getKind() == AsmToken::RParen)
Jack Carter30116cd2012-10-04 02:29:46 +0000838 Parser.Lex(); // eat ')' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000839
840 } else
Jack Carter30116cd2012-10-04 02:29:46 +0000841 return true; // parenthesis must follow reloc operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000842
Jack Carter30116cd2012-10-04 02:29:46 +0000843 // Check the type of the expression
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000844 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000845 // it's a constant, evaluate lo or hi value
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000846 int Val = MCE->getValue();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000847 if (Str == "lo") {
848 Val = Val & 0xffff;
849 } else if (Str == "hi") {
850 Val = (Val & 0xffff0000) >> 16;
851 }
852 Res = MCConstantExpr::Create(Val, getContext());
853 return false;
854 }
855
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000856 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter30116cd2012-10-04 02:29:46 +0000857 // it's a symbol, create symbolic expression from symbol
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000858 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000859 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
860 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
861 return false;
862 }
863 return true;
864}
865
Jack Carterec65be82012-09-05 23:34:03 +0000866bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
867 SMLoc &EndLoc) {
868
869 StartLoc = Parser.getTok().getLoc();
870 RegNo = tryParseRegister("");
871 EndLoc = Parser.getTok().getLoc();
872 return (RegNo == (unsigned)-1);
873}
874
Jack Carter6b96c3f2012-09-06 20:00:02 +0000875bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
876
877 SMLoc S;
878
879 switch(getLexer().getKind()) {
880 default:
881 return true;
882 case AsmToken::Integer:
883 case AsmToken::Minus:
884 case AsmToken::Plus:
885 return (getParser().ParseExpression(Res));
Jack Carterf740d6e2012-09-07 00:23:42 +0000886 case AsmToken::Percent:
Jack Carter6b96c3f2012-09-06 20:00:02 +0000887 return parseRelocOperand(Res);
Jack Carter6b96c3f2012-09-06 20:00:02 +0000888 case AsmToken::LParen:
Jack Carter30116cd2012-10-04 02:29:46 +0000889 return false; // it's probably assuming 0
Jack Carter6b96c3f2012-09-06 20:00:02 +0000890 }
891 return true;
892}
893
Jack Carterec65be82012-09-05 23:34:03 +0000894MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
895 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000896
897 const MCExpr *IdVal = 0;
898 SMLoc S;
Jack Carter30116cd2012-10-04 02:29:46 +0000899 // first operand is the offset
Jack Carter6b96c3f2012-09-06 20:00:02 +0000900 S = Parser.getTok().getLoc();
901
902 if (parseMemOffset(IdVal))
903 return MatchOperand_ParseFail;
904
Jack Carter30116cd2012-10-04 02:29:46 +0000905 const AsmToken &Tok = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000906 if (Tok.isNot(AsmToken::LParen)) {
Jack Carter2f68b312012-10-09 23:29:45 +0000907 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
908 if (Mnemonic->getToken() == "la") {
909 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
910 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
911 return MatchOperand_Success;
912 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000913 Error(Parser.getTok().getLoc(), "'(' expected");
914 return MatchOperand_ParseFail;
915 }
916
917 Parser.Lex(); // Eat '(' token.
918
Jack Carter2f68b312012-10-09 23:29:45 +0000919 const AsmToken &Tok1 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000920 if (Tok1.is(AsmToken::Dollar)) {
921 Parser.Lex(); // Eat '$' token.
922 if (tryParseRegisterOperand(Operands,"")) {
923 Error(Parser.getTok().getLoc(), "unexpected token in operand");
924 return MatchOperand_ParseFail;
925 }
926
927 } else {
Jack Carter30116cd2012-10-04 02:29:46 +0000928 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carter6b96c3f2012-09-06 20:00:02 +0000929 return MatchOperand_ParseFail;
930 }
931
Jack Carter30116cd2012-10-04 02:29:46 +0000932 const AsmToken &Tok2 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000933 if (Tok2.isNot(AsmToken::RParen)) {
934 Error(Parser.getTok().getLoc(), "')' expected");
935 return MatchOperand_ParseFail;
936 }
937
938 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
939
940 Parser.Lex(); // Eat ')' token.
941
942 if (IdVal == 0)
943 IdVal = MCConstantExpr::Create(0, getContext());
944
Jack Carter30116cd2012-10-04 02:29:46 +0000945 // now replace register operand with the mem operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000946 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
947 int RegNo = op->getReg();
Jack Carter30116cd2012-10-04 02:29:46 +0000948 // remove register from operands
Jack Carter6b96c3f2012-09-06 20:00:02 +0000949 Operands.pop_back();
Jack Carter30116cd2012-10-04 02:29:46 +0000950 // and add memory operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000951 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
952 delete op;
Jack Carterec65be82012-09-05 23:34:03 +0000953 return MatchOperand_Success;
954}
955
Jack Carter6b96c3f2012-09-06 20:00:02 +0000956MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
957
958 MCSymbolRefExpr::VariantKind VK
959 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
960 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
961 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
962 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
963 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
964 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
965 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
966 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
967 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
968 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
969 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
970 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
971 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
972 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
973 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
974 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
975 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
976 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
977 .Default(MCSymbolRefExpr::VK_None);
978
979 return VK;
980}
981
Benjamin Kramer1ac45872012-09-10 11:52:14 +0000982static int ConvertCcString(StringRef CondString) {
Jack Carterf740d6e2012-09-07 00:23:42 +0000983 int CC = StringSwitch<unsigned>(CondString)
984 .Case(".f", 0)
985 .Case(".un", 1)
986 .Case(".eq", 2)
987 .Case(".ueq", 3)
988 .Case(".olt", 4)
989 .Case(".ult", 5)
990 .Case(".ole", 6)
991 .Case(".ule", 7)
992 .Case(".sf", 8)
993 .Case(".ngle", 9)
994 .Case(".seq", 10)
995 .Case(".ngl", 11)
996 .Case(".lt", 12)
997 .Case(".nge", 13)
998 .Case(".le", 14)
999 .Case(".ngt", 15)
1000 .Default(-1);
1001
1002 return CC;
1003}
1004
1005bool MipsAsmParser::
1006parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter30116cd2012-10-04 02:29:46 +00001007 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1008 // split the format
Jack Carterf740d6e2012-09-07 00:23:42 +00001009 size_t Start = Name.find('.'), Next = Name.rfind('.');
1010 StringRef Format1 = Name.slice(Start, Next);
Jack Carter30116cd2012-10-04 02:29:46 +00001011 // and add the first format to the operands
Jack Carterf740d6e2012-09-07 00:23:42 +00001012 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carter30116cd2012-10-04 02:29:46 +00001013 // now for the second format
Jack Carterf740d6e2012-09-07 00:23:42 +00001014 StringRef Format2 = Name.slice(Next, StringRef::npos);
1015 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1016
Jack Carter30116cd2012-10-04 02:29:46 +00001017 // set the format for the first register
Jack Carterf740d6e2012-09-07 00:23:42 +00001018 setFpFormat(Format1);
1019
1020 // Read the remaining operands.
1021 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1022 // Read the first operand.
1023 if (ParseOperand(Operands, Name)) {
1024 SMLoc Loc = getLexer().getLoc();
1025 Parser.EatToEndOfStatement();
1026 return Error(Loc, "unexpected token in argument list");
1027 }
1028
1029 if (getLexer().isNot(AsmToken::Comma)) {
1030 SMLoc Loc = getLexer().getLoc();
1031 Parser.EatToEndOfStatement();
1032 return Error(Loc, "unexpected token in argument list");
1033
1034 }
1035 Parser.Lex(); // Eat the comma.
1036
1037 //set the format for the first register
1038 setFpFormat(Format2);
1039
1040 // Parse and remember the operand.
1041 if (ParseOperand(Operands, Name)) {
1042 SMLoc Loc = getLexer().getLoc();
1043 Parser.EatToEndOfStatement();
1044 return Error(Loc, "unexpected token in argument list");
1045 }
1046 }
1047
1048 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1049 SMLoc Loc = getLexer().getLoc();
1050 Parser.EatToEndOfStatement();
1051 return Error(Loc, "unexpected token in argument list");
1052 }
1053
1054 Parser.Lex(); // Consume the EndOfStatement
1055 return false;
1056}
1057
Rafael Espindolafddf8042012-01-11 03:56:41 +00001058bool MipsAsmParser::
1059ParseInstruction(StringRef Name, SMLoc NameLoc,
1060 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter30116cd2012-10-04 02:29:46 +00001061 // floating point instructions: should register be treated as double?
Jack Carterf740d6e2012-09-07 00:23:42 +00001062 if (requestsDoubleOperand(Name)) {
1063 setFpFormat(FP_FORMAT_D);
Jack Carterec65be82012-09-05 23:34:03 +00001064 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterf740d6e2012-09-07 00:23:42 +00001065 }
1066 else {
1067 setDefaultFpFormat();
1068 // Create the leading tokens for the mnemonic, split by '.' characters.
1069 size_t Start = 0, Next = Name.find('.');
1070 StringRef Mnemonic = Name.slice(Start, Next);
1071
1072 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1073
1074 if (Next != StringRef::npos) {
Jack Carter30116cd2012-10-04 02:29:46 +00001075 // there is a format token in mnemonic
1076 // StringRef Rest = Name.slice(Next, StringRef::npos);
Jack Carterf740d6e2012-09-07 00:23:42 +00001077 size_t Dot = Name.find('.', Next+1);
1078 StringRef Format = Name.slice(Next, Dot);
1079 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1080 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1081 else {
1082 if (Name.startswith("c.")){
1083 // floating point compare, add '.' and immediate represent for cc
1084 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1085 int Cc = ConvertCcString(Format);
1086 if (Cc == -1) {
1087 return Error(NameLoc, "Invalid conditional code");
1088 }
1089 SMLoc E = SMLoc::getFromPointer(
1090 Parser.getTok().getLoc().getPointer() -1 );
1091 Operands.push_back(MipsOperand::CreateImm(
1092 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1093 } else {
Jack Carter30116cd2012-10-04 02:29:46 +00001094 // trunc, ceil, floor ...
Jack Carterf740d6e2012-09-07 00:23:42 +00001095 return parseMathOperation(Name, NameLoc, Operands);
1096 }
1097
Jack Carter30116cd2012-10-04 02:29:46 +00001098 // the rest is a format
Jack Carterf740d6e2012-09-07 00:23:42 +00001099 Format = Name.slice(Dot, StringRef::npos);
1100 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1101 }
1102
1103 setFpFormat(Format);
1104 }
1105 }
Jack Carterec65be82012-09-05 23:34:03 +00001106
1107 // Read the remaining operands.
1108 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1109 // Read the first operand.
1110 if (ParseOperand(Operands, Name)) {
1111 SMLoc Loc = getLexer().getLoc();
1112 Parser.EatToEndOfStatement();
1113 return Error(Loc, "unexpected token in argument list");
1114 }
1115
1116 while (getLexer().is(AsmToken::Comma) ) {
1117 Parser.Lex(); // Eat the comma.
1118
1119 // Parse and remember the operand.
1120 if (ParseOperand(Operands, Name)) {
1121 SMLoc Loc = getLexer().getLoc();
1122 Parser.EatToEndOfStatement();
1123 return Error(Loc, "unexpected token in argument list");
1124 }
1125 }
1126 }
1127
1128 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1129 SMLoc Loc = getLexer().getLoc();
1130 Parser.EatToEndOfStatement();
1131 return Error(Loc, "unexpected token in argument list");
1132 }
1133
1134 Parser.Lex(); // Consume the EndOfStatement
1135 return false;
Rafael Espindolafddf8042012-01-11 03:56:41 +00001136}
1137
Jack Carter30116cd2012-10-04 02:29:46 +00001138bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1139 SMLoc Loc = getLexer().getLoc();
1140 Parser.EatToEndOfStatement();
1141 return Error(Loc, ErrorMsg);
1142}
1143
1144bool MipsAsmParser::parseSetNoAtDirective() {
1145 // line should look like:
1146 // .set noat
1147 // set at reg to 0
Jack Carter10d5ff62012-10-05 23:55:28 +00001148 Options.setATReg(0);
Jack Carter30116cd2012-10-04 02:29:46 +00001149 // eat noat
1150 Parser.Lex();
1151 // if this is not the end of the statement, report error
1152 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1153 reportParseError("unexpected token in statement");
1154 return false;
1155 }
1156 Parser.Lex(); // Consume the EndOfStatement
1157 return false;
1158}
1159bool MipsAsmParser::parseSetAtDirective() {
1160 // line can be
1161 // .set at - defaults to $1
1162 // or .set at=$reg
1163 getParser().Lex();
1164 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter10d5ff62012-10-05 23:55:28 +00001165 Options.setATReg(1);
Jack Carter30116cd2012-10-04 02:29:46 +00001166 Parser.Lex(); // Consume the EndOfStatement
1167 return false;
1168 } else if (getLexer().is(AsmToken::Equal)) {
1169 getParser().Lex(); //eat '='
1170 if (getLexer().isNot(AsmToken::Dollar)) {
1171 reportParseError("unexpected token in statement");
1172 return false;
1173 }
1174 Parser.Lex(); // eat '$'
1175 if (getLexer().isNot(AsmToken::Integer)) {
1176 reportParseError("unexpected token in statement");
1177 return false;
1178 }
1179 const AsmToken &Reg = Parser.getTok();
Jack Carter10d5ff62012-10-05 23:55:28 +00001180 if (!Options.setATReg(Reg.getIntVal())) {
Jack Carter30116cd2012-10-04 02:29:46 +00001181 reportParseError("unexpected token in statement");
1182 return false;
1183 }
1184 getParser().Lex(); //eat reg
1185
1186 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1187 reportParseError("unexpected token in statement");
1188 return false;
1189 }
1190 Parser.Lex(); // Consume the EndOfStatement
1191 return false;
1192 } else {
1193 reportParseError("unexpected token in statement");
1194 return false;
1195 }
1196}
1197
1198bool MipsAsmParser::parseSetReorderDirective() {
1199 Parser.Lex();
1200 // if this is not the end of the statement, report error
1201 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1202 reportParseError("unexpected token in statement");
1203 return false;
1204 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001205 Options.setReorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001206 Parser.Lex(); // Consume the EndOfStatement
1207 return false;
1208}
1209
1210bool MipsAsmParser::parseSetNoReorderDirective() {
1211 Parser.Lex();
1212 // if this is not the end of the statement, report error
1213 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1214 reportParseError("unexpected token in statement");
1215 return false;
1216 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001217 Options.setNoreorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001218 Parser.Lex(); // Consume the EndOfStatement
1219 return false;
1220}
1221
1222bool MipsAsmParser::parseSetMacroDirective() {
1223 Parser.Lex();
1224 // if this is not the end of the statement, report error
1225 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1226 reportParseError("unexpected token in statement");
1227 return false;
1228 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001229 Options.setMacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001230 Parser.Lex(); // Consume the EndOfStatement
1231 return false;
1232}
1233
1234bool MipsAsmParser::parseSetNoMacroDirective() {
1235 Parser.Lex();
1236 // if this is not the end of the statement, report error
1237 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1238 reportParseError("`noreorder' must be set before `nomacro'");
1239 return false;
1240 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001241 if (Options.isReorder()) {
Jack Carter30116cd2012-10-04 02:29:46 +00001242 reportParseError("`noreorder' must be set before `nomacro'");
1243 return false;
1244 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001245 Options.setNomacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001246 Parser.Lex(); // Consume the EndOfStatement
1247 return false;
1248}
1249bool MipsAsmParser::parseDirectiveSet() {
1250
1251 // get next token
1252 const AsmToken &Tok = Parser.getTok();
1253
1254 if (Tok.getString() == "noat") {
1255 return parseSetNoAtDirective();
1256 } else if (Tok.getString() == "at") {
1257 return parseSetAtDirective();
1258 } else if (Tok.getString() == "reorder") {
1259 return parseSetReorderDirective();
1260 } else if (Tok.getString() == "noreorder") {
1261 return parseSetNoReorderDirective();
1262 } else if (Tok.getString() == "macro") {
1263 return parseSetMacroDirective();
1264 } else if (Tok.getString() == "nomacro") {
1265 return parseSetNoMacroDirective();
1266 } else if (Tok.getString() == "nomips16") {
1267 // ignore this directive for now
1268 Parser.EatToEndOfStatement();
1269 return false;
1270 } else if (Tok.getString() == "nomicromips") {
1271 // ignore this directive for now
1272 Parser.EatToEndOfStatement();
1273 return false;
1274 }
1275 return true;
1276}
1277
1278bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carteracbea452012-09-07 00:48:02 +00001279
1280 if (DirectiveID.getString() == ".ent") {
Jack Carter30116cd2012-10-04 02:29:46 +00001281 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001282 Parser.Lex();
1283 return false;
1284 }
1285
1286 if (DirectiveID.getString() == ".end") {
Jack Carter30116cd2012-10-04 02:29:46 +00001287 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001288 Parser.Lex();
1289 return false;
1290 }
1291
1292 if (DirectiveID.getString() == ".frame") {
Jack Carter30116cd2012-10-04 02:29:46 +00001293 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001294 Parser.EatToEndOfStatement();
1295 return false;
1296 }
1297
1298 if (DirectiveID.getString() == ".set") {
Jack Carter30116cd2012-10-04 02:29:46 +00001299 return parseDirectiveSet();
Jack Carteracbea452012-09-07 00:48:02 +00001300 }
1301
1302 if (DirectiveID.getString() == ".fmask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001303 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001304 Parser.EatToEndOfStatement();
1305 return false;
1306 }
1307
1308 if (DirectiveID.getString() == ".mask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001309 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001310 Parser.EatToEndOfStatement();
1311 return false;
1312 }
1313
1314 if (DirectiveID.getString() == ".gpword") {
Jack Carter30116cd2012-10-04 02:29:46 +00001315 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001316 Parser.EatToEndOfStatement();
1317 return false;
1318 }
1319
Rafael Espindolafddf8042012-01-11 03:56:41 +00001320 return true;
1321}
1322
Rafael Espindolafddf8042012-01-11 03:56:41 +00001323extern "C" void LLVMInitializeMipsAsmParser() {
1324 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1325 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1326 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1327 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1328}
Jack Carterec65be82012-09-05 23:34:03 +00001329
1330#define GET_REGISTER_MATCHER
1331#define GET_MATCHER_IMPLEMENTATION
1332#include "MipsGenAsmMatcher.inc"