blob: 0795cb963b35bff2b1bdae77d0eea2fe425d649c [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);
Jack Carterc15c1d22013-04-25 23:31:35 +0000421 if (MCID.hasDelaySlot() && Options.isReorder()) {
422 // If this instruction has a delay slot and .set reorder is active,
423 // emit a NOP after it.
424 Instructions.push_back(Inst);
425 MCInst NopInst;
426 NopInst.setOpcode(Mips::SLL);
427 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
428 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
429 NopInst.addOperand(MCOperand::CreateImm(0));
430 Instructions.push_back(NopInst);
431 return false;
432 }
433
Jack Carter9e65aa32013-03-22 00:05:30 +0000434 if (MCID.mayLoad() || MCID.mayStore()) {
435 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000436 // reference or immediate we may have to expand instructions.
437 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000438 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Jack Carterd0bd6422013-04-18 00:41:53 +0000439 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY)
440 || (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000441 MCOperand &Op = Inst.getOperand(i);
442 if (Op.isImm()) {
443 int MemOffset = Op.getImm();
444 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000445 // Offset can't exceed 16bit value.
446 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000447 return false;
448 }
449 } else if (Op.isExpr()) {
450 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000451 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000452 const MCSymbolRefExpr *SR =
Jack Carterb5cf5902013-04-17 00:18:04 +0000453 static_cast<const MCSymbolRefExpr*>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000454 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000455 // Expand symbol.
456 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000457 return false;
458 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000459 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000460 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000461 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000462 }
463 }
464 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000465 } // for
466 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000467
468 if (needsExpansion(Inst))
469 expandInstruction(Inst, IDLoc, Instructions);
470 else
471 Instructions.push_back(Inst);
472
473 return false;
474}
475
Jack Carter30a59822012-10-04 04:03:53 +0000476bool MipsAsmParser::needsExpansion(MCInst &Inst) {
477
Jack Carterd0bd6422013-04-18 00:41:53 +0000478 switch (Inst.getOpcode()) {
479 case Mips::LoadImm32Reg:
480 case Mips::LoadAddr32Imm:
481 case Mips::LoadAddr32Reg:
482 return true;
483 default:
484 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000485 }
486}
Jack Carter92995f12012-10-06 00:53:28 +0000487
Jack Carter30a59822012-10-04 04:03:53 +0000488void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000489 SmallVectorImpl<MCInst> &Instructions) {
490 switch (Inst.getOpcode()) {
491 case Mips::LoadImm32Reg:
492 return expandLoadImm(Inst, IDLoc, Instructions);
493 case Mips::LoadAddr32Imm:
494 return expandLoadAddressImm(Inst, IDLoc, Instructions);
495 case Mips::LoadAddr32Reg:
496 return expandLoadAddressReg(Inst, IDLoc, Instructions);
497 }
Jack Carter30a59822012-10-04 04:03:53 +0000498}
Jack Carter92995f12012-10-06 00:53:28 +0000499
Jack Carter30a59822012-10-04 04:03:53 +0000500void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000501 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000502 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000503 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000504 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000505 const MCOperand &RegOp = Inst.getOperand(0);
506 assert(RegOp.isReg() && "expected register operand kind");
507
508 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000509 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000510 if (0 <= ImmValue && ImmValue <= 65535) {
511 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000512 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000513 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000514 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000515 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000516 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000517 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000518 } else if (ImmValue < 0 && ImmValue >= -32768) {
519 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000520 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000521 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000522 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000523 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000524 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000525 Instructions.push_back(tmpInst);
526 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000527 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000528 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000529 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000530 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000531 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
532 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000533 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000534 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000535 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000536 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
537 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
538 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
539 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000540 Instructions.push_back(tmpInst);
541 }
542}
Jack Carter92995f12012-10-06 00:53:28 +0000543
Jack Carter543fdf82012-10-09 23:29:45 +0000544void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000545 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000546 MCInst tmpInst;
547 const MCOperand &ImmOp = Inst.getOperand(2);
548 assert(ImmOp.isImm() && "expected immediate operand kind");
549 const MCOperand &SrcRegOp = Inst.getOperand(1);
550 assert(SrcRegOp.isReg() && "expected register operand kind");
551 const MCOperand &DstRegOp = Inst.getOperand(0);
552 assert(DstRegOp.isReg() && "expected register operand kind");
553 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000554 if (-32768 <= ImmValue && ImmValue <= 65535) {
555 // For -32768 <= j <= 65535.
556 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000557 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000558 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
559 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
560 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
561 Instructions.push_back(tmpInst);
562 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000563 // For any other value of j that is representable as a 32-bit integer.
564 // la d,j(s) => lui d,hi16(j)
565 // ori d,d,lo16(j)
566 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000567 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000568 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
569 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
570 Instructions.push_back(tmpInst);
571 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000572 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000573 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
574 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
575 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
576 Instructions.push_back(tmpInst);
577 tmpInst.clear();
578 tmpInst.setOpcode(Mips::ADDu);
579 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
580 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
581 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
582 Instructions.push_back(tmpInst);
583 }
584}
585
586void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000587 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000588 MCInst tmpInst;
589 const MCOperand &ImmOp = Inst.getOperand(1);
590 assert(ImmOp.isImm() && "expected immediate operand kind");
591 const MCOperand &RegOp = Inst.getOperand(0);
592 assert(RegOp.isReg() && "expected register operand kind");
593 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000594 if (-32768 <= ImmValue && ImmValue <= 65535) {
595 // For -32768 <= j <= 65535.
596 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +0000597 tmpInst.setOpcode(Mips::ADDiu);
598 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000599 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +0000600 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
601 Instructions.push_back(tmpInst);
602 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000603 // For any other value of j that is representable as a 32-bit integer.
604 // la d,j => lui d,hi16(j)
605 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000606 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000607 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
608 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
609 Instructions.push_back(tmpInst);
610 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000611 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000612 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
613 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
614 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
615 Instructions.push_back(tmpInst);
616 }
617}
618
Jack Carter9e65aa32013-03-22 00:05:30 +0000619void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000620 SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000621 const MCSymbolRefExpr *SR;
622 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +0000623 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +0000624 const MCExpr *ExprOffset;
625 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +0000626 unsigned AtRegNum = getReg((isMips64()) ? Mips::CPU64RegsRegClassID
627 : Mips::CPURegsRegClassID, getATReg());
628 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000629 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
630 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000631 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000632 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
633 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000634 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +0000635 if (isImmOpnd) {
636 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
637 ImmOffset = Inst.getOperand(2).getImm();
638 LoOffset = ImmOffset & 0x0000ffff;
639 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +0000640 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +0000641 if (LoOffset & 0x8000)
642 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +0000643 } else
Jack Carter9e65aa32013-03-22 00:05:30 +0000644 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000645 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +0000646 TempInst.setLoc(IDLoc);
647 // 1st instruction in expansion is LUi. For load instruction we can use
648 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +0000649 // but for stores we must use $at.
650 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +0000651 TempInst.setOpcode(Mips::LUi);
652 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
653 if (isImmOpnd)
654 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
655 else {
656 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
657 SR = static_cast<const MCSymbolRefExpr*>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +0000658 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
659 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
660 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000661 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000662 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000663 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +0000664 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000665 }
666 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000667 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +0000668 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000669 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +0000670 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +0000671 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000672 TempInst.setOpcode(Mips::ADDu);
673 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
674 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
675 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
676 Instructions.push_back(TempInst);
677 TempInst.clear();
Jack Carterb5cf5902013-04-17 00:18:04 +0000678 // And finaly, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +0000679 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000680 TempInst.setOpcode(Inst.getOpcode());
681 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
682 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
683 if (isImmOpnd)
684 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
685 else {
686 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000687 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
688 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
689 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000690 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000691 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000692 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +0000693 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000694 }
695 }
696 Instructions.push_back(TempInst);
697 TempInst.clear();
698}
699
Rafael Espindola870c4e92012-01-11 03:56:41 +0000700bool MipsAsmParser::
Chad Rosier49963552012-10-13 00:26:04 +0000701MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +0000702 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +0000703 MCStreamer &Out, unsigned &ErrorInfo,
704 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000705 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +0000706 SmallVector<MCInst, 8> Instructions;
Chad Rosier2f480a82012-10-12 22:53:36 +0000707 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier49963552012-10-13 00:26:04 +0000708 MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +0000709
710 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000711 default:
712 break;
Jack Carterb4dbc172012-09-05 23:34:03 +0000713 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000714 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +0000715 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +0000716 for (unsigned i = 0; i < Instructions.size(); i++)
Jack Carter9e65aa32013-03-22 00:05:30 +0000717 Out.EmitInstruction(Instructions[i]);
Jack Carterb4dbc172012-09-05 23:34:03 +0000718 return false;
719 }
720 case Match_MissingFeature:
721 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
722 return true;
723 case Match_InvalidOperand: {
724 SMLoc ErrorLoc = IDLoc;
725 if (ErrorInfo != ~0U) {
726 if (ErrorInfo >= Operands.size())
727 return Error(IDLoc, "too few operands for instruction");
728
Jack Carterd0bd6422013-04-18 00:41:53 +0000729 ErrorLoc = ((MipsOperand*) Operands[ErrorInfo])->getStartLoc();
730 if (ErrorLoc == SMLoc())
731 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +0000732 }
733
734 return Error(ErrorLoc, "invalid operand for instruction");
735 }
736 case Match_MnemonicFail:
737 return Error(IDLoc, "invalid instruction");
738 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000739 return true;
740}
741
Jack Carter1ac53222013-02-20 23:11:17 +0000742int MipsAsmParser::matchCPURegisterName(StringRef Name) {
743 int CC;
744
745 if (Name == "at")
746 return getATReg();
747
748 CC = StringSwitch<unsigned>(Name)
749 .Case("zero", 0)
750 .Case("a0", 4)
751 .Case("a1", 5)
752 .Case("a2", 6)
753 .Case("a3", 7)
754 .Case("v0", 2)
755 .Case("v1", 3)
756 .Case("s0", 16)
757 .Case("s1", 17)
758 .Case("s2", 18)
759 .Case("s3", 19)
760 .Case("s4", 20)
761 .Case("s5", 21)
762 .Case("s6", 22)
763 .Case("s7", 23)
764 .Case("k0", 26)
765 .Case("k1", 27)
766 .Case("sp", 29)
767 .Case("fp", 30)
768 .Case("gp", 28)
769 .Case("ra", 31)
770 .Case("t0", 8)
771 .Case("t1", 9)
772 .Case("t2", 10)
773 .Case("t3", 11)
774 .Case("t4", 12)
775 .Case("t5", 13)
776 .Case("t6", 14)
777 .Case("t7", 15)
778 .Case("t8", 24)
779 .Case("t9", 25)
780 .Default(-1);
781
Jack Carterd0bd6422013-04-18 00:41:53 +0000782 // Although SGI documentation just cuts out t0-t3 for n32/n64,
Jack Carter1ac53222013-02-20 23:11:17 +0000783 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
784 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
Jack Carterd0bd6422013-04-18 00:41:53 +0000785 if (isMips64() && 8 <= CC && CC <= 11)
Jack Carter1ac53222013-02-20 23:11:17 +0000786 CC += 4;
787
788 if (CC == -1 && isMips64())
789 CC = StringSwitch<unsigned>(Name)
790 .Case("a4", 8)
791 .Case("a5", 9)
792 .Case("a6", 10)
793 .Case("a7", 11)
794 .Case("kt0", 26)
795 .Case("kt1", 27)
796 .Case("s8", 30)
797 .Default(-1);
798
799 return CC;
800}
Jack Carterd0bd6422013-04-18 00:41:53 +0000801
Jack Carter873c7242013-01-12 01:03:14 +0000802int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000803
Jack Carter2ad73da2013-04-15 22:21:55 +0000804 if (Name.equals("fcc0"))
805 return Mips::FCC0;
806
Jack Carter1ac53222013-02-20 23:11:17 +0000807 int CC;
808 CC = matchCPURegisterName(Name);
David Chisnall37051252012-10-09 16:27:43 +0000809 if (CC != -1)
Jack Carterd0bd6422013-04-18 00:41:53 +0000810 return matchRegisterByNumber(CC, is64BitReg ? Mips::CPU64RegsRegClassID
811 : Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000812
Jack Cartera63b16a2012-09-07 00:23:42 +0000813 if (Name[0] == 'f') {
814 StringRef NumString = Name.substr(1);
815 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +0000816 if (NumString.getAsInteger(10, IntVal))
817 return -1; // This is not an integer.
Jack Cartera63b16a2012-09-07 00:23:42 +0000818 if (IntVal > 31)
819 return -1;
820
821 FpFormatTy Format = getFpFormat();
822
823 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
824 return getReg(Mips::FGR32RegClassID, IntVal);
825 if (Format == FP_FORMAT_D) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000826 if (isFP64()) {
Jack Cartera63b16a2012-09-07 00:23:42 +0000827 return getReg(Mips::FGR64RegClassID, IntVal);
828 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000829 // Only even numbers available as register pairs.
830 if ((IntVal > 31) || (IntVal % 2 != 0))
Jack Cartera63b16a2012-09-07 00:23:42 +0000831 return -1;
Jack Carterd0bd6422013-04-18 00:41:53 +0000832 return getReg(Mips::AFGR64RegClassID, IntVal / 2);
Jack Cartera63b16a2012-09-07 00:23:42 +0000833 }
834 }
835
Jack Carterb4dbc172012-09-05 23:34:03 +0000836 return -1;
837}
Jack Carterd0bd6422013-04-18 00:41:53 +0000838
Jack Cartera63b16a2012-09-07 00:23:42 +0000839void MipsAsmParser::setDefaultFpFormat() {
840
841 if (isMips64() || isFP64())
842 FpFormat = FP_FORMAT_D;
843 else
844 FpFormat = FP_FORMAT_S;
845}
846
847bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
848
849 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
850 .Case("ldxc1", true)
851 .Case("ldc1", true)
852 .Case("sdxc1", true)
853 .Case("sdc1", true)
854 .Default(false);
855
856 return IsDouble;
857}
Jack Carterd0bd6422013-04-18 00:41:53 +0000858
Jack Cartera63b16a2012-09-07 00:23:42 +0000859void MipsAsmParser::setFpFormat(StringRef Format) {
860
861 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
862 .Case(".s", FP_FORMAT_S)
863 .Case(".d", FP_FORMAT_D)
864 .Case(".l", FP_FORMAT_L)
865 .Case(".w", FP_FORMAT_W)
866 .Default(FP_FORMAT_NONE);
867}
Jack Carterb4dbc172012-09-05 23:34:03 +0000868
Jack Carter0b744b32012-10-04 02:29:46 +0000869bool MipsAssemblerOptions::setATReg(unsigned Reg) {
870 if (Reg > 31)
871 return false;
872
873 aTReg = Reg;
874 return true;
875}
876
Jack Carter1ac53222013-02-20 23:11:17 +0000877int MipsAsmParser::getATReg() {
878 return Options.getATRegNum();
Jack Carter0b744b32012-10-04 02:29:46 +0000879}
880
Jack Carterd0bd6422013-04-18 00:41:53 +0000881unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000882 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
883}
884
Jack Carter873c7242013-01-12 01:03:14 +0000885int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000886
887 if (RegNum > 31)
888 return -1;
889
Jack Carter873c7242013-01-12 01:03:14 +0000890 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +0000891}
892
Jack Carter873c7242013-01-12 01:03:14 +0000893int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000894 const AsmToken &Tok = Parser.getTok();
895 int RegNum = -1;
896
897 if (Tok.is(AsmToken::Identifier)) {
898 std::string lowerCase = Tok.getString().lower();
Jack Carter873c7242013-01-12 01:03:14 +0000899 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000900 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +0000901 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carterd0bd6422013-04-18 00:41:53 +0000902 is64BitReg ? Mips::CPU64RegsRegClassID : Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000903 return RegNum;
904}
905
Jack Carterd0bd6422013-04-18 00:41:53 +0000906bool MipsAsmParser::tryParseRegisterOperand(
907 SmallVectorImpl<MCParsedAsmOperand*> &Operands, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000908
909 SMLoc S = Parser.getTok().getLoc();
910 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +0000911
Jack Carter873c7242013-01-12 01:03:14 +0000912 RegNo = tryParseRegister(is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000913 if (RegNo == -1)
914 return true;
915
Jack Carter873c7242013-01-12 01:03:14 +0000916 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterd0bd6422013-04-18 00:41:53 +0000917 Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000918 Parser.Lex(); // Eat register token.
919 return false;
920}
921
922bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
923 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +0000924 // Check if the current operand has a custom associated parser, if so, try to
925 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +0000926 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
927 if (ResTy == MatchOperand_Success)
928 return false;
929 // If there wasn't a custom match, try the generic matcher below. Otherwise,
930 // there was a match, but an error occurred, in which case, just return that
931 // the operand parsing failed.
932 if (ResTy == MatchOperand_ParseFail)
933 return true;
934
935 switch (getLexer().getKind()) {
936 default:
937 Error(Parser.getTok().getLoc(), "unexpected token in operand");
938 return true;
939 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000940 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +0000941 SMLoc S = Parser.getTok().getLoc();
942 Parser.Lex(); // Eat dollar token.
Jack Carterd0bd6422013-04-18 00:41:53 +0000943 // Parse the register operand.
Jack Carter873c7242013-01-12 01:03:14 +0000944 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000945 if (getLexer().is(AsmToken::LParen)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000946 // Check if it is indexed addressing operand.
Jack Carterb4dbc172012-09-05 23:34:03 +0000947 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carterd0bd6422013-04-18 00:41:53 +0000948 Parser.Lex(); // Eat the parenthesis.
Jack Carterb4dbc172012-09-05 23:34:03 +0000949 if (getLexer().isNot(AsmToken::Dollar))
950 return true;
951
Jack Carterd0bd6422013-04-18 00:41:53 +0000952 Parser.Lex(); // Eat the dollar
Jack Carter873c7242013-01-12 01:03:14 +0000953 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterb4dbc172012-09-05 23:34:03 +0000954 return true;
955
956 if (!getLexer().is(AsmToken::RParen))
957 return true;
958
959 S = Parser.getTok().getLoc();
960 Operands.push_back(MipsOperand::CreateToken(")", S));
961 Parser.Lex();
962 }
963 return false;
964 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000965 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +0000966 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000967 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +0000968 return true;
969
Jack Carter873c7242013-01-12 01:03:14 +0000970 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000971
Benjamin Kramerfa530572012-09-07 09:47:42 +0000972 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterb4dbc172012-09-05 23:34:03 +0000973
Jack Carterd0bd6422013-04-18 00:41:53 +0000974 // Otherwise create a symbol reference.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000975 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterb4dbc172012-09-05 23:34:03 +0000976 getContext());
977
978 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
979 return false;
980 }
981 case AsmToken::Identifier:
Jack Carterd76b2372013-03-21 21:44:16 +0000982 // Look for the existing symbol, we should check if
Jack Carterd0bd6422013-04-18 00:41:53 +0000983 // we need to assigne the propper RegisterKind.
984 if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
985 return false;
986 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +0000987 case AsmToken::LParen:
988 case AsmToken::Minus:
989 case AsmToken::Plus:
990 case AsmToken::Integer:
991 case AsmToken::String: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000992 // Quoted label names.
Jack Carterb4dbc172012-09-05 23:34:03 +0000993 const MCExpr *IdVal;
994 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000995 if (getParser().parseExpression(IdVal))
Jack Carterb4dbc172012-09-05 23:34:03 +0000996 return true;
Jack Carter873c7242013-01-12 01:03:14 +0000997 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000998 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
999 return false;
1000 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001001 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001002 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001003 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001004 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001005 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001006 return true;
1007
Jack Carter873c7242013-01-12 01:03:14 +00001008 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1009
Jack Carterdc1e35d2012-09-06 20:00:02 +00001010 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1011 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001012 } // case AsmToken::Percent
1013 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001014 return true;
1015}
1016
Jack Carterb5cf5902013-04-17 00:18:04 +00001017const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
1018 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001019 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001020 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001021 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001022 // It's a constant, evaluate lo or hi value.
Jack Carterb5cf5902013-04-17 00:18:04 +00001023 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001024 short Val = MCE->getValue();
1025 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001026 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001027 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001028 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001029 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001030 // Lower part is treated as a signed int, so if it is negative
Jack Carterd0bd6422013-04-18 00:41:53 +00001031 // we must add 1 to the hi part to compensate.
Jack Carterdc463382013-02-21 02:09:31 +00001032 if (LoSign)
1033 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001034 Res = MCConstantExpr::Create(Val, getContext());
Evgeniy Stepanov3d8ab192013-04-17 06:45:11 +00001035 } else {
1036 llvm_unreachable("Invalid RelocStr value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001037 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001038 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001039 }
1040
Jack Carterb5cf5902013-04-17 00:18:04 +00001041 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001042 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001043 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001044 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001045 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001046 return Res;
1047 }
1048
1049 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001050 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1051 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001052 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1053 return Res;
1054 }
1055
1056 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001057 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1058 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1059 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001060 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001061 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001062 return Expr;
1063}
1064
1065bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1066
1067 switch (Expr->getKind()) {
1068 case MCExpr::Constant:
1069 return true;
1070 case MCExpr::SymbolRef:
1071 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1072 case MCExpr::Binary:
1073 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1074 if (!isEvaluated(BE->getLHS()))
1075 return false;
1076 return isEvaluated(BE->getRHS());
1077 }
1078 case MCExpr::Unary:
1079 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1080 default:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001081 return false;
1082 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001083 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001084}
Jack Carterd0bd6422013-04-18 00:41:53 +00001085
Jack Carterb5cf5902013-04-17 00:18:04 +00001086bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001087 Parser.Lex(); // Eat the % token.
1088 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001089 if (Tok.isNot(AsmToken::Identifier))
1090 return true;
1091
1092 std::string Str = Tok.getIdentifier().str();
1093
Jack Carterd0bd6422013-04-18 00:41:53 +00001094 Parser.Lex(); // Eat the identifier.
1095 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001096 const MCExpr *IdVal;
1097 SMLoc EndLoc;
1098
1099 if (getLexer().getKind() == AsmToken::LParen) {
1100 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001101 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001102 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001103 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001104 const AsmToken &nextTok = Parser.getTok();
1105 if (nextTok.isNot(AsmToken::Identifier))
1106 return true;
1107 Str += "(%";
1108 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001109 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001110 if (getLexer().getKind() != AsmToken::LParen)
1111 return true;
1112 } else
1113 break;
1114 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001115 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001116 return true;
1117
1118 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001119 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001120
1121 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001122 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001123
Jack Carterd0bd6422013-04-18 00:41:53 +00001124 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001125 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001126}
1127
Jack Carterb4dbc172012-09-05 23:34:03 +00001128bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1129 SMLoc &EndLoc) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001130 StartLoc = Parser.getTok().getLoc();
Jack Carter873c7242013-01-12 01:03:14 +00001131 RegNo = tryParseRegister(isMips64());
1132 EndLoc = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001133 return (RegNo == (unsigned) -1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001134}
1135
Jack Carterb5cf5902013-04-17 00:18:04 +00001136bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001137 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001138 bool Result = true;
1139
1140 while (getLexer().getKind() == AsmToken::LParen)
1141 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001142
Jack Carterd0bd6422013-04-18 00:41:53 +00001143 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001144 default:
1145 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001146 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001147 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001148 case AsmToken::Integer:
1149 case AsmToken::Minus:
1150 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001151 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001152 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001153 else
1154 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001155 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001156 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001157 break;
Jack Carter873c7242013-01-12 01:03:14 +00001158 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001159 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001160 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001161 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001162}
1163
Jack Carterb4dbc172012-09-05 23:34:03 +00001164MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Jack Carterd0bd6422013-04-18 00:41:53 +00001165 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001166
1167 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001168 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001169 bool isParenExpr = false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001170 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001171 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001172
Jack Carterb5cf5902013-04-17 00:18:04 +00001173 if (getLexer().getKind() == AsmToken::LParen) {
1174 Parser.Lex();
1175 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001176 }
1177
Jack Carterb5cf5902013-04-17 00:18:04 +00001178 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001179 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001180 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001181
Jack Carterd0bd6422013-04-18 00:41:53 +00001182 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001183 if (Tok.isNot(AsmToken::LParen)) {
1184 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
1185 if (Mnemonic->getToken() == "la") {
1186 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001187 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001188 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1189 return MatchOperand_Success;
1190 }
1191 if (Tok.is(AsmToken::EndOfStatement)) {
1192 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001193 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001194
Jack Carterd0bd6422013-04-18 00:41:53 +00001195 // Zero register assumed, add a memory operand with ZERO as its base.
1196 Operands.push_back(MipsOperand::CreateMem(isMips64() ? Mips::ZERO_64
1197 : Mips::ZERO,
1198 IdVal, S, E));
Jack Carterb5cf5902013-04-17 00:18:04 +00001199 return MatchOperand_Success;
1200 }
1201 Error(Parser.getTok().getLoc(), "'(' expected");
1202 return MatchOperand_ParseFail;
1203 }
1204
Jack Carterd0bd6422013-04-18 00:41:53 +00001205 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001206 }
1207
1208 const AsmToken &Tok1 = Parser.getTok(); // Get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +00001209 if (Tok1.is(AsmToken::Dollar)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001210 Parser.Lex(); // Eat the '$' token.
Jack Carter873c7242013-01-12 01:03:14 +00001211 if (tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001212 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1213 return MatchOperand_ParseFail;
1214 }
1215
1216 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001217 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001218 return MatchOperand_ParseFail;
1219 }
1220
Jack Carterd0bd6422013-04-18 00:41:53 +00001221 const AsmToken &Tok2 = Parser.getTok(); // Get next token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001222 if (Tok2.isNot(AsmToken::RParen)) {
1223 Error(Parser.getTok().getLoc(), "')' expected");
1224 return MatchOperand_ParseFail;
1225 }
1226
Jack Carter873c7242013-01-12 01:03:14 +00001227 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1228
Jack Carterd0bd6422013-04-18 00:41:53 +00001229 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001230
1231 if (IdVal == 0)
1232 IdVal = MCConstantExpr::Create(0, getContext());
1233
Jack Carterd0bd6422013-04-18 00:41:53 +00001234 // Replace the register operand with the memory operand.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001235 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1236 int RegNo = op->getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001237 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001238 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001239 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001240 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1241 int64_t Imm;
1242 if (IdVal->EvaluateAsAbsolute(Imm))
1243 IdVal = MCConstantExpr::Create(Imm, getContext());
1244 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1245 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1246 getContext());
1247 }
1248
Jack Carterdc1e35d2012-09-06 20:00:02 +00001249 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1250 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +00001251 return MatchOperand_Success;
1252}
1253
Jack Carter873c7242013-01-12 01:03:14 +00001254MipsAsmParser::OperandMatchResultTy
1255MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1256
1257 if (!isMips64())
1258 return MatchOperand_NoMatch;
Jack Carterd76b2372013-03-21 21:44:16 +00001259 if (getLexer().getKind() == AsmToken::Identifier) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001260 if (searchSymbolAlias(Operands, MipsOperand::Kind_CPU64Regs))
Jack Carterd76b2372013-03-21 21:44:16 +00001261 return MatchOperand_Success;
1262 return MatchOperand_NoMatch;
1263 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001264 // If the first token is not '$', we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001265 if (Parser.getTok().isNot(AsmToken::Dollar))
1266 return MatchOperand_NoMatch;
1267
1268 Parser.Lex(); // Eat $
Jack Carterd0bd6422013-04-18 00:41:53 +00001269 if (!tryParseRegisterOperand(Operands, true)) {
1270 // Set the proper register kind.
Jack Carter873c7242013-01-12 01:03:14 +00001271 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1272 op->setRegKind(MipsOperand::Kind_CPU64Regs);
1273 return MatchOperand_Success;
1274 }
1275 return MatchOperand_NoMatch;
1276}
1277
Jack Carterd0bd6422013-04-18 00:41:53 +00001278bool MipsAsmParser::searchSymbolAlias(
1279 SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegisterKind) {
Jack Carterd76b2372013-03-21 21:44:16 +00001280
1281 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1282 if (Sym) {
1283 SMLoc S = Parser.getTok().getLoc();
1284 const MCExpr *Expr;
1285 if (Sym->isVariable())
1286 Expr = Sym->getVariableValue();
1287 else
1288 return false;
1289 if (Expr->getKind() == MCExpr::SymbolRef) {
1290 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
1291 const StringRef DefSymbol = Ref->getSymbol().getName();
1292 if (DefSymbol.startswith("$")) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001293 // Lookup for the register with the corresponding name.
1294 int RegNum = matchRegisterName(DefSymbol.substr(1), isMips64());
Jack Carterd76b2372013-03-21 21:44:16 +00001295 if (RegNum > -1) {
1296 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001297 MipsOperand *op = MipsOperand::CreateReg(RegNum, S,
1298 Parser.getTok().getLoc());
1299 op->setRegKind((MipsOperand::RegisterKind) RegisterKind);
Jack Carterd76b2372013-03-21 21:44:16 +00001300 Operands.push_back(op);
1301 return true;
1302 }
1303 }
1304 } else if (Expr->getKind() == MCExpr::Constant) {
1305 Parser.Lex();
1306 const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001307 MipsOperand *op = MipsOperand::CreateImm(Const, S,
1308 Parser.getTok().getLoc());
Jack Carterd76b2372013-03-21 21:44:16 +00001309 Operands.push_back(op);
1310 return true;
1311 }
1312 }
1313 return false;
1314}
Jack Carterd0bd6422013-04-18 00:41:53 +00001315
Jack Carter873c7242013-01-12 01:03:14 +00001316MipsAsmParser::OperandMatchResultTy
1317MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1318
Jack Carterd76b2372013-03-21 21:44:16 +00001319 if (getLexer().getKind() == AsmToken::Identifier) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001320 if (searchSymbolAlias(Operands, MipsOperand::Kind_CPURegs))
Jack Carterd76b2372013-03-21 21:44:16 +00001321 return MatchOperand_Success;
1322 return MatchOperand_NoMatch;
1323 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001324 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001325 if (Parser.getTok().isNot(AsmToken::Dollar))
1326 return MatchOperand_NoMatch;
1327
1328 Parser.Lex(); // Eat $
Jack Carterd0bd6422013-04-18 00:41:53 +00001329 if (!tryParseRegisterOperand(Operands, false)) {
1330 // Set the proper register kind.
Jack Carter873c7242013-01-12 01:03:14 +00001331 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1332 op->setRegKind(MipsOperand::Kind_CPURegs);
1333 return MatchOperand_Success;
1334 }
1335 return MatchOperand_NoMatch;
1336}
1337
1338MipsAsmParser::OperandMatchResultTy
1339MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1340
Jack Carter2a74a87b2013-01-17 00:28:20 +00001341 if (isMips64())
1342 return MatchOperand_NoMatch;
1343
Jack Carterd0bd6422013-04-18 00:41:53 +00001344 // If the first token is not '$' we have error.
Jack Carter873c7242013-01-12 01:03:14 +00001345 if (Parser.getTok().isNot(AsmToken::Dollar))
1346 return MatchOperand_NoMatch;
1347 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001348 Parser.Lex(); // Eat the '$'.
Jack Carter873c7242013-01-12 01:03:14 +00001349
Jack Carterd0bd6422013-04-18 00:41:53 +00001350 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001351 if (Tok.isNot(AsmToken::Integer))
1352 return MatchOperand_NoMatch;
1353
1354 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001355 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001356 if (RegNum != 29)
1357 return MatchOperand_ParseFail;
1358
1359 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001360 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001361 op->setRegKind(MipsOperand::Kind_HWRegs);
1362 Operands.push_back(op);
1363
Jack Carterd0bd6422013-04-18 00:41:53 +00001364 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001365 return MatchOperand_Success;
1366}
1367
1368MipsAsmParser::OperandMatchResultTy
Jack Carterd0bd6422013-04-18 00:41:53 +00001369MipsAsmParser::parseHW64Regs(
1370 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter2a74a87b2013-01-17 00:28:20 +00001371
1372 if (!isMips64())
1373 return MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001374 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001375 if (Parser.getTok().isNot(AsmToken::Dollar))
1376 return MatchOperand_NoMatch;
1377 SMLoc S = Parser.getTok().getLoc();
1378 Parser.Lex(); // Eat $
1379
Jack Carterd0bd6422013-04-18 00:41:53 +00001380 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001381 if (Tok.isNot(AsmToken::Integer))
1382 return MatchOperand_NoMatch;
1383
1384 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001385 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001386 if (RegNum != 29)
1387 return MatchOperand_ParseFail;
1388
1389 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001390 Parser.getTok().getLoc());
Jack Carter2a74a87b2013-01-17 00:28:20 +00001391 op->setRegKind(MipsOperand::Kind_HW64Regs);
Jack Carter873c7242013-01-12 01:03:14 +00001392 Operands.push_back(op);
1393
Jack Carterd0bd6422013-04-18 00:41:53 +00001394 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001395 return MatchOperand_Success;
1396}
1397
1398MipsAsmParser::OperandMatchResultTy
1399MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1400 unsigned RegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001401 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001402 if (Parser.getTok().isNot(AsmToken::Dollar))
1403 return MatchOperand_NoMatch;
1404 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001405 Parser.Lex(); // Eat the '$'
Jack Carter873c7242013-01-12 01:03:14 +00001406
Jack Carterd0bd6422013-04-18 00:41:53 +00001407 const AsmToken &Tok = Parser.getTok(); // Get next token.
Jack Carter873c7242013-01-12 01:03:14 +00001408 if (Tok.is(AsmToken::Integer)) {
1409 RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001410 // At the moment only fcc0 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001411 if (RegNum != 0)
1412 return MatchOperand_ParseFail;
1413 } else if (Tok.is(AsmToken::Identifier)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001414 // At the moment only fcc0 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001415 if (Tok.getIdentifier() != "fcc0")
1416 return MatchOperand_ParseFail;
1417 } else
1418 return MatchOperand_NoMatch;
1419
1420 MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001421 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001422 op->setRegKind(MipsOperand::Kind_CCRRegs);
1423 Operands.push_back(op);
1424
Jack Carterd0bd6422013-04-18 00:41:53 +00001425 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001426 return MatchOperand_Success;
1427}
1428
Jack Carterdc1e35d2012-09-06 20:00:02 +00001429MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1430
1431 MCSymbolRefExpr::VariantKind VK
1432 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1433 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1434 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1435 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1436 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1437 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1438 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1439 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1440 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1441 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1442 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1443 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1444 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1445 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1446 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1447 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1448 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1449 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1450 .Default(MCSymbolRefExpr::VK_None);
1451
1452 return VK;
1453}
1454
Benjamin Kramer47b5c572012-09-10 11:52:14 +00001455static int ConvertCcString(StringRef CondString) {
Jack Cartera63b16a2012-09-07 00:23:42 +00001456 int CC = StringSwitch<unsigned>(CondString)
Jack Carterd0bd6422013-04-18 00:41:53 +00001457 .Case(".f", 0)
1458 .Case(".un", 1)
1459 .Case(".eq", 2)
1460 .Case(".ueq", 3)
1461 .Case(".olt", 4)
1462 .Case(".ult", 5)
1463 .Case(".ole", 6)
1464 .Case(".ule", 7)
1465 .Case(".sf", 8)
1466 .Case(".ngle", 9)
1467 .Case(".seq", 10)
1468 .Case(".ngl", 11)
1469 .Case(".lt", 12)
1470 .Case(".nge", 13)
1471 .Case(".le", 14)
1472 .Case(".ngt", 15)
1473 .Default(-1);
Jack Cartera63b16a2012-09-07 00:23:42 +00001474
1475 return CC;
1476}
1477
1478bool MipsAsmParser::
1479parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter0b744b32012-10-04 02:29:46 +00001480 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001481 // Split the format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001482 size_t Start = Name.find('.'), Next = Name.rfind('.');
1483 StringRef Format1 = Name.slice(Start, Next);
Jack Carterd0bd6422013-04-18 00:41:53 +00001484 // Add the first format to the operands.
Jack Cartera63b16a2012-09-07 00:23:42 +00001485 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carterd0bd6422013-04-18 00:41:53 +00001486 // Now for the second format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001487 StringRef Format2 = Name.slice(Next, StringRef::npos);
1488 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1489
Jack Carterd0bd6422013-04-18 00:41:53 +00001490 // Set the format for the first register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001491 setFpFormat(Format1);
1492
1493 // Read the remaining operands.
1494 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1495 // Read the first operand.
1496 if (ParseOperand(Operands, Name)) {
1497 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001498 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001499 return Error(Loc, "unexpected token in argument list");
1500 }
1501
1502 if (getLexer().isNot(AsmToken::Comma)) {
1503 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001504 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001505 return Error(Loc, "unexpected token in argument list");
Jack Cartera63b16a2012-09-07 00:23:42 +00001506 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001507 Parser.Lex(); // Eat the comma.
Jack Cartera63b16a2012-09-07 00:23:42 +00001508
Jack Carterb5cf5902013-04-17 00:18:04 +00001509 // Set the format for the first register
Jack Cartera63b16a2012-09-07 00:23:42 +00001510 setFpFormat(Format2);
1511
1512 // Parse and remember the operand.
1513 if (ParseOperand(Operands, Name)) {
1514 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001515 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001516 return Error(Loc, "unexpected token in argument list");
1517 }
1518 }
1519
1520 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1521 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001522 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001523 return Error(Loc, "unexpected token in argument list");
1524 }
1525
Jack Carterd0bd6422013-04-18 00:41:53 +00001526 Parser.Lex(); // Consume the EndOfStatement.
Jack Cartera63b16a2012-09-07 00:23:42 +00001527 return false;
1528}
1529
Rafael Espindola870c4e92012-01-11 03:56:41 +00001530bool MipsAsmParser::
Chad Rosierf0e87202012-10-25 20:41:34 +00001531ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindola870c4e92012-01-11 03:56:41 +00001532 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter1ac53222013-02-20 23:11:17 +00001533 StringRef Mnemonic;
Jack Carterd0bd6422013-04-18 00:41:53 +00001534 // Floating point instructions: Should the register be treated as a double?
Jack Cartera63b16a2012-09-07 00:23:42 +00001535 if (requestsDoubleOperand(Name)) {
1536 setFpFormat(FP_FORMAT_D);
Jack Carterd0bd6422013-04-18 00:41:53 +00001537 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
1538 Mnemonic = Name;
1539 } else {
Jack Cartera63b16a2012-09-07 00:23:42 +00001540 setDefaultFpFormat();
1541 // Create the leading tokens for the mnemonic, split by '.' characters.
1542 size_t Start = 0, Next = Name.find('.');
Jack Carter1ac53222013-02-20 23:11:17 +00001543 Mnemonic = Name.slice(Start, Next);
Jack Cartera63b16a2012-09-07 00:23:42 +00001544
1545 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1546
1547 if (Next != StringRef::npos) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001548 // There is a format token in mnemonic.
1549 size_t Dot = Name.find('.', Next + 1);
Jack Cartera63b16a2012-09-07 00:23:42 +00001550 StringRef Format = Name.slice(Next, Dot);
Jack Carterd0bd6422013-04-18 00:41:53 +00001551 if (Dot == StringRef::npos) // Only one '.' in a string, it's a format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001552 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1553 else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001554 if (Name.startswith("c.")) {
1555 // Floating point compare, add '.' and immediate represent for cc.
Jack Cartera63b16a2012-09-07 00:23:42 +00001556 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1557 int Cc = ConvertCcString(Format);
1558 if (Cc == -1) {
1559 return Error(NameLoc, "Invalid conditional code");
1560 }
Jack Carter873c7242013-01-12 01:03:14 +00001561 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001562 Parser.getTok().getLoc().getPointer() - 1);
1563 Operands.push_back(
1564 MipsOperand::CreateImm(MCConstantExpr::Create(Cc, getContext()),
1565 NameLoc, E));
Jack Cartera63b16a2012-09-07 00:23:42 +00001566 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001567 // trunc, ceil, floor ...
Jack Cartera63b16a2012-09-07 00:23:42 +00001568 return parseMathOperation(Name, NameLoc, Operands);
1569 }
1570
Jack Carterd0bd6422013-04-18 00:41:53 +00001571 // The rest is a format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001572 Format = Name.slice(Dot, StringRef::npos);
1573 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1574 }
1575
1576 setFpFormat(Format);
1577 }
1578 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001579
1580 // Read the remaining operands.
1581 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1582 // Read the first operand.
Jack Carter1ac53222013-02-20 23:11:17 +00001583 if (ParseOperand(Operands, Mnemonic)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001584 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001585 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001586 return Error(Loc, "unexpected token in argument list");
1587 }
1588
Jack Carterd0bd6422013-04-18 00:41:53 +00001589 while (getLexer().is(AsmToken::Comma)) {
1590 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00001591
1592 // Parse and remember the operand.
1593 if (ParseOperand(Operands, Name)) {
1594 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001595 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001596 return Error(Loc, "unexpected token in argument list");
1597 }
1598 }
1599 }
1600
1601 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1602 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001603 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001604 return Error(Loc, "unexpected token in argument list");
1605 }
1606
Jack Carterd0bd6422013-04-18 00:41:53 +00001607 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00001608 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00001609}
1610
Jack Carter0b744b32012-10-04 02:29:46 +00001611bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001612 SMLoc Loc = getLexer().getLoc();
1613 Parser.eatToEndOfStatement();
1614 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00001615}
1616
1617bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001618 // Line should look like: ".set noat".
1619 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00001620 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00001621 // eat noat
1622 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001623 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001624 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1625 reportParseError("unexpected token in statement");
1626 return false;
1627 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001628 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001629 return false;
1630}
Jack Carterd0bd6422013-04-18 00:41:53 +00001631
Jack Carter0b744b32012-10-04 02:29:46 +00001632bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001633 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00001634 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00001635 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00001636 getParser().Lex();
1637 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00001638 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00001639 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001640 return false;
1641 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001642 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00001643 if (getLexer().isNot(AsmToken::Dollar)) {
1644 reportParseError("unexpected token in statement");
1645 return false;
1646 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001647 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00001648 const AsmToken &Reg = Parser.getTok();
1649 if (Reg.is(AsmToken::Identifier)) {
1650 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
1651 } else if (Reg.is(AsmToken::Integer)) {
1652 AtRegNo = Reg.getIntVal();
1653 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001654 reportParseError("unexpected token in statement");
1655 return false;
1656 }
Jack Carter1ac53222013-02-20 23:11:17 +00001657
Jack Carterd0bd6422013-04-18 00:41:53 +00001658 if (AtRegNo < 1 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00001659 reportParseError("unexpected token in statement");
1660 return false;
1661 }
1662
1663 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00001664 reportParseError("unexpected token in statement");
1665 return false;
1666 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001667 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00001668
1669 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1670 reportParseError("unexpected token in statement");
1671 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001672 }
1673 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001674 return false;
1675 } else {
1676 reportParseError("unexpected token in statement");
1677 return false;
1678 }
1679}
1680
1681bool MipsAsmParser::parseSetReorderDirective() {
1682 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001683 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001684 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1685 reportParseError("unexpected token in statement");
1686 return false;
1687 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001688 Options.setReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00001689 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001690 return false;
1691}
1692
1693bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001694 Parser.Lex();
1695 // If this is not the end of the statement, report an error.
1696 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1697 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00001698 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001699 }
1700 Options.setNoreorder();
1701 Parser.Lex(); // Consume the EndOfStatement.
1702 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001703}
1704
1705bool MipsAsmParser::parseSetMacroDirective() {
1706 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001707 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001708 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1709 reportParseError("unexpected token in statement");
1710 return false;
1711 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001712 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001713 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001714 return false;
1715}
1716
1717bool MipsAsmParser::parseSetNoMacroDirective() {
1718 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001719 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001720 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1721 reportParseError("`noreorder' must be set before `nomacro'");
1722 return false;
1723 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001724 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00001725 reportParseError("`noreorder' must be set before `nomacro'");
1726 return false;
1727 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001728 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001729 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001730 return false;
1731}
Jack Carterd76b2372013-03-21 21:44:16 +00001732
1733bool MipsAsmParser::parseSetAssignment() {
1734 StringRef Name;
1735 const MCExpr *Value;
1736
1737 if (Parser.parseIdentifier(Name))
1738 reportParseError("expected identifier after .set");
1739
1740 if (getLexer().isNot(AsmToken::Comma))
1741 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00001742 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00001743
1744 if (Parser.parseExpression(Value))
1745 reportParseError("expected valid expression after comma");
1746
Jack Carterd0bd6422013-04-18 00:41:53 +00001747 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00001748 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00001749 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00001750 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00001751 Sym = getContext().GetOrCreateSymbol(Name);
1752 Sym->setVariableValue(Value);
1753
1754 return false;
1755}
Jack Carterd0bd6422013-04-18 00:41:53 +00001756
Jack Carter0b744b32012-10-04 02:29:46 +00001757bool MipsAsmParser::parseDirectiveSet() {
1758
Jack Carterd0bd6422013-04-18 00:41:53 +00001759 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00001760 const AsmToken &Tok = Parser.getTok();
1761
1762 if (Tok.getString() == "noat") {
1763 return parseSetNoAtDirective();
1764 } else if (Tok.getString() == "at") {
1765 return parseSetAtDirective();
1766 } else if (Tok.getString() == "reorder") {
1767 return parseSetReorderDirective();
1768 } else if (Tok.getString() == "noreorder") {
1769 return parseSetNoReorderDirective();
1770 } else if (Tok.getString() == "macro") {
1771 return parseSetMacroDirective();
1772 } else if (Tok.getString() == "nomacro") {
1773 return parseSetNoMacroDirective();
1774 } else if (Tok.getString() == "nomips16") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001775 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001776 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001777 return false;
1778 } else if (Tok.getString() == "nomicromips") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001779 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001780 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001781 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001782 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001783 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00001784 parseSetAssignment();
1785 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001786 }
Jack Carter07c818d2013-01-25 01:31:34 +00001787
Jack Carter0b744b32012-10-04 02:29:46 +00001788 return true;
1789}
1790
Jack Carter07c818d2013-01-25 01:31:34 +00001791/// parseDirectiveWord
1792/// ::= .word [ expression (, expression)* ]
1793bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
1794 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1795 for (;;) {
1796 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001797 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00001798 return true;
1799
1800 getParser().getStreamer().EmitValue(Value, Size);
1801
1802 if (getLexer().is(AsmToken::EndOfStatement))
1803 break;
1804
1805 // FIXME: Improve diagnostic.
1806 if (getLexer().isNot(AsmToken::Comma))
1807 return Error(L, "unexpected token in directive");
1808 Parser.Lex();
1809 }
1810 }
1811
1812 Parser.Lex();
1813 return false;
1814}
1815
Jack Carter0b744b32012-10-04 02:29:46 +00001816bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +00001817
Jack Carter07c818d2013-01-25 01:31:34 +00001818 StringRef IDVal = DirectiveID.getString();
1819
Jack Carterd0bd6422013-04-18 00:41:53 +00001820 if (IDVal == ".ent") {
1821 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001822 Parser.Lex();
1823 return false;
1824 }
1825
Jack Carter07c818d2013-01-25 01:31:34 +00001826 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001827 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001828 Parser.Lex();
1829 return false;
1830 }
1831
Jack Carter07c818d2013-01-25 01:31:34 +00001832 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001833 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001834 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001835 return false;
1836 }
1837
Jack Carter07c818d2013-01-25 01:31:34 +00001838 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00001839 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00001840 }
1841
Jack Carter07c818d2013-01-25 01:31:34 +00001842 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001843 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001844 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001845 return false;
1846 }
1847
Jack Carter07c818d2013-01-25 01:31:34 +00001848 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001849 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001850 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001851 return false;
1852 }
1853
Jack Carter07c818d2013-01-25 01:31:34 +00001854 if (IDVal == ".gpword") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001855 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001856 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001857 return false;
1858 }
1859
Jack Carter07c818d2013-01-25 01:31:34 +00001860 if (IDVal == ".word") {
1861 parseDirectiveWord(4, DirectiveID.getLoc());
1862 return false;
1863 }
1864
Rafael Espindola870c4e92012-01-11 03:56:41 +00001865 return true;
1866}
1867
Rafael Espindola870c4e92012-01-11 03:56:41 +00001868extern "C" void LLVMInitializeMipsAsmParser() {
1869 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1870 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1871 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1872 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1873}
Jack Carterb4dbc172012-09-05 23:34:03 +00001874
1875#define GET_REGISTER_MATCHER
1876#define GET_MATCHER_IMPLEMENTATION
1877#include "MipsGenAsmMatcher.inc"