blob: d1d69d886a8ef3350ffcea7c42cb0d0309160320 [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 }
360 void addCPURegsAsmOperands(MCInst &Inst, unsigned N) const {
361 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 }
367 void addCPU64RegsAsmOperands(MCInst &Inst, unsigned N) const {
368 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
369 }
370
371 bool isHWRegsAsm() const {
372 assert((Kind == k_Register) && "Invalid access!");
373 return Reg.Kind == Kind_HWRegs;
374 }
375 void addHWRegsAsmOperands(MCInst &Inst, unsigned N) const {
376 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
377 }
378
379 bool isHW64RegsAsm() const {
380 assert((Kind == k_Register) && "Invalid access!");
381 return Reg.Kind == Kind_HW64Regs;
382 }
383 void addHW64RegsAsmOperands(MCInst &Inst, unsigned N) const {
384 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
385 }
386
387 void addCCRAsmOperands(MCInst &Inst, unsigned N) const {
388 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
389 }
390
391 bool isCCRAsm() const {
392 assert((Kind == k_Register) && "Invalid access!");
393 return Reg.Kind == Kind_CCRRegs;
394 }
395
Jack Carterb4dbc172012-09-05 23:34:03 +0000396 /// getStartLoc - Get the location of the first token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000397 SMLoc getStartLoc() const {
398 return StartLoc;
399 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000400 /// getEndLoc - Get the location of the last token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000401 SMLoc getEndLoc() const {
402 return EndLoc;
403 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000404
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000405 virtual void print(raw_ostream &OS) const {
406 llvm_unreachable("unimplemented!");
407 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000408}; // class MipsOperand
409} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000410
Jack Carter9e65aa32013-03-22 00:05:30 +0000411namespace llvm {
412extern const MCInstrDesc MipsInsts[];
413}
414static const MCInstrDesc &getInstDesc(unsigned Opcode) {
415 return MipsInsts[Opcode];
416}
417
418bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000419 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000420 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
421 Inst.setLoc(IDLoc);
Jack Carterc15c1d22013-04-25 23:31:35 +0000422 if (MCID.hasDelaySlot() && Options.isReorder()) {
423 // If this instruction has a delay slot and .set reorder is active,
424 // emit a NOP after it.
425 Instructions.push_back(Inst);
426 MCInst NopInst;
427 NopInst.setOpcode(Mips::SLL);
428 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
429 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
430 NopInst.addOperand(MCOperand::CreateImm(0));
431 Instructions.push_back(NopInst);
432 return false;
433 }
434
Jack Carter9e65aa32013-03-22 00:05:30 +0000435 if (MCID.mayLoad() || MCID.mayStore()) {
436 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000437 // reference or immediate we may have to expand instructions.
438 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000439 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Jack Carterd0bd6422013-04-18 00:41:53 +0000440 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY)
441 || (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000442 MCOperand &Op = Inst.getOperand(i);
443 if (Op.isImm()) {
444 int MemOffset = Op.getImm();
445 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000446 // Offset can't exceed 16bit value.
447 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000448 return false;
449 }
450 } else if (Op.isExpr()) {
451 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000452 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000453 const MCSymbolRefExpr *SR =
Jack Carterb5cf5902013-04-17 00:18:04 +0000454 static_cast<const MCSymbolRefExpr*>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000455 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000456 // Expand symbol.
457 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000458 return false;
459 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000460 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000461 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000462 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000463 }
464 }
465 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000466 } // for
467 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000468
469 if (needsExpansion(Inst))
470 expandInstruction(Inst, IDLoc, Instructions);
471 else
472 Instructions.push_back(Inst);
473
474 return false;
475}
476
Jack Carter30a59822012-10-04 04:03:53 +0000477bool MipsAsmParser::needsExpansion(MCInst &Inst) {
478
Jack Carterd0bd6422013-04-18 00:41:53 +0000479 switch (Inst.getOpcode()) {
480 case Mips::LoadImm32Reg:
481 case Mips::LoadAddr32Imm:
482 case Mips::LoadAddr32Reg:
483 return true;
484 default:
485 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000486 }
487}
Jack Carter92995f12012-10-06 00:53:28 +0000488
Jack Carter30a59822012-10-04 04:03:53 +0000489void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000490 SmallVectorImpl<MCInst> &Instructions) {
491 switch (Inst.getOpcode()) {
492 case Mips::LoadImm32Reg:
493 return expandLoadImm(Inst, IDLoc, Instructions);
494 case Mips::LoadAddr32Imm:
495 return expandLoadAddressImm(Inst, IDLoc, Instructions);
496 case Mips::LoadAddr32Reg:
497 return expandLoadAddressReg(Inst, IDLoc, Instructions);
498 }
Jack Carter30a59822012-10-04 04:03:53 +0000499}
Jack Carter92995f12012-10-06 00:53:28 +0000500
Jack Carter30a59822012-10-04 04:03:53 +0000501void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000502 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000503 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000504 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000505 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000506 const MCOperand &RegOp = Inst.getOperand(0);
507 assert(RegOp.isReg() && "expected register operand kind");
508
509 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000510 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000511 if (0 <= ImmValue && ImmValue <= 65535) {
512 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000513 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000514 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000515 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000516 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000517 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000518 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000519 } else if (ImmValue < 0 && ImmValue >= -32768) {
520 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000521 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000522 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000523 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000524 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000525 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000526 Instructions.push_back(tmpInst);
527 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000528 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000529 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000530 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000531 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000532 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
533 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000534 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000535 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000536 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000537 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
538 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
539 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
540 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000541 Instructions.push_back(tmpInst);
542 }
543}
Jack Carter92995f12012-10-06 00:53:28 +0000544
Jack Carter543fdf82012-10-09 23:29:45 +0000545void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000546 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000547 MCInst tmpInst;
548 const MCOperand &ImmOp = Inst.getOperand(2);
549 assert(ImmOp.isImm() && "expected immediate operand kind");
550 const MCOperand &SrcRegOp = Inst.getOperand(1);
551 assert(SrcRegOp.isReg() && "expected register operand kind");
552 const MCOperand &DstRegOp = Inst.getOperand(0);
553 assert(DstRegOp.isReg() && "expected register operand kind");
554 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000555 if (-32768 <= ImmValue && ImmValue <= 65535) {
556 // For -32768 <= j <= 65535.
557 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000558 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000559 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
560 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
561 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
562 Instructions.push_back(tmpInst);
563 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000564 // For any other value of j that is representable as a 32-bit integer.
565 // la d,j(s) => lui d,hi16(j)
566 // ori d,d,lo16(j)
567 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000568 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000569 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
570 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
571 Instructions.push_back(tmpInst);
572 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000573 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000574 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
575 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
576 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
577 Instructions.push_back(tmpInst);
578 tmpInst.clear();
579 tmpInst.setOpcode(Mips::ADDu);
580 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
581 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
582 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
583 Instructions.push_back(tmpInst);
584 }
585}
586
587void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000588 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000589 MCInst tmpInst;
590 const MCOperand &ImmOp = Inst.getOperand(1);
591 assert(ImmOp.isImm() && "expected immediate operand kind");
592 const MCOperand &RegOp = Inst.getOperand(0);
593 assert(RegOp.isReg() && "expected register operand kind");
594 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000595 if (-32768 <= ImmValue && ImmValue <= 65535) {
596 // For -32768 <= j <= 65535.
597 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +0000598 tmpInst.setOpcode(Mips::ADDiu);
599 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000600 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +0000601 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
602 Instructions.push_back(tmpInst);
603 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000604 // For any other value of j that is representable as a 32-bit integer.
605 // la d,j => lui d,hi16(j)
606 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000607 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000608 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
609 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
610 Instructions.push_back(tmpInst);
611 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000612 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000613 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
614 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
615 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
616 Instructions.push_back(tmpInst);
617 }
618}
619
Jack Carter9e65aa32013-03-22 00:05:30 +0000620void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000621 SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000622 const MCSymbolRefExpr *SR;
623 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +0000624 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +0000625 const MCExpr *ExprOffset;
626 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +0000627 unsigned AtRegNum = getReg((isMips64()) ? Mips::CPU64RegsRegClassID
628 : Mips::CPURegsRegClassID, getATReg());
629 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000630 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
631 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000632 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000633 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
634 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000635 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +0000636 if (isImmOpnd) {
637 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
638 ImmOffset = Inst.getOperand(2).getImm();
639 LoOffset = ImmOffset & 0x0000ffff;
640 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +0000641 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +0000642 if (LoOffset & 0x8000)
643 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +0000644 } else
Jack Carter9e65aa32013-03-22 00:05:30 +0000645 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000646 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +0000647 TempInst.setLoc(IDLoc);
648 // 1st instruction in expansion is LUi. For load instruction we can use
649 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +0000650 // but for stores we must use $at.
651 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +0000652 TempInst.setOpcode(Mips::LUi);
653 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
654 if (isImmOpnd)
655 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
656 else {
657 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
658 SR = static_cast<const MCSymbolRefExpr*>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +0000659 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
660 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
661 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000662 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000663 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000664 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +0000665 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000666 }
667 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000668 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +0000669 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000670 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +0000671 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +0000672 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000673 TempInst.setOpcode(Mips::ADDu);
674 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
675 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
676 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
677 Instructions.push_back(TempInst);
678 TempInst.clear();
Jack Carterb5cf5902013-04-17 00:18:04 +0000679 // And finaly, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +0000680 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000681 TempInst.setOpcode(Inst.getOpcode());
682 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
683 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
684 if (isImmOpnd)
685 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
686 else {
687 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000688 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
689 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
690 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000691 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000692 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000693 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +0000694 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000695 }
696 }
697 Instructions.push_back(TempInst);
698 TempInst.clear();
699}
700
Rafael Espindola870c4e92012-01-11 03:56:41 +0000701bool MipsAsmParser::
Chad Rosier49963552012-10-13 00:26:04 +0000702MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +0000703 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +0000704 MCStreamer &Out, unsigned &ErrorInfo,
705 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000706 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +0000707 SmallVector<MCInst, 8> Instructions;
Chad Rosier2f480a82012-10-12 22:53:36 +0000708 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier49963552012-10-13 00:26:04 +0000709 MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +0000710
711 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000712 default:
713 break;
Jack Carterb4dbc172012-09-05 23:34:03 +0000714 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000715 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +0000716 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +0000717 for (unsigned i = 0; i < Instructions.size(); i++)
Jack Carter9e65aa32013-03-22 00:05:30 +0000718 Out.EmitInstruction(Instructions[i]);
Jack Carterb4dbc172012-09-05 23:34:03 +0000719 return false;
720 }
721 case Match_MissingFeature:
722 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
723 return true;
724 case Match_InvalidOperand: {
725 SMLoc ErrorLoc = IDLoc;
726 if (ErrorInfo != ~0U) {
727 if (ErrorInfo >= Operands.size())
728 return Error(IDLoc, "too few operands for instruction");
729
Jack Carterd0bd6422013-04-18 00:41:53 +0000730 ErrorLoc = ((MipsOperand*) Operands[ErrorInfo])->getStartLoc();
731 if (ErrorLoc == SMLoc())
732 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +0000733 }
734
735 return Error(ErrorLoc, "invalid operand for instruction");
736 }
737 case Match_MnemonicFail:
738 return Error(IDLoc, "invalid instruction");
739 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000740 return true;
741}
742
Jack Carter1ac53222013-02-20 23:11:17 +0000743int MipsAsmParser::matchCPURegisterName(StringRef Name) {
744 int CC;
745
746 if (Name == "at")
747 return getATReg();
748
749 CC = StringSwitch<unsigned>(Name)
750 .Case("zero", 0)
751 .Case("a0", 4)
752 .Case("a1", 5)
753 .Case("a2", 6)
754 .Case("a3", 7)
755 .Case("v0", 2)
756 .Case("v1", 3)
757 .Case("s0", 16)
758 .Case("s1", 17)
759 .Case("s2", 18)
760 .Case("s3", 19)
761 .Case("s4", 20)
762 .Case("s5", 21)
763 .Case("s6", 22)
764 .Case("s7", 23)
765 .Case("k0", 26)
766 .Case("k1", 27)
767 .Case("sp", 29)
768 .Case("fp", 30)
769 .Case("gp", 28)
770 .Case("ra", 31)
771 .Case("t0", 8)
772 .Case("t1", 9)
773 .Case("t2", 10)
774 .Case("t3", 11)
775 .Case("t4", 12)
776 .Case("t5", 13)
777 .Case("t6", 14)
778 .Case("t7", 15)
779 .Case("t8", 24)
780 .Case("t9", 25)
781 .Default(-1);
782
Jack Carterd0bd6422013-04-18 00:41:53 +0000783 // Although SGI documentation just cuts out t0-t3 for n32/n64,
Jack Carter1ac53222013-02-20 23:11:17 +0000784 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
785 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
Jack Carterd0bd6422013-04-18 00:41:53 +0000786 if (isMips64() && 8 <= CC && CC <= 11)
Jack Carter1ac53222013-02-20 23:11:17 +0000787 CC += 4;
788
789 if (CC == -1 && isMips64())
790 CC = StringSwitch<unsigned>(Name)
791 .Case("a4", 8)
792 .Case("a5", 9)
793 .Case("a6", 10)
794 .Case("a7", 11)
795 .Case("kt0", 26)
796 .Case("kt1", 27)
797 .Case("s8", 30)
798 .Default(-1);
799
800 return CC;
801}
Jack Carterd0bd6422013-04-18 00:41:53 +0000802
Jack Carter873c7242013-01-12 01:03:14 +0000803int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000804
Jack Carter2ad73da2013-04-15 22:21:55 +0000805 if (Name.equals("fcc0"))
806 return Mips::FCC0;
807
Jack Carter1ac53222013-02-20 23:11:17 +0000808 int CC;
809 CC = matchCPURegisterName(Name);
David Chisnall37051252012-10-09 16:27:43 +0000810 if (CC != -1)
Jack Carterd0bd6422013-04-18 00:41:53 +0000811 return matchRegisterByNumber(CC, is64BitReg ? Mips::CPU64RegsRegClassID
812 : Mips::CPURegsRegClassID);
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
822 FpFormatTy Format = getFpFormat();
823
824 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
825 return getReg(Mips::FGR32RegClassID, IntVal);
826 if (Format == FP_FORMAT_D) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000827 if (isFP64()) {
Jack Cartera63b16a2012-09-07 00:23:42 +0000828 return getReg(Mips::FGR64RegClassID, IntVal);
829 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000830 // Only even numbers available as register pairs.
831 if ((IntVal > 31) || (IntVal % 2 != 0))
Jack Cartera63b16a2012-09-07 00:23:42 +0000832 return -1;
Jack Carterd0bd6422013-04-18 00:41:53 +0000833 return getReg(Mips::AFGR64RegClassID, IntVal / 2);
Jack Cartera63b16a2012-09-07 00:23:42 +0000834 }
835 }
836
Jack Carterb4dbc172012-09-05 23:34:03 +0000837 return -1;
838}
Jack Carterd0bd6422013-04-18 00:41:53 +0000839
Jack Cartera63b16a2012-09-07 00:23:42 +0000840void MipsAsmParser::setDefaultFpFormat() {
841
842 if (isMips64() || isFP64())
843 FpFormat = FP_FORMAT_D;
844 else
845 FpFormat = FP_FORMAT_S;
846}
847
848bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
849
850 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
851 .Case("ldxc1", true)
852 .Case("ldc1", true)
853 .Case("sdxc1", true)
854 .Case("sdc1", true)
855 .Default(false);
856
857 return IsDouble;
858}
Jack Carterd0bd6422013-04-18 00:41:53 +0000859
Jack Cartera63b16a2012-09-07 00:23:42 +0000860void MipsAsmParser::setFpFormat(StringRef Format) {
861
862 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
863 .Case(".s", FP_FORMAT_S)
864 .Case(".d", FP_FORMAT_D)
865 .Case(".l", FP_FORMAT_L)
866 .Case(".w", FP_FORMAT_W)
867 .Default(FP_FORMAT_NONE);
868}
Jack Carterb4dbc172012-09-05 23:34:03 +0000869
Jack Carter0b744b32012-10-04 02:29:46 +0000870bool MipsAssemblerOptions::setATReg(unsigned Reg) {
871 if (Reg > 31)
872 return false;
873
874 aTReg = Reg;
875 return true;
876}
877
Jack Carter1ac53222013-02-20 23:11:17 +0000878int MipsAsmParser::getATReg() {
879 return Options.getATRegNum();
Jack Carter0b744b32012-10-04 02:29:46 +0000880}
881
Jack Carterd0bd6422013-04-18 00:41:53 +0000882unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000883 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
884}
885
Jack Carter873c7242013-01-12 01:03:14 +0000886int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000887
888 if (RegNum > 31)
889 return -1;
890
Jack Carter873c7242013-01-12 01:03:14 +0000891 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +0000892}
893
Jack Carter873c7242013-01-12 01:03:14 +0000894int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000895 const AsmToken &Tok = Parser.getTok();
896 int RegNum = -1;
897
898 if (Tok.is(AsmToken::Identifier)) {
899 std::string lowerCase = Tok.getString().lower();
Jack Carter873c7242013-01-12 01:03:14 +0000900 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000901 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +0000902 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carterd0bd6422013-04-18 00:41:53 +0000903 is64BitReg ? Mips::CPU64RegsRegClassID : Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000904 return RegNum;
905}
906
Jack Carterd0bd6422013-04-18 00:41:53 +0000907bool MipsAsmParser::tryParseRegisterOperand(
908 SmallVectorImpl<MCParsedAsmOperand*> &Operands, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000909
910 SMLoc S = Parser.getTok().getLoc();
911 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +0000912
Jack Carter873c7242013-01-12 01:03:14 +0000913 RegNo = tryParseRegister(is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000914 if (RegNo == -1)
915 return true;
916
Jack Carter873c7242013-01-12 01:03:14 +0000917 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterd0bd6422013-04-18 00:41:53 +0000918 Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000919 Parser.Lex(); // Eat register token.
920 return false;
921}
922
923bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
924 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +0000925 // Check if the current operand has a custom associated parser, if so, try to
926 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +0000927 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
928 if (ResTy == MatchOperand_Success)
929 return false;
930 // If there wasn't a custom match, try the generic matcher below. Otherwise,
931 // there was a match, but an error occurred, in which case, just return that
932 // the operand parsing failed.
933 if (ResTy == MatchOperand_ParseFail)
934 return true;
935
936 switch (getLexer().getKind()) {
937 default:
938 Error(Parser.getTok().getLoc(), "unexpected token in operand");
939 return true;
940 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000941 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +0000942 SMLoc S = Parser.getTok().getLoc();
943 Parser.Lex(); // Eat dollar token.
Jack Carterd0bd6422013-04-18 00:41:53 +0000944 // Parse the register operand.
Jack Carter873c7242013-01-12 01:03:14 +0000945 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000946 if (getLexer().is(AsmToken::LParen)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000947 // Check if it is indexed addressing operand.
Jack Carterb4dbc172012-09-05 23:34:03 +0000948 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carterd0bd6422013-04-18 00:41:53 +0000949 Parser.Lex(); // Eat the parenthesis.
Jack Carterb4dbc172012-09-05 23:34:03 +0000950 if (getLexer().isNot(AsmToken::Dollar))
951 return true;
952
Jack Carterd0bd6422013-04-18 00:41:53 +0000953 Parser.Lex(); // Eat the dollar
Jack Carter873c7242013-01-12 01:03:14 +0000954 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterb4dbc172012-09-05 23:34:03 +0000955 return true;
956
957 if (!getLexer().is(AsmToken::RParen))
958 return true;
959
960 S = Parser.getTok().getLoc();
961 Operands.push_back(MipsOperand::CreateToken(")", S));
962 Parser.Lex();
963 }
964 return false;
965 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000966 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +0000967 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000968 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +0000969 return true;
970
Jack Carter873c7242013-01-12 01:03:14 +0000971 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000972
Benjamin Kramerfa530572012-09-07 09:47:42 +0000973 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterb4dbc172012-09-05 23:34:03 +0000974
Jack Carterd0bd6422013-04-18 00:41:53 +0000975 // Otherwise create a symbol reference.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000976 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterb4dbc172012-09-05 23:34:03 +0000977 getContext());
978
979 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
980 return false;
981 }
982 case AsmToken::Identifier:
Jack Carterd76b2372013-03-21 21:44:16 +0000983 // Look for the existing symbol, we should check if
Jack Carterd0bd6422013-04-18 00:41:53 +0000984 // we need to assigne the propper RegisterKind.
985 if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
986 return false;
987 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +0000988 case AsmToken::LParen:
989 case AsmToken::Minus:
990 case AsmToken::Plus:
991 case AsmToken::Integer:
992 case AsmToken::String: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000993 // Quoted label names.
Jack Carterb4dbc172012-09-05 23:34:03 +0000994 const MCExpr *IdVal;
995 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000996 if (getParser().parseExpression(IdVal))
Jack Carterb4dbc172012-09-05 23:34:03 +0000997 return true;
Jack Carter873c7242013-01-12 01:03:14 +0000998 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000999 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1000 return false;
1001 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001002 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001003 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001004 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001005 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001006 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001007 return true;
1008
Jack Carter873c7242013-01-12 01:03:14 +00001009 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1010
Jack Carterdc1e35d2012-09-06 20:00:02 +00001011 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1012 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001013 } // case AsmToken::Percent
1014 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001015 return true;
1016}
1017
Jack Carterb5cf5902013-04-17 00:18:04 +00001018const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
1019 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001020 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001021 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001022 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001023 // It's a constant, evaluate lo or hi value.
Jack Carterb5cf5902013-04-17 00:18:04 +00001024 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001025 short Val = MCE->getValue();
1026 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001027 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001028 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001029 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001030 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001031 // Lower part is treated as a signed int, so if it is negative
Jack Carterd0bd6422013-04-18 00:41:53 +00001032 // we must add 1 to the hi part to compensate.
Jack Carterdc463382013-02-21 02:09:31 +00001033 if (LoSign)
1034 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001035 Res = MCConstantExpr::Create(Val, getContext());
Evgeniy Stepanov3d8ab192013-04-17 06:45:11 +00001036 } else {
1037 llvm_unreachable("Invalid RelocStr value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001038 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001039 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001040 }
1041
Jack Carterb5cf5902013-04-17 00:18:04 +00001042 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001043 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001044 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001045 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001046 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001047 return Res;
1048 }
1049
1050 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001051 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1052 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001053 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1054 return Res;
1055 }
1056
1057 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001058 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1059 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1060 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001061 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001062 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001063 return Expr;
1064}
1065
1066bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1067
1068 switch (Expr->getKind()) {
1069 case MCExpr::Constant:
1070 return true;
1071 case MCExpr::SymbolRef:
1072 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1073 case MCExpr::Binary:
1074 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1075 if (!isEvaluated(BE->getLHS()))
1076 return false;
1077 return isEvaluated(BE->getRHS());
1078 }
1079 case MCExpr::Unary:
1080 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1081 default:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001082 return false;
1083 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001084 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001085}
Jack Carterd0bd6422013-04-18 00:41:53 +00001086
Jack Carterb5cf5902013-04-17 00:18:04 +00001087bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001088 Parser.Lex(); // Eat the % token.
1089 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001090 if (Tok.isNot(AsmToken::Identifier))
1091 return true;
1092
1093 std::string Str = Tok.getIdentifier().str();
1094
Jack Carterd0bd6422013-04-18 00:41:53 +00001095 Parser.Lex(); // Eat the identifier.
1096 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001097 const MCExpr *IdVal;
1098 SMLoc EndLoc;
1099
1100 if (getLexer().getKind() == AsmToken::LParen) {
1101 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001102 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001103 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001104 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001105 const AsmToken &nextTok = Parser.getTok();
1106 if (nextTok.isNot(AsmToken::Identifier))
1107 return true;
1108 Str += "(%";
1109 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001110 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001111 if (getLexer().getKind() != AsmToken::LParen)
1112 return true;
1113 } else
1114 break;
1115 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001116 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001117 return true;
1118
1119 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001120 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001121
1122 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001123 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001124
Jack Carterd0bd6422013-04-18 00:41:53 +00001125 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001126 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001127}
1128
Jack Carterb4dbc172012-09-05 23:34:03 +00001129bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1130 SMLoc &EndLoc) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001131 StartLoc = Parser.getTok().getLoc();
Jack Carter873c7242013-01-12 01:03:14 +00001132 RegNo = tryParseRegister(isMips64());
1133 EndLoc = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001134 return (RegNo == (unsigned) -1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001135}
1136
Jack Carterb5cf5902013-04-17 00:18:04 +00001137bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001138 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001139 bool Result = true;
1140
1141 while (getLexer().getKind() == AsmToken::LParen)
1142 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001143
Jack Carterd0bd6422013-04-18 00:41:53 +00001144 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001145 default:
1146 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001147 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001148 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001149 case AsmToken::Integer:
1150 case AsmToken::Minus:
1151 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001152 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001153 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001154 else
1155 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001156 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001157 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001158 break;
Jack Carter873c7242013-01-12 01:03:14 +00001159 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001160 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001161 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001162 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001163}
1164
Jack Carterb4dbc172012-09-05 23:34:03 +00001165MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Jack Carterd0bd6422013-04-18 00:41:53 +00001166 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001167
1168 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001169 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001170 bool isParenExpr = false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001171 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001172 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001173
Jack Carterb5cf5902013-04-17 00:18:04 +00001174 if (getLexer().getKind() == AsmToken::LParen) {
1175 Parser.Lex();
1176 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001177 }
1178
Jack Carterb5cf5902013-04-17 00:18:04 +00001179 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001180 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001181 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001182
Jack Carterd0bd6422013-04-18 00:41:53 +00001183 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001184 if (Tok.isNot(AsmToken::LParen)) {
1185 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
1186 if (Mnemonic->getToken() == "la") {
1187 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001188 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001189 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1190 return MatchOperand_Success;
1191 }
1192 if (Tok.is(AsmToken::EndOfStatement)) {
1193 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001194 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001195
Jack Carterd0bd6422013-04-18 00:41:53 +00001196 // Zero register assumed, add a memory operand with ZERO as its base.
1197 Operands.push_back(MipsOperand::CreateMem(isMips64() ? Mips::ZERO_64
1198 : Mips::ZERO,
1199 IdVal, S, E));
Jack Carterb5cf5902013-04-17 00:18:04 +00001200 return MatchOperand_Success;
1201 }
1202 Error(Parser.getTok().getLoc(), "'(' expected");
1203 return MatchOperand_ParseFail;
1204 }
1205
Jack Carterd0bd6422013-04-18 00:41:53 +00001206 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001207 }
1208
1209 const AsmToken &Tok1 = Parser.getTok(); // Get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +00001210 if (Tok1.is(AsmToken::Dollar)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001211 Parser.Lex(); // Eat the '$' token.
Jack Carter873c7242013-01-12 01:03:14 +00001212 if (tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001213 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1214 return MatchOperand_ParseFail;
1215 }
1216
1217 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001218 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001219 return MatchOperand_ParseFail;
1220 }
1221
Jack Carterd0bd6422013-04-18 00:41:53 +00001222 const AsmToken &Tok2 = Parser.getTok(); // Get next token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001223 if (Tok2.isNot(AsmToken::RParen)) {
1224 Error(Parser.getTok().getLoc(), "')' expected");
1225 return MatchOperand_ParseFail;
1226 }
1227
Jack Carter873c7242013-01-12 01:03:14 +00001228 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1229
Jack Carterd0bd6422013-04-18 00:41:53 +00001230 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001231
1232 if (IdVal == 0)
1233 IdVal = MCConstantExpr::Create(0, getContext());
1234
Jack Carterd0bd6422013-04-18 00:41:53 +00001235 // Replace the register operand with the memory operand.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001236 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1237 int RegNo = op->getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001238 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001239 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001240 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001241 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1242 int64_t Imm;
1243 if (IdVal->EvaluateAsAbsolute(Imm))
1244 IdVal = MCConstantExpr::Create(Imm, getContext());
1245 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1246 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1247 getContext());
1248 }
1249
Jack Carterdc1e35d2012-09-06 20:00:02 +00001250 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1251 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +00001252 return MatchOperand_Success;
1253}
1254
Jack Carter873c7242013-01-12 01:03:14 +00001255MipsAsmParser::OperandMatchResultTy
1256MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1257
1258 if (!isMips64())
1259 return MatchOperand_NoMatch;
Jack Carterd76b2372013-03-21 21:44:16 +00001260 if (getLexer().getKind() == AsmToken::Identifier) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001261 if (searchSymbolAlias(Operands, MipsOperand::Kind_CPU64Regs))
Jack Carterd76b2372013-03-21 21:44:16 +00001262 return MatchOperand_Success;
1263 return MatchOperand_NoMatch;
1264 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001265 // If the first token is not '$', we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001266 if (Parser.getTok().isNot(AsmToken::Dollar))
1267 return MatchOperand_NoMatch;
1268
1269 Parser.Lex(); // Eat $
Jack Carterd0bd6422013-04-18 00:41:53 +00001270 if (!tryParseRegisterOperand(Operands, true)) {
1271 // Set the proper register kind.
Jack Carter873c7242013-01-12 01:03:14 +00001272 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1273 op->setRegKind(MipsOperand::Kind_CPU64Regs);
1274 return MatchOperand_Success;
1275 }
1276 return MatchOperand_NoMatch;
1277}
1278
Jack Carterd0bd6422013-04-18 00:41:53 +00001279bool MipsAsmParser::searchSymbolAlias(
1280 SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegisterKind) {
Jack Carterd76b2372013-03-21 21:44:16 +00001281
1282 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1283 if (Sym) {
1284 SMLoc S = Parser.getTok().getLoc();
1285 const MCExpr *Expr;
1286 if (Sym->isVariable())
1287 Expr = Sym->getVariableValue();
1288 else
1289 return false;
1290 if (Expr->getKind() == MCExpr::SymbolRef) {
1291 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
1292 const StringRef DefSymbol = Ref->getSymbol().getName();
1293 if (DefSymbol.startswith("$")) {
Jack Carter02593002013-05-28 22:21:05 +00001294 int RegNum = -1;
1295 APInt IntVal(32, -1);
1296 if (!DefSymbol.substr(1).getAsInteger(10, IntVal))
1297 RegNum = matchRegisterByNumber(IntVal.getZExtValue(),
1298 isMips64()
1299 ? Mips::CPU64RegsRegClassID
1300 : Mips::CPURegsRegClassID);
1301 else
1302 // Lookup for the register with corresponding name
1303 RegNum = matchRegisterName(DefSymbol.substr(1), isMips64());
Jack Carterd76b2372013-03-21 21:44:16 +00001304 if (RegNum > -1) {
1305 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001306 MipsOperand *op = MipsOperand::CreateReg(RegNum, S,
1307 Parser.getTok().getLoc());
1308 op->setRegKind((MipsOperand::RegisterKind) RegisterKind);
Jack Carterd76b2372013-03-21 21:44:16 +00001309 Operands.push_back(op);
1310 return true;
1311 }
1312 }
1313 } else if (Expr->getKind() == MCExpr::Constant) {
1314 Parser.Lex();
1315 const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001316 MipsOperand *op = MipsOperand::CreateImm(Const, S,
Jack Carter02593002013-05-28 22:21:05 +00001317 Parser.getTok().getLoc());
Jack Carterd76b2372013-03-21 21:44:16 +00001318 Operands.push_back(op);
1319 return true;
1320 }
1321 }
1322 return false;
1323}
Jack Carterd0bd6422013-04-18 00:41:53 +00001324
Jack Carter873c7242013-01-12 01:03:14 +00001325MipsAsmParser::OperandMatchResultTy
1326MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1327
Jack Carterd76b2372013-03-21 21:44:16 +00001328 if (getLexer().getKind() == AsmToken::Identifier) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001329 if (searchSymbolAlias(Operands, MipsOperand::Kind_CPURegs))
Jack Carterd76b2372013-03-21 21:44:16 +00001330 return MatchOperand_Success;
1331 return MatchOperand_NoMatch;
1332 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001333 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001334 if (Parser.getTok().isNot(AsmToken::Dollar))
1335 return MatchOperand_NoMatch;
1336
1337 Parser.Lex(); // Eat $
Jack Carterd0bd6422013-04-18 00:41:53 +00001338 if (!tryParseRegisterOperand(Operands, false)) {
1339 // Set the proper register kind.
Jack Carter873c7242013-01-12 01:03:14 +00001340 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1341 op->setRegKind(MipsOperand::Kind_CPURegs);
1342 return MatchOperand_Success;
1343 }
1344 return MatchOperand_NoMatch;
1345}
1346
1347MipsAsmParser::OperandMatchResultTy
1348MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1349
Jack Carter2a74a87b2013-01-17 00:28:20 +00001350 if (isMips64())
1351 return MatchOperand_NoMatch;
1352
Jack Carterd0bd6422013-04-18 00:41:53 +00001353 // If the first token is not '$' we have error.
Jack Carter873c7242013-01-12 01:03:14 +00001354 if (Parser.getTok().isNot(AsmToken::Dollar))
1355 return MatchOperand_NoMatch;
1356 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001357 Parser.Lex(); // Eat the '$'.
Jack Carter873c7242013-01-12 01:03:14 +00001358
Jack Carterd0bd6422013-04-18 00:41:53 +00001359 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001360 if (Tok.isNot(AsmToken::Integer))
1361 return MatchOperand_NoMatch;
1362
1363 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001364 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001365 if (RegNum != 29)
1366 return MatchOperand_ParseFail;
1367
1368 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001369 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001370 op->setRegKind(MipsOperand::Kind_HWRegs);
1371 Operands.push_back(op);
1372
Jack Carterd0bd6422013-04-18 00:41:53 +00001373 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001374 return MatchOperand_Success;
1375}
1376
1377MipsAsmParser::OperandMatchResultTy
Jack Carterd0bd6422013-04-18 00:41:53 +00001378MipsAsmParser::parseHW64Regs(
1379 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter2a74a87b2013-01-17 00:28:20 +00001380
1381 if (!isMips64())
1382 return MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001383 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001384 if (Parser.getTok().isNot(AsmToken::Dollar))
1385 return MatchOperand_NoMatch;
1386 SMLoc S = Parser.getTok().getLoc();
1387 Parser.Lex(); // Eat $
1388
Jack Carterd0bd6422013-04-18 00:41:53 +00001389 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001390 if (Tok.isNot(AsmToken::Integer))
1391 return MatchOperand_NoMatch;
1392
1393 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001394 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001395 if (RegNum != 29)
1396 return MatchOperand_ParseFail;
1397
1398 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001399 Parser.getTok().getLoc());
Jack Carter2a74a87b2013-01-17 00:28:20 +00001400 op->setRegKind(MipsOperand::Kind_HW64Regs);
Jack Carter873c7242013-01-12 01:03:14 +00001401 Operands.push_back(op);
1402
Jack Carterd0bd6422013-04-18 00:41:53 +00001403 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001404 return MatchOperand_Success;
1405}
1406
1407MipsAsmParser::OperandMatchResultTy
1408MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1409 unsigned RegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001410 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001411 if (Parser.getTok().isNot(AsmToken::Dollar))
1412 return MatchOperand_NoMatch;
1413 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001414 Parser.Lex(); // Eat the '$'
Jack Carter873c7242013-01-12 01:03:14 +00001415
Jack Carterd0bd6422013-04-18 00:41:53 +00001416 const AsmToken &Tok = Parser.getTok(); // Get next token.
Jack Carter873c7242013-01-12 01:03:14 +00001417 if (Tok.is(AsmToken::Integer)) {
1418 RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001419 // At the moment only fcc0 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001420 if (RegNum != 0)
1421 return MatchOperand_ParseFail;
1422 } else if (Tok.is(AsmToken::Identifier)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001423 // At the moment only fcc0 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001424 if (Tok.getIdentifier() != "fcc0")
1425 return MatchOperand_ParseFail;
1426 } else
1427 return MatchOperand_NoMatch;
1428
1429 MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001430 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001431 op->setRegKind(MipsOperand::Kind_CCRRegs);
1432 Operands.push_back(op);
1433
Jack Carterd0bd6422013-04-18 00:41:53 +00001434 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001435 return MatchOperand_Success;
1436}
1437
Jack Carterdc1e35d2012-09-06 20:00:02 +00001438MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1439
1440 MCSymbolRefExpr::VariantKind VK
1441 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1442 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1443 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1444 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1445 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1446 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1447 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1448 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1449 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1450 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1451 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1452 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1453 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1454 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1455 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1456 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1457 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1458 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1459 .Default(MCSymbolRefExpr::VK_None);
1460
1461 return VK;
1462}
Vladimir Medicea381912013-06-04 08:28:53 +00001463// Converts condition string to immediate operand value.
Benjamin Kramer47b5c572012-09-10 11:52:14 +00001464static int ConvertCcString(StringRef CondString) {
Jack Cartera63b16a2012-09-07 00:23:42 +00001465 int CC = StringSwitch<unsigned>(CondString)
Jack Carterd0bd6422013-04-18 00:41:53 +00001466 .Case(".f", 0)
1467 .Case(".un", 1)
1468 .Case(".eq", 2)
1469 .Case(".ueq", 3)
1470 .Case(".olt", 4)
1471 .Case(".ult", 5)
1472 .Case(".ole", 6)
1473 .Case(".ule", 7)
1474 .Case(".sf", 8)
1475 .Case(".ngle", 9)
1476 .Case(".seq", 10)
1477 .Case(".ngl", 11)
1478 .Case(".lt", 12)
1479 .Case(".nge", 13)
1480 .Case(".le", 14)
1481 .Case(".ngt", 15)
1482 .Default(-1);
Jack Cartera63b16a2012-09-07 00:23:42 +00001483
1484 return CC;
1485}
1486
1487bool MipsAsmParser::
1488parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter0b744b32012-10-04 02:29:46 +00001489 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001490 // Split the format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001491 size_t Start = Name.find('.'), Next = Name.rfind('.');
1492 StringRef Format1 = Name.slice(Start, Next);
Jack Carterd0bd6422013-04-18 00:41:53 +00001493 // Add the first format to the operands.
Jack Cartera63b16a2012-09-07 00:23:42 +00001494 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carterd0bd6422013-04-18 00:41:53 +00001495 // Now for the second format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001496 StringRef Format2 = Name.slice(Next, StringRef::npos);
1497 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1498
Jack Carterd0bd6422013-04-18 00:41:53 +00001499 // Set the format for the first register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001500 setFpFormat(Format1);
1501
1502 // Read the remaining operands.
1503 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1504 // Read the first operand.
1505 if (ParseOperand(Operands, Name)) {
1506 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001507 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001508 return Error(Loc, "unexpected token in argument list");
1509 }
1510
1511 if (getLexer().isNot(AsmToken::Comma)) {
1512 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001513 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001514 return Error(Loc, "unexpected token in argument list");
Jack Cartera63b16a2012-09-07 00:23:42 +00001515 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001516 Parser.Lex(); // Eat the comma.
Jack Cartera63b16a2012-09-07 00:23:42 +00001517
Jack Carterb5cf5902013-04-17 00:18:04 +00001518 // Set the format for the first register
Jack Cartera63b16a2012-09-07 00:23:42 +00001519 setFpFormat(Format2);
1520
1521 // Parse and remember the operand.
1522 if (ParseOperand(Operands, Name)) {
1523 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001524 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001525 return Error(Loc, "unexpected token in argument list");
1526 }
1527 }
1528
1529 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1530 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001531 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001532 return Error(Loc, "unexpected token in argument list");
1533 }
1534
Jack Carterd0bd6422013-04-18 00:41:53 +00001535 Parser.Lex(); // Consume the EndOfStatement.
Jack Cartera63b16a2012-09-07 00:23:42 +00001536 return false;
1537}
1538
Rafael Espindola870c4e92012-01-11 03:56:41 +00001539bool MipsAsmParser::
Chad Rosierf0e87202012-10-25 20:41:34 +00001540ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindola870c4e92012-01-11 03:56:41 +00001541 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter1ac53222013-02-20 23:11:17 +00001542 StringRef Mnemonic;
Jack Carterd0bd6422013-04-18 00:41:53 +00001543 // Floating point instructions: Should the register be treated as a double?
Jack Cartera63b16a2012-09-07 00:23:42 +00001544 if (requestsDoubleOperand(Name)) {
1545 setFpFormat(FP_FORMAT_D);
Jack Carterd0bd6422013-04-18 00:41:53 +00001546 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
1547 Mnemonic = Name;
1548 } else {
Jack Cartera63b16a2012-09-07 00:23:42 +00001549 setDefaultFpFormat();
1550 // Create the leading tokens for the mnemonic, split by '.' characters.
1551 size_t Start = 0, Next = Name.find('.');
Jack Carter1ac53222013-02-20 23:11:17 +00001552 Mnemonic = Name.slice(Start, Next);
Jack Cartera63b16a2012-09-07 00:23:42 +00001553
1554 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1555
1556 if (Next != StringRef::npos) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001557 // There is a format token in mnemonic.
1558 size_t Dot = Name.find('.', Next + 1);
Jack Cartera63b16a2012-09-07 00:23:42 +00001559 StringRef Format = Name.slice(Next, Dot);
Jack Carterd0bd6422013-04-18 00:41:53 +00001560 if (Dot == StringRef::npos) // Only one '.' in a string, it's a format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001561 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1562 else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001563 if (Name.startswith("c.")) {
1564 // Floating point compare, add '.' and immediate represent for cc.
Jack Cartera63b16a2012-09-07 00:23:42 +00001565 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1566 int Cc = ConvertCcString(Format);
1567 if (Cc == -1) {
1568 return Error(NameLoc, "Invalid conditional code");
1569 }
Jack Carter873c7242013-01-12 01:03:14 +00001570 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001571 Parser.getTok().getLoc().getPointer() - 1);
1572 Operands.push_back(
1573 MipsOperand::CreateImm(MCConstantExpr::Create(Cc, getContext()),
1574 NameLoc, E));
Jack Cartera63b16a2012-09-07 00:23:42 +00001575 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001576 // trunc, ceil, floor ...
Jack Cartera63b16a2012-09-07 00:23:42 +00001577 return parseMathOperation(Name, NameLoc, Operands);
1578 }
1579
Jack Carterd0bd6422013-04-18 00:41:53 +00001580 // The rest is a format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001581 Format = Name.slice(Dot, StringRef::npos);
1582 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1583 }
1584
1585 setFpFormat(Format);
1586 }
1587 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001588
1589 // Read the remaining operands.
1590 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1591 // Read the first operand.
Jack Carter1ac53222013-02-20 23:11:17 +00001592 if (ParseOperand(Operands, Mnemonic)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001593 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001594 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001595 return Error(Loc, "unexpected token in argument list");
1596 }
1597
Jack Carterd0bd6422013-04-18 00:41:53 +00001598 while (getLexer().is(AsmToken::Comma)) {
1599 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00001600
1601 // Parse and remember the operand.
1602 if (ParseOperand(Operands, Name)) {
1603 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001604 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001605 return Error(Loc, "unexpected token in argument list");
1606 }
1607 }
1608 }
1609
1610 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1611 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001612 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001613 return Error(Loc, "unexpected token in argument list");
1614 }
1615
Jack Carterd0bd6422013-04-18 00:41:53 +00001616 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00001617 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00001618}
1619
Jack Carter0b744b32012-10-04 02:29:46 +00001620bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001621 SMLoc Loc = getLexer().getLoc();
1622 Parser.eatToEndOfStatement();
1623 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00001624}
1625
1626bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001627 // Line should look like: ".set noat".
1628 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00001629 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00001630 // eat noat
1631 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001632 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001633 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1634 reportParseError("unexpected token in statement");
1635 return false;
1636 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001637 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001638 return false;
1639}
Jack Carterd0bd6422013-04-18 00:41:53 +00001640
Jack Carter0b744b32012-10-04 02:29:46 +00001641bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001642 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00001643 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00001644 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00001645 getParser().Lex();
1646 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00001647 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00001648 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001649 return false;
1650 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001651 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00001652 if (getLexer().isNot(AsmToken::Dollar)) {
1653 reportParseError("unexpected token in statement");
1654 return false;
1655 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001656 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00001657 const AsmToken &Reg = Parser.getTok();
1658 if (Reg.is(AsmToken::Identifier)) {
1659 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
1660 } else if (Reg.is(AsmToken::Integer)) {
1661 AtRegNo = Reg.getIntVal();
1662 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001663 reportParseError("unexpected token in statement");
1664 return false;
1665 }
Jack Carter1ac53222013-02-20 23:11:17 +00001666
Jack Carterd0bd6422013-04-18 00:41:53 +00001667 if (AtRegNo < 1 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00001668 reportParseError("unexpected token in statement");
1669 return false;
1670 }
1671
1672 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00001673 reportParseError("unexpected token in statement");
1674 return false;
1675 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001676 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00001677
1678 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1679 reportParseError("unexpected token in statement");
1680 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001681 }
1682 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001683 return false;
1684 } else {
1685 reportParseError("unexpected token in statement");
1686 return false;
1687 }
1688}
1689
1690bool MipsAsmParser::parseSetReorderDirective() {
1691 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001692 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001693 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1694 reportParseError("unexpected token in statement");
1695 return false;
1696 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001697 Options.setReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00001698 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001699 return false;
1700}
1701
1702bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001703 Parser.Lex();
1704 // If this is not the end of the statement, report an error.
1705 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1706 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00001707 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001708 }
1709 Options.setNoreorder();
1710 Parser.Lex(); // Consume the EndOfStatement.
1711 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001712}
1713
1714bool MipsAsmParser::parseSetMacroDirective() {
1715 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001716 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001717 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1718 reportParseError("unexpected token in statement");
1719 return false;
1720 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001721 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001722 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001723 return false;
1724}
1725
1726bool MipsAsmParser::parseSetNoMacroDirective() {
1727 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001728 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001729 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1730 reportParseError("`noreorder' must be set before `nomacro'");
1731 return false;
1732 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001733 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00001734 reportParseError("`noreorder' must be set before `nomacro'");
1735 return false;
1736 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001737 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001738 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001739 return false;
1740}
Jack Carterd76b2372013-03-21 21:44:16 +00001741
1742bool MipsAsmParser::parseSetAssignment() {
1743 StringRef Name;
1744 const MCExpr *Value;
1745
1746 if (Parser.parseIdentifier(Name))
1747 reportParseError("expected identifier after .set");
1748
1749 if (getLexer().isNot(AsmToken::Comma))
1750 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00001751 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00001752
Jack Carter02593002013-05-28 22:21:05 +00001753 if (getLexer().is(AsmToken::Dollar)) {
1754 MCSymbol *Symbol;
1755 SMLoc DollarLoc = getLexer().getLoc();
1756 // Consume the dollar sign, and check for a following identifier.
1757 Parser.Lex();
1758 // We have a '$' followed by something, make sure they are adjacent.
1759 if (DollarLoc.getPointer() + 1 != getTok().getLoc().getPointer())
1760 return true;
1761 StringRef Res = StringRef(DollarLoc.getPointer(),
1762 getTok().getEndLoc().getPointer() - DollarLoc.getPointer());
1763 Symbol = getContext().GetOrCreateSymbol(Res);
1764 Parser.Lex();
1765 Value = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
1766 getContext());
1767 } else if (Parser.parseExpression(Value))
1768 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00001769
Jack Carterd0bd6422013-04-18 00:41:53 +00001770 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00001771 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00001772 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00001773 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00001774 Sym = getContext().GetOrCreateSymbol(Name);
1775 Sym->setVariableValue(Value);
1776
1777 return false;
1778}
Jack Carterd0bd6422013-04-18 00:41:53 +00001779
Jack Carter0b744b32012-10-04 02:29:46 +00001780bool MipsAsmParser::parseDirectiveSet() {
1781
Jack Carterd0bd6422013-04-18 00:41:53 +00001782 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00001783 const AsmToken &Tok = Parser.getTok();
1784
1785 if (Tok.getString() == "noat") {
1786 return parseSetNoAtDirective();
1787 } else if (Tok.getString() == "at") {
1788 return parseSetAtDirective();
1789 } else if (Tok.getString() == "reorder") {
1790 return parseSetReorderDirective();
1791 } else if (Tok.getString() == "noreorder") {
1792 return parseSetNoReorderDirective();
1793 } else if (Tok.getString() == "macro") {
1794 return parseSetMacroDirective();
1795 } else if (Tok.getString() == "nomacro") {
1796 return parseSetNoMacroDirective();
1797 } else if (Tok.getString() == "nomips16") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001798 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001799 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001800 return false;
1801 } else if (Tok.getString() == "nomicromips") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001802 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001803 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001804 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001805 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001806 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00001807 parseSetAssignment();
1808 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001809 }
Jack Carter07c818d2013-01-25 01:31:34 +00001810
Jack Carter0b744b32012-10-04 02:29:46 +00001811 return true;
1812}
1813
Jack Carter07c818d2013-01-25 01:31:34 +00001814/// parseDirectiveWord
1815/// ::= .word [ expression (, expression)* ]
1816bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
1817 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1818 for (;;) {
1819 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001820 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00001821 return true;
1822
1823 getParser().getStreamer().EmitValue(Value, Size);
1824
1825 if (getLexer().is(AsmToken::EndOfStatement))
1826 break;
1827
1828 // FIXME: Improve diagnostic.
1829 if (getLexer().isNot(AsmToken::Comma))
1830 return Error(L, "unexpected token in directive");
1831 Parser.Lex();
1832 }
1833 }
1834
1835 Parser.Lex();
1836 return false;
1837}
1838
Jack Carter0b744b32012-10-04 02:29:46 +00001839bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +00001840
Jack Carter07c818d2013-01-25 01:31:34 +00001841 StringRef IDVal = DirectiveID.getString();
1842
Jack Carterd0bd6422013-04-18 00:41:53 +00001843 if (IDVal == ".ent") {
1844 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001845 Parser.Lex();
1846 return false;
1847 }
1848
Jack Carter07c818d2013-01-25 01:31:34 +00001849 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001850 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001851 Parser.Lex();
1852 return false;
1853 }
1854
Jack Carter07c818d2013-01-25 01:31:34 +00001855 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001856 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001857 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001858 return false;
1859 }
1860
Jack Carter07c818d2013-01-25 01:31:34 +00001861 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00001862 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00001863 }
1864
Jack Carter07c818d2013-01-25 01:31:34 +00001865 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001866 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001867 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001868 return false;
1869 }
1870
Jack Carter07c818d2013-01-25 01:31:34 +00001871 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001872 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001873 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001874 return false;
1875 }
1876
Jack Carter07c818d2013-01-25 01:31:34 +00001877 if (IDVal == ".gpword") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001878 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001879 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001880 return false;
1881 }
1882
Jack Carter07c818d2013-01-25 01:31:34 +00001883 if (IDVal == ".word") {
1884 parseDirectiveWord(4, DirectiveID.getLoc());
1885 return false;
1886 }
1887
Rafael Espindola870c4e92012-01-11 03:56:41 +00001888 return true;
1889}
1890
Rafael Espindola870c4e92012-01-11 03:56:41 +00001891extern "C" void LLVMInitializeMipsAsmParser() {
1892 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1893 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1894 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1895 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1896}
Jack Carterb4dbc172012-09-05 23:34:03 +00001897
1898#define GET_REGISTER_MATCHER
1899#define GET_MATCHER_IMPLEMENTATION
1900#include "MipsGenAsmMatcher.inc"