blob: befc573826e08c10cbd6e4b02025e9b4a2b4ee05 [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"
Rafael Espindola870c4e92012-01-11 03:56:41 +000023
24using namespace llvm;
25
26namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000027class MipsAssemblerOptions {
28public:
29 MipsAssemblerOptions():
30 aTReg(1), reorder(true), macro(true) {
31 }
Jack Carterb4dbc172012-09-05 23:34:03 +000032
Jack Carter0b744b32012-10-04 02:29:46 +000033 unsigned getATRegNum() {return aTReg;}
34 bool setATReg(unsigned Reg);
35
36 bool isReorder() {return reorder;}
37 void setReorder() {reorder = true;}
38 void setNoreorder() {reorder = false;}
39
40 bool isMacro() {return macro;}
41 void setMacro() {macro = true;}
42 void setNomacro() {macro = false;}
43
44private:
45 unsigned aTReg;
46 bool reorder;
47 bool macro;
48};
49}
50
51namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000052class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka7605630c2012-08-17 20:16:42 +000053
Jack Cartera63b16a2012-09-07 00:23:42 +000054 enum FpFormatTy {
55 FP_FORMAT_NONE = -1,
56 FP_FORMAT_S,
57 FP_FORMAT_D,
58 FP_FORMAT_L,
59 FP_FORMAT_W
60 } FpFormat;
61
Jack Carterb4dbc172012-09-05 23:34:03 +000062 MCSubtargetInfo &STI;
63 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000064 MipsAssemblerOptions Options;
Jack Carter0b744b32012-10-04 02:29:46 +000065
Akira Hatanaka7605630c2012-08-17 20:16:42 +000066#define GET_ASSEMBLER_HEADER
67#include "MipsGenAsmMatcher.inc"
68
Chad Rosier49963552012-10-13 00:26:04 +000069 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +000070 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +000071 MCStreamer &Out, unsigned &ErrorInfo,
72 bool MatchingInlineAsm);
Rafael Espindola870c4e92012-01-11 03:56:41 +000073
74 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
75
Chad Rosierf0e87202012-10-25 20:41:34 +000076 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
77 SMLoc NameLoc,
Akira Hatanaka7605630c2012-08-17 20:16:42 +000078 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindola870c4e92012-01-11 03:56:41 +000079
Jack Cartera63b16a2012-09-07 00:23:42 +000080 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
81 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
82
Rafael Espindola870c4e92012-01-11 03:56:41 +000083 bool ParseDirective(AsmToken DirectiveID);
84
Jack Carterb4dbc172012-09-05 23:34:03 +000085 MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +000086 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
87
88 MipsAsmParser::OperandMatchResultTy
89 parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
90
91 MipsAsmParser::OperandMatchResultTy
92 parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
93
94 MipsAsmParser::OperandMatchResultTy
95 parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
96
97 MipsAsmParser::OperandMatchResultTy
98 parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
99
100 MipsAsmParser::OperandMatchResultTy
101 parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Chad Rosier391d29972012-09-03 18:47:45 +0000102
Jack Carterd76b2372013-03-21 21:44:16 +0000103 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
104 unsigned RegisterClass);
105
Jack Carterb4dbc172012-09-05 23:34:03 +0000106 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
107 StringRef Mnemonic);
108
Jack Carter873c7242013-01-12 01:03:14 +0000109 int tryParseRegister(bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000110
111 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carter873c7242013-01-12 01:03:14 +0000112 bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000113
Jack Carter30a59822012-10-04 04:03:53 +0000114 bool needsExpansion(MCInst &Inst);
115
116 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000117 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000118 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000119 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000120 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
121 SmallVectorImpl<MCInst> &Instructions);
122 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
123 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000124 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
125 SmallVectorImpl<MCInst> &Instructions,
126 bool isLoad,bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000127 bool reportParseError(StringRef ErrorMsg);
128
Jack Carterb5cf5902013-04-17 00:18:04 +0000129 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000130 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000131
Jack Carterb5cf5902013-04-17 00:18:04 +0000132 const MCExpr* evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
133
134 bool isEvaluated(const MCExpr *Expr);
Jack Carter0b744b32012-10-04 02:29:46 +0000135 bool parseDirectiveSet();
136
137 bool parseSetAtDirective();
138 bool parseSetNoAtDirective();
139 bool parseSetMacroDirective();
140 bool parseSetNoMacroDirective();
141 bool parseSetReorderDirective();
142 bool parseSetNoReorderDirective();
143
Jack Carterd76b2372013-03-21 21:44:16 +0000144 bool parseSetAssignment();
145
Jack Carter07c818d2013-01-25 01:31:34 +0000146 bool parseDirectiveWord(unsigned Size, SMLoc L);
147
Jack Carterdc1e35d2012-09-06 20:00:02 +0000148 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000149
Jack Carterb4dbc172012-09-05 23:34:03 +0000150 bool isMips64() const {
151 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
152 }
153
Jack Cartera63b16a2012-09-07 00:23:42 +0000154 bool isFP64() const {
155 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
156 }
157
Jack Carter873c7242013-01-12 01:03:14 +0000158 int matchRegisterName(StringRef Symbol, bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000159
Jack Carter1ac53222013-02-20 23:11:17 +0000160 int matchCPURegisterName(StringRef Symbol);
161
Jack Carter873c7242013-01-12 01:03:14 +0000162 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000163
Jack Cartera63b16a2012-09-07 00:23:42 +0000164 void setFpFormat(FpFormatTy Format) {
165 FpFormat = Format;
166 }
167
168 void setDefaultFpFormat();
169
170 void setFpFormat(StringRef Format);
171
172 FpFormatTy getFpFormat() {return FpFormat;}
173
174 bool requestsDoubleOperand(StringRef Mnemonic);
175
Jack Carterd0bd6422013-04-18 00:41:53 +0000176 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000177
Jack Carter1ac53222013-02-20 23:11:17 +0000178 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000179
180 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
181 SmallVectorImpl<MCInst> &Instructions);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000182public:
183 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterb4dbc172012-09-05 23:34:03 +0000184 : MCTargetAsmParser(), STI(sti), Parser(parser) {
185 // Initialize the set of available features.
186 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindola870c4e92012-01-11 03:56:41 +0000187 }
188
Jack Carterb4dbc172012-09-05 23:34:03 +0000189 MCAsmParser &getParser() const { return Parser; }
190 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
191
Rafael Espindola870c4e92012-01-11 03:56:41 +0000192};
193}
194
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000195namespace {
196
197/// MipsOperand - Instances of this class represent a parsed Mips machine
198/// instruction.
199class MipsOperand : public MCParsedAsmOperand {
Jack Carterb4dbc172012-09-05 23:34:03 +0000200
Jack Carter873c7242013-01-12 01:03:14 +0000201public:
202 enum RegisterKind {
203 Kind_None,
204 Kind_CPURegs,
205 Kind_CPU64Regs,
206 Kind_HWRegs,
207 Kind_HW64Regs,
208 Kind_FGR32Regs,
209 Kind_FGR64Regs,
Jack Carter1ac53222013-02-20 23:11:17 +0000210 Kind_AFGR64Regs,
Jack Carter873c7242013-01-12 01:03:14 +0000211 Kind_CCRRegs
212 };
213
214private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000215 enum KindTy {
216 k_CondCode,
217 k_CoprocNum,
218 k_Immediate,
219 k_Memory,
220 k_PostIndexRegister,
221 k_Register,
222 k_Token
223 } Kind;
224
225 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterb4dbc172012-09-05 23:34:03 +0000226
Eric Christopher8996c5d2013-03-15 00:42:55 +0000227 struct Token {
228 const char *Data;
229 unsigned Length;
230 };
231
232 struct RegOp {
233 unsigned RegNum;
234 RegisterKind Kind;
235 };
236
237 struct ImmOp {
238 const MCExpr *Val;
239 };
240
241 struct MemOp {
242 unsigned Base;
243 const MCExpr *Off;
244 };
245
Jack Carterb4dbc172012-09-05 23:34:03 +0000246 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000247 struct Token Tok;
248 struct RegOp Reg;
249 struct ImmOp Imm;
250 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000251 };
252
253 SMLoc StartLoc, EndLoc;
254
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000255public:
256 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000257 assert(N == 1 && "Invalid number of operands!");
258 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000259 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000260
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000261 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterb4dbc172012-09-05 23:34:03 +0000262 // Add as immediate when possible. Null MCExpr = 0.
263 if (Expr == 0)
264 Inst.addOperand(MCOperand::CreateImm(0));
265 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
266 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
267 else
268 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000269 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000270
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000271 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000272 assert(N == 1 && "Invalid number of operands!");
273 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000274 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000275 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000276
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000277 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000278 assert(N == 2 && "Invalid number of operands!");
279
280 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
281
282 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000283 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000284 }
285
286 bool isReg() const { return Kind == k_Register; }
287 bool isImm() const { return Kind == k_Immediate; }
288 bool isToken() const { return Kind == k_Token; }
289 bool isMem() const { return Kind == k_Memory; }
290
291 StringRef getToken() const {
292 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000293 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000294 }
295
296 unsigned getReg() const {
297 assert((Kind == k_Register) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000298 return Reg.RegNum;
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000299 }
300
Jack Carter873c7242013-01-12 01:03:14 +0000301 void setRegKind(RegisterKind RegKind) {
302 assert((Kind == k_Register) && "Invalid access!");
303 Reg.Kind = RegKind;
304 }
305
Jack Carterb4dbc172012-09-05 23:34:03 +0000306 const MCExpr *getImm() const {
307 assert((Kind == k_Immediate) && "Invalid access!");
308 return Imm.Val;
309 }
310
Jack Carterdc1e35d2012-09-06 20:00:02 +0000311 unsigned getMemBase() const {
312 assert((Kind == k_Memory) && "Invalid access!");
313 return Mem.Base;
314 }
315
316 const MCExpr *getMemOff() const {
317 assert((Kind == k_Memory) && "Invalid access!");
318 return Mem.Off;
319 }
320
Jack Carterb4dbc172012-09-05 23:34:03 +0000321 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
322 MipsOperand *Op = new MipsOperand(k_Token);
323 Op->Tok.Data = Str.data();
324 Op->Tok.Length = Str.size();
325 Op->StartLoc = S;
326 Op->EndLoc = S;
327 return Op;
328 }
329
330 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
331 MipsOperand *Op = new MipsOperand(k_Register);
332 Op->Reg.RegNum = RegNum;
333 Op->StartLoc = S;
334 Op->EndLoc = E;
335 return Op;
336 }
337
338 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
339 MipsOperand *Op = new MipsOperand(k_Immediate);
340 Op->Imm.Val = Val;
341 Op->StartLoc = S;
342 Op->EndLoc = E;
343 return Op;
344 }
345
Jack Carterdc1e35d2012-09-06 20:00:02 +0000346 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
347 SMLoc S, SMLoc E) {
348 MipsOperand *Op = new MipsOperand(k_Memory);
349 Op->Mem.Base = Base;
350 Op->Mem.Off = Off;
351 Op->StartLoc = S;
352 Op->EndLoc = E;
353 return Op;
354 }
355
Jack Carter873c7242013-01-12 01:03:14 +0000356 bool isCPURegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000357 return Kind == k_Register && Reg.Kind == Kind_CPURegs;
Jack Carter873c7242013-01-12 01:03:14 +0000358 }
359 void addCPURegsAsmOperands(MCInst &Inst, unsigned N) const {
360 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
361 }
362
363 bool isCPU64RegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000364 return Kind == k_Register && Reg.Kind == Kind_CPU64Regs;
Jack Carter873c7242013-01-12 01:03:14 +0000365 }
366 void addCPU64RegsAsmOperands(MCInst &Inst, unsigned N) const {
367 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
368 }
369
370 bool isHWRegsAsm() const {
371 assert((Kind == k_Register) && "Invalid access!");
372 return Reg.Kind == Kind_HWRegs;
373 }
374 void addHWRegsAsmOperands(MCInst &Inst, unsigned N) const {
375 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
376 }
377
378 bool isHW64RegsAsm() const {
379 assert((Kind == k_Register) && "Invalid access!");
380 return Reg.Kind == Kind_HW64Regs;
381 }
382 void addHW64RegsAsmOperands(MCInst &Inst, unsigned N) const {
383 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
384 }
385
386 void addCCRAsmOperands(MCInst &Inst, unsigned N) const {
387 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
388 }
389
390 bool isCCRAsm() const {
391 assert((Kind == k_Register) && "Invalid access!");
392 return Reg.Kind == Kind_CCRRegs;
393 }
394
Jack Carterb4dbc172012-09-05 23:34:03 +0000395 /// getStartLoc - Get the location of the first token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000396 SMLoc getStartLoc() const {
397 return StartLoc;
398 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000399 /// getEndLoc - Get the location of the last token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000400 SMLoc getEndLoc() const {
401 return EndLoc;
402 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000403
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000404 virtual void print(raw_ostream &OS) const {
405 llvm_unreachable("unimplemented!");
406 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000407}; // class MipsOperand
408} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000409
Jack Carter9e65aa32013-03-22 00:05:30 +0000410namespace llvm {
411extern const MCInstrDesc MipsInsts[];
412}
413static const MCInstrDesc &getInstDesc(unsigned Opcode) {
414 return MipsInsts[Opcode];
415}
416
417bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000418 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000419 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
420 Inst.setLoc(IDLoc);
421 if (MCID.mayLoad() || MCID.mayStore()) {
422 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000423 // reference or immediate we may have to expand instructions.
424 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000425 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Jack Carterd0bd6422013-04-18 00:41:53 +0000426 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY)
427 || (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000428 MCOperand &Op = Inst.getOperand(i);
429 if (Op.isImm()) {
430 int MemOffset = Op.getImm();
431 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000432 // Offset can't exceed 16bit value.
433 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000434 return false;
435 }
436 } else if (Op.isExpr()) {
437 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000438 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000439 const MCSymbolRefExpr *SR =
Jack Carterb5cf5902013-04-17 00:18:04 +0000440 static_cast<const MCSymbolRefExpr*>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000441 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000442 // Expand symbol.
443 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000444 return false;
445 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000446 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000447 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000448 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000449 }
450 }
451 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000452 } // for
453 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000454
455 if (needsExpansion(Inst))
456 expandInstruction(Inst, IDLoc, Instructions);
457 else
458 Instructions.push_back(Inst);
459
460 return false;
461}
462
Jack Carter30a59822012-10-04 04:03:53 +0000463bool MipsAsmParser::needsExpansion(MCInst &Inst) {
464
Jack Carterd0bd6422013-04-18 00:41:53 +0000465 switch (Inst.getOpcode()) {
466 case Mips::LoadImm32Reg:
467 case Mips::LoadAddr32Imm:
468 case Mips::LoadAddr32Reg:
469 return true;
470 default:
471 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000472 }
473}
Jack Carter92995f12012-10-06 00:53:28 +0000474
Jack Carter30a59822012-10-04 04:03:53 +0000475void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000476 SmallVectorImpl<MCInst> &Instructions) {
477 switch (Inst.getOpcode()) {
478 case Mips::LoadImm32Reg:
479 return expandLoadImm(Inst, IDLoc, Instructions);
480 case Mips::LoadAddr32Imm:
481 return expandLoadAddressImm(Inst, IDLoc, Instructions);
482 case Mips::LoadAddr32Reg:
483 return expandLoadAddressReg(Inst, IDLoc, Instructions);
484 }
Jack Carter30a59822012-10-04 04:03:53 +0000485}
Jack Carter92995f12012-10-06 00:53:28 +0000486
Jack Carter30a59822012-10-04 04:03:53 +0000487void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000488 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000489 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000490 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000491 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000492 const MCOperand &RegOp = Inst.getOperand(0);
493 assert(RegOp.isReg() && "expected register operand kind");
494
495 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000496 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000497 if (0 <= ImmValue && ImmValue <= 65535) {
498 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000499 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000500 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000501 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000502 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000503 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000504 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000505 } else if (ImmValue < 0 && ImmValue >= -32768) {
506 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000507 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000508 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000509 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000510 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000511 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000512 Instructions.push_back(tmpInst);
513 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000514 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000515 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000516 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000517 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000518 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
519 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000520 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000521 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000522 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000523 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
524 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
525 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
526 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000527 Instructions.push_back(tmpInst);
528 }
529}
Jack Carter92995f12012-10-06 00:53:28 +0000530
Jack Carter543fdf82012-10-09 23:29:45 +0000531void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000532 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000533 MCInst tmpInst;
534 const MCOperand &ImmOp = Inst.getOperand(2);
535 assert(ImmOp.isImm() && "expected immediate operand kind");
536 const MCOperand &SrcRegOp = Inst.getOperand(1);
537 assert(SrcRegOp.isReg() && "expected register operand kind");
538 const MCOperand &DstRegOp = Inst.getOperand(0);
539 assert(DstRegOp.isReg() && "expected register operand kind");
540 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000541 if (-32768 <= ImmValue && ImmValue <= 65535) {
542 // For -32768 <= j <= 65535.
543 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000544 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000545 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
546 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
547 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
548 Instructions.push_back(tmpInst);
549 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000550 // For any other value of j that is representable as a 32-bit integer.
551 // la d,j(s) => lui d,hi16(j)
552 // ori d,d,lo16(j)
553 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000554 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000555 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
556 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
557 Instructions.push_back(tmpInst);
558 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000559 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000560 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
561 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
562 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
563 Instructions.push_back(tmpInst);
564 tmpInst.clear();
565 tmpInst.setOpcode(Mips::ADDu);
566 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
567 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
568 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
569 Instructions.push_back(tmpInst);
570 }
571}
572
573void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000574 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000575 MCInst tmpInst;
576 const MCOperand &ImmOp = Inst.getOperand(1);
577 assert(ImmOp.isImm() && "expected immediate operand kind");
578 const MCOperand &RegOp = Inst.getOperand(0);
579 assert(RegOp.isReg() && "expected register operand kind");
580 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000581 if (-32768 <= ImmValue && ImmValue <= 65535) {
582 // For -32768 <= j <= 65535.
583 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +0000584 tmpInst.setOpcode(Mips::ADDiu);
585 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000586 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +0000587 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
588 Instructions.push_back(tmpInst);
589 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000590 // For any other value of j that is representable as a 32-bit integer.
591 // la d,j => lui d,hi16(j)
592 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000593 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000594 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
595 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
596 Instructions.push_back(tmpInst);
597 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000598 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000599 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
600 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
601 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
602 Instructions.push_back(tmpInst);
603 }
604}
605
Jack Carter9e65aa32013-03-22 00:05:30 +0000606void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000607 SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000608 const MCSymbolRefExpr *SR;
609 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +0000610 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +0000611 const MCExpr *ExprOffset;
612 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +0000613 unsigned AtRegNum = getReg((isMips64()) ? Mips::CPU64RegsRegClassID
614 : Mips::CPURegsRegClassID, getATReg());
615 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000616 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
617 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000618 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000619 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
620 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000621 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +0000622 if (isImmOpnd) {
623 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
624 ImmOffset = Inst.getOperand(2).getImm();
625 LoOffset = ImmOffset & 0x0000ffff;
626 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +0000627 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +0000628 if (LoOffset & 0x8000)
629 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +0000630 } else
Jack Carter9e65aa32013-03-22 00:05:30 +0000631 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000632 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +0000633 TempInst.setLoc(IDLoc);
634 // 1st instruction in expansion is LUi. For load instruction we can use
635 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +0000636 // but for stores we must use $at.
637 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +0000638 TempInst.setOpcode(Mips::LUi);
639 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
640 if (isImmOpnd)
641 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
642 else {
643 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
644 SR = static_cast<const MCSymbolRefExpr*>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +0000645 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
646 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
647 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000648 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000649 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000650 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +0000651 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000652 }
653 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000654 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +0000655 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000656 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +0000657 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +0000658 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000659 TempInst.setOpcode(Mips::ADDu);
660 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
661 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
662 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
663 Instructions.push_back(TempInst);
664 TempInst.clear();
Jack Carterb5cf5902013-04-17 00:18:04 +0000665 // And finaly, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +0000666 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000667 TempInst.setOpcode(Inst.getOpcode());
668 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
669 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
670 if (isImmOpnd)
671 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
672 else {
673 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000674 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
675 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
676 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000677 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000678 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000679 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +0000680 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000681 }
682 }
683 Instructions.push_back(TempInst);
684 TempInst.clear();
685}
686
Rafael Espindola870c4e92012-01-11 03:56:41 +0000687bool MipsAsmParser::
Chad Rosier49963552012-10-13 00:26:04 +0000688MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +0000689 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +0000690 MCStreamer &Out, unsigned &ErrorInfo,
691 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000692 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +0000693 SmallVector<MCInst, 8> Instructions;
Chad Rosier2f480a82012-10-12 22:53:36 +0000694 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier49963552012-10-13 00:26:04 +0000695 MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +0000696
697 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000698 default:
699 break;
Jack Carterb4dbc172012-09-05 23:34:03 +0000700 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000701 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +0000702 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +0000703 for (unsigned i = 0; i < Instructions.size(); i++)
Jack Carter9e65aa32013-03-22 00:05:30 +0000704 Out.EmitInstruction(Instructions[i]);
Jack Carterb4dbc172012-09-05 23:34:03 +0000705 return false;
706 }
707 case Match_MissingFeature:
708 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
709 return true;
710 case Match_InvalidOperand: {
711 SMLoc ErrorLoc = IDLoc;
712 if (ErrorInfo != ~0U) {
713 if (ErrorInfo >= Operands.size())
714 return Error(IDLoc, "too few operands for instruction");
715
Jack Carterd0bd6422013-04-18 00:41:53 +0000716 ErrorLoc = ((MipsOperand*) Operands[ErrorInfo])->getStartLoc();
717 if (ErrorLoc == SMLoc())
718 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +0000719 }
720
721 return Error(ErrorLoc, "invalid operand for instruction");
722 }
723 case Match_MnemonicFail:
724 return Error(IDLoc, "invalid instruction");
725 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000726 return true;
727}
728
Jack Carter1ac53222013-02-20 23:11:17 +0000729int MipsAsmParser::matchCPURegisterName(StringRef Name) {
730 int CC;
731
732 if (Name == "at")
733 return getATReg();
734
735 CC = StringSwitch<unsigned>(Name)
736 .Case("zero", 0)
737 .Case("a0", 4)
738 .Case("a1", 5)
739 .Case("a2", 6)
740 .Case("a3", 7)
741 .Case("v0", 2)
742 .Case("v1", 3)
743 .Case("s0", 16)
744 .Case("s1", 17)
745 .Case("s2", 18)
746 .Case("s3", 19)
747 .Case("s4", 20)
748 .Case("s5", 21)
749 .Case("s6", 22)
750 .Case("s7", 23)
751 .Case("k0", 26)
752 .Case("k1", 27)
753 .Case("sp", 29)
754 .Case("fp", 30)
755 .Case("gp", 28)
756 .Case("ra", 31)
757 .Case("t0", 8)
758 .Case("t1", 9)
759 .Case("t2", 10)
760 .Case("t3", 11)
761 .Case("t4", 12)
762 .Case("t5", 13)
763 .Case("t6", 14)
764 .Case("t7", 15)
765 .Case("t8", 24)
766 .Case("t9", 25)
767 .Default(-1);
768
Jack Carterd0bd6422013-04-18 00:41:53 +0000769 // Although SGI documentation just cuts out t0-t3 for n32/n64,
Jack Carter1ac53222013-02-20 23:11:17 +0000770 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
771 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
Jack Carterd0bd6422013-04-18 00:41:53 +0000772 if (isMips64() && 8 <= CC && CC <= 11)
Jack Carter1ac53222013-02-20 23:11:17 +0000773 CC += 4;
774
775 if (CC == -1 && isMips64())
776 CC = StringSwitch<unsigned>(Name)
777 .Case("a4", 8)
778 .Case("a5", 9)
779 .Case("a6", 10)
780 .Case("a7", 11)
781 .Case("kt0", 26)
782 .Case("kt1", 27)
783 .Case("s8", 30)
784 .Default(-1);
785
786 return CC;
787}
Jack Carterd0bd6422013-04-18 00:41:53 +0000788
Jack Carter873c7242013-01-12 01:03:14 +0000789int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000790
Jack Carter2ad73da2013-04-15 22:21:55 +0000791 if (Name.equals("fcc0"))
792 return Mips::FCC0;
793
Jack Carter1ac53222013-02-20 23:11:17 +0000794 int CC;
795 CC = matchCPURegisterName(Name);
David Chisnall37051252012-10-09 16:27:43 +0000796 if (CC != -1)
Jack Carterd0bd6422013-04-18 00:41:53 +0000797 return matchRegisterByNumber(CC, is64BitReg ? Mips::CPU64RegsRegClassID
798 : Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000799
Jack Cartera63b16a2012-09-07 00:23:42 +0000800 if (Name[0] == 'f') {
801 StringRef NumString = Name.substr(1);
802 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +0000803 if (NumString.getAsInteger(10, IntVal))
804 return -1; // This is not an integer.
Jack Cartera63b16a2012-09-07 00:23:42 +0000805 if (IntVal > 31)
806 return -1;
807
808 FpFormatTy Format = getFpFormat();
809
810 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
811 return getReg(Mips::FGR32RegClassID, IntVal);
812 if (Format == FP_FORMAT_D) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000813 if (isFP64()) {
Jack Cartera63b16a2012-09-07 00:23:42 +0000814 return getReg(Mips::FGR64RegClassID, IntVal);
815 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000816 // Only even numbers available as register pairs.
817 if ((IntVal > 31) || (IntVal % 2 != 0))
Jack Cartera63b16a2012-09-07 00:23:42 +0000818 return -1;
Jack Carterd0bd6422013-04-18 00:41:53 +0000819 return getReg(Mips::AFGR64RegClassID, IntVal / 2);
Jack Cartera63b16a2012-09-07 00:23:42 +0000820 }
821 }
822
Jack Carterb4dbc172012-09-05 23:34:03 +0000823 return -1;
824}
Jack Carterd0bd6422013-04-18 00:41:53 +0000825
Jack Cartera63b16a2012-09-07 00:23:42 +0000826void MipsAsmParser::setDefaultFpFormat() {
827
828 if (isMips64() || isFP64())
829 FpFormat = FP_FORMAT_D;
830 else
831 FpFormat = FP_FORMAT_S;
832}
833
834bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
835
836 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
837 .Case("ldxc1", true)
838 .Case("ldc1", true)
839 .Case("sdxc1", true)
840 .Case("sdc1", true)
841 .Default(false);
842
843 return IsDouble;
844}
Jack Carterd0bd6422013-04-18 00:41:53 +0000845
Jack Cartera63b16a2012-09-07 00:23:42 +0000846void MipsAsmParser::setFpFormat(StringRef Format) {
847
848 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
849 .Case(".s", FP_FORMAT_S)
850 .Case(".d", FP_FORMAT_D)
851 .Case(".l", FP_FORMAT_L)
852 .Case(".w", FP_FORMAT_W)
853 .Default(FP_FORMAT_NONE);
854}
Jack Carterb4dbc172012-09-05 23:34:03 +0000855
Jack Carter0b744b32012-10-04 02:29:46 +0000856bool MipsAssemblerOptions::setATReg(unsigned Reg) {
857 if (Reg > 31)
858 return false;
859
860 aTReg = Reg;
861 return true;
862}
863
Jack Carter1ac53222013-02-20 23:11:17 +0000864int MipsAsmParser::getATReg() {
865 return Options.getATRegNum();
Jack Carter0b744b32012-10-04 02:29:46 +0000866}
867
Jack Carterd0bd6422013-04-18 00:41:53 +0000868unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000869 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
870}
871
Jack Carter873c7242013-01-12 01:03:14 +0000872int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000873
874 if (RegNum > 31)
875 return -1;
876
Jack Carter873c7242013-01-12 01:03:14 +0000877 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +0000878}
879
Jack Carter873c7242013-01-12 01:03:14 +0000880int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000881 const AsmToken &Tok = Parser.getTok();
882 int RegNum = -1;
883
884 if (Tok.is(AsmToken::Identifier)) {
885 std::string lowerCase = Tok.getString().lower();
Jack Carter873c7242013-01-12 01:03:14 +0000886 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000887 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +0000888 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carterd0bd6422013-04-18 00:41:53 +0000889 is64BitReg ? Mips::CPU64RegsRegClassID : Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000890 return RegNum;
891}
892
Jack Carterd0bd6422013-04-18 00:41:53 +0000893bool MipsAsmParser::tryParseRegisterOperand(
894 SmallVectorImpl<MCParsedAsmOperand*> &Operands, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000895
896 SMLoc S = Parser.getTok().getLoc();
897 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +0000898
Jack Carter873c7242013-01-12 01:03:14 +0000899 RegNo = tryParseRegister(is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000900 if (RegNo == -1)
901 return true;
902
Jack Carter873c7242013-01-12 01:03:14 +0000903 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterd0bd6422013-04-18 00:41:53 +0000904 Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000905 Parser.Lex(); // Eat register token.
906 return false;
907}
908
909bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
910 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +0000911 // Check if the current operand has a custom associated parser, if so, try to
912 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +0000913 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
914 if (ResTy == MatchOperand_Success)
915 return false;
916 // If there wasn't a custom match, try the generic matcher below. Otherwise,
917 // there was a match, but an error occurred, in which case, just return that
918 // the operand parsing failed.
919 if (ResTy == MatchOperand_ParseFail)
920 return true;
921
922 switch (getLexer().getKind()) {
923 default:
924 Error(Parser.getTok().getLoc(), "unexpected token in operand");
925 return true;
926 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000927 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +0000928 SMLoc S = Parser.getTok().getLoc();
929 Parser.Lex(); // Eat dollar token.
Jack Carterd0bd6422013-04-18 00:41:53 +0000930 // Parse the register operand.
Jack Carter873c7242013-01-12 01:03:14 +0000931 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000932 if (getLexer().is(AsmToken::LParen)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000933 // Check if it is indexed addressing operand.
Jack Carterb4dbc172012-09-05 23:34:03 +0000934 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carterd0bd6422013-04-18 00:41:53 +0000935 Parser.Lex(); // Eat the parenthesis.
Jack Carterb4dbc172012-09-05 23:34:03 +0000936 if (getLexer().isNot(AsmToken::Dollar))
937 return true;
938
Jack Carterd0bd6422013-04-18 00:41:53 +0000939 Parser.Lex(); // Eat the dollar
Jack Carter873c7242013-01-12 01:03:14 +0000940 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterb4dbc172012-09-05 23:34:03 +0000941 return true;
942
943 if (!getLexer().is(AsmToken::RParen))
944 return true;
945
946 S = Parser.getTok().getLoc();
947 Operands.push_back(MipsOperand::CreateToken(")", S));
948 Parser.Lex();
949 }
950 return false;
951 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000952 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +0000953 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000954 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +0000955 return true;
956
Jack Carter873c7242013-01-12 01:03:14 +0000957 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000958
Benjamin Kramerfa530572012-09-07 09:47:42 +0000959 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterb4dbc172012-09-05 23:34:03 +0000960
Jack Carterd0bd6422013-04-18 00:41:53 +0000961 // Otherwise create a symbol reference.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000962 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterb4dbc172012-09-05 23:34:03 +0000963 getContext());
964
965 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
966 return false;
967 }
968 case AsmToken::Identifier:
Jack Carterd76b2372013-03-21 21:44:16 +0000969 // Look for the existing symbol, we should check if
Jack Carterd0bd6422013-04-18 00:41:53 +0000970 // we need to assigne the propper RegisterKind.
971 if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
972 return false;
973 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +0000974 case AsmToken::LParen:
975 case AsmToken::Minus:
976 case AsmToken::Plus:
977 case AsmToken::Integer:
978 case AsmToken::String: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000979 // Quoted label names.
Jack Carterb4dbc172012-09-05 23:34:03 +0000980 const MCExpr *IdVal;
981 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000982 if (getParser().parseExpression(IdVal))
Jack Carterb4dbc172012-09-05 23:34:03 +0000983 return true;
Jack Carter873c7242013-01-12 01:03:14 +0000984 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000985 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
986 return false;
987 }
Jack Carterdc1e35d2012-09-06 20:00:02 +0000988 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000989 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000990 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +0000991 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +0000992 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +0000993 return true;
994
Jack Carter873c7242013-01-12 01:03:14 +0000995 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
996
Jack Carterdc1e35d2012-09-06 20:00:02 +0000997 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
998 return false;
Jack Carter0b744b32012-10-04 02:29:46 +0000999 } // case AsmToken::Percent
1000 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001001 return true;
1002}
1003
Jack Carterb5cf5902013-04-17 00:18:04 +00001004const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
1005 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001006 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001007 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001008 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001009 // It's a constant, evaluate lo or hi value.
Jack Carterb5cf5902013-04-17 00:18:04 +00001010 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001011 short Val = MCE->getValue();
1012 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001013 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001014 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001015 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001016 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001017 // Lower part is treated as a signed int, so if it is negative
Jack Carterd0bd6422013-04-18 00:41:53 +00001018 // we must add 1 to the hi part to compensate.
Jack Carterdc463382013-02-21 02:09:31 +00001019 if (LoSign)
1020 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001021 Res = MCConstantExpr::Create(Val, getContext());
Evgeniy Stepanov3d8ab192013-04-17 06:45:11 +00001022 } else {
1023 llvm_unreachable("Invalid RelocStr value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001024 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001025 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001026 }
1027
Jack Carterb5cf5902013-04-17 00:18:04 +00001028 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001029 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001030 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001031 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001032 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001033 return Res;
1034 }
1035
1036 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001037 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1038 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001039 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1040 return Res;
1041 }
1042
1043 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001044 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1045 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1046 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001047 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001048 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001049 return Expr;
1050}
1051
1052bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1053
1054 switch (Expr->getKind()) {
1055 case MCExpr::Constant:
1056 return true;
1057 case MCExpr::SymbolRef:
1058 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1059 case MCExpr::Binary:
1060 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1061 if (!isEvaluated(BE->getLHS()))
1062 return false;
1063 return isEvaluated(BE->getRHS());
1064 }
1065 case MCExpr::Unary:
1066 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1067 default:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001068 return false;
1069 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001070 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001071}
Jack Carterd0bd6422013-04-18 00:41:53 +00001072
Jack Carterb5cf5902013-04-17 00:18:04 +00001073bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001074 Parser.Lex(); // Eat the % token.
1075 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001076 if (Tok.isNot(AsmToken::Identifier))
1077 return true;
1078
1079 std::string Str = Tok.getIdentifier().str();
1080
Jack Carterd0bd6422013-04-18 00:41:53 +00001081 Parser.Lex(); // Eat the identifier.
1082 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001083 const MCExpr *IdVal;
1084 SMLoc EndLoc;
1085
1086 if (getLexer().getKind() == AsmToken::LParen) {
1087 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001088 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001089 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001090 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001091 const AsmToken &nextTok = Parser.getTok();
1092 if (nextTok.isNot(AsmToken::Identifier))
1093 return true;
1094 Str += "(%";
1095 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001096 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001097 if (getLexer().getKind() != AsmToken::LParen)
1098 return true;
1099 } else
1100 break;
1101 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001102 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001103 return true;
1104
1105 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001106 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001107
1108 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001109 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001110
Jack Carterd0bd6422013-04-18 00:41:53 +00001111 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001112 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001113}
1114
Jack Carterb4dbc172012-09-05 23:34:03 +00001115bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1116 SMLoc &EndLoc) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001117 StartLoc = Parser.getTok().getLoc();
Jack Carter873c7242013-01-12 01:03:14 +00001118 RegNo = tryParseRegister(isMips64());
1119 EndLoc = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001120 return (RegNo == (unsigned) -1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001121}
1122
Jack Carterb5cf5902013-04-17 00:18:04 +00001123bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001124 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001125 bool Result = true;
1126
1127 while (getLexer().getKind() == AsmToken::LParen)
1128 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001129
Jack Carterd0bd6422013-04-18 00:41:53 +00001130 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001131 default:
1132 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001133 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001134 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001135 case AsmToken::Integer:
1136 case AsmToken::Minus:
1137 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001138 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001139 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001140 else
1141 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001142 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001143 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001144 break;
Jack Carter873c7242013-01-12 01:03:14 +00001145 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001146 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001147 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001148 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001149}
1150
Jack Carterb4dbc172012-09-05 23:34:03 +00001151MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Jack Carterd0bd6422013-04-18 00:41:53 +00001152 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001153
1154 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001155 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001156 bool isParenExpr = false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001157 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001158 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001159
Jack Carterb5cf5902013-04-17 00:18:04 +00001160 if (getLexer().getKind() == AsmToken::LParen) {
1161 Parser.Lex();
1162 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001163 }
1164
Jack Carterb5cf5902013-04-17 00:18:04 +00001165 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001166 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001167 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001168
Jack Carterd0bd6422013-04-18 00:41:53 +00001169 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001170 if (Tok.isNot(AsmToken::LParen)) {
1171 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
1172 if (Mnemonic->getToken() == "la") {
1173 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001174 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001175 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1176 return MatchOperand_Success;
1177 }
1178 if (Tok.is(AsmToken::EndOfStatement)) {
1179 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001180 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001181
Jack Carterd0bd6422013-04-18 00:41:53 +00001182 // Zero register assumed, add a memory operand with ZERO as its base.
1183 Operands.push_back(MipsOperand::CreateMem(isMips64() ? Mips::ZERO_64
1184 : Mips::ZERO,
1185 IdVal, S, E));
Jack Carterb5cf5902013-04-17 00:18:04 +00001186 return MatchOperand_Success;
1187 }
1188 Error(Parser.getTok().getLoc(), "'(' expected");
1189 return MatchOperand_ParseFail;
1190 }
1191
Jack Carterd0bd6422013-04-18 00:41:53 +00001192 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001193 }
1194
1195 const AsmToken &Tok1 = Parser.getTok(); // Get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +00001196 if (Tok1.is(AsmToken::Dollar)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001197 Parser.Lex(); // Eat the '$' token.
Jack Carter873c7242013-01-12 01:03:14 +00001198 if (tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001199 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1200 return MatchOperand_ParseFail;
1201 }
1202
1203 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001204 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001205 return MatchOperand_ParseFail;
1206 }
1207
Jack Carterd0bd6422013-04-18 00:41:53 +00001208 const AsmToken &Tok2 = Parser.getTok(); // Get next token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001209 if (Tok2.isNot(AsmToken::RParen)) {
1210 Error(Parser.getTok().getLoc(), "')' expected");
1211 return MatchOperand_ParseFail;
1212 }
1213
Jack Carter873c7242013-01-12 01:03:14 +00001214 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1215
Jack Carterd0bd6422013-04-18 00:41:53 +00001216 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001217
1218 if (IdVal == 0)
1219 IdVal = MCConstantExpr::Create(0, getContext());
1220
Jack Carterd0bd6422013-04-18 00:41:53 +00001221 // Replace the register operand with the memory operand.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001222 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1223 int RegNo = op->getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001224 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001225 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001226 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001227 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1228 int64_t Imm;
1229 if (IdVal->EvaluateAsAbsolute(Imm))
1230 IdVal = MCConstantExpr::Create(Imm, getContext());
1231 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1232 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1233 getContext());
1234 }
1235
Jack Carterdc1e35d2012-09-06 20:00:02 +00001236 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1237 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +00001238 return MatchOperand_Success;
1239}
1240
Jack Carter873c7242013-01-12 01:03:14 +00001241MipsAsmParser::OperandMatchResultTy
1242MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1243
1244 if (!isMips64())
1245 return MatchOperand_NoMatch;
Jack Carterd76b2372013-03-21 21:44:16 +00001246 if (getLexer().getKind() == AsmToken::Identifier) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001247 if (searchSymbolAlias(Operands, MipsOperand::Kind_CPU64Regs))
Jack Carterd76b2372013-03-21 21:44:16 +00001248 return MatchOperand_Success;
1249 return MatchOperand_NoMatch;
1250 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001251 // If the first token is not '$', we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001252 if (Parser.getTok().isNot(AsmToken::Dollar))
1253 return MatchOperand_NoMatch;
1254
1255 Parser.Lex(); // Eat $
Jack Carterd0bd6422013-04-18 00:41:53 +00001256 if (!tryParseRegisterOperand(Operands, true)) {
1257 // Set the proper register kind.
Jack Carter873c7242013-01-12 01:03:14 +00001258 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1259 op->setRegKind(MipsOperand::Kind_CPU64Regs);
1260 return MatchOperand_Success;
1261 }
1262 return MatchOperand_NoMatch;
1263}
1264
Jack Carterd0bd6422013-04-18 00:41:53 +00001265bool MipsAsmParser::searchSymbolAlias(
1266 SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegisterKind) {
Jack Carterd76b2372013-03-21 21:44:16 +00001267
1268 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1269 if (Sym) {
1270 SMLoc S = Parser.getTok().getLoc();
1271 const MCExpr *Expr;
1272 if (Sym->isVariable())
1273 Expr = Sym->getVariableValue();
1274 else
1275 return false;
1276 if (Expr->getKind() == MCExpr::SymbolRef) {
1277 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
1278 const StringRef DefSymbol = Ref->getSymbol().getName();
1279 if (DefSymbol.startswith("$")) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001280 // Lookup for the register with the corresponding name.
1281 int RegNum = matchRegisterName(DefSymbol.substr(1), isMips64());
Jack Carterd76b2372013-03-21 21:44:16 +00001282 if (RegNum > -1) {
1283 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001284 MipsOperand *op = MipsOperand::CreateReg(RegNum, S,
1285 Parser.getTok().getLoc());
1286 op->setRegKind((MipsOperand::RegisterKind) RegisterKind);
Jack Carterd76b2372013-03-21 21:44:16 +00001287 Operands.push_back(op);
1288 return true;
1289 }
1290 }
1291 } else if (Expr->getKind() == MCExpr::Constant) {
1292 Parser.Lex();
1293 const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001294 MipsOperand *op = MipsOperand::CreateImm(Const, S,
1295 Parser.getTok().getLoc());
Jack Carterd76b2372013-03-21 21:44:16 +00001296 Operands.push_back(op);
1297 return true;
1298 }
1299 }
1300 return false;
1301}
Jack Carterd0bd6422013-04-18 00:41:53 +00001302
Jack Carter873c7242013-01-12 01:03:14 +00001303MipsAsmParser::OperandMatchResultTy
1304MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1305
Jack Carterd76b2372013-03-21 21:44:16 +00001306 if (getLexer().getKind() == AsmToken::Identifier) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001307 if (searchSymbolAlias(Operands, MipsOperand::Kind_CPURegs))
Jack Carterd76b2372013-03-21 21:44:16 +00001308 return MatchOperand_Success;
1309 return MatchOperand_NoMatch;
1310 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001311 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001312 if (Parser.getTok().isNot(AsmToken::Dollar))
1313 return MatchOperand_NoMatch;
1314
1315 Parser.Lex(); // Eat $
Jack Carterd0bd6422013-04-18 00:41:53 +00001316 if (!tryParseRegisterOperand(Operands, false)) {
1317 // Set the proper register kind.
Jack Carter873c7242013-01-12 01:03:14 +00001318 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1319 op->setRegKind(MipsOperand::Kind_CPURegs);
1320 return MatchOperand_Success;
1321 }
1322 return MatchOperand_NoMatch;
1323}
1324
1325MipsAsmParser::OperandMatchResultTy
1326MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1327
Jack Carter2a74a87b2013-01-17 00:28:20 +00001328 if (isMips64())
1329 return MatchOperand_NoMatch;
1330
Jack Carterd0bd6422013-04-18 00:41:53 +00001331 // If the first token is not '$' we have error.
Jack Carter873c7242013-01-12 01:03:14 +00001332 if (Parser.getTok().isNot(AsmToken::Dollar))
1333 return MatchOperand_NoMatch;
1334 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001335 Parser.Lex(); // Eat the '$'.
Jack Carter873c7242013-01-12 01:03:14 +00001336
Jack Carterd0bd6422013-04-18 00:41:53 +00001337 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001338 if (Tok.isNot(AsmToken::Integer))
1339 return MatchOperand_NoMatch;
1340
1341 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001342 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001343 if (RegNum != 29)
1344 return MatchOperand_ParseFail;
1345
1346 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001347 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001348 op->setRegKind(MipsOperand::Kind_HWRegs);
1349 Operands.push_back(op);
1350
Jack Carterd0bd6422013-04-18 00:41:53 +00001351 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001352 return MatchOperand_Success;
1353}
1354
1355MipsAsmParser::OperandMatchResultTy
Jack Carterd0bd6422013-04-18 00:41:53 +00001356MipsAsmParser::parseHW64Regs(
1357 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter2a74a87b2013-01-17 00:28:20 +00001358
1359 if (!isMips64())
1360 return MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001361 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001362 if (Parser.getTok().isNot(AsmToken::Dollar))
1363 return MatchOperand_NoMatch;
1364 SMLoc S = Parser.getTok().getLoc();
1365 Parser.Lex(); // Eat $
1366
Jack Carterd0bd6422013-04-18 00:41:53 +00001367 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001368 if (Tok.isNot(AsmToken::Integer))
1369 return MatchOperand_NoMatch;
1370
1371 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001372 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001373 if (RegNum != 29)
1374 return MatchOperand_ParseFail;
1375
1376 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001377 Parser.getTok().getLoc());
Jack Carter2a74a87b2013-01-17 00:28:20 +00001378 op->setRegKind(MipsOperand::Kind_HW64Regs);
Jack Carter873c7242013-01-12 01:03:14 +00001379 Operands.push_back(op);
1380
Jack Carterd0bd6422013-04-18 00:41:53 +00001381 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001382 return MatchOperand_Success;
1383}
1384
1385MipsAsmParser::OperandMatchResultTy
1386MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1387 unsigned RegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001388 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001389 if (Parser.getTok().isNot(AsmToken::Dollar))
1390 return MatchOperand_NoMatch;
1391 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001392 Parser.Lex(); // Eat the '$'
Jack Carter873c7242013-01-12 01:03:14 +00001393
Jack Carterd0bd6422013-04-18 00:41:53 +00001394 const AsmToken &Tok = Parser.getTok(); // Get next token.
Jack Carter873c7242013-01-12 01:03:14 +00001395 if (Tok.is(AsmToken::Integer)) {
1396 RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001397 // At the moment only fcc0 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001398 if (RegNum != 0)
1399 return MatchOperand_ParseFail;
1400 } else if (Tok.is(AsmToken::Identifier)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001401 // At the moment only fcc0 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001402 if (Tok.getIdentifier() != "fcc0")
1403 return MatchOperand_ParseFail;
1404 } else
1405 return MatchOperand_NoMatch;
1406
1407 MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001408 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001409 op->setRegKind(MipsOperand::Kind_CCRRegs);
1410 Operands.push_back(op);
1411
Jack Carterd0bd6422013-04-18 00:41:53 +00001412 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001413 return MatchOperand_Success;
1414}
1415
Jack Carterdc1e35d2012-09-06 20:00:02 +00001416MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1417
1418 MCSymbolRefExpr::VariantKind VK
1419 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1420 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1421 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1422 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1423 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1424 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1425 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1426 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1427 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1428 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1429 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1430 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1431 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1432 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1433 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1434 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1435 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1436 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1437 .Default(MCSymbolRefExpr::VK_None);
1438
1439 return VK;
1440}
1441
Benjamin Kramer47b5c572012-09-10 11:52:14 +00001442static int ConvertCcString(StringRef CondString) {
Jack Cartera63b16a2012-09-07 00:23:42 +00001443 int CC = StringSwitch<unsigned>(CondString)
Jack Carterd0bd6422013-04-18 00:41:53 +00001444 .Case(".f", 0)
1445 .Case(".un", 1)
1446 .Case(".eq", 2)
1447 .Case(".ueq", 3)
1448 .Case(".olt", 4)
1449 .Case(".ult", 5)
1450 .Case(".ole", 6)
1451 .Case(".ule", 7)
1452 .Case(".sf", 8)
1453 .Case(".ngle", 9)
1454 .Case(".seq", 10)
1455 .Case(".ngl", 11)
1456 .Case(".lt", 12)
1457 .Case(".nge", 13)
1458 .Case(".le", 14)
1459 .Case(".ngt", 15)
1460 .Default(-1);
Jack Cartera63b16a2012-09-07 00:23:42 +00001461
1462 return CC;
1463}
1464
1465bool MipsAsmParser::
1466parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter0b744b32012-10-04 02:29:46 +00001467 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001468 // Split the format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001469 size_t Start = Name.find('.'), Next = Name.rfind('.');
1470 StringRef Format1 = Name.slice(Start, Next);
Jack Carterd0bd6422013-04-18 00:41:53 +00001471 // Add the first format to the operands.
Jack Cartera63b16a2012-09-07 00:23:42 +00001472 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carterd0bd6422013-04-18 00:41:53 +00001473 // Now for the second format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001474 StringRef Format2 = Name.slice(Next, StringRef::npos);
1475 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1476
Jack Carterd0bd6422013-04-18 00:41:53 +00001477 // Set the format for the first register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001478 setFpFormat(Format1);
1479
1480 // Read the remaining operands.
1481 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1482 // Read the first operand.
1483 if (ParseOperand(Operands, Name)) {
1484 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001485 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001486 return Error(Loc, "unexpected token in argument list");
1487 }
1488
1489 if (getLexer().isNot(AsmToken::Comma)) {
1490 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001491 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001492 return Error(Loc, "unexpected token in argument list");
Jack Cartera63b16a2012-09-07 00:23:42 +00001493 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001494 Parser.Lex(); // Eat the comma.
Jack Cartera63b16a2012-09-07 00:23:42 +00001495
Jack Carterb5cf5902013-04-17 00:18:04 +00001496 // Set the format for the first register
Jack Cartera63b16a2012-09-07 00:23:42 +00001497 setFpFormat(Format2);
1498
1499 // Parse and remember the operand.
1500 if (ParseOperand(Operands, Name)) {
1501 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001502 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001503 return Error(Loc, "unexpected token in argument list");
1504 }
1505 }
1506
1507 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1508 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001509 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001510 return Error(Loc, "unexpected token in argument list");
1511 }
1512
Jack Carterd0bd6422013-04-18 00:41:53 +00001513 Parser.Lex(); // Consume the EndOfStatement.
Jack Cartera63b16a2012-09-07 00:23:42 +00001514 return false;
1515}
1516
Rafael Espindola870c4e92012-01-11 03:56:41 +00001517bool MipsAsmParser::
Chad Rosierf0e87202012-10-25 20:41:34 +00001518ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindola870c4e92012-01-11 03:56:41 +00001519 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter1ac53222013-02-20 23:11:17 +00001520 StringRef Mnemonic;
Jack Carterd0bd6422013-04-18 00:41:53 +00001521 // Floating point instructions: Should the register be treated as a double?
Jack Cartera63b16a2012-09-07 00:23:42 +00001522 if (requestsDoubleOperand(Name)) {
1523 setFpFormat(FP_FORMAT_D);
Jack Carterd0bd6422013-04-18 00:41:53 +00001524 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
1525 Mnemonic = Name;
1526 } else {
Jack Cartera63b16a2012-09-07 00:23:42 +00001527 setDefaultFpFormat();
1528 // Create the leading tokens for the mnemonic, split by '.' characters.
1529 size_t Start = 0, Next = Name.find('.');
Jack Carter1ac53222013-02-20 23:11:17 +00001530 Mnemonic = Name.slice(Start, Next);
Jack Cartera63b16a2012-09-07 00:23:42 +00001531
1532 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1533
1534 if (Next != StringRef::npos) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001535 // There is a format token in mnemonic.
1536 size_t Dot = Name.find('.', Next + 1);
Jack Cartera63b16a2012-09-07 00:23:42 +00001537 StringRef Format = Name.slice(Next, Dot);
Jack Carterd0bd6422013-04-18 00:41:53 +00001538 if (Dot == StringRef::npos) // Only one '.' in a string, it's a format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001539 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1540 else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001541 if (Name.startswith("c.")) {
1542 // Floating point compare, add '.' and immediate represent for cc.
Jack Cartera63b16a2012-09-07 00:23:42 +00001543 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1544 int Cc = ConvertCcString(Format);
1545 if (Cc == -1) {
1546 return Error(NameLoc, "Invalid conditional code");
1547 }
Jack Carter873c7242013-01-12 01:03:14 +00001548 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001549 Parser.getTok().getLoc().getPointer() - 1);
1550 Operands.push_back(
1551 MipsOperand::CreateImm(MCConstantExpr::Create(Cc, getContext()),
1552 NameLoc, E));
Jack Cartera63b16a2012-09-07 00:23:42 +00001553 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001554 // trunc, ceil, floor ...
Jack Cartera63b16a2012-09-07 00:23:42 +00001555 return parseMathOperation(Name, NameLoc, Operands);
1556 }
1557
Jack Carterd0bd6422013-04-18 00:41:53 +00001558 // The rest is a format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001559 Format = Name.slice(Dot, StringRef::npos);
1560 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1561 }
1562
1563 setFpFormat(Format);
1564 }
1565 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001566
1567 // Read the remaining operands.
1568 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1569 // Read the first operand.
Jack Carter1ac53222013-02-20 23:11:17 +00001570 if (ParseOperand(Operands, Mnemonic)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001571 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001572 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001573 return Error(Loc, "unexpected token in argument list");
1574 }
1575
Jack Carterd0bd6422013-04-18 00:41:53 +00001576 while (getLexer().is(AsmToken::Comma)) {
1577 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00001578
1579 // Parse and remember the operand.
1580 if (ParseOperand(Operands, Name)) {
1581 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001582 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001583 return Error(Loc, "unexpected token in argument list");
1584 }
1585 }
1586 }
1587
1588 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1589 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001590 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001591 return Error(Loc, "unexpected token in argument list");
1592 }
1593
Jack Carterd0bd6422013-04-18 00:41:53 +00001594 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00001595 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00001596}
1597
Jack Carter0b744b32012-10-04 02:29:46 +00001598bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001599 SMLoc Loc = getLexer().getLoc();
1600 Parser.eatToEndOfStatement();
1601 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00001602}
1603
1604bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001605 // Line should look like: ".set noat".
1606 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00001607 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00001608 // eat noat
1609 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001610 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001611 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1612 reportParseError("unexpected token in statement");
1613 return false;
1614 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001615 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001616 return false;
1617}
Jack Carterd0bd6422013-04-18 00:41:53 +00001618
Jack Carter0b744b32012-10-04 02:29:46 +00001619bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001620 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00001621 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00001622 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00001623 getParser().Lex();
1624 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00001625 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00001626 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001627 return false;
1628 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001629 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00001630 if (getLexer().isNot(AsmToken::Dollar)) {
1631 reportParseError("unexpected token in statement");
1632 return false;
1633 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001634 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00001635 const AsmToken &Reg = Parser.getTok();
1636 if (Reg.is(AsmToken::Identifier)) {
1637 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
1638 } else if (Reg.is(AsmToken::Integer)) {
1639 AtRegNo = Reg.getIntVal();
1640 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001641 reportParseError("unexpected token in statement");
1642 return false;
1643 }
Jack Carter1ac53222013-02-20 23:11:17 +00001644
Jack Carterd0bd6422013-04-18 00:41:53 +00001645 if (AtRegNo < 1 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00001646 reportParseError("unexpected token in statement");
1647 return false;
1648 }
1649
1650 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00001651 reportParseError("unexpected token in statement");
1652 return false;
1653 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001654 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00001655
1656 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1657 reportParseError("unexpected token in statement");
1658 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001659 }
1660 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001661 return false;
1662 } else {
1663 reportParseError("unexpected token in statement");
1664 return false;
1665 }
1666}
1667
1668bool MipsAsmParser::parseSetReorderDirective() {
1669 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001670 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001671 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1672 reportParseError("unexpected token in statement");
1673 return false;
1674 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001675 Options.setReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00001676 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001677 return false;
1678}
1679
1680bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001681 Parser.Lex();
1682 // If this is not the end of the statement, report an error.
1683 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1684 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00001685 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001686 }
1687 Options.setNoreorder();
1688 Parser.Lex(); // Consume the EndOfStatement.
1689 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001690}
1691
1692bool MipsAsmParser::parseSetMacroDirective() {
1693 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001694 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001695 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1696 reportParseError("unexpected token in statement");
1697 return false;
1698 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001699 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001700 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001701 return false;
1702}
1703
1704bool MipsAsmParser::parseSetNoMacroDirective() {
1705 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001706 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001707 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1708 reportParseError("`noreorder' must be set before `nomacro'");
1709 return false;
1710 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001711 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00001712 reportParseError("`noreorder' must be set before `nomacro'");
1713 return false;
1714 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001715 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001716 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001717 return false;
1718}
Jack Carterd76b2372013-03-21 21:44:16 +00001719
1720bool MipsAsmParser::parseSetAssignment() {
1721 StringRef Name;
1722 const MCExpr *Value;
1723
1724 if (Parser.parseIdentifier(Name))
1725 reportParseError("expected identifier after .set");
1726
1727 if (getLexer().isNot(AsmToken::Comma))
1728 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00001729 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00001730
1731 if (Parser.parseExpression(Value))
1732 reportParseError("expected valid expression after comma");
1733
Jack Carterd0bd6422013-04-18 00:41:53 +00001734 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00001735 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00001736 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00001737 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00001738 Sym = getContext().GetOrCreateSymbol(Name);
1739 Sym->setVariableValue(Value);
1740
1741 return false;
1742}
Jack Carterd0bd6422013-04-18 00:41:53 +00001743
Jack Carter0b744b32012-10-04 02:29:46 +00001744bool MipsAsmParser::parseDirectiveSet() {
1745
Jack Carterd0bd6422013-04-18 00:41:53 +00001746 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00001747 const AsmToken &Tok = Parser.getTok();
1748
1749 if (Tok.getString() == "noat") {
1750 return parseSetNoAtDirective();
1751 } else if (Tok.getString() == "at") {
1752 return parseSetAtDirective();
1753 } else if (Tok.getString() == "reorder") {
1754 return parseSetReorderDirective();
1755 } else if (Tok.getString() == "noreorder") {
1756 return parseSetNoReorderDirective();
1757 } else if (Tok.getString() == "macro") {
1758 return parseSetMacroDirective();
1759 } else if (Tok.getString() == "nomacro") {
1760 return parseSetNoMacroDirective();
1761 } else if (Tok.getString() == "nomips16") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001762 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001763 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001764 return false;
1765 } else if (Tok.getString() == "nomicromips") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001766 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001767 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001768 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001769 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001770 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00001771 parseSetAssignment();
1772 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001773 }
Jack Carter07c818d2013-01-25 01:31:34 +00001774
Jack Carter0b744b32012-10-04 02:29:46 +00001775 return true;
1776}
1777
Jack Carter07c818d2013-01-25 01:31:34 +00001778/// parseDirectiveWord
1779/// ::= .word [ expression (, expression)* ]
1780bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
1781 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1782 for (;;) {
1783 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001784 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00001785 return true;
1786
1787 getParser().getStreamer().EmitValue(Value, Size);
1788
1789 if (getLexer().is(AsmToken::EndOfStatement))
1790 break;
1791
1792 // FIXME: Improve diagnostic.
1793 if (getLexer().isNot(AsmToken::Comma))
1794 return Error(L, "unexpected token in directive");
1795 Parser.Lex();
1796 }
1797 }
1798
1799 Parser.Lex();
1800 return false;
1801}
1802
Jack Carter0b744b32012-10-04 02:29:46 +00001803bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +00001804
Jack Carter07c818d2013-01-25 01:31:34 +00001805 StringRef IDVal = DirectiveID.getString();
1806
Jack Carterd0bd6422013-04-18 00:41:53 +00001807 if (IDVal == ".ent") {
1808 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001809 Parser.Lex();
1810 return false;
1811 }
1812
Jack Carter07c818d2013-01-25 01:31:34 +00001813 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001814 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001815 Parser.Lex();
1816 return false;
1817 }
1818
Jack Carter07c818d2013-01-25 01:31:34 +00001819 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001820 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001821 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001822 return false;
1823 }
1824
Jack Carter07c818d2013-01-25 01:31:34 +00001825 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00001826 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00001827 }
1828
Jack Carter07c818d2013-01-25 01:31:34 +00001829 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001830 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001831 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001832 return false;
1833 }
1834
Jack Carter07c818d2013-01-25 01:31:34 +00001835 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001836 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001837 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001838 return false;
1839 }
1840
Jack Carter07c818d2013-01-25 01:31:34 +00001841 if (IDVal == ".gpword") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001842 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001843 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001844 return false;
1845 }
1846
Jack Carter07c818d2013-01-25 01:31:34 +00001847 if (IDVal == ".word") {
1848 parseDirectiveWord(4, DirectiveID.getLoc());
1849 return false;
1850 }
1851
Rafael Espindola870c4e92012-01-11 03:56:41 +00001852 return true;
1853}
1854
Rafael Espindola870c4e92012-01-11 03:56:41 +00001855extern "C" void LLVMInitializeMipsAsmParser() {
1856 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1857 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1858 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1859 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1860}
Jack Carterb4dbc172012-09-05 23:34:03 +00001861
1862#define GET_REGISTER_MATCHER
1863#define GET_MATCHER_IMPLEMENTATION
1864#include "MipsGenAsmMatcher.inc"