blob: 67b524883cf82ef0d26f50b2d7dc93da40856b66 [file] [log] [blame]
Jia Liuc5707112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindolafddf8042012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterec65be82012-09-05 23:34:03 +000011#include "MipsRegisterInfo.h"
12#include "llvm/ADT/StringSwitch.h"
13#include "llvm/MC/MCContext.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCInst.h"
16#include "llvm/MC/MCStreamer.h"
17#include "llvm/MC/MCSubtargetInfo.h"
18#include "llvm/MC/MCSymbol.h"
Rafael Espindolafddf8042012-01-11 03:56:41 +000019#include "llvm/MC/MCParser/MCAsmLexer.h"
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000020#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21#include "llvm/MC/MCTargetAsmParser.h"
Jack Carterec65be82012-09-05 23:34:03 +000022#include "llvm/Support/TargetRegistry.h"
Rafael Espindolafddf8042012-01-11 03:56:41 +000023
24using namespace llvm;
25
26namespace {
Jack Carter30116cd2012-10-04 02:29:46 +000027class MipsAssemblerOptions {
28public:
29 MipsAssemblerOptions():
30 aTReg(1), reorder(true), macro(true) {
31 }
Jack Carterec65be82012-09-05 23:34:03 +000032
Jack Carter30116cd2012-10-04 02:29:46 +000033 unsigned getATRegNum() {return aTReg;}
34 bool setATReg(unsigned Reg);
35
36 bool isReorder() {return reorder;}
37 void setReorder() {reorder = true;}
38 void setNoreorder() {reorder = false;}
39
40 bool isMacro() {return macro;}
41 void setMacro() {macro = true;}
42 void setNomacro() {macro = false;}
43
44private:
45 unsigned aTReg;
46 bool reorder;
47 bool macro;
48};
49}
50
51namespace {
Rafael Espindolafddf8042012-01-11 03:56:41 +000052class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000053
Jack Carterf740d6e2012-09-07 00:23:42 +000054 enum FpFormatTy {
55 FP_FORMAT_NONE = -1,
56 FP_FORMAT_S,
57 FP_FORMAT_D,
58 FP_FORMAT_L,
59 FP_FORMAT_W
60 } FpFormat;
61
Jack Carterec65be82012-09-05 23:34:03 +000062 MCSubtargetInfo &STI;
63 MCAsmParser &Parser;
Jack Carter10d5ff62012-10-05 23:55:28 +000064 MipsAssemblerOptions Options;
Jack Carter30116cd2012-10-04 02:29:46 +000065
Jack Carterec65be82012-09-05 23:34:03 +000066
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000067#define GET_ASSEMBLER_HEADER
68#include "MipsGenAsmMatcher.inc"
69
Chad Rosier84125ca2012-10-13 00:26:04 +000070 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindolafddf8042012-01-11 03:56:41 +000071 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier84125ca2012-10-13 00:26:04 +000072 MCStreamer &Out, unsigned &ErrorInfo,
73 bool MatchingInlineAsm);
Rafael Espindolafddf8042012-01-11 03:56:41 +000074
75 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
76
Chad Rosier6a020a72012-10-25 20:41:34 +000077 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
78 SMLoc NameLoc,
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000079 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindolafddf8042012-01-11 03:56:41 +000080
Jack Carterf740d6e2012-09-07 00:23:42 +000081 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
82 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
83
Rafael Espindolafddf8042012-01-11 03:56:41 +000084 bool ParseDirective(AsmToken DirectiveID);
85
Jack Carterec65be82012-09-05 23:34:03 +000086 MipsAsmParser::OperandMatchResultTy
87 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
Chad Rosier038f3e32012-09-03 18:47:45 +000088
Jack Carterec65be82012-09-05 23:34:03 +000089 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
90 StringRef Mnemonic);
91
92 int tryParseRegister(StringRef Mnemonic);
93
94 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
95 StringRef Mnemonic);
96
Jack Carter9d577c82012-10-04 04:03:53 +000097 bool needsExpansion(MCInst &Inst);
98
99 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000100 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9d577c82012-10-04 04:03:53 +0000101 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000102 SmallVectorImpl<MCInst> &Instructions);
Jack Carter2f68b312012-10-09 23:29:45 +0000103 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
104 SmallVectorImpl<MCInst> &Instructions);
105 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
106 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30116cd2012-10-04 02:29:46 +0000107 bool reportParseError(StringRef ErrorMsg);
108
Jack Carter6b96c3f2012-09-06 20:00:02 +0000109 bool parseMemOffset(const MCExpr *&Res);
110 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter30116cd2012-10-04 02:29:46 +0000111
112 bool parseDirectiveSet();
113
114 bool parseSetAtDirective();
115 bool parseSetNoAtDirective();
116 bool parseSetMacroDirective();
117 bool parseSetNoMacroDirective();
118 bool parseSetReorderDirective();
119 bool parseSetNoReorderDirective();
120
Jack Carter6b96c3f2012-09-06 20:00:02 +0000121 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Carterf740d6e2012-09-07 00:23:42 +0000122
Jack Carterec65be82012-09-05 23:34:03 +0000123 bool isMips64() const {
124 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
125 }
126
Jack Carterf740d6e2012-09-07 00:23:42 +0000127 bool isFP64() const {
128 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
129 }
130
Jack Carterec65be82012-09-05 23:34:03 +0000131 int matchRegisterName(StringRef Symbol);
132
133 int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
134
Jack Carterf740d6e2012-09-07 00:23:42 +0000135 void setFpFormat(FpFormatTy Format) {
136 FpFormat = Format;
137 }
138
139 void setDefaultFpFormat();
140
141 void setFpFormat(StringRef Format);
142
143 FpFormatTy getFpFormat() {return FpFormat;}
144
145 bool requestsDoubleOperand(StringRef Mnemonic);
146
Jack Carterec65be82012-09-05 23:34:03 +0000147 unsigned getReg(int RC,int RegNo);
Chad Rosier038f3e32012-09-03 18:47:45 +0000148
Jack Carter30116cd2012-10-04 02:29:46 +0000149 unsigned getATReg();
Rafael Espindolafddf8042012-01-11 03:56:41 +0000150public:
151 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterec65be82012-09-05 23:34:03 +0000152 : MCTargetAsmParser(), STI(sti), Parser(parser) {
153 // Initialize the set of available features.
154 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindolafddf8042012-01-11 03:56:41 +0000155 }
156
Jack Carterec65be82012-09-05 23:34:03 +0000157 MCAsmParser &getParser() const { return Parser; }
158 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
159
Rafael Espindolafddf8042012-01-11 03:56:41 +0000160};
161}
162
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000163namespace {
164
165/// MipsOperand - Instances of this class represent a parsed Mips machine
166/// instruction.
167class MipsOperand : public MCParsedAsmOperand {
Jack Carterec65be82012-09-05 23:34:03 +0000168
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000169 enum KindTy {
170 k_CondCode,
171 k_CoprocNum,
172 k_Immediate,
173 k_Memory,
174 k_PostIndexRegister,
175 k_Register,
176 k_Token
177 } Kind;
178
179 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterec65be82012-09-05 23:34:03 +0000180
181 union {
182 struct {
183 const char *Data;
184 unsigned Length;
185 } Tok;
186
187 struct {
188 unsigned RegNum;
189 } Reg;
190
191 struct {
192 const MCExpr *Val;
193 } Imm;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000194
195 struct {
196 unsigned Base;
197 const MCExpr *Off;
198 } Mem;
Jack Carterec65be82012-09-05 23:34:03 +0000199 };
200
201 SMLoc StartLoc, EndLoc;
202
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000203public:
204 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000205 assert(N == 1 && "Invalid number of operands!");
206 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000207 }
Jack Carterec65be82012-09-05 23:34:03 +0000208
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000209 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterec65be82012-09-05 23:34:03 +0000210 // Add as immediate when possible. Null MCExpr = 0.
211 if (Expr == 0)
212 Inst.addOperand(MCOperand::CreateImm(0));
213 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
214 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
215 else
216 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000217 }
Jack Carterec65be82012-09-05 23:34:03 +0000218
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000219 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000220 assert(N == 1 && "Invalid number of operands!");
221 const MCExpr *Expr = getImm();
222 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000223 }
Jack Carterec65be82012-09-05 23:34:03 +0000224
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000225 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000226 assert(N == 2 && "Invalid number of operands!");
227
228 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
229
230 const MCExpr *Expr = getMemOff();
231 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000232 }
233
234 bool isReg() const { return Kind == k_Register; }
235 bool isImm() const { return Kind == k_Immediate; }
236 bool isToken() const { return Kind == k_Token; }
237 bool isMem() const { return Kind == k_Memory; }
238
239 StringRef getToken() const {
240 assert(Kind == k_Token && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000241 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000242 }
243
244 unsigned getReg() const {
245 assert((Kind == k_Register) && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000246 return Reg.RegNum;
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000247 }
248
Jack Carterec65be82012-09-05 23:34:03 +0000249 const MCExpr *getImm() const {
250 assert((Kind == k_Immediate) && "Invalid access!");
251 return Imm.Val;
252 }
253
Jack Carter6b96c3f2012-09-06 20:00:02 +0000254 unsigned getMemBase() const {
255 assert((Kind == k_Memory) && "Invalid access!");
256 return Mem.Base;
257 }
258
259 const MCExpr *getMemOff() const {
260 assert((Kind == k_Memory) && "Invalid access!");
261 return Mem.Off;
262 }
263
Jack Carterec65be82012-09-05 23:34:03 +0000264 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
265 MipsOperand *Op = new MipsOperand(k_Token);
266 Op->Tok.Data = Str.data();
267 Op->Tok.Length = Str.size();
268 Op->StartLoc = S;
269 Op->EndLoc = S;
270 return Op;
271 }
272
273 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
274 MipsOperand *Op = new MipsOperand(k_Register);
275 Op->Reg.RegNum = RegNum;
276 Op->StartLoc = S;
277 Op->EndLoc = E;
278 return Op;
279 }
280
281 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
282 MipsOperand *Op = new MipsOperand(k_Immediate);
283 Op->Imm.Val = Val;
284 Op->StartLoc = S;
285 Op->EndLoc = E;
286 return Op;
287 }
288
Jack Carter6b96c3f2012-09-06 20:00:02 +0000289 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
290 SMLoc S, SMLoc E) {
291 MipsOperand *Op = new MipsOperand(k_Memory);
292 Op->Mem.Base = Base;
293 Op->Mem.Off = Off;
294 Op->StartLoc = S;
295 Op->EndLoc = E;
296 return Op;
297 }
298
Jack Carterec65be82012-09-05 23:34:03 +0000299 /// getStartLoc - Get the location of the first token of this operand.
300 SMLoc getStartLoc() const { return StartLoc; }
301 /// getEndLoc - Get the location of the last token of this operand.
302 SMLoc getEndLoc() const { return EndLoc; }
303
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000304 virtual void print(raw_ostream &OS) const {
305 llvm_unreachable("unimplemented!");
306 }
307};
308}
309
Jack Carter9d577c82012-10-04 04:03:53 +0000310bool MipsAsmParser::needsExpansion(MCInst &Inst) {
311
312 switch(Inst.getOpcode()) {
313 case Mips::LoadImm32Reg:
Jack Carter2f68b312012-10-09 23:29:45 +0000314 case Mips::LoadAddr32Imm:
315 case Mips::LoadAddr32Reg:
Jack Carter9d577c82012-10-04 04:03:53 +0000316 return true;
317 default:
318 return false;
319 }
320}
Jack Carter2490dc62012-10-06 00:53:28 +0000321
Jack Carter9d577c82012-10-04 04:03:53 +0000322void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter2490dc62012-10-06 00:53:28 +0000323 SmallVectorImpl<MCInst> &Instructions){
Jack Carter9d577c82012-10-04 04:03:53 +0000324 switch(Inst.getOpcode()) {
325 case Mips::LoadImm32Reg:
326 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carter2f68b312012-10-09 23:29:45 +0000327 case Mips::LoadAddr32Imm:
328 return expandLoadAddressImm(Inst,IDLoc,Instructions);
329 case Mips::LoadAddr32Reg:
330 return expandLoadAddressReg(Inst,IDLoc,Instructions);
Jack Carter9d577c82012-10-04 04:03:53 +0000331 }
Jack Carter9d577c82012-10-04 04:03:53 +0000332}
Jack Carter2490dc62012-10-06 00:53:28 +0000333
Jack Carter9d577c82012-10-04 04:03:53 +0000334void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter2f68b312012-10-09 23:29:45 +0000335 SmallVectorImpl<MCInst> &Instructions){
Jack Carter2490dc62012-10-06 00:53:28 +0000336 MCInst tmpInst;
Jack Carter9d577c82012-10-04 04:03:53 +0000337 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter2f68b312012-10-09 23:29:45 +0000338 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter9d577c82012-10-04 04:03:53 +0000339 const MCOperand &RegOp = Inst.getOperand(0);
340 assert(RegOp.isReg() && "expected register operand kind");
341
342 int ImmValue = ImmOp.getImm();
Jack Carter2490dc62012-10-06 00:53:28 +0000343 tmpInst.setLoc(IDLoc);
Jack Carter9d577c82012-10-04 04:03:53 +0000344 if ( 0 <= ImmValue && ImmValue <= 65535) {
Jack Carter2490dc62012-10-06 00:53:28 +0000345 // for 0 <= j <= 65535.
Jack Carter9d577c82012-10-04 04:03:53 +0000346 // li d,j => ori d,$zero,j
Jack Carter2490dc62012-10-06 00:53:28 +0000347 tmpInst.setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
348 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
349 tmpInst.addOperand(
Jack Carter9d577c82012-10-04 04:03:53 +0000350 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
Jack Carter2490dc62012-10-06 00:53:28 +0000351 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter9d577c82012-10-04 04:03:53 +0000352 Instructions.push_back(tmpInst);
353 } else if ( ImmValue < 0 && ImmValue >= -32768) {
Jack Carter2490dc62012-10-06 00:53:28 +0000354 // for -32768 <= j < 0.
Jack Carter9d577c82012-10-04 04:03:53 +0000355 // li d,j => addiu d,$zero,j
Jack Carter2490dc62012-10-06 00:53:28 +0000356 tmpInst.setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
357 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
358 tmpInst.addOperand(
Jack Carter9d577c82012-10-04 04:03:53 +0000359 MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO));
Jack Carter2490dc62012-10-06 00:53:28 +0000360 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter9d577c82012-10-04 04:03:53 +0000361 Instructions.push_back(tmpInst);
362 } else {
363 // for any other value of j that is representable as a 32-bit integer.
364 // li d,j => lui d,hi16(j)
Jack Carter2f68b312012-10-09 23:29:45 +0000365 // ori d,d,lo16(j)
Jack Carter2490dc62012-10-06 00:53:28 +0000366 tmpInst.setOpcode(isMips64() ? Mips::LUi64 : Mips::LUi);
367 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
368 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter9d577c82012-10-04 04:03:53 +0000369 Instructions.push_back(tmpInst);
Jack Carter2490dc62012-10-06 00:53:28 +0000370 tmpInst.clear();
371 tmpInst.setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi);
372 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
373 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
374 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
375 tmpInst.setLoc(IDLoc);
Jack Carter9d577c82012-10-04 04:03:53 +0000376 Instructions.push_back(tmpInst);
377 }
378}
Jack Carter2490dc62012-10-06 00:53:28 +0000379
Jack Carter2f68b312012-10-09 23:29:45 +0000380void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
381 SmallVectorImpl<MCInst> &Instructions){
382 MCInst tmpInst;
383 const MCOperand &ImmOp = Inst.getOperand(2);
384 assert(ImmOp.isImm() && "expected immediate operand kind");
385 const MCOperand &SrcRegOp = Inst.getOperand(1);
386 assert(SrcRegOp.isReg() && "expected register operand kind");
387 const MCOperand &DstRegOp = Inst.getOperand(0);
388 assert(DstRegOp.isReg() && "expected register operand kind");
389 int ImmValue = ImmOp.getImm();
390 if ( -32768 <= ImmValue && ImmValue <= 65535) {
391 //for -32768 <= j <= 65535.
392 //la d,j(s) => addiu d,s,j
393 tmpInst.setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files?
394 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
395 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
396 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
397 Instructions.push_back(tmpInst);
398 } else {
399 //for any other value of j that is representable as a 32-bit integer.
400 //la d,j(s) => lui d,hi16(j)
401 // ori d,d,lo16(j)
402 // addu d,d,s
403 tmpInst.setOpcode(isMips64()?Mips::LUi64:Mips::LUi);
404 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
405 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
406 Instructions.push_back(tmpInst);
407 tmpInst.clear();
408 tmpInst.setOpcode(isMips64()?Mips::ORi64:Mips::ORi);
409 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
410 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
411 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
412 Instructions.push_back(tmpInst);
413 tmpInst.clear();
414 tmpInst.setOpcode(Mips::ADDu);
415 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
416 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
417 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
418 Instructions.push_back(tmpInst);
419 }
420}
421
422void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
423 SmallVectorImpl<MCInst> &Instructions){
424 MCInst tmpInst;
425 const MCOperand &ImmOp = Inst.getOperand(1);
426 assert(ImmOp.isImm() && "expected immediate operand kind");
427 const MCOperand &RegOp = Inst.getOperand(0);
428 assert(RegOp.isReg() && "expected register operand kind");
429 int ImmValue = ImmOp.getImm();
430 if ( -32768 <= ImmValue && ImmValue <= 65535) {
431 //for -32768 <= j <= 65535.
432 //la d,j => addiu d,$zero,j
433 tmpInst.setOpcode(Mips::ADDiu);
434 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
435 tmpInst.addOperand(
436 MCOperand::CreateReg(isMips64()?Mips::ZERO_64:Mips::ZERO));
437 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
438 Instructions.push_back(tmpInst);
439 } else {
440 //for any other value of j that is representable as a 32-bit integer.
441 //la d,j => lui d,hi16(j)
442 // ori d,d,lo16(j)
443 tmpInst.setOpcode(isMips64()?Mips::LUi64:Mips::LUi);
444 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
445 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
446 Instructions.push_back(tmpInst);
447 tmpInst.clear();
448 tmpInst.setOpcode(isMips64()?Mips::ORi64:Mips::ORi);
449 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
450 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
451 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
452 Instructions.push_back(tmpInst);
453 }
454}
455
Rafael Espindolafddf8042012-01-11 03:56:41 +0000456bool MipsAsmParser::
Chad Rosier84125ca2012-10-13 00:26:04 +0000457MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindolafddf8042012-01-11 03:56:41 +0000458 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier84125ca2012-10-13 00:26:04 +0000459 MCStreamer &Out, unsigned &ErrorInfo,
460 bool MatchingInlineAsm) {
Jack Carterec65be82012-09-05 23:34:03 +0000461 MCInst Inst;
Chad Rosier6e006d32012-10-12 22:53:36 +0000462 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier84125ca2012-10-13 00:26:04 +0000463 MatchingInlineAsm);
Jack Carterec65be82012-09-05 23:34:03 +0000464
465 switch (MatchResult) {
466 default: break;
467 case Match_Success: {
Jack Carter9d577c82012-10-04 04:03:53 +0000468 if (needsExpansion(Inst)) {
Jack Carter2490dc62012-10-06 00:53:28 +0000469 SmallVector<MCInst, 4> Instructions;
Jack Carter9d577c82012-10-04 04:03:53 +0000470 expandInstruction(Inst, IDLoc, Instructions);
471 for(unsigned i =0; i < Instructions.size(); i++){
Jack Carter2490dc62012-10-06 00:53:28 +0000472 Out.EmitInstruction(Instructions[i]);
Jack Carter9d577c82012-10-04 04:03:53 +0000473 }
474 } else {
475 Inst.setLoc(IDLoc);
476 Out.EmitInstruction(Inst);
477 }
Jack Carterec65be82012-09-05 23:34:03 +0000478 return false;
479 }
480 case Match_MissingFeature:
481 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
482 return true;
483 case Match_InvalidOperand: {
484 SMLoc ErrorLoc = IDLoc;
485 if (ErrorInfo != ~0U) {
486 if (ErrorInfo >= Operands.size())
487 return Error(IDLoc, "too few operands for instruction");
488
489 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
490 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
491 }
492
493 return Error(ErrorLoc, "invalid operand for instruction");
494 }
495 case Match_MnemonicFail:
496 return Error(IDLoc, "invalid instruction");
497 }
Rafael Espindolafddf8042012-01-11 03:56:41 +0000498 return true;
499}
500
Jack Carterec65be82012-09-05 23:34:03 +0000501int MipsAsmParser::matchRegisterName(StringRef Name) {
502
David Chisnall572e1bd2012-10-09 16:27:43 +0000503 int CC;
504 if (!isMips64())
505 CC = StringSwitch<unsigned>(Name)
506 .Case("zero", Mips::ZERO)
507 .Case("a0", Mips::A0)
508 .Case("a1", Mips::A1)
509 .Case("a2", Mips::A2)
510 .Case("a3", Mips::A3)
511 .Case("v0", Mips::V0)
512 .Case("v1", Mips::V1)
513 .Case("s0", Mips::S0)
514 .Case("s1", Mips::S1)
515 .Case("s2", Mips::S2)
516 .Case("s3", Mips::S3)
517 .Case("s4", Mips::S4)
518 .Case("s5", Mips::S5)
519 .Case("s6", Mips::S6)
520 .Case("s7", Mips::S7)
521 .Case("k0", Mips::K0)
522 .Case("k1", Mips::K1)
523 .Case("sp", Mips::SP)
524 .Case("fp", Mips::FP)
525 .Case("gp", Mips::GP)
526 .Case("ra", Mips::RA)
527 .Case("t0", Mips::T0)
528 .Case("t1", Mips::T1)
529 .Case("t2", Mips::T2)
530 .Case("t3", Mips::T3)
531 .Case("t4", Mips::T4)
532 .Case("t5", Mips::T5)
533 .Case("t6", Mips::T6)
534 .Case("t7", Mips::T7)
535 .Case("t8", Mips::T8)
536 .Case("t9", Mips::T9)
537 .Case("at", Mips::AT)
538 .Case("fcc0", Mips::FCC0)
539 .Default(-1);
540 else
541 CC = StringSwitch<unsigned>(Name)
542 .Case("zero", Mips::ZERO_64)
543 .Case("at", Mips::AT_64)
544 .Case("v0", Mips::V0_64)
545 .Case("v1", Mips::V1_64)
546 .Case("a0", Mips::A0_64)
547 .Case("a1", Mips::A1_64)
548 .Case("a2", Mips::A2_64)
549 .Case("a3", Mips::A3_64)
550 .Case("a4", Mips::T0_64)
551 .Case("a5", Mips::T1_64)
552 .Case("a6", Mips::T2_64)
553 .Case("a7", Mips::T3_64)
554 .Case("t4", Mips::T4_64)
555 .Case("t5", Mips::T5_64)
556 .Case("t6", Mips::T6_64)
557 .Case("t7", Mips::T7_64)
558 .Case("s0", Mips::S0_64)
559 .Case("s1", Mips::S1_64)
560 .Case("s2", Mips::S2_64)
561 .Case("s3", Mips::S3_64)
562 .Case("s4", Mips::S4_64)
563 .Case("s5", Mips::S5_64)
564 .Case("s6", Mips::S6_64)
565 .Case("s7", Mips::S7_64)
566 .Case("t8", Mips::T8_64)
567 .Case("t9", Mips::T9_64)
568 .Case("kt0", Mips::K0_64)
569 .Case("kt1", Mips::K1_64)
570 .Case("gp", Mips::GP_64)
571 .Case("sp", Mips::SP_64)
572 .Case("fp", Mips::FP_64)
573 .Case("s8", Mips::FP_64)
574 .Case("ra", Mips::RA_64)
575 .Default(-1);
Jack Carterec65be82012-09-05 23:34:03 +0000576
David Chisnall572e1bd2012-10-09 16:27:43 +0000577 if (CC != -1)
Jack Carterec65be82012-09-05 23:34:03 +0000578 return CC;
Jack Carterec65be82012-09-05 23:34:03 +0000579
Jack Carterf740d6e2012-09-07 00:23:42 +0000580 if (Name[0] == 'f') {
581 StringRef NumString = Name.substr(1);
582 unsigned IntVal;
583 if( NumString.getAsInteger(10, IntVal))
Jack Carter9d577c82012-10-04 04:03:53 +0000584 return -1; // not integer
Jack Carterf740d6e2012-09-07 00:23:42 +0000585 if (IntVal > 31)
586 return -1;
587
588 FpFormatTy Format = getFpFormat();
589
590 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
591 return getReg(Mips::FGR32RegClassID, IntVal);
592 if (Format == FP_FORMAT_D) {
593 if(isFP64()) {
594 return getReg(Mips::FGR64RegClassID, IntVal);
595 }
Jack Carter9d577c82012-10-04 04:03:53 +0000596 // only even numbers available as register pairs
Jack Carterf740d6e2012-09-07 00:23:42 +0000597 if (( IntVal > 31) || (IntVal%2 != 0))
598 return -1;
599 return getReg(Mips::AFGR64RegClassID, IntVal/2);
600 }
601 }
602
Jack Carterec65be82012-09-05 23:34:03 +0000603 return -1;
604}
Jack Carterf740d6e2012-09-07 00:23:42 +0000605void MipsAsmParser::setDefaultFpFormat() {
606
607 if (isMips64() || isFP64())
608 FpFormat = FP_FORMAT_D;
609 else
610 FpFormat = FP_FORMAT_S;
611}
612
613bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
614
615 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
616 .Case("ldxc1", true)
617 .Case("ldc1", true)
618 .Case("sdxc1", true)
619 .Case("sdc1", true)
620 .Default(false);
621
622 return IsDouble;
623}
624void MipsAsmParser::setFpFormat(StringRef Format) {
625
626 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
627 .Case(".s", FP_FORMAT_S)
628 .Case(".d", FP_FORMAT_D)
629 .Case(".l", FP_FORMAT_L)
630 .Case(".w", FP_FORMAT_W)
631 .Default(FP_FORMAT_NONE);
632}
Jack Carterec65be82012-09-05 23:34:03 +0000633
Jack Carter30116cd2012-10-04 02:29:46 +0000634bool MipsAssemblerOptions::setATReg(unsigned Reg) {
635 if (Reg > 31)
636 return false;
637
638 aTReg = Reg;
639 return true;
640}
641
642unsigned MipsAsmParser::getATReg() {
Jack Carter10d5ff62012-10-05 23:55:28 +0000643 unsigned Reg = Options.getATRegNum();
Jack Carter30116cd2012-10-04 02:29:46 +0000644 if (isMips64())
645 return getReg(Mips::CPU64RegsRegClassID,Reg);
Jack Carter10d5ff62012-10-05 23:55:28 +0000646
647 return getReg(Mips::CPURegsRegClassID,Reg);
Jack Carter30116cd2012-10-04 02:29:46 +0000648}
649
650unsigned MipsAsmParser::getReg(int RC,int RegNo) {
Jack Carterec65be82012-09-05 23:34:03 +0000651 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
652}
653
Jack Carter30116cd2012-10-04 02:29:46 +0000654int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
Jack Carterec65be82012-09-05 23:34:03 +0000655
656 if (Mnemonic.lower() == "rdhwr") {
Jack Carter9d577c82012-10-04 04:03:53 +0000657 // at the moment only hwreg29 is supported
Jack Carterec65be82012-09-05 23:34:03 +0000658 if (RegNum != 29)
659 return -1;
660 return Mips::HWR29;
661 }
662
663 if (RegNum > 31)
664 return -1;
665
David Chisnall572e1bd2012-10-09 16:27:43 +0000666 // MIPS64 registers are numbered 1 after the 32-bit equivalents
667 return getReg(Mips::CPURegsRegClassID, RegNum) + isMips64();
Jack Carterec65be82012-09-05 23:34:03 +0000668}
669
670int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
671 const AsmToken &Tok = Parser.getTok();
672 int RegNum = -1;
673
674 if (Tok.is(AsmToken::Identifier)) {
675 std::string lowerCase = Tok.getString().lower();
676 RegNum = matchRegisterName(lowerCase);
677 } else if (Tok.is(AsmToken::Integer))
Jack Carter9d577c82012-10-04 04:03:53 +0000678 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carter6b96c3f2012-09-06 20:00:02 +0000679 Mnemonic.lower());
Jack Carterf740d6e2012-09-07 00:23:42 +0000680 else
681 return RegNum; //error
Jack Carter9d577c82012-10-04 04:03:53 +0000682 // 64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
Jack Carterf740d6e2012-09-07 00:23:42 +0000683 if (isMips64() && RegNum == Mips::ZERO_64) {
684 if (Mnemonic.find("ddiv") != StringRef::npos)
685 RegNum = Mips::ZERO;
686 }
Jack Carterec65be82012-09-05 23:34:03 +0000687 return RegNum;
688}
689
Rafael Espindolafddf8042012-01-11 03:56:41 +0000690bool MipsAsmParser::
Jack Carterec65be82012-09-05 23:34:03 +0000691 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
692 StringRef Mnemonic){
693
694 SMLoc S = Parser.getTok().getLoc();
695 int RegNo = -1;
Jack Carterf740d6e2012-09-07 00:23:42 +0000696
Jack Carter9d577c82012-10-04 04:03:53 +0000697 // FIXME: we should make a more generic method for CCR
Jack Carterf740d6e2012-09-07 00:23:42 +0000698 if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
699 && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
Jack Carter9d577c82012-10-04 04:03:53 +0000700 RegNo = Parser.getTok().getIntVal(); // get the int value
701 // at the moment only fcc0 is supported
Jack Carterf740d6e2012-09-07 00:23:42 +0000702 if (RegNo == 0)
703 RegNo = Mips::FCC0;
704 } else
705 RegNo = tryParseRegister(Mnemonic);
Jack Carterec65be82012-09-05 23:34:03 +0000706 if (RegNo == -1)
707 return true;
708
709 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterf740d6e2012-09-07 00:23:42 +0000710 Parser.getTok().getLoc()));
Jack Carterec65be82012-09-05 23:34:03 +0000711 Parser.Lex(); // Eat register token.
712 return false;
713}
714
715bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
716 StringRef Mnemonic) {
Jack Carter9d577c82012-10-04 04:03:53 +0000717 // Check if the current operand has a custom associated parser, if so, try to
718 // custom parse the operand, or fallback to the general approach.
Jack Carterec65be82012-09-05 23:34:03 +0000719 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
720 if (ResTy == MatchOperand_Success)
721 return false;
722 // If there wasn't a custom match, try the generic matcher below. Otherwise,
723 // there was a match, but an error occurred, in which case, just return that
724 // the operand parsing failed.
725 if (ResTy == MatchOperand_ParseFail)
726 return true;
727
728 switch (getLexer().getKind()) {
729 default:
730 Error(Parser.getTok().getLoc(), "unexpected token in operand");
731 return true;
732 case AsmToken::Dollar: {
Jack Carter9d577c82012-10-04 04:03:53 +0000733 // parse register
Jack Carterec65be82012-09-05 23:34:03 +0000734 SMLoc S = Parser.getTok().getLoc();
735 Parser.Lex(); // Eat dollar token.
Jack Carter9d577c82012-10-04 04:03:53 +0000736 // parse register operand
737 if (!tryParseRegisterOperand(Operands, Mnemonic)) {
Jack Carterec65be82012-09-05 23:34:03 +0000738 if (getLexer().is(AsmToken::LParen)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000739 // check if it is indexed addressing operand
Jack Carterec65be82012-09-05 23:34:03 +0000740 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carter9d577c82012-10-04 04:03:53 +0000741 Parser.Lex(); // eat parenthesis
Jack Carterec65be82012-09-05 23:34:03 +0000742 if (getLexer().isNot(AsmToken::Dollar))
743 return true;
744
Jack Carter9d577c82012-10-04 04:03:53 +0000745 Parser.Lex(); // eat dollar
746 if (tryParseRegisterOperand(Operands, Mnemonic))
Jack Carterec65be82012-09-05 23:34:03 +0000747 return true;
748
749 if (!getLexer().is(AsmToken::RParen))
750 return true;
751
752 S = Parser.getTok().getLoc();
753 Operands.push_back(MipsOperand::CreateToken(")", S));
754 Parser.Lex();
755 }
756 return false;
757 }
Jack Carter9d577c82012-10-04 04:03:53 +0000758 // maybe it is a symbol reference
Jack Carterec65be82012-09-05 23:34:03 +0000759 StringRef Identifier;
760 if (Parser.ParseIdentifier(Identifier))
761 return true;
762
Jack Carter6b96c3f2012-09-06 20:00:02 +0000763 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000764
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000765 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterec65be82012-09-05 23:34:03 +0000766
767 // Otherwise create a symbol ref.
Jack Carter6b96c3f2012-09-06 20:00:02 +0000768 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterec65be82012-09-05 23:34:03 +0000769 getContext());
770
771 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
772 return false;
773 }
774 case AsmToken::Identifier:
775 case AsmToken::LParen:
776 case AsmToken::Minus:
777 case AsmToken::Plus:
778 case AsmToken::Integer:
779 case AsmToken::String: {
780 // quoted label names
781 const MCExpr *IdVal;
782 SMLoc S = Parser.getTok().getLoc();
783 if (getParser().ParseExpression(IdVal))
784 return true;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000785 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000786 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
787 return false;
788 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000789 case AsmToken::Percent: {
Jack Carter9d577c82012-10-04 04:03:53 +0000790 // it is a symbol reference or constant expression
Jack Carter6b96c3f2012-09-06 20:00:02 +0000791 const MCExpr *IdVal;
Jack Carter9d577c82012-10-04 04:03:53 +0000792 SMLoc S = Parser.getTok().getLoc(); // start location of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000793 if (parseRelocOperand(IdVal))
794 return true;
795
796 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
797
798 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
799 return false;
Jack Carter30116cd2012-10-04 02:29:46 +0000800 } // case AsmToken::Percent
801 } // switch(getLexer().getKind())
Rafael Espindolafddf8042012-01-11 03:56:41 +0000802 return true;
803}
804
Jack Carter6b96c3f2012-09-06 20:00:02 +0000805bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
806
Jack Carter30116cd2012-10-04 02:29:46 +0000807 Parser.Lex(); // eat % token
Jack Carter9d577c82012-10-04 04:03:53 +0000808 const AsmToken &Tok = Parser.getTok(); // get next token, operation
Jack Carter6b96c3f2012-09-06 20:00:02 +0000809 if (Tok.isNot(AsmToken::Identifier))
810 return true;
811
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000812 std::string Str = Tok.getIdentifier().str();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000813
Jack Carter9d577c82012-10-04 04:03:53 +0000814 Parser.Lex(); // eat identifier
Jack Carter30116cd2012-10-04 02:29:46 +0000815 // now make expression from the rest of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000816 const MCExpr *IdVal;
817 SMLoc EndLoc;
818
819 if (getLexer().getKind() == AsmToken::LParen) {
820 while (1) {
Jack Carter30116cd2012-10-04 02:29:46 +0000821 Parser.Lex(); // eat '(' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000822 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carter30116cd2012-10-04 02:29:46 +0000823 Parser.Lex(); // eat % token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000824 const AsmToken &nextTok = Parser.getTok();
825 if (nextTok.isNot(AsmToken::Identifier))
826 return true;
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000827 Str += "(%";
828 Str += nextTok.getIdentifier();
Jack Carter30116cd2012-10-04 02:29:46 +0000829 Parser.Lex(); // eat identifier
Jack Carter6b96c3f2012-09-06 20:00:02 +0000830 if (getLexer().getKind() != AsmToken::LParen)
831 return true;
832 } else
833 break;
834 }
835 if (getParser().ParseParenExpression(IdVal,EndLoc))
836 return true;
837
838 while (getLexer().getKind() == AsmToken::RParen)
Jack Carter30116cd2012-10-04 02:29:46 +0000839 Parser.Lex(); // eat ')' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000840
841 } else
Jack Carter30116cd2012-10-04 02:29:46 +0000842 return true; // parenthesis must follow reloc operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000843
Jack Carter30116cd2012-10-04 02:29:46 +0000844 // Check the type of the expression
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000845 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carter9d577c82012-10-04 04:03:53 +0000846 // it's a constant, evaluate lo or hi value
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000847 int Val = MCE->getValue();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000848 if (Str == "lo") {
849 Val = Val & 0xffff;
850 } else if (Str == "hi") {
851 Val = (Val & 0xffff0000) >> 16;
852 }
853 Res = MCConstantExpr::Create(Val, getContext());
854 return false;
855 }
856
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000857 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter30116cd2012-10-04 02:29:46 +0000858 // it's a symbol, create symbolic expression from symbol
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000859 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000860 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
861 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
862 return false;
863 }
864 return true;
865}
866
Jack Carterec65be82012-09-05 23:34:03 +0000867bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
868 SMLoc &EndLoc) {
869
870 StartLoc = Parser.getTok().getLoc();
871 RegNo = tryParseRegister("");
872 EndLoc = Parser.getTok().getLoc();
873 return (RegNo == (unsigned)-1);
874}
875
Jack Carter6b96c3f2012-09-06 20:00:02 +0000876bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
877
878 SMLoc S;
879
880 switch(getLexer().getKind()) {
881 default:
882 return true;
883 case AsmToken::Integer:
884 case AsmToken::Minus:
885 case AsmToken::Plus:
886 return (getParser().ParseExpression(Res));
Jack Carterf740d6e2012-09-07 00:23:42 +0000887 case AsmToken::Percent:
Jack Carter6b96c3f2012-09-06 20:00:02 +0000888 return parseRelocOperand(Res);
Jack Carter6b96c3f2012-09-06 20:00:02 +0000889 case AsmToken::LParen:
Jack Carter30116cd2012-10-04 02:29:46 +0000890 return false; // it's probably assuming 0
Jack Carter6b96c3f2012-09-06 20:00:02 +0000891 }
892 return true;
893}
894
Jack Carterec65be82012-09-05 23:34:03 +0000895MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
896 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000897
898 const MCExpr *IdVal = 0;
899 SMLoc S;
Jack Carter30116cd2012-10-04 02:29:46 +0000900 // first operand is the offset
Jack Carter6b96c3f2012-09-06 20:00:02 +0000901 S = Parser.getTok().getLoc();
902
903 if (parseMemOffset(IdVal))
904 return MatchOperand_ParseFail;
905
Jack Carter30116cd2012-10-04 02:29:46 +0000906 const AsmToken &Tok = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000907 if (Tok.isNot(AsmToken::LParen)) {
Jack Carter2f68b312012-10-09 23:29:45 +0000908 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
909 if (Mnemonic->getToken() == "la") {
910 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
911 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
912 return MatchOperand_Success;
913 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000914 Error(Parser.getTok().getLoc(), "'(' expected");
915 return MatchOperand_ParseFail;
916 }
917
918 Parser.Lex(); // Eat '(' token.
919
Jack Carter2f68b312012-10-09 23:29:45 +0000920 const AsmToken &Tok1 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000921 if (Tok1.is(AsmToken::Dollar)) {
922 Parser.Lex(); // Eat '$' token.
923 if (tryParseRegisterOperand(Operands,"")) {
924 Error(Parser.getTok().getLoc(), "unexpected token in operand");
925 return MatchOperand_ParseFail;
926 }
927
928 } else {
Jack Carter30116cd2012-10-04 02:29:46 +0000929 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carter6b96c3f2012-09-06 20:00:02 +0000930 return MatchOperand_ParseFail;
931 }
932
Jack Carter30116cd2012-10-04 02:29:46 +0000933 const AsmToken &Tok2 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000934 if (Tok2.isNot(AsmToken::RParen)) {
935 Error(Parser.getTok().getLoc(), "')' expected");
936 return MatchOperand_ParseFail;
937 }
938
939 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
940
941 Parser.Lex(); // Eat ')' token.
942
943 if (IdVal == 0)
944 IdVal = MCConstantExpr::Create(0, getContext());
945
Jack Carter30116cd2012-10-04 02:29:46 +0000946 // now replace register operand with the mem operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000947 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
948 int RegNo = op->getReg();
Jack Carter30116cd2012-10-04 02:29:46 +0000949 // remove register from operands
Jack Carter6b96c3f2012-09-06 20:00:02 +0000950 Operands.pop_back();
Jack Carter30116cd2012-10-04 02:29:46 +0000951 // and add memory operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000952 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
953 delete op;
Jack Carterec65be82012-09-05 23:34:03 +0000954 return MatchOperand_Success;
955}
956
Jack Carter6b96c3f2012-09-06 20:00:02 +0000957MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
958
959 MCSymbolRefExpr::VariantKind VK
960 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
961 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
962 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
963 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
964 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
965 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
966 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
967 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
968 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
969 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
970 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
971 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
972 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
973 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
974 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
975 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
976 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
977 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
978 .Default(MCSymbolRefExpr::VK_None);
979
980 return VK;
981}
982
Benjamin Kramer1ac45872012-09-10 11:52:14 +0000983static int ConvertCcString(StringRef CondString) {
Jack Carterf740d6e2012-09-07 00:23:42 +0000984 int CC = StringSwitch<unsigned>(CondString)
985 .Case(".f", 0)
986 .Case(".un", 1)
987 .Case(".eq", 2)
988 .Case(".ueq", 3)
989 .Case(".olt", 4)
990 .Case(".ult", 5)
991 .Case(".ole", 6)
992 .Case(".ule", 7)
993 .Case(".sf", 8)
994 .Case(".ngle", 9)
995 .Case(".seq", 10)
996 .Case(".ngl", 11)
997 .Case(".lt", 12)
998 .Case(".nge", 13)
999 .Case(".le", 14)
1000 .Case(".ngt", 15)
1001 .Default(-1);
1002
1003 return CC;
1004}
1005
1006bool MipsAsmParser::
1007parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter30116cd2012-10-04 02:29:46 +00001008 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1009 // split the format
Jack Carterf740d6e2012-09-07 00:23:42 +00001010 size_t Start = Name.find('.'), Next = Name.rfind('.');
1011 StringRef Format1 = Name.slice(Start, Next);
Jack Carter30116cd2012-10-04 02:29:46 +00001012 // and add the first format to the operands
Jack Carterf740d6e2012-09-07 00:23:42 +00001013 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carter30116cd2012-10-04 02:29:46 +00001014 // now for the second format
Jack Carterf740d6e2012-09-07 00:23:42 +00001015 StringRef Format2 = Name.slice(Next, StringRef::npos);
1016 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1017
Jack Carter30116cd2012-10-04 02:29:46 +00001018 // set the format for the first register
Jack Carterf740d6e2012-09-07 00:23:42 +00001019 setFpFormat(Format1);
1020
1021 // Read the remaining operands.
1022 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1023 // Read the first operand.
1024 if (ParseOperand(Operands, Name)) {
1025 SMLoc Loc = getLexer().getLoc();
1026 Parser.EatToEndOfStatement();
1027 return Error(Loc, "unexpected token in argument list");
1028 }
1029
1030 if (getLexer().isNot(AsmToken::Comma)) {
1031 SMLoc Loc = getLexer().getLoc();
1032 Parser.EatToEndOfStatement();
1033 return Error(Loc, "unexpected token in argument list");
1034
1035 }
1036 Parser.Lex(); // Eat the comma.
1037
1038 //set the format for the first register
1039 setFpFormat(Format2);
1040
1041 // Parse and remember the operand.
1042 if (ParseOperand(Operands, Name)) {
1043 SMLoc Loc = getLexer().getLoc();
1044 Parser.EatToEndOfStatement();
1045 return Error(Loc, "unexpected token in argument list");
1046 }
1047 }
1048
1049 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1050 SMLoc Loc = getLexer().getLoc();
1051 Parser.EatToEndOfStatement();
1052 return Error(Loc, "unexpected token in argument list");
1053 }
1054
1055 Parser.Lex(); // Consume the EndOfStatement
1056 return false;
1057}
1058
Rafael Espindolafddf8042012-01-11 03:56:41 +00001059bool MipsAsmParser::
Chad Rosier6a020a72012-10-25 20:41:34 +00001060ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindolafddf8042012-01-11 03:56:41 +00001061 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter30116cd2012-10-04 02:29:46 +00001062 // floating point instructions: should register be treated as double?
Jack Carterf740d6e2012-09-07 00:23:42 +00001063 if (requestsDoubleOperand(Name)) {
1064 setFpFormat(FP_FORMAT_D);
Jack Carterec65be82012-09-05 23:34:03 +00001065 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterf740d6e2012-09-07 00:23:42 +00001066 }
1067 else {
1068 setDefaultFpFormat();
1069 // Create the leading tokens for the mnemonic, split by '.' characters.
1070 size_t Start = 0, Next = Name.find('.');
1071 StringRef Mnemonic = Name.slice(Start, Next);
1072
1073 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1074
1075 if (Next != StringRef::npos) {
Jack Carter30116cd2012-10-04 02:29:46 +00001076 // there is a format token in mnemonic
1077 // StringRef Rest = Name.slice(Next, StringRef::npos);
Jack Carterf740d6e2012-09-07 00:23:42 +00001078 size_t Dot = Name.find('.', Next+1);
1079 StringRef Format = Name.slice(Next, Dot);
1080 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1081 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1082 else {
1083 if (Name.startswith("c.")){
1084 // floating point compare, add '.' and immediate represent for cc
1085 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1086 int Cc = ConvertCcString(Format);
1087 if (Cc == -1) {
1088 return Error(NameLoc, "Invalid conditional code");
1089 }
1090 SMLoc E = SMLoc::getFromPointer(
1091 Parser.getTok().getLoc().getPointer() -1 );
1092 Operands.push_back(MipsOperand::CreateImm(
1093 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1094 } else {
Jack Carter30116cd2012-10-04 02:29:46 +00001095 // trunc, ceil, floor ...
Jack Carterf740d6e2012-09-07 00:23:42 +00001096 return parseMathOperation(Name, NameLoc, Operands);
1097 }
1098
Jack Carter30116cd2012-10-04 02:29:46 +00001099 // the rest is a format
Jack Carterf740d6e2012-09-07 00:23:42 +00001100 Format = Name.slice(Dot, StringRef::npos);
1101 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1102 }
1103
1104 setFpFormat(Format);
1105 }
1106 }
Jack Carterec65be82012-09-05 23:34:03 +00001107
1108 // Read the remaining operands.
1109 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1110 // Read the first operand.
1111 if (ParseOperand(Operands, Name)) {
1112 SMLoc Loc = getLexer().getLoc();
1113 Parser.EatToEndOfStatement();
1114 return Error(Loc, "unexpected token in argument list");
1115 }
1116
1117 while (getLexer().is(AsmToken::Comma) ) {
1118 Parser.Lex(); // Eat the comma.
1119
1120 // Parse and remember the operand.
1121 if (ParseOperand(Operands, Name)) {
1122 SMLoc Loc = getLexer().getLoc();
1123 Parser.EatToEndOfStatement();
1124 return Error(Loc, "unexpected token in argument list");
1125 }
1126 }
1127 }
1128
1129 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1130 SMLoc Loc = getLexer().getLoc();
1131 Parser.EatToEndOfStatement();
1132 return Error(Loc, "unexpected token in argument list");
1133 }
1134
1135 Parser.Lex(); // Consume the EndOfStatement
1136 return false;
Rafael Espindolafddf8042012-01-11 03:56:41 +00001137}
1138
Jack Carter30116cd2012-10-04 02:29:46 +00001139bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1140 SMLoc Loc = getLexer().getLoc();
1141 Parser.EatToEndOfStatement();
1142 return Error(Loc, ErrorMsg);
1143}
1144
1145bool MipsAsmParser::parseSetNoAtDirective() {
1146 // line should look like:
1147 // .set noat
1148 // set at reg to 0
Jack Carter10d5ff62012-10-05 23:55:28 +00001149 Options.setATReg(0);
Jack Carter30116cd2012-10-04 02:29:46 +00001150 // eat noat
1151 Parser.Lex();
1152 // if this is not the end of the statement, report error
1153 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1154 reportParseError("unexpected token in statement");
1155 return false;
1156 }
1157 Parser.Lex(); // Consume the EndOfStatement
1158 return false;
1159}
1160bool MipsAsmParser::parseSetAtDirective() {
1161 // line can be
1162 // .set at - defaults to $1
1163 // or .set at=$reg
1164 getParser().Lex();
1165 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter10d5ff62012-10-05 23:55:28 +00001166 Options.setATReg(1);
Jack Carter30116cd2012-10-04 02:29:46 +00001167 Parser.Lex(); // Consume the EndOfStatement
1168 return false;
1169 } else if (getLexer().is(AsmToken::Equal)) {
1170 getParser().Lex(); //eat '='
1171 if (getLexer().isNot(AsmToken::Dollar)) {
1172 reportParseError("unexpected token in statement");
1173 return false;
1174 }
1175 Parser.Lex(); // eat '$'
1176 if (getLexer().isNot(AsmToken::Integer)) {
1177 reportParseError("unexpected token in statement");
1178 return false;
1179 }
1180 const AsmToken &Reg = Parser.getTok();
Jack Carter10d5ff62012-10-05 23:55:28 +00001181 if (!Options.setATReg(Reg.getIntVal())) {
Jack Carter30116cd2012-10-04 02:29:46 +00001182 reportParseError("unexpected token in statement");
1183 return false;
1184 }
1185 getParser().Lex(); //eat reg
1186
1187 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1188 reportParseError("unexpected token in statement");
1189 return false;
1190 }
1191 Parser.Lex(); // Consume the EndOfStatement
1192 return false;
1193 } else {
1194 reportParseError("unexpected token in statement");
1195 return false;
1196 }
1197}
1198
1199bool MipsAsmParser::parseSetReorderDirective() {
1200 Parser.Lex();
1201 // if this is not the end of the statement, report error
1202 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1203 reportParseError("unexpected token in statement");
1204 return false;
1205 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001206 Options.setReorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001207 Parser.Lex(); // Consume the EndOfStatement
1208 return false;
1209}
1210
1211bool MipsAsmParser::parseSetNoReorderDirective() {
1212 Parser.Lex();
1213 // if this is not the end of the statement, report error
1214 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1215 reportParseError("unexpected token in statement");
1216 return false;
1217 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001218 Options.setNoreorder();
Jack Carter30116cd2012-10-04 02:29:46 +00001219 Parser.Lex(); // Consume the EndOfStatement
1220 return false;
1221}
1222
1223bool MipsAsmParser::parseSetMacroDirective() {
1224 Parser.Lex();
1225 // if this is not the end of the statement, report error
1226 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1227 reportParseError("unexpected token in statement");
1228 return false;
1229 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001230 Options.setMacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001231 Parser.Lex(); // Consume the EndOfStatement
1232 return false;
1233}
1234
1235bool MipsAsmParser::parseSetNoMacroDirective() {
1236 Parser.Lex();
1237 // if this is not the end of the statement, report error
1238 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1239 reportParseError("`noreorder' must be set before `nomacro'");
1240 return false;
1241 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001242 if (Options.isReorder()) {
Jack Carter30116cd2012-10-04 02:29:46 +00001243 reportParseError("`noreorder' must be set before `nomacro'");
1244 return false;
1245 }
Jack Carter10d5ff62012-10-05 23:55:28 +00001246 Options.setNomacro();
Jack Carter30116cd2012-10-04 02:29:46 +00001247 Parser.Lex(); // Consume the EndOfStatement
1248 return false;
1249}
1250bool MipsAsmParser::parseDirectiveSet() {
1251
1252 // get next token
1253 const AsmToken &Tok = Parser.getTok();
1254
1255 if (Tok.getString() == "noat") {
1256 return parseSetNoAtDirective();
1257 } else if (Tok.getString() == "at") {
1258 return parseSetAtDirective();
1259 } else if (Tok.getString() == "reorder") {
1260 return parseSetReorderDirective();
1261 } else if (Tok.getString() == "noreorder") {
1262 return parseSetNoReorderDirective();
1263 } else if (Tok.getString() == "macro") {
1264 return parseSetMacroDirective();
1265 } else if (Tok.getString() == "nomacro") {
1266 return parseSetNoMacroDirective();
1267 } else if (Tok.getString() == "nomips16") {
1268 // ignore this directive for now
1269 Parser.EatToEndOfStatement();
1270 return false;
1271 } else if (Tok.getString() == "nomicromips") {
1272 // ignore this directive for now
1273 Parser.EatToEndOfStatement();
1274 return false;
1275 }
1276 return true;
1277}
1278
1279bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carteracbea452012-09-07 00:48:02 +00001280
1281 if (DirectiveID.getString() == ".ent") {
Jack Carter30116cd2012-10-04 02:29:46 +00001282 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001283 Parser.Lex();
1284 return false;
1285 }
1286
1287 if (DirectiveID.getString() == ".end") {
Jack Carter30116cd2012-10-04 02:29:46 +00001288 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001289 Parser.Lex();
1290 return false;
1291 }
1292
1293 if (DirectiveID.getString() == ".frame") {
Jack Carter30116cd2012-10-04 02:29:46 +00001294 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001295 Parser.EatToEndOfStatement();
1296 return false;
1297 }
1298
1299 if (DirectiveID.getString() == ".set") {
Jack Carter30116cd2012-10-04 02:29:46 +00001300 return parseDirectiveSet();
Jack Carteracbea452012-09-07 00:48:02 +00001301 }
1302
1303 if (DirectiveID.getString() == ".fmask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001304 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001305 Parser.EatToEndOfStatement();
1306 return false;
1307 }
1308
1309 if (DirectiveID.getString() == ".mask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001310 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001311 Parser.EatToEndOfStatement();
1312 return false;
1313 }
1314
1315 if (DirectiveID.getString() == ".gpword") {
Jack Carter30116cd2012-10-04 02:29:46 +00001316 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001317 Parser.EatToEndOfStatement();
1318 return false;
1319 }
1320
Rafael Espindolafddf8042012-01-11 03:56:41 +00001321 return true;
1322}
1323
Rafael Espindolafddf8042012-01-11 03:56:41 +00001324extern "C" void LLVMInitializeMipsAsmParser() {
1325 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1326 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1327 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1328 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1329}
Jack Carterec65be82012-09-05 23:34:03 +00001330
1331#define GET_REGISTER_MATCHER
1332#define GET_MATCHER_IMPLEMENTATION
1333#include "MipsGenAsmMatcher.inc"