blob: e810480b89ab4b51f1a1f0f2ca84ee072b703342 [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
Jack Cartera63b16a2012-09-07 00:23:42 +000081 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
82 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
83
Rafael Espindola870c4e92012-01-11 03:56:41 +000084 bool ParseDirective(AsmToken DirectiveID);
85
Jack Carterb4dbc172012-09-05 23:34:03 +000086 MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +000087 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
88
89 MipsAsmParser::OperandMatchResultTy
90 parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
91
92 MipsAsmParser::OperandMatchResultTy
93 parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
94
95 MipsAsmParser::OperandMatchResultTy
96 parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
97
98 MipsAsmParser::OperandMatchResultTy
99 parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
100
101 MipsAsmParser::OperandMatchResultTy
102 parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Chad Rosier391d29972012-09-03 18:47:45 +0000103
Jack Carterd76b2372013-03-21 21:44:16 +0000104 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
105 unsigned RegisterClass);
106
Jack Carterb4dbc172012-09-05 23:34:03 +0000107 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
108 StringRef Mnemonic);
109
Jack Carter873c7242013-01-12 01:03:14 +0000110 int tryParseRegister(bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000111
112 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carter873c7242013-01-12 01:03:14 +0000113 bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000114
Jack Carter30a59822012-10-04 04:03:53 +0000115 bool needsExpansion(MCInst &Inst);
116
117 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000118 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000119 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000120 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000121 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
122 SmallVectorImpl<MCInst> &Instructions);
123 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
124 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000125 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
126 SmallVectorImpl<MCInst> &Instructions,
127 bool isLoad,bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000128 bool reportParseError(StringRef ErrorMsg);
129
Jack Carterb5cf5902013-04-17 00:18:04 +0000130 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000131 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000132
Jack Carterb5cf5902013-04-17 00:18:04 +0000133 const MCExpr* evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
134
135 bool isEvaluated(const MCExpr *Expr);
Jack Carter0b744b32012-10-04 02:29:46 +0000136 bool parseDirectiveSet();
137
138 bool parseSetAtDirective();
139 bool parseSetNoAtDirective();
140 bool parseSetMacroDirective();
141 bool parseSetNoMacroDirective();
142 bool parseSetReorderDirective();
143 bool parseSetNoReorderDirective();
144
Jack Carterd76b2372013-03-21 21:44:16 +0000145 bool parseSetAssignment();
146
Jack Carter07c818d2013-01-25 01:31:34 +0000147 bool parseDirectiveWord(unsigned Size, SMLoc L);
148
Jack Carterdc1e35d2012-09-06 20:00:02 +0000149 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000150
Jack Carterb4dbc172012-09-05 23:34:03 +0000151 bool isMips64() const {
152 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
153 }
154
Jack Cartera63b16a2012-09-07 00:23:42 +0000155 bool isFP64() const {
156 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
157 }
158
Jack Carter873c7242013-01-12 01:03:14 +0000159 int matchRegisterName(StringRef Symbol, bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000160
Jack Carter1ac53222013-02-20 23:11:17 +0000161 int matchCPURegisterName(StringRef Symbol);
162
Jack Carter873c7242013-01-12 01:03:14 +0000163 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000164
Jack Cartera63b16a2012-09-07 00:23:42 +0000165 void setFpFormat(FpFormatTy Format) {
166 FpFormat = Format;
167 }
168
169 void setDefaultFpFormat();
170
171 void setFpFormat(StringRef Format);
172
173 FpFormatTy getFpFormat() {return FpFormat;}
174
175 bool requestsDoubleOperand(StringRef Mnemonic);
176
Jack Carterd0bd6422013-04-18 00:41:53 +0000177 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000178
Jack Carter1ac53222013-02-20 23:11:17 +0000179 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000180
181 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
182 SmallVectorImpl<MCInst> &Instructions);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000183public:
184 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterb4dbc172012-09-05 23:34:03 +0000185 : MCTargetAsmParser(), STI(sti), Parser(parser) {
186 // Initialize the set of available features.
187 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindola870c4e92012-01-11 03:56:41 +0000188 }
189
Jack Carterb4dbc172012-09-05 23:34:03 +0000190 MCAsmParser &getParser() const { return Parser; }
191 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
192
Rafael Espindola870c4e92012-01-11 03:56:41 +0000193};
194}
195
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000196namespace {
197
198/// MipsOperand - Instances of this class represent a parsed Mips machine
199/// instruction.
200class MipsOperand : public MCParsedAsmOperand {
Jack Carterb4dbc172012-09-05 23:34:03 +0000201
Jack Carter873c7242013-01-12 01:03:14 +0000202public:
203 enum RegisterKind {
204 Kind_None,
205 Kind_CPURegs,
206 Kind_CPU64Regs,
207 Kind_HWRegs,
208 Kind_HW64Regs,
209 Kind_FGR32Regs,
210 Kind_FGR64Regs,
Jack Carter1ac53222013-02-20 23:11:17 +0000211 Kind_AFGR64Regs,
Jack Carter873c7242013-01-12 01:03:14 +0000212 Kind_CCRRegs
213 };
214
215private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000216 enum KindTy {
217 k_CondCode,
218 k_CoprocNum,
219 k_Immediate,
220 k_Memory,
221 k_PostIndexRegister,
222 k_Register,
223 k_Token
224 } Kind;
225
226 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterb4dbc172012-09-05 23:34:03 +0000227
Eric Christopher8996c5d2013-03-15 00:42:55 +0000228 struct Token {
229 const char *Data;
230 unsigned Length;
231 };
232
233 struct RegOp {
234 unsigned RegNum;
235 RegisterKind Kind;
236 };
237
238 struct ImmOp {
239 const MCExpr *Val;
240 };
241
242 struct MemOp {
243 unsigned Base;
244 const MCExpr *Off;
245 };
246
Jack Carterb4dbc172012-09-05 23:34:03 +0000247 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000248 struct Token Tok;
249 struct RegOp Reg;
250 struct ImmOp Imm;
251 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000252 };
253
254 SMLoc StartLoc, EndLoc;
255
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000256public:
257 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000258 assert(N == 1 && "Invalid number of operands!");
259 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000260 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000261
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000262 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterb4dbc172012-09-05 23:34:03 +0000263 // Add as immediate when possible. Null MCExpr = 0.
264 if (Expr == 0)
265 Inst.addOperand(MCOperand::CreateImm(0));
266 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
267 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
268 else
269 Inst.addOperand(MCOperand::CreateExpr(Expr));
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 addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000273 assert(N == 1 && "Invalid number of operands!");
274 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000275 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000276 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000277
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000278 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000279 assert(N == 2 && "Invalid number of operands!");
280
281 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
282
283 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000284 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000285 }
286
287 bool isReg() const { return Kind == k_Register; }
288 bool isImm() const { return Kind == k_Immediate; }
289 bool isToken() const { return Kind == k_Token; }
290 bool isMem() const { return Kind == k_Memory; }
291
292 StringRef getToken() const {
293 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000294 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000295 }
296
297 unsigned getReg() const {
298 assert((Kind == k_Register) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000299 return Reg.RegNum;
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000300 }
301
Jack Carter873c7242013-01-12 01:03:14 +0000302 void setRegKind(RegisterKind RegKind) {
303 assert((Kind == k_Register) && "Invalid access!");
304 Reg.Kind = RegKind;
305 }
306
Jack Carterb4dbc172012-09-05 23:34:03 +0000307 const MCExpr *getImm() const {
308 assert((Kind == k_Immediate) && "Invalid access!");
309 return Imm.Val;
310 }
311
Jack Carterdc1e35d2012-09-06 20:00:02 +0000312 unsigned getMemBase() const {
313 assert((Kind == k_Memory) && "Invalid access!");
314 return Mem.Base;
315 }
316
317 const MCExpr *getMemOff() const {
318 assert((Kind == k_Memory) && "Invalid access!");
319 return Mem.Off;
320 }
321
Jack Carterb4dbc172012-09-05 23:34:03 +0000322 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
323 MipsOperand *Op = new MipsOperand(k_Token);
324 Op->Tok.Data = Str.data();
325 Op->Tok.Length = Str.size();
326 Op->StartLoc = S;
327 Op->EndLoc = S;
328 return Op;
329 }
330
331 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
332 MipsOperand *Op = new MipsOperand(k_Register);
333 Op->Reg.RegNum = RegNum;
334 Op->StartLoc = S;
335 Op->EndLoc = E;
336 return Op;
337 }
338
339 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
340 MipsOperand *Op = new MipsOperand(k_Immediate);
341 Op->Imm.Val = Val;
342 Op->StartLoc = S;
343 Op->EndLoc = E;
344 return Op;
345 }
346
Jack Carterdc1e35d2012-09-06 20:00:02 +0000347 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
348 SMLoc S, SMLoc E) {
349 MipsOperand *Op = new MipsOperand(k_Memory);
350 Op->Mem.Base = Base;
351 Op->Mem.Off = Off;
352 Op->StartLoc = S;
353 Op->EndLoc = E;
354 return Op;
355 }
356
Jack Carter873c7242013-01-12 01:03:14 +0000357 bool isCPURegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000358 return Kind == k_Register && Reg.Kind == Kind_CPURegs;
Jack Carter873c7242013-01-12 01:03:14 +0000359 }
Vladimir Medicc6960592013-06-19 10:14:36 +0000360 void addRegAsmOperands(MCInst &Inst, unsigned N) const {
Jack Carter873c7242013-01-12 01:03:14 +0000361 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
362 }
363
364 bool isCPU64RegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000365 return Kind == k_Register && Reg.Kind == Kind_CPU64Regs;
Jack Carter873c7242013-01-12 01:03:14 +0000366 }
Jack Carter873c7242013-01-12 01:03:14 +0000367
368 bool isHWRegsAsm() const {
369 assert((Kind == k_Register) && "Invalid access!");
370 return Reg.Kind == Kind_HWRegs;
371 }
Jack Carter873c7242013-01-12 01:03:14 +0000372
373 bool isHW64RegsAsm() const {
374 assert((Kind == k_Register) && "Invalid access!");
375 return Reg.Kind == Kind_HW64Regs;
376 }
Jack Carter873c7242013-01-12 01:03:14 +0000377
378 bool isCCRAsm() const {
379 assert((Kind == k_Register) && "Invalid access!");
380 return Reg.Kind == Kind_CCRRegs;
381 }
382
Jack Carterb4dbc172012-09-05 23:34:03 +0000383 /// getStartLoc - Get the location of the first token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000384 SMLoc getStartLoc() const {
385 return StartLoc;
386 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000387 /// getEndLoc - Get the location of the last token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000388 SMLoc getEndLoc() const {
389 return EndLoc;
390 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000391
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000392 virtual void print(raw_ostream &OS) const {
393 llvm_unreachable("unimplemented!");
394 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000395}; // class MipsOperand
396} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000397
Jack Carter9e65aa32013-03-22 00:05:30 +0000398namespace llvm {
399extern const MCInstrDesc MipsInsts[];
400}
401static const MCInstrDesc &getInstDesc(unsigned Opcode) {
402 return MipsInsts[Opcode];
403}
404
405bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000406 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000407 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
408 Inst.setLoc(IDLoc);
Jack Carterc15c1d22013-04-25 23:31:35 +0000409 if (MCID.hasDelaySlot() && Options.isReorder()) {
410 // If this instruction has a delay slot and .set reorder is active,
411 // emit a NOP after it.
412 Instructions.push_back(Inst);
413 MCInst NopInst;
414 NopInst.setOpcode(Mips::SLL);
415 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
416 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
417 NopInst.addOperand(MCOperand::CreateImm(0));
418 Instructions.push_back(NopInst);
419 return false;
420 }
421
Jack Carter9e65aa32013-03-22 00:05:30 +0000422 if (MCID.mayLoad() || MCID.mayStore()) {
423 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000424 // reference or immediate we may have to expand instructions.
425 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000426 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Jack Carterd0bd6422013-04-18 00:41:53 +0000427 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY)
428 || (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000429 MCOperand &Op = Inst.getOperand(i);
430 if (Op.isImm()) {
431 int MemOffset = Op.getImm();
432 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000433 // Offset can't exceed 16bit value.
434 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000435 return false;
436 }
437 } else if (Op.isExpr()) {
438 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000439 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000440 const MCSymbolRefExpr *SR =
Jack Carterb5cf5902013-04-17 00:18:04 +0000441 static_cast<const MCSymbolRefExpr*>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000442 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000443 // Expand symbol.
444 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000445 return false;
446 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000447 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000448 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000449 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000450 }
451 }
452 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000453 } // for
454 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000455
456 if (needsExpansion(Inst))
457 expandInstruction(Inst, IDLoc, Instructions);
458 else
459 Instructions.push_back(Inst);
460
461 return false;
462}
463
Jack Carter30a59822012-10-04 04:03:53 +0000464bool MipsAsmParser::needsExpansion(MCInst &Inst) {
465
Jack Carterd0bd6422013-04-18 00:41:53 +0000466 switch (Inst.getOpcode()) {
467 case Mips::LoadImm32Reg:
468 case Mips::LoadAddr32Imm:
469 case Mips::LoadAddr32Reg:
470 return true;
471 default:
472 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000473 }
474}
Jack Carter92995f12012-10-06 00:53:28 +0000475
Jack Carter30a59822012-10-04 04:03:53 +0000476void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000477 SmallVectorImpl<MCInst> &Instructions) {
478 switch (Inst.getOpcode()) {
479 case Mips::LoadImm32Reg:
480 return expandLoadImm(Inst, IDLoc, Instructions);
481 case Mips::LoadAddr32Imm:
482 return expandLoadAddressImm(Inst, IDLoc, Instructions);
483 case Mips::LoadAddr32Reg:
484 return expandLoadAddressReg(Inst, IDLoc, Instructions);
485 }
Jack Carter30a59822012-10-04 04:03:53 +0000486}
Jack Carter92995f12012-10-06 00:53:28 +0000487
Jack Carter30a59822012-10-04 04:03:53 +0000488void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000489 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000490 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000491 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000492 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000493 const MCOperand &RegOp = Inst.getOperand(0);
494 assert(RegOp.isReg() && "expected register operand kind");
495
496 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000497 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000498 if (0 <= ImmValue && ImmValue <= 65535) {
499 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000500 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000501 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000502 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000503 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000504 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000505 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000506 } else if (ImmValue < 0 && ImmValue >= -32768) {
507 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000508 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000509 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000510 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000511 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000512 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000513 Instructions.push_back(tmpInst);
514 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000515 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000516 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000517 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000518 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000519 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
520 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000521 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000522 tmpInst.clear();
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()));
525 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
526 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
527 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000528 Instructions.push_back(tmpInst);
529 }
530}
Jack Carter92995f12012-10-06 00:53:28 +0000531
Jack Carter543fdf82012-10-09 23:29:45 +0000532void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000533 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000534 MCInst tmpInst;
535 const MCOperand &ImmOp = Inst.getOperand(2);
536 assert(ImmOp.isImm() && "expected immediate operand kind");
537 const MCOperand &SrcRegOp = Inst.getOperand(1);
538 assert(SrcRegOp.isReg() && "expected register operand kind");
539 const MCOperand &DstRegOp = Inst.getOperand(0);
540 assert(DstRegOp.isReg() && "expected register operand kind");
541 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000542 if (-32768 <= ImmValue && ImmValue <= 65535) {
543 // For -32768 <= j <= 65535.
544 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000545 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000546 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
547 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
548 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
549 Instructions.push_back(tmpInst);
550 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000551 // For any other value of j that is representable as a 32-bit integer.
552 // la d,j(s) => lui d,hi16(j)
553 // ori d,d,lo16(j)
554 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000555 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000556 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
557 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
558 Instructions.push_back(tmpInst);
559 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000560 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000561 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
562 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
563 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
564 Instructions.push_back(tmpInst);
565 tmpInst.clear();
566 tmpInst.setOpcode(Mips::ADDu);
567 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
568 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
569 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
570 Instructions.push_back(tmpInst);
571 }
572}
573
574void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000575 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000576 MCInst tmpInst;
577 const MCOperand &ImmOp = Inst.getOperand(1);
578 assert(ImmOp.isImm() && "expected immediate operand kind");
579 const MCOperand &RegOp = Inst.getOperand(0);
580 assert(RegOp.isReg() && "expected register operand kind");
581 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000582 if (-32768 <= ImmValue && ImmValue <= 65535) {
583 // For -32768 <= j <= 65535.
584 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +0000585 tmpInst.setOpcode(Mips::ADDiu);
586 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000587 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +0000588 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
589 Instructions.push_back(tmpInst);
590 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000591 // For any other value of j that is representable as a 32-bit integer.
592 // la d,j => lui d,hi16(j)
593 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000594 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000595 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
596 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
597 Instructions.push_back(tmpInst);
598 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000599 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000600 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
601 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
602 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
603 Instructions.push_back(tmpInst);
604 }
605}
606
Jack Carter9e65aa32013-03-22 00:05:30 +0000607void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000608 SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000609 const MCSymbolRefExpr *SR;
610 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +0000611 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +0000612 const MCExpr *ExprOffset;
613 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +0000614 unsigned AtRegNum = getReg((isMips64()) ? Mips::CPU64RegsRegClassID
615 : Mips::CPURegsRegClassID, getATReg());
616 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000617 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
618 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000619 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000620 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
621 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000622 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +0000623 if (isImmOpnd) {
624 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
625 ImmOffset = Inst.getOperand(2).getImm();
626 LoOffset = ImmOffset & 0x0000ffff;
627 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +0000628 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +0000629 if (LoOffset & 0x8000)
630 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +0000631 } else
Jack Carter9e65aa32013-03-22 00:05:30 +0000632 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000633 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +0000634 TempInst.setLoc(IDLoc);
635 // 1st instruction in expansion is LUi. For load instruction we can use
636 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +0000637 // but for stores we must use $at.
638 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +0000639 TempInst.setOpcode(Mips::LUi);
640 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
641 if (isImmOpnd)
642 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
643 else {
644 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
645 SR = static_cast<const MCSymbolRefExpr*>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +0000646 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
647 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
648 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000649 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000650 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000651 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +0000652 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000653 }
654 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000655 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +0000656 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000657 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +0000658 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +0000659 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000660 TempInst.setOpcode(Mips::ADDu);
661 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
662 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
663 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
664 Instructions.push_back(TempInst);
665 TempInst.clear();
Jack Carterb5cf5902013-04-17 00:18:04 +0000666 // And finaly, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +0000667 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000668 TempInst.setOpcode(Inst.getOpcode());
669 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
670 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
671 if (isImmOpnd)
672 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
673 else {
674 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000675 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
676 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
677 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000678 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000679 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000680 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +0000681 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000682 }
683 }
684 Instructions.push_back(TempInst);
685 TempInst.clear();
686}
687
Rafael Espindola870c4e92012-01-11 03:56:41 +0000688bool MipsAsmParser::
Chad Rosier49963552012-10-13 00:26:04 +0000689MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +0000690 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +0000691 MCStreamer &Out, unsigned &ErrorInfo,
692 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000693 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +0000694 SmallVector<MCInst, 8> Instructions;
Chad Rosier2f480a82012-10-12 22:53:36 +0000695 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier49963552012-10-13 00:26:04 +0000696 MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +0000697
698 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000699 default:
700 break;
Jack Carterb4dbc172012-09-05 23:34:03 +0000701 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000702 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +0000703 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +0000704 for (unsigned i = 0; i < Instructions.size(); i++)
Jack Carter9e65aa32013-03-22 00:05:30 +0000705 Out.EmitInstruction(Instructions[i]);
Jack Carterb4dbc172012-09-05 23:34:03 +0000706 return false;
707 }
708 case Match_MissingFeature:
709 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
710 return true;
711 case Match_InvalidOperand: {
712 SMLoc ErrorLoc = IDLoc;
713 if (ErrorInfo != ~0U) {
714 if (ErrorInfo >= Operands.size())
715 return Error(IDLoc, "too few operands for instruction");
716
Jack Carterd0bd6422013-04-18 00:41:53 +0000717 ErrorLoc = ((MipsOperand*) Operands[ErrorInfo])->getStartLoc();
718 if (ErrorLoc == SMLoc())
719 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +0000720 }
721
722 return Error(ErrorLoc, "invalid operand for instruction");
723 }
724 case Match_MnemonicFail:
725 return Error(IDLoc, "invalid instruction");
726 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000727 return true;
728}
729
Jack Carter1ac53222013-02-20 23:11:17 +0000730int MipsAsmParser::matchCPURegisterName(StringRef Name) {
731 int CC;
732
733 if (Name == "at")
734 return getATReg();
735
736 CC = StringSwitch<unsigned>(Name)
737 .Case("zero", 0)
738 .Case("a0", 4)
739 .Case("a1", 5)
740 .Case("a2", 6)
741 .Case("a3", 7)
742 .Case("v0", 2)
743 .Case("v1", 3)
744 .Case("s0", 16)
745 .Case("s1", 17)
746 .Case("s2", 18)
747 .Case("s3", 19)
748 .Case("s4", 20)
749 .Case("s5", 21)
750 .Case("s6", 22)
751 .Case("s7", 23)
752 .Case("k0", 26)
753 .Case("k1", 27)
754 .Case("sp", 29)
755 .Case("fp", 30)
756 .Case("gp", 28)
757 .Case("ra", 31)
758 .Case("t0", 8)
759 .Case("t1", 9)
760 .Case("t2", 10)
761 .Case("t3", 11)
762 .Case("t4", 12)
763 .Case("t5", 13)
764 .Case("t6", 14)
765 .Case("t7", 15)
766 .Case("t8", 24)
767 .Case("t9", 25)
768 .Default(-1);
769
Jack Carterd0bd6422013-04-18 00:41:53 +0000770 // Although SGI documentation just cuts out t0-t3 for n32/n64,
Jack Carter1ac53222013-02-20 23:11:17 +0000771 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
772 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
Jack Carterd0bd6422013-04-18 00:41:53 +0000773 if (isMips64() && 8 <= CC && CC <= 11)
Jack Carter1ac53222013-02-20 23:11:17 +0000774 CC += 4;
775
776 if (CC == -1 && isMips64())
777 CC = StringSwitch<unsigned>(Name)
778 .Case("a4", 8)
779 .Case("a5", 9)
780 .Case("a6", 10)
781 .Case("a7", 11)
782 .Case("kt0", 26)
783 .Case("kt1", 27)
784 .Case("s8", 30)
785 .Default(-1);
786
787 return CC;
788}
Jack Carterd0bd6422013-04-18 00:41:53 +0000789
Jack Carter873c7242013-01-12 01:03:14 +0000790int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000791
Jack Carter2ad73da2013-04-15 22:21:55 +0000792 if (Name.equals("fcc0"))
793 return Mips::FCC0;
794
Jack Carter1ac53222013-02-20 23:11:17 +0000795 int CC;
796 CC = matchCPURegisterName(Name);
David Chisnall37051252012-10-09 16:27:43 +0000797 if (CC != -1)
Jack Carterd0bd6422013-04-18 00:41:53 +0000798 return matchRegisterByNumber(CC, is64BitReg ? Mips::CPU64RegsRegClassID
799 : Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000800
Jack Cartera63b16a2012-09-07 00:23:42 +0000801 if (Name[0] == 'f') {
802 StringRef NumString = Name.substr(1);
803 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +0000804 if (NumString.getAsInteger(10, IntVal))
805 return -1; // This is not an integer.
Jack Cartera63b16a2012-09-07 00:23:42 +0000806 if (IntVal > 31)
807 return -1;
808
809 FpFormatTy Format = getFpFormat();
810
811 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
812 return getReg(Mips::FGR32RegClassID, IntVal);
813 if (Format == FP_FORMAT_D) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000814 if (isFP64()) {
Jack Cartera63b16a2012-09-07 00:23:42 +0000815 return getReg(Mips::FGR64RegClassID, IntVal);
816 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000817 // Only even numbers available as register pairs.
818 if ((IntVal > 31) || (IntVal % 2 != 0))
Jack Cartera63b16a2012-09-07 00:23:42 +0000819 return -1;
Jack Carterd0bd6422013-04-18 00:41:53 +0000820 return getReg(Mips::AFGR64RegClassID, IntVal / 2);
Jack Cartera63b16a2012-09-07 00:23:42 +0000821 }
822 }
823
Jack Carterb4dbc172012-09-05 23:34:03 +0000824 return -1;
825}
Jack Carterd0bd6422013-04-18 00:41:53 +0000826
Jack Cartera63b16a2012-09-07 00:23:42 +0000827void MipsAsmParser::setDefaultFpFormat() {
828
829 if (isMips64() || isFP64())
830 FpFormat = FP_FORMAT_D;
831 else
832 FpFormat = FP_FORMAT_S;
833}
834
835bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
836
837 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
838 .Case("ldxc1", true)
839 .Case("ldc1", true)
840 .Case("sdxc1", true)
841 .Case("sdc1", true)
842 .Default(false);
843
844 return IsDouble;
845}
Jack Carterd0bd6422013-04-18 00:41:53 +0000846
Jack Cartera63b16a2012-09-07 00:23:42 +0000847void MipsAsmParser::setFpFormat(StringRef Format) {
848
849 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
850 .Case(".s", FP_FORMAT_S)
851 .Case(".d", FP_FORMAT_D)
852 .Case(".l", FP_FORMAT_L)
853 .Case(".w", FP_FORMAT_W)
854 .Default(FP_FORMAT_NONE);
855}
Jack Carterb4dbc172012-09-05 23:34:03 +0000856
Jack Carter0b744b32012-10-04 02:29:46 +0000857bool MipsAssemblerOptions::setATReg(unsigned Reg) {
858 if (Reg > 31)
859 return false;
860
861 aTReg = Reg;
862 return true;
863}
864
Jack Carter1ac53222013-02-20 23:11:17 +0000865int MipsAsmParser::getATReg() {
866 return Options.getATRegNum();
Jack Carter0b744b32012-10-04 02:29:46 +0000867}
868
Jack Carterd0bd6422013-04-18 00:41:53 +0000869unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +0000870 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +0000871}
872
Jack Carter873c7242013-01-12 01:03:14 +0000873int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000874
875 if (RegNum > 31)
876 return -1;
877
Jack Carter873c7242013-01-12 01:03:14 +0000878 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +0000879}
880
Jack Carter873c7242013-01-12 01:03:14 +0000881int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000882 const AsmToken &Tok = Parser.getTok();
883 int RegNum = -1;
884
885 if (Tok.is(AsmToken::Identifier)) {
886 std::string lowerCase = Tok.getString().lower();
Jack Carter873c7242013-01-12 01:03:14 +0000887 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000888 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +0000889 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carterd0bd6422013-04-18 00:41:53 +0000890 is64BitReg ? Mips::CPU64RegsRegClassID : Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000891 return RegNum;
892}
893
Jack Carterd0bd6422013-04-18 00:41:53 +0000894bool MipsAsmParser::tryParseRegisterOperand(
895 SmallVectorImpl<MCParsedAsmOperand*> &Operands, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000896
897 SMLoc S = Parser.getTok().getLoc();
898 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +0000899
Jack Carter873c7242013-01-12 01:03:14 +0000900 RegNo = tryParseRegister(is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000901 if (RegNo == -1)
902 return true;
903
Jack Carter873c7242013-01-12 01:03:14 +0000904 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterd0bd6422013-04-18 00:41:53 +0000905 Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000906 Parser.Lex(); // Eat register token.
907 return false;
908}
909
910bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
911 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +0000912 // Check if the current operand has a custom associated parser, if so, try to
913 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +0000914 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
915 if (ResTy == MatchOperand_Success)
916 return false;
917 // If there wasn't a custom match, try the generic matcher below. Otherwise,
918 // there was a match, but an error occurred, in which case, just return that
919 // the operand parsing failed.
920 if (ResTy == MatchOperand_ParseFail)
921 return true;
922
923 switch (getLexer().getKind()) {
924 default:
925 Error(Parser.getTok().getLoc(), "unexpected token in operand");
926 return true;
927 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000928 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +0000929 SMLoc S = Parser.getTok().getLoc();
930 Parser.Lex(); // Eat dollar token.
Jack Carterd0bd6422013-04-18 00:41:53 +0000931 // Parse the register operand.
Jack Carter873c7242013-01-12 01:03:14 +0000932 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000933 if (getLexer().is(AsmToken::LParen)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000934 // Check if it is indexed addressing operand.
Jack Carterb4dbc172012-09-05 23:34:03 +0000935 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carterd0bd6422013-04-18 00:41:53 +0000936 Parser.Lex(); // Eat the parenthesis.
Jack Carterb4dbc172012-09-05 23:34:03 +0000937 if (getLexer().isNot(AsmToken::Dollar))
938 return true;
939
Jack Carterd0bd6422013-04-18 00:41:53 +0000940 Parser.Lex(); // Eat the dollar
Jack Carter873c7242013-01-12 01:03:14 +0000941 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterb4dbc172012-09-05 23:34:03 +0000942 return true;
943
944 if (!getLexer().is(AsmToken::RParen))
945 return true;
946
947 S = Parser.getTok().getLoc();
948 Operands.push_back(MipsOperand::CreateToken(")", S));
949 Parser.Lex();
950 }
951 return false;
952 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000953 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +0000954 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000955 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +0000956 return true;
957
Jack Carter873c7242013-01-12 01:03:14 +0000958 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000959
Benjamin Kramerfa530572012-09-07 09:47:42 +0000960 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterb4dbc172012-09-05 23:34:03 +0000961
Jack Carterd0bd6422013-04-18 00:41:53 +0000962 // Otherwise create a symbol reference.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000963 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterb4dbc172012-09-05 23:34:03 +0000964 getContext());
965
966 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
967 return false;
968 }
969 case AsmToken::Identifier:
Jack Carterd76b2372013-03-21 21:44:16 +0000970 // Look for the existing symbol, we should check if
Jack Carterd0bd6422013-04-18 00:41:53 +0000971 // we need to assigne the propper RegisterKind.
972 if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
973 return false;
974 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +0000975 case AsmToken::LParen:
976 case AsmToken::Minus:
977 case AsmToken::Plus:
978 case AsmToken::Integer:
979 case AsmToken::String: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000980 // Quoted label names.
Jack Carterb4dbc172012-09-05 23:34:03 +0000981 const MCExpr *IdVal;
982 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000983 if (getParser().parseExpression(IdVal))
Jack Carterb4dbc172012-09-05 23:34:03 +0000984 return true;
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 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
987 return false;
988 }
Jack Carterdc1e35d2012-09-06 20:00:02 +0000989 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000990 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000991 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +0000992 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +0000993 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +0000994 return true;
995
Jack Carter873c7242013-01-12 01:03:14 +0000996 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
997
Jack Carterdc1e35d2012-09-06 20:00:02 +0000998 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
999 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001000 } // case AsmToken::Percent
1001 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001002 return true;
1003}
1004
Jack Carterb5cf5902013-04-17 00:18:04 +00001005const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
1006 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001007 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001008 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001009 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001010 // It's a constant, evaluate lo or hi value.
Jack Carterb5cf5902013-04-17 00:18:04 +00001011 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001012 short Val = MCE->getValue();
1013 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001014 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001015 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001016 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001017 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001018 // Lower part is treated as a signed int, so if it is negative
Jack Carterd0bd6422013-04-18 00:41:53 +00001019 // we must add 1 to the hi part to compensate.
Jack Carterdc463382013-02-21 02:09:31 +00001020 if (LoSign)
1021 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001022 Res = MCConstantExpr::Create(Val, getContext());
Evgeniy Stepanov3d8ab192013-04-17 06:45:11 +00001023 } else {
1024 llvm_unreachable("Invalid RelocStr value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001025 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001026 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001027 }
1028
Jack Carterb5cf5902013-04-17 00:18:04 +00001029 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001030 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001031 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001032 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001033 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001034 return Res;
1035 }
1036
1037 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001038 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1039 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001040 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1041 return Res;
1042 }
1043
1044 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001045 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1046 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1047 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001048 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001049 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001050 return Expr;
1051}
1052
1053bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1054
1055 switch (Expr->getKind()) {
1056 case MCExpr::Constant:
1057 return true;
1058 case MCExpr::SymbolRef:
1059 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1060 case MCExpr::Binary:
1061 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1062 if (!isEvaluated(BE->getLHS()))
1063 return false;
1064 return isEvaluated(BE->getRHS());
1065 }
1066 case MCExpr::Unary:
1067 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1068 default:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001069 return false;
1070 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001071 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001072}
Jack Carterd0bd6422013-04-18 00:41:53 +00001073
Jack Carterb5cf5902013-04-17 00:18:04 +00001074bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001075 Parser.Lex(); // Eat the % token.
1076 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001077 if (Tok.isNot(AsmToken::Identifier))
1078 return true;
1079
1080 std::string Str = Tok.getIdentifier().str();
1081
Jack Carterd0bd6422013-04-18 00:41:53 +00001082 Parser.Lex(); // Eat the identifier.
1083 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001084 const MCExpr *IdVal;
1085 SMLoc EndLoc;
1086
1087 if (getLexer().getKind() == AsmToken::LParen) {
1088 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001089 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001090 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001091 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001092 const AsmToken &nextTok = Parser.getTok();
1093 if (nextTok.isNot(AsmToken::Identifier))
1094 return true;
1095 Str += "(%";
1096 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001097 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001098 if (getLexer().getKind() != AsmToken::LParen)
1099 return true;
1100 } else
1101 break;
1102 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001103 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001104 return true;
1105
1106 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001107 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001108
1109 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001110 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001111
Jack Carterd0bd6422013-04-18 00:41:53 +00001112 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001113 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001114}
1115
Jack Carterb4dbc172012-09-05 23:34:03 +00001116bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1117 SMLoc &EndLoc) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001118 StartLoc = Parser.getTok().getLoc();
Jack Carter873c7242013-01-12 01:03:14 +00001119 RegNo = tryParseRegister(isMips64());
1120 EndLoc = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001121 return (RegNo == (unsigned) -1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001122}
1123
Jack Carterb5cf5902013-04-17 00:18:04 +00001124bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001125 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001126 bool Result = true;
1127
1128 while (getLexer().getKind() == AsmToken::LParen)
1129 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001130
Jack Carterd0bd6422013-04-18 00:41:53 +00001131 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001132 default:
1133 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001134 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001135 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001136 case AsmToken::Integer:
1137 case AsmToken::Minus:
1138 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001139 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001140 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001141 else
1142 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001143 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001144 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001145 break;
Jack Carter873c7242013-01-12 01:03:14 +00001146 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001147 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001148 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001149 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001150}
1151
Jack Carterb4dbc172012-09-05 23:34:03 +00001152MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Jack Carterd0bd6422013-04-18 00:41:53 +00001153 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001154
1155 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001156 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001157 bool isParenExpr = false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001158 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001159 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001160
Jack Carterb5cf5902013-04-17 00:18:04 +00001161 if (getLexer().getKind() == AsmToken::LParen) {
1162 Parser.Lex();
1163 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001164 }
1165
Jack Carterb5cf5902013-04-17 00:18:04 +00001166 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001167 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001168 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001169
Jack Carterd0bd6422013-04-18 00:41:53 +00001170 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001171 if (Tok.isNot(AsmToken::LParen)) {
1172 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
1173 if (Mnemonic->getToken() == "la") {
1174 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001175 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001176 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1177 return MatchOperand_Success;
1178 }
1179 if (Tok.is(AsmToken::EndOfStatement)) {
1180 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001181 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001182
Jack Carterd0bd6422013-04-18 00:41:53 +00001183 // Zero register assumed, add a memory operand with ZERO as its base.
1184 Operands.push_back(MipsOperand::CreateMem(isMips64() ? Mips::ZERO_64
1185 : Mips::ZERO,
1186 IdVal, S, E));
Jack Carterb5cf5902013-04-17 00:18:04 +00001187 return MatchOperand_Success;
1188 }
1189 Error(Parser.getTok().getLoc(), "'(' expected");
1190 return MatchOperand_ParseFail;
1191 }
1192
Jack Carterd0bd6422013-04-18 00:41:53 +00001193 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001194 }
1195
1196 const AsmToken &Tok1 = Parser.getTok(); // Get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +00001197 if (Tok1.is(AsmToken::Dollar)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001198 Parser.Lex(); // Eat the '$' token.
Jack Carter873c7242013-01-12 01:03:14 +00001199 if (tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001200 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1201 return MatchOperand_ParseFail;
1202 }
1203
1204 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001205 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001206 return MatchOperand_ParseFail;
1207 }
1208
Jack Carterd0bd6422013-04-18 00:41:53 +00001209 const AsmToken &Tok2 = Parser.getTok(); // Get next token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001210 if (Tok2.isNot(AsmToken::RParen)) {
1211 Error(Parser.getTok().getLoc(), "')' expected");
1212 return MatchOperand_ParseFail;
1213 }
1214
Jack Carter873c7242013-01-12 01:03:14 +00001215 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1216
Jack Carterd0bd6422013-04-18 00:41:53 +00001217 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001218
1219 if (IdVal == 0)
1220 IdVal = MCConstantExpr::Create(0, getContext());
1221
Jack Carterd0bd6422013-04-18 00:41:53 +00001222 // Replace the register operand with the memory operand.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001223 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1224 int RegNo = op->getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001225 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001226 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001227 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001228 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1229 int64_t Imm;
1230 if (IdVal->EvaluateAsAbsolute(Imm))
1231 IdVal = MCConstantExpr::Create(Imm, getContext());
1232 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1233 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1234 getContext());
1235 }
1236
Jack Carterdc1e35d2012-09-06 20:00:02 +00001237 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1238 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +00001239 return MatchOperand_Success;
1240}
1241
Jack Carter873c7242013-01-12 01:03:14 +00001242MipsAsmParser::OperandMatchResultTy
1243MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1244
1245 if (!isMips64())
1246 return MatchOperand_NoMatch;
Jack Carterd76b2372013-03-21 21:44:16 +00001247 if (getLexer().getKind() == AsmToken::Identifier) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001248 if (searchSymbolAlias(Operands, MipsOperand::Kind_CPU64Regs))
Jack Carterd76b2372013-03-21 21:44:16 +00001249 return MatchOperand_Success;
1250 return MatchOperand_NoMatch;
1251 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001252 // If the first token is not '$', we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001253 if (Parser.getTok().isNot(AsmToken::Dollar))
1254 return MatchOperand_NoMatch;
1255
1256 Parser.Lex(); // Eat $
Jack Carterd0bd6422013-04-18 00:41:53 +00001257 if (!tryParseRegisterOperand(Operands, true)) {
1258 // Set the proper register kind.
Jack Carter873c7242013-01-12 01:03:14 +00001259 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1260 op->setRegKind(MipsOperand::Kind_CPU64Regs);
1261 return MatchOperand_Success;
1262 }
1263 return MatchOperand_NoMatch;
1264}
1265
Jack Carterd0bd6422013-04-18 00:41:53 +00001266bool MipsAsmParser::searchSymbolAlias(
1267 SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegisterKind) {
Jack Carterd76b2372013-03-21 21:44:16 +00001268
1269 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1270 if (Sym) {
1271 SMLoc S = Parser.getTok().getLoc();
1272 const MCExpr *Expr;
1273 if (Sym->isVariable())
1274 Expr = Sym->getVariableValue();
1275 else
1276 return false;
1277 if (Expr->getKind() == MCExpr::SymbolRef) {
1278 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
1279 const StringRef DefSymbol = Ref->getSymbol().getName();
1280 if (DefSymbol.startswith("$")) {
Jack Carter02593002013-05-28 22:21:05 +00001281 int RegNum = -1;
1282 APInt IntVal(32, -1);
1283 if (!DefSymbol.substr(1).getAsInteger(10, IntVal))
1284 RegNum = matchRegisterByNumber(IntVal.getZExtValue(),
1285 isMips64()
1286 ? Mips::CPU64RegsRegClassID
1287 : Mips::CPURegsRegClassID);
1288 else
1289 // Lookup for the register with corresponding name
1290 RegNum = matchRegisterName(DefSymbol.substr(1), isMips64());
Jack Carterd76b2372013-03-21 21:44:16 +00001291 if (RegNum > -1) {
1292 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001293 MipsOperand *op = MipsOperand::CreateReg(RegNum, S,
1294 Parser.getTok().getLoc());
1295 op->setRegKind((MipsOperand::RegisterKind) RegisterKind);
Jack Carterd76b2372013-03-21 21:44:16 +00001296 Operands.push_back(op);
1297 return true;
1298 }
1299 }
1300 } else if (Expr->getKind() == MCExpr::Constant) {
1301 Parser.Lex();
1302 const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001303 MipsOperand *op = MipsOperand::CreateImm(Const, S,
Jack Carter02593002013-05-28 22:21:05 +00001304 Parser.getTok().getLoc());
Jack Carterd76b2372013-03-21 21:44:16 +00001305 Operands.push_back(op);
1306 return true;
1307 }
1308 }
1309 return false;
1310}
Jack Carterd0bd6422013-04-18 00:41:53 +00001311
Jack Carter873c7242013-01-12 01:03:14 +00001312MipsAsmParser::OperandMatchResultTy
1313MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1314
Jack Carterd76b2372013-03-21 21:44:16 +00001315 if (getLexer().getKind() == AsmToken::Identifier) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001316 if (searchSymbolAlias(Operands, MipsOperand::Kind_CPURegs))
Jack Carterd76b2372013-03-21 21:44:16 +00001317 return MatchOperand_Success;
1318 return MatchOperand_NoMatch;
1319 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001320 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001321 if (Parser.getTok().isNot(AsmToken::Dollar))
1322 return MatchOperand_NoMatch;
1323
1324 Parser.Lex(); // Eat $
Jack Carterd0bd6422013-04-18 00:41:53 +00001325 if (!tryParseRegisterOperand(Operands, false)) {
1326 // Set the proper register kind.
Jack Carter873c7242013-01-12 01:03:14 +00001327 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1328 op->setRegKind(MipsOperand::Kind_CPURegs);
1329 return MatchOperand_Success;
1330 }
1331 return MatchOperand_NoMatch;
1332}
1333
1334MipsAsmParser::OperandMatchResultTy
1335MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1336
Jack Carter2a74a87b2013-01-17 00:28:20 +00001337 if (isMips64())
1338 return MatchOperand_NoMatch;
1339
Jack Carterd0bd6422013-04-18 00:41:53 +00001340 // If the first token is not '$' we have error.
Jack Carter873c7242013-01-12 01:03:14 +00001341 if (Parser.getTok().isNot(AsmToken::Dollar))
1342 return MatchOperand_NoMatch;
1343 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001344 Parser.Lex(); // Eat the '$'.
Jack Carter873c7242013-01-12 01:03:14 +00001345
Jack Carterd0bd6422013-04-18 00:41:53 +00001346 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001347 if (Tok.isNot(AsmToken::Integer))
1348 return MatchOperand_NoMatch;
1349
1350 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001351 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001352 if (RegNum != 29)
1353 return MatchOperand_ParseFail;
1354
1355 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001356 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001357 op->setRegKind(MipsOperand::Kind_HWRegs);
1358 Operands.push_back(op);
1359
Jack Carterd0bd6422013-04-18 00:41:53 +00001360 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001361 return MatchOperand_Success;
1362}
1363
1364MipsAsmParser::OperandMatchResultTy
Jack Carterd0bd6422013-04-18 00:41:53 +00001365MipsAsmParser::parseHW64Regs(
1366 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter2a74a87b2013-01-17 00:28:20 +00001367
1368 if (!isMips64())
1369 return MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001370 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001371 if (Parser.getTok().isNot(AsmToken::Dollar))
1372 return MatchOperand_NoMatch;
1373 SMLoc S = Parser.getTok().getLoc();
1374 Parser.Lex(); // Eat $
1375
Jack Carterd0bd6422013-04-18 00:41:53 +00001376 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001377 if (Tok.isNot(AsmToken::Integer))
1378 return MatchOperand_NoMatch;
1379
1380 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001381 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001382 if (RegNum != 29)
1383 return MatchOperand_ParseFail;
1384
1385 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001386 Parser.getTok().getLoc());
Jack Carter2a74a87b2013-01-17 00:28:20 +00001387 op->setRegKind(MipsOperand::Kind_HW64Regs);
Jack Carter873c7242013-01-12 01:03:14 +00001388 Operands.push_back(op);
1389
Jack Carterd0bd6422013-04-18 00:41:53 +00001390 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001391 return MatchOperand_Success;
1392}
1393
1394MipsAsmParser::OperandMatchResultTy
1395MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1396 unsigned RegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001397 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001398 if (Parser.getTok().isNot(AsmToken::Dollar))
1399 return MatchOperand_NoMatch;
1400 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001401 Parser.Lex(); // Eat the '$'
Jack Carter873c7242013-01-12 01:03:14 +00001402
Jack Carterd0bd6422013-04-18 00:41:53 +00001403 const AsmToken &Tok = Parser.getTok(); // Get next token.
Jack Carter873c7242013-01-12 01:03:14 +00001404 if (Tok.is(AsmToken::Integer)) {
1405 RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001406 // At the moment only fcc0 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001407 if (RegNum != 0)
1408 return MatchOperand_ParseFail;
1409 } else if (Tok.is(AsmToken::Identifier)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001410 // At the moment only fcc0 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001411 if (Tok.getIdentifier() != "fcc0")
1412 return MatchOperand_ParseFail;
1413 } else
1414 return MatchOperand_NoMatch;
1415
1416 MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001417 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001418 op->setRegKind(MipsOperand::Kind_CCRRegs);
1419 Operands.push_back(op);
1420
Jack Carterd0bd6422013-04-18 00:41:53 +00001421 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001422 return MatchOperand_Success;
1423}
1424
Jack Carterdc1e35d2012-09-06 20:00:02 +00001425MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1426
1427 MCSymbolRefExpr::VariantKind VK
1428 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1429 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1430 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1431 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1432 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1433 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1434 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1435 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1436 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1437 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1438 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1439 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1440 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1441 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1442 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1443 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1444 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1445 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1446 .Default(MCSymbolRefExpr::VK_None);
1447
1448 return VK;
1449}
Vladimir Medicea381912013-06-04 08:28:53 +00001450// Converts condition string to immediate operand value.
Benjamin Kramer47b5c572012-09-10 11:52:14 +00001451static int ConvertCcString(StringRef CondString) {
Jack Cartera63b16a2012-09-07 00:23:42 +00001452 int CC = StringSwitch<unsigned>(CondString)
Jack Carterd0bd6422013-04-18 00:41:53 +00001453 .Case(".f", 0)
1454 .Case(".un", 1)
1455 .Case(".eq", 2)
1456 .Case(".ueq", 3)
1457 .Case(".olt", 4)
1458 .Case(".ult", 5)
1459 .Case(".ole", 6)
1460 .Case(".ule", 7)
1461 .Case(".sf", 8)
1462 .Case(".ngle", 9)
1463 .Case(".seq", 10)
1464 .Case(".ngl", 11)
1465 .Case(".lt", 12)
1466 .Case(".nge", 13)
1467 .Case(".le", 14)
1468 .Case(".ngt", 15)
1469 .Default(-1);
Jack Cartera63b16a2012-09-07 00:23:42 +00001470
1471 return CC;
1472}
1473
1474bool MipsAsmParser::
1475parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter0b744b32012-10-04 02:29:46 +00001476 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001477 // Split the format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001478 size_t Start = Name.find('.'), Next = Name.rfind('.');
1479 StringRef Format1 = Name.slice(Start, Next);
Jack Carterd0bd6422013-04-18 00:41:53 +00001480 // Add the first format to the operands.
Jack Cartera63b16a2012-09-07 00:23:42 +00001481 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carterd0bd6422013-04-18 00:41:53 +00001482 // Now for the second format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001483 StringRef Format2 = Name.slice(Next, StringRef::npos);
1484 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1485
Jack Carterd0bd6422013-04-18 00:41:53 +00001486 // Set the format for the first register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001487 setFpFormat(Format1);
1488
1489 // Read the remaining operands.
1490 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1491 // Read the first operand.
1492 if (ParseOperand(Operands, Name)) {
1493 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001494 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001495 return Error(Loc, "unexpected token in argument list");
1496 }
1497
1498 if (getLexer().isNot(AsmToken::Comma)) {
1499 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001500 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001501 return Error(Loc, "unexpected token in argument list");
Jack Cartera63b16a2012-09-07 00:23:42 +00001502 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001503 Parser.Lex(); // Eat the comma.
Jack Cartera63b16a2012-09-07 00:23:42 +00001504
Jack Carterb5cf5902013-04-17 00:18:04 +00001505 // Set the format for the first register
Jack Cartera63b16a2012-09-07 00:23:42 +00001506 setFpFormat(Format2);
1507
1508 // Parse and remember the operand.
1509 if (ParseOperand(Operands, Name)) {
1510 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001511 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001512 return Error(Loc, "unexpected token in argument list");
1513 }
1514 }
1515
1516 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1517 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001518 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001519 return Error(Loc, "unexpected token in argument list");
1520 }
1521
Jack Carterd0bd6422013-04-18 00:41:53 +00001522 Parser.Lex(); // Consume the EndOfStatement.
Jack Cartera63b16a2012-09-07 00:23:42 +00001523 return false;
1524}
1525
Rafael Espindola870c4e92012-01-11 03:56:41 +00001526bool MipsAsmParser::
Chad Rosierf0e87202012-10-25 20:41:34 +00001527ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindola870c4e92012-01-11 03:56:41 +00001528 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter1ac53222013-02-20 23:11:17 +00001529 StringRef Mnemonic;
Jack Carterd0bd6422013-04-18 00:41:53 +00001530 // Floating point instructions: Should the register be treated as a double?
Jack Cartera63b16a2012-09-07 00:23:42 +00001531 if (requestsDoubleOperand(Name)) {
1532 setFpFormat(FP_FORMAT_D);
Jack Carterd0bd6422013-04-18 00:41:53 +00001533 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
1534 Mnemonic = Name;
1535 } else {
Jack Cartera63b16a2012-09-07 00:23:42 +00001536 setDefaultFpFormat();
1537 // Create the leading tokens for the mnemonic, split by '.' characters.
1538 size_t Start = 0, Next = Name.find('.');
Jack Carter1ac53222013-02-20 23:11:17 +00001539 Mnemonic = Name.slice(Start, Next);
Jack Cartera63b16a2012-09-07 00:23:42 +00001540
1541 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1542
1543 if (Next != StringRef::npos) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001544 // There is a format token in mnemonic.
1545 size_t Dot = Name.find('.', Next + 1);
Jack Cartera63b16a2012-09-07 00:23:42 +00001546 StringRef Format = Name.slice(Next, Dot);
Jack Carterd0bd6422013-04-18 00:41:53 +00001547 if (Dot == StringRef::npos) // Only one '.' in a string, it's a format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001548 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1549 else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001550 if (Name.startswith("c.")) {
1551 // Floating point compare, add '.' and immediate represent for cc.
Jack Cartera63b16a2012-09-07 00:23:42 +00001552 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1553 int Cc = ConvertCcString(Format);
1554 if (Cc == -1) {
1555 return Error(NameLoc, "Invalid conditional code");
1556 }
Jack Carter873c7242013-01-12 01:03:14 +00001557 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001558 Parser.getTok().getLoc().getPointer() - 1);
1559 Operands.push_back(
1560 MipsOperand::CreateImm(MCConstantExpr::Create(Cc, getContext()),
1561 NameLoc, E));
Jack Cartera63b16a2012-09-07 00:23:42 +00001562 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001563 // trunc, ceil, floor ...
Jack Cartera63b16a2012-09-07 00:23:42 +00001564 return parseMathOperation(Name, NameLoc, Operands);
1565 }
1566
Jack Carterd0bd6422013-04-18 00:41:53 +00001567 // The rest is a format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001568 Format = Name.slice(Dot, StringRef::npos);
1569 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1570 }
1571
1572 setFpFormat(Format);
1573 }
1574 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001575
1576 // Read the remaining operands.
1577 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1578 // Read the first operand.
Jack Carter1ac53222013-02-20 23:11:17 +00001579 if (ParseOperand(Operands, Mnemonic)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001580 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001581 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001582 return Error(Loc, "unexpected token in argument list");
1583 }
1584
Jack Carterd0bd6422013-04-18 00:41:53 +00001585 while (getLexer().is(AsmToken::Comma)) {
1586 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00001587
1588 // Parse and remember the operand.
1589 if (ParseOperand(Operands, Name)) {
1590 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001591 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001592 return Error(Loc, "unexpected token in argument list");
1593 }
1594 }
1595 }
1596
1597 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1598 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 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00001604 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00001605}
1606
Jack Carter0b744b32012-10-04 02:29:46 +00001607bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001608 SMLoc Loc = getLexer().getLoc();
1609 Parser.eatToEndOfStatement();
1610 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00001611}
1612
1613bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001614 // Line should look like: ".set noat".
1615 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00001616 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00001617 // eat noat
1618 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001619 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001620 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1621 reportParseError("unexpected token in statement");
1622 return false;
1623 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001624 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001625 return false;
1626}
Jack Carterd0bd6422013-04-18 00:41:53 +00001627
Jack Carter0b744b32012-10-04 02:29:46 +00001628bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001629 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00001630 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00001631 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00001632 getParser().Lex();
1633 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00001634 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00001635 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001636 return false;
1637 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001638 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00001639 if (getLexer().isNot(AsmToken::Dollar)) {
1640 reportParseError("unexpected token in statement");
1641 return false;
1642 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001643 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00001644 const AsmToken &Reg = Parser.getTok();
1645 if (Reg.is(AsmToken::Identifier)) {
1646 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
1647 } else if (Reg.is(AsmToken::Integer)) {
1648 AtRegNo = Reg.getIntVal();
1649 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001650 reportParseError("unexpected token in statement");
1651 return false;
1652 }
Jack Carter1ac53222013-02-20 23:11:17 +00001653
Jack Carterd0bd6422013-04-18 00:41:53 +00001654 if (AtRegNo < 1 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00001655 reportParseError("unexpected token in statement");
1656 return false;
1657 }
1658
1659 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00001660 reportParseError("unexpected token in statement");
1661 return false;
1662 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001663 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00001664
1665 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1666 reportParseError("unexpected token in statement");
1667 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001668 }
1669 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001670 return false;
1671 } else {
1672 reportParseError("unexpected token in statement");
1673 return false;
1674 }
1675}
1676
1677bool MipsAsmParser::parseSetReorderDirective() {
1678 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001679 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001680 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1681 reportParseError("unexpected token in statement");
1682 return false;
1683 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001684 Options.setReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00001685 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001686 return false;
1687}
1688
1689bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001690 Parser.Lex();
1691 // If this is not the end of the statement, report an error.
1692 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1693 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00001694 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001695 }
1696 Options.setNoreorder();
1697 Parser.Lex(); // Consume the EndOfStatement.
1698 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001699}
1700
1701bool MipsAsmParser::parseSetMacroDirective() {
1702 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001703 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001704 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1705 reportParseError("unexpected token in statement");
1706 return false;
1707 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001708 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001709 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001710 return false;
1711}
1712
1713bool MipsAsmParser::parseSetNoMacroDirective() {
1714 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001715 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001716 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1717 reportParseError("`noreorder' must be set before `nomacro'");
1718 return false;
1719 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001720 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00001721 reportParseError("`noreorder' must be set before `nomacro'");
1722 return false;
1723 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001724 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001725 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001726 return false;
1727}
Jack Carterd76b2372013-03-21 21:44:16 +00001728
1729bool MipsAsmParser::parseSetAssignment() {
1730 StringRef Name;
1731 const MCExpr *Value;
1732
1733 if (Parser.parseIdentifier(Name))
1734 reportParseError("expected identifier after .set");
1735
1736 if (getLexer().isNot(AsmToken::Comma))
1737 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00001738 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00001739
Jack Carter02593002013-05-28 22:21:05 +00001740 if (getLexer().is(AsmToken::Dollar)) {
1741 MCSymbol *Symbol;
1742 SMLoc DollarLoc = getLexer().getLoc();
1743 // Consume the dollar sign, and check for a following identifier.
1744 Parser.Lex();
1745 // We have a '$' followed by something, make sure they are adjacent.
1746 if (DollarLoc.getPointer() + 1 != getTok().getLoc().getPointer())
1747 return true;
1748 StringRef Res = StringRef(DollarLoc.getPointer(),
1749 getTok().getEndLoc().getPointer() - DollarLoc.getPointer());
1750 Symbol = getContext().GetOrCreateSymbol(Res);
1751 Parser.Lex();
1752 Value = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
1753 getContext());
1754 } else if (Parser.parseExpression(Value))
1755 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00001756
Jack Carterd0bd6422013-04-18 00:41:53 +00001757 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00001758 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00001759 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00001760 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00001761 Sym = getContext().GetOrCreateSymbol(Name);
1762 Sym->setVariableValue(Value);
1763
1764 return false;
1765}
Jack Carterd0bd6422013-04-18 00:41:53 +00001766
Jack Carter0b744b32012-10-04 02:29:46 +00001767bool MipsAsmParser::parseDirectiveSet() {
1768
Jack Carterd0bd6422013-04-18 00:41:53 +00001769 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00001770 const AsmToken &Tok = Parser.getTok();
1771
1772 if (Tok.getString() == "noat") {
1773 return parseSetNoAtDirective();
1774 } else if (Tok.getString() == "at") {
1775 return parseSetAtDirective();
1776 } else if (Tok.getString() == "reorder") {
1777 return parseSetReorderDirective();
1778 } else if (Tok.getString() == "noreorder") {
1779 return parseSetNoReorderDirective();
1780 } else if (Tok.getString() == "macro") {
1781 return parseSetMacroDirective();
1782 } else if (Tok.getString() == "nomacro") {
1783 return parseSetNoMacroDirective();
1784 } else if (Tok.getString() == "nomips16") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001785 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001786 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001787 return false;
1788 } else if (Tok.getString() == "nomicromips") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001789 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001790 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001791 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001792 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001793 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00001794 parseSetAssignment();
1795 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001796 }
Jack Carter07c818d2013-01-25 01:31:34 +00001797
Jack Carter0b744b32012-10-04 02:29:46 +00001798 return true;
1799}
1800
Jack Carter07c818d2013-01-25 01:31:34 +00001801/// parseDirectiveWord
1802/// ::= .word [ expression (, expression)* ]
1803bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
1804 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1805 for (;;) {
1806 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001807 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00001808 return true;
1809
1810 getParser().getStreamer().EmitValue(Value, Size);
1811
1812 if (getLexer().is(AsmToken::EndOfStatement))
1813 break;
1814
1815 // FIXME: Improve diagnostic.
1816 if (getLexer().isNot(AsmToken::Comma))
1817 return Error(L, "unexpected token in directive");
1818 Parser.Lex();
1819 }
1820 }
1821
1822 Parser.Lex();
1823 return false;
1824}
1825
Jack Carter0b744b32012-10-04 02:29:46 +00001826bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +00001827
Jack Carter07c818d2013-01-25 01:31:34 +00001828 StringRef IDVal = DirectiveID.getString();
1829
Jack Carterd0bd6422013-04-18 00:41:53 +00001830 if (IDVal == ".ent") {
1831 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001832 Parser.Lex();
1833 return false;
1834 }
1835
Jack Carter07c818d2013-01-25 01:31:34 +00001836 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001837 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001838 Parser.Lex();
1839 return false;
1840 }
1841
Jack Carter07c818d2013-01-25 01:31:34 +00001842 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001843 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001844 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001845 return false;
1846 }
1847
Jack Carter07c818d2013-01-25 01:31:34 +00001848 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00001849 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00001850 }
1851
Jack Carter07c818d2013-01-25 01:31:34 +00001852 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001853 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001854 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001855 return false;
1856 }
1857
Jack Carter07c818d2013-01-25 01:31:34 +00001858 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001859 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001860 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001861 return false;
1862 }
1863
Jack Carter07c818d2013-01-25 01:31:34 +00001864 if (IDVal == ".gpword") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001865 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001866 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001867 return false;
1868 }
1869
Jack Carter07c818d2013-01-25 01:31:34 +00001870 if (IDVal == ".word") {
1871 parseDirectiveWord(4, DirectiveID.getLoc());
1872 return false;
1873 }
1874
Rafael Espindola870c4e92012-01-11 03:56:41 +00001875 return true;
1876}
1877
Rafael Espindola870c4e92012-01-11 03:56:41 +00001878extern "C" void LLVMInitializeMipsAsmParser() {
1879 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1880 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1881 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1882 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1883}
Jack Carterb4dbc172012-09-05 23:34:03 +00001884
1885#define GET_REGISTER_MATCHER
1886#define GET_MATCHER_IMPLEMENTATION
1887#include "MipsGenAsmMatcher.inc"