blob: 56a5dfdafbdd64ba3a384a7988fc53b3f734c222 [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
Jack Carterd76b2372013-03-21 21:44:16 +0000114 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Vladimir Medic8cd17102013-06-20 11:21:49 +0000115 unsigned RegKind);
Jack Carterd76b2372013-03-21 21:44:16 +0000116
Jack Carterb4dbc172012-09-05 23:34:03 +0000117 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
118 StringRef Mnemonic);
119
Jack Carter873c7242013-01-12 01:03:14 +0000120 int tryParseRegister(bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000121
122 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carter873c7242013-01-12 01:03:14 +0000123 bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000124
Jack Carter30a59822012-10-04 04:03:53 +0000125 bool needsExpansion(MCInst &Inst);
126
127 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000128 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000129 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000130 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000131 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
132 SmallVectorImpl<MCInst> &Instructions);
133 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
134 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000135 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
136 SmallVectorImpl<MCInst> &Instructions,
137 bool isLoad,bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000138 bool reportParseError(StringRef ErrorMsg);
139
Jack Carterb5cf5902013-04-17 00:18:04 +0000140 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000141 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000142
Jack Carterb5cf5902013-04-17 00:18:04 +0000143 const MCExpr* evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
144
145 bool isEvaluated(const MCExpr *Expr);
Jack Carter0b744b32012-10-04 02:29:46 +0000146 bool parseDirectiveSet();
147
148 bool parseSetAtDirective();
149 bool parseSetNoAtDirective();
150 bool parseSetMacroDirective();
151 bool parseSetNoMacroDirective();
152 bool parseSetReorderDirective();
153 bool parseSetNoReorderDirective();
154
Jack Carterd76b2372013-03-21 21:44:16 +0000155 bool parseSetAssignment();
156
Jack Carter07c818d2013-01-25 01:31:34 +0000157 bool parseDirectiveWord(unsigned Size, SMLoc L);
158
Jack Carterdc1e35d2012-09-06 20:00:02 +0000159 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000160
Jack Carterb4dbc172012-09-05 23:34:03 +0000161 bool isMips64() const {
162 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
163 }
164
Jack Cartera63b16a2012-09-07 00:23:42 +0000165 bool isFP64() const {
166 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
167 }
168
Jack Carter873c7242013-01-12 01:03:14 +0000169 int matchRegisterName(StringRef Symbol, bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000170
Jack Carter1ac53222013-02-20 23:11:17 +0000171 int matchCPURegisterName(StringRef Symbol);
172
Jack Carter873c7242013-01-12 01:03:14 +0000173 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000174
Vladimir Medic8cd17102013-06-20 11:21:49 +0000175 int matchFPURegisterName(StringRef Name, FpFormatTy Format);
176
Jack Cartera63b16a2012-09-07 00:23:42 +0000177 void setFpFormat(FpFormatTy Format) {
178 FpFormat = Format;
179 }
180
181 void setDefaultFpFormat();
182
183 void setFpFormat(StringRef Format);
184
185 FpFormatTy getFpFormat() {return FpFormat;}
186
Jack Carterd0bd6422013-04-18 00:41:53 +0000187 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000188
Jack Carter1ac53222013-02-20 23:11:17 +0000189 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000190
191 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
192 SmallVectorImpl<MCInst> &Instructions);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000193public:
194 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterb4dbc172012-09-05 23:34:03 +0000195 : MCTargetAsmParser(), STI(sti), Parser(parser) {
196 // Initialize the set of available features.
197 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindola870c4e92012-01-11 03:56:41 +0000198 }
199
Jack Carterb4dbc172012-09-05 23:34:03 +0000200 MCAsmParser &getParser() const { return Parser; }
201 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
202
Rafael Espindola870c4e92012-01-11 03:56:41 +0000203};
204}
205
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000206namespace {
207
208/// MipsOperand - Instances of this class represent a parsed Mips machine
209/// instruction.
210class MipsOperand : public MCParsedAsmOperand {
Jack Carterb4dbc172012-09-05 23:34:03 +0000211
Jack Carter873c7242013-01-12 01:03:14 +0000212public:
213 enum RegisterKind {
214 Kind_None,
215 Kind_CPURegs,
216 Kind_CPU64Regs,
217 Kind_HWRegs,
218 Kind_HW64Regs,
219 Kind_FGR32Regs,
220 Kind_FGR64Regs,
Jack Carter1ac53222013-02-20 23:11:17 +0000221 Kind_AFGR64Regs,
Jack Carter873c7242013-01-12 01:03:14 +0000222 Kind_CCRRegs
223 };
224
225private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000226 enum KindTy {
227 k_CondCode,
228 k_CoprocNum,
229 k_Immediate,
230 k_Memory,
231 k_PostIndexRegister,
232 k_Register,
233 k_Token
234 } Kind;
235
236 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterb4dbc172012-09-05 23:34:03 +0000237
Eric Christopher8996c5d2013-03-15 00:42:55 +0000238 struct Token {
239 const char *Data;
240 unsigned Length;
241 };
242
243 struct RegOp {
244 unsigned RegNum;
245 RegisterKind Kind;
246 };
247
248 struct ImmOp {
249 const MCExpr *Val;
250 };
251
252 struct MemOp {
253 unsigned Base;
254 const MCExpr *Off;
255 };
256
Jack Carterb4dbc172012-09-05 23:34:03 +0000257 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000258 struct Token Tok;
259 struct RegOp Reg;
260 struct ImmOp Imm;
261 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000262 };
263
264 SMLoc StartLoc, EndLoc;
265
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000266public:
267 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000268 assert(N == 1 && "Invalid number of operands!");
269 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000270 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000271
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000272 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterb4dbc172012-09-05 23:34:03 +0000273 // Add as immediate when possible. Null MCExpr = 0.
274 if (Expr == 0)
275 Inst.addOperand(MCOperand::CreateImm(0));
276 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
277 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
278 else
279 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000280 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000281
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000282 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000283 assert(N == 1 && "Invalid number of operands!");
284 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000285 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000286 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000287
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000288 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000289 assert(N == 2 && "Invalid number of operands!");
290
291 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
292
293 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000294 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000295 }
296
297 bool isReg() const { return Kind == k_Register; }
298 bool isImm() const { return Kind == k_Immediate; }
299 bool isToken() const { return Kind == k_Token; }
300 bool isMem() const { return Kind == k_Memory; }
301
302 StringRef getToken() const {
303 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000304 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000305 }
306
307 unsigned getReg() const {
308 assert((Kind == k_Register) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000309 return Reg.RegNum;
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000310 }
311
Jack Carter873c7242013-01-12 01:03:14 +0000312 void setRegKind(RegisterKind RegKind) {
313 assert((Kind == k_Register) && "Invalid access!");
314 Reg.Kind = RegKind;
315 }
316
Jack Carterb4dbc172012-09-05 23:34:03 +0000317 const MCExpr *getImm() const {
318 assert((Kind == k_Immediate) && "Invalid access!");
319 return Imm.Val;
320 }
321
Jack Carterdc1e35d2012-09-06 20:00:02 +0000322 unsigned getMemBase() const {
323 assert((Kind == k_Memory) && "Invalid access!");
324 return Mem.Base;
325 }
326
327 const MCExpr *getMemOff() const {
328 assert((Kind == k_Memory) && "Invalid access!");
329 return Mem.Off;
330 }
331
Jack Carterb4dbc172012-09-05 23:34:03 +0000332 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
333 MipsOperand *Op = new MipsOperand(k_Token);
334 Op->Tok.Data = Str.data();
335 Op->Tok.Length = Str.size();
336 Op->StartLoc = S;
337 Op->EndLoc = S;
338 return Op;
339 }
340
341 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
342 MipsOperand *Op = new MipsOperand(k_Register);
343 Op->Reg.RegNum = RegNum;
344 Op->StartLoc = S;
345 Op->EndLoc = E;
346 return Op;
347 }
348
349 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
350 MipsOperand *Op = new MipsOperand(k_Immediate);
351 Op->Imm.Val = Val;
352 Op->StartLoc = S;
353 Op->EndLoc = E;
354 return Op;
355 }
356
Jack Carterdc1e35d2012-09-06 20:00:02 +0000357 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
358 SMLoc S, SMLoc E) {
359 MipsOperand *Op = new MipsOperand(k_Memory);
360 Op->Mem.Base = Base;
361 Op->Mem.Off = Off;
362 Op->StartLoc = S;
363 Op->EndLoc = E;
364 return Op;
365 }
366
Jack Carter873c7242013-01-12 01:03:14 +0000367 bool isCPURegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000368 return Kind == k_Register && Reg.Kind == Kind_CPURegs;
Jack Carter873c7242013-01-12 01:03:14 +0000369 }
Vladimir Medicc6960592013-06-19 10:14:36 +0000370 void addRegAsmOperands(MCInst &Inst, unsigned N) const {
Jack Carter873c7242013-01-12 01:03:14 +0000371 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
372 }
373
374 bool isCPU64RegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000375 return Kind == k_Register && Reg.Kind == Kind_CPU64Regs;
Jack Carter873c7242013-01-12 01:03:14 +0000376 }
Jack Carter873c7242013-01-12 01:03:14 +0000377
378 bool isHWRegsAsm() const {
379 assert((Kind == k_Register) && "Invalid access!");
380 return Reg.Kind == Kind_HWRegs;
381 }
Jack Carter873c7242013-01-12 01:03:14 +0000382
383 bool isHW64RegsAsm() const {
384 assert((Kind == k_Register) && "Invalid access!");
385 return Reg.Kind == Kind_HW64Regs;
386 }
Jack Carter873c7242013-01-12 01:03:14 +0000387
388 bool isCCRAsm() const {
389 assert((Kind == k_Register) && "Invalid access!");
390 return Reg.Kind == Kind_CCRRegs;
391 }
392
Vladimir Medic233dd512013-06-24 10:05:34 +0000393 bool isAFGR64Asm() const {
394 return Kind == k_Register && Reg.Kind == Kind_AFGR64Regs;
395 }
396
397 bool isFGR64Asm() const {
398 return Kind == k_Register && Reg.Kind == Kind_FGR64Regs;
399 }
400
401 bool isFGR32Asm() const {
402 return (Kind == k_Register) && Reg.Kind == Kind_FGR32Regs;
403 }
404
Jack Carterb4dbc172012-09-05 23:34:03 +0000405 /// getStartLoc - Get the location of the first token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000406 SMLoc getStartLoc() const {
407 return StartLoc;
408 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000409 /// getEndLoc - Get the location of the last token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000410 SMLoc getEndLoc() const {
411 return EndLoc;
412 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000413
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000414 virtual void print(raw_ostream &OS) const {
415 llvm_unreachable("unimplemented!");
416 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000417}; // class MipsOperand
418} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000419
Jack Carter9e65aa32013-03-22 00:05:30 +0000420namespace llvm {
421extern const MCInstrDesc MipsInsts[];
422}
423static const MCInstrDesc &getInstDesc(unsigned Opcode) {
424 return MipsInsts[Opcode];
425}
426
427bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000428 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000429 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
430 Inst.setLoc(IDLoc);
Jack Carterc15c1d22013-04-25 23:31:35 +0000431 if (MCID.hasDelaySlot() && Options.isReorder()) {
432 // If this instruction has a delay slot and .set reorder is active,
433 // emit a NOP after it.
434 Instructions.push_back(Inst);
435 MCInst NopInst;
436 NopInst.setOpcode(Mips::SLL);
437 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
438 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
439 NopInst.addOperand(MCOperand::CreateImm(0));
440 Instructions.push_back(NopInst);
441 return false;
442 }
443
Jack Carter9e65aa32013-03-22 00:05:30 +0000444 if (MCID.mayLoad() || MCID.mayStore()) {
445 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000446 // reference or immediate we may have to expand instructions.
447 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000448 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Jack Carterd0bd6422013-04-18 00:41:53 +0000449 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY)
450 || (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000451 MCOperand &Op = Inst.getOperand(i);
452 if (Op.isImm()) {
453 int MemOffset = Op.getImm();
454 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000455 // Offset can't exceed 16bit value.
456 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000457 return false;
458 }
459 } else if (Op.isExpr()) {
460 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000461 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000462 const MCSymbolRefExpr *SR =
Jack Carterb5cf5902013-04-17 00:18:04 +0000463 static_cast<const MCSymbolRefExpr*>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000464 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000465 // Expand symbol.
466 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000467 return false;
468 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000469 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000470 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000471 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000472 }
473 }
474 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000475 } // for
476 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000477
478 if (needsExpansion(Inst))
479 expandInstruction(Inst, IDLoc, Instructions);
480 else
481 Instructions.push_back(Inst);
482
483 return false;
484}
485
Jack Carter30a59822012-10-04 04:03:53 +0000486bool MipsAsmParser::needsExpansion(MCInst &Inst) {
487
Jack Carterd0bd6422013-04-18 00:41:53 +0000488 switch (Inst.getOpcode()) {
489 case Mips::LoadImm32Reg:
490 case Mips::LoadAddr32Imm:
491 case Mips::LoadAddr32Reg:
492 return true;
493 default:
494 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000495 }
496}
Jack Carter92995f12012-10-06 00:53:28 +0000497
Jack Carter30a59822012-10-04 04:03:53 +0000498void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000499 SmallVectorImpl<MCInst> &Instructions) {
500 switch (Inst.getOpcode()) {
501 case Mips::LoadImm32Reg:
502 return expandLoadImm(Inst, IDLoc, Instructions);
503 case Mips::LoadAddr32Imm:
504 return expandLoadAddressImm(Inst, IDLoc, Instructions);
505 case Mips::LoadAddr32Reg:
506 return expandLoadAddressReg(Inst, IDLoc, Instructions);
507 }
Jack Carter30a59822012-10-04 04:03:53 +0000508}
Jack Carter92995f12012-10-06 00:53:28 +0000509
Jack Carter30a59822012-10-04 04:03:53 +0000510void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000511 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000512 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000513 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000514 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000515 const MCOperand &RegOp = Inst.getOperand(0);
516 assert(RegOp.isReg() && "expected register operand kind");
517
518 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000519 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000520 if (0 <= ImmValue && ImmValue <= 65535) {
521 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000522 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000523 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000524 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000525 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000526 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000527 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000528 } else if (ImmValue < 0 && ImmValue >= -32768) {
529 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000530 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000531 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000532 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000533 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000534 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000535 Instructions.push_back(tmpInst);
536 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000537 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000538 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000539 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000540 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000541 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
542 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000543 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000544 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000545 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000546 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
547 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
548 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
549 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000550 Instructions.push_back(tmpInst);
551 }
552}
Jack Carter92995f12012-10-06 00:53:28 +0000553
Jack Carter543fdf82012-10-09 23:29:45 +0000554void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000555 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000556 MCInst tmpInst;
557 const MCOperand &ImmOp = Inst.getOperand(2);
558 assert(ImmOp.isImm() && "expected immediate operand kind");
559 const MCOperand &SrcRegOp = Inst.getOperand(1);
560 assert(SrcRegOp.isReg() && "expected register operand kind");
561 const MCOperand &DstRegOp = Inst.getOperand(0);
562 assert(DstRegOp.isReg() && "expected register operand kind");
563 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000564 if (-32768 <= ImmValue && ImmValue <= 65535) {
565 // For -32768 <= j <= 65535.
566 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000567 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000568 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
569 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
570 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
571 Instructions.push_back(tmpInst);
572 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000573 // For any other value of j that is representable as a 32-bit integer.
574 // la d,j(s) => lui d,hi16(j)
575 // ori d,d,lo16(j)
576 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000577 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000578 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
579 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
580 Instructions.push_back(tmpInst);
581 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000582 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000583 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
584 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
585 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
586 Instructions.push_back(tmpInst);
587 tmpInst.clear();
588 tmpInst.setOpcode(Mips::ADDu);
589 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
590 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
591 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
592 Instructions.push_back(tmpInst);
593 }
594}
595
596void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000597 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000598 MCInst tmpInst;
599 const MCOperand &ImmOp = Inst.getOperand(1);
600 assert(ImmOp.isImm() && "expected immediate operand kind");
601 const MCOperand &RegOp = Inst.getOperand(0);
602 assert(RegOp.isReg() && "expected register operand kind");
603 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000604 if (-32768 <= ImmValue && ImmValue <= 65535) {
605 // For -32768 <= j <= 65535.
606 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +0000607 tmpInst.setOpcode(Mips::ADDiu);
608 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000609 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +0000610 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
611 Instructions.push_back(tmpInst);
612 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000613 // For any other value of j that is representable as a 32-bit integer.
614 // la d,j => lui d,hi16(j)
615 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000616 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000617 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
618 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
619 Instructions.push_back(tmpInst);
620 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000621 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000622 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
623 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
624 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
625 Instructions.push_back(tmpInst);
626 }
627}
628
Jack Carter9e65aa32013-03-22 00:05:30 +0000629void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000630 SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000631 const MCSymbolRefExpr *SR;
632 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +0000633 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +0000634 const MCExpr *ExprOffset;
635 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +0000636 unsigned AtRegNum = getReg((isMips64()) ? Mips::CPU64RegsRegClassID
637 : Mips::CPURegsRegClassID, getATReg());
638 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000639 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
640 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000641 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000642 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
643 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000644 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +0000645 if (isImmOpnd) {
646 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
647 ImmOffset = Inst.getOperand(2).getImm();
648 LoOffset = ImmOffset & 0x0000ffff;
649 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +0000650 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +0000651 if (LoOffset & 0x8000)
652 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +0000653 } else
Jack Carter9e65aa32013-03-22 00:05:30 +0000654 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000655 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +0000656 TempInst.setLoc(IDLoc);
657 // 1st instruction in expansion is LUi. For load instruction we can use
658 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +0000659 // but for stores we must use $at.
660 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +0000661 TempInst.setOpcode(Mips::LUi);
662 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
663 if (isImmOpnd)
664 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
665 else {
666 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
667 SR = static_cast<const MCSymbolRefExpr*>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +0000668 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
669 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
670 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000671 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000672 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000673 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +0000674 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000675 }
676 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000677 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +0000678 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000679 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +0000680 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +0000681 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000682 TempInst.setOpcode(Mips::ADDu);
683 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
684 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
685 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
686 Instructions.push_back(TempInst);
687 TempInst.clear();
Jack Carterb5cf5902013-04-17 00:18:04 +0000688 // And finaly, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +0000689 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000690 TempInst.setOpcode(Inst.getOpcode());
691 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
692 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
693 if (isImmOpnd)
694 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
695 else {
696 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000697 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
698 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
699 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000700 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000701 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000702 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +0000703 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000704 }
705 }
706 Instructions.push_back(TempInst);
707 TempInst.clear();
708}
709
Rafael Espindola870c4e92012-01-11 03:56:41 +0000710bool MipsAsmParser::
Chad Rosier49963552012-10-13 00:26:04 +0000711MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +0000712 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +0000713 MCStreamer &Out, unsigned &ErrorInfo,
714 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000715 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +0000716 SmallVector<MCInst, 8> Instructions;
Chad Rosier2f480a82012-10-12 22:53:36 +0000717 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier49963552012-10-13 00:26:04 +0000718 MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +0000719
720 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000721 default:
722 break;
Jack Carterb4dbc172012-09-05 23:34:03 +0000723 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000724 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +0000725 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +0000726 for (unsigned i = 0; i < Instructions.size(); i++)
Jack Carter9e65aa32013-03-22 00:05:30 +0000727 Out.EmitInstruction(Instructions[i]);
Jack Carterb4dbc172012-09-05 23:34:03 +0000728 return false;
729 }
730 case Match_MissingFeature:
731 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
732 return true;
733 case Match_InvalidOperand: {
734 SMLoc ErrorLoc = IDLoc;
735 if (ErrorInfo != ~0U) {
736 if (ErrorInfo >= Operands.size())
737 return Error(IDLoc, "too few operands for instruction");
738
Jack Carterd0bd6422013-04-18 00:41:53 +0000739 ErrorLoc = ((MipsOperand*) Operands[ErrorInfo])->getStartLoc();
740 if (ErrorLoc == SMLoc())
741 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +0000742 }
743
744 return Error(ErrorLoc, "invalid operand for instruction");
745 }
746 case Match_MnemonicFail:
747 return Error(IDLoc, "invalid instruction");
748 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000749 return true;
750}
751
Jack Carter1ac53222013-02-20 23:11:17 +0000752int MipsAsmParser::matchCPURegisterName(StringRef Name) {
753 int CC;
754
755 if (Name == "at")
756 return getATReg();
757
758 CC = StringSwitch<unsigned>(Name)
759 .Case("zero", 0)
760 .Case("a0", 4)
761 .Case("a1", 5)
762 .Case("a2", 6)
763 .Case("a3", 7)
764 .Case("v0", 2)
765 .Case("v1", 3)
766 .Case("s0", 16)
767 .Case("s1", 17)
768 .Case("s2", 18)
769 .Case("s3", 19)
770 .Case("s4", 20)
771 .Case("s5", 21)
772 .Case("s6", 22)
773 .Case("s7", 23)
774 .Case("k0", 26)
775 .Case("k1", 27)
776 .Case("sp", 29)
777 .Case("fp", 30)
778 .Case("gp", 28)
779 .Case("ra", 31)
780 .Case("t0", 8)
781 .Case("t1", 9)
782 .Case("t2", 10)
783 .Case("t3", 11)
784 .Case("t4", 12)
785 .Case("t5", 13)
786 .Case("t6", 14)
787 .Case("t7", 15)
788 .Case("t8", 24)
789 .Case("t9", 25)
790 .Default(-1);
791
Jack Carterd0bd6422013-04-18 00:41:53 +0000792 // Although SGI documentation just cuts out t0-t3 for n32/n64,
Jack Carter1ac53222013-02-20 23:11:17 +0000793 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
794 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
Jack Carterd0bd6422013-04-18 00:41:53 +0000795 if (isMips64() && 8 <= CC && CC <= 11)
Jack Carter1ac53222013-02-20 23:11:17 +0000796 CC += 4;
797
798 if (CC == -1 && isMips64())
799 CC = StringSwitch<unsigned>(Name)
800 .Case("a4", 8)
801 .Case("a5", 9)
802 .Case("a6", 10)
803 .Case("a7", 11)
804 .Case("kt0", 26)
805 .Case("kt1", 27)
806 .Case("s8", 30)
807 .Default(-1);
808
809 return CC;
810}
Jack Carterd0bd6422013-04-18 00:41:53 +0000811
Vladimir Medic8cd17102013-06-20 11:21:49 +0000812int MipsAsmParser::matchFPURegisterName(StringRef Name, FpFormatTy Format) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000813
Jack Cartera63b16a2012-09-07 00:23:42 +0000814 if (Name[0] == 'f') {
815 StringRef NumString = Name.substr(1);
816 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +0000817 if (NumString.getAsInteger(10, IntVal))
818 return -1; // This is not an integer.
Jack Cartera63b16a2012-09-07 00:23:42 +0000819 if (IntVal > 31)
820 return -1;
821
Jack Cartera63b16a2012-09-07 00:23:42 +0000822 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
823 return getReg(Mips::FGR32RegClassID, IntVal);
824 if (Format == FP_FORMAT_D) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000825 if (isFP64()) {
Jack Cartera63b16a2012-09-07 00:23:42 +0000826 return getReg(Mips::FGR64RegClassID, IntVal);
827 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000828 // Only even numbers available as register pairs.
829 if ((IntVal > 31) || (IntVal % 2 != 0))
Jack Cartera63b16a2012-09-07 00:23:42 +0000830 return -1;
Jack Carterd0bd6422013-04-18 00:41:53 +0000831 return getReg(Mips::AFGR64RegClassID, IntVal / 2);
Jack Cartera63b16a2012-09-07 00:23:42 +0000832 }
833 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000834 return -1;
835}
Jack Carterd0bd6422013-04-18 00:41:53 +0000836
Vladimir Medic8cd17102013-06-20 11:21:49 +0000837int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
838
839 if (Name.equals("fcc0"))
840 return Mips::FCC0;
841
842 int CC;
843 CC = matchCPURegisterName(Name);
844 if (CC != -1)
845 return matchRegisterByNumber(CC, is64BitReg ? Mips::CPU64RegsRegClassID
846 : Mips::CPURegsRegClassID);
847 return matchFPURegisterName(Name, getFpFormat());
848}
849
Jack Cartera63b16a2012-09-07 00:23:42 +0000850void MipsAsmParser::setDefaultFpFormat() {
851
852 if (isMips64() || isFP64())
853 FpFormat = FP_FORMAT_D;
854 else
855 FpFormat = FP_FORMAT_S;
856}
857
Jack Cartera63b16a2012-09-07 00:23:42 +0000858void MipsAsmParser::setFpFormat(StringRef Format) {
859
860 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
861 .Case(".s", FP_FORMAT_S)
862 .Case(".d", FP_FORMAT_D)
863 .Case(".l", FP_FORMAT_L)
864 .Case(".w", FP_FORMAT_W)
865 .Default(FP_FORMAT_NONE);
866}
Jack Carterb4dbc172012-09-05 23:34:03 +0000867
Jack Carter0b744b32012-10-04 02:29:46 +0000868bool MipsAssemblerOptions::setATReg(unsigned Reg) {
869 if (Reg > 31)
870 return false;
871
872 aTReg = Reg;
873 return true;
874}
875
Jack Carter1ac53222013-02-20 23:11:17 +0000876int MipsAsmParser::getATReg() {
877 return Options.getATRegNum();
Jack Carter0b744b32012-10-04 02:29:46 +0000878}
879
Jack Carterd0bd6422013-04-18 00:41:53 +0000880unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +0000881 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +0000882}
883
Jack Carter873c7242013-01-12 01:03:14 +0000884int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000885
886 if (RegNum > 31)
887 return -1;
888
Jack Carter873c7242013-01-12 01:03:14 +0000889 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +0000890}
891
Jack Carter873c7242013-01-12 01:03:14 +0000892int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000893 const AsmToken &Tok = Parser.getTok();
894 int RegNum = -1;
895
896 if (Tok.is(AsmToken::Identifier)) {
897 std::string lowerCase = Tok.getString().lower();
Jack Carter873c7242013-01-12 01:03:14 +0000898 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000899 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +0000900 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carterd0bd6422013-04-18 00:41:53 +0000901 is64BitReg ? Mips::CPU64RegsRegClassID : Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000902 return RegNum;
903}
904
Jack Carterd0bd6422013-04-18 00:41:53 +0000905bool MipsAsmParser::tryParseRegisterOperand(
906 SmallVectorImpl<MCParsedAsmOperand*> &Operands, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000907
908 SMLoc S = Parser.getTok().getLoc();
909 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +0000910
Jack Carter873c7242013-01-12 01:03:14 +0000911 RegNo = tryParseRegister(is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000912 if (RegNo == -1)
913 return true;
914
Jack Carter873c7242013-01-12 01:03:14 +0000915 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterd0bd6422013-04-18 00:41:53 +0000916 Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000917 Parser.Lex(); // Eat register token.
918 return false;
919}
920
921bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
922 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +0000923 // Check if the current operand has a custom associated parser, if so, try to
924 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +0000925 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
926 if (ResTy == MatchOperand_Success)
927 return false;
928 // If there wasn't a custom match, try the generic matcher below. Otherwise,
929 // there was a match, but an error occurred, in which case, just return that
930 // the operand parsing failed.
931 if (ResTy == MatchOperand_ParseFail)
932 return true;
933
934 switch (getLexer().getKind()) {
935 default:
936 Error(Parser.getTok().getLoc(), "unexpected token in operand");
937 return true;
938 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000939 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +0000940 SMLoc S = Parser.getTok().getLoc();
941 Parser.Lex(); // Eat dollar token.
Jack Carterd0bd6422013-04-18 00:41:53 +0000942 // Parse the register operand.
Jack Carter873c7242013-01-12 01:03:14 +0000943 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000944 if (getLexer().is(AsmToken::LParen)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000945 // Check if it is indexed addressing operand.
Jack Carterb4dbc172012-09-05 23:34:03 +0000946 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carterd0bd6422013-04-18 00:41:53 +0000947 Parser.Lex(); // Eat the parenthesis.
Jack Carterb4dbc172012-09-05 23:34:03 +0000948 if (getLexer().isNot(AsmToken::Dollar))
949 return true;
950
Jack Carterd0bd6422013-04-18 00:41:53 +0000951 Parser.Lex(); // Eat the dollar
Jack Carter873c7242013-01-12 01:03:14 +0000952 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterb4dbc172012-09-05 23:34:03 +0000953 return true;
954
955 if (!getLexer().is(AsmToken::RParen))
956 return true;
957
958 S = Parser.getTok().getLoc();
959 Operands.push_back(MipsOperand::CreateToken(")", S));
960 Parser.Lex();
961 }
962 return false;
963 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000964 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +0000965 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000966 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +0000967 return true;
968
Jack Carter873c7242013-01-12 01:03:14 +0000969 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000970
Benjamin Kramerfa530572012-09-07 09:47:42 +0000971 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterb4dbc172012-09-05 23:34:03 +0000972
Jack Carterd0bd6422013-04-18 00:41:53 +0000973 // Otherwise create a symbol reference.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000974 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterb4dbc172012-09-05 23:34:03 +0000975 getContext());
976
977 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
978 return false;
979 }
980 case AsmToken::Identifier:
Jack Carterd76b2372013-03-21 21:44:16 +0000981 // Look for the existing symbol, we should check if
Jack Carterd0bd6422013-04-18 00:41:53 +0000982 // we need to assigne the propper RegisterKind.
983 if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
984 return false;
985 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +0000986 case AsmToken::LParen:
987 case AsmToken::Minus:
988 case AsmToken::Plus:
989 case AsmToken::Integer:
990 case AsmToken::String: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000991 // Quoted label names.
Jack Carterb4dbc172012-09-05 23:34:03 +0000992 const MCExpr *IdVal;
993 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000994 if (getParser().parseExpression(IdVal))
Jack Carterb4dbc172012-09-05 23:34:03 +0000995 return true;
Jack Carter873c7242013-01-12 01:03:14 +0000996 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000997 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
998 return false;
999 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001000 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001001 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001002 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001003 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001004 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001005 return true;
1006
Jack Carter873c7242013-01-12 01:03:14 +00001007 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1008
Jack Carterdc1e35d2012-09-06 20:00:02 +00001009 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1010 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001011 } // case AsmToken::Percent
1012 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001013 return true;
1014}
1015
Jack Carterb5cf5902013-04-17 00:18:04 +00001016const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
1017 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001018 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001019 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001020 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001021 // It's a constant, evaluate lo or hi value.
Jack Carterb5cf5902013-04-17 00:18:04 +00001022 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001023 short Val = MCE->getValue();
1024 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001025 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001026 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001027 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001028 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001029 // Lower part is treated as a signed int, so if it is negative
Jack Carterd0bd6422013-04-18 00:41:53 +00001030 // we must add 1 to the hi part to compensate.
Jack Carterdc463382013-02-21 02:09:31 +00001031 if (LoSign)
1032 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001033 Res = MCConstantExpr::Create(Val, getContext());
Evgeniy Stepanov3d8ab192013-04-17 06:45:11 +00001034 } else {
1035 llvm_unreachable("Invalid RelocStr value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001036 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001037 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001038 }
1039
Jack Carterb5cf5902013-04-17 00:18:04 +00001040 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001041 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001042 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001043 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001044 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001045 return Res;
1046 }
1047
1048 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001049 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1050 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001051 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1052 return Res;
1053 }
1054
1055 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001056 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1057 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1058 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001059 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001060 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001061 return Expr;
1062}
1063
1064bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1065
1066 switch (Expr->getKind()) {
1067 case MCExpr::Constant:
1068 return true;
1069 case MCExpr::SymbolRef:
1070 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1071 case MCExpr::Binary:
1072 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1073 if (!isEvaluated(BE->getLHS()))
1074 return false;
1075 return isEvaluated(BE->getRHS());
1076 }
1077 case MCExpr::Unary:
1078 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1079 default:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001080 return false;
1081 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001082 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001083}
Jack Carterd0bd6422013-04-18 00:41:53 +00001084
Jack Carterb5cf5902013-04-17 00:18:04 +00001085bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001086 Parser.Lex(); // Eat the % token.
1087 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001088 if (Tok.isNot(AsmToken::Identifier))
1089 return true;
1090
1091 std::string Str = Tok.getIdentifier().str();
1092
Jack Carterd0bd6422013-04-18 00:41:53 +00001093 Parser.Lex(); // Eat the identifier.
1094 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001095 const MCExpr *IdVal;
1096 SMLoc EndLoc;
1097
1098 if (getLexer().getKind() == AsmToken::LParen) {
1099 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001100 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001101 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001102 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001103 const AsmToken &nextTok = Parser.getTok();
1104 if (nextTok.isNot(AsmToken::Identifier))
1105 return true;
1106 Str += "(%";
1107 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001108 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001109 if (getLexer().getKind() != AsmToken::LParen)
1110 return true;
1111 } else
1112 break;
1113 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001114 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001115 return true;
1116
1117 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001118 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001119
1120 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001121 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001122
Jack Carterd0bd6422013-04-18 00:41:53 +00001123 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001124 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001125}
1126
Jack Carterb4dbc172012-09-05 23:34:03 +00001127bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1128 SMLoc &EndLoc) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001129 StartLoc = Parser.getTok().getLoc();
Jack Carter873c7242013-01-12 01:03:14 +00001130 RegNo = tryParseRegister(isMips64());
1131 EndLoc = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001132 return (RegNo == (unsigned) -1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001133}
1134
Jack Carterb5cf5902013-04-17 00:18:04 +00001135bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001136 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001137 bool Result = true;
1138
1139 while (getLexer().getKind() == AsmToken::LParen)
1140 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001141
Jack Carterd0bd6422013-04-18 00:41:53 +00001142 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001143 default:
1144 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001145 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001146 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001147 case AsmToken::Integer:
1148 case AsmToken::Minus:
1149 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001150 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001151 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001152 else
1153 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001154 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001155 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001156 break;
Jack Carter873c7242013-01-12 01:03:14 +00001157 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001158 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001159 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001160 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001161}
1162
Jack Carterb4dbc172012-09-05 23:34:03 +00001163MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Jack Carterd0bd6422013-04-18 00:41:53 +00001164 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001165
1166 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001167 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001168 bool isParenExpr = false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001169 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001170 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001171
Jack Carterb5cf5902013-04-17 00:18:04 +00001172 if (getLexer().getKind() == AsmToken::LParen) {
1173 Parser.Lex();
1174 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001175 }
1176
Jack Carterb5cf5902013-04-17 00:18:04 +00001177 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001178 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001179 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001180
Jack Carterd0bd6422013-04-18 00:41:53 +00001181 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001182 if (Tok.isNot(AsmToken::LParen)) {
1183 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
1184 if (Mnemonic->getToken() == "la") {
1185 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001186 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001187 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1188 return MatchOperand_Success;
1189 }
1190 if (Tok.is(AsmToken::EndOfStatement)) {
1191 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001192 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001193
Jack Carterd0bd6422013-04-18 00:41:53 +00001194 // Zero register assumed, add a memory operand with ZERO as its base.
1195 Operands.push_back(MipsOperand::CreateMem(isMips64() ? Mips::ZERO_64
1196 : Mips::ZERO,
1197 IdVal, S, E));
Jack Carterb5cf5902013-04-17 00:18:04 +00001198 return MatchOperand_Success;
1199 }
1200 Error(Parser.getTok().getLoc(), "'(' expected");
1201 return MatchOperand_ParseFail;
1202 }
1203
Jack Carterd0bd6422013-04-18 00:41:53 +00001204 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001205 }
1206
1207 const AsmToken &Tok1 = Parser.getTok(); // Get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +00001208 if (Tok1.is(AsmToken::Dollar)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001209 Parser.Lex(); // Eat the '$' token.
Jack Carter873c7242013-01-12 01:03:14 +00001210 if (tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001211 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1212 return MatchOperand_ParseFail;
1213 }
1214
1215 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001216 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001217 return MatchOperand_ParseFail;
1218 }
1219
Jack Carterd0bd6422013-04-18 00:41:53 +00001220 const AsmToken &Tok2 = Parser.getTok(); // Get next token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001221 if (Tok2.isNot(AsmToken::RParen)) {
1222 Error(Parser.getTok().getLoc(), "')' expected");
1223 return MatchOperand_ParseFail;
1224 }
1225
Jack Carter873c7242013-01-12 01:03:14 +00001226 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1227
Jack Carterd0bd6422013-04-18 00:41:53 +00001228 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001229
1230 if (IdVal == 0)
1231 IdVal = MCConstantExpr::Create(0, getContext());
1232
Jack Carterd0bd6422013-04-18 00:41:53 +00001233 // Replace the register operand with the memory operand.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001234 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1235 int RegNo = op->getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001236 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001237 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001238 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001239 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1240 int64_t Imm;
1241 if (IdVal->EvaluateAsAbsolute(Imm))
1242 IdVal = MCConstantExpr::Create(Imm, getContext());
1243 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1244 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1245 getContext());
1246 }
1247
Jack Carterdc1e35d2012-09-06 20:00:02 +00001248 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1249 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +00001250 return MatchOperand_Success;
1251}
1252
Jack Carter873c7242013-01-12 01:03:14 +00001253MipsAsmParser::OperandMatchResultTy
Vladimir Medic8cd17102013-06-20 11:21:49 +00001254MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
1255 int RegKind) {
1256 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
Jack Carterd76b2372013-03-21 21:44:16 +00001257 if (getLexer().getKind() == AsmToken::Identifier) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001258 if (searchSymbolAlias(Operands, Kind))
Jack Carterd76b2372013-03-21 21:44:16 +00001259 return MatchOperand_Success;
1260 return MatchOperand_NoMatch;
1261 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001262 // If the first token is not '$', we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001263 if (Parser.getTok().isNot(AsmToken::Dollar))
1264 return MatchOperand_NoMatch;
1265
1266 Parser.Lex(); // Eat $
Vladimir Medic8cd17102013-06-20 11:21:49 +00001267 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001268 // Set the proper register kind.
Jack Carter873c7242013-01-12 01:03:14 +00001269 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
Vladimir Medic8cd17102013-06-20 11:21:49 +00001270 op->setRegKind(Kind);
Vladimir Medic3467b902013-07-18 09:28:35 +00001271 if ((Kind == MipsOperand::Kind_CPURegs)
1272 && (getLexer().is(AsmToken::LParen))) {
1273 // Check if it is indexed addressing operand.
1274 Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
1275 Parser.Lex(); // Eat the parenthesis.
1276 if (parseRegs(Operands,RegKind) != MatchOperand_Success)
1277 return MatchOperand_NoMatch;
1278 if (getLexer().isNot(AsmToken::RParen))
1279 return MatchOperand_NoMatch;
1280 Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
1281 Parser.Lex();
1282 }
Jack Carter873c7242013-01-12 01:03:14 +00001283 return MatchOperand_Success;
1284 }
1285 return MatchOperand_NoMatch;
1286}
Vladimir Medic64828a12013-07-16 10:07:14 +00001287
Vladimir Medic8cd17102013-06-20 11:21:49 +00001288MipsAsmParser::OperandMatchResultTy
1289MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1290
1291 if (!isMips64())
1292 return MatchOperand_NoMatch;
1293 return parseRegs(Operands, (int) MipsOperand::Kind_CPU64Regs);
1294}
1295
1296MipsAsmParser::OperandMatchResultTy
1297MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1298 return parseRegs(Operands, (int) MipsOperand::Kind_CPURegs);
1299}
Jack Carter873c7242013-01-12 01:03:14 +00001300
Vladimir Medic233dd512013-06-24 10:05:34 +00001301MipsAsmParser::OperandMatchResultTy
1302MipsAsmParser::parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1303
1304 if (isFP64())
1305 return MatchOperand_NoMatch;
1306 // Double operand is expected, set appropriate format
1307 setFpFormat(FP_FORMAT_D);
1308
1309 return parseRegs(Operands, (int) MipsOperand::Kind_AFGR64Regs);
1310}
1311
1312MipsAsmParser::OperandMatchResultTy
1313MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1314 if (!isFP64())
1315 return MatchOperand_NoMatch;
1316 // Double operand is expected, set appropriate format
1317 setFpFormat(FP_FORMAT_D);
1318
1319 return parseRegs(Operands, (int) MipsOperand::Kind_FGR64Regs);
1320}
1321
1322MipsAsmParser::OperandMatchResultTy
1323MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1324 // Single operand is expected, set appropriate format
1325 setFpFormat(FP_FORMAT_S);
1326 return parseRegs(Operands, (int) MipsOperand::Kind_FGR32Regs);
1327}
1328
Jack Carterd0bd6422013-04-18 00:41:53 +00001329bool MipsAsmParser::searchSymbolAlias(
Vladimir Medic8cd17102013-06-20 11:21:49 +00001330 SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegKind) {
Jack Carterd76b2372013-03-21 21:44:16 +00001331
1332 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1333 if (Sym) {
1334 SMLoc S = Parser.getTok().getLoc();
1335 const MCExpr *Expr;
1336 if (Sym->isVariable())
1337 Expr = Sym->getVariableValue();
1338 else
1339 return false;
1340 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001341 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind) RegKind;
Jack Carterd76b2372013-03-21 21:44:16 +00001342 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
1343 const StringRef DefSymbol = Ref->getSymbol().getName();
1344 if (DefSymbol.startswith("$")) {
Jack Carter02593002013-05-28 22:21:05 +00001345 int RegNum = -1;
1346 APInt IntVal(32, -1);
1347 if (!DefSymbol.substr(1).getAsInteger(10, IntVal))
1348 RegNum = matchRegisterByNumber(IntVal.getZExtValue(),
Vladimir Medic64828a12013-07-16 10:07:14 +00001349 isMips64()
1350 ? Mips::CPU64RegsRegClassID
1351 : Mips::CPURegsRegClassID);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001352 else {
1353 // Lookup for the register with the corresponding name.
1354 switch (Kind) {
1355 case MipsOperand::Kind_AFGR64Regs:
1356 case MipsOperand::Kind_FGR64Regs:
1357 RegNum = matchFPURegisterName(DefSymbol.substr(1), FP_FORMAT_D);
1358 break;
1359 case MipsOperand::Kind_FGR32Regs:
1360 RegNum = matchFPURegisterName(DefSymbol.substr(1), FP_FORMAT_S);
1361 break;
1362 case MipsOperand::Kind_CPU64Regs:
1363 case MipsOperand::Kind_CPURegs:
1364 default:
1365 RegNum = matchRegisterName(DefSymbol.substr(1), isMips64());
1366 break;
1367 }
1368 }
Jack Carterd76b2372013-03-21 21:44:16 +00001369 if (RegNum > -1) {
1370 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001371 MipsOperand *op = MipsOperand::CreateReg(RegNum, S,
1372 Parser.getTok().getLoc());
Vladimir Medic8cd17102013-06-20 11:21:49 +00001373 op->setRegKind(Kind);
Jack Carterd76b2372013-03-21 21:44:16 +00001374 Operands.push_back(op);
1375 return true;
1376 }
1377 }
1378 } else if (Expr->getKind() == MCExpr::Constant) {
1379 Parser.Lex();
1380 const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001381 MipsOperand *op = MipsOperand::CreateImm(Const, S,
Vladimir Medic64828a12013-07-16 10:07:14 +00001382 Parser.getTok().getLoc());
Jack Carterd76b2372013-03-21 21:44:16 +00001383 Operands.push_back(op);
1384 return true;
1385 }
1386 }
1387 return false;
1388}
Jack Carterd0bd6422013-04-18 00:41:53 +00001389
Jack Carter873c7242013-01-12 01:03:14 +00001390MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +00001391MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1392
Jack Carter2a74a87b2013-01-17 00:28:20 +00001393 if (isMips64())
1394 return MatchOperand_NoMatch;
1395
Jack Carterd0bd6422013-04-18 00:41:53 +00001396 // If the first token is not '$' we have error.
Jack Carter873c7242013-01-12 01:03:14 +00001397 if (Parser.getTok().isNot(AsmToken::Dollar))
1398 return MatchOperand_NoMatch;
1399 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001400 Parser.Lex(); // Eat the '$'.
Jack Carter873c7242013-01-12 01:03:14 +00001401
Jack Carterd0bd6422013-04-18 00:41:53 +00001402 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001403 if (Tok.isNot(AsmToken::Integer))
1404 return MatchOperand_NoMatch;
1405
1406 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001407 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001408 if (RegNum != 29)
1409 return MatchOperand_ParseFail;
1410
1411 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001412 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001413 op->setRegKind(MipsOperand::Kind_HWRegs);
1414 Operands.push_back(op);
1415
Jack Carterd0bd6422013-04-18 00:41:53 +00001416 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001417 return MatchOperand_Success;
1418}
1419
1420MipsAsmParser::OperandMatchResultTy
Jack Carterd0bd6422013-04-18 00:41:53 +00001421MipsAsmParser::parseHW64Regs(
1422 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter2a74a87b2013-01-17 00:28:20 +00001423
1424 if (!isMips64())
1425 return MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001426 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001427 if (Parser.getTok().isNot(AsmToken::Dollar))
1428 return MatchOperand_NoMatch;
1429 SMLoc S = Parser.getTok().getLoc();
1430 Parser.Lex(); // Eat $
1431
Jack Carterd0bd6422013-04-18 00:41:53 +00001432 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001433 if (Tok.isNot(AsmToken::Integer))
1434 return MatchOperand_NoMatch;
1435
1436 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001437 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001438 if (RegNum != 29)
1439 return MatchOperand_ParseFail;
1440
1441 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001442 Parser.getTok().getLoc());
Jack Carter2a74a87b2013-01-17 00:28:20 +00001443 op->setRegKind(MipsOperand::Kind_HW64Regs);
Jack Carter873c7242013-01-12 01:03:14 +00001444 Operands.push_back(op);
1445
Jack Carterd0bd6422013-04-18 00:41:53 +00001446 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001447 return MatchOperand_Success;
1448}
1449
1450MipsAsmParser::OperandMatchResultTy
1451MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1452 unsigned RegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001453 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001454 if (Parser.getTok().isNot(AsmToken::Dollar))
1455 return MatchOperand_NoMatch;
1456 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001457 Parser.Lex(); // Eat the '$'
Jack Carter873c7242013-01-12 01:03:14 +00001458
Jack Carterd0bd6422013-04-18 00:41:53 +00001459 const AsmToken &Tok = Parser.getTok(); // Get next token.
Jack Carter873c7242013-01-12 01:03:14 +00001460 if (Tok.is(AsmToken::Integer)) {
1461 RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001462 // At the moment only fcc0 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001463 if (RegNum != 0)
1464 return MatchOperand_ParseFail;
1465 } else if (Tok.is(AsmToken::Identifier)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001466 // At the moment only fcc0 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001467 if (Tok.getIdentifier() != "fcc0")
1468 return MatchOperand_ParseFail;
1469 } else
1470 return MatchOperand_NoMatch;
1471
1472 MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001473 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001474 op->setRegKind(MipsOperand::Kind_CCRRegs);
1475 Operands.push_back(op);
1476
Jack Carterd0bd6422013-04-18 00:41:53 +00001477 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001478 return MatchOperand_Success;
1479}
1480
Jack Carterdc1e35d2012-09-06 20:00:02 +00001481MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1482
1483 MCSymbolRefExpr::VariantKind VK
1484 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1485 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1486 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1487 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1488 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1489 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1490 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1491 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1492 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1493 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1494 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1495 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1496 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1497 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1498 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1499 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1500 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1501 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1502 .Default(MCSymbolRefExpr::VK_None);
1503
1504 return VK;
1505}
Jack Cartera63b16a2012-09-07 00:23:42 +00001506
Rafael Espindola870c4e92012-01-11 03:56:41 +00001507bool MipsAsmParser::
Chad Rosierf0e87202012-10-25 20:41:34 +00001508ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindola870c4e92012-01-11 03:56:41 +00001509 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic74593e62013-07-17 15:00:42 +00001510 // Check if we have valid mnemonic
1511 if (!mnemonicIsValid(Name)) {
1512 Parser.eatToEndOfStatement();
1513 return Error(NameLoc, "Unknown instruction");
1514 }
Vladimir Medic64828a12013-07-16 10:07:14 +00001515 // First operand in MCInst is instruction mnemonic.
1516 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterb4dbc172012-09-05 23:34:03 +00001517
1518 // Read the remaining operands.
1519 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1520 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00001521 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001522 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001523 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001524 return Error(Loc, "unexpected token in argument list");
1525 }
1526
Jack Carterd0bd6422013-04-18 00:41:53 +00001527 while (getLexer().is(AsmToken::Comma)) {
1528 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00001529 // Parse and remember the operand.
1530 if (ParseOperand(Operands, Name)) {
1531 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001532 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001533 return Error(Loc, "unexpected token in argument list");
1534 }
1535 }
1536 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001537 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1538 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001539 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001540 return Error(Loc, "unexpected token in argument list");
1541 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001542 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00001543 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00001544}
1545
Jack Carter0b744b32012-10-04 02:29:46 +00001546bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001547 SMLoc Loc = getLexer().getLoc();
1548 Parser.eatToEndOfStatement();
1549 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00001550}
1551
1552bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001553 // Line should look like: ".set noat".
1554 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00001555 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00001556 // eat noat
1557 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001558 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001559 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1560 reportParseError("unexpected token in statement");
1561 return false;
1562 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001563 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001564 return false;
1565}
Jack Carterd0bd6422013-04-18 00:41:53 +00001566
Jack Carter0b744b32012-10-04 02:29:46 +00001567bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001568 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00001569 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00001570 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00001571 getParser().Lex();
1572 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00001573 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00001574 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001575 return false;
1576 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001577 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00001578 if (getLexer().isNot(AsmToken::Dollar)) {
1579 reportParseError("unexpected token in statement");
1580 return false;
1581 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001582 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00001583 const AsmToken &Reg = Parser.getTok();
1584 if (Reg.is(AsmToken::Identifier)) {
1585 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
1586 } else if (Reg.is(AsmToken::Integer)) {
1587 AtRegNo = Reg.getIntVal();
1588 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001589 reportParseError("unexpected token in statement");
1590 return false;
1591 }
Jack Carter1ac53222013-02-20 23:11:17 +00001592
Jack Carterd0bd6422013-04-18 00:41:53 +00001593 if (AtRegNo < 1 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00001594 reportParseError("unexpected token in statement");
1595 return false;
1596 }
1597
1598 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00001599 reportParseError("unexpected token in statement");
1600 return false;
1601 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001602 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00001603
1604 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1605 reportParseError("unexpected token in statement");
1606 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001607 }
1608 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001609 return false;
1610 } else {
1611 reportParseError("unexpected token in statement");
1612 return false;
1613 }
1614}
1615
1616bool MipsAsmParser::parseSetReorderDirective() {
1617 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001618 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001619 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1620 reportParseError("unexpected token in statement");
1621 return false;
1622 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001623 Options.setReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00001624 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001625 return false;
1626}
1627
1628bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001629 Parser.Lex();
1630 // If this is not the end of the statement, report an error.
1631 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1632 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00001633 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001634 }
1635 Options.setNoreorder();
1636 Parser.Lex(); // Consume the EndOfStatement.
1637 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001638}
1639
1640bool MipsAsmParser::parseSetMacroDirective() {
1641 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001642 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001643 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1644 reportParseError("unexpected token in statement");
1645 return false;
1646 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001647 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001648 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001649 return false;
1650}
1651
1652bool MipsAsmParser::parseSetNoMacroDirective() {
1653 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001654 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001655 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1656 reportParseError("`noreorder' must be set before `nomacro'");
1657 return false;
1658 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001659 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00001660 reportParseError("`noreorder' must be set before `nomacro'");
1661 return false;
1662 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001663 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001664 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001665 return false;
1666}
Jack Carterd76b2372013-03-21 21:44:16 +00001667
1668bool MipsAsmParser::parseSetAssignment() {
1669 StringRef Name;
1670 const MCExpr *Value;
1671
1672 if (Parser.parseIdentifier(Name))
1673 reportParseError("expected identifier after .set");
1674
1675 if (getLexer().isNot(AsmToken::Comma))
1676 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00001677 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00001678
Jack Carter02593002013-05-28 22:21:05 +00001679 if (getLexer().is(AsmToken::Dollar)) {
1680 MCSymbol *Symbol;
1681 SMLoc DollarLoc = getLexer().getLoc();
1682 // Consume the dollar sign, and check for a following identifier.
1683 Parser.Lex();
1684 // We have a '$' followed by something, make sure they are adjacent.
1685 if (DollarLoc.getPointer() + 1 != getTok().getLoc().getPointer())
1686 return true;
1687 StringRef Res = StringRef(DollarLoc.getPointer(),
1688 getTok().getEndLoc().getPointer() - DollarLoc.getPointer());
1689 Symbol = getContext().GetOrCreateSymbol(Res);
1690 Parser.Lex();
1691 Value = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
1692 getContext());
1693 } else if (Parser.parseExpression(Value))
1694 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00001695
Jack Carterd0bd6422013-04-18 00:41:53 +00001696 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00001697 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00001698 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00001699 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00001700 Sym = getContext().GetOrCreateSymbol(Name);
1701 Sym->setVariableValue(Value);
1702
1703 return false;
1704}
Jack Carterd0bd6422013-04-18 00:41:53 +00001705
Jack Carter0b744b32012-10-04 02:29:46 +00001706bool MipsAsmParser::parseDirectiveSet() {
1707
Jack Carterd0bd6422013-04-18 00:41:53 +00001708 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00001709 const AsmToken &Tok = Parser.getTok();
1710
1711 if (Tok.getString() == "noat") {
1712 return parseSetNoAtDirective();
1713 } else if (Tok.getString() == "at") {
1714 return parseSetAtDirective();
1715 } else if (Tok.getString() == "reorder") {
1716 return parseSetReorderDirective();
1717 } else if (Tok.getString() == "noreorder") {
1718 return parseSetNoReorderDirective();
1719 } else if (Tok.getString() == "macro") {
1720 return parseSetMacroDirective();
1721 } else if (Tok.getString() == "nomacro") {
1722 return parseSetNoMacroDirective();
1723 } else if (Tok.getString() == "nomips16") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001724 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001725 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001726 return false;
1727 } else if (Tok.getString() == "nomicromips") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001728 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001729 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001730 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001731 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001732 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00001733 parseSetAssignment();
1734 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001735 }
Jack Carter07c818d2013-01-25 01:31:34 +00001736
Jack Carter0b744b32012-10-04 02:29:46 +00001737 return true;
1738}
1739
Jack Carter07c818d2013-01-25 01:31:34 +00001740/// parseDirectiveWord
1741/// ::= .word [ expression (, expression)* ]
1742bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
1743 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1744 for (;;) {
1745 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001746 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00001747 return true;
1748
1749 getParser().getStreamer().EmitValue(Value, Size);
1750
1751 if (getLexer().is(AsmToken::EndOfStatement))
1752 break;
1753
1754 // FIXME: Improve diagnostic.
1755 if (getLexer().isNot(AsmToken::Comma))
1756 return Error(L, "unexpected token in directive");
1757 Parser.Lex();
1758 }
1759 }
1760
1761 Parser.Lex();
1762 return false;
1763}
1764
Jack Carter0b744b32012-10-04 02:29:46 +00001765bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +00001766
Jack Carter07c818d2013-01-25 01:31:34 +00001767 StringRef IDVal = DirectiveID.getString();
1768
Jack Carterd0bd6422013-04-18 00:41:53 +00001769 if (IDVal == ".ent") {
1770 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001771 Parser.Lex();
1772 return false;
1773 }
1774
Jack Carter07c818d2013-01-25 01:31:34 +00001775 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001776 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001777 Parser.Lex();
1778 return false;
1779 }
1780
Jack Carter07c818d2013-01-25 01:31:34 +00001781 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001782 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001783 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001784 return false;
1785 }
1786
Jack Carter07c818d2013-01-25 01:31:34 +00001787 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00001788 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00001789 }
1790
Jack Carter07c818d2013-01-25 01:31:34 +00001791 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001792 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001793 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001794 return false;
1795 }
1796
Jack Carter07c818d2013-01-25 01:31:34 +00001797 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001798 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001799 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001800 return false;
1801 }
1802
Jack Carter07c818d2013-01-25 01:31:34 +00001803 if (IDVal == ".gpword") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001804 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001805 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001806 return false;
1807 }
1808
Jack Carter07c818d2013-01-25 01:31:34 +00001809 if (IDVal == ".word") {
1810 parseDirectiveWord(4, DirectiveID.getLoc());
1811 return false;
1812 }
1813
Rafael Espindola870c4e92012-01-11 03:56:41 +00001814 return true;
1815}
1816
Rafael Espindola870c4e92012-01-11 03:56:41 +00001817extern "C" void LLVMInitializeMipsAsmParser() {
1818 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1819 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1820 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1821 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1822}
Jack Carterb4dbc172012-09-05 23:34:03 +00001823
1824#define GET_REGISTER_MATCHER
1825#define GET_MATCHER_IMPLEMENTATION
1826#include "MipsGenAsmMatcher.inc"