blob: 4b419ad9e28cf4f3fecb6c2e709b24feb84b57d6 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000011#include "MipsRegisterInfo.h"
12#include "llvm/ADT/StringSwitch.h"
13#include "llvm/MC/MCContext.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCInst.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000016#include "llvm/MC/MCParser/MCAsmLexer.h"
17#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCSubtargetInfo.h"
20#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000021#include "llvm/MC/MCTargetAsmParser.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000022#include "llvm/Support/TargetRegistry.h"
Jack Carter02593002013-05-28 22:21:05 +000023#include "llvm/ADT/APInt.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000024
25using namespace llvm;
26
27namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000028class MipsAssemblerOptions {
29public:
30 MipsAssemblerOptions():
31 aTReg(1), reorder(true), macro(true) {
32 }
Jack Carterb4dbc172012-09-05 23:34:03 +000033
Jack Carter0b744b32012-10-04 02:29:46 +000034 unsigned getATRegNum() {return aTReg;}
35 bool setATReg(unsigned Reg);
36
37 bool isReorder() {return reorder;}
38 void setReorder() {reorder = true;}
39 void setNoreorder() {reorder = false;}
40
41 bool isMacro() {return macro;}
42 void setMacro() {macro = true;}
43 void setNomacro() {macro = false;}
44
45private:
46 unsigned aTReg;
47 bool reorder;
48 bool macro;
49};
50}
51
52namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000053class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka7605630c2012-08-17 20:16:42 +000054
Jack Cartera63b16a2012-09-07 00:23:42 +000055 enum FpFormatTy {
56 FP_FORMAT_NONE = -1,
57 FP_FORMAT_S,
58 FP_FORMAT_D,
59 FP_FORMAT_L,
60 FP_FORMAT_W
61 } FpFormat;
62
Jack Carterb4dbc172012-09-05 23:34:03 +000063 MCSubtargetInfo &STI;
64 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000065 MipsAssemblerOptions Options;
Jack Carter0b744b32012-10-04 02:29:46 +000066
Akira Hatanaka7605630c2012-08-17 20:16:42 +000067#define GET_ASSEMBLER_HEADER
68#include "MipsGenAsmMatcher.inc"
69
Chad Rosier49963552012-10-13 00:26:04 +000070 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +000071 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +000072 MCStreamer &Out, unsigned &ErrorInfo,
73 bool MatchingInlineAsm);
Rafael Espindola870c4e92012-01-11 03:56:41 +000074
75 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
76
Chad Rosierf0e87202012-10-25 20:41:34 +000077 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
78 SMLoc NameLoc,
Akira Hatanaka7605630c2012-08-17 20:16:42 +000079 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindola870c4e92012-01-11 03:56:41 +000080
81 bool ParseDirective(AsmToken DirectiveID);
82
Jack Carterb4dbc172012-09-05 23:34:03 +000083 MipsAsmParser::OperandMatchResultTy
Vladimir Medic8cd17102013-06-20 11:21:49 +000084 parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
85 int RegKind);
Vladimir Medic64828a12013-07-16 10:07:14 +000086
87 MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +000088 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
89
90 MipsAsmParser::OperandMatchResultTy
91 parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
92
93 MipsAsmParser::OperandMatchResultTy
94 parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
95
96 MipsAsmParser::OperandMatchResultTy
97 parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
98
99 MipsAsmParser::OperandMatchResultTy
100 parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
101
102 MipsAsmParser::OperandMatchResultTy
103 parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Chad Rosier391d29972012-09-03 18:47:45 +0000104
Vladimir Medic233dd512013-06-24 10:05:34 +0000105 MipsAsmParser::OperandMatchResultTy
106 parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
107
108 MipsAsmParser::OperandMatchResultTy
109 parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
110
111 MipsAsmParser::OperandMatchResultTy
112 parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
113
Vladimir Medic643b3982013-07-30 10:12:14 +0000114 MipsAsmParser::OperandMatchResultTy
115 parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
116
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000117 MipsAsmParser::OperandMatchResultTy
118 parseACRegsDSP(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
119
Jack Carterd76b2372013-03-21 21:44:16 +0000120 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Vladimir Medic8cd17102013-06-20 11:21:49 +0000121 unsigned RegKind);
Jack Carterd76b2372013-03-21 21:44:16 +0000122
Jack Carterb4dbc172012-09-05 23:34:03 +0000123 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
124 StringRef Mnemonic);
125
Jack Carter873c7242013-01-12 01:03:14 +0000126 int tryParseRegister(bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000127
128 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carter873c7242013-01-12 01:03:14 +0000129 bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000130
Jack Carter30a59822012-10-04 04:03:53 +0000131 bool needsExpansion(MCInst &Inst);
132
133 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000134 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000135 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000136 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000137 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
138 SmallVectorImpl<MCInst> &Instructions);
139 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
140 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000141 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
142 SmallVectorImpl<MCInst> &Instructions,
143 bool isLoad,bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000144 bool reportParseError(StringRef ErrorMsg);
145
Jack Carterb5cf5902013-04-17 00:18:04 +0000146 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000147 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000148
Jack Carterb5cf5902013-04-17 00:18:04 +0000149 const MCExpr* evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
150
151 bool isEvaluated(const MCExpr *Expr);
Jack Carter0b744b32012-10-04 02:29:46 +0000152 bool parseDirectiveSet();
153
154 bool parseSetAtDirective();
155 bool parseSetNoAtDirective();
156 bool parseSetMacroDirective();
157 bool parseSetNoMacroDirective();
158 bool parseSetReorderDirective();
159 bool parseSetNoReorderDirective();
160
Jack Carterd76b2372013-03-21 21:44:16 +0000161 bool parseSetAssignment();
162
Jack Carter07c818d2013-01-25 01:31:34 +0000163 bool parseDirectiveWord(unsigned Size, SMLoc L);
164
Jack Carterdc1e35d2012-09-06 20:00:02 +0000165 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000166
Jack Carterb4dbc172012-09-05 23:34:03 +0000167 bool isMips64() const {
168 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
169 }
170
Jack Cartera63b16a2012-09-07 00:23:42 +0000171 bool isFP64() const {
172 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
173 }
174
Jack Carter873c7242013-01-12 01:03:14 +0000175 int matchRegisterName(StringRef Symbol, bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000176
Jack Carter1ac53222013-02-20 23:11:17 +0000177 int matchCPURegisterName(StringRef Symbol);
178
Jack Carter873c7242013-01-12 01:03:14 +0000179 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000180
Vladimir Medic8cd17102013-06-20 11:21:49 +0000181 int matchFPURegisterName(StringRef Name, FpFormatTy Format);
182
Jack Cartera63b16a2012-09-07 00:23:42 +0000183 void setFpFormat(FpFormatTy Format) {
184 FpFormat = Format;
185 }
186
187 void setDefaultFpFormat();
188
189 void setFpFormat(StringRef Format);
190
191 FpFormatTy getFpFormat() {return FpFormat;}
192
Jack Carterd0bd6422013-04-18 00:41:53 +0000193 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000194
Jack Carter1ac53222013-02-20 23:11:17 +0000195 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000196
197 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
198 SmallVectorImpl<MCInst> &Instructions);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000199public:
200 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterb4dbc172012-09-05 23:34:03 +0000201 : MCTargetAsmParser(), STI(sti), Parser(parser) {
202 // Initialize the set of available features.
203 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindola870c4e92012-01-11 03:56:41 +0000204 }
205
Jack Carterb4dbc172012-09-05 23:34:03 +0000206 MCAsmParser &getParser() const { return Parser; }
207 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
208
Rafael Espindola870c4e92012-01-11 03:56:41 +0000209};
210}
211
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000212namespace {
213
214/// MipsOperand - Instances of this class represent a parsed Mips machine
215/// instruction.
216class MipsOperand : public MCParsedAsmOperand {
Jack Carterb4dbc172012-09-05 23:34:03 +0000217
Jack Carter873c7242013-01-12 01:03:14 +0000218public:
219 enum RegisterKind {
220 Kind_None,
221 Kind_CPURegs,
222 Kind_CPU64Regs,
223 Kind_HWRegs,
224 Kind_HW64Regs,
225 Kind_FGR32Regs,
226 Kind_FGR64Regs,
Jack Carter1ac53222013-02-20 23:11:17 +0000227 Kind_AFGR64Regs,
Vladimir Medic643b3982013-07-30 10:12:14 +0000228 Kind_CCRRegs,
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000229 Kind_FCCRegs,
230 Kind_ACRegsDSP
Jack Carter873c7242013-01-12 01:03:14 +0000231 };
232
233private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000234 enum KindTy {
235 k_CondCode,
236 k_CoprocNum,
237 k_Immediate,
238 k_Memory,
239 k_PostIndexRegister,
240 k_Register,
241 k_Token
242 } Kind;
243
244 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterb4dbc172012-09-05 23:34:03 +0000245
Eric Christopher8996c5d2013-03-15 00:42:55 +0000246 struct Token {
247 const char *Data;
248 unsigned Length;
249 };
250
251 struct RegOp {
252 unsigned RegNum;
253 RegisterKind Kind;
254 };
255
256 struct ImmOp {
257 const MCExpr *Val;
258 };
259
260 struct MemOp {
261 unsigned Base;
262 const MCExpr *Off;
263 };
264
Jack Carterb4dbc172012-09-05 23:34:03 +0000265 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000266 struct Token Tok;
267 struct RegOp Reg;
268 struct ImmOp Imm;
269 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000270 };
271
272 SMLoc StartLoc, EndLoc;
273
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000274public:
275 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000276 assert(N == 1 && "Invalid number of operands!");
277 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000278 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000279
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000280 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterb4dbc172012-09-05 23:34:03 +0000281 // Add as immediate when possible. Null MCExpr = 0.
282 if (Expr == 0)
283 Inst.addOperand(MCOperand::CreateImm(0));
284 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
285 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
286 else
287 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000288 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000289
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000290 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000291 assert(N == 1 && "Invalid number of operands!");
292 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000293 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000294 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000295
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000296 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000297 assert(N == 2 && "Invalid number of operands!");
298
299 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
300
301 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000302 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000303 }
304
305 bool isReg() const { return Kind == k_Register; }
306 bool isImm() const { return Kind == k_Immediate; }
307 bool isToken() const { return Kind == k_Token; }
308 bool isMem() const { return Kind == k_Memory; }
309
310 StringRef getToken() const {
311 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000312 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000313 }
314
315 unsigned getReg() const {
316 assert((Kind == k_Register) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000317 return Reg.RegNum;
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000318 }
319
Jack Carter873c7242013-01-12 01:03:14 +0000320 void setRegKind(RegisterKind RegKind) {
321 assert((Kind == k_Register) && "Invalid access!");
322 Reg.Kind = RegKind;
323 }
324
Jack Carterb4dbc172012-09-05 23:34:03 +0000325 const MCExpr *getImm() const {
326 assert((Kind == k_Immediate) && "Invalid access!");
327 return Imm.Val;
328 }
329
Jack Carterdc1e35d2012-09-06 20:00:02 +0000330 unsigned getMemBase() const {
331 assert((Kind == k_Memory) && "Invalid access!");
332 return Mem.Base;
333 }
334
335 const MCExpr *getMemOff() const {
336 assert((Kind == k_Memory) && "Invalid access!");
337 return Mem.Off;
338 }
339
Jack Carterb4dbc172012-09-05 23:34:03 +0000340 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
341 MipsOperand *Op = new MipsOperand(k_Token);
342 Op->Tok.Data = Str.data();
343 Op->Tok.Length = Str.size();
344 Op->StartLoc = S;
345 Op->EndLoc = S;
346 return Op;
347 }
348
349 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
350 MipsOperand *Op = new MipsOperand(k_Register);
351 Op->Reg.RegNum = RegNum;
352 Op->StartLoc = S;
353 Op->EndLoc = E;
354 return Op;
355 }
356
357 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
358 MipsOperand *Op = new MipsOperand(k_Immediate);
359 Op->Imm.Val = Val;
360 Op->StartLoc = S;
361 Op->EndLoc = E;
362 return Op;
363 }
364
Jack Carterdc1e35d2012-09-06 20:00:02 +0000365 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
366 SMLoc S, SMLoc E) {
367 MipsOperand *Op = new MipsOperand(k_Memory);
368 Op->Mem.Base = Base;
369 Op->Mem.Off = Off;
370 Op->StartLoc = S;
371 Op->EndLoc = E;
372 return Op;
373 }
374
Jack Carter873c7242013-01-12 01:03:14 +0000375 bool isCPURegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000376 return Kind == k_Register && Reg.Kind == Kind_CPURegs;
Jack Carter873c7242013-01-12 01:03:14 +0000377 }
Vladimir Medicc6960592013-06-19 10:14:36 +0000378 void addRegAsmOperands(MCInst &Inst, unsigned N) const {
Jack Carter873c7242013-01-12 01:03:14 +0000379 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
380 }
381
382 bool isCPU64RegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000383 return Kind == k_Register && Reg.Kind == Kind_CPU64Regs;
Jack Carter873c7242013-01-12 01:03:14 +0000384 }
Jack Carter873c7242013-01-12 01:03:14 +0000385
386 bool isHWRegsAsm() const {
387 assert((Kind == k_Register) && "Invalid access!");
388 return Reg.Kind == Kind_HWRegs;
389 }
Jack Carter873c7242013-01-12 01:03:14 +0000390
391 bool isHW64RegsAsm() const {
392 assert((Kind == k_Register) && "Invalid access!");
393 return Reg.Kind == Kind_HW64Regs;
394 }
Jack Carter873c7242013-01-12 01:03:14 +0000395
396 bool isCCRAsm() const {
397 assert((Kind == k_Register) && "Invalid access!");
398 return Reg.Kind == Kind_CCRRegs;
399 }
400
Vladimir Medic233dd512013-06-24 10:05:34 +0000401 bool isAFGR64Asm() const {
402 return Kind == k_Register && Reg.Kind == Kind_AFGR64Regs;
403 }
404
405 bool isFGR64Asm() const {
406 return Kind == k_Register && Reg.Kind == Kind_FGR64Regs;
407 }
408
409 bool isFGR32Asm() const {
410 return (Kind == k_Register) && Reg.Kind == Kind_FGR32Regs;
411 }
412
Vladimir Medic643b3982013-07-30 10:12:14 +0000413 bool isFCCRegsAsm() const {
414 return (Kind == k_Register) && Reg.Kind == Kind_FCCRegs;
415 }
416
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000417 bool isACRegsDSPAsm() const {
418 return Kind == k_Register && Reg.Kind == Kind_ACRegsDSP;
419 }
420
Jack Carterb4dbc172012-09-05 23:34:03 +0000421 /// getStartLoc - Get the location of the first token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000422 SMLoc getStartLoc() const {
423 return StartLoc;
424 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000425 /// getEndLoc - Get the location of the last token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000426 SMLoc getEndLoc() const {
427 return EndLoc;
428 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000429
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000430 virtual void print(raw_ostream &OS) const {
431 llvm_unreachable("unimplemented!");
432 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000433}; // class MipsOperand
434} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000435
Jack Carter9e65aa32013-03-22 00:05:30 +0000436namespace llvm {
437extern const MCInstrDesc MipsInsts[];
438}
439static const MCInstrDesc &getInstDesc(unsigned Opcode) {
440 return MipsInsts[Opcode];
441}
442
443bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000444 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000445 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
446 Inst.setLoc(IDLoc);
Jack Carterc15c1d22013-04-25 23:31:35 +0000447 if (MCID.hasDelaySlot() && Options.isReorder()) {
448 // If this instruction has a delay slot and .set reorder is active,
449 // emit a NOP after it.
450 Instructions.push_back(Inst);
451 MCInst NopInst;
452 NopInst.setOpcode(Mips::SLL);
453 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
454 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
455 NopInst.addOperand(MCOperand::CreateImm(0));
456 Instructions.push_back(NopInst);
457 return false;
458 }
459
Jack Carter9e65aa32013-03-22 00:05:30 +0000460 if (MCID.mayLoad() || MCID.mayStore()) {
461 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000462 // reference or immediate we may have to expand instructions.
463 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000464 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Jack Carterd0bd6422013-04-18 00:41:53 +0000465 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY)
466 || (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000467 MCOperand &Op = Inst.getOperand(i);
468 if (Op.isImm()) {
469 int MemOffset = Op.getImm();
470 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000471 // Offset can't exceed 16bit value.
472 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000473 return false;
474 }
475 } else if (Op.isExpr()) {
476 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000477 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000478 const MCSymbolRefExpr *SR =
Jack Carterb5cf5902013-04-17 00:18:04 +0000479 static_cast<const MCSymbolRefExpr*>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000480 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000481 // Expand symbol.
482 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000483 return false;
484 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000485 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000486 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000487 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000488 }
489 }
490 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000491 } // for
492 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000493
494 if (needsExpansion(Inst))
495 expandInstruction(Inst, IDLoc, Instructions);
496 else
497 Instructions.push_back(Inst);
498
499 return false;
500}
501
Jack Carter30a59822012-10-04 04:03:53 +0000502bool MipsAsmParser::needsExpansion(MCInst &Inst) {
503
Jack Carterd0bd6422013-04-18 00:41:53 +0000504 switch (Inst.getOpcode()) {
505 case Mips::LoadImm32Reg:
506 case Mips::LoadAddr32Imm:
507 case Mips::LoadAddr32Reg:
508 return true;
509 default:
510 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000511 }
512}
Jack Carter92995f12012-10-06 00:53:28 +0000513
Jack Carter30a59822012-10-04 04:03:53 +0000514void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000515 SmallVectorImpl<MCInst> &Instructions) {
516 switch (Inst.getOpcode()) {
517 case Mips::LoadImm32Reg:
518 return expandLoadImm(Inst, IDLoc, Instructions);
519 case Mips::LoadAddr32Imm:
520 return expandLoadAddressImm(Inst, IDLoc, Instructions);
521 case Mips::LoadAddr32Reg:
522 return expandLoadAddressReg(Inst, IDLoc, Instructions);
523 }
Jack Carter30a59822012-10-04 04:03:53 +0000524}
Jack Carter92995f12012-10-06 00:53:28 +0000525
Jack Carter30a59822012-10-04 04:03:53 +0000526void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000527 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000528 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000529 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000530 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000531 const MCOperand &RegOp = Inst.getOperand(0);
532 assert(RegOp.isReg() && "expected register operand kind");
533
534 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000535 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000536 if (0 <= ImmValue && ImmValue <= 65535) {
537 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000538 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000539 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000540 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000541 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000542 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000543 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000544 } else if (ImmValue < 0 && ImmValue >= -32768) {
545 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000546 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000547 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000548 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000549 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000550 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000551 Instructions.push_back(tmpInst);
552 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000553 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000554 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000555 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000556 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000557 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
558 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000559 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000560 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000561 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000562 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
563 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
564 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
565 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000566 Instructions.push_back(tmpInst);
567 }
568}
Jack Carter92995f12012-10-06 00:53:28 +0000569
Jack Carter543fdf82012-10-09 23:29:45 +0000570void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000571 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000572 MCInst tmpInst;
573 const MCOperand &ImmOp = Inst.getOperand(2);
574 assert(ImmOp.isImm() && "expected immediate operand kind");
575 const MCOperand &SrcRegOp = Inst.getOperand(1);
576 assert(SrcRegOp.isReg() && "expected register operand kind");
577 const MCOperand &DstRegOp = Inst.getOperand(0);
578 assert(DstRegOp.isReg() && "expected register operand kind");
579 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000580 if (-32768 <= ImmValue && ImmValue <= 65535) {
581 // For -32768 <= j <= 65535.
582 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000583 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000584 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
585 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
586 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
587 Instructions.push_back(tmpInst);
588 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000589 // For any other value of j that is representable as a 32-bit integer.
590 // la d,j(s) => lui d,hi16(j)
591 // ori d,d,lo16(j)
592 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000593 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000594 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
595 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
596 Instructions.push_back(tmpInst);
597 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000598 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000599 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
600 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
601 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
602 Instructions.push_back(tmpInst);
603 tmpInst.clear();
604 tmpInst.setOpcode(Mips::ADDu);
605 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
606 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
607 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
608 Instructions.push_back(tmpInst);
609 }
610}
611
612void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000613 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000614 MCInst tmpInst;
615 const MCOperand &ImmOp = Inst.getOperand(1);
616 assert(ImmOp.isImm() && "expected immediate operand kind");
617 const MCOperand &RegOp = Inst.getOperand(0);
618 assert(RegOp.isReg() && "expected register operand kind");
619 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000620 if (-32768 <= ImmValue && ImmValue <= 65535) {
621 // For -32768 <= j <= 65535.
622 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +0000623 tmpInst.setOpcode(Mips::ADDiu);
624 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000625 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +0000626 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
627 Instructions.push_back(tmpInst);
628 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000629 // For any other value of j that is representable as a 32-bit integer.
630 // la d,j => lui d,hi16(j)
631 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000632 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000633 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
634 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
635 Instructions.push_back(tmpInst);
636 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000637 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000638 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
639 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
640 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
641 Instructions.push_back(tmpInst);
642 }
643}
644
Jack Carter9e65aa32013-03-22 00:05:30 +0000645void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000646 SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000647 const MCSymbolRefExpr *SR;
648 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +0000649 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +0000650 const MCExpr *ExprOffset;
651 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +0000652 unsigned AtRegNum = getReg((isMips64()) ? Mips::CPU64RegsRegClassID
653 : Mips::CPURegsRegClassID, getATReg());
654 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000655 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
656 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000657 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000658 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
659 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000660 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +0000661 if (isImmOpnd) {
662 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
663 ImmOffset = Inst.getOperand(2).getImm();
664 LoOffset = ImmOffset & 0x0000ffff;
665 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +0000666 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +0000667 if (LoOffset & 0x8000)
668 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +0000669 } else
Jack Carter9e65aa32013-03-22 00:05:30 +0000670 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000671 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +0000672 TempInst.setLoc(IDLoc);
673 // 1st instruction in expansion is LUi. For load instruction we can use
674 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +0000675 // but for stores we must use $at.
676 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +0000677 TempInst.setOpcode(Mips::LUi);
678 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
679 if (isImmOpnd)
680 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
681 else {
682 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
683 SR = static_cast<const MCSymbolRefExpr*>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +0000684 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
685 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
686 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000687 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000688 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000689 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +0000690 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000691 }
692 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000693 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +0000694 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000695 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +0000696 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +0000697 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000698 TempInst.setOpcode(Mips::ADDu);
699 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
700 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
701 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
702 Instructions.push_back(TempInst);
703 TempInst.clear();
Jack Carterb5cf5902013-04-17 00:18:04 +0000704 // And finaly, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +0000705 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000706 TempInst.setOpcode(Inst.getOpcode());
707 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
708 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
709 if (isImmOpnd)
710 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
711 else {
712 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000713 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
714 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
715 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000716 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000717 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000718 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +0000719 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000720 }
721 }
722 Instructions.push_back(TempInst);
723 TempInst.clear();
724}
725
Rafael Espindola870c4e92012-01-11 03:56:41 +0000726bool MipsAsmParser::
Chad Rosier49963552012-10-13 00:26:04 +0000727MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +0000728 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +0000729 MCStreamer &Out, unsigned &ErrorInfo,
730 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000731 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +0000732 SmallVector<MCInst, 8> Instructions;
Chad Rosier2f480a82012-10-12 22:53:36 +0000733 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier49963552012-10-13 00:26:04 +0000734 MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +0000735
736 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000737 default:
738 break;
Jack Carterb4dbc172012-09-05 23:34:03 +0000739 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000740 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +0000741 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +0000742 for (unsigned i = 0; i < Instructions.size(); i++)
Jack Carter9e65aa32013-03-22 00:05:30 +0000743 Out.EmitInstruction(Instructions[i]);
Jack Carterb4dbc172012-09-05 23:34:03 +0000744 return false;
745 }
746 case Match_MissingFeature:
747 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
748 return true;
749 case Match_InvalidOperand: {
750 SMLoc ErrorLoc = IDLoc;
751 if (ErrorInfo != ~0U) {
752 if (ErrorInfo >= Operands.size())
753 return Error(IDLoc, "too few operands for instruction");
754
Jack Carterd0bd6422013-04-18 00:41:53 +0000755 ErrorLoc = ((MipsOperand*) Operands[ErrorInfo])->getStartLoc();
756 if (ErrorLoc == SMLoc())
757 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +0000758 }
759
760 return Error(ErrorLoc, "invalid operand for instruction");
761 }
762 case Match_MnemonicFail:
763 return Error(IDLoc, "invalid instruction");
764 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000765 return true;
766}
767
Jack Carter1ac53222013-02-20 23:11:17 +0000768int MipsAsmParser::matchCPURegisterName(StringRef Name) {
769 int CC;
770
771 if (Name == "at")
772 return getATReg();
773
774 CC = StringSwitch<unsigned>(Name)
775 .Case("zero", 0)
776 .Case("a0", 4)
777 .Case("a1", 5)
778 .Case("a2", 6)
779 .Case("a3", 7)
780 .Case("v0", 2)
781 .Case("v1", 3)
782 .Case("s0", 16)
783 .Case("s1", 17)
784 .Case("s2", 18)
785 .Case("s3", 19)
786 .Case("s4", 20)
787 .Case("s5", 21)
788 .Case("s6", 22)
789 .Case("s7", 23)
790 .Case("k0", 26)
791 .Case("k1", 27)
792 .Case("sp", 29)
793 .Case("fp", 30)
794 .Case("gp", 28)
795 .Case("ra", 31)
796 .Case("t0", 8)
797 .Case("t1", 9)
798 .Case("t2", 10)
799 .Case("t3", 11)
800 .Case("t4", 12)
801 .Case("t5", 13)
802 .Case("t6", 14)
803 .Case("t7", 15)
804 .Case("t8", 24)
805 .Case("t9", 25)
806 .Default(-1);
807
Jack Carterd0bd6422013-04-18 00:41:53 +0000808 // Although SGI documentation just cuts out t0-t3 for n32/n64,
Jack Carter1ac53222013-02-20 23:11:17 +0000809 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
810 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
Jack Carterd0bd6422013-04-18 00:41:53 +0000811 if (isMips64() && 8 <= CC && CC <= 11)
Jack Carter1ac53222013-02-20 23:11:17 +0000812 CC += 4;
813
814 if (CC == -1 && isMips64())
815 CC = StringSwitch<unsigned>(Name)
816 .Case("a4", 8)
817 .Case("a5", 9)
818 .Case("a6", 10)
819 .Case("a7", 11)
820 .Case("kt0", 26)
821 .Case("kt1", 27)
822 .Case("s8", 30)
823 .Default(-1);
824
825 return CC;
826}
Jack Carterd0bd6422013-04-18 00:41:53 +0000827
Vladimir Medic8cd17102013-06-20 11:21:49 +0000828int MipsAsmParser::matchFPURegisterName(StringRef Name, FpFormatTy Format) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000829
Jack Cartera63b16a2012-09-07 00:23:42 +0000830 if (Name[0] == 'f') {
831 StringRef NumString = Name.substr(1);
832 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +0000833 if (NumString.getAsInteger(10, IntVal))
834 return -1; // This is not an integer.
Jack Cartera63b16a2012-09-07 00:23:42 +0000835 if (IntVal > 31)
836 return -1;
837
Jack Cartera63b16a2012-09-07 00:23:42 +0000838 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
839 return getReg(Mips::FGR32RegClassID, IntVal);
840 if (Format == FP_FORMAT_D) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000841 if (isFP64()) {
Jack Cartera63b16a2012-09-07 00:23:42 +0000842 return getReg(Mips::FGR64RegClassID, IntVal);
843 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000844 // Only even numbers available as register pairs.
845 if ((IntVal > 31) || (IntVal % 2 != 0))
Jack Cartera63b16a2012-09-07 00:23:42 +0000846 return -1;
Jack Carterd0bd6422013-04-18 00:41:53 +0000847 return getReg(Mips::AFGR64RegClassID, IntVal / 2);
Jack Cartera63b16a2012-09-07 00:23:42 +0000848 }
849 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000850 return -1;
851}
Jack Carterd0bd6422013-04-18 00:41:53 +0000852
Vladimir Medic8cd17102013-06-20 11:21:49 +0000853int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
854
855 if (Name.equals("fcc0"))
856 return Mips::FCC0;
857
858 int CC;
859 CC = matchCPURegisterName(Name);
860 if (CC != -1)
861 return matchRegisterByNumber(CC, is64BitReg ? Mips::CPU64RegsRegClassID
862 : Mips::CPURegsRegClassID);
863 return matchFPURegisterName(Name, getFpFormat());
864}
865
Jack Cartera63b16a2012-09-07 00:23:42 +0000866void MipsAsmParser::setDefaultFpFormat() {
867
868 if (isMips64() || isFP64())
869 FpFormat = FP_FORMAT_D;
870 else
871 FpFormat = FP_FORMAT_S;
872}
873
Jack Cartera63b16a2012-09-07 00:23:42 +0000874void MipsAsmParser::setFpFormat(StringRef Format) {
875
876 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
877 .Case(".s", FP_FORMAT_S)
878 .Case(".d", FP_FORMAT_D)
879 .Case(".l", FP_FORMAT_L)
880 .Case(".w", FP_FORMAT_W)
881 .Default(FP_FORMAT_NONE);
882}
Jack Carterb4dbc172012-09-05 23:34:03 +0000883
Jack Carter0b744b32012-10-04 02:29:46 +0000884bool MipsAssemblerOptions::setATReg(unsigned Reg) {
885 if (Reg > 31)
886 return false;
887
888 aTReg = Reg;
889 return true;
890}
891
Jack Carter1ac53222013-02-20 23:11:17 +0000892int MipsAsmParser::getATReg() {
893 return Options.getATRegNum();
Jack Carter0b744b32012-10-04 02:29:46 +0000894}
895
Jack Carterd0bd6422013-04-18 00:41:53 +0000896unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +0000897 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +0000898}
899
Jack Carter873c7242013-01-12 01:03:14 +0000900int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000901
902 if (RegNum > 31)
903 return -1;
904
Jack Carter873c7242013-01-12 01:03:14 +0000905 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +0000906}
907
Jack Carter873c7242013-01-12 01:03:14 +0000908int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000909 const AsmToken &Tok = Parser.getTok();
910 int RegNum = -1;
911
912 if (Tok.is(AsmToken::Identifier)) {
913 std::string lowerCase = Tok.getString().lower();
Jack Carter873c7242013-01-12 01:03:14 +0000914 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000915 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +0000916 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carterd0bd6422013-04-18 00:41:53 +0000917 is64BitReg ? Mips::CPU64RegsRegClassID : Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000918 return RegNum;
919}
920
Jack Carterd0bd6422013-04-18 00:41:53 +0000921bool MipsAsmParser::tryParseRegisterOperand(
922 SmallVectorImpl<MCParsedAsmOperand*> &Operands, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000923
924 SMLoc S = Parser.getTok().getLoc();
925 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +0000926
Jack Carter873c7242013-01-12 01:03:14 +0000927 RegNo = tryParseRegister(is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000928 if (RegNo == -1)
929 return true;
930
Jack Carter873c7242013-01-12 01:03:14 +0000931 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterd0bd6422013-04-18 00:41:53 +0000932 Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000933 Parser.Lex(); // Eat register token.
934 return false;
935}
936
937bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
938 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +0000939 // Check if the current operand has a custom associated parser, if so, try to
940 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +0000941 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
942 if (ResTy == MatchOperand_Success)
943 return false;
944 // If there wasn't a custom match, try the generic matcher below. Otherwise,
945 // there was a match, but an error occurred, in which case, just return that
946 // the operand parsing failed.
947 if (ResTy == MatchOperand_ParseFail)
948 return true;
949
950 switch (getLexer().getKind()) {
951 default:
952 Error(Parser.getTok().getLoc(), "unexpected token in operand");
953 return true;
954 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000955 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +0000956 SMLoc S = Parser.getTok().getLoc();
957 Parser.Lex(); // Eat dollar token.
Jack Carterd0bd6422013-04-18 00:41:53 +0000958 // Parse the register operand.
Jack Carter873c7242013-01-12 01:03:14 +0000959 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000960 if (getLexer().is(AsmToken::LParen)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000961 // Check if it is indexed addressing operand.
Jack Carterb4dbc172012-09-05 23:34:03 +0000962 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carterd0bd6422013-04-18 00:41:53 +0000963 Parser.Lex(); // Eat the parenthesis.
Jack Carterb4dbc172012-09-05 23:34:03 +0000964 if (getLexer().isNot(AsmToken::Dollar))
965 return true;
966
Jack Carterd0bd6422013-04-18 00:41:53 +0000967 Parser.Lex(); // Eat the dollar
Jack Carter873c7242013-01-12 01:03:14 +0000968 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterb4dbc172012-09-05 23:34:03 +0000969 return true;
970
971 if (!getLexer().is(AsmToken::RParen))
972 return true;
973
974 S = Parser.getTok().getLoc();
975 Operands.push_back(MipsOperand::CreateToken(")", S));
976 Parser.Lex();
977 }
978 return false;
979 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000980 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +0000981 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000982 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +0000983 return true;
984
Jack Carter873c7242013-01-12 01:03:14 +0000985 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000986
Benjamin Kramerfa530572012-09-07 09:47:42 +0000987 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterb4dbc172012-09-05 23:34:03 +0000988
Jack Carterd0bd6422013-04-18 00:41:53 +0000989 // Otherwise create a symbol reference.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000990 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterb4dbc172012-09-05 23:34:03 +0000991 getContext());
992
993 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
994 return false;
995 }
996 case AsmToken::Identifier:
Jack Carterd76b2372013-03-21 21:44:16 +0000997 // Look for the existing symbol, we should check if
Jack Carterd0bd6422013-04-18 00:41:53 +0000998 // we need to assigne the propper RegisterKind.
999 if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
1000 return false;
1001 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001002 case AsmToken::LParen:
1003 case AsmToken::Minus:
1004 case AsmToken::Plus:
1005 case AsmToken::Integer:
1006 case AsmToken::String: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001007 // Quoted label names.
Jack Carterb4dbc172012-09-05 23:34:03 +00001008 const MCExpr *IdVal;
1009 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001010 if (getParser().parseExpression(IdVal))
Jack Carterb4dbc172012-09-05 23:34:03 +00001011 return true;
Jack Carter873c7242013-01-12 01:03:14 +00001012 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001013 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1014 return false;
1015 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001016 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001017 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001018 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001019 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001020 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001021 return true;
1022
Jack Carter873c7242013-01-12 01:03:14 +00001023 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1024
Jack Carterdc1e35d2012-09-06 20:00:02 +00001025 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1026 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001027 } // case AsmToken::Percent
1028 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001029 return true;
1030}
1031
Jack Carterb5cf5902013-04-17 00:18:04 +00001032const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
1033 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001034 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001035 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001036 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001037 // It's a constant, evaluate lo or hi value.
Jack Carterb5cf5902013-04-17 00:18:04 +00001038 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001039 short Val = MCE->getValue();
1040 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001041 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001042 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001043 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001044 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001045 // Lower part is treated as a signed int, so if it is negative
Jack Carterd0bd6422013-04-18 00:41:53 +00001046 // we must add 1 to the hi part to compensate.
Jack Carterdc463382013-02-21 02:09:31 +00001047 if (LoSign)
1048 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001049 Res = MCConstantExpr::Create(Val, getContext());
Evgeniy Stepanov3d8ab192013-04-17 06:45:11 +00001050 } else {
1051 llvm_unreachable("Invalid RelocStr value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001052 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001053 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001054 }
1055
Jack Carterb5cf5902013-04-17 00:18:04 +00001056 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001057 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001058 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001059 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001060 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001061 return Res;
1062 }
1063
1064 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001065 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1066 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001067 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1068 return Res;
1069 }
1070
1071 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001072 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1073 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1074 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001075 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001076 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001077 return Expr;
1078}
1079
1080bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1081
1082 switch (Expr->getKind()) {
1083 case MCExpr::Constant:
1084 return true;
1085 case MCExpr::SymbolRef:
1086 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1087 case MCExpr::Binary:
1088 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1089 if (!isEvaluated(BE->getLHS()))
1090 return false;
1091 return isEvaluated(BE->getRHS());
1092 }
1093 case MCExpr::Unary:
1094 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1095 default:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001096 return false;
1097 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001098 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001099}
Jack Carterd0bd6422013-04-18 00:41:53 +00001100
Jack Carterb5cf5902013-04-17 00:18:04 +00001101bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001102 Parser.Lex(); // Eat the % token.
1103 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001104 if (Tok.isNot(AsmToken::Identifier))
1105 return true;
1106
1107 std::string Str = Tok.getIdentifier().str();
1108
Jack Carterd0bd6422013-04-18 00:41:53 +00001109 Parser.Lex(); // Eat the identifier.
1110 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001111 const MCExpr *IdVal;
1112 SMLoc EndLoc;
1113
1114 if (getLexer().getKind() == AsmToken::LParen) {
1115 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001116 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001117 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001118 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001119 const AsmToken &nextTok = Parser.getTok();
1120 if (nextTok.isNot(AsmToken::Identifier))
1121 return true;
1122 Str += "(%";
1123 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001124 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001125 if (getLexer().getKind() != AsmToken::LParen)
1126 return true;
1127 } else
1128 break;
1129 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001130 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001131 return true;
1132
1133 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001134 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001135
1136 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001137 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001138
Jack Carterd0bd6422013-04-18 00:41:53 +00001139 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001140 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001141}
1142
Jack Carterb4dbc172012-09-05 23:34:03 +00001143bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1144 SMLoc &EndLoc) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001145 StartLoc = Parser.getTok().getLoc();
Jack Carter873c7242013-01-12 01:03:14 +00001146 RegNo = tryParseRegister(isMips64());
1147 EndLoc = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001148 return (RegNo == (unsigned) -1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001149}
1150
Jack Carterb5cf5902013-04-17 00:18:04 +00001151bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001152 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001153 bool Result = true;
1154
1155 while (getLexer().getKind() == AsmToken::LParen)
1156 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001157
Jack Carterd0bd6422013-04-18 00:41:53 +00001158 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001159 default:
1160 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001161 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001162 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001163 case AsmToken::Integer:
1164 case AsmToken::Minus:
1165 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001166 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001167 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001168 else
1169 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001170 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001171 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001172 break;
Jack Carter873c7242013-01-12 01:03:14 +00001173 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001174 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001175 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001176 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001177}
1178
Jack Carterb4dbc172012-09-05 23:34:03 +00001179MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Jack Carterd0bd6422013-04-18 00:41:53 +00001180 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001181
1182 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001183 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001184 bool isParenExpr = false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001185 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001186 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001187
Jack Carterb5cf5902013-04-17 00:18:04 +00001188 if (getLexer().getKind() == AsmToken::LParen) {
1189 Parser.Lex();
1190 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001191 }
1192
Jack Carterb5cf5902013-04-17 00:18:04 +00001193 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001194 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001195 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001196
Jack Carterd0bd6422013-04-18 00:41:53 +00001197 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001198 if (Tok.isNot(AsmToken::LParen)) {
1199 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
1200 if (Mnemonic->getToken() == "la") {
1201 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001202 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001203 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1204 return MatchOperand_Success;
1205 }
1206 if (Tok.is(AsmToken::EndOfStatement)) {
1207 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001208 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001209
Jack Carterd0bd6422013-04-18 00:41:53 +00001210 // Zero register assumed, add a memory operand with ZERO as its base.
1211 Operands.push_back(MipsOperand::CreateMem(isMips64() ? Mips::ZERO_64
1212 : Mips::ZERO,
1213 IdVal, S, E));
Jack Carterb5cf5902013-04-17 00:18:04 +00001214 return MatchOperand_Success;
1215 }
1216 Error(Parser.getTok().getLoc(), "'(' expected");
1217 return MatchOperand_ParseFail;
1218 }
1219
Jack Carterd0bd6422013-04-18 00:41:53 +00001220 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001221 }
1222
1223 const AsmToken &Tok1 = Parser.getTok(); // Get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +00001224 if (Tok1.is(AsmToken::Dollar)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001225 Parser.Lex(); // Eat the '$' token.
Jack Carter873c7242013-01-12 01:03:14 +00001226 if (tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001227 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1228 return MatchOperand_ParseFail;
1229 }
1230
1231 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001232 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001233 return MatchOperand_ParseFail;
1234 }
1235
Jack Carterd0bd6422013-04-18 00:41:53 +00001236 const AsmToken &Tok2 = Parser.getTok(); // Get next token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001237 if (Tok2.isNot(AsmToken::RParen)) {
1238 Error(Parser.getTok().getLoc(), "')' expected");
1239 return MatchOperand_ParseFail;
1240 }
1241
Jack Carter873c7242013-01-12 01:03:14 +00001242 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1243
Jack Carterd0bd6422013-04-18 00:41:53 +00001244 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001245
1246 if (IdVal == 0)
1247 IdVal = MCConstantExpr::Create(0, getContext());
1248
Jack Carterd0bd6422013-04-18 00:41:53 +00001249 // Replace the register operand with the memory operand.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001250 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1251 int RegNo = op->getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001252 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001253 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001254 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001255 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1256 int64_t Imm;
1257 if (IdVal->EvaluateAsAbsolute(Imm))
1258 IdVal = MCConstantExpr::Create(Imm, getContext());
1259 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1260 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1261 getContext());
1262 }
1263
Jack Carterdc1e35d2012-09-06 20:00:02 +00001264 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1265 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +00001266 return MatchOperand_Success;
1267}
1268
Jack Carter873c7242013-01-12 01:03:14 +00001269MipsAsmParser::OperandMatchResultTy
Vladimir Medic8cd17102013-06-20 11:21:49 +00001270MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
1271 int RegKind) {
1272 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
Jack Carterd76b2372013-03-21 21:44:16 +00001273 if (getLexer().getKind() == AsmToken::Identifier) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001274 if (searchSymbolAlias(Operands, Kind))
Jack Carterd76b2372013-03-21 21:44:16 +00001275 return MatchOperand_Success;
1276 return MatchOperand_NoMatch;
1277 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001278 // If the first token is not '$', we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001279 if (Parser.getTok().isNot(AsmToken::Dollar))
1280 return MatchOperand_NoMatch;
1281
1282 Parser.Lex(); // Eat $
Akira Hatanaka34a32c02013-08-06 22:20:40 +00001283 if (!tryParseRegisterOperand(Operands,
1284 RegKind == MipsOperand::Kind_CPU64Regs)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001285 // Set the proper register kind.
Jack Carter873c7242013-01-12 01:03:14 +00001286 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
Vladimir Medic8cd17102013-06-20 11:21:49 +00001287 op->setRegKind(Kind);
Vladimir Medic3467b902013-07-18 09:28:35 +00001288 if ((Kind == MipsOperand::Kind_CPURegs)
1289 && (getLexer().is(AsmToken::LParen))) {
1290 // Check if it is indexed addressing operand.
1291 Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
1292 Parser.Lex(); // Eat the parenthesis.
1293 if (parseRegs(Operands,RegKind) != MatchOperand_Success)
1294 return MatchOperand_NoMatch;
1295 if (getLexer().isNot(AsmToken::RParen))
1296 return MatchOperand_NoMatch;
1297 Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
1298 Parser.Lex();
1299 }
Jack Carter873c7242013-01-12 01:03:14 +00001300 return MatchOperand_Success;
1301 }
1302 return MatchOperand_NoMatch;
1303}
Vladimir Medic64828a12013-07-16 10:07:14 +00001304
Vladimir Medic8cd17102013-06-20 11:21:49 +00001305MipsAsmParser::OperandMatchResultTy
1306MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1307
1308 if (!isMips64())
1309 return MatchOperand_NoMatch;
1310 return parseRegs(Operands, (int) MipsOperand::Kind_CPU64Regs);
1311}
1312
1313MipsAsmParser::OperandMatchResultTy
1314MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1315 return parseRegs(Operands, (int) MipsOperand::Kind_CPURegs);
1316}
Jack Carter873c7242013-01-12 01:03:14 +00001317
Vladimir Medic233dd512013-06-24 10:05:34 +00001318MipsAsmParser::OperandMatchResultTy
1319MipsAsmParser::parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1320
1321 if (isFP64())
1322 return MatchOperand_NoMatch;
1323 // Double operand is expected, set appropriate format
1324 setFpFormat(FP_FORMAT_D);
1325
1326 return parseRegs(Operands, (int) MipsOperand::Kind_AFGR64Regs);
1327}
1328
1329MipsAsmParser::OperandMatchResultTy
1330MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1331 if (!isFP64())
1332 return MatchOperand_NoMatch;
1333 // Double operand is expected, set appropriate format
1334 setFpFormat(FP_FORMAT_D);
1335
1336 return parseRegs(Operands, (int) MipsOperand::Kind_FGR64Regs);
1337}
1338
1339MipsAsmParser::OperandMatchResultTy
1340MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1341 // Single operand is expected, set appropriate format
1342 setFpFormat(FP_FORMAT_S);
1343 return parseRegs(Operands, (int) MipsOperand::Kind_FGR32Regs);
1344}
1345
Vladimir Medic643b3982013-07-30 10:12:14 +00001346MipsAsmParser::OperandMatchResultTy
1347MipsAsmParser::parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1348 // If the first token is not '$' we have an error.
1349 if (Parser.getTok().isNot(AsmToken::Dollar))
1350 return MatchOperand_NoMatch;
1351
1352 SMLoc S = Parser.getTok().getLoc();
1353 Parser.Lex(); // Eat the '$'
1354
1355 const AsmToken &Tok = Parser.getTok(); // Get next token.
1356
1357 if (Tok.isNot(AsmToken::Identifier))
1358 return MatchOperand_NoMatch;
1359
1360 if (!Tok.getIdentifier().startswith("fcc"))
1361 return MatchOperand_NoMatch;
1362
1363 StringRef NumString = Tok.getIdentifier().substr(3);
1364
1365 unsigned IntVal;
1366 if (NumString.getAsInteger(10, IntVal))
1367 return MatchOperand_NoMatch;
1368
1369 unsigned Reg = matchRegisterByNumber(IntVal, Mips::FCCRegClassID);
1370
1371 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
1372 Op->setRegKind(MipsOperand::Kind_FCCRegs);
1373 Operands.push_back(Op);
1374
1375 Parser.Lex(); // Eat the register number.
1376 return MatchOperand_Success;
1377}
1378
Akira Hatanaka34a32c02013-08-06 22:20:40 +00001379MipsAsmParser::OperandMatchResultTy
1380MipsAsmParser::parseACRegsDSP(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1381 // If the first token is not '$' we have an error.
1382 if (Parser.getTok().isNot(AsmToken::Dollar))
1383 return MatchOperand_NoMatch;
1384
1385 SMLoc S = Parser.getTok().getLoc();
1386 Parser.Lex(); // Eat the '$'
1387
1388 const AsmToken &Tok = Parser.getTok(); // Get next token.
1389
1390 if (Tok.isNot(AsmToken::Identifier))
1391 return MatchOperand_NoMatch;
1392
1393 if (!Tok.getIdentifier().startswith("acc"))
1394 return MatchOperand_NoMatch;
1395
1396 StringRef NumString = Tok.getIdentifier().substr(3);
1397
1398 unsigned IntVal;
1399 if (NumString.getAsInteger(10, IntVal))
1400 return MatchOperand_NoMatch;
1401
1402 unsigned Reg = matchRegisterByNumber(IntVal, Mips::ACRegsDSPRegClassID);
1403
1404 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
1405 Op->setRegKind(MipsOperand::Kind_ACRegsDSP);
1406 Operands.push_back(Op);
1407
1408 Parser.Lex(); // Eat the register number.
1409 return MatchOperand_Success;
1410}
1411
Jack Carterd0bd6422013-04-18 00:41:53 +00001412bool MipsAsmParser::searchSymbolAlias(
Vladimir Medic8cd17102013-06-20 11:21:49 +00001413 SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegKind) {
Jack Carterd76b2372013-03-21 21:44:16 +00001414
1415 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1416 if (Sym) {
1417 SMLoc S = Parser.getTok().getLoc();
1418 const MCExpr *Expr;
1419 if (Sym->isVariable())
1420 Expr = Sym->getVariableValue();
1421 else
1422 return false;
1423 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001424 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind) RegKind;
Jack Carterd76b2372013-03-21 21:44:16 +00001425 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
1426 const StringRef DefSymbol = Ref->getSymbol().getName();
1427 if (DefSymbol.startswith("$")) {
Jack Carter02593002013-05-28 22:21:05 +00001428 int RegNum = -1;
1429 APInt IntVal(32, -1);
1430 if (!DefSymbol.substr(1).getAsInteger(10, IntVal))
1431 RegNum = matchRegisterByNumber(IntVal.getZExtValue(),
Vladimir Medic64828a12013-07-16 10:07:14 +00001432 isMips64()
1433 ? Mips::CPU64RegsRegClassID
1434 : Mips::CPURegsRegClassID);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001435 else {
1436 // Lookup for the register with the corresponding name.
1437 switch (Kind) {
1438 case MipsOperand::Kind_AFGR64Regs:
1439 case MipsOperand::Kind_FGR64Regs:
1440 RegNum = matchFPURegisterName(DefSymbol.substr(1), FP_FORMAT_D);
1441 break;
1442 case MipsOperand::Kind_FGR32Regs:
1443 RegNum = matchFPURegisterName(DefSymbol.substr(1), FP_FORMAT_S);
1444 break;
1445 case MipsOperand::Kind_CPU64Regs:
1446 case MipsOperand::Kind_CPURegs:
1447 default:
1448 RegNum = matchRegisterName(DefSymbol.substr(1), isMips64());
1449 break;
1450 }
1451 }
Jack Carterd76b2372013-03-21 21:44:16 +00001452 if (RegNum > -1) {
1453 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001454 MipsOperand *op = MipsOperand::CreateReg(RegNum, S,
1455 Parser.getTok().getLoc());
Vladimir Medic8cd17102013-06-20 11:21:49 +00001456 op->setRegKind(Kind);
Jack Carterd76b2372013-03-21 21:44:16 +00001457 Operands.push_back(op);
1458 return true;
1459 }
1460 }
1461 } else if (Expr->getKind() == MCExpr::Constant) {
1462 Parser.Lex();
1463 const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001464 MipsOperand *op = MipsOperand::CreateImm(Const, S,
Vladimir Medic64828a12013-07-16 10:07:14 +00001465 Parser.getTok().getLoc());
Jack Carterd76b2372013-03-21 21:44:16 +00001466 Operands.push_back(op);
1467 return true;
1468 }
1469 }
1470 return false;
1471}
Jack Carterd0bd6422013-04-18 00:41:53 +00001472
Jack Carter873c7242013-01-12 01:03:14 +00001473MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +00001474MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1475
Jack Carter2a74a87b2013-01-17 00:28:20 +00001476 if (isMips64())
1477 return MatchOperand_NoMatch;
1478
Jack Carterd0bd6422013-04-18 00:41:53 +00001479 // If the first token is not '$' we have error.
Jack Carter873c7242013-01-12 01:03:14 +00001480 if (Parser.getTok().isNot(AsmToken::Dollar))
1481 return MatchOperand_NoMatch;
1482 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001483 Parser.Lex(); // Eat the '$'.
Jack Carter873c7242013-01-12 01:03:14 +00001484
Jack Carterd0bd6422013-04-18 00:41:53 +00001485 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001486 if (Tok.isNot(AsmToken::Integer))
1487 return MatchOperand_NoMatch;
1488
1489 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001490 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001491 if (RegNum != 29)
1492 return MatchOperand_ParseFail;
1493
1494 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001495 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001496 op->setRegKind(MipsOperand::Kind_HWRegs);
1497 Operands.push_back(op);
1498
Jack Carterd0bd6422013-04-18 00:41:53 +00001499 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001500 return MatchOperand_Success;
1501}
1502
1503MipsAsmParser::OperandMatchResultTy
Jack Carterd0bd6422013-04-18 00:41:53 +00001504MipsAsmParser::parseHW64Regs(
1505 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter2a74a87b2013-01-17 00:28:20 +00001506
1507 if (!isMips64())
1508 return MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001509 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001510 if (Parser.getTok().isNot(AsmToken::Dollar))
1511 return MatchOperand_NoMatch;
1512 SMLoc S = Parser.getTok().getLoc();
1513 Parser.Lex(); // Eat $
1514
Jack Carterd0bd6422013-04-18 00:41:53 +00001515 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001516 if (Tok.isNot(AsmToken::Integer))
1517 return MatchOperand_NoMatch;
1518
1519 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001520 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001521 if (RegNum != 29)
1522 return MatchOperand_ParseFail;
1523
1524 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001525 Parser.getTok().getLoc());
Jack Carter2a74a87b2013-01-17 00:28:20 +00001526 op->setRegKind(MipsOperand::Kind_HW64Regs);
Jack Carter873c7242013-01-12 01:03:14 +00001527 Operands.push_back(op);
1528
Jack Carterd0bd6422013-04-18 00:41:53 +00001529 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001530 return MatchOperand_Success;
1531}
1532
1533MipsAsmParser::OperandMatchResultTy
1534MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001535 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001536 if (Parser.getTok().isNot(AsmToken::Dollar))
Akira Hatanakadade526a2013-07-24 18:43:52 +00001537 return MatchOperand_NoMatch;
Akira Hatanaka4d2ea3c2013-07-22 19:30:38 +00001538
Jack Carter873c7242013-01-12 01:03:14 +00001539 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001540 Parser.Lex(); // Eat the '$'
Jack Carter873c7242013-01-12 01:03:14 +00001541
Jack Carterd0bd6422013-04-18 00:41:53 +00001542 const AsmToken &Tok = Parser.getTok(); // Get next token.
Jack Carter873c7242013-01-12 01:03:14 +00001543
Akira Hatanaka4d2ea3c2013-07-22 19:30:38 +00001544 if (Tok.isNot(AsmToken::Integer))
Akira Hatanakadade526a2013-07-24 18:43:52 +00001545 return MatchOperand_NoMatch;
Akira Hatanaka4d2ea3c2013-07-22 19:30:38 +00001546
1547 unsigned Reg = matchRegisterByNumber(Tok.getIntVal(), Mips::CCRRegClassID);
1548
1549 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
1550 Op->setRegKind(MipsOperand::Kind_CCRRegs);
1551 Operands.push_back(Op);
Jack Carter873c7242013-01-12 01:03:14 +00001552
Jack Carterd0bd6422013-04-18 00:41:53 +00001553 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001554 return MatchOperand_Success;
1555}
1556
Jack Carterdc1e35d2012-09-06 20:00:02 +00001557MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1558
1559 MCSymbolRefExpr::VariantKind VK
1560 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1561 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1562 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1563 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1564 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1565 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1566 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1567 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1568 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1569 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1570 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1571 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1572 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1573 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1574 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1575 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1576 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1577 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1578 .Default(MCSymbolRefExpr::VK_None);
1579
1580 return VK;
1581}
Jack Cartera63b16a2012-09-07 00:23:42 +00001582
Rafael Espindola870c4e92012-01-11 03:56:41 +00001583bool MipsAsmParser::
Chad Rosierf0e87202012-10-25 20:41:34 +00001584ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindola870c4e92012-01-11 03:56:41 +00001585 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic74593e62013-07-17 15:00:42 +00001586 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00001587 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00001588 Parser.eatToEndOfStatement();
1589 return Error(NameLoc, "Unknown instruction");
1590 }
Vladimir Medic64828a12013-07-16 10:07:14 +00001591 // First operand in MCInst is instruction mnemonic.
1592 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterb4dbc172012-09-05 23:34:03 +00001593
1594 // Read the remaining operands.
1595 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1596 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00001597 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001598 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001599 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001600 return Error(Loc, "unexpected token in argument list");
1601 }
1602
Jack Carterd0bd6422013-04-18 00:41:53 +00001603 while (getLexer().is(AsmToken::Comma)) {
1604 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00001605 // Parse and remember the operand.
1606 if (ParseOperand(Operands, Name)) {
1607 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001608 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001609 return Error(Loc, "unexpected token in argument list");
1610 }
1611 }
1612 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001613 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1614 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001615 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001616 return Error(Loc, "unexpected token in argument list");
1617 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001618 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00001619 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00001620}
1621
Jack Carter0b744b32012-10-04 02:29:46 +00001622bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001623 SMLoc Loc = getLexer().getLoc();
1624 Parser.eatToEndOfStatement();
1625 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00001626}
1627
1628bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001629 // Line should look like: ".set noat".
1630 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00001631 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00001632 // eat noat
1633 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001634 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001635 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1636 reportParseError("unexpected token in statement");
1637 return false;
1638 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001639 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001640 return false;
1641}
Jack Carterd0bd6422013-04-18 00:41:53 +00001642
Jack Carter0b744b32012-10-04 02:29:46 +00001643bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001644 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00001645 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00001646 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00001647 getParser().Lex();
1648 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00001649 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00001650 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001651 return false;
1652 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001653 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00001654 if (getLexer().isNot(AsmToken::Dollar)) {
1655 reportParseError("unexpected token in statement");
1656 return false;
1657 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001658 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00001659 const AsmToken &Reg = Parser.getTok();
1660 if (Reg.is(AsmToken::Identifier)) {
1661 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
1662 } else if (Reg.is(AsmToken::Integer)) {
1663 AtRegNo = Reg.getIntVal();
1664 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001665 reportParseError("unexpected token in statement");
1666 return false;
1667 }
Jack Carter1ac53222013-02-20 23:11:17 +00001668
Jack Carterd0bd6422013-04-18 00:41:53 +00001669 if (AtRegNo < 1 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00001670 reportParseError("unexpected token in statement");
1671 return false;
1672 }
1673
1674 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00001675 reportParseError("unexpected token in statement");
1676 return false;
1677 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001678 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00001679
1680 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1681 reportParseError("unexpected token in statement");
1682 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001683 }
1684 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001685 return false;
1686 } else {
1687 reportParseError("unexpected token in statement");
1688 return false;
1689 }
1690}
1691
1692bool MipsAsmParser::parseSetReorderDirective() {
1693 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001694 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001695 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1696 reportParseError("unexpected token in statement");
1697 return false;
1698 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001699 Options.setReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00001700 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001701 return false;
1702}
1703
1704bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001705 Parser.Lex();
1706 // If this is not the end of the statement, report an error.
1707 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1708 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00001709 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001710 }
1711 Options.setNoreorder();
1712 Parser.Lex(); // Consume the EndOfStatement.
1713 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001714}
1715
1716bool MipsAsmParser::parseSetMacroDirective() {
1717 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001718 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001719 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1720 reportParseError("unexpected token in statement");
1721 return false;
1722 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001723 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001724 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001725 return false;
1726}
1727
1728bool MipsAsmParser::parseSetNoMacroDirective() {
1729 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001730 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001731 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1732 reportParseError("`noreorder' must be set before `nomacro'");
1733 return false;
1734 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001735 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00001736 reportParseError("`noreorder' must be set before `nomacro'");
1737 return false;
1738 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001739 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001740 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001741 return false;
1742}
Jack Carterd76b2372013-03-21 21:44:16 +00001743
1744bool MipsAsmParser::parseSetAssignment() {
1745 StringRef Name;
1746 const MCExpr *Value;
1747
1748 if (Parser.parseIdentifier(Name))
1749 reportParseError("expected identifier after .set");
1750
1751 if (getLexer().isNot(AsmToken::Comma))
1752 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00001753 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00001754
Jack Carter02593002013-05-28 22:21:05 +00001755 if (getLexer().is(AsmToken::Dollar)) {
1756 MCSymbol *Symbol;
1757 SMLoc DollarLoc = getLexer().getLoc();
1758 // Consume the dollar sign, and check for a following identifier.
1759 Parser.Lex();
1760 // We have a '$' followed by something, make sure they are adjacent.
1761 if (DollarLoc.getPointer() + 1 != getTok().getLoc().getPointer())
1762 return true;
1763 StringRef Res = StringRef(DollarLoc.getPointer(),
1764 getTok().getEndLoc().getPointer() - DollarLoc.getPointer());
1765 Symbol = getContext().GetOrCreateSymbol(Res);
1766 Parser.Lex();
1767 Value = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
1768 getContext());
1769 } else if (Parser.parseExpression(Value))
1770 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00001771
Jack Carterd0bd6422013-04-18 00:41:53 +00001772 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00001773 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00001774 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00001775 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00001776 Sym = getContext().GetOrCreateSymbol(Name);
1777 Sym->setVariableValue(Value);
1778
1779 return false;
1780}
Jack Carterd0bd6422013-04-18 00:41:53 +00001781
Jack Carter0b744b32012-10-04 02:29:46 +00001782bool MipsAsmParser::parseDirectiveSet() {
1783
Jack Carterd0bd6422013-04-18 00:41:53 +00001784 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00001785 const AsmToken &Tok = Parser.getTok();
1786
1787 if (Tok.getString() == "noat") {
1788 return parseSetNoAtDirective();
1789 } else if (Tok.getString() == "at") {
1790 return parseSetAtDirective();
1791 } else if (Tok.getString() == "reorder") {
1792 return parseSetReorderDirective();
1793 } else if (Tok.getString() == "noreorder") {
1794 return parseSetNoReorderDirective();
1795 } else if (Tok.getString() == "macro") {
1796 return parseSetMacroDirective();
1797 } else if (Tok.getString() == "nomacro") {
1798 return parseSetNoMacroDirective();
1799 } else if (Tok.getString() == "nomips16") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001800 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001801 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001802 return false;
1803 } else if (Tok.getString() == "nomicromips") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001804 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001805 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001806 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001807 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001808 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00001809 parseSetAssignment();
1810 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001811 }
Jack Carter07c818d2013-01-25 01:31:34 +00001812
Jack Carter0b744b32012-10-04 02:29:46 +00001813 return true;
1814}
1815
Jack Carter07c818d2013-01-25 01:31:34 +00001816/// parseDirectiveWord
1817/// ::= .word [ expression (, expression)* ]
1818bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
1819 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1820 for (;;) {
1821 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001822 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00001823 return true;
1824
1825 getParser().getStreamer().EmitValue(Value, Size);
1826
1827 if (getLexer().is(AsmToken::EndOfStatement))
1828 break;
1829
1830 // FIXME: Improve diagnostic.
1831 if (getLexer().isNot(AsmToken::Comma))
1832 return Error(L, "unexpected token in directive");
1833 Parser.Lex();
1834 }
1835 }
1836
1837 Parser.Lex();
1838 return false;
1839}
1840
Jack Carter0b744b32012-10-04 02:29:46 +00001841bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +00001842
Jack Carter07c818d2013-01-25 01:31:34 +00001843 StringRef IDVal = DirectiveID.getString();
1844
Jack Carterd0bd6422013-04-18 00:41:53 +00001845 if (IDVal == ".ent") {
1846 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001847 Parser.Lex();
1848 return false;
1849 }
1850
Jack Carter07c818d2013-01-25 01:31:34 +00001851 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001852 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001853 Parser.Lex();
1854 return false;
1855 }
1856
Jack Carter07c818d2013-01-25 01:31:34 +00001857 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001858 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001859 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001860 return false;
1861 }
1862
Jack Carter07c818d2013-01-25 01:31:34 +00001863 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00001864 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00001865 }
1866
Jack Carter07c818d2013-01-25 01:31:34 +00001867 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001868 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001869 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001870 return false;
1871 }
1872
Jack Carter07c818d2013-01-25 01:31:34 +00001873 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001874 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001875 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001876 return false;
1877 }
1878
Jack Carter07c818d2013-01-25 01:31:34 +00001879 if (IDVal == ".gpword") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001880 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001881 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001882 return false;
1883 }
1884
Jack Carter07c818d2013-01-25 01:31:34 +00001885 if (IDVal == ".word") {
1886 parseDirectiveWord(4, DirectiveID.getLoc());
1887 return false;
1888 }
1889
Rafael Espindola870c4e92012-01-11 03:56:41 +00001890 return true;
1891}
1892
Rafael Espindola870c4e92012-01-11 03:56:41 +00001893extern "C" void LLVMInitializeMipsAsmParser() {
1894 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1895 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1896 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1897 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1898}
Jack Carterb4dbc172012-09-05 23:34:03 +00001899
1900#define GET_REGISTER_MATCHER
1901#define GET_MATCHER_IMPLEMENTATION
1902#include "MipsGenAsmMatcher.inc"