blob: c94c6614aed473acd4252a82c08989477d5b1378 [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
Rafael Espindolafddf8042012-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 Hatanaka72e9b6a2012-08-17 20:16:42 +000077 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindolafddf8042012-01-11 03:56:41 +000078
Jack Carterf740d6e2012-09-07 00:23:42 +000079 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
80 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
81
Rafael Espindolafddf8042012-01-11 03:56:41 +000082 bool ParseDirective(AsmToken DirectiveID);
83
Jack Carterec65be82012-09-05 23:34:03 +000084 MipsAsmParser::OperandMatchResultTy
85 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
Chad Rosier038f3e32012-09-03 18:47:45 +000086
Jack Carterec65be82012-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 Carter9d577c82012-10-04 04:03:53 +000095 bool needsExpansion(MCInst &Inst);
96
97 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +000098 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9d577c82012-10-04 04:03:53 +000099 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000100 SmallVectorImpl<MCInst> &Instructions);
Jack Carter2f68b312012-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 Carter30116cd2012-10-04 02:29:46 +0000105 bool reportParseError(StringRef ErrorMsg);
106
Jack Carter6b96c3f2012-09-06 20:00:02 +0000107 bool parseMemOffset(const MCExpr *&Res);
108 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter30116cd2012-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 Carter6b96c3f2012-09-06 20:00:02 +0000119 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Carterf740d6e2012-09-07 00:23:42 +0000120
Jack Carterec65be82012-09-05 23:34:03 +0000121 bool isMips64() const {
122 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
123 }
124
Jack Carterf740d6e2012-09-07 00:23:42 +0000125 bool isFP64() const {
126 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
127 }
128
Jack Carterec65be82012-09-05 23:34:03 +0000129 int matchRegisterName(StringRef Symbol);
130
131 int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
132
Jack Carterf740d6e2012-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 Carterec65be82012-09-05 23:34:03 +0000145 unsigned getReg(int RC,int RegNo);
Chad Rosier038f3e32012-09-03 18:47:45 +0000146
Jack Carter30116cd2012-10-04 02:29:46 +0000147 unsigned getATReg();
Rafael Espindolafddf8042012-01-11 03:56:41 +0000148public:
149 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterec65be82012-09-05 23:34:03 +0000150 : MCTargetAsmParser(), STI(sti), Parser(parser) {
151 // Initialize the set of available features.
152 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindolafddf8042012-01-11 03:56:41 +0000153 }
154
Jack Carterec65be82012-09-05 23:34:03 +0000155 MCAsmParser &getParser() const { return Parser; }
156 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
157
Rafael Espindolafddf8042012-01-11 03:56:41 +0000158};
159}
160
Akira Hatanaka72e9b6a2012-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 Carterec65be82012-09-05 23:34:03 +0000166
Akira Hatanaka72e9b6a2012-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 Carterec65be82012-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 Carter6b96c3f2012-09-06 20:00:02 +0000192
193 struct {
194 unsigned Base;
195 const MCExpr *Off;
196 } Mem;
Jack Carterec65be82012-09-05 23:34:03 +0000197 };
198
199 SMLoc StartLoc, EndLoc;
200
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000201public:
202 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000203 assert(N == 1 && "Invalid number of operands!");
204 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000205 }
Jack Carterec65be82012-09-05 23:34:03 +0000206
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000207 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterec65be82012-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 Hatanaka72e9b6a2012-08-17 20:16:42 +0000215 }
Jack Carterec65be82012-09-05 23:34:03 +0000216
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000217 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000218 assert(N == 1 && "Invalid number of operands!");
219 const MCExpr *Expr = getImm();
220 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000221 }
Jack Carterec65be82012-09-05 23:34:03 +0000222
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000223 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carter6b96c3f2012-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 Hatanaka72e9b6a2012-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 Carterec65be82012-09-05 23:34:03 +0000239 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000240 }
241
242 unsigned getReg() const {
243 assert((Kind == k_Register) && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000244 return Reg.RegNum;
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000245 }
246
Jack Carterec65be82012-09-05 23:34:03 +0000247 const MCExpr *getImm() const {
248 assert((Kind == k_Immediate) && "Invalid access!");
249 return Imm.Val;
250 }
251
Jack Carter6b96c3f2012-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 Carterec65be82012-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 Carter6b96c3f2012-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 Carterec65be82012-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 Hatanaka72e9b6a2012-08-17 20:16:42 +0000302 virtual void print(raw_ostream &OS) const {
303 llvm_unreachable("unimplemented!");
304 }
305};
306}
307
Jack Carter9d577c82012-10-04 04:03:53 +0000308bool MipsAsmParser::needsExpansion(MCInst &Inst) {
309
310 switch(Inst.getOpcode()) {
311 case Mips::LoadImm32Reg:
Jack Carter2f68b312012-10-09 23:29:45 +0000312 case Mips::LoadAddr32Imm:
313 case Mips::LoadAddr32Reg:
Jack Carter9d577c82012-10-04 04:03:53 +0000314 return true;
315 default:
316 return false;
317 }
318}
Jack Carter2490dc62012-10-06 00:53:28 +0000319
Jack Carter9d577c82012-10-04 04:03:53 +0000320void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000321 SmallVectorImpl<MCInst> &Instructions){
Jack Carter9d577c82012-10-04 04:03:53 +0000322 switch(Inst.getOpcode()) {
323 case Mips::LoadImm32Reg:
324 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carter2f68b312012-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 Carter9d577c82012-10-04 04:03:53 +0000329 }
Jack Carter9d577c82012-10-04 04:03:53 +0000330}
Jack Carter2490dc62012-10-06 00:53:28 +0000331
Jack Carter9d577c82012-10-04 04:03:53 +0000332void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter2f68b312012-10-09 23:29:45 +0000333 SmallVectorImpl<MCInst> &Instructions){
Jack Carter2490dc62012-10-06 00:53:28 +0000334 MCInst tmpInst;
Jack Carter9d577c82012-10-04 04:03:53 +0000335 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter2f68b312012-10-09 23:29:45 +0000336 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter9d577c82012-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 Carter2490dc62012-10-06 00:53:28 +0000341 tmpInst.setLoc(IDLoc);
Jack Carter9d577c82012-10-04 04:03:53 +0000342 if ( 0 <= ImmValue && ImmValue <= 65535) {
Jack Carter2490dc62012-10-06 00:53:28 +0000343 // for 0 <= j <= 65535.
Jack Carter9d577c82012-10-04 04:03:53 +0000344 // li d,j => ori d,$zero,j
Jack Carter2490dc62012-10-06 00:53:28 +0000345 tmpInst.setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
346 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
347 tmpInst.addOperand(
Jack Carter9d577c82012-10-04 04:03:53 +0000348 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
Jack Carter2490dc62012-10-06 00:53:28 +0000349 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter9d577c82012-10-04 04:03:53 +0000350 Instructions.push_back(tmpInst);
351 } else if ( ImmValue < 0 && ImmValue >= -32768) {
Jack Carter2490dc62012-10-06 00:53:28 +0000352 // for -32768 <= j < 0.
Jack Carter9d577c82012-10-04 04:03:53 +0000353 // li d,j => addiu d,$zero,j
Jack Carter2490dc62012-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 Carter9d577c82012-10-04 04:03:53 +0000357 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
Jack Carter2490dc62012-10-06 00:53:28 +0000358 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter9d577c82012-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 Carter2f68b312012-10-09 23:29:45 +0000363 // ori d,d,lo16(j)
Jack Carter2490dc62012-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 Carter9d577c82012-10-04 04:03:53 +0000367 Instructions.push_back(tmpInst);
Jack Carter2490dc62012-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 Carter9d577c82012-10-04 04:03:53 +0000374 Instructions.push_back(tmpInst);
375 }
376}
Jack Carter2490dc62012-10-06 00:53:28 +0000377
Jack Carter2f68b312012-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 Espindolafddf8042012-01-11 03:56:41 +0000454bool MipsAsmParser::
455MatchAndEmitInstruction(SMLoc IDLoc,
456 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
457 MCStreamer &Out) {
Jack Carterec65be82012-09-05 23:34:03 +0000458 MCInst Inst;
Chad Rosier22685872012-10-01 23:45:51 +0000459 unsigned ErrorInfo;
Chad Rosier6e006d32012-10-12 22:53:36 +0000460 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier22685872012-10-01 23:45:51 +0000461 /*matchingInlineAsm*/ false);
Jack Carterec65be82012-09-05 23:34:03 +0000462
463 switch (MatchResult) {
464 default: break;
465 case Match_Success: {
Jack Carter9d577c82012-10-04 04:03:53 +0000466 if (needsExpansion(Inst)) {
Jack Carter2490dc62012-10-06 00:53:28 +0000467 SmallVector<MCInst, 4> Instructions;
Jack Carter9d577c82012-10-04 04:03:53 +0000468 expandInstruction(Inst, IDLoc, Instructions);
469 for(unsigned i =0; i < Instructions.size(); i++){
Jack Carter2490dc62012-10-06 00:53:28 +0000470 Out.EmitInstruction(Instructions[i]);
Jack Carter9d577c82012-10-04 04:03:53 +0000471 }
472 } else {
473 Inst.setLoc(IDLoc);
474 Out.EmitInstruction(Inst);
475 }
Jack Carterec65be82012-09-05 23:34:03 +0000476 return false;
477 }
478 case Match_MissingFeature:
479 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
480 return true;
481 case Match_InvalidOperand: {
482 SMLoc ErrorLoc = IDLoc;
483 if (ErrorInfo != ~0U) {
484 if (ErrorInfo >= Operands.size())
485 return Error(IDLoc, "too few operands for instruction");
486
487 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
488 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
489 }
490
491 return Error(ErrorLoc, "invalid operand for instruction");
492 }
493 case Match_MnemonicFail:
494 return Error(IDLoc, "invalid instruction");
495 }
Rafael Espindolafddf8042012-01-11 03:56:41 +0000496 return true;
497}
498
Jack Carterec65be82012-09-05 23:34:03 +0000499int MipsAsmParser::matchRegisterName(StringRef Name) {
500
David Chisnall572e1bd2012-10-09 16:27:43 +0000501 int CC;
502 if (!isMips64())
503 CC = StringSwitch<unsigned>(Name)
504 .Case("zero", Mips::ZERO)
505 .Case("a0", Mips::A0)
506 .Case("a1", Mips::A1)
507 .Case("a2", Mips::A2)
508 .Case("a3", Mips::A3)
509 .Case("v0", Mips::V0)
510 .Case("v1", Mips::V1)
511 .Case("s0", Mips::S0)
512 .Case("s1", Mips::S1)
513 .Case("s2", Mips::S2)
514 .Case("s3", Mips::S3)
515 .Case("s4", Mips::S4)
516 .Case("s5", Mips::S5)
517 .Case("s6", Mips::S6)
518 .Case("s7", Mips::S7)
519 .Case("k0", Mips::K0)
520 .Case("k1", Mips::K1)
521 .Case("sp", Mips::SP)
522 .Case("fp", Mips::FP)
523 .Case("gp", Mips::GP)
524 .Case("ra", Mips::RA)
525 .Case("t0", Mips::T0)
526 .Case("t1", Mips::T1)
527 .Case("t2", Mips::T2)
528 .Case("t3", Mips::T3)
529 .Case("t4", Mips::T4)
530 .Case("t5", Mips::T5)
531 .Case("t6", Mips::T6)
532 .Case("t7", Mips::T7)
533 .Case("t8", Mips::T8)
534 .Case("t9", Mips::T9)
535 .Case("at", Mips::AT)
536 .Case("fcc0", Mips::FCC0)
537 .Default(-1);
538 else
539 CC = StringSwitch<unsigned>(Name)
540 .Case("zero", Mips::ZERO_64)
541 .Case("at", Mips::AT_64)
542 .Case("v0", Mips::V0_64)
543 .Case("v1", Mips::V1_64)
544 .Case("a0", Mips::A0_64)
545 .Case("a1", Mips::A1_64)
546 .Case("a2", Mips::A2_64)
547 .Case("a3", Mips::A3_64)
548 .Case("a4", Mips::T0_64)
549 .Case("a5", Mips::T1_64)
550 .Case("a6", Mips::T2_64)
551 .Case("a7", Mips::T3_64)
552 .Case("t4", Mips::T4_64)
553 .Case("t5", Mips::T5_64)
554 .Case("t6", Mips::T6_64)
555 .Case("t7", Mips::T7_64)
556 .Case("s0", Mips::S0_64)
557 .Case("s1", Mips::S1_64)
558 .Case("s2", Mips::S2_64)
559 .Case("s3", Mips::S3_64)
560 .Case("s4", Mips::S4_64)
561 .Case("s5", Mips::S5_64)
562 .Case("s6", Mips::S6_64)
563 .Case("s7", Mips::S7_64)
564 .Case("t8", Mips::T8_64)
565 .Case("t9", Mips::T9_64)
566 .Case("kt0", Mips::K0_64)
567 .Case("kt1", Mips::K1_64)
568 .Case("gp", Mips::GP_64)
569 .Case("sp", Mips::SP_64)
570 .Case("fp", Mips::FP_64)
571 .Case("s8", Mips::FP_64)
572 .Case("ra", Mips::RA_64)
573 .Default(-1);
Jack Carterec65be82012-09-05 23:34:03 +0000574
David Chisnall572e1bd2012-10-09 16:27:43 +0000575 if (CC != -1)
Jack Carterec65be82012-09-05 23:34:03 +0000576 return CC;
Jack Carterec65be82012-09-05 23:34:03 +0000577
Jack Carterf740d6e2012-09-07 00:23:42 +0000578 if (Name[0] == 'f') {
579 StringRef NumString = Name.substr(1);
580 unsigned IntVal;
581 if( NumString.getAsInteger(10, IntVal))
Jack Carter9d577c82012-10-04 04:03:53 +0000582 return -1; // not integer
Jack Carterf740d6e2012-09-07 00:23:42 +0000583 if (IntVal > 31)
584 return -1;
585
586 FpFormatTy Format = getFpFormat();
587
588 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
589 return getReg(Mips::FGR32RegClassID, IntVal);
590 if (Format == FP_FORMAT_D) {
591 if(isFP64()) {
592 return getReg(Mips::FGR64RegClassID, IntVal);
593 }
Jack Carter9d577c82012-10-04 04:03:53 +0000594 // only even numbers available as register pairs
Jack Carterf740d6e2012-09-07 00:23:42 +0000595 if (( IntVal > 31) || (IntVal%2 != 0))
596 return -1;
597 return getReg(Mips::AFGR64RegClassID, IntVal/2);
598 }
599 }
600
Jack Carterec65be82012-09-05 23:34:03 +0000601 return -1;
602}
Jack Carterf740d6e2012-09-07 00:23:42 +0000603void MipsAsmParser::setDefaultFpFormat() {
604
605 if (isMips64() || isFP64())
606 FpFormat = FP_FORMAT_D;
607 else
608 FpFormat = FP_FORMAT_S;
609}
610
611bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
612
613 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
614 .Case("ldxc1", true)
615 .Case("ldc1", true)
616 .Case("sdxc1", true)
617 .Case("sdc1", true)
618 .Default(false);
619
620 return IsDouble;
621}
622void MipsAsmParser::setFpFormat(StringRef Format) {
623
624 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
625 .Case(".s", FP_FORMAT_S)
626 .Case(".d", FP_FORMAT_D)
627 .Case(".l", FP_FORMAT_L)
628 .Case(".w", FP_FORMAT_W)
629 .Default(FP_FORMAT_NONE);
630}
Jack Carterec65be82012-09-05 23:34:03 +0000631
Jack Carter30116cd2012-10-04 02:29:46 +0000632bool MipsAssemblerOptions::setATReg(unsigned Reg) {
633 if (Reg > 31)
634 return false;
635
636 aTReg = Reg;
637 return true;
638}
639
640unsigned MipsAsmParser::getATReg() {
Jack Carter10d5ff62012-10-05 23:55:28 +0000641 unsigned Reg = Options.getATRegNum();
Jack Carter30116cd2012-10-04 02:29:46 +0000642 if (isMips64())
643 return getReg(Mips::CPU64RegsRegClassID,Reg);
Jack Carter10d5ff62012-10-05 23:55:28 +0000644
645 return getReg(Mips::CPURegsRegClassID,Reg);
Jack Carter30116cd2012-10-04 02:29:46 +0000646}
647
648unsigned MipsAsmParser::getReg(int RC,int RegNo) {
Jack Carterec65be82012-09-05 23:34:03 +0000649 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
650}
651
Jack Carter30116cd2012-10-04 02:29:46 +0000652int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
Jack Carterec65be82012-09-05 23:34:03 +0000653
654 if (Mnemonic.lower() == "rdhwr") {
Jack Carter9d577c82012-10-04 04:03:53 +0000655 // at the moment only hwreg29 is supported
Jack Carterec65be82012-09-05 23:34:03 +0000656 if (RegNum != 29)
657 return -1;
658 return Mips::HWR29;
659 }
660
661 if (RegNum > 31)
662 return -1;
663
David Chisnall572e1bd2012-10-09 16:27:43 +0000664 // MIPS64 registers are numbered 1 after the 32-bit equivalents
665 return getReg(Mips::CPURegsRegClassID, RegNum) + isMips64();
Jack Carterec65be82012-09-05 23:34:03 +0000666}
667
668int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
669 const AsmToken &Tok = Parser.getTok();
670 int RegNum = -1;
671
672 if (Tok.is(AsmToken::Identifier)) {
673 std::string lowerCase = Tok.getString().lower();
674 RegNum = matchRegisterName(lowerCase);
675 } else if (Tok.is(AsmToken::Integer))
Jack Carter9d577c82012-10-04 04:03:53 +0000676 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carter6b96c3f2012-09-06 20:00:02 +0000677 Mnemonic.lower());
Jack Carterf740d6e2012-09-07 00:23:42 +0000678 else
679 return RegNum; //error
Jack Carter9d577c82012-10-04 04:03:53 +0000680 // 64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
Jack Carterf740d6e2012-09-07 00:23:42 +0000681 if (isMips64() && RegNum == Mips::ZERO_64) {
682 if (Mnemonic.find("ddiv") != StringRef::npos)
683 RegNum = Mips::ZERO;
684 }
Jack Carterec65be82012-09-05 23:34:03 +0000685 return RegNum;
686}
687
Rafael Espindolafddf8042012-01-11 03:56:41 +0000688bool MipsAsmParser::
Jack Carterec65be82012-09-05 23:34:03 +0000689 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
690 StringRef Mnemonic){
691
692 SMLoc S = Parser.getTok().getLoc();
693 int RegNo = -1;
Jack Carterf740d6e2012-09-07 00:23:42 +0000694
Jack Carter9d577c82012-10-04 04:03:53 +0000695 // FIXME: we should make a more generic method for CCR
Jack Carterf740d6e2012-09-07 00:23:42 +0000696 if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
697 && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
Jack Carter9d577c82012-10-04 04:03:53 +0000698 RegNo = Parser.getTok().getIntVal(); // get the int value
699 // at the moment only fcc0 is supported
Jack Carterf740d6e2012-09-07 00:23:42 +0000700 if (RegNo == 0)
701 RegNo = Mips::FCC0;
702 } else
703 RegNo = tryParseRegister(Mnemonic);
Jack Carterec65be82012-09-05 23:34:03 +0000704 if (RegNo == -1)
705 return true;
706
707 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterf740d6e2012-09-07 00:23:42 +0000708 Parser.getTok().getLoc()));
Jack Carterec65be82012-09-05 23:34:03 +0000709 Parser.Lex(); // Eat register token.
710 return false;
711}
712
713bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
714 StringRef Mnemonic) {
Jack Carter9d577c82012-10-04 04:03:53 +0000715 // Check if the current operand has a custom associated parser, if so, try to
716 // custom parse the operand, or fallback to the general approach.
Jack Carterec65be82012-09-05 23:34:03 +0000717 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
718 if (ResTy == MatchOperand_Success)
719 return false;
720 // If there wasn't a custom match, try the generic matcher below. Otherwise,
721 // there was a match, but an error occurred, in which case, just return that
722 // the operand parsing failed.
723 if (ResTy == MatchOperand_ParseFail)
724 return true;
725
726 switch (getLexer().getKind()) {
727 default:
728 Error(Parser.getTok().getLoc(), "unexpected token in operand");
729 return true;
730 case AsmToken::Dollar: {
Jack Carter9d577c82012-10-04 04:03:53 +0000731 // parse register
Jack Carterec65be82012-09-05 23:34:03 +0000732 SMLoc S = Parser.getTok().getLoc();
733 Parser.Lex(); // Eat dollar token.
Jack Carter9d577c82012-10-04 04:03:53 +0000734 // parse register operand
735 if (!tryParseRegisterOperand(Operands, Mnemonic)) {
Jack Carterec65be82012-09-05 23:34:03 +0000736 if (getLexer().is(AsmToken::LParen)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000737 // check if it is indexed addressing operand
Jack Carterec65be82012-09-05 23:34:03 +0000738 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carter9d577c82012-10-04 04:03:53 +0000739 Parser.Lex(); // eat parenthesis
Jack Carterec65be82012-09-05 23:34:03 +0000740 if (getLexer().isNot(AsmToken::Dollar))
741 return true;
742
Jack Carter9d577c82012-10-04 04:03:53 +0000743 Parser.Lex(); // eat dollar
744 if (tryParseRegisterOperand(Operands, Mnemonic))
Jack Carterec65be82012-09-05 23:34:03 +0000745 return true;
746
747 if (!getLexer().is(AsmToken::RParen))
748 return true;
749
750 S = Parser.getTok().getLoc();
751 Operands.push_back(MipsOperand::CreateToken(")", S));
752 Parser.Lex();
753 }
754 return false;
755 }
Jack Carter9d577c82012-10-04 04:03:53 +0000756 // maybe it is a symbol reference
Jack Carterec65be82012-09-05 23:34:03 +0000757 StringRef Identifier;
758 if (Parser.ParseIdentifier(Identifier))
759 return true;
760
Jack Carter6b96c3f2012-09-06 20:00:02 +0000761 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000762
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000763 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterec65be82012-09-05 23:34:03 +0000764
765 // Otherwise create a symbol ref.
Jack Carter6b96c3f2012-09-06 20:00:02 +0000766 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterec65be82012-09-05 23:34:03 +0000767 getContext());
768
769 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
770 return false;
771 }
772 case AsmToken::Identifier:
773 case AsmToken::LParen:
774 case AsmToken::Minus:
775 case AsmToken::Plus:
776 case AsmToken::Integer:
777 case AsmToken::String: {
778 // quoted label names
779 const MCExpr *IdVal;
780 SMLoc S = Parser.getTok().getLoc();
781 if (getParser().ParseExpression(IdVal))
782 return true;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000783 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000784 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
785 return false;
786 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000787 case AsmToken::Percent: {
Jack Carter9d577c82012-10-04 04:03:53 +0000788 // it is a symbol reference or constant expression
Jack Carter6b96c3f2012-09-06 20:00:02 +0000789 const MCExpr *IdVal;
Jack Carter9d577c82012-10-04 04:03:53 +0000790 SMLoc S = Parser.getTok().getLoc(); // start location of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000791 if (parseRelocOperand(IdVal))
792 return true;
793
794 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
795
796 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
797 return false;
Jack Carter30116cd2012-10-04 02:29:46 +0000798 } // case AsmToken::Percent
799 } // switch(getLexer().getKind())
Rafael Espindolafddf8042012-01-11 03:56:41 +0000800 return true;
801}
802
Jack Carter6b96c3f2012-09-06 20:00:02 +0000803bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
804
Jack Carter30116cd2012-10-04 02:29:46 +0000805 Parser.Lex(); // eat % token
Jack Carter9d577c82012-10-04 04:03:53 +0000806 const AsmToken &Tok = Parser.getTok(); // get next token, operation
Jack Carter6b96c3f2012-09-06 20:00:02 +0000807 if (Tok.isNot(AsmToken::Identifier))
808 return true;
809
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000810 std::string Str = Tok.getIdentifier().str();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000811
Jack Carter9d577c82012-10-04 04:03:53 +0000812 Parser.Lex(); // eat identifier
Jack Carter30116cd2012-10-04 02:29:46 +0000813 // now make expression from the rest of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000814 const MCExpr *IdVal;
815 SMLoc EndLoc;
816
817 if (getLexer().getKind() == AsmToken::LParen) {
818 while (1) {
Jack Carter30116cd2012-10-04 02:29:46 +0000819 Parser.Lex(); // eat '(' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000820 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carter30116cd2012-10-04 02:29:46 +0000821 Parser.Lex(); // eat % token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000822 const AsmToken &nextTok = Parser.getTok();
823 if (nextTok.isNot(AsmToken::Identifier))
824 return true;
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000825 Str += "(%";
826 Str += nextTok.getIdentifier();
Jack Carter30116cd2012-10-04 02:29:46 +0000827 Parser.Lex(); // eat identifier
Jack Carter6b96c3f2012-09-06 20:00:02 +0000828 if (getLexer().getKind() != AsmToken::LParen)
829 return true;
830 } else
831 break;
832 }
833 if (getParser().ParseParenExpression(IdVal,EndLoc))
834 return true;
835
836 while (getLexer().getKind() == AsmToken::RParen)
Jack Carter30116cd2012-10-04 02:29:46 +0000837 Parser.Lex(); // eat ')' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000838
839 } else
Jack Carter30116cd2012-10-04 02:29:46 +0000840 return true; // parenthesis must follow reloc operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000841
Jack Carter30116cd2012-10-04 02:29:46 +0000842 // Check the type of the expression
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000843 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000844 // it's a constant, evaluate lo or hi value
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000845 int Val = MCE->getValue();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000846 if (Str == "lo") {
847 Val = Val & 0xffff;
848 } else if (Str == "hi") {
849 Val = (Val & 0xffff0000) >> 16;
850 }
851 Res = MCConstantExpr::Create(Val, getContext());
852 return false;
853 }
854
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000855 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter30116cd2012-10-04 02:29:46 +0000856 // it's a symbol, create symbolic expression from symbol
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000857 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000858 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
859 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
860 return false;
861 }
862 return true;
863}
864
Jack Carterec65be82012-09-05 23:34:03 +0000865bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
866 SMLoc &EndLoc) {
867
868 StartLoc = Parser.getTok().getLoc();
869 RegNo = tryParseRegister("");
870 EndLoc = Parser.getTok().getLoc();
871 return (RegNo == (unsigned)-1);
872}
873
Jack Carter6b96c3f2012-09-06 20:00:02 +0000874bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
875
876 SMLoc S;
877
878 switch(getLexer().getKind()) {
879 default:
880 return true;
881 case AsmToken::Integer:
882 case AsmToken::Minus:
883 case AsmToken::Plus:
884 return (getParser().ParseExpression(Res));
Jack Carterf740d6e2012-09-07 00:23:42 +0000885 case AsmToken::Percent:
Jack Carter6b96c3f2012-09-06 20:00:02 +0000886 return parseRelocOperand(Res);
Jack Carter6b96c3f2012-09-06 20:00:02 +0000887 case AsmToken::LParen:
Jack Carter30116cd2012-10-04 02:29:46 +0000888 return false; // it's probably assuming 0
Jack Carter6b96c3f2012-09-06 20:00:02 +0000889 }
890 return true;
891}
892
Jack Carterec65be82012-09-05 23:34:03 +0000893MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
894 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000895
896 const MCExpr *IdVal = 0;
897 SMLoc S;
Jack Carter30116cd2012-10-04 02:29:46 +0000898 // first operand is the offset
Jack Carter6b96c3f2012-09-06 20:00:02 +0000899 S = Parser.getTok().getLoc();
900
901 if (parseMemOffset(IdVal))
902 return MatchOperand_ParseFail;
903
Jack Carter30116cd2012-10-04 02:29:46 +0000904 const AsmToken &Tok = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000905 if (Tok.isNot(AsmToken::LParen)) {
Jack Carter2f68b312012-10-09 23:29:45 +0000906 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
907 if (Mnemonic->getToken() == "la") {
908 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
909 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
910 return MatchOperand_Success;
911 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000912 Error(Parser.getTok().getLoc(), "'(' expected");
913 return MatchOperand_ParseFail;
914 }
915
916 Parser.Lex(); // Eat '(' token.
917
Jack Carter2f68b312012-10-09 23:29:45 +0000918 const AsmToken &Tok1 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000919 if (Tok1.is(AsmToken::Dollar)) {
920 Parser.Lex(); // Eat '$' token.
921 if (tryParseRegisterOperand(Operands,"")) {
922 Error(Parser.getTok().getLoc(), "unexpected token in operand");
923 return MatchOperand_ParseFail;
924 }
925
926 } else {
Jack Carter30116cd2012-10-04 02:29:46 +0000927 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carter6b96c3f2012-09-06 20:00:02 +0000928 return MatchOperand_ParseFail;
929 }
930
Jack Carter30116cd2012-10-04 02:29:46 +0000931 const AsmToken &Tok2 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000932 if (Tok2.isNot(AsmToken::RParen)) {
933 Error(Parser.getTok().getLoc(), "')' expected");
934 return MatchOperand_ParseFail;
935 }
936
937 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
938
939 Parser.Lex(); // Eat ')' token.
940
941 if (IdVal == 0)
942 IdVal = MCConstantExpr::Create(0, getContext());
943
Jack Carter30116cd2012-10-04 02:29:46 +0000944 // now replace register operand with the mem operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000945 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
946 int RegNo = op->getReg();
Jack Carter30116cd2012-10-04 02:29:46 +0000947 // remove register from operands
Jack Carter6b96c3f2012-09-06 20:00:02 +0000948 Operands.pop_back();
Jack Carter30116cd2012-10-04 02:29:46 +0000949 // and add memory operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000950 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
951 delete op;
Jack Carterec65be82012-09-05 23:34:03 +0000952 return MatchOperand_Success;
953}
954
Jack Carter6b96c3f2012-09-06 20:00:02 +0000955MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
956
957 MCSymbolRefExpr::VariantKind VK
958 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
959 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
960 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
961 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
962 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
963 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
964 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
965 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
966 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
967 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
968 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
969 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
970 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
971 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
972 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
973 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
974 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
975 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
976 .Default(MCSymbolRefExpr::VK_None);
977
978 return VK;
979}
980
Benjamin Kramer1ac45872012-09-10 11:52:14 +0000981static int ConvertCcString(StringRef CondString) {
Jack Carterf740d6e2012-09-07 00:23:42 +0000982 int CC = StringSwitch<unsigned>(CondString)
983 .Case(".f", 0)
984 .Case(".un", 1)
985 .Case(".eq", 2)
986 .Case(".ueq", 3)
987 .Case(".olt", 4)
988 .Case(".ult", 5)
989 .Case(".ole", 6)
990 .Case(".ule", 7)
991 .Case(".sf", 8)
992 .Case(".ngle", 9)
993 .Case(".seq", 10)
994 .Case(".ngl", 11)
995 .Case(".lt", 12)
996 .Case(".nge", 13)
997 .Case(".le", 14)
998 .Case(".ngt", 15)
999 .Default(-1);
1000
1001 return CC;
1002}
1003
1004bool MipsAsmParser::
1005parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter30116cd2012-10-04 02:29:46 +00001006 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1007 // split the format
Jack Carterf740d6e2012-09-07 00:23:42 +00001008 size_t Start = Name.find('.'), Next = Name.rfind('.');
1009 StringRef Format1 = Name.slice(Start, Next);
Jack Carter30116cd2012-10-04 02:29:46 +00001010 // and add the first format to the operands
Jack Carterf740d6e2012-09-07 00:23:42 +00001011 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carter30116cd2012-10-04 02:29:46 +00001012 // now for the second format
Jack Carterf740d6e2012-09-07 00:23:42 +00001013 StringRef Format2 = Name.slice(Next, StringRef::npos);
1014 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1015
Jack Carter30116cd2012-10-04 02:29:46 +00001016 // set the format for the first register
Jack Carterf740d6e2012-09-07 00:23:42 +00001017 setFpFormat(Format1);
1018
1019 // Read the remaining operands.
1020 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1021 // Read the first operand.
1022 if (ParseOperand(Operands, Name)) {
1023 SMLoc Loc = getLexer().getLoc();
1024 Parser.EatToEndOfStatement();
1025 return Error(Loc, "unexpected token in argument list");
1026 }
1027
1028 if (getLexer().isNot(AsmToken::Comma)) {
1029 SMLoc Loc = getLexer().getLoc();
1030 Parser.EatToEndOfStatement();
1031 return Error(Loc, "unexpected token in argument list");
1032
1033 }
1034 Parser.Lex(); // Eat the comma.
1035
1036 //set the format for the first register
1037 setFpFormat(Format2);
1038
1039 // Parse and remember the operand.
1040 if (ParseOperand(Operands, Name)) {
1041 SMLoc Loc = getLexer().getLoc();
1042 Parser.EatToEndOfStatement();
1043 return Error(Loc, "unexpected token in argument list");
1044 }
1045 }
1046
1047 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1048 SMLoc Loc = getLexer().getLoc();
1049 Parser.EatToEndOfStatement();
1050 return Error(Loc, "unexpected token in argument list");
1051 }
1052
1053 Parser.Lex(); // Consume the EndOfStatement
1054 return false;
1055}
1056
Rafael Espindolafddf8042012-01-11 03:56:41 +00001057bool MipsAsmParser::
1058ParseInstruction(StringRef Name, SMLoc NameLoc,
1059 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter30116cd2012-10-04 02:29:46 +00001060 // floating point instructions: should register be treated as double?
Jack Carterf740d6e2012-09-07 00:23:42 +00001061 if (requestsDoubleOperand(Name)) {
1062 setFpFormat(FP_FORMAT_D);
Jack Carterec65be82012-09-05 23:34:03 +00001063 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterf740d6e2012-09-07 00:23:42 +00001064 }
1065 else {
1066 setDefaultFpFormat();
1067 // Create the leading tokens for the mnemonic, split by '.' characters.
1068 size_t Start = 0, Next = Name.find('.');
1069 StringRef Mnemonic = Name.slice(Start, Next);
1070
1071 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1072
1073 if (Next != StringRef::npos) {
Jack Carter30116cd2012-10-04 02:29:46 +00001074 // there is a format token in mnemonic
1075 // StringRef Rest = Name.slice(Next, StringRef::npos);
Jack Carterf740d6e2012-09-07 00:23:42 +00001076 size_t Dot = Name.find('.', Next+1);
1077 StringRef Format = Name.slice(Next, Dot);
1078 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1079 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1080 else {
1081 if (Name.startswith("c.")){
1082 // floating point compare, add '.' and immediate represent for cc
1083 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1084 int Cc = ConvertCcString(Format);
1085 if (Cc == -1) {
1086 return Error(NameLoc, "Invalid conditional code");
1087 }
1088 SMLoc E = SMLoc::getFromPointer(
1089 Parser.getTok().getLoc().getPointer() -1 );
1090 Operands.push_back(MipsOperand::CreateImm(
1091 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1092 } else {
Jack Carter30116cd2012-10-04 02:29:46 +00001093 // trunc, ceil, floor ...
Jack Carterf740d6e2012-09-07 00:23:42 +00001094 return parseMathOperation(Name, NameLoc, Operands);
1095 }
1096
Jack Carter30116cd2012-10-04 02:29:46 +00001097 // the rest is a format
Jack Carterf740d6e2012-09-07 00:23:42 +00001098 Format = Name.slice(Dot, StringRef::npos);
1099 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1100 }
1101
1102 setFpFormat(Format);
1103 }
1104 }
Jack Carterec65be82012-09-05 23:34:03 +00001105
1106 // Read the remaining operands.
1107 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1108 // Read the first operand.
1109 if (ParseOperand(Operands, Name)) {
1110 SMLoc Loc = getLexer().getLoc();
1111 Parser.EatToEndOfStatement();
1112 return Error(Loc, "unexpected token in argument list");
1113 }
1114
1115 while (getLexer().is(AsmToken::Comma) ) {
1116 Parser.Lex(); // Eat the comma.
1117
1118 // Parse and remember the operand.
1119 if (ParseOperand(Operands, Name)) {
1120 SMLoc Loc = getLexer().getLoc();
1121 Parser.EatToEndOfStatement();
1122 return Error(Loc, "unexpected token in argument list");
1123 }
1124 }
1125 }
1126
1127 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1128 SMLoc Loc = getLexer().getLoc();
1129 Parser.EatToEndOfStatement();
1130 return Error(Loc, "unexpected token in argument list");
1131 }
1132
1133 Parser.Lex(); // Consume the EndOfStatement
1134 return false;
Rafael Espindolafddf8042012-01-11 03:56:41 +00001135}
1136
Jack Carter30116cd2012-10-04 02:29:46 +00001137bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1138 SMLoc Loc = getLexer().getLoc();
1139 Parser.EatToEndOfStatement();
1140 return Error(Loc, ErrorMsg);
1141}
1142
1143bool MipsAsmParser::parseSetNoAtDirective() {
1144 // line should look like:
1145 // .set noat
1146 // set at reg to 0
Jack Carter10d5ff62012-10-05 23:55:28 +00001147 Options.setATReg(0);
Jack Carter30116cd2012-10-04 02:29:46 +00001148 // eat noat
1149 Parser.Lex();
1150 // if this is not the end of the statement, report error
1151 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1152 reportParseError("unexpected token in statement");
1153 return false;
1154 }
1155 Parser.Lex(); // Consume the EndOfStatement
1156 return false;
1157}
1158bool MipsAsmParser::parseSetAtDirective() {
1159 // line can be
1160 // .set at - defaults to $1
1161 // or .set at=$reg
1162 getParser().Lex();
1163 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter10d5ff62012-10-05 23:55:28 +00001164 Options.setATReg(1);
Jack Carter30116cd2012-10-04 02:29:46 +00001165 Parser.Lex(); // Consume the EndOfStatement
1166 return false;
1167 } else if (getLexer().is(AsmToken::Equal)) {
1168 getParser().Lex(); //eat '='
1169 if (getLexer().isNot(AsmToken::Dollar)) {
1170 reportParseError("unexpected token in statement");
1171 return false;
1172 }
1173 Parser.Lex(); // eat '$'
1174 if (getLexer().isNot(AsmToken::Integer)) {
1175 reportParseError("unexpected token in statement");
1176 return false;
1177 }
1178 const AsmToken &Reg = Parser.getTok();
Jack Carter10d5ff62012-10-05 23:55:28 +00001179 if (!Options.setATReg(Reg.getIntVal())) {
Jack Carter30116cd2012-10-04 02:29:46 +00001180 reportParseError("unexpected token in statement");
1181 return false;
1182 }
1183 getParser().Lex(); //eat reg
1184
1185 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1186 reportParseError("unexpected token in statement");
1187 return false;
1188 }
1189 Parser.Lex(); // Consume the EndOfStatement
1190 return false;
1191 } else {
1192 reportParseError("unexpected token in statement");
1193 return false;
1194 }
1195}
1196
1197bool MipsAsmParser::parseSetReorderDirective() {
1198 Parser.Lex();
1199 // if this is not the end of the statement, report error
1200 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1201 reportParseError("unexpected token in statement");
1202 return false;
1203 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001204 Options.setReorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001205 Parser.Lex(); // Consume the EndOfStatement
1206 return false;
1207}
1208
1209bool MipsAsmParser::parseSetNoReorderDirective() {
1210 Parser.Lex();
1211 // if this is not the end of the statement, report error
1212 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1213 reportParseError("unexpected token in statement");
1214 return false;
1215 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001216 Options.setNoreorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001217 Parser.Lex(); // Consume the EndOfStatement
1218 return false;
1219}
1220
1221bool MipsAsmParser::parseSetMacroDirective() {
1222 Parser.Lex();
1223 // if this is not the end of the statement, report error
1224 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1225 reportParseError("unexpected token in statement");
1226 return false;
1227 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001228 Options.setMacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001229 Parser.Lex(); // Consume the EndOfStatement
1230 return false;
1231}
1232
1233bool MipsAsmParser::parseSetNoMacroDirective() {
1234 Parser.Lex();
1235 // if this is not the end of the statement, report error
1236 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1237 reportParseError("`noreorder' must be set before `nomacro'");
1238 return false;
1239 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001240 if (Options.isReorder()) {
Jack Carter30116cd2012-10-04 02:29:46 +00001241 reportParseError("`noreorder' must be set before `nomacro'");
1242 return false;
1243 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001244 Options.setNomacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001245 Parser.Lex(); // Consume the EndOfStatement
1246 return false;
1247}
1248bool MipsAsmParser::parseDirectiveSet() {
1249
1250 // get next token
1251 const AsmToken &Tok = Parser.getTok();
1252
1253 if (Tok.getString() == "noat") {
1254 return parseSetNoAtDirective();
1255 } else if (Tok.getString() == "at") {
1256 return parseSetAtDirective();
1257 } else if (Tok.getString() == "reorder") {
1258 return parseSetReorderDirective();
1259 } else if (Tok.getString() == "noreorder") {
1260 return parseSetNoReorderDirective();
1261 } else if (Tok.getString() == "macro") {
1262 return parseSetMacroDirective();
1263 } else if (Tok.getString() == "nomacro") {
1264 return parseSetNoMacroDirective();
1265 } else if (Tok.getString() == "nomips16") {
1266 // ignore this directive for now
1267 Parser.EatToEndOfStatement();
1268 return false;
1269 } else if (Tok.getString() == "nomicromips") {
1270 // ignore this directive for now
1271 Parser.EatToEndOfStatement();
1272 return false;
1273 }
1274 return true;
1275}
1276
1277bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carteracbea452012-09-07 00:48:02 +00001278
1279 if (DirectiveID.getString() == ".ent") {
Jack Carter30116cd2012-10-04 02:29:46 +00001280 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001281 Parser.Lex();
1282 return false;
1283 }
1284
1285 if (DirectiveID.getString() == ".end") {
Jack Carter30116cd2012-10-04 02:29:46 +00001286 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001287 Parser.Lex();
1288 return false;
1289 }
1290
1291 if (DirectiveID.getString() == ".frame") {
Jack Carter30116cd2012-10-04 02:29:46 +00001292 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001293 Parser.EatToEndOfStatement();
1294 return false;
1295 }
1296
1297 if (DirectiveID.getString() == ".set") {
Jack Carter30116cd2012-10-04 02:29:46 +00001298 return parseDirectiveSet();
Jack Carteracbea452012-09-07 00:48:02 +00001299 }
1300
1301 if (DirectiveID.getString() == ".fmask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001302 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001303 Parser.EatToEndOfStatement();
1304 return false;
1305 }
1306
1307 if (DirectiveID.getString() == ".mask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001308 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001309 Parser.EatToEndOfStatement();
1310 return false;
1311 }
1312
1313 if (DirectiveID.getString() == ".gpword") {
Jack Carter30116cd2012-10-04 02:29:46 +00001314 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001315 Parser.EatToEndOfStatement();
1316 return false;
1317 }
1318
Rafael Espindolafddf8042012-01-11 03:56:41 +00001319 return true;
1320}
1321
Rafael Espindolafddf8042012-01-11 03:56:41 +00001322extern "C" void LLVMInitializeMipsAsmParser() {
1323 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1324 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1325 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1326 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1327}
Jack Carterec65be82012-09-05 23:34:03 +00001328
1329#define GET_REGISTER_MATCHER
1330#define GET_MATCHER_IMPLEMENTATION
1331#include "MipsGenAsmMatcher.inc"