blob: c2980ffeea8daf7d5feaee34bef8694bb76510b4 [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;
Jack Carterec65be82012-09-05 23:34:03 +0000459 unsigned Kind;
Chad Rosier22685872012-10-01 23:45:51 +0000460 unsigned ErrorInfo;
Chad Rosier9ba9d4d2012-10-05 18:41:14 +0000461 MatchInstMapAndConstraints MapAndConstraints;
Chad Rosier22685872012-10-01 23:45:51 +0000462 unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst,
463 MapAndConstraints, ErrorInfo,
464 /*matchingInlineAsm*/ false);
Jack Carterec65be82012-09-05 23:34:03 +0000465
466 switch (MatchResult) {
467 default: break;
468 case Match_Success: {
Jack Carter9d577c82012-10-04 04:03:53 +0000469 if (needsExpansion(Inst)) {
Jack Carter2490dc62012-10-06 00:53:28 +0000470 SmallVector<MCInst, 4> Instructions;
Jack Carter9d577c82012-10-04 04:03:53 +0000471 expandInstruction(Inst, IDLoc, Instructions);
472 for(unsigned i =0; i < Instructions.size(); i++){
Jack Carter2490dc62012-10-06 00:53:28 +0000473 Out.EmitInstruction(Instructions[i]);
Jack Carter9d577c82012-10-04 04:03:53 +0000474 }
475 } else {
476 Inst.setLoc(IDLoc);
477 Out.EmitInstruction(Inst);
478 }
Jack Carterec65be82012-09-05 23:34:03 +0000479 return false;
480 }
481 case Match_MissingFeature:
482 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
483 return true;
484 case Match_InvalidOperand: {
485 SMLoc ErrorLoc = IDLoc;
486 if (ErrorInfo != ~0U) {
487 if (ErrorInfo >= Operands.size())
488 return Error(IDLoc, "too few operands for instruction");
489
490 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
491 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
492 }
493
494 return Error(ErrorLoc, "invalid operand for instruction");
495 }
496 case Match_MnemonicFail:
497 return Error(IDLoc, "invalid instruction");
498 }
Rafael Espindolafddf8042012-01-11 03:56:41 +0000499 return true;
500}
501
Jack Carterec65be82012-09-05 23:34:03 +0000502int MipsAsmParser::matchRegisterName(StringRef Name) {
503
David Chisnall572e1bd2012-10-09 16:27:43 +0000504 int CC;
505 if (!isMips64())
506 CC = StringSwitch<unsigned>(Name)
507 .Case("zero", Mips::ZERO)
508 .Case("a0", Mips::A0)
509 .Case("a1", Mips::A1)
510 .Case("a2", Mips::A2)
511 .Case("a3", Mips::A3)
512 .Case("v0", Mips::V0)
513 .Case("v1", Mips::V1)
514 .Case("s0", Mips::S0)
515 .Case("s1", Mips::S1)
516 .Case("s2", Mips::S2)
517 .Case("s3", Mips::S3)
518 .Case("s4", Mips::S4)
519 .Case("s5", Mips::S5)
520 .Case("s6", Mips::S6)
521 .Case("s7", Mips::S7)
522 .Case("k0", Mips::K0)
523 .Case("k1", Mips::K1)
524 .Case("sp", Mips::SP)
525 .Case("fp", Mips::FP)
526 .Case("gp", Mips::GP)
527 .Case("ra", Mips::RA)
528 .Case("t0", Mips::T0)
529 .Case("t1", Mips::T1)
530 .Case("t2", Mips::T2)
531 .Case("t3", Mips::T3)
532 .Case("t4", Mips::T4)
533 .Case("t5", Mips::T5)
534 .Case("t6", Mips::T6)
535 .Case("t7", Mips::T7)
536 .Case("t8", Mips::T8)
537 .Case("t9", Mips::T9)
538 .Case("at", Mips::AT)
539 .Case("fcc0", Mips::FCC0)
540 .Default(-1);
541 else
542 CC = StringSwitch<unsigned>(Name)
543 .Case("zero", Mips::ZERO_64)
544 .Case("at", Mips::AT_64)
545 .Case("v0", Mips::V0_64)
546 .Case("v1", Mips::V1_64)
547 .Case("a0", Mips::A0_64)
548 .Case("a1", Mips::A1_64)
549 .Case("a2", Mips::A2_64)
550 .Case("a3", Mips::A3_64)
551 .Case("a4", Mips::T0_64)
552 .Case("a5", Mips::T1_64)
553 .Case("a6", Mips::T2_64)
554 .Case("a7", Mips::T3_64)
555 .Case("t4", Mips::T4_64)
556 .Case("t5", Mips::T5_64)
557 .Case("t6", Mips::T6_64)
558 .Case("t7", Mips::T7_64)
559 .Case("s0", Mips::S0_64)
560 .Case("s1", Mips::S1_64)
561 .Case("s2", Mips::S2_64)
562 .Case("s3", Mips::S3_64)
563 .Case("s4", Mips::S4_64)
564 .Case("s5", Mips::S5_64)
565 .Case("s6", Mips::S6_64)
566 .Case("s7", Mips::S7_64)
567 .Case("t8", Mips::T8_64)
568 .Case("t9", Mips::T9_64)
569 .Case("kt0", Mips::K0_64)
570 .Case("kt1", Mips::K1_64)
571 .Case("gp", Mips::GP_64)
572 .Case("sp", Mips::SP_64)
573 .Case("fp", Mips::FP_64)
574 .Case("s8", Mips::FP_64)
575 .Case("ra", Mips::RA_64)
576 .Default(-1);
Jack Carterec65be82012-09-05 23:34:03 +0000577
David Chisnall572e1bd2012-10-09 16:27:43 +0000578 if (CC != -1)
Jack Carterec65be82012-09-05 23:34:03 +0000579 return CC;
Jack Carterec65be82012-09-05 23:34:03 +0000580
Jack Carterf740d6e2012-09-07 00:23:42 +0000581 if (Name[0] == 'f') {
582 StringRef NumString = Name.substr(1);
583 unsigned IntVal;
584 if( NumString.getAsInteger(10, IntVal))
Jack Carter9d577c82012-10-04 04:03:53 +0000585 return -1; // not integer
Jack Carterf740d6e2012-09-07 00:23:42 +0000586 if (IntVal > 31)
587 return -1;
588
589 FpFormatTy Format = getFpFormat();
590
591 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
592 return getReg(Mips::FGR32RegClassID, IntVal);
593 if (Format == FP_FORMAT_D) {
594 if(isFP64()) {
595 return getReg(Mips::FGR64RegClassID, IntVal);
596 }
Jack Carter9d577c82012-10-04 04:03:53 +0000597 // only even numbers available as register pairs
Jack Carterf740d6e2012-09-07 00:23:42 +0000598 if (( IntVal > 31) || (IntVal%2 != 0))
599 return -1;
600 return getReg(Mips::AFGR64RegClassID, IntVal/2);
601 }
602 }
603
Jack Carterec65be82012-09-05 23:34:03 +0000604 return -1;
605}
Jack Carterf740d6e2012-09-07 00:23:42 +0000606void MipsAsmParser::setDefaultFpFormat() {
607
608 if (isMips64() || isFP64())
609 FpFormat = FP_FORMAT_D;
610 else
611 FpFormat = FP_FORMAT_S;
612}
613
614bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
615
616 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
617 .Case("ldxc1", true)
618 .Case("ldc1", true)
619 .Case("sdxc1", true)
620 .Case("sdc1", true)
621 .Default(false);
622
623 return IsDouble;
624}
625void MipsAsmParser::setFpFormat(StringRef Format) {
626
627 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
628 .Case(".s", FP_FORMAT_S)
629 .Case(".d", FP_FORMAT_D)
630 .Case(".l", FP_FORMAT_L)
631 .Case(".w", FP_FORMAT_W)
632 .Default(FP_FORMAT_NONE);
633}
Jack Carterec65be82012-09-05 23:34:03 +0000634
Jack Carter30116cd2012-10-04 02:29:46 +0000635bool MipsAssemblerOptions::setATReg(unsigned Reg) {
636 if (Reg > 31)
637 return false;
638
639 aTReg = Reg;
640 return true;
641}
642
643unsigned MipsAsmParser::getATReg() {
Jack Carter10d5ff62012-10-05 23:55:28 +0000644 unsigned Reg = Options.getATRegNum();
Jack Carter30116cd2012-10-04 02:29:46 +0000645 if (isMips64())
646 return getReg(Mips::CPU64RegsRegClassID,Reg);
Jack Carter10d5ff62012-10-05 23:55:28 +0000647
648 return getReg(Mips::CPURegsRegClassID,Reg);
Jack Carter30116cd2012-10-04 02:29:46 +0000649}
650
651unsigned MipsAsmParser::getReg(int RC,int RegNo) {
Jack Carterec65be82012-09-05 23:34:03 +0000652 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
653}
654
Jack Carter30116cd2012-10-04 02:29:46 +0000655int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
Jack Carterec65be82012-09-05 23:34:03 +0000656
657 if (Mnemonic.lower() == "rdhwr") {
Jack Carter9d577c82012-10-04 04:03:53 +0000658 // at the moment only hwreg29 is supported
Jack Carterec65be82012-09-05 23:34:03 +0000659 if (RegNum != 29)
660 return -1;
661 return Mips::HWR29;
662 }
663
664 if (RegNum > 31)
665 return -1;
666
David Chisnall572e1bd2012-10-09 16:27:43 +0000667 // MIPS64 registers are numbered 1 after the 32-bit equivalents
668 return getReg(Mips::CPURegsRegClassID, RegNum) + isMips64();
Jack Carterec65be82012-09-05 23:34:03 +0000669}
670
671int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
672 const AsmToken &Tok = Parser.getTok();
673 int RegNum = -1;
674
675 if (Tok.is(AsmToken::Identifier)) {
676 std::string lowerCase = Tok.getString().lower();
677 RegNum = matchRegisterName(lowerCase);
678 } else if (Tok.is(AsmToken::Integer))
Jack Carter9d577c82012-10-04 04:03:53 +0000679 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carter6b96c3f2012-09-06 20:00:02 +0000680 Mnemonic.lower());
Jack Carterf740d6e2012-09-07 00:23:42 +0000681 else
682 return RegNum; //error
Jack Carter9d577c82012-10-04 04:03:53 +0000683 // 64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
Jack Carterf740d6e2012-09-07 00:23:42 +0000684 if (isMips64() && RegNum == Mips::ZERO_64) {
685 if (Mnemonic.find("ddiv") != StringRef::npos)
686 RegNum = Mips::ZERO;
687 }
Jack Carterec65be82012-09-05 23:34:03 +0000688 return RegNum;
689}
690
Rafael Espindolafddf8042012-01-11 03:56:41 +0000691bool MipsAsmParser::
Jack Carterec65be82012-09-05 23:34:03 +0000692 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
693 StringRef Mnemonic){
694
695 SMLoc S = Parser.getTok().getLoc();
696 int RegNo = -1;
Jack Carterf740d6e2012-09-07 00:23:42 +0000697
Jack Carter9d577c82012-10-04 04:03:53 +0000698 // FIXME: we should make a more generic method for CCR
Jack Carterf740d6e2012-09-07 00:23:42 +0000699 if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
700 && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
Jack Carter9d577c82012-10-04 04:03:53 +0000701 RegNo = Parser.getTok().getIntVal(); // get the int value
702 // at the moment only fcc0 is supported
Jack Carterf740d6e2012-09-07 00:23:42 +0000703 if (RegNo == 0)
704 RegNo = Mips::FCC0;
705 } else
706 RegNo = tryParseRegister(Mnemonic);
Jack Carterec65be82012-09-05 23:34:03 +0000707 if (RegNo == -1)
708 return true;
709
710 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterf740d6e2012-09-07 00:23:42 +0000711 Parser.getTok().getLoc()));
Jack Carterec65be82012-09-05 23:34:03 +0000712 Parser.Lex(); // Eat register token.
713 return false;
714}
715
716bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
717 StringRef Mnemonic) {
Jack Carter9d577c82012-10-04 04:03:53 +0000718 // Check if the current operand has a custom associated parser, if so, try to
719 // custom parse the operand, or fallback to the general approach.
Jack Carterec65be82012-09-05 23:34:03 +0000720 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
721 if (ResTy == MatchOperand_Success)
722 return false;
723 // If there wasn't a custom match, try the generic matcher below. Otherwise,
724 // there was a match, but an error occurred, in which case, just return that
725 // the operand parsing failed.
726 if (ResTy == MatchOperand_ParseFail)
727 return true;
728
729 switch (getLexer().getKind()) {
730 default:
731 Error(Parser.getTok().getLoc(), "unexpected token in operand");
732 return true;
733 case AsmToken::Dollar: {
Jack Carter9d577c82012-10-04 04:03:53 +0000734 // parse register
Jack Carterec65be82012-09-05 23:34:03 +0000735 SMLoc S = Parser.getTok().getLoc();
736 Parser.Lex(); // Eat dollar token.
Jack Carter9d577c82012-10-04 04:03:53 +0000737 // parse register operand
738 if (!tryParseRegisterOperand(Operands, Mnemonic)) {
Jack Carterec65be82012-09-05 23:34:03 +0000739 if (getLexer().is(AsmToken::LParen)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000740 // check if it is indexed addressing operand
Jack Carterec65be82012-09-05 23:34:03 +0000741 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carter9d577c82012-10-04 04:03:53 +0000742 Parser.Lex(); // eat parenthesis
Jack Carterec65be82012-09-05 23:34:03 +0000743 if (getLexer().isNot(AsmToken::Dollar))
744 return true;
745
Jack Carter9d577c82012-10-04 04:03:53 +0000746 Parser.Lex(); // eat dollar
747 if (tryParseRegisterOperand(Operands, Mnemonic))
Jack Carterec65be82012-09-05 23:34:03 +0000748 return true;
749
750 if (!getLexer().is(AsmToken::RParen))
751 return true;
752
753 S = Parser.getTok().getLoc();
754 Operands.push_back(MipsOperand::CreateToken(")", S));
755 Parser.Lex();
756 }
757 return false;
758 }
Jack Carter9d577c82012-10-04 04:03:53 +0000759 // maybe it is a symbol reference
Jack Carterec65be82012-09-05 23:34:03 +0000760 StringRef Identifier;
761 if (Parser.ParseIdentifier(Identifier))
762 return true;
763
Jack Carter6b96c3f2012-09-06 20:00:02 +0000764 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000765
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000766 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterec65be82012-09-05 23:34:03 +0000767
768 // Otherwise create a symbol ref.
Jack Carter6b96c3f2012-09-06 20:00:02 +0000769 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterec65be82012-09-05 23:34:03 +0000770 getContext());
771
772 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
773 return false;
774 }
775 case AsmToken::Identifier:
776 case AsmToken::LParen:
777 case AsmToken::Minus:
778 case AsmToken::Plus:
779 case AsmToken::Integer:
780 case AsmToken::String: {
781 // quoted label names
782 const MCExpr *IdVal;
783 SMLoc S = Parser.getTok().getLoc();
784 if (getParser().ParseExpression(IdVal))
785 return true;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000786 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000787 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
788 return false;
789 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000790 case AsmToken::Percent: {
Jack Carter9d577c82012-10-04 04:03:53 +0000791 // it is a symbol reference or constant expression
Jack Carter6b96c3f2012-09-06 20:00:02 +0000792 const MCExpr *IdVal;
Jack Carter9d577c82012-10-04 04:03:53 +0000793 SMLoc S = Parser.getTok().getLoc(); // start location of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000794 if (parseRelocOperand(IdVal))
795 return true;
796
797 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
798
799 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
800 return false;
Jack Carter30116cd2012-10-04 02:29:46 +0000801 } // case AsmToken::Percent
802 } // switch(getLexer().getKind())
Rafael Espindolafddf8042012-01-11 03:56:41 +0000803 return true;
804}
805
Jack Carter6b96c3f2012-09-06 20:00:02 +0000806bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
807
Jack Carter30116cd2012-10-04 02:29:46 +0000808 Parser.Lex(); // eat % token
Jack Carter9d577c82012-10-04 04:03:53 +0000809 const AsmToken &Tok = Parser.getTok(); // get next token, operation
Jack Carter6b96c3f2012-09-06 20:00:02 +0000810 if (Tok.isNot(AsmToken::Identifier))
811 return true;
812
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000813 std::string Str = Tok.getIdentifier().str();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000814
Jack Carter9d577c82012-10-04 04:03:53 +0000815 Parser.Lex(); // eat identifier
Jack Carter30116cd2012-10-04 02:29:46 +0000816 // now make expression from the rest of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000817 const MCExpr *IdVal;
818 SMLoc EndLoc;
819
820 if (getLexer().getKind() == AsmToken::LParen) {
821 while (1) {
Jack Carter30116cd2012-10-04 02:29:46 +0000822 Parser.Lex(); // eat '(' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000823 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carter30116cd2012-10-04 02:29:46 +0000824 Parser.Lex(); // eat % token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000825 const AsmToken &nextTok = Parser.getTok();
826 if (nextTok.isNot(AsmToken::Identifier))
827 return true;
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000828 Str += "(%";
829 Str += nextTok.getIdentifier();
Jack Carter30116cd2012-10-04 02:29:46 +0000830 Parser.Lex(); // eat identifier
Jack Carter6b96c3f2012-09-06 20:00:02 +0000831 if (getLexer().getKind() != AsmToken::LParen)
832 return true;
833 } else
834 break;
835 }
836 if (getParser().ParseParenExpression(IdVal,EndLoc))
837 return true;
838
839 while (getLexer().getKind() == AsmToken::RParen)
Jack Carter30116cd2012-10-04 02:29:46 +0000840 Parser.Lex(); // eat ')' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000841
842 } else
Jack Carter30116cd2012-10-04 02:29:46 +0000843 return true; // parenthesis must follow reloc operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000844
Jack Carter30116cd2012-10-04 02:29:46 +0000845 // Check the type of the expression
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000846 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000847 // it's a constant, evaluate lo or hi value
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000848 int Val = MCE->getValue();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000849 if (Str == "lo") {
850 Val = Val & 0xffff;
851 } else if (Str == "hi") {
852 Val = (Val & 0xffff0000) >> 16;
853 }
854 Res = MCConstantExpr::Create(Val, getContext());
855 return false;
856 }
857
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000858 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter30116cd2012-10-04 02:29:46 +0000859 // it's a symbol, create symbolic expression from symbol
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000860 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000861 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
862 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
863 return false;
864 }
865 return true;
866}
867
Jack Carterec65be82012-09-05 23:34:03 +0000868bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
869 SMLoc &EndLoc) {
870
871 StartLoc = Parser.getTok().getLoc();
872 RegNo = tryParseRegister("");
873 EndLoc = Parser.getTok().getLoc();
874 return (RegNo == (unsigned)-1);
875}
876
Jack Carter6b96c3f2012-09-06 20:00:02 +0000877bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
878
879 SMLoc S;
880
881 switch(getLexer().getKind()) {
882 default:
883 return true;
884 case AsmToken::Integer:
885 case AsmToken::Minus:
886 case AsmToken::Plus:
887 return (getParser().ParseExpression(Res));
Jack Carterf740d6e2012-09-07 00:23:42 +0000888 case AsmToken::Percent:
Jack Carter6b96c3f2012-09-06 20:00:02 +0000889 return parseRelocOperand(Res);
Jack Carter6b96c3f2012-09-06 20:00:02 +0000890 case AsmToken::LParen:
Jack Carter30116cd2012-10-04 02:29:46 +0000891 return false; // it's probably assuming 0
Jack Carter6b96c3f2012-09-06 20:00:02 +0000892 }
893 return true;
894}
895
Jack Carterec65be82012-09-05 23:34:03 +0000896MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
897 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000898
899 const MCExpr *IdVal = 0;
900 SMLoc S;
Jack Carter30116cd2012-10-04 02:29:46 +0000901 // first operand is the offset
Jack Carter6b96c3f2012-09-06 20:00:02 +0000902 S = Parser.getTok().getLoc();
903
904 if (parseMemOffset(IdVal))
905 return MatchOperand_ParseFail;
906
Jack Carter30116cd2012-10-04 02:29:46 +0000907 const AsmToken &Tok = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000908 if (Tok.isNot(AsmToken::LParen)) {
Jack Carter2f68b312012-10-09 23:29:45 +0000909 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
910 if (Mnemonic->getToken() == "la") {
911 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
912 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
913 return MatchOperand_Success;
914 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000915 Error(Parser.getTok().getLoc(), "'(' expected");
916 return MatchOperand_ParseFail;
917 }
918
919 Parser.Lex(); // Eat '(' token.
920
Jack Carter2f68b312012-10-09 23:29:45 +0000921 const AsmToken &Tok1 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000922 if (Tok1.is(AsmToken::Dollar)) {
923 Parser.Lex(); // Eat '$' token.
924 if (tryParseRegisterOperand(Operands,"")) {
925 Error(Parser.getTok().getLoc(), "unexpected token in operand");
926 return MatchOperand_ParseFail;
927 }
928
929 } else {
Jack Carter30116cd2012-10-04 02:29:46 +0000930 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carter6b96c3f2012-09-06 20:00:02 +0000931 return MatchOperand_ParseFail;
932 }
933
Jack Carter30116cd2012-10-04 02:29:46 +0000934 const AsmToken &Tok2 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000935 if (Tok2.isNot(AsmToken::RParen)) {
936 Error(Parser.getTok().getLoc(), "')' expected");
937 return MatchOperand_ParseFail;
938 }
939
940 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
941
942 Parser.Lex(); // Eat ')' token.
943
944 if (IdVal == 0)
945 IdVal = MCConstantExpr::Create(0, getContext());
946
Jack Carter30116cd2012-10-04 02:29:46 +0000947 // now replace register operand with the mem operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000948 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
949 int RegNo = op->getReg();
Jack Carter30116cd2012-10-04 02:29:46 +0000950 // remove register from operands
Jack Carter6b96c3f2012-09-06 20:00:02 +0000951 Operands.pop_back();
Jack Carter30116cd2012-10-04 02:29:46 +0000952 // and add memory operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000953 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
954 delete op;
Jack Carterec65be82012-09-05 23:34:03 +0000955 return MatchOperand_Success;
956}
957
Jack Carter6b96c3f2012-09-06 20:00:02 +0000958MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
959
960 MCSymbolRefExpr::VariantKind VK
961 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
962 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
963 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
964 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
965 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
966 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
967 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
968 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
969 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
970 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
971 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
972 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
973 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
974 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
975 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
976 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
977 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
978 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
979 .Default(MCSymbolRefExpr::VK_None);
980
981 return VK;
982}
983
Benjamin Kramer1ac45872012-09-10 11:52:14 +0000984static int ConvertCcString(StringRef CondString) {
Jack Carterf740d6e2012-09-07 00:23:42 +0000985 int CC = StringSwitch<unsigned>(CondString)
986 .Case(".f", 0)
987 .Case(".un", 1)
988 .Case(".eq", 2)
989 .Case(".ueq", 3)
990 .Case(".olt", 4)
991 .Case(".ult", 5)
992 .Case(".ole", 6)
993 .Case(".ule", 7)
994 .Case(".sf", 8)
995 .Case(".ngle", 9)
996 .Case(".seq", 10)
997 .Case(".ngl", 11)
998 .Case(".lt", 12)
999 .Case(".nge", 13)
1000 .Case(".le", 14)
1001 .Case(".ngt", 15)
1002 .Default(-1);
1003
1004 return CC;
1005}
1006
1007bool MipsAsmParser::
1008parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter30116cd2012-10-04 02:29:46 +00001009 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1010 // split the format
Jack Carterf740d6e2012-09-07 00:23:42 +00001011 size_t Start = Name.find('.'), Next = Name.rfind('.');
1012 StringRef Format1 = Name.slice(Start, Next);
Jack Carter30116cd2012-10-04 02:29:46 +00001013 // and add the first format to the operands
Jack Carterf740d6e2012-09-07 00:23:42 +00001014 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carter30116cd2012-10-04 02:29:46 +00001015 // now for the second format
Jack Carterf740d6e2012-09-07 00:23:42 +00001016 StringRef Format2 = Name.slice(Next, StringRef::npos);
1017 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1018
Jack Carter30116cd2012-10-04 02:29:46 +00001019 // set the format for the first register
Jack Carterf740d6e2012-09-07 00:23:42 +00001020 setFpFormat(Format1);
1021
1022 // Read the remaining operands.
1023 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1024 // Read the first operand.
1025 if (ParseOperand(Operands, Name)) {
1026 SMLoc Loc = getLexer().getLoc();
1027 Parser.EatToEndOfStatement();
1028 return Error(Loc, "unexpected token in argument list");
1029 }
1030
1031 if (getLexer().isNot(AsmToken::Comma)) {
1032 SMLoc Loc = getLexer().getLoc();
1033 Parser.EatToEndOfStatement();
1034 return Error(Loc, "unexpected token in argument list");
1035
1036 }
1037 Parser.Lex(); // Eat the comma.
1038
1039 //set the format for the first register
1040 setFpFormat(Format2);
1041
1042 // Parse and remember the operand.
1043 if (ParseOperand(Operands, Name)) {
1044 SMLoc Loc = getLexer().getLoc();
1045 Parser.EatToEndOfStatement();
1046 return Error(Loc, "unexpected token in argument list");
1047 }
1048 }
1049
1050 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1051 SMLoc Loc = getLexer().getLoc();
1052 Parser.EatToEndOfStatement();
1053 return Error(Loc, "unexpected token in argument list");
1054 }
1055
1056 Parser.Lex(); // Consume the EndOfStatement
1057 return false;
1058}
1059
Rafael Espindolafddf8042012-01-11 03:56:41 +00001060bool MipsAsmParser::
1061ParseInstruction(StringRef Name, SMLoc NameLoc,
1062 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter30116cd2012-10-04 02:29:46 +00001063 // floating point instructions: should register be treated as double?
Jack Carterf740d6e2012-09-07 00:23:42 +00001064 if (requestsDoubleOperand(Name)) {
1065 setFpFormat(FP_FORMAT_D);
Jack Carterec65be82012-09-05 23:34:03 +00001066 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterf740d6e2012-09-07 00:23:42 +00001067 }
1068 else {
1069 setDefaultFpFormat();
1070 // Create the leading tokens for the mnemonic, split by '.' characters.
1071 size_t Start = 0, Next = Name.find('.');
1072 StringRef Mnemonic = Name.slice(Start, Next);
1073
1074 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1075
1076 if (Next != StringRef::npos) {
Jack Carter30116cd2012-10-04 02:29:46 +00001077 // there is a format token in mnemonic
1078 // StringRef Rest = Name.slice(Next, StringRef::npos);
Jack Carterf740d6e2012-09-07 00:23:42 +00001079 size_t Dot = Name.find('.', Next+1);
1080 StringRef Format = Name.slice(Next, Dot);
1081 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1082 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1083 else {
1084 if (Name.startswith("c.")){
1085 // floating point compare, add '.' and immediate represent for cc
1086 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1087 int Cc = ConvertCcString(Format);
1088 if (Cc == -1) {
1089 return Error(NameLoc, "Invalid conditional code");
1090 }
1091 SMLoc E = SMLoc::getFromPointer(
1092 Parser.getTok().getLoc().getPointer() -1 );
1093 Operands.push_back(MipsOperand::CreateImm(
1094 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1095 } else {
Jack Carter30116cd2012-10-04 02:29:46 +00001096 // trunc, ceil, floor ...
Jack Carterf740d6e2012-09-07 00:23:42 +00001097 return parseMathOperation(Name, NameLoc, Operands);
1098 }
1099
Jack Carter30116cd2012-10-04 02:29:46 +00001100 // the rest is a format
Jack Carterf740d6e2012-09-07 00:23:42 +00001101 Format = Name.slice(Dot, StringRef::npos);
1102 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1103 }
1104
1105 setFpFormat(Format);
1106 }
1107 }
Jack Carterec65be82012-09-05 23:34:03 +00001108
1109 // Read the remaining operands.
1110 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1111 // Read the first operand.
1112 if (ParseOperand(Operands, Name)) {
1113 SMLoc Loc = getLexer().getLoc();
1114 Parser.EatToEndOfStatement();
1115 return Error(Loc, "unexpected token in argument list");
1116 }
1117
1118 while (getLexer().is(AsmToken::Comma) ) {
1119 Parser.Lex(); // Eat the comma.
1120
1121 // Parse and remember the operand.
1122 if (ParseOperand(Operands, Name)) {
1123 SMLoc Loc = getLexer().getLoc();
1124 Parser.EatToEndOfStatement();
1125 return Error(Loc, "unexpected token in argument list");
1126 }
1127 }
1128 }
1129
1130 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1131 SMLoc Loc = getLexer().getLoc();
1132 Parser.EatToEndOfStatement();
1133 return Error(Loc, "unexpected token in argument list");
1134 }
1135
1136 Parser.Lex(); // Consume the EndOfStatement
1137 return false;
Rafael Espindolafddf8042012-01-11 03:56:41 +00001138}
1139
Jack Carter30116cd2012-10-04 02:29:46 +00001140bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1141 SMLoc Loc = getLexer().getLoc();
1142 Parser.EatToEndOfStatement();
1143 return Error(Loc, ErrorMsg);
1144}
1145
1146bool MipsAsmParser::parseSetNoAtDirective() {
1147 // line should look like:
1148 // .set noat
1149 // set at reg to 0
Jack Carter10d5ff62012-10-05 23:55:28 +00001150 Options.setATReg(0);
Jack Carter30116cd2012-10-04 02:29:46 +00001151 // eat noat
1152 Parser.Lex();
1153 // if this is not the end of the statement, report error
1154 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1155 reportParseError("unexpected token in statement");
1156 return false;
1157 }
1158 Parser.Lex(); // Consume the EndOfStatement
1159 return false;
1160}
1161bool MipsAsmParser::parseSetAtDirective() {
1162 // line can be
1163 // .set at - defaults to $1
1164 // or .set at=$reg
1165 getParser().Lex();
1166 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter10d5ff62012-10-05 23:55:28 +00001167 Options.setATReg(1);
Jack Carter30116cd2012-10-04 02:29:46 +00001168 Parser.Lex(); // Consume the EndOfStatement
1169 return false;
1170 } else if (getLexer().is(AsmToken::Equal)) {
1171 getParser().Lex(); //eat '='
1172 if (getLexer().isNot(AsmToken::Dollar)) {
1173 reportParseError("unexpected token in statement");
1174 return false;
1175 }
1176 Parser.Lex(); // eat '$'
1177 if (getLexer().isNot(AsmToken::Integer)) {
1178 reportParseError("unexpected token in statement");
1179 return false;
1180 }
1181 const AsmToken &Reg = Parser.getTok();
Jack Carter10d5ff62012-10-05 23:55:28 +00001182 if (!Options.setATReg(Reg.getIntVal())) {
Jack Carter30116cd2012-10-04 02:29:46 +00001183 reportParseError("unexpected token in statement");
1184 return false;
1185 }
1186 getParser().Lex(); //eat reg
1187
1188 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1189 reportParseError("unexpected token in statement");
1190 return false;
1191 }
1192 Parser.Lex(); // Consume the EndOfStatement
1193 return false;
1194 } else {
1195 reportParseError("unexpected token in statement");
1196 return false;
1197 }
1198}
1199
1200bool MipsAsmParser::parseSetReorderDirective() {
1201 Parser.Lex();
1202 // if this is not the end of the statement, report error
1203 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1204 reportParseError("unexpected token in statement");
1205 return false;
1206 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001207 Options.setReorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001208 Parser.Lex(); // Consume the EndOfStatement
1209 return false;
1210}
1211
1212bool MipsAsmParser::parseSetNoReorderDirective() {
1213 Parser.Lex();
1214 // if this is not the end of the statement, report error
1215 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1216 reportParseError("unexpected token in statement");
1217 return false;
1218 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001219 Options.setNoreorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001220 Parser.Lex(); // Consume the EndOfStatement
1221 return false;
1222}
1223
1224bool MipsAsmParser::parseSetMacroDirective() {
1225 Parser.Lex();
1226 // if this is not the end of the statement, report error
1227 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1228 reportParseError("unexpected token in statement");
1229 return false;
1230 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001231 Options.setMacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001232 Parser.Lex(); // Consume the EndOfStatement
1233 return false;
1234}
1235
1236bool MipsAsmParser::parseSetNoMacroDirective() {
1237 Parser.Lex();
1238 // if this is not the end of the statement, report error
1239 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1240 reportParseError("`noreorder' must be set before `nomacro'");
1241 return false;
1242 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001243 if (Options.isReorder()) {
Jack Carter30116cd2012-10-04 02:29:46 +00001244 reportParseError("`noreorder' must be set before `nomacro'");
1245 return false;
1246 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001247 Options.setNomacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001248 Parser.Lex(); // Consume the EndOfStatement
1249 return false;
1250}
1251bool MipsAsmParser::parseDirectiveSet() {
1252
1253 // get next token
1254 const AsmToken &Tok = Parser.getTok();
1255
1256 if (Tok.getString() == "noat") {
1257 return parseSetNoAtDirective();
1258 } else if (Tok.getString() == "at") {
1259 return parseSetAtDirective();
1260 } else if (Tok.getString() == "reorder") {
1261 return parseSetReorderDirective();
1262 } else if (Tok.getString() == "noreorder") {
1263 return parseSetNoReorderDirective();
1264 } else if (Tok.getString() == "macro") {
1265 return parseSetMacroDirective();
1266 } else if (Tok.getString() == "nomacro") {
1267 return parseSetNoMacroDirective();
1268 } else if (Tok.getString() == "nomips16") {
1269 // ignore this directive for now
1270 Parser.EatToEndOfStatement();
1271 return false;
1272 } else if (Tok.getString() == "nomicromips") {
1273 // ignore this directive for now
1274 Parser.EatToEndOfStatement();
1275 return false;
1276 }
1277 return true;
1278}
1279
1280bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carteracbea452012-09-07 00:48:02 +00001281
1282 if (DirectiveID.getString() == ".ent") {
Jack Carter30116cd2012-10-04 02:29:46 +00001283 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001284 Parser.Lex();
1285 return false;
1286 }
1287
1288 if (DirectiveID.getString() == ".end") {
Jack Carter30116cd2012-10-04 02:29:46 +00001289 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001290 Parser.Lex();
1291 return false;
1292 }
1293
1294 if (DirectiveID.getString() == ".frame") {
Jack Carter30116cd2012-10-04 02:29:46 +00001295 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001296 Parser.EatToEndOfStatement();
1297 return false;
1298 }
1299
1300 if (DirectiveID.getString() == ".set") {
Jack Carter30116cd2012-10-04 02:29:46 +00001301 return parseDirectiveSet();
Jack Carteracbea452012-09-07 00:48:02 +00001302 }
1303
1304 if (DirectiveID.getString() == ".fmask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001305 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001306 Parser.EatToEndOfStatement();
1307 return false;
1308 }
1309
1310 if (DirectiveID.getString() == ".mask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001311 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001312 Parser.EatToEndOfStatement();
1313 return false;
1314 }
1315
1316 if (DirectiveID.getString() == ".gpword") {
Jack Carter30116cd2012-10-04 02:29:46 +00001317 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001318 Parser.EatToEndOfStatement();
1319 return false;
1320 }
1321
Rafael Espindolafddf8042012-01-11 03:56:41 +00001322 return true;
1323}
1324
Rafael Espindolafddf8042012-01-11 03:56:41 +00001325extern "C" void LLVMInitializeMipsAsmParser() {
1326 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1327 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1328 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1329 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1330}
Jack Carterec65be82012-09-05 23:34:03 +00001331
1332#define GET_REGISTER_MATCHER
1333#define GET_MATCHER_IMPLEMENTATION
1334#include "MipsGenAsmMatcher.inc"