blob: 6ee1472b06ca9a7a6eb4fbb8ba61268355e71896 [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
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000014#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000015#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000017#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000021#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/MC/MCParser/MCAsmLexer.h"
23#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCStreamer.h"
25#include "llvm/MC/MCSubtargetInfo.h"
26#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000027#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000028#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000029#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000031#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000032#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000033#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000034
35using namespace llvm;
36
Chandler Carruthe96dd892014-04-21 22:55:11 +000037#define DEBUG_TYPE "mips-asm-parser"
38
Joey Gouly0e76fa72013-09-12 10:28:05 +000039namespace llvm {
40class MCInstrInfo;
41}
42
Rafael Espindola870c4e92012-01-11 03:56:41 +000043namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000044class MipsAssemblerOptions {
45public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000046 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000047 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000048
Toma Tabacu9db22db2014-09-09 10:15:38 +000049 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000050 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000051 Reorder = Opts->isReorder();
52 Macro = Opts->isMacro();
53 Features = Opts->getFeatures();
54 }
55
Toma Tabacub19cf202015-04-27 13:12:59 +000056 unsigned getATRegIndex() const { return ATReg; }
57 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000058 if (Reg > 31)
59 return false;
60
61 ATReg = Reg;
62 return true;
63 }
Jack Carter0b744b32012-10-04 02:29:46 +000064
Toma Tabacu9db22db2014-09-09 10:15:38 +000065 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000066 void setReorder() { Reorder = true; }
67 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000068
Toma Tabacu9db22db2014-09-09 10:15:38 +000069 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000070 void setMacro() { Macro = true; }
71 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000072
Toma Tabacu465acfd2015-06-09 13:33:26 +000073 const FeatureBitset &getFeatures() const { return Features; }
74 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000075
Daniel Sandersf0df2212014-08-04 12:20:00 +000076 // Set of features that are either architecture features or referenced
77 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
78 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
79 // The reason we need this mask is explained in the selectArch function.
80 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000081 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000082
Jack Carter0b744b32012-10-04 02:29:46 +000083private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000084 unsigned ATReg;
85 bool Reorder;
86 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000087 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000088};
89}
90
Michael Kupersteindb0712f2015-05-26 10:47:10 +000091const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
92 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
93 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
94 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
95 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
96 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
97 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
98 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
99 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
100};
101
Jack Carter0b744b32012-10-04 02:29:46 +0000102namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000103class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000104 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000105 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000106 return static_cast<MipsTargetStreamer &>(TS);
107 }
108
Jack Carterb4dbc172012-09-05 23:34:03 +0000109 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000110 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000111 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000112 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
113 // nullptr, which indicates that no function is currently
114 // selected. This usually happens after an '.end func'
115 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000116 bool IsLittleEndian;
Jack Carter0b744b32012-10-04 02:29:46 +0000117
Daniel Sandersef638fe2014-10-03 15:37:37 +0000118 // Print a warning along with its fix-it message at the given range.
119 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
120 SMRange Range, bool ShowColors = true);
121
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000122#define GET_ASSEMBLER_HEADER
123#include "MipsGenAsmMatcher.inc"
124
Matheus Almeida595fcab2014-06-11 15:05:56 +0000125 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
126
Chad Rosier49963552012-10-13 00:26:04 +0000127 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000128 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000129 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000130 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000131
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000132 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000133 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000134
Toma Tabacu13964452014-09-04 13:23:44 +0000135 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000136
Toma Tabacu13964452014-09-04 13:23:44 +0000137 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000138
David Blaikie960ea3f2014-06-08 16:18:35 +0000139 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
140 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000141
Craig Topper56c590a2014-04-29 07:58:02 +0000142 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000143
David Blaikie960ea3f2014-06-08 16:18:35 +0000144 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000145
146 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000147 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000148 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000149
Jack Carter873c7242013-01-12 01:03:14 +0000150 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000151 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000152
Toma Tabacu13964452014-09-04 13:23:44 +0000153 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000154
Toma Tabacu13964452014-09-04 13:23:44 +0000155 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000156
Toma Tabacu13964452014-09-04 13:23:44 +0000157 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000158
David Blaikie960ea3f2014-06-08 16:18:35 +0000159 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000160
Toma Tabacu13964452014-09-04 13:23:44 +0000161 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000162
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000163 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000164 parseRegisterPair (OperandVector &Operands);
165
166 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000167 parseMovePRegPair(OperandVector &Operands);
168
169 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000170 parseRegisterList (OperandVector &Operands);
171
David Blaikie960ea3f2014-06-08 16:18:35 +0000172 bool searchSymbolAlias(OperandVector &Operands);
173
Toma Tabacu13964452014-09-04 13:23:44 +0000174 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000175
Jack Carter30a59822012-10-04 04:03:53 +0000176 bool needsExpansion(MCInst &Inst);
177
Matheus Almeida3813d572014-06-19 14:39:14 +0000178 // Expands assembly pseudo instructions.
179 // Returns false on success, true otherwise.
180 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000181 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000182
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000183 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
184 SmallVectorImpl<MCInst> &Instructions);
185
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000186 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
187 bool Is32BitImm, SMLoc IDLoc,
188 SmallVectorImpl<MCInst> &Instructions);
189
Toma Tabacuf712ede2015-06-17 14:31:51 +0000190 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
191 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
192 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000193
Toma Tabacu00e98672015-05-01 12:19:27 +0000194 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000195 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000196
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000197 bool expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000198 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000199
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000200 bool expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000201 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000202 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
203 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000204
Jack Carter9e65aa32013-03-22 00:05:30 +0000205 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000206 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
207 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000208
209 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
210 SmallVectorImpl<MCInst> &Instructions);
211
Toma Tabacue1e460d2015-06-11 10:36:10 +0000212 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
213 SmallVectorImpl<MCInst> &Instructions);
214
Toma Tabacu1a108322015-06-17 13:20:24 +0000215 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
216 SmallVectorImpl<MCInst> &Instructions);
217
Toma Tabacud88d79c2015-06-23 14:39:42 +0000218 bool expandUlhu(MCInst &Inst, SMLoc IDLoc,
219 SmallVectorImpl<MCInst> &Instructions);
220
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000221 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
222 SmallVectorImpl<MCInst> &Instructions);
223
Toma Tabacu234482a2015-03-16 12:03:39 +0000224 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
225 SmallVectorImpl<MCInst> &Instructions);
226
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000227 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000228 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000229
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000230 bool reportParseError(Twine ErrorMsg);
231 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000232
Jack Carterb5cf5902013-04-17 00:18:04 +0000233 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000234 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000235
Vladimir Medic4c299852013-11-06 11:27:05 +0000236 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000237
238 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000239 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000240 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000241 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000242 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000243 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000244 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000245 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000246 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000247 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000248
249 bool parseSetAtDirective();
250 bool parseSetNoAtDirective();
251 bool parseSetMacroDirective();
252 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000253 bool parseSetMsaDirective();
254 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000255 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000256 bool parseSetReorderDirective();
257 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000258 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000259 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000260 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000261 bool parseSetOddSPRegDirective();
262 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000263 bool parseSetPopDirective();
264 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000265 bool parseSetSoftFloatDirective();
266 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000267
Jack Carterd76b2372013-03-21 21:44:16 +0000268 bool parseSetAssignment();
269
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000270 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000271 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000272 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000273 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000274 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000275 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
276 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000277
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000278 bool parseInternalDirectiveReallowModule();
279
Jack Carterdc1e35d2012-09-06 20:00:02 +0000280 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000281
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000282 bool eatComma(StringRef ErrorStr);
283
Jack Carter1ac53222013-02-20 23:11:17 +0000284 int matchCPURegisterName(StringRef Symbol);
285
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000286 int matchHWRegsRegisterName(StringRef Symbol);
287
Jack Carter873c7242013-01-12 01:03:14 +0000288 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000289
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000290 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000291
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000292 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000293
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000294 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000295
Jack Carter5dc8ac92013-09-25 23:50:44 +0000296 int matchMSA128RegisterName(StringRef Name);
297
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000298 int matchMSA128CtrlRegisterName(StringRef Name);
299
Jack Carterd0bd6422013-04-18 00:41:53 +0000300 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000301
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000302 unsigned getGPR(int RegNo);
303
Toma Tabacu89a712b2015-04-15 10:48:56 +0000304 /// Returns the internal register number for the current AT. Also checks if
305 /// the current AT is unavailable (set to $0) and gives an error if it is.
306 /// This should be used in pseudo-instruction expansions which need AT.
307 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000308
309 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000310 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000311
312 // Helper function that checks if the value of a vector index is within the
313 // boundaries of accepted values for each RegisterKind
314 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
315 bool validateMSAIndex(int Val, int RegKind);
316
Daniel Sandersf0df2212014-08-04 12:20:00 +0000317 // Selects a new architecture by updating the FeatureBits with the necessary
318 // info including implied dependencies.
319 // Internally, it clears all the feature bits related to *any* architecture
320 // and selects the new one using the ToggleFeature functionality of the
321 // MCSubtargetInfo object that handles implied dependencies. The reason we
322 // clear all the arch related bits manually is because ToggleFeature only
323 // clears the features that imply the feature being cleared and not the
324 // features implied by the feature being cleared. This is easier to see
325 // with an example:
326 // --------------------------------------------------
327 // | Feature | Implies |
328 // | -------------------------------------------------|
329 // | FeatureMips1 | None |
330 // | FeatureMips2 | FeatureMips1 |
331 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
332 // | FeatureMips4 | FeatureMips3 |
333 // | ... | |
334 // --------------------------------------------------
335 //
336 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
337 // FeatureMipsGP64 | FeatureMips1)
338 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
339 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000340 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000341 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
342 STI.setFeatureBits(FeatureBits);
343 setAvailableFeatures(
344 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000345 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000346 }
347
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000348 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000349 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000350 setAvailableFeatures(
351 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000352 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000353 }
354 }
355
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000356 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000357 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000358 setAvailableFeatures(
359 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000360 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000361 }
362 }
363
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000364 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
365 setFeatureBits(Feature, FeatureString);
366 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
367 }
368
369 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
370 clearFeatureBits(Feature, FeatureString);
371 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
372 }
373
Rafael Espindola870c4e92012-01-11 03:56:41 +0000374public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000375 enum MipsMatchResultTy {
376 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
377#define GET_OPERAND_DIAGNOSTIC_TYPES
378#include "MipsGenAsmMatcher.inc"
379#undef GET_OPERAND_DIAGNOSTIC_TYPES
380
381 };
382
Joey Gouly0e76fa72013-09-12 10:28:05 +0000383 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000384 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000385 : MCTargetAsmParser(), STI(sti),
386 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
387 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000388 MCAsmParserExtension::Initialize(parser);
389
Toma Tabacu11e14a92015-04-21 11:50:52 +0000390 parser.addAliasForDirective(".asciiz", ".asciz");
391
Jack Carterb4dbc172012-09-05 23:34:03 +0000392 // Initialize the set of available features.
393 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000394
395 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000396 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000397 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000398
399 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000400 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000401 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000402
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000403 getTargetStreamer().updateABIInfo(*this);
404
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000405 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000406 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000407
408 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000409
410 Triple TheTriple(sti.getTargetTriple());
411 if ((TheTriple.getArch() == Triple::mips) ||
412 (TheTriple.getArch() == Triple::mips64))
413 IsLittleEndian = false;
414 else
415 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000416 }
417
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000418 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
419 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
420
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000421 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
422 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000423 const MipsABIInfo &getABI() const { return ABI; }
424 bool isABI_N32() const { return ABI.IsN32(); }
425 bool isABI_N64() const { return ABI.IsN64(); }
426 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000427 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000428
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000429 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000430 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000431 }
432
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000433 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000434 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000435 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000436 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
437 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
438 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
439 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
440 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000441 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000442 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000443 }
444 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000445 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000446 }
447 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000448 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000449 }
450 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000451 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000452 }
Daniel Sanders17793142015-02-18 16:24:50 +0000453 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000454 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000455 }
456 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000457 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000458 }
459 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000460 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000461 }
462 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000463 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000464 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000465 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000466 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000467 }
468 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000469 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000470 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000471
472 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
473 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
474 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000475 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000476 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000477 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000478
479 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000480 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000481 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000482
Eric Christophere8ae3e32015-05-07 23:10:21 +0000483 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000484 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000485 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000486
Toma Tabacud9d344b2015-04-27 14:05:04 +0000487 /// Warn if RegIndex is the same as the current AT.
488 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000489
490 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000491
492 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000493};
494}
495
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000496namespace {
497
498/// MipsOperand - Instances of this class represent a parsed Mips machine
499/// instruction.
500class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000501public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000502 /// Broad categories of register classes
503 /// The exact class is finalized by the render method.
504 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000505 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000506 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000507 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000508 RegKind_FCC = 4, /// FCC
509 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
510 RegKind_MSACtrl = 16, /// MSA control registers
511 RegKind_COP2 = 32, /// COP2
512 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
513 /// context).
514 RegKind_CCR = 128, /// CCR
515 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000516 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000517 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000518 /// Potentially any (e.g. $1)
519 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
520 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000521 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000522 };
523
524private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000525 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000526 k_Immediate, /// An immediate (possibly involving symbol references)
527 k_Memory, /// Base + Offset Memory Address
528 k_PhysRegister, /// A physical register from the Mips namespace
529 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000530 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000531 k_RegList, /// A physical register list
532 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000533 } Kind;
534
David Blaikie960ea3f2014-06-08 16:18:35 +0000535public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000536 MipsOperand(KindTy K, MipsAsmParser &Parser)
537 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
538
David Blaikie960ea3f2014-06-08 16:18:35 +0000539private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000540 /// For diagnostics, and checking the assembler temporary
541 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000542
Eric Christopher8996c5d2013-03-15 00:42:55 +0000543 struct Token {
544 const char *Data;
545 unsigned Length;
546 };
547
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000548 struct PhysRegOp {
549 unsigned Num; /// Register Number
550 };
551
552 struct RegIdxOp {
553 unsigned Index; /// Index into the register class
554 RegKind Kind; /// Bitfield of the kinds it could possibly be
555 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000556 };
557
558 struct ImmOp {
559 const MCExpr *Val;
560 };
561
562 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000563 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000564 const MCExpr *Off;
565 };
566
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000567 struct RegListOp {
568 SmallVector<unsigned, 10> *List;
569 };
570
Jack Carterb4dbc172012-09-05 23:34:03 +0000571 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000572 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000573 struct PhysRegOp PhysReg;
574 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000575 struct ImmOp Imm;
576 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000577 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000578 };
579
580 SMLoc StartLoc, EndLoc;
581
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000582 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000583 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
584 const MCRegisterInfo *RegInfo,
585 SMLoc S, SMLoc E,
586 MipsAsmParser &Parser) {
587 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000588 Op->RegIdx.Index = Index;
589 Op->RegIdx.RegInfo = RegInfo;
590 Op->RegIdx.Kind = RegKind;
591 Op->StartLoc = S;
592 Op->EndLoc = E;
593 return Op;
594 }
595
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000596public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000597 /// Coerce the register to GPR32 and return the real register for the current
598 /// target.
599 unsigned getGPR32Reg() const {
600 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000601 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000602 unsigned ClassID = Mips::GPR32RegClassID;
603 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000604 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000605
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000606 /// Coerce the register to GPR32 and return the real register for the current
607 /// target.
608 unsigned getGPRMM16Reg() const {
609 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
610 unsigned ClassID = Mips::GPR32RegClassID;
611 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
612 }
613
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000614 /// Coerce the register to GPR64 and return the real register for the current
615 /// target.
616 unsigned getGPR64Reg() const {
617 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
618 unsigned ClassID = Mips::GPR64RegClassID;
619 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000620 }
621
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000622private:
623 /// Coerce the register to AFGR64 and return the real register for the current
624 /// target.
625 unsigned getAFGR64Reg() const {
626 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
627 if (RegIdx.Index % 2 != 0)
628 AsmParser.Warning(StartLoc, "Float register should be even.");
629 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
630 .getRegister(RegIdx.Index / 2);
631 }
632
633 /// Coerce the register to FGR64 and return the real register for the current
634 /// target.
635 unsigned getFGR64Reg() const {
636 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
637 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
638 .getRegister(RegIdx.Index);
639 }
640
641 /// Coerce the register to FGR32 and return the real register for the current
642 /// target.
643 unsigned getFGR32Reg() const {
644 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
645 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
646 .getRegister(RegIdx.Index);
647 }
648
649 /// Coerce the register to FGRH32 and return the real register for the current
650 /// target.
651 unsigned getFGRH32Reg() const {
652 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
653 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
654 .getRegister(RegIdx.Index);
655 }
656
657 /// Coerce the register to FCC and return the real register for the current
658 /// target.
659 unsigned getFCCReg() const {
660 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
661 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
662 .getRegister(RegIdx.Index);
663 }
664
665 /// Coerce the register to MSA128 and return the real register for the current
666 /// target.
667 unsigned getMSA128Reg() const {
668 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
669 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
670 // identical
671 unsigned ClassID = Mips::MSA128BRegClassID;
672 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
673 }
674
675 /// Coerce the register to MSACtrl and return the real register for the
676 /// current target.
677 unsigned getMSACtrlReg() const {
678 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
679 unsigned ClassID = Mips::MSACtrlRegClassID;
680 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
681 }
682
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000683 /// Coerce the register to COP0 and return the real register for the
684 /// current target.
685 unsigned getCOP0Reg() const {
686 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
687 unsigned ClassID = Mips::COP0RegClassID;
688 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
689 }
690
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000691 /// Coerce the register to COP2 and return the real register for the
692 /// current target.
693 unsigned getCOP2Reg() const {
694 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
695 unsigned ClassID = Mips::COP2RegClassID;
696 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
697 }
698
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000699 /// Coerce the register to COP3 and return the real register for the
700 /// current target.
701 unsigned getCOP3Reg() const {
702 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
703 unsigned ClassID = Mips::COP3RegClassID;
704 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
705 }
706
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000707 /// Coerce the register to ACC64DSP and return the real register for the
708 /// current target.
709 unsigned getACC64DSPReg() const {
710 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
711 unsigned ClassID = Mips::ACC64DSPRegClassID;
712 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
713 }
714
715 /// Coerce the register to HI32DSP and return the real register for the
716 /// current target.
717 unsigned getHI32DSPReg() const {
718 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
719 unsigned ClassID = Mips::HI32DSPRegClassID;
720 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
721 }
722
723 /// Coerce the register to LO32DSP and return the real register for the
724 /// current target.
725 unsigned getLO32DSPReg() const {
726 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
727 unsigned ClassID = Mips::LO32DSPRegClassID;
728 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
729 }
730
731 /// Coerce the register to CCR and return the real register for the
732 /// current target.
733 unsigned getCCRReg() const {
734 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
735 unsigned ClassID = Mips::CCRRegClassID;
736 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
737 }
738
739 /// Coerce the register to HWRegs and return the real register for the
740 /// current target.
741 unsigned getHWRegsReg() const {
742 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
743 unsigned ClassID = Mips::HWRegsRegClassID;
744 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
745 }
746
747public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000748 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000749 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000750 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000751 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000752 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000753 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000754 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000755 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000756 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000757
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000758 void addRegOperands(MCInst &Inst, unsigned N) const {
759 llvm_unreachable("Use a custom parser instead");
760 }
761
Daniel Sanders21bce302014-04-01 12:35:23 +0000762 /// Render the operand to an MCInst as a GPR32
763 /// Asserts if the wrong number of operands are requested, or the operand
764 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000765 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
766 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000767 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000768 }
769
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000770 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
771 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000772 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000773 }
774
Jozef Kolek1904fa22014-11-24 14:25:53 +0000775 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
776 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000777 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000778 }
779
Zoran Jovanovic41688672015-02-10 16:36:20 +0000780 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
781 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000782 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000783 }
784
Daniel Sanders21bce302014-04-01 12:35:23 +0000785 /// Render the operand to an MCInst as a GPR64
786 /// Asserts if the wrong number of operands are requested, or the operand
787 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000788 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
789 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000790 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000791 }
792
793 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
794 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000795 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000796 }
797
798 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
799 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000800 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000801 }
802
803 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
804 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000805 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000806 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000807 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000808 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
809 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000810 }
811
812 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
813 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000814 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000815 }
816
817 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
818 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000819 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000820 }
821
822 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
823 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000824 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000825 }
826
827 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
828 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000829 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 }
831
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000832 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
833 assert(N == 1 && "Invalid number of operands!");
834 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
835 }
836
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000837 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
838 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000839 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000840 }
841
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000842 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
843 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000844 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000845 }
846
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000847 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
848 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000849 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 }
851
852 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
853 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000854 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000855 }
856
857 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
858 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000859 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000860 }
861
862 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
863 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000864 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000865 }
866
867 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
868 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000869 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000870 }
871
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000872 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000873 assert(N == 1 && "Invalid number of operands!");
874 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000875 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000876 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000877
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000878 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000879 assert(N == 2 && "Invalid number of operands!");
880
Jim Grosbache9119e42015-05-13 18:37:00 +0000881 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000882
883 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000884 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000885 }
886
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000887 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
888 assert(N == 2 && "Invalid number of operands!");
889
Jim Grosbache9119e42015-05-13 18:37:00 +0000890 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000891
892 const MCExpr *Expr = getMemOff();
893 addExpr(Inst, Expr);
894 }
895
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000896 void addRegListOperands(MCInst &Inst, unsigned N) const {
897 assert(N == 1 && "Invalid number of operands!");
898
899 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000900 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000901 }
902
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000903 void addRegPairOperands(MCInst &Inst, unsigned N) const {
904 assert(N == 2 && "Invalid number of operands!");
905 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000906 Inst.addOperand(MCOperand::createReg(RegNo++));
907 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000908 }
909
Zoran Jovanovic41688672015-02-10 16:36:20 +0000910 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
911 assert(N == 2 && "Invalid number of operands!");
912 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000913 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000914 }
915
Craig Topper56c590a2014-04-29 07:58:02 +0000916 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000917 // As a special case until we sort out the definition of div/divu, pretend
918 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
919 if (isGPRAsmReg() && RegIdx.Index == 0)
920 return true;
921
922 return Kind == k_PhysRegister;
923 }
924 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000925 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000926 bool isConstantImm() const {
927 return isImm() && dyn_cast<MCConstantExpr>(getImm());
928 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000929 template <unsigned Bits> bool isUImm() const {
930 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
931 }
Craig Topper56c590a2014-04-29 07:58:02 +0000932 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000933 // Note: It's not possible to pretend that other operand kinds are tokens.
934 // The matcher emitter checks tokens first.
935 return Kind == k_Token;
936 }
Craig Topper56c590a2014-04-29 07:58:02 +0000937 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000938 bool isConstantMemOff() const {
939 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
940 }
941 template <unsigned Bits> bool isMemWithSimmOffset() const {
942 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
943 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000944 bool isMemWithGRPMM16Base() const {
945 return isMem() && getMemBase()->isMM16AsmReg();
946 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000947 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
948 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
949 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
950 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000951 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
952 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
953 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
954 && (getMemBase()->getGPR32Reg() == Mips::SP);
955 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000956 bool isRegList16() const {
957 if (!isRegList())
958 return false;
959
960 int Size = RegList.List->size();
961 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
962 RegList.List->back() != Mips::RA)
963 return false;
964
965 int PrevReg = *RegList.List->begin();
966 for (int i = 1; i < Size - 1; i++) {
967 int Reg = (*(RegList.List))[i];
968 if ( Reg != PrevReg + 1)
969 return false;
970 PrevReg = Reg;
971 }
972
973 return true;
974 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000975 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000976 bool isLSAImm() const {
977 if (!isConstantImm())
978 return false;
979 int64_t Val = getConstantImm();
980 return 1 <= Val && Val <= 4;
981 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000982 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000983 bool isMovePRegPair() const {
984 if (Kind != k_RegList || RegList.List->size() != 2)
985 return false;
986
987 unsigned R0 = RegList.List->front();
988 unsigned R1 = RegList.List->back();
989
990 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
991 (R0 == Mips::A1 && R1 == Mips::A3) ||
992 (R0 == Mips::A2 && R1 == Mips::A3) ||
993 (R0 == Mips::A0 && R1 == Mips::S5) ||
994 (R0 == Mips::A0 && R1 == Mips::S6) ||
995 (R0 == Mips::A0 && R1 == Mips::A1) ||
996 (R0 == Mips::A0 && R1 == Mips::A2) ||
997 (R0 == Mips::A0 && R1 == Mips::A3))
998 return true;
999
1000 return false;
1001 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001002
1003 StringRef getToken() const {
1004 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001005 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001006 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001007 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001008
Craig Topper56c590a2014-04-29 07:58:02 +00001009 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001010 // As a special case until we sort out the definition of div/divu, pretend
1011 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1012 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1013 RegIdx.Kind & RegKind_GPR)
1014 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001015
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001016 assert(Kind == k_PhysRegister && "Invalid access!");
1017 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001018 }
1019
Jack Carterb4dbc172012-09-05 23:34:03 +00001020 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001021 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001022 return Imm.Val;
1023 }
1024
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001025 int64_t getConstantImm() const {
1026 const MCExpr *Val = getImm();
1027 return static_cast<const MCConstantExpr *>(Val)->getValue();
1028 }
1029
1030 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001031 assert((Kind == k_Memory) && "Invalid access!");
1032 return Mem.Base;
1033 }
1034
1035 const MCExpr *getMemOff() const {
1036 assert((Kind == k_Memory) && "Invalid access!");
1037 return Mem.Off;
1038 }
1039
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001040 int64_t getConstantMemOff() const {
1041 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1042 }
1043
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001044 const SmallVectorImpl<unsigned> &getRegList() const {
1045 assert((Kind == k_RegList) && "Invalid access!");
1046 return *(RegList.List);
1047 }
1048
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001049 unsigned getRegPair() const {
1050 assert((Kind == k_RegPair) && "Invalid access!");
1051 return RegIdx.Index;
1052 }
1053
David Blaikie960ea3f2014-06-08 16:18:35 +00001054 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1055 MipsAsmParser &Parser) {
1056 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001057 Op->Tok.Data = Str.data();
1058 Op->Tok.Length = Str.size();
1059 Op->StartLoc = S;
1060 Op->EndLoc = S;
1061 return Op;
1062 }
1063
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001064 /// Create a numeric register (e.g. $1). The exact register remains
1065 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001066 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001067 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001068 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001069 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001070 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001071 }
1072
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001073 /// Create a register that is definitely a GPR.
1074 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001075 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001076 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001077 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001078 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001079 }
1080
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001081 /// Create a register that is definitely a FGR.
1082 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001083 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001084 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001085 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001086 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1087 }
1088
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001089 /// Create a register that is definitely a HWReg.
1090 /// This is typically only used for named registers such as $hwr_cpunum.
1091 static std::unique_ptr<MipsOperand>
1092 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1093 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1094 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1095 }
1096
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001097 /// Create a register that is definitely an FCC.
1098 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001099 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001100 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001101 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001102 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1103 }
1104
1105 /// Create a register that is definitely an ACC.
1106 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001107 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001108 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001109 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001110 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1111 }
1112
1113 /// Create a register that is definitely an MSA128.
1114 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001115 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001116 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001117 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001118 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1119 }
1120
1121 /// Create a register that is definitely an MSACtrl.
1122 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001123 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001124 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001125 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001126 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1127 }
1128
David Blaikie960ea3f2014-06-08 16:18:35 +00001129 static std::unique_ptr<MipsOperand>
1130 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1131 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001132 Op->Imm.Val = Val;
1133 Op->StartLoc = S;
1134 Op->EndLoc = E;
1135 return Op;
1136 }
1137
David Blaikie960ea3f2014-06-08 16:18:35 +00001138 static std::unique_ptr<MipsOperand>
1139 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1140 SMLoc E, MipsAsmParser &Parser) {
1141 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1142 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001143 Op->Mem.Off = Off;
1144 Op->StartLoc = S;
1145 Op->EndLoc = E;
1146 return Op;
1147 }
1148
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001149 static std::unique_ptr<MipsOperand>
1150 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1151 MipsAsmParser &Parser) {
1152 assert (Regs.size() > 0 && "Empty list not allowed");
1153
1154 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001155 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001156 Op->StartLoc = StartLoc;
1157 Op->EndLoc = EndLoc;
1158 return Op;
1159 }
1160
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001161 static std::unique_ptr<MipsOperand>
1162 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1163 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1164 Op->RegIdx.Index = RegNo;
1165 Op->StartLoc = S;
1166 Op->EndLoc = E;
1167 return Op;
1168 }
1169
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001170 bool isGPRAsmReg() const {
1171 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001172 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001173 bool isMM16AsmReg() const {
1174 if (!(isRegIdx() && RegIdx.Kind))
1175 return false;
1176 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1177 || RegIdx.Index == 16 || RegIdx.Index == 17);
1178 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001179 bool isMM16AsmRegZero() const {
1180 if (!(isRegIdx() && RegIdx.Kind))
1181 return false;
1182 return (RegIdx.Index == 0 ||
1183 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1184 RegIdx.Index == 17);
1185 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001186 bool isMM16AsmRegMoveP() const {
1187 if (!(isRegIdx() && RegIdx.Kind))
1188 return false;
1189 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1190 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1191 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001192 bool isFGRAsmReg() const {
1193 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1194 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001195 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001196 bool isHWRegsAsmReg() const {
1197 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001198 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001199 bool isCCRAsmReg() const {
1200 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001201 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001202 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001203 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1204 return false;
1205 if (!AsmParser.hasEightFccRegisters())
1206 return RegIdx.Index == 0;
1207 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001208 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001209 bool isACCAsmReg() const {
1210 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001211 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001212 bool isCOP0AsmReg() const {
1213 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1214 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001215 bool isCOP2AsmReg() const {
1216 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001217 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001218 bool isCOP3AsmReg() const {
1219 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1220 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001221 bool isMSA128AsmReg() const {
1222 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001223 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001224 bool isMSACtrlAsmReg() const {
1225 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001226 }
1227
Jack Carterb4dbc172012-09-05 23:34:03 +00001228 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001229 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001230 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001231 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001232
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001233 virtual ~MipsOperand() {
1234 switch (Kind) {
1235 case k_Immediate:
1236 break;
1237 case k_Memory:
1238 delete Mem.Base;
1239 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001240 case k_RegList:
1241 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001242 case k_PhysRegister:
1243 case k_RegisterIndex:
1244 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001245 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001246 break;
1247 }
1248 }
1249
Craig Topper56c590a2014-04-29 07:58:02 +00001250 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001251 switch (Kind) {
1252 case k_Immediate:
1253 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001254 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001255 OS << ">";
1256 break;
1257 case k_Memory:
1258 OS << "Mem<";
1259 Mem.Base->print(OS);
1260 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001261 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001262 OS << ">";
1263 break;
1264 case k_PhysRegister:
1265 OS << "PhysReg<" << PhysReg.Num << ">";
1266 break;
1267 case k_RegisterIndex:
1268 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1269 break;
1270 case k_Token:
1271 OS << Tok.Data;
1272 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001273 case k_RegList:
1274 OS << "RegList< ";
1275 for (auto Reg : (*RegList.List))
1276 OS << Reg << " ";
1277 OS << ">";
1278 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001279 case k_RegPair:
1280 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1281 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001282 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001283 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001284}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001285} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001286
Jack Carter9e65aa32013-03-22 00:05:30 +00001287namespace llvm {
1288extern const MCInstrDesc MipsInsts[];
1289}
1290static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1291 return MipsInsts[Opcode];
1292}
1293
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001294static bool hasShortDelaySlot(unsigned Opcode) {
1295 switch (Opcode) {
1296 case Mips::JALS_MM:
1297 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001298 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001299 case Mips::BGEZALS_MM:
1300 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001301 return true;
1302 default:
1303 return false;
1304 }
1305}
1306
Jack Carter9e65aa32013-03-22 00:05:30 +00001307bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001308 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001309 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001310
Jack Carter9e65aa32013-03-22 00:05:30 +00001311 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001312
1313 if (MCID.isBranch() || MCID.isCall()) {
1314 const unsigned Opcode = Inst.getOpcode();
1315 MCOperand Offset;
1316
1317 switch (Opcode) {
1318 default:
1319 break;
Kai Nackee0245392015-01-27 19:11:28 +00001320 case Mips::BBIT0:
1321 case Mips::BBIT032:
1322 case Mips::BBIT1:
1323 case Mips::BBIT132:
1324 assert(hasCnMips() && "instruction only valid for octeon cpus");
1325 // Fall through
1326
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001327 case Mips::BEQ:
1328 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001329 case Mips::BEQ_MM:
1330 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001331 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001332 Offset = Inst.getOperand(2);
1333 if (!Offset.isImm())
1334 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001335 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001336 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001337 if (OffsetToAlignment(Offset.getImm(),
1338 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001339 return Error(IDLoc, "branch to misaligned address");
1340 break;
1341 case Mips::BGEZ:
1342 case Mips::BGTZ:
1343 case Mips::BLEZ:
1344 case Mips::BLTZ:
1345 case Mips::BGEZAL:
1346 case Mips::BLTZAL:
1347 case Mips::BC1F:
1348 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001349 case Mips::BGEZ_MM:
1350 case Mips::BGTZ_MM:
1351 case Mips::BLEZ_MM:
1352 case Mips::BLTZ_MM:
1353 case Mips::BGEZAL_MM:
1354 case Mips::BLTZAL_MM:
1355 case Mips::BC1F_MM:
1356 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001357 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001358 Offset = Inst.getOperand(1);
1359 if (!Offset.isImm())
1360 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001361 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001362 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001363 if (OffsetToAlignment(Offset.getImm(),
1364 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001365 return Error(IDLoc, "branch to misaligned address");
1366 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001367 case Mips::BEQZ16_MM:
1368 case Mips::BNEZ16_MM:
1369 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1370 Offset = Inst.getOperand(1);
1371 if (!Offset.isImm())
1372 break; // We'll deal with this situation later on when applying fixups.
1373 if (!isIntN(8, Offset.getImm()))
1374 return Error(IDLoc, "branch target out of range");
1375 if (OffsetToAlignment(Offset.getImm(), 2LL))
1376 return Error(IDLoc, "branch to misaligned address");
1377 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001378 }
1379 }
1380
Daniel Sandersa84989a2014-06-16 13:25:35 +00001381 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1382 // We still accept it but it is a normal nop.
1383 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1384 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1385 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1386 "nop instruction");
1387 }
1388
Kai Nackee0245392015-01-27 19:11:28 +00001389 if (hasCnMips()) {
1390 const unsigned Opcode = Inst.getOpcode();
1391 MCOperand Opnd;
1392 int Imm;
1393
1394 switch (Opcode) {
1395 default:
1396 break;
1397
1398 case Mips::BBIT0:
1399 case Mips::BBIT032:
1400 case Mips::BBIT1:
1401 case Mips::BBIT132:
1402 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1403 // The offset is handled above
1404 Opnd = Inst.getOperand(1);
1405 if (!Opnd.isImm())
1406 return Error(IDLoc, "expected immediate operand kind");
1407 Imm = Opnd.getImm();
1408 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1409 Opcode == Mips::BBIT1 ? 63 : 31))
1410 return Error(IDLoc, "immediate operand value out of range");
1411 if (Imm > 31) {
1412 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1413 : Mips::BBIT132);
1414 Inst.getOperand(1).setImm(Imm - 32);
1415 }
1416 break;
1417
1418 case Mips::CINS:
1419 case Mips::CINS32:
1420 case Mips::EXTS:
1421 case Mips::EXTS32:
1422 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1423 // Check length
1424 Opnd = Inst.getOperand(3);
1425 if (!Opnd.isImm())
1426 return Error(IDLoc, "expected immediate operand kind");
1427 Imm = Opnd.getImm();
1428 if (Imm < 0 || Imm > 31)
1429 return Error(IDLoc, "immediate operand value out of range");
1430 // Check position
1431 Opnd = Inst.getOperand(2);
1432 if (!Opnd.isImm())
1433 return Error(IDLoc, "expected immediate operand kind");
1434 Imm = Opnd.getImm();
1435 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1436 Opcode == Mips::EXTS ? 63 : 31))
1437 return Error(IDLoc, "immediate operand value out of range");
1438 if (Imm > 31) {
1439 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1440 Inst.getOperand(2).setImm(Imm - 32);
1441 }
1442 break;
1443
1444 case Mips::SEQi:
1445 case Mips::SNEi:
1446 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1447 Opnd = Inst.getOperand(2);
1448 if (!Opnd.isImm())
1449 return Error(IDLoc, "expected immediate operand kind");
1450 Imm = Opnd.getImm();
1451 if (!isInt<10>(Imm))
1452 return Error(IDLoc, "immediate operand value out of range");
1453 break;
1454 }
1455 }
1456
Jack Carter9e65aa32013-03-22 00:05:30 +00001457 if (MCID.mayLoad() || MCID.mayStore()) {
1458 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001459 // reference or immediate we may have to expand instructions.
1460 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001461 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001462 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1463 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001464 MCOperand &Op = Inst.getOperand(i);
1465 if (Op.isImm()) {
1466 int MemOffset = Op.getImm();
1467 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001468 // Offset can't exceed 16bit value.
1469 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001470 return false;
1471 }
1472 } else if (Op.isExpr()) {
1473 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001474 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001475 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001476 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001477 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001478 // Expand symbol.
1479 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001480 return false;
1481 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001482 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001483 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001484 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001485 }
1486 }
1487 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001488 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001489 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001490
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001491 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001492 if (MCID.mayLoad()) {
1493 // Try to create 16-bit GP relative load instruction.
1494 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1495 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1496 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1497 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1498 MCOperand &Op = Inst.getOperand(i);
1499 if (Op.isImm()) {
1500 int MemOffset = Op.getImm();
1501 MCOperand &DstReg = Inst.getOperand(0);
1502 MCOperand &BaseReg = Inst.getOperand(1);
1503 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1504 getContext().getRegisterInfo()->getRegClass(
1505 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1506 BaseReg.getReg() == Mips::GP) {
1507 MCInst TmpInst;
1508 TmpInst.setLoc(IDLoc);
1509 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001510 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1511 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1512 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001513 Instructions.push_back(TmpInst);
1514 return false;
1515 }
1516 }
1517 }
1518 } // for
1519 } // if load
1520
1521 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1522
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001523 MCOperand Opnd;
1524 int Imm;
1525
1526 switch (Inst.getOpcode()) {
1527 default:
1528 break;
1529 case Mips::ADDIUS5_MM:
1530 Opnd = Inst.getOperand(2);
1531 if (!Opnd.isImm())
1532 return Error(IDLoc, "expected immediate operand kind");
1533 Imm = Opnd.getImm();
1534 if (Imm < -8 || Imm > 7)
1535 return Error(IDLoc, "immediate operand value out of range");
1536 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001537 case Mips::ADDIUSP_MM:
1538 Opnd = Inst.getOperand(0);
1539 if (!Opnd.isImm())
1540 return Error(IDLoc, "expected immediate operand kind");
1541 Imm = Opnd.getImm();
1542 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1543 Imm % 4 != 0)
1544 return Error(IDLoc, "immediate operand value out of range");
1545 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001546 case Mips::SLL16_MM:
1547 case Mips::SRL16_MM:
1548 Opnd = Inst.getOperand(2);
1549 if (!Opnd.isImm())
1550 return Error(IDLoc, "expected immediate operand kind");
1551 Imm = Opnd.getImm();
1552 if (Imm < 1 || Imm > 8)
1553 return Error(IDLoc, "immediate operand value out of range");
1554 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001555 case Mips::LI16_MM:
1556 Opnd = Inst.getOperand(1);
1557 if (!Opnd.isImm())
1558 return Error(IDLoc, "expected immediate operand kind");
1559 Imm = Opnd.getImm();
1560 if (Imm < -1 || Imm > 126)
1561 return Error(IDLoc, "immediate operand value out of range");
1562 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001563 case Mips::ADDIUR2_MM:
1564 Opnd = Inst.getOperand(2);
1565 if (!Opnd.isImm())
1566 return Error(IDLoc, "expected immediate operand kind");
1567 Imm = Opnd.getImm();
1568 if (!(Imm == 1 || Imm == -1 ||
1569 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1570 return Error(IDLoc, "immediate operand value out of range");
1571 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001572 case Mips::ADDIUR1SP_MM:
1573 Opnd = Inst.getOperand(1);
1574 if (!Opnd.isImm())
1575 return Error(IDLoc, "expected immediate operand kind");
1576 Imm = Opnd.getImm();
1577 if (OffsetToAlignment(Imm, 4LL))
1578 return Error(IDLoc, "misaligned immediate operand value");
1579 if (Imm < 0 || Imm > 255)
1580 return Error(IDLoc, "immediate operand value out of range");
1581 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001582 case Mips::ANDI16_MM:
1583 Opnd = Inst.getOperand(2);
1584 if (!Opnd.isImm())
1585 return Error(IDLoc, "expected immediate operand kind");
1586 Imm = Opnd.getImm();
1587 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1588 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1589 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1590 return Error(IDLoc, "immediate operand value out of range");
1591 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001592 case Mips::LBU16_MM:
1593 Opnd = Inst.getOperand(2);
1594 if (!Opnd.isImm())
1595 return Error(IDLoc, "expected immediate operand kind");
1596 Imm = Opnd.getImm();
1597 if (Imm < -1 || Imm > 14)
1598 return Error(IDLoc, "immediate operand value out of range");
1599 break;
1600 case Mips::SB16_MM:
1601 Opnd = Inst.getOperand(2);
1602 if (!Opnd.isImm())
1603 return Error(IDLoc, "expected immediate operand kind");
1604 Imm = Opnd.getImm();
1605 if (Imm < 0 || Imm > 15)
1606 return Error(IDLoc, "immediate operand value out of range");
1607 break;
1608 case Mips::LHU16_MM:
1609 case Mips::SH16_MM:
1610 Opnd = Inst.getOperand(2);
1611 if (!Opnd.isImm())
1612 return Error(IDLoc, "expected immediate operand kind");
1613 Imm = Opnd.getImm();
1614 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1615 return Error(IDLoc, "immediate operand value out of range");
1616 break;
1617 case Mips::LW16_MM:
1618 case Mips::SW16_MM:
1619 Opnd = Inst.getOperand(2);
1620 if (!Opnd.isImm())
1621 return Error(IDLoc, "expected immediate operand kind");
1622 Imm = Opnd.getImm();
1623 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1624 return Error(IDLoc, "immediate operand value out of range");
1625 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001626 case Mips::CACHE:
1627 case Mips::PREF:
1628 Opnd = Inst.getOperand(2);
1629 if (!Opnd.isImm())
1630 return Error(IDLoc, "expected immediate operand kind");
1631 Imm = Opnd.getImm();
1632 if (!isUInt<5>(Imm))
1633 return Error(IDLoc, "immediate operand value out of range");
1634 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001635 case Mips::ADDIUPC_MM:
1636 MCOperand Opnd = Inst.getOperand(1);
1637 if (!Opnd.isImm())
1638 return Error(IDLoc, "expected immediate operand kind");
1639 int Imm = Opnd.getImm();
1640 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1641 return Error(IDLoc, "immediate operand value out of range");
1642 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001643 }
1644 }
1645
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001646 if (needsExpansion(Inst)) {
1647 if (expandInstruction(Inst, IDLoc, Instructions))
1648 return true;
1649 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001650 Instructions.push_back(Inst);
1651
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001652 // If this instruction has a delay slot and .set reorder is active,
1653 // emit a NOP after it.
1654 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1655 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1656
Jack Carter9e65aa32013-03-22 00:05:30 +00001657 return false;
1658}
1659
Jack Carter30a59822012-10-04 04:03:53 +00001660bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1661
Jack Carterd0bd6422013-04-18 00:41:53 +00001662 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001663 case Mips::LoadImm32:
1664 case Mips::LoadImm64:
1665 case Mips::LoadAddrImm32:
1666 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001667 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001668 case Mips::LWM_MM:
1669 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001670 case Mips::JalOneReg:
1671 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001672 case Mips::BneImm:
1673 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001674 case Mips::BLT:
1675 case Mips::BLE:
1676 case Mips::BGE:
1677 case Mips::BGT:
1678 case Mips::BLTU:
1679 case Mips::BLEU:
1680 case Mips::BGEU:
1681 case Mips::BGTU:
Toma Tabacud88d79c2015-06-23 14:39:42 +00001682 case Mips::Ulhu:
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001683 case Mips::Ulw:
Jack Carterd0bd6422013-04-18 00:41:53 +00001684 return true;
1685 default:
1686 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001687 }
1688}
Jack Carter92995f12012-10-06 00:53:28 +00001689
Matheus Almeida3813d572014-06-19 14:39:14 +00001690bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001691 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001692 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001693 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001694 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001695 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001696 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001697 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001698 case Mips::LoadAddrImm32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001699 return expandLoadAddressImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001700 case Mips::LoadAddrReg32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001701 return expandLoadAddressReg(Inst, true, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001702 case Mips::B_MM_Pseudo:
1703 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001704 case Mips::SWM_MM:
1705 case Mips::LWM_MM:
1706 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001707 case Mips::JalOneReg:
1708 case Mips::JalTwoReg:
1709 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001710 case Mips::BneImm:
1711 case Mips::BeqImm:
1712 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00001713 case Mips::BLT:
1714 case Mips::BLE:
1715 case Mips::BGE:
1716 case Mips::BGT:
1717 case Mips::BLTU:
1718 case Mips::BLEU:
1719 case Mips::BGEU:
1720 case Mips::BGTU:
1721 return expandCondBranches(Inst, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00001722 case Mips::Ulhu:
1723 return expandUlhu(Inst, IDLoc, Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001724 case Mips::Ulw:
1725 return expandUlw(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001726 }
Jack Carter30a59822012-10-04 04:03:53 +00001727}
Jack Carter92995f12012-10-06 00:53:28 +00001728
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001729namespace {
Daniel Sanders03f9c012015-07-14 12:24:22 +00001730void emitRX(unsigned Opcode, unsigned DstReg, MCOperand Imm, SMLoc IDLoc,
1731 SmallVectorImpl<MCInst> &Instructions) {
1732 MCInst tmpInst;
1733 tmpInst.setOpcode(Opcode);
1734 tmpInst.addOperand(MCOperand::createReg(DstReg));
1735 tmpInst.addOperand(Imm);
1736 tmpInst.setLoc(IDLoc);
1737 Instructions.push_back(tmpInst);
1738}
1739
1740void emitRI(unsigned Opcode, unsigned DstReg, int16_t Imm, SMLoc IDLoc,
1741 SmallVectorImpl<MCInst> &Instructions) {
1742 emitRX(Opcode, DstReg, MCOperand::createImm(Imm), IDLoc, Instructions);
1743}
1744
1745
1746void emitRRX(unsigned Opcode, unsigned DstReg, unsigned SrcReg, MCOperand Imm,
1747 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1748 MCInst tmpInst;
1749 tmpInst.setOpcode(Opcode);
1750 tmpInst.addOperand(MCOperand::createReg(DstReg));
1751 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1752 tmpInst.addOperand(Imm);
1753 tmpInst.setLoc(IDLoc);
1754 Instructions.push_back(tmpInst);
1755}
1756
1757void emitRRR(unsigned Opcode, unsigned DstReg, unsigned SrcReg,
1758 unsigned SrcReg2, SMLoc IDLoc,
1759 SmallVectorImpl<MCInst> &Instructions) {
1760 emitRRX(Opcode, DstReg, SrcReg, MCOperand::createReg(SrcReg2), IDLoc,
1761 Instructions);
1762}
1763
1764void emitRRI(unsigned Opcode, unsigned DstReg, unsigned SrcReg, int16_t Imm,
1765 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1766 emitRRX(Opcode, DstReg, SrcReg, MCOperand::createImm(Imm), IDLoc,
1767 Instructions);
1768}
1769
Toma Tabacua2861db2015-05-01 10:26:47 +00001770template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001771void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001772 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00001773 if (ShiftAmount >= 32)
1774 emitRRI(Mips::DSLL32, RegNo, RegNo, ShiftAmount - 32, IDLoc, Instructions);
1775 else if (ShiftAmount > 0)
1776 emitRRI(Mips::DSLL, RegNo, RegNo, ShiftAmount, IDLoc, Instructions);
1777
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001778 // There's no need for an ORi if the immediate is 0.
1779 if (Operand.isImm() && Operand.getImm() == 0)
1780 return;
1781
Daniel Sanders03f9c012015-07-14 12:24:22 +00001782 emitRRX(Mips::ORi, RegNo, RegNo, Operand, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001783}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001784
Toma Tabacua2861db2015-05-01 10:26:47 +00001785template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001786void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001787 SmallVectorImpl<MCInst> &Instructions) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001788 createLShiftOri<ShiftAmount>(MCOperand::createImm(Value), RegNo, IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001789 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001790}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001791}
1792
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001793bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1794 SmallVectorImpl<MCInst> &Instructions) {
1795 // Create a JALR instruction which is going to replace the pseudo-JAL.
1796 MCInst JalrInst;
1797 JalrInst.setLoc(IDLoc);
1798 const MCOperand FirstRegOp = Inst.getOperand(0);
1799 const unsigned Opcode = Inst.getOpcode();
1800
1801 if (Opcode == Mips::JalOneReg) {
1802 // jal $rs => jalr $rs
1803 if (inMicroMipsMode()) {
1804 JalrInst.setOpcode(Mips::JALR16_MM);
1805 JalrInst.addOperand(FirstRegOp);
1806 } else {
1807 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00001808 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001809 JalrInst.addOperand(FirstRegOp);
1810 }
1811 } else if (Opcode == Mips::JalTwoReg) {
1812 // jal $rd, $rs => jalr $rd, $rs
1813 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1814 JalrInst.addOperand(FirstRegOp);
1815 const MCOperand SecondRegOp = Inst.getOperand(1);
1816 JalrInst.addOperand(SecondRegOp);
1817 }
1818 Instructions.push_back(JalrInst);
1819
1820 // If .set reorder is active, emit a NOP after it.
1821 if (AssemblerOptions.back()->isReorder()) {
1822 // This is a 32-bit NOP because these 2 pseudo-instructions
1823 // do not have a short delay slot.
1824 MCInst NopInst;
1825 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001826 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1827 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1828 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001829 Instructions.push_back(NopInst);
1830 }
1831
1832 return false;
1833}
1834
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001835bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
1836 unsigned SrcReg, bool Is32BitImm, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001837 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001838 if (!Is32BitImm && !isGP64bit()) {
1839 Error(IDLoc, "instruction requires a 64-bit architecture");
1840 return true;
1841 }
1842
Daniel Sanders03f9c012015-07-14 12:24:22 +00001843 if (Is32BitImm) {
1844 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
1845 // Sign extend up to 64-bit so that the predicates match the hardware
1846 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
1847 // true.
1848 ImmValue = SignExtend64<32>(ImmValue);
1849 } else {
1850 Error(IDLoc, "instruction requires a 32-bit immediate");
1851 return true;
1852 }
1853 }
1854
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001855 bool UseSrcReg = false;
1856 if (SrcReg != Mips::NoRegister)
1857 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00001858
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001859 unsigned TmpReg = DstReg;
1860 if (UseSrcReg && (DstReg == SrcReg)) {
1861 // At this point we need AT to perform the expansions and we exit if it is
1862 // not available.
1863 unsigned ATReg = getATReg(IDLoc);
1864 if (!ATReg)
1865 return true;
1866 TmpReg = ATReg;
1867 }
1868
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001869 // FIXME: gas has a special case for values that are 000...1111, which
1870 // becomes a li -1 and then a dsrl
Daniel Sanders03f9c012015-07-14 12:24:22 +00001871 if (isInt<16>(ImmValue)) {
Jack Carter30a59822012-10-04 04:03:53 +00001872 // li d,j => addiu d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001873 if (!UseSrcReg)
1874 SrcReg = Mips::ZERO;
Daniel Sanders03f9c012015-07-14 12:24:22 +00001875 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
1876 } else if (isUInt<16>(ImmValue)) {
1877 // li d,j => ori d,$zero,j
1878 unsigned TmpReg = DstReg;
1879 if (SrcReg == DstReg) {
1880 unsigned ATReg = getATReg(IDLoc);
1881 if (!ATReg)
1882 return true;
1883 TmpReg = ATReg;
1884 }
1885
1886 emitRRI(Mips::ORi, TmpReg, Mips::ZERO, ImmValue, IDLoc, Instructions);
1887 if (UseSrcReg)
1888 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
Toma Tabacua3d056f2015-05-15 09:42:11 +00001889 } else if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00001890 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00001891
Toma Tabacuae47f932015-04-10 13:28:16 +00001892 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001893 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001894 // ori d,d,lo16(j)
Toma Tabacu79588102015-04-29 10:19:56 +00001895 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1896 uint16_t Bits15To0 = ImmValue & 0xffff;
1897
Toma Tabacua3d056f2015-05-15 09:42:11 +00001898 if (!Is32BitImm && !isInt<32>(ImmValue)) {
1899 // For DLI, expand to an ORi instead of a LUi to avoid sign-extending the
1900 // upper 32 bits.
Daniel Sanders03f9c012015-07-14 12:24:22 +00001901 emitRRI(Mips::ORi, TmpReg, Mips::ZERO, Bits31To16, IDLoc, Instructions);
1902 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
1903 } else
1904 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001905 createLShiftOri<0>(Bits15To0, TmpReg, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001906
1907 if (UseSrcReg)
Toma Tabacu0b3e9782015-06-23 14:00:54 +00001908 createAddu(DstReg, TmpReg, SrcReg, !Is32BitImm, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001909
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001910 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Toma Tabacu81496c12015-05-20 08:54:45 +00001911 warnIfNoMacro(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001912
1913 // <------- lo32 ------>
1914 // <------- hi32 ------>
1915 // <- hi16 -> <- lo16 ->
1916 // _________________________________
1917 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001918 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001919 // |__________|__________|__________|
1920 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001921 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001922 // li d,j => lui d,hi16(j)
1923 // ori d,d,hi16(lo32(j))
1924 // dsll d,d,16
1925 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001926 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1927 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1928 uint16_t Bits15To0 = ImmValue & 0xffff;
1929
Daniel Sanders03f9c012015-07-14 12:24:22 +00001930 emitRI(Mips::LUi, TmpReg, Bits47To32, IDLoc, Instructions);
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001931 createLShiftOri<0>(Bits31To16, TmpReg, IDLoc, Instructions);
1932 createLShiftOri<16>(Bits15To0, TmpReg, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001933
1934 if (UseSrcReg)
Toma Tabacu0b3e9782015-06-23 14:00:54 +00001935 createAddu(DstReg, TmpReg, SrcReg, !Is32BitImm, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001936
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001937 } else {
Toma Tabacu81496c12015-05-20 08:54:45 +00001938 warnIfNoMacro(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001939
1940 // <------- hi32 ------> <------- lo32 ------>
1941 // <- hi16 -> <- lo16 ->
1942 // ___________________________________________
1943 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001944 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001945 // |__________|__________|__________|__________|
1946 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001947 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001948 // li d,j => lui d,hi16(j)
1949 // ori d,d,lo16(hi32(j))
1950 // dsll d,d,16
1951 // ori d,d,hi16(lo32(j))
1952 // dsll d,d,16
1953 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001954 uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff;
1955 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1956 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1957 uint16_t Bits15To0 = ImmValue & 0xffff;
1958
Daniel Sanders03f9c012015-07-14 12:24:22 +00001959 emitRI(Mips::LUi, TmpReg, Bits63To48, IDLoc, Instructions);
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001960 createLShiftOri<0>(Bits47To32, TmpReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001961
1962 // When Bits31To16 is 0, do a left shift of 32 bits instead of doing
1963 // two left shifts of 16 bits.
1964 if (Bits31To16 == 0) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001965 createLShiftOri<32>(Bits15To0, TmpReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001966 } else {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001967 createLShiftOri<16>(Bits31To16, TmpReg, IDLoc, Instructions);
1968 createLShiftOri<16>(Bits15To0, TmpReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001969 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001970
1971 if (UseSrcReg)
Toma Tabacu0b3e9782015-06-23 14:00:54 +00001972 createAddu(DstReg, TmpReg, SrcReg, !Is32BitImm, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001973 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001974 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001975}
Jack Carter92995f12012-10-06 00:53:28 +00001976
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001977bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
1978 SmallVectorImpl<MCInst> &Instructions) {
1979 const MCOperand &ImmOp = Inst.getOperand(1);
1980 assert(ImmOp.isImm() && "expected immediate operand kind");
1981 const MCOperand &DstRegOp = Inst.getOperand(0);
1982 assert(DstRegOp.isReg() && "expected register operand kind");
1983
1984 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1985 Is32BitImm, IDLoc, Instructions))
1986 return true;
1987
1988 return false;
1989}
1990
Matheus Almeida3813d572014-06-19 14:39:14 +00001991bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001992MipsAsmParser::expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001993 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001994 const MCOperand &DstRegOp = Inst.getOperand(0);
1995 assert(DstRegOp.isReg() && "expected register operand kind");
1996
Toma Tabacuf712ede2015-06-17 14:31:51 +00001997 const MCOperand &SrcRegOp = Inst.getOperand(1);
1998 assert(SrcRegOp.isReg() && "expected register operand kind");
1999
Jack Carter543fdf82012-10-09 23:29:45 +00002000 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00002001 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
2002 "expected immediate operand kind");
2003 if (!ImmOp.isImm()) {
Toma Tabacuf712ede2015-06-17 14:31:51 +00002004 if (loadAndAddSymbolAddress(ImmOp.getExpr(), DstRegOp.getReg(),
2005 SrcRegOp.getReg(), Is32BitImm, IDLoc,
2006 Instructions))
Toma Tabacu674825c2015-06-16 12:16:24 +00002007 return true;
2008
Toma Tabacu0d64b202014-08-14 10:29:17 +00002009 return false;
2010 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002011
2012 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), SrcRegOp.getReg(),
2013 Is32BitImm, IDLoc, Instructions))
2014 return true;
2015
Matheus Almeida3813d572014-06-19 14:39:14 +00002016 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00002017}
2018
Matheus Almeida3813d572014-06-19 14:39:14 +00002019bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002020MipsAsmParser::expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002021 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00002022 const MCOperand &DstRegOp = Inst.getOperand(0);
2023 assert(DstRegOp.isReg() && "expected register operand kind");
2024
Jack Carter543fdf82012-10-09 23:29:45 +00002025 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00002026 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
2027 "expected immediate operand kind");
2028 if (!ImmOp.isImm()) {
Toma Tabacuf712ede2015-06-17 14:31:51 +00002029 if (loadAndAddSymbolAddress(ImmOp.getExpr(), DstRegOp.getReg(),
2030 Mips::NoRegister, Is32BitImm, IDLoc,
2031 Instructions))
Toma Tabacu674825c2015-06-16 12:16:24 +00002032 return true;
2033
Toma Tabacu0d64b202014-08-14 10:29:17 +00002034 return false;
2035 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002036
2037 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
2038 Is32BitImm, IDLoc, Instructions))
2039 return true;
2040
Matheus Almeida3813d572014-06-19 14:39:14 +00002041 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00002042}
2043
Toma Tabacuf712ede2015-06-17 14:31:51 +00002044bool MipsAsmParser::loadAndAddSymbolAddress(
2045 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2046 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002047 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002048
Toma Tabacuec1de822015-05-14 10:53:40 +00002049 if (Is32BitSym && isABI_N64())
2050 Warning(IDLoc, "instruction loads the 32-bit address of a 64-bit symbol");
2051
Toma Tabacu0d64b202014-08-14 10:29:17 +00002052 MCInst tmpInst;
Toma Tabacu674825c2015-06-16 12:16:24 +00002053 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymExpr);
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002054 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
2055 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
2056 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
2057 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
2058
Toma Tabacufb9d1252015-06-22 12:08:39 +00002059 bool UseSrcReg = SrcReg != Mips::NoRegister;
2060
2061 unsigned TmpReg = DstReg;
2062 if (UseSrcReg && (DstReg == SrcReg)) {
2063 // At this point we need AT to perform the expansions and we exit if it is
2064 // not available.
2065 unsigned ATReg = getATReg(IDLoc);
2066 if (!ATReg)
2067 return true;
2068 TmpReg = ATReg;
2069 }
2070
Toma Tabacuec1de822015-05-14 10:53:40 +00002071 if (!Is32BitSym) {
Toma Tabacu0d64b202014-08-14 10:29:17 +00002072 // If it's a 64-bit architecture, expand to:
2073 // la d,sym => lui d,highest(sym)
2074 // ori d,d,higher(sym)
2075 // dsll d,d,16
2076 // ori d,d,hi16(sym)
2077 // dsll d,d,16
2078 // ori d,d,lo16(sym)
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002079 const MCSymbolRefExpr *HighestExpr = MCSymbolRefExpr::create(
2080 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
2081 const MCSymbolRefExpr *HigherExpr = MCSymbolRefExpr::create(
2082 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
Toma Tabacu0d64b202014-08-14 10:29:17 +00002083
2084 tmpInst.setOpcode(Mips::LUi);
Toma Tabacufb9d1252015-06-22 12:08:39 +00002085 tmpInst.addOperand(MCOperand::createReg(TmpReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00002086 tmpInst.addOperand(MCOperand::createExpr(HighestExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00002087 Instructions.push_back(tmpInst);
2088
Toma Tabacufb9d1252015-06-22 12:08:39 +00002089 createLShiftOri<0>(MCOperand::createExpr(HigherExpr), TmpReg, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00002090 Instructions);
Toma Tabacufb9d1252015-06-22 12:08:39 +00002091 createLShiftOri<16>(MCOperand::createExpr(HiExpr), TmpReg, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00002092 Instructions);
Toma Tabacufb9d1252015-06-22 12:08:39 +00002093 createLShiftOri<16>(MCOperand::createExpr(LoExpr), TmpReg, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00002094 Instructions);
2095 } else {
2096 // Otherwise, expand to:
2097 // la d,sym => lui d,hi16(sym)
2098 // ori d,d,lo16(sym)
2099 tmpInst.setOpcode(Mips::LUi);
Toma Tabacufb9d1252015-06-22 12:08:39 +00002100 tmpInst.addOperand(MCOperand::createReg(TmpReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00002101 tmpInst.addOperand(MCOperand::createExpr(HiExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00002102 Instructions.push_back(tmpInst);
2103
Daniel Sanders03f9c012015-07-14 12:24:22 +00002104 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), SMLoc(),
2105 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00002106 }
Toma Tabacuf712ede2015-06-17 14:31:51 +00002107
Toma Tabacufb9d1252015-06-22 12:08:39 +00002108 if (UseSrcReg)
Toma Tabacu0b3e9782015-06-23 14:00:54 +00002109 createAddu(DstReg, TmpReg, SrcReg, !Is32BitSym, Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002110
Toma Tabacu674825c2015-06-16 12:16:24 +00002111 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002112}
2113
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002114bool MipsAsmParser::expandUncondBranchMMPseudo(
2115 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002116 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2117 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002118
2119 MCOperand Offset = Inst.getOperand(0);
2120 if (Offset.isExpr()) {
2121 Inst.clear();
2122 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002123 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2124 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2125 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002126 } else {
2127 assert(Offset.isImm() && "expected immediate operand kind");
2128 if (isIntN(11, Offset.getImm())) {
2129 // If offset fits into 11 bits then this instruction becomes microMIPS
2130 // 16-bit unconditional branch instruction.
2131 Inst.setOpcode(Mips::B16_MM);
2132 } else {
2133 if (!isIntN(17, Offset.getImm()))
2134 Error(IDLoc, "branch target out of range");
2135 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2136 Error(IDLoc, "branch to misaligned address");
2137 Inst.clear();
2138 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002139 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2140 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2141 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002142 }
2143 }
2144 Instructions.push_back(Inst);
2145
Toma Tabacu234482a2015-03-16 12:03:39 +00002146 // If .set reorder is active, emit a NOP after the branch instruction.
2147 if (AssemblerOptions.back()->isReorder())
2148 createNop(true, IDLoc, Instructions);
2149
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002150 return false;
2151}
2152
Toma Tabacue1e460d2015-06-11 10:36:10 +00002153bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2154 SmallVectorImpl<MCInst> &Instructions) {
2155 const MCOperand &DstRegOp = Inst.getOperand(0);
2156 assert(DstRegOp.isReg() && "expected register operand kind");
2157
2158 const MCOperand &ImmOp = Inst.getOperand(1);
2159 assert(ImmOp.isImm() && "expected immediate operand kind");
2160
2161 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2162 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2163
2164 unsigned OpCode = 0;
2165 switch(Inst.getOpcode()) {
2166 case Mips::BneImm:
2167 OpCode = Mips::BNE;
2168 break;
2169 case Mips::BeqImm:
2170 OpCode = Mips::BEQ;
2171 break;
2172 default:
2173 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2174 break;
2175 }
2176
2177 int64_t ImmValue = ImmOp.getImm();
2178 if (ImmValue == 0) {
2179 MCInst BranchInst;
2180 BranchInst.setOpcode(OpCode);
2181 BranchInst.addOperand(DstRegOp);
2182 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2183 BranchInst.addOperand(MemOffsetOp);
2184 Instructions.push_back(BranchInst);
2185 } else {
2186 warnIfNoMacro(IDLoc);
2187
2188 unsigned ATReg = getATReg(IDLoc);
2189 if (!ATReg)
2190 return true;
2191
2192 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), IDLoc,
2193 Instructions))
2194 return true;
2195
2196 MCInst BranchInst;
2197 BranchInst.setOpcode(OpCode);
2198 BranchInst.addOperand(DstRegOp);
2199 BranchInst.addOperand(MCOperand::createReg(ATReg));
2200 BranchInst.addOperand(MemOffsetOp);
2201 Instructions.push_back(BranchInst);
2202 }
2203 return false;
2204}
2205
Jack Carter9e65aa32013-03-22 00:05:30 +00002206void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002207 SmallVectorImpl<MCInst> &Instructions,
2208 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002209 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002210 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002211 const MCExpr *ExprOffset;
2212 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002213 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002214 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2215 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002216 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002217 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2218 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002219 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002220 if (isImmOpnd) {
2221 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2222 ImmOffset = Inst.getOperand(2).getImm();
2223 LoOffset = ImmOffset & 0x0000ffff;
2224 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002225 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002226 if (LoOffset & 0x8000)
2227 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002228 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002229 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002230 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002231 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002232 // These are some of the types of expansions we perform here:
2233 // 1) lw $8, sym => lui $8, %hi(sym)
2234 // lw $8, %lo(sym)($8)
2235 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2236 // add $8, $8, $9
2237 // lw $8, %lo(offset)($9)
2238 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2239 // add $at, $at, $8
2240 // lw $8, %lo(offset)($at)
2241 // 4) sw $8, sym => lui $at, %hi(sym)
2242 // sw $8, %lo(sym)($at)
2243 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2244 // add $at, $at, $8
2245 // sw $8, %lo(offset)($at)
2246 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2247 // ldc1 $f0, %lo(sym)($at)
2248 //
2249 // For load instructions we can use the destination register as a temporary
2250 // if base and dst are different (examples 1 and 2) and if the base register
2251 // is general purpose otherwise we must use $at (example 6) and error if it's
2252 // not available. For stores we must use $at (examples 4 and 5) because we
2253 // must not clobber the source register setting up the offset.
2254 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2255 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2256 unsigned RegClassIDOp0 =
2257 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2258 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2259 (RegClassIDOp0 == Mips::GPR64RegClassID);
2260 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002261 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002262 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002263 // At this point we need AT to perform the expansions and we exit if it is
2264 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002265 TmpRegNum = getATReg(IDLoc);
2266 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002267 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002268 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002269
Jack Carter9e65aa32013-03-22 00:05:30 +00002270 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002271 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002272 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002273 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002274 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002275 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
2276 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002277 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002278 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002279 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002280 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002281 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002282 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002283 if (BaseRegNum != Mips::ZERO) {
2284 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002285 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2286 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2287 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002288 Instructions.push_back(TempInst);
2289 TempInst.clear();
2290 }
Alp Tokercb402912014-01-24 17:20:08 +00002291 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002292 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002293 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002294 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2295 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002296 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002297 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002298 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002299 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
2300 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002301 }
2302 Instructions.push_back(TempInst);
2303 TempInst.clear();
2304}
2305
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002306bool
2307MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2308 SmallVectorImpl<MCInst> &Instructions) {
2309 unsigned OpNum = Inst.getNumOperands();
2310 unsigned Opcode = Inst.getOpcode();
2311 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2312
2313 assert (Inst.getOperand(OpNum - 1).isImm() &&
2314 Inst.getOperand(OpNum - 2).isReg() &&
2315 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2316
2317 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2318 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2319 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2320 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2321 // It can be implemented as SWM16 or LWM16 instruction.
2322 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2323
2324 Inst.setOpcode(NewOpcode);
2325 Instructions.push_back(Inst);
2326 return false;
2327}
2328
Toma Tabacu1a108322015-06-17 13:20:24 +00002329bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2330 SmallVectorImpl<MCInst> &Instructions) {
2331 unsigned PseudoOpcode = Inst.getOpcode();
2332 unsigned SrcReg = Inst.getOperand(0).getReg();
2333 unsigned TrgReg = Inst.getOperand(1).getReg();
2334 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2335
2336 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
2337 bool ReverseOrderSLT, IsUnsigned, AcceptsEquality;
2338
2339 switch (PseudoOpcode) {
2340 case Mips::BLT:
2341 case Mips::BLTU:
2342 AcceptsEquality = false;
2343 ReverseOrderSLT = false;
2344 IsUnsigned = (PseudoOpcode == Mips::BLTU);
2345 ZeroSrcOpcode = Mips::BGTZ;
2346 ZeroTrgOpcode = Mips::BLTZ;
2347 break;
2348 case Mips::BLE:
2349 case Mips::BLEU:
2350 AcceptsEquality = true;
2351 ReverseOrderSLT = true;
2352 IsUnsigned = (PseudoOpcode == Mips::BLEU);
2353 ZeroSrcOpcode = Mips::BGEZ;
2354 ZeroTrgOpcode = Mips::BLEZ;
2355 break;
2356 case Mips::BGE:
2357 case Mips::BGEU:
2358 AcceptsEquality = true;
2359 ReverseOrderSLT = false;
2360 IsUnsigned = (PseudoOpcode == Mips::BGEU);
2361 ZeroSrcOpcode = Mips::BLEZ;
2362 ZeroTrgOpcode = Mips::BGEZ;
2363 break;
2364 case Mips::BGT:
2365 case Mips::BGTU:
2366 AcceptsEquality = false;
2367 ReverseOrderSLT = true;
2368 IsUnsigned = (PseudoOpcode == Mips::BGTU);
2369 ZeroSrcOpcode = Mips::BLTZ;
2370 ZeroTrgOpcode = Mips::BGTZ;
2371 break;
2372 default:
2373 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2374 }
2375
2376 MCInst BranchInst;
2377 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2378 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2379 if (IsSrcRegZero && IsTrgRegZero) {
2380 // FIXME: All of these Opcode-specific if's are needed for compatibility
2381 // with GAS' behaviour. However, they may not generate the most efficient
2382 // code in some circumstances.
2383 if (PseudoOpcode == Mips::BLT) {
2384 BranchInst.setOpcode(Mips::BLTZ);
2385 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2386 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2387 Instructions.push_back(BranchInst);
2388 return false;
2389 }
2390 if (PseudoOpcode == Mips::BLE) {
2391 BranchInst.setOpcode(Mips::BLEZ);
2392 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2393 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2394 Instructions.push_back(BranchInst);
2395 Warning(IDLoc, "branch is always taken");
2396 return false;
2397 }
2398 if (PseudoOpcode == Mips::BGE) {
2399 BranchInst.setOpcode(Mips::BGEZ);
2400 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2401 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2402 Instructions.push_back(BranchInst);
2403 Warning(IDLoc, "branch is always taken");
2404 return false;
2405 }
2406 if (PseudoOpcode == Mips::BGT) {
2407 BranchInst.setOpcode(Mips::BGTZ);
2408 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2409 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2410 Instructions.push_back(BranchInst);
2411 return false;
2412 }
2413 if (PseudoOpcode == Mips::BGTU) {
2414 BranchInst.setOpcode(Mips::BNE);
2415 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2416 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2417 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2418 Instructions.push_back(BranchInst);
2419 return false;
2420 }
2421 if (AcceptsEquality) {
2422 // If both registers are $0 and the pseudo-branch accepts equality, it
2423 // will always be taken, so we emit an unconditional branch.
2424 BranchInst.setOpcode(Mips::BEQ);
2425 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2426 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2427 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2428 Instructions.push_back(BranchInst);
2429 Warning(IDLoc, "branch is always taken");
2430 return false;
2431 }
2432 // If both registers are $0 and the pseudo-branch does not accept
2433 // equality, it will never be taken, so we don't have to emit anything.
2434 return false;
2435 }
2436 if (IsSrcRegZero || IsTrgRegZero) {
2437 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2438 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2439 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2440 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2441 // the pseudo-branch will never be taken, so we don't emit anything.
2442 // This only applies to unsigned pseudo-branches.
2443 return false;
2444 }
2445 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2446 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2447 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2448 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2449 // the pseudo-branch will always be taken, so we emit an unconditional
2450 // branch.
2451 // This only applies to unsigned pseudo-branches.
2452 BranchInst.setOpcode(Mips::BEQ);
2453 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2454 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2455 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2456 Instructions.push_back(BranchInst);
2457 Warning(IDLoc, "branch is always taken");
2458 return false;
2459 }
2460 if (IsUnsigned) {
2461 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2462 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2463 // the pseudo-branch will be taken only when the non-zero register is
2464 // different from 0, so we emit a BNEZ.
2465 //
2466 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2467 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2468 // the pseudo-branch will be taken only when the non-zero register is
2469 // equal to 0, so we emit a BEQZ.
2470 //
2471 // Because only BLEU and BGEU branch on equality, we can use the
2472 // AcceptsEquality variable to decide when to emit the BEQZ.
2473 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2474 BranchInst.addOperand(
2475 MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2476 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2477 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2478 Instructions.push_back(BranchInst);
2479 return false;
2480 }
2481 // If we have a signed pseudo-branch and one of the registers is $0,
2482 // we can use an appropriate compare-to-zero branch. We select which one
2483 // to use in the switch statement above.
2484 BranchInst.setOpcode(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode);
2485 BranchInst.addOperand(MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2486 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2487 Instructions.push_back(BranchInst);
2488 return false;
2489 }
2490
2491 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2492 // expansions. If it is not available, we return.
2493 unsigned ATRegNum = getATReg(IDLoc);
2494 if (!ATRegNum)
2495 return true;
2496
2497 warnIfNoMacro(IDLoc);
2498
2499 // SLT fits well with 2 of our 4 pseudo-branches:
2500 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2501 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2502 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2503 // This is accomplished by using a BNEZ with the result of the SLT.
2504 //
2505 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2506 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2507 // Because only BGE and BLE branch on equality, we can use the
2508 // AcceptsEquality variable to decide when to emit the BEQZ.
2509 // Note that the order of the SLT arguments doesn't change between
2510 // opposites.
2511 //
2512 // The same applies to the unsigned variants, except that SLTu is used
2513 // instead of SLT.
2514 MCInst SetInst;
2515 SetInst.setOpcode(IsUnsigned ? Mips::SLTu : Mips::SLT);
2516 SetInst.addOperand(MCOperand::createReg(ATRegNum));
2517 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? TrgReg : SrcReg));
2518 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? SrcReg : TrgReg));
2519 Instructions.push_back(SetInst);
2520
2521 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2522 BranchInst.addOperand(MCOperand::createReg(ATRegNum));
2523 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2524 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2525 Instructions.push_back(BranchInst);
2526 return false;
2527}
2528
Toma Tabacud88d79c2015-06-23 14:39:42 +00002529bool MipsAsmParser::expandUlhu(MCInst &Inst, SMLoc IDLoc,
2530 SmallVectorImpl<MCInst> &Instructions) {
2531 if (hasMips32r6() || hasMips64r6()) {
2532 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2533 return false;
2534 }
2535
2536 warnIfNoMacro(IDLoc);
2537
2538 const MCOperand &DstRegOp = Inst.getOperand(0);
2539 assert(DstRegOp.isReg() && "expected register operand kind");
2540
2541 const MCOperand &SrcRegOp = Inst.getOperand(1);
2542 assert(SrcRegOp.isReg() && "expected register operand kind");
2543
2544 const MCOperand &OffsetImmOp = Inst.getOperand(2);
2545 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
2546
2547 unsigned DstReg = DstRegOp.getReg();
2548 unsigned SrcReg = SrcRegOp.getReg();
2549 int64_t OffsetValue = OffsetImmOp.getImm();
2550
2551 // NOTE: We always need AT for ULHU, as it is always used as the source
2552 // register for one of the LBu's.
2553 unsigned ATReg = getATReg(IDLoc);
2554 if (!ATReg)
2555 return true;
2556
2557 // When the value of offset+1 does not fit in 16 bits, we have to load the
2558 // offset in AT, (D)ADDu the original source register (if there was one), and
2559 // then use AT as the source register for the 2 generated LBu's.
2560 bool LoadedOffsetInAT = false;
2561 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
2562 LoadedOffsetInAT = true;
2563
2564 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
2565 IDLoc, Instructions))
2566 return true;
2567
2568 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
2569 // because it will make our output more similar to GAS'. For example,
2570 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
2571 // instead of just an "ori $1, $9, 32768".
2572 // NOTE: If there is no source register specified in the ULHU, the parser
2573 // will interpret it as $0.
2574 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
2575 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
2576 }
2577
2578 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
2579 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
2580 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
2581
2582 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
2583 if (isLittle()) {
2584 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2585 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2586 } else {
2587 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2588 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2589 }
2590
2591 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
2592
2593 MCInst TmpInst;
2594 TmpInst.setOpcode(Mips::LBu);
2595 TmpInst.addOperand(MCOperand::createReg(FirstLbuDstReg));
2596 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2597 TmpInst.addOperand(MCOperand::createImm(FirstLbuOffset));
2598 Instructions.push_back(TmpInst);
2599
2600 TmpInst.clear();
2601 TmpInst.setOpcode(Mips::LBu);
2602 TmpInst.addOperand(MCOperand::createReg(SecondLbuDstReg));
2603 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2604 TmpInst.addOperand(MCOperand::createImm(SecondLbuOffset));
2605 Instructions.push_back(TmpInst);
2606
2607 TmpInst.clear();
2608 TmpInst.setOpcode(Mips::SLL);
2609 TmpInst.addOperand(MCOperand::createReg(SllReg));
2610 TmpInst.addOperand(MCOperand::createReg(SllReg));
2611 TmpInst.addOperand(MCOperand::createImm(8));
2612 Instructions.push_back(TmpInst);
2613
2614 TmpInst.clear();
2615 TmpInst.setOpcode(Mips::OR);
2616 TmpInst.addOperand(MCOperand::createReg(DstReg));
2617 TmpInst.addOperand(MCOperand::createReg(DstReg));
2618 TmpInst.addOperand(MCOperand::createReg(ATReg));
2619 Instructions.push_back(TmpInst);
2620
2621 return false;
2622}
2623
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002624bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
2625 SmallVectorImpl<MCInst> &Instructions) {
2626 if (hasMips32r6() || hasMips64r6()) {
2627 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2628 return false;
2629 }
2630
2631 const MCOperand &DstRegOp = Inst.getOperand(0);
2632 assert(DstRegOp.isReg() && "expected register operand kind");
2633
2634 const MCOperand &SrcRegOp = Inst.getOperand(1);
2635 assert(SrcRegOp.isReg() && "expected register operand kind");
2636
2637 const MCOperand &OffsetImmOp = Inst.getOperand(2);
2638 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
2639
2640 unsigned SrcReg = SrcRegOp.getReg();
2641 int64_t OffsetValue = OffsetImmOp.getImm();
2642 unsigned ATReg = 0;
2643
2644 // When the value of offset+3 does not fit in 16 bits, we have to load the
2645 // offset in AT, (D)ADDu the original source register (if there was one), and
2646 // then use AT as the source register for the generated LWL and LWR.
2647 bool LoadedOffsetInAT = false;
2648 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
2649 ATReg = getATReg(IDLoc);
2650 if (!ATReg)
2651 return true;
2652 LoadedOffsetInAT = true;
2653
2654 warnIfNoMacro(IDLoc);
2655
2656 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
2657 IDLoc, Instructions))
2658 return true;
2659
2660 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
2661 // because it will make our output more similar to GAS'. For example,
2662 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
2663 // instead of just an "ori $1, $9, 32768".
2664 // NOTE: If there is no source register specified in the ULW, the parser
2665 // will interpret it as $0.
2666 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
2667 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
2668 }
2669
2670 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
2671 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
2672 if (isLittle()) {
2673 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
2674 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2675 } else {
2676 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2677 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
2678 }
2679
2680 MCInst LeftLoadInst;
2681 LeftLoadInst.setOpcode(Mips::LWL);
2682 LeftLoadInst.addOperand(DstRegOp);
2683 LeftLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
2684 LeftLoadInst.addOperand(MCOperand::createImm(LeftLoadOffset));
2685 Instructions.push_back(LeftLoadInst);
2686
2687 MCInst RightLoadInst;
2688 RightLoadInst.setOpcode(Mips::LWR);
2689 RightLoadInst.addOperand(DstRegOp);
2690 RightLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
2691 RightLoadInst.addOperand(MCOperand::createImm(RightLoadOffset ));
2692 Instructions.push_back(RightLoadInst);
2693
2694 return false;
2695}
2696
Toma Tabacu234482a2015-03-16 12:03:39 +00002697void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2698 SmallVectorImpl<MCInst> &Instructions) {
2699 MCInst NopInst;
2700 if (hasShortDelaySlot) {
2701 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002702 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2703 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00002704 } else {
2705 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00002706 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2707 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2708 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00002709 }
2710 Instructions.push_back(NopInst);
2711}
2712
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002713void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00002714 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002715 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00002716 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
2717 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002718}
2719
Matheus Almeida595fcab2014-06-11 15:05:56 +00002720unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2721 // As described by the Mips32r2 spec, the registers Rd and Rs for
2722 // jalr.hb must be different.
2723 unsigned Opcode = Inst.getOpcode();
2724
2725 if (Opcode == Mips::JALR_HB &&
2726 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2727 return Match_RequiresDifferentSrcAndDst;
2728
2729 return Match_Success;
2730}
2731
David Blaikie960ea3f2014-06-08 16:18:35 +00002732bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2733 OperandVector &Operands,
2734 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002735 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002736 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002737
Jack Carterb4dbc172012-09-05 23:34:03 +00002738 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002739 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002740 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00002741 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002742
2743 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002744 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002745 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002746 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002747 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002748 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002749 return false;
2750 }
2751 case Match_MissingFeature:
2752 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2753 return true;
2754 case Match_InvalidOperand: {
2755 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002756 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002757 if (ErrorInfo >= Operands.size())
2758 return Error(IDLoc, "too few operands for instruction");
2759
David Blaikie960ea3f2014-06-08 16:18:35 +00002760 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002761 if (ErrorLoc == SMLoc())
2762 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002763 }
2764
2765 return Error(ErrorLoc, "invalid operand for instruction");
2766 }
2767 case Match_MnemonicFail:
2768 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002769 case Match_RequiresDifferentSrcAndDst:
2770 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002771 }
Craig Topper589ceee2015-01-03 08:16:34 +00002772
2773 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002774}
2775
Toma Tabacud9d344b2015-04-27 14:05:04 +00002776void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2777 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2778 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2779 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002780}
2781
Toma Tabacu81496c12015-05-20 08:54:45 +00002782void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
2783 if (!AssemblerOptions.back()->isMacro())
2784 Warning(Loc, "macro instruction expanded into multiple instructions");
2785}
2786
Daniel Sandersef638fe2014-10-03 15:37:37 +00002787void
2788MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2789 SMRange Range, bool ShowColors) {
2790 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002791 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002792 ShowColors);
2793}
2794
Jack Carter1ac53222013-02-20 23:11:17 +00002795int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002796 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002797
Vladimir Medic4c299852013-11-06 11:27:05 +00002798 CC = StringSwitch<unsigned>(Name)
2799 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002800 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002801 .Case("a0", 4)
2802 .Case("a1", 5)
2803 .Case("a2", 6)
2804 .Case("a3", 7)
2805 .Case("v0", 2)
2806 .Case("v1", 3)
2807 .Case("s0", 16)
2808 .Case("s1", 17)
2809 .Case("s2", 18)
2810 .Case("s3", 19)
2811 .Case("s4", 20)
2812 .Case("s5", 21)
2813 .Case("s6", 22)
2814 .Case("s7", 23)
2815 .Case("k0", 26)
2816 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002817 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002818 .Case("sp", 29)
2819 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002820 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002821 .Case("ra", 31)
2822 .Case("t0", 8)
2823 .Case("t1", 9)
2824 .Case("t2", 10)
2825 .Case("t3", 11)
2826 .Case("t4", 12)
2827 .Case("t5", 13)
2828 .Case("t6", 14)
2829 .Case("t7", 15)
2830 .Case("t8", 24)
2831 .Case("t9", 25)
2832 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002833
Toma Tabacufda445c2014-09-15 15:33:01 +00002834 if (!(isABI_N32() || isABI_N64()))
2835 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002836
Daniel Sandersef638fe2014-10-03 15:37:37 +00002837 if (12 <= CC && CC <= 15) {
2838 // Name is one of t4-t7
2839 AsmToken RegTok = getLexer().peekTok();
2840 SMRange RegRange = RegTok.getLocRange();
2841
2842 StringRef FixedName = StringSwitch<StringRef>(Name)
2843 .Case("t4", "t0")
2844 .Case("t5", "t1")
2845 .Case("t6", "t2")
2846 .Case("t7", "t3")
2847 .Default("");
2848 assert(FixedName != "" && "Register name is not one of t4-t7.");
2849
2850 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2851 "Did you mean $" + FixedName + "?", RegRange);
2852 }
2853
Toma Tabacufda445c2014-09-15 15:33:01 +00002854 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2855 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2856 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2857 if (8 <= CC && CC <= 11)
2858 CC += 4;
2859
2860 if (CC == -1)
2861 CC = StringSwitch<unsigned>(Name)
2862 .Case("a4", 8)
2863 .Case("a5", 9)
2864 .Case("a6", 10)
2865 .Case("a7", 11)
2866 .Case("kt0", 26)
2867 .Case("kt1", 27)
2868 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002869
2870 return CC;
2871}
Jack Carterd0bd6422013-04-18 00:41:53 +00002872
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002873int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2874 int CC;
2875
2876 CC = StringSwitch<unsigned>(Name)
2877 .Case("hwr_cpunum", 0)
2878 .Case("hwr_synci_step", 1)
2879 .Case("hwr_cc", 2)
2880 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002881 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002882 .Default(-1);
2883
2884 return CC;
2885}
2886
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002887int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002888
Jack Cartera63b16a2012-09-07 00:23:42 +00002889 if (Name[0] == 'f') {
2890 StringRef NumString = Name.substr(1);
2891 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002892 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002893 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002894 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002895 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002896 return IntVal;
2897 }
2898 return -1;
2899}
Jack Cartera63b16a2012-09-07 00:23:42 +00002900
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002901int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2902
2903 if (Name.startswith("fcc")) {
2904 StringRef NumString = Name.substr(3);
2905 unsigned IntVal;
2906 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002907 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002908 if (IntVal > 7) // There are only 8 fcc registers.
2909 return -1;
2910 return IntVal;
2911 }
2912 return -1;
2913}
2914
2915int MipsAsmParser::matchACRegisterName(StringRef Name) {
2916
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002917 if (Name.startswith("ac")) {
2918 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002919 unsigned IntVal;
2920 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002921 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002922 if (IntVal > 3) // There are only 3 acc registers.
2923 return -1;
2924 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002925 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002926 return -1;
2927}
Jack Carterd0bd6422013-04-18 00:41:53 +00002928
Jack Carter5dc8ac92013-09-25 23:50:44 +00002929int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2930 unsigned IntVal;
2931
2932 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2933 return -1;
2934
2935 if (IntVal > 31)
2936 return -1;
2937
2938 return IntVal;
2939}
2940
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002941int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2942 int CC;
2943
2944 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002945 .Case("msair", 0)
2946 .Case("msacsr", 1)
2947 .Case("msaaccess", 2)
2948 .Case("msasave", 3)
2949 .Case("msamodify", 4)
2950 .Case("msarequest", 5)
2951 .Case("msamap", 6)
2952 .Case("msaunmap", 7)
2953 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002954
2955 return CC;
2956}
2957
Toma Tabacu89a712b2015-04-15 10:48:56 +00002958unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002959 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002960 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002961 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002962 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002963 return 0;
2964 }
2965 unsigned AT = getReg(
2966 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002967 return AT;
2968}
Jack Carter0b744b32012-10-04 02:29:46 +00002969
Jack Carterd0bd6422013-04-18 00:41:53 +00002970unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002971 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002972}
2973
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002974unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002975 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002976 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002977}
2978
Jack Carter873c7242013-01-12 01:03:14 +00002979int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002980 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002981 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002982 return -1;
2983
Jack Carter873c7242013-01-12 01:03:14 +00002984 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002985}
2986
Toma Tabacu13964452014-09-04 13:23:44 +00002987bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002988 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002989 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002990
Jack Carter30a59822012-10-04 04:03:53 +00002991 // Check if the current operand has a custom associated parser, if so, try to
2992 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002993 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2994 if (ResTy == MatchOperand_Success)
2995 return false;
2996 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2997 // there was a match, but an error occurred, in which case, just return that
2998 // the operand parsing failed.
2999 if (ResTy == MatchOperand_ParseFail)
3000 return true;
3001
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003002 DEBUG(dbgs() << ".. Generic Parser\n");
3003
Jack Carterb4dbc172012-09-05 23:34:03 +00003004 switch (getLexer().getKind()) {
3005 default:
3006 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3007 return true;
3008 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003009 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003010 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003011
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003012 // Almost all registers have been parsed by custom parsers. There is only
3013 // one exception to this. $zero (and it's alias $0) will reach this point
3014 // for div, divu, and similar instructions because it is not an operand
3015 // to the instruction definition but an explicit register. Special case
3016 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003017 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003018 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003019
Jack Carterd0bd6422013-04-18 00:41:53 +00003020 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003021 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003022 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003023 return true;
3024
Jack Carter873c7242013-01-12 01:03:14 +00003025 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003026 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003027 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003028 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003029 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003030
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003031 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003032 return false;
3033 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003034 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003035 case AsmToken::LParen:
3036 case AsmToken::Minus:
3037 case AsmToken::Plus:
3038 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003039 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003040 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003041 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003042 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003043 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003044 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003045 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003046 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003047 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003048 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003049 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003050 return true;
3051
Jack Carter873c7242013-01-12 01:03:14 +00003052 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3053
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003054 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003055 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003056 } // case AsmToken::Percent
3057 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003058 return true;
3059}
3060
Vladimir Medic4c299852013-11-06 11:27:05 +00003061const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003062 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003063 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003064 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003065 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003066 // It's a constant, evaluate reloc value.
3067 int16_t Val;
3068 switch (getVariantKind(RelocStr)) {
3069 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3070 // Get the 1st 16-bits.
3071 Val = MCE->getValue() & 0xffff;
3072 break;
3073 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3074 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3075 // 16 bits being negative.
3076 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3077 break;
3078 case MCSymbolRefExpr::VK_Mips_HIGHER:
3079 // Get the 3rd 16-bits.
3080 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3081 break;
3082 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3083 // Get the 4th 16-bits.
3084 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3085 break;
3086 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003087 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003088 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003089 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003090 }
3091
Jack Carterb5cf5902013-04-17 00:18:04 +00003092 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003093 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003094 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003095 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003096 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003097 return Res;
3098 }
3099
3100 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003101 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3102
Sasa Stankovic06c47802014-04-03 10:37:45 +00003103 // Try to create target expression.
3104 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003105 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003106
Jack Carterd0bd6422013-04-18 00:41:53 +00003107 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3108 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003109 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003110 return Res;
3111 }
3112
3113 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003114 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003115 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003116 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003117 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003118 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003119 return Expr;
3120}
3121
3122bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3123
3124 switch (Expr->getKind()) {
3125 case MCExpr::Constant:
3126 return true;
3127 case MCExpr::SymbolRef:
3128 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3129 case MCExpr::Binary:
3130 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3131 if (!isEvaluated(BE->getLHS()))
3132 return false;
3133 return isEvaluated(BE->getRHS());
3134 }
3135 case MCExpr::Unary:
3136 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003137 case MCExpr::Target:
3138 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003139 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003140 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003141}
Jack Carterd0bd6422013-04-18 00:41:53 +00003142
Jack Carterb5cf5902013-04-17 00:18:04 +00003143bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003144 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003145 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003146 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003147 if (Tok.isNot(AsmToken::Identifier))
3148 return true;
3149
Yaron Keren075759a2015-03-30 15:42:36 +00003150 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003151
Jack Carterd0bd6422013-04-18 00:41:53 +00003152 Parser.Lex(); // Eat the identifier.
3153 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003154 const MCExpr *IdVal;
3155 SMLoc EndLoc;
3156
3157 if (getLexer().getKind() == AsmToken::LParen) {
3158 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003159 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003160 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003161 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003162 const AsmToken &nextTok = Parser.getTok();
3163 if (nextTok.isNot(AsmToken::Identifier))
3164 return true;
3165 Str += "(%";
3166 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003167 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003168 if (getLexer().getKind() != AsmToken::LParen)
3169 return true;
3170 } else
3171 break;
3172 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003173 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003174 return true;
3175
3176 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003177 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003178
3179 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003180 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003181
Jack Carterd0bd6422013-04-18 00:41:53 +00003182 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003183 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003184}
3185
Jack Carterb4dbc172012-09-05 23:34:03 +00003186bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3187 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003188 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003189 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003190 if (ResTy == MatchOperand_Success) {
3191 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003192 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003193 StartLoc = Operand.getStartLoc();
3194 EndLoc = Operand.getEndLoc();
3195
3196 // AFAIK, we only support numeric registers and named GPR's in CFI
3197 // directives.
3198 // Don't worry about eating tokens before failing. Using an unrecognised
3199 // register is a parse error.
3200 if (Operand.isGPRAsmReg()) {
3201 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003202 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003203 }
3204
3205 return (RegNo == (unsigned)-1);
3206 }
3207
3208 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003209 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003210}
3211
Jack Carterb5cf5902013-04-17 00:18:04 +00003212bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003213 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003214 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003215 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003216 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003217
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003218 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003219 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003220 ++NumOfLParen;
3221 }
Jack Carter873c7242013-01-12 01:03:14 +00003222
Jack Carterd0bd6422013-04-18 00:41:53 +00003223 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003224 default:
3225 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003226 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003227 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003228 case AsmToken::Integer:
3229 case AsmToken::Minus:
3230 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003231 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003232 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003233 else
3234 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003235 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003236 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003237 break;
Jack Carter873c7242013-01-12 01:03:14 +00003238 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003239 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003240 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003241 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003242}
3243
David Blaikie960ea3f2014-06-08 16:18:35 +00003244MipsAsmParser::OperandMatchResultTy
3245MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003246 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003247 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003248 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003249 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003250 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003251 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003252 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003253 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003254
Jack Carterb5cf5902013-04-17 00:18:04 +00003255 if (getLexer().getKind() == AsmToken::LParen) {
3256 Parser.Lex();
3257 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003258 }
3259
Jack Carterb5cf5902013-04-17 00:18:04 +00003260 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003261 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003262 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003263
Jack Carterd0bd6422013-04-18 00:41:53 +00003264 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003265 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003266 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
3267 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003268 SMLoc E =
3269 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003270 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003271 return MatchOperand_Success;
3272 }
3273 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003274 SMLoc E =
3275 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003276
Jack Carterd0bd6422013-04-18 00:41:53 +00003277 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003278 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003279 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003280 S, E, *this);
3281 Operands.push_back(
3282 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003283 return MatchOperand_Success;
3284 }
3285 Error(Parser.getTok().getLoc(), "'(' expected");
3286 return MatchOperand_ParseFail;
3287 }
3288
Jack Carterd0bd6422013-04-18 00:41:53 +00003289 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003290 }
3291
Toma Tabacu13964452014-09-04 13:23:44 +00003292 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003293 if (Res != MatchOperand_Success)
3294 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003295
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003296 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003297 Error(Parser.getTok().getLoc(), "')' expected");
3298 return MatchOperand_ParseFail;
3299 }
3300
Jack Carter873c7242013-01-12 01:03:14 +00003301 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3302
Jack Carterd0bd6422013-04-18 00:41:53 +00003303 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003304
Craig Topper062a2ba2014-04-25 05:30:21 +00003305 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003306 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003307
Jack Carterd0bd6422013-04-18 00:41:53 +00003308 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003309 std::unique_ptr<MipsOperand> op(
3310 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003311 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003312 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003313 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003314 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003315 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3316 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003317 if (IdVal->evaluateAsAbsolute(Imm))
3318 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003319 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003320 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003321 getContext());
3322 }
3323
David Blaikie960ea3f2014-06-08 16:18:35 +00003324 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003325 return MatchOperand_Success;
3326}
3327
David Blaikie960ea3f2014-06-08 16:18:35 +00003328bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003329 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003330 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003331 if (Sym) {
3332 SMLoc S = Parser.getTok().getLoc();
3333 const MCExpr *Expr;
3334 if (Sym->isVariable())
3335 Expr = Sym->getVariableValue();
3336 else
3337 return false;
3338 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003339 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003340 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003341 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003342 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003343 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003344 if (ResTy == MatchOperand_Success) {
3345 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003346 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003347 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003348 llvm_unreachable("Should never ParseFail");
3349 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003350 }
3351 } else if (Expr->getKind() == MCExpr::Constant) {
3352 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003353 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003354 Operands.push_back(
3355 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003356 return true;
3357 }
3358 }
3359 return false;
3360}
Jack Carterd0bd6422013-04-18 00:41:53 +00003361
Jack Carter873c7242013-01-12 01:03:14 +00003362MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003363MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003364 StringRef Identifier,
3365 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003366 int Index = matchCPURegisterName(Identifier);
3367 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003368 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003369 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3370 return MatchOperand_Success;
3371 }
3372
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003373 Index = matchHWRegsRegisterName(Identifier);
3374 if (Index != -1) {
3375 Operands.push_back(MipsOperand::createHWRegsReg(
3376 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3377 return MatchOperand_Success;
3378 }
3379
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003380 Index = matchFPURegisterName(Identifier);
3381 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003382 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003383 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3384 return MatchOperand_Success;
3385 }
3386
3387 Index = matchFCCRegisterName(Identifier);
3388 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003389 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003390 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3391 return MatchOperand_Success;
3392 }
3393
3394 Index = matchACRegisterName(Identifier);
3395 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003396 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003397 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3398 return MatchOperand_Success;
3399 }
3400
3401 Index = matchMSA128RegisterName(Identifier);
3402 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003403 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003404 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3405 return MatchOperand_Success;
3406 }
3407
3408 Index = matchMSA128CtrlRegisterName(Identifier);
3409 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003410 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003411 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3412 return MatchOperand_Success;
3413 }
3414
3415 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003416}
3417
3418MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003419MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003420 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003421 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003422
3423 if (Token.is(AsmToken::Identifier)) {
3424 DEBUG(dbgs() << ".. identifier\n");
3425 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003426 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003427 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003428 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003429 } else if (Token.is(AsmToken::Integer)) {
3430 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003431 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003432 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3433 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003434 return MatchOperand_Success;
3435 }
3436
3437 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3438
3439 return MatchOperand_NoMatch;
3440}
3441
David Blaikie960ea3f2014-06-08 16:18:35 +00003442MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003443MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003444 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003445 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003446
3447 auto Token = Parser.getTok();
3448
3449 SMLoc S = Token.getLoc();
3450
3451 if (Token.isNot(AsmToken::Dollar)) {
3452 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3453 if (Token.is(AsmToken::Identifier)) {
3454 if (searchSymbolAlias(Operands))
3455 return MatchOperand_Success;
3456 }
3457 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3458 return MatchOperand_NoMatch;
3459 }
3460 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003461
Toma Tabacu13964452014-09-04 13:23:44 +00003462 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00003463 if (ResTy == MatchOperand_Success) {
3464 Parser.Lex(); // $
3465 Parser.Lex(); // identifier
3466 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003467 return ResTy;
3468}
3469
3470MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003471MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003472 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003473 switch (getLexer().getKind()) {
3474 default:
3475 return MatchOperand_NoMatch;
3476 case AsmToken::LParen:
3477 case AsmToken::Minus:
3478 case AsmToken::Plus:
3479 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003480 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003481 case AsmToken::String:
3482 break;
3483 }
3484
3485 const MCExpr *IdVal;
3486 SMLoc S = Parser.getTok().getLoc();
3487 if (getParser().parseExpression(IdVal))
3488 return MatchOperand_ParseFail;
3489
3490 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3491 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
3492 return MatchOperand_Success;
3493}
3494
David Blaikie960ea3f2014-06-08 16:18:35 +00003495MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003496MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003497 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003498 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003499
3500 SMLoc S = getLexer().getLoc();
3501
3502 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00003503 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003504 if (ResTy != MatchOperand_NoMatch)
3505 return ResTy;
3506
Daniel Sanders315386c2014-04-01 10:40:14 +00003507 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00003508 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00003509 if (ResTy != MatchOperand_NoMatch)
3510 return ResTy;
3511
Daniel Sandersffd84362014-04-01 10:41:48 +00003512 const MCExpr *Expr = nullptr;
3513 if (Parser.parseExpression(Expr)) {
3514 // We have no way of knowing if a symbol was consumed so we must ParseFail
3515 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003516 }
Daniel Sandersffd84362014-04-01 10:41:48 +00003517 Operands.push_back(
3518 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003519 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00003520}
3521
Vladimir Medic2b953d02013-10-01 09:48:56 +00003522MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00003523MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003524 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00003525 const MCExpr *IdVal;
3526 // If the first token is '$' we may have register operand.
3527 if (Parser.getTok().is(AsmToken::Dollar))
3528 return MatchOperand_NoMatch;
3529 SMLoc S = Parser.getTok().getLoc();
3530 if (getParser().parseExpression(IdVal))
3531 return MatchOperand_ParseFail;
3532 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003533 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003534 int64_t Val = MCE->getValue();
3535 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3536 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003537 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003538 return MatchOperand_Success;
3539}
3540
Matheus Almeida779c5932013-11-18 12:32:49 +00003541MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003542MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003543 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003544 switch (getLexer().getKind()) {
3545 default:
3546 return MatchOperand_NoMatch;
3547 case AsmToken::LParen:
3548 case AsmToken::Plus:
3549 case AsmToken::Minus:
3550 case AsmToken::Integer:
3551 break;
3552 }
3553
3554 const MCExpr *Expr;
3555 SMLoc S = Parser.getTok().getLoc();
3556
3557 if (getParser().parseExpression(Expr))
3558 return MatchOperand_ParseFail;
3559
3560 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003561 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00003562 Error(S, "expected immediate value");
3563 return MatchOperand_ParseFail;
3564 }
3565
3566 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3567 // and because the CPU always adds one to the immediate field, the allowed
3568 // range becomes 1..4. We'll only check the range here and will deal
3569 // with the addition/subtraction when actually decoding/encoding
3570 // the instruction.
3571 if (Val < 1 || Val > 4) {
3572 Error(S, "immediate not in range (1..4)");
3573 return MatchOperand_ParseFail;
3574 }
3575
Jack Carter3b2c96e2014-01-22 23:31:38 +00003576 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003577 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003578 return MatchOperand_Success;
3579}
3580
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003581MipsAsmParser::OperandMatchResultTy
3582MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3583 MCAsmParser &Parser = getParser();
3584 SmallVector<unsigned, 10> Regs;
3585 unsigned RegNo;
3586 unsigned PrevReg = Mips::NoRegister;
3587 bool RegRange = false;
3588 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3589
3590 if (Parser.getTok().isNot(AsmToken::Dollar))
3591 return MatchOperand_ParseFail;
3592
3593 SMLoc S = Parser.getTok().getLoc();
3594 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3595 SMLoc E = getLexer().getLoc();
3596 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3597 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3598 if (RegRange) {
3599 // Remove last register operand because registers from register range
3600 // should be inserted first.
3601 if (RegNo == Mips::RA) {
3602 Regs.push_back(RegNo);
3603 } else {
3604 unsigned TmpReg = PrevReg + 1;
3605 while (TmpReg <= RegNo) {
3606 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3607 Error(E, "invalid register operand");
3608 return MatchOperand_ParseFail;
3609 }
3610
3611 PrevReg = TmpReg;
3612 Regs.push_back(TmpReg++);
3613 }
3614 }
3615
3616 RegRange = false;
3617 } else {
3618 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3619 (RegNo != Mips::RA)) {
3620 Error(E, "$16 or $31 expected");
3621 return MatchOperand_ParseFail;
3622 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3623 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3624 Error(E, "invalid register operand");
3625 return MatchOperand_ParseFail;
3626 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3627 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3628 Error(E, "consecutive register numbers expected");
3629 return MatchOperand_ParseFail;
3630 }
3631
3632 Regs.push_back(RegNo);
3633 }
3634
3635 if (Parser.getTok().is(AsmToken::Minus))
3636 RegRange = true;
3637
3638 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3639 !Parser.getTok().isNot(AsmToken::Comma)) {
3640 Error(E, "',' or '-' expected");
3641 return MatchOperand_ParseFail;
3642 }
3643
3644 Lex(); // Consume comma or minus
3645 if (Parser.getTok().isNot(AsmToken::Dollar))
3646 break;
3647
3648 PrevReg = RegNo;
3649 }
3650
3651 SMLoc E = Parser.getTok().getLoc();
3652 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3653 parseMemOperand(Operands);
3654 return MatchOperand_Success;
3655}
3656
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003657MipsAsmParser::OperandMatchResultTy
3658MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3659 MCAsmParser &Parser = getParser();
3660
3661 SMLoc S = Parser.getTok().getLoc();
3662 if (parseAnyRegister(Operands) != MatchOperand_Success)
3663 return MatchOperand_ParseFail;
3664
3665 SMLoc E = Parser.getTok().getLoc();
3666 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3667 unsigned Reg = Op.getGPR32Reg();
3668 Operands.pop_back();
3669 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3670 return MatchOperand_Success;
3671}
3672
Zoran Jovanovic41688672015-02-10 16:36:20 +00003673MipsAsmParser::OperandMatchResultTy
3674MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3675 MCAsmParser &Parser = getParser();
3676 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3677 SmallVector<unsigned, 10> Regs;
3678
3679 if (Parser.getTok().isNot(AsmToken::Dollar))
3680 return MatchOperand_ParseFail;
3681
3682 SMLoc S = Parser.getTok().getLoc();
3683
3684 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3685 return MatchOperand_ParseFail;
3686
3687 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3688 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3689 Regs.push_back(RegNo);
3690
3691 SMLoc E = Parser.getTok().getLoc();
3692 if (Parser.getTok().isNot(AsmToken::Comma)) {
3693 Error(E, "',' expected");
3694 return MatchOperand_ParseFail;
3695 }
3696
3697 // Remove comma.
3698 Parser.Lex();
3699
3700 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3701 return MatchOperand_ParseFail;
3702
3703 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3704 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3705 Regs.push_back(RegNo);
3706
3707 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3708
3709 return MatchOperand_Success;
3710}
3711
Jack Carterdc1e35d2012-09-06 20:00:02 +00003712MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3713
Vladimir Medic4c299852013-11-06 11:27:05 +00003714 MCSymbolRefExpr::VariantKind VK =
3715 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3716 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3717 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3718 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3719 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3720 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3721 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3722 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3723 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3724 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3725 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3726 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3727 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3728 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3729 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3730 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3731 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3732 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003733 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3734 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3735 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3736 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3737 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3738 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003739 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3740 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003741 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003742
Matheus Almeida2852af82014-04-22 10:15:54 +00003743 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003744
Jack Carterdc1e35d2012-09-06 20:00:02 +00003745 return VK;
3746}
Jack Cartera63b16a2012-09-07 00:23:42 +00003747
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003748/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3749/// either this.
3750/// ::= '(', register, ')'
3751/// handle it before we iterate so we don't get tripped up by the lack of
3752/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003753bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003754 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003755 if (getLexer().is(AsmToken::LParen)) {
3756 Operands.push_back(
3757 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3758 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003759 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003760 SMLoc Loc = getLexer().getLoc();
3761 Parser.eatToEndOfStatement();
3762 return Error(Loc, "unexpected token in argument list");
3763 }
3764 if (Parser.getTok().isNot(AsmToken::RParen)) {
3765 SMLoc Loc = getLexer().getLoc();
3766 Parser.eatToEndOfStatement();
3767 return Error(Loc, "unexpected token, expected ')'");
3768 }
3769 Operands.push_back(
3770 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3771 Parser.Lex();
3772 }
3773 return false;
3774}
3775
3776/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3777/// either one of these.
3778/// ::= '[', register, ']'
3779/// ::= '[', integer, ']'
3780/// handle it before we iterate so we don't get tripped up by the lack of
3781/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003782bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003783 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003784 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003785 if (getLexer().is(AsmToken::LBrac)) {
3786 Operands.push_back(
3787 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3788 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003789 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003790 SMLoc Loc = getLexer().getLoc();
3791 Parser.eatToEndOfStatement();
3792 return Error(Loc, "unexpected token in argument list");
3793 }
3794 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3795 SMLoc Loc = getLexer().getLoc();
3796 Parser.eatToEndOfStatement();
3797 return Error(Loc, "unexpected token, expected ']'");
3798 }
3799 Operands.push_back(
3800 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3801 Parser.Lex();
3802 }
3803 return false;
3804}
3805
David Blaikie960ea3f2014-06-08 16:18:35 +00003806bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3807 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003808 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003809 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003810
3811 // We have reached first instruction, module directive are now forbidden.
3812 getTargetStreamer().forbidModuleDirective();
3813
Vladimir Medic74593e62013-07-17 15:00:42 +00003814 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003815 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003816 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003817 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003818 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003819 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003820 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003821
3822 // Read the remaining operands.
3823 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3824 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003825 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003826 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003827 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003828 return Error(Loc, "unexpected token in argument list");
3829 }
Toma Tabacu13964452014-09-04 13:23:44 +00003830 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003831 return true;
3832 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003833
Jack Carterd0bd6422013-04-18 00:41:53 +00003834 while (getLexer().is(AsmToken::Comma)) {
3835 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003836 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003837 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003838 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003839 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003840 return Error(Loc, "unexpected token in argument list");
3841 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003842 // Parse bracket and parenthesis suffixes before we iterate
3843 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003844 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003845 return true;
3846 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003847 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003848 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003849 }
3850 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003851 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3852 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003853 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003854 return Error(Loc, "unexpected token in argument list");
3855 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003856 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003857 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003858}
3859
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003860bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003861 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003862 SMLoc Loc = getLexer().getLoc();
3863 Parser.eatToEndOfStatement();
3864 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003865}
3866
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003867bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003868 return Error(Loc, ErrorMsg);
3869}
3870
Jack Carter0b744b32012-10-04 02:29:46 +00003871bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003872 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003873 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003874
3875 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003876 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003877
3878 Parser.Lex(); // Eat "noat".
3879
Jack Carterd0bd6422013-04-18 00:41:53 +00003880 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003881 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003882 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003883 return false;
3884 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003885
3886 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003887 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003888 return false;
3889}
Jack Carterd0bd6422013-04-18 00:41:53 +00003890
Jack Carter0b744b32012-10-04 02:29:46 +00003891bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003892 // Line can be: ".set at", which sets $at to $1
3893 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003894 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003895 Parser.Lex(); // Eat "at".
3896
Jack Carter0b744b32012-10-04 02:29:46 +00003897 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003898 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003899 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003900
3901 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003902 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003903 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003904 }
3905
3906 if (getLexer().isNot(AsmToken::Equal)) {
3907 reportParseError("unexpected token, expected equals sign");
3908 return false;
3909 }
3910 Parser.Lex(); // Eat "=".
3911
3912 if (getLexer().isNot(AsmToken::Dollar)) {
3913 if (getLexer().is(AsmToken::EndOfStatement)) {
3914 reportParseError("no register specified");
3915 return false;
3916 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003917 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003918 return false;
3919 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003920 }
3921 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003922
Toma Tabacu16a74492015-02-13 10:30:57 +00003923 // Find out what "reg" is.
3924 unsigned AtRegNo;
3925 const AsmToken &Reg = Parser.getTok();
3926 if (Reg.is(AsmToken::Identifier)) {
3927 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3928 } else if (Reg.is(AsmToken::Integer)) {
3929 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003930 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003931 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003932 return false;
3933 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003934
3935 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003936 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003937 reportParseError("invalid register");
3938 return false;
3939 }
3940 Parser.Lex(); // Eat "reg".
3941
3942 // If this is not the end of the statement, report an error.
3943 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3944 reportParseError("unexpected token, expected end of statement");
3945 return false;
3946 }
3947
3948 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3949
3950 Parser.Lex(); // Consume the EndOfStatement.
3951 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003952}
3953
3954bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003955 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003956 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003957 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003958 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003959 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003960 return false;
3961 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003962 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003963 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003964 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003965 return false;
3966}
3967
3968bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003969 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003970 Parser.Lex();
3971 // If this is not the end of the statement, report an error.
3972 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003973 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003974 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003975 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003976 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003977 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003978 Parser.Lex(); // Consume the EndOfStatement.
3979 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003980}
3981
3982bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003983 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003984 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003985 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003986 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003987 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003988 return false;
3989 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003990 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003991 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003992 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003993 return false;
3994}
3995
3996bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003997 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003998 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003999 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004000 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004001 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004002 return false;
4003 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004004 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004005 reportParseError("`noreorder' must be set before `nomacro'");
4006 return false;
4007 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004008 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004009 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004010 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004011 return false;
4012}
Jack Carterd76b2372013-03-21 21:44:16 +00004013
Daniel Sanders44934432014-08-07 12:03:36 +00004014bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004015 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004016 Parser.Lex();
4017
4018 // If this is not the end of the statement, report an error.
4019 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004020 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004021
4022 setFeatureBits(Mips::FeatureMSA, "msa");
4023 getTargetStreamer().emitDirectiveSetMsa();
4024 return false;
4025}
4026
4027bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004028 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004029 Parser.Lex();
4030
4031 // If this is not the end of the statement, report an error.
4032 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004033 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004034
4035 clearFeatureBits(Mips::FeatureMSA, "msa");
4036 getTargetStreamer().emitDirectiveSetNoMsa();
4037 return false;
4038}
4039
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004040bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004041 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004042 Parser.Lex(); // Eat "nodsp".
4043
4044 // If this is not the end of the statement, report an error.
4045 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4046 reportParseError("unexpected token, expected end of statement");
4047 return false;
4048 }
4049
4050 clearFeatureBits(Mips::FeatureDSP, "dsp");
4051 getTargetStreamer().emitDirectiveSetNoDsp();
4052 return false;
4053}
4054
Toma Tabacucc2502d2014-11-04 17:18:07 +00004055bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004056 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004057 Parser.Lex(); // Eat "mips16".
4058
Jack Carter39536722014-01-22 23:08:42 +00004059 // If this is not the end of the statement, report an error.
4060 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004061 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004062 return false;
4063 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004064
4065 setFeatureBits(Mips::FeatureMips16, "mips16");
4066 getTargetStreamer().emitDirectiveSetMips16();
4067 Parser.Lex(); // Consume the EndOfStatement.
4068 return false;
4069}
4070
4071bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004072 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004073 Parser.Lex(); // Eat "nomips16".
4074
4075 // If this is not the end of the statement, report an error.
4076 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4077 reportParseError("unexpected token, expected end of statement");
4078 return false;
4079 }
4080
4081 clearFeatureBits(Mips::FeatureMips16, "mips16");
4082 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004083 Parser.Lex(); // Consume the EndOfStatement.
4084 return false;
4085}
4086
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004087bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004088 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004089 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004090 // Line can be: .set fp=32
4091 // .set fp=xx
4092 // .set fp=64
4093 Parser.Lex(); // Eat fp token
4094 AsmToken Tok = Parser.getTok();
4095 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004096 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004097 return false;
4098 }
4099 Parser.Lex(); // Eat '=' token.
4100 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004101
4102 if (!parseFpABIValue(FpAbiVal, ".set"))
4103 return false;
4104
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004105 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004106 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004107 return false;
4108 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004109 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004110 Parser.Lex(); // Consume the EndOfStatement.
4111 return false;
4112}
4113
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004114bool MipsAsmParser::parseSetOddSPRegDirective() {
4115 MCAsmParser &Parser = getParser();
4116
4117 Parser.Lex(); // Eat "oddspreg".
4118 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4119 reportParseError("unexpected token, expected end of statement");
4120 return false;
4121 }
4122
4123 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4124 getTargetStreamer().emitDirectiveSetOddSPReg();
4125 return false;
4126}
4127
4128bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4129 MCAsmParser &Parser = getParser();
4130
4131 Parser.Lex(); // Eat "nooddspreg".
4132 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4133 reportParseError("unexpected token, expected end of statement");
4134 return false;
4135 }
4136
4137 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4138 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4139 return false;
4140}
4141
Toma Tabacu9db22db2014-09-09 10:15:38 +00004142bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004143 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004144 SMLoc Loc = getLexer().getLoc();
4145
4146 Parser.Lex();
4147 if (getLexer().isNot(AsmToken::EndOfStatement))
4148 return reportParseError("unexpected token, expected end of statement");
4149
4150 // Always keep an element on the options "stack" to prevent the user
4151 // from changing the initial options. This is how we remember them.
4152 if (AssemblerOptions.size() == 2)
4153 return reportParseError(Loc, ".set pop with no .set push");
4154
4155 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004156 setAvailableFeatures(
4157 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4158 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004159
4160 getTargetStreamer().emitDirectiveSetPop();
4161 return false;
4162}
4163
4164bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004165 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004166 Parser.Lex();
4167 if (getLexer().isNot(AsmToken::EndOfStatement))
4168 return reportParseError("unexpected token, expected end of statement");
4169
4170 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004171 AssemblerOptions.push_back(
4172 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004173
4174 getTargetStreamer().emitDirectiveSetPush();
4175 return false;
4176}
4177
Toma Tabacu29696502015-06-02 09:48:04 +00004178bool MipsAsmParser::parseSetSoftFloatDirective() {
4179 MCAsmParser &Parser = getParser();
4180 Parser.Lex();
4181 if (getLexer().isNot(AsmToken::EndOfStatement))
4182 return reportParseError("unexpected token, expected end of statement");
4183
4184 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4185 getTargetStreamer().emitDirectiveSetSoftFloat();
4186 return false;
4187}
4188
4189bool MipsAsmParser::parseSetHardFloatDirective() {
4190 MCAsmParser &Parser = getParser();
4191 Parser.Lex();
4192 if (getLexer().isNot(AsmToken::EndOfStatement))
4193 return reportParseError("unexpected token, expected end of statement");
4194
4195 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4196 getTargetStreamer().emitDirectiveSetHardFloat();
4197 return false;
4198}
4199
Jack Carterd76b2372013-03-21 21:44:16 +00004200bool MipsAsmParser::parseSetAssignment() {
4201 StringRef Name;
4202 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004203 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004204
4205 if (Parser.parseIdentifier(Name))
4206 reportParseError("expected identifier after .set");
4207
4208 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004209 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004210 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004211
Jack Carter3b2c96e2014-01-22 23:31:38 +00004212 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004213 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004214
Jim Grosbach6f482002015-05-18 18:43:14 +00004215 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004216 Sym->setVariableValue(Value);
4217
4218 return false;
4219}
Jack Carterd0bd6422013-04-18 00:41:53 +00004220
Toma Tabacu26647792014-09-09 12:52:14 +00004221bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004222 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004223 Parser.Lex();
4224 if (getLexer().isNot(AsmToken::EndOfStatement))
4225 return reportParseError("unexpected token, expected end of statement");
4226
4227 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004228 setAvailableFeatures(
4229 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4230 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004231 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4232
4233 getTargetStreamer().emitDirectiveSetMips0();
4234 return false;
4235}
4236
Toma Tabacu85618b32014-08-19 14:22:52 +00004237bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004238 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004239 Parser.Lex();
4240 if (getLexer().isNot(AsmToken::Equal))
4241 return reportParseError("unexpected token, expected equals sign");
4242
4243 Parser.Lex();
4244 StringRef Arch;
4245 if (Parser.parseIdentifier(Arch))
4246 return reportParseError("expected arch identifier");
4247
4248 StringRef ArchFeatureName =
4249 StringSwitch<StringRef>(Arch)
4250 .Case("mips1", "mips1")
4251 .Case("mips2", "mips2")
4252 .Case("mips3", "mips3")
4253 .Case("mips4", "mips4")
4254 .Case("mips5", "mips5")
4255 .Case("mips32", "mips32")
4256 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004257 .Case("mips32r3", "mips32r3")
4258 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004259 .Case("mips32r6", "mips32r6")
4260 .Case("mips64", "mips64")
4261 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004262 .Case("mips64r3", "mips64r3")
4263 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004264 .Case("mips64r6", "mips64r6")
4265 .Case("cnmips", "cnmips")
4266 .Case("r4000", "mips3") // This is an implementation of Mips3.
4267 .Default("");
4268
4269 if (ArchFeatureName.empty())
4270 return reportParseError("unsupported architecture");
4271
4272 selectArch(ArchFeatureName);
4273 getTargetStreamer().emitDirectiveSetArch(Arch);
4274 return false;
4275}
4276
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004277bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004278 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004279 Parser.Lex();
4280 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004281 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004282
Matheus Almeida2852af82014-04-22 10:15:54 +00004283 switch (Feature) {
4284 default:
4285 llvm_unreachable("Unimplemented feature");
4286 case Mips::FeatureDSP:
4287 setFeatureBits(Mips::FeatureDSP, "dsp");
4288 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004289 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004290 case Mips::FeatureMicroMips:
4291 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004292 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004293 case Mips::FeatureMips1:
4294 selectArch("mips1");
4295 getTargetStreamer().emitDirectiveSetMips1();
4296 break;
4297 case Mips::FeatureMips2:
4298 selectArch("mips2");
4299 getTargetStreamer().emitDirectiveSetMips2();
4300 break;
4301 case Mips::FeatureMips3:
4302 selectArch("mips3");
4303 getTargetStreamer().emitDirectiveSetMips3();
4304 break;
4305 case Mips::FeatureMips4:
4306 selectArch("mips4");
4307 getTargetStreamer().emitDirectiveSetMips4();
4308 break;
4309 case Mips::FeatureMips5:
4310 selectArch("mips5");
4311 getTargetStreamer().emitDirectiveSetMips5();
4312 break;
4313 case Mips::FeatureMips32:
4314 selectArch("mips32");
4315 getTargetStreamer().emitDirectiveSetMips32();
4316 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004317 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004318 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004319 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004320 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004321 case Mips::FeatureMips32r3:
4322 selectArch("mips32r3");
4323 getTargetStreamer().emitDirectiveSetMips32R3();
4324 break;
4325 case Mips::FeatureMips32r5:
4326 selectArch("mips32r5");
4327 getTargetStreamer().emitDirectiveSetMips32R5();
4328 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004329 case Mips::FeatureMips32r6:
4330 selectArch("mips32r6");
4331 getTargetStreamer().emitDirectiveSetMips32R6();
4332 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004333 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004334 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004335 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004336 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004337 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004338 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004339 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004340 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004341 case Mips::FeatureMips64r3:
4342 selectArch("mips64r3");
4343 getTargetStreamer().emitDirectiveSetMips64R3();
4344 break;
4345 case Mips::FeatureMips64r5:
4346 selectArch("mips64r5");
4347 getTargetStreamer().emitDirectiveSetMips64R5();
4348 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004349 case Mips::FeatureMips64r6:
4350 selectArch("mips64r6");
4351 getTargetStreamer().emitDirectiveSetMips64R6();
4352 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004353 }
4354 return false;
4355}
4356
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004357bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004358 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004359 if (getLexer().isNot(AsmToken::Comma)) {
4360 SMLoc Loc = getLexer().getLoc();
4361 Parser.eatToEndOfStatement();
4362 return Error(Loc, ErrorStr);
4363 }
4364
Matheus Almeida2852af82014-04-22 10:15:54 +00004365 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004366 return true;
4367}
4368
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004369bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004370 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004371 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004372
Toma Tabacudde4c462014-11-06 10:02:45 +00004373 if (inMips16Mode()) {
4374 reportParseError(".cpload is not supported in Mips16 mode");
4375 return false;
4376 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004377
David Blaikie960ea3f2014-06-08 16:18:35 +00004378 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004379 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004380 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4381 reportParseError("expected register containing function address");
4382 return false;
4383 }
4384
David Blaikie960ea3f2014-06-08 16:18:35 +00004385 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4386 if (!RegOpnd.isGPRAsmReg()) {
4387 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004388 return false;
4389 }
4390
Toma Tabacudde4c462014-11-06 10:02:45 +00004391 // If this is not the end of the statement, report an error.
4392 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4393 reportParseError("unexpected token, expected end of statement");
4394 return false;
4395 }
4396
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004397 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004398 return false;
4399}
4400
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004401bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004402 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004403 unsigned FuncReg;
4404 unsigned Save;
4405 bool SaveIsReg = true;
4406
Matheus Almeida7e815762014-06-18 13:08:59 +00004407 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004408 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004409 if (ResTy == MatchOperand_NoMatch) {
4410 reportParseError("expected register containing function address");
4411 Parser.eatToEndOfStatement();
4412 return false;
4413 }
4414
4415 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4416 if (!FuncRegOpnd.isGPRAsmReg()) {
4417 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
4418 Parser.eatToEndOfStatement();
4419 return false;
4420 }
4421
4422 FuncReg = FuncRegOpnd.getGPR32Reg();
4423 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004424
Toma Tabacu65f10572014-09-16 15:00:52 +00004425 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004426 return true;
4427
Toma Tabacu13964452014-09-04 13:23:44 +00004428 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004429 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004430 const AsmToken &Tok = Parser.getTok();
4431 if (Tok.is(AsmToken::Integer)) {
4432 Save = Tok.getIntVal();
4433 SaveIsReg = false;
4434 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00004435 } else {
4436 reportParseError("expected save register or stack offset");
4437 Parser.eatToEndOfStatement();
4438 return false;
4439 }
4440 } else {
4441 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4442 if (!SaveOpnd.isGPRAsmReg()) {
4443 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
4444 Parser.eatToEndOfStatement();
4445 return false;
4446 }
4447 Save = SaveOpnd.getGPR32Reg();
4448 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004449
Toma Tabacu65f10572014-09-16 15:00:52 +00004450 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004451 return true;
4452
Toma Tabacu8874eac2015-02-18 13:46:53 +00004453 const MCExpr *Expr;
4454 if (Parser.parseExpression(Expr)) {
4455 reportParseError("expected expression");
4456 return false;
4457 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004458
Toma Tabacu8874eac2015-02-18 13:46:53 +00004459 if (Expr->getKind() != MCExpr::SymbolRef) {
4460 reportParseError("expected symbol");
4461 return false;
4462 }
4463 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
4464
4465 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
4466 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004467 return false;
4468}
4469
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004470bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004471 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004472 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4473 const AsmToken &Tok = Parser.getTok();
4474
4475 if (Tok.getString() == "2008") {
4476 Parser.Lex();
4477 getTargetStreamer().emitDirectiveNaN2008();
4478 return false;
4479 } else if (Tok.getString() == "legacy") {
4480 Parser.Lex();
4481 getTargetStreamer().emitDirectiveNaNLegacy();
4482 return false;
4483 }
4484 }
4485 // If we don't recognize the option passed to the .nan
4486 // directive (e.g. no option or unknown option), emit an error.
4487 reportParseError("invalid option in .nan directive");
4488 return false;
4489}
4490
Jack Carter0b744b32012-10-04 02:29:46 +00004491bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004492 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004493 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00004494 const AsmToken &Tok = Parser.getTok();
4495
4496 if (Tok.getString() == "noat") {
4497 return parseSetNoAtDirective();
4498 } else if (Tok.getString() == "at") {
4499 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00004500 } else if (Tok.getString() == "arch") {
4501 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004502 } else if (Tok.getString() == "fp") {
4503 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004504 } else if (Tok.getString() == "oddspreg") {
4505 return parseSetOddSPRegDirective();
4506 } else if (Tok.getString() == "nooddspreg") {
4507 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004508 } else if (Tok.getString() == "pop") {
4509 return parseSetPopDirective();
4510 } else if (Tok.getString() == "push") {
4511 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00004512 } else if (Tok.getString() == "reorder") {
4513 return parseSetReorderDirective();
4514 } else if (Tok.getString() == "noreorder") {
4515 return parseSetNoReorderDirective();
4516 } else if (Tok.getString() == "macro") {
4517 return parseSetMacroDirective();
4518 } else if (Tok.getString() == "nomacro") {
4519 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00004520 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00004521 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004522 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00004523 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004524 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00004525 getTargetStreamer().emitDirectiveSetNoMicroMips();
4526 Parser.eatToEndOfStatement();
4527 return false;
4528 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004529 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00004530 } else if (Tok.getString() == "mips0") {
4531 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00004532 } else if (Tok.getString() == "mips1") {
4533 return parseSetFeature(Mips::FeatureMips1);
4534 } else if (Tok.getString() == "mips2") {
4535 return parseSetFeature(Mips::FeatureMips2);
4536 } else if (Tok.getString() == "mips3") {
4537 return parseSetFeature(Mips::FeatureMips3);
4538 } else if (Tok.getString() == "mips4") {
4539 return parseSetFeature(Mips::FeatureMips4);
4540 } else if (Tok.getString() == "mips5") {
4541 return parseSetFeature(Mips::FeatureMips5);
4542 } else if (Tok.getString() == "mips32") {
4543 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00004544 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004545 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004546 } else if (Tok.getString() == "mips32r3") {
4547 return parseSetFeature(Mips::FeatureMips32r3);
4548 } else if (Tok.getString() == "mips32r5") {
4549 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004550 } else if (Tok.getString() == "mips32r6") {
4551 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004552 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004553 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004554 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004555 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004556 } else if (Tok.getString() == "mips64r3") {
4557 return parseSetFeature(Mips::FeatureMips64r3);
4558 } else if (Tok.getString() == "mips64r5") {
4559 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004560 } else if (Tok.getString() == "mips64r6") {
4561 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00004562 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004563 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004564 } else if (Tok.getString() == "nodsp") {
4565 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00004566 } else if (Tok.getString() == "msa") {
4567 return parseSetMsaDirective();
4568 } else if (Tok.getString() == "nomsa") {
4569 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00004570 } else if (Tok.getString() == "softfloat") {
4571 return parseSetSoftFloatDirective();
4572 } else if (Tok.getString() == "hardfloat") {
4573 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00004574 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00004575 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00004576 parseSetAssignment();
4577 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004578 }
Jack Carter07c818d2013-01-25 01:31:34 +00004579
Jack Carter0b744b32012-10-04 02:29:46 +00004580 return true;
4581}
4582
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004583/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00004584/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004585bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004586 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004587 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4588 for (;;) {
4589 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004590 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00004591 return true;
4592
4593 getParser().getStreamer().EmitValue(Value, Size);
4594
4595 if (getLexer().is(AsmToken::EndOfStatement))
4596 break;
4597
Jack Carter07c818d2013-01-25 01:31:34 +00004598 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004599 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00004600 Parser.Lex();
4601 }
4602 }
4603
4604 Parser.Lex();
4605 return false;
4606}
4607
Vladimir Medic4c299852013-11-06 11:27:05 +00004608/// parseDirectiveGpWord
4609/// ::= .gpword local_sym
4610bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004611 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004612 const MCExpr *Value;
4613 // EmitGPRel32Value requires an expression, so we are using base class
4614 // method to evaluate the expression.
4615 if (getParser().parseExpression(Value))
4616 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004617 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004618
Vladimir Medice10c1122013-11-13 13:18:04 +00004619 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004620 return Error(getLexer().getLoc(),
4621 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004622 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004623 return false;
4624}
4625
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004626/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004627/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004628bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004629 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004630 const MCExpr *Value;
4631 // EmitGPRel64Value requires an expression, so we are using base class
4632 // method to evaluate the expression.
4633 if (getParser().parseExpression(Value))
4634 return true;
4635 getParser().getStreamer().EmitGPRel64Value(Value);
4636
4637 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004638 return Error(getLexer().getLoc(),
4639 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004640 Parser.Lex(); // Eat EndOfStatement token.
4641 return false;
4642}
4643
Jack Carter0cd3c192014-01-06 23:27:31 +00004644bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004645 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004646 // Get the option token.
4647 AsmToken Tok = Parser.getTok();
4648 // At the moment only identifiers are supported.
4649 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004650 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004651 Parser.eatToEndOfStatement();
4652 return false;
4653 }
4654
4655 StringRef Option = Tok.getIdentifier();
4656
4657 if (Option == "pic0") {
4658 getTargetStreamer().emitDirectiveOptionPic0();
4659 Parser.Lex();
4660 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4661 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004662 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004663 Parser.eatToEndOfStatement();
4664 }
4665 return false;
4666 }
4667
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004668 if (Option == "pic2") {
4669 getTargetStreamer().emitDirectiveOptionPic2();
4670 Parser.Lex();
4671 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4672 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004673 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004674 Parser.eatToEndOfStatement();
4675 }
4676 return false;
4677 }
4678
Jack Carter0cd3c192014-01-06 23:27:31 +00004679 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004680 Warning(Parser.getTok().getLoc(),
4681 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004682 Parser.eatToEndOfStatement();
4683 return false;
4684}
4685
Toma Tabacu9ca50962015-04-16 09:53:47 +00004686/// parseInsnDirective
4687/// ::= .insn
4688bool MipsAsmParser::parseInsnDirective() {
4689 // If this is not the end of the statement, report an error.
4690 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4691 reportParseError("unexpected token, expected end of statement");
4692 return false;
4693 }
4694
4695 // The actual label marking happens in
4696 // MipsELFStreamer::createPendingLabelRelocs().
4697 getTargetStreamer().emitDirectiveInsn();
4698
4699 getParser().Lex(); // Eat EndOfStatement token.
4700 return false;
4701}
4702
Daniel Sanders7e527422014-07-10 13:38:23 +00004703/// parseDirectiveModule
4704/// ::= .module oddspreg
4705/// ::= .module nooddspreg
4706/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00004707/// ::= .module softfloat
4708/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004709bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004710 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004711 MCAsmLexer &Lexer = getLexer();
4712 SMLoc L = Lexer.getLoc();
4713
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004714 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004715 // TODO : get a better message.
4716 reportParseError(".module directive must appear before any code");
4717 return false;
4718 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004719
Toma Tabacuc405c822015-01-23 10:40:19 +00004720 StringRef Option;
4721 if (Parser.parseIdentifier(Option)) {
4722 reportParseError("expected .module option identifier");
4723 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004724 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004725
Toma Tabacuc405c822015-01-23 10:40:19 +00004726 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004727 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00004728
Toma Tabacu3c499582015-06-25 10:56:57 +00004729 // Synchronize the abiflags information with the FeatureBits information we
4730 // changed above.
4731 getTargetStreamer().updateABIInfo(*this);
4732
4733 // If printing assembly, use the recently updated abiflags information.
4734 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4735 // emitted at the end).
4736 getTargetStreamer().emitDirectiveModuleOddSPReg();
4737
Toma Tabacuc405c822015-01-23 10:40:19 +00004738 // If this is not the end of the statement, report an error.
4739 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4740 reportParseError("unexpected token, expected end of statement");
4741 return false;
4742 }
4743
4744 return false; // parseDirectiveModule has finished successfully.
4745 } else if (Option == "nooddspreg") {
4746 if (!isABI_O32()) {
4747 Error(L, "'.module nooddspreg' requires the O32 ABI");
4748 return false;
4749 }
4750
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004751 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00004752
Toma Tabacu3c499582015-06-25 10:56:57 +00004753 // Synchronize the abiflags information with the FeatureBits information we
4754 // changed above.
4755 getTargetStreamer().updateABIInfo(*this);
4756
4757 // If printing assembly, use the recently updated abiflags information.
4758 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4759 // emitted at the end).
4760 getTargetStreamer().emitDirectiveModuleOddSPReg();
4761
Toma Tabacuc405c822015-01-23 10:40:19 +00004762 // If this is not the end of the statement, report an error.
4763 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4764 reportParseError("unexpected token, expected end of statement");
4765 return false;
4766 }
4767
4768 return false; // parseDirectiveModule has finished successfully.
4769 } else if (Option == "fp") {
4770 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00004771 } else if (Option == "softfloat") {
4772 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4773
4774 // Synchronize the ABI Flags information with the FeatureBits information we
4775 // updated above.
4776 getTargetStreamer().updateABIInfo(*this);
4777
4778 // If printing assembly, use the recently updated ABI Flags information.
4779 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4780 // emitted later).
4781 getTargetStreamer().emitDirectiveModuleSoftFloat();
4782
4783 // If this is not the end of the statement, report an error.
4784 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4785 reportParseError("unexpected token, expected end of statement");
4786 return false;
4787 }
4788
4789 return false; // parseDirectiveModule has finished successfully.
4790 } else if (Option == "hardfloat") {
4791 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4792
4793 // Synchronize the ABI Flags information with the FeatureBits information we
4794 // updated above.
4795 getTargetStreamer().updateABIInfo(*this);
4796
4797 // If printing assembly, use the recently updated ABI Flags information.
4798 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4799 // emitted later).
4800 getTargetStreamer().emitDirectiveModuleHardFloat();
4801
4802 // If this is not the end of the statement, report an error.
4803 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4804 reportParseError("unexpected token, expected end of statement");
4805 return false;
4806 }
4807
4808 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00004809 } else {
4810 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4811 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004812}
4813
4814/// parseDirectiveModuleFP
4815/// ::= =32
4816/// ::= =xx
4817/// ::= =64
4818bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004819 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004820 MCAsmLexer &Lexer = getLexer();
4821
4822 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004823 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004824 return false;
4825 }
4826 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004827
Daniel Sanders7e527422014-07-10 13:38:23 +00004828 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004829 if (!parseFpABIValue(FpABI, ".module"))
4830 return false;
4831
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004832 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004833 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004834 return false;
4835 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004836
Toma Tabacua64e5402015-06-25 12:44:38 +00004837 // Synchronize the abiflags information with the FeatureBits information we
4838 // changed above.
4839 getTargetStreamer().updateABIInfo(*this);
4840
4841 // If printing assembly, use the recently updated abiflags information.
4842 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4843 // emitted at the end).
4844 getTargetStreamer().emitDirectiveModuleFP();
4845
Daniel Sanders7e527422014-07-10 13:38:23 +00004846 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004847 return false;
4848}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004849
Daniel Sanders7e527422014-07-10 13:38:23 +00004850bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004851 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004852 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004853 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004854 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004855
4856 if (Lexer.is(AsmToken::Identifier)) {
4857 StringRef Value = Parser.getTok().getString();
4858 Parser.Lex();
4859
4860 if (Value != "xx") {
4861 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4862 return false;
4863 }
4864
4865 if (!isABI_O32()) {
4866 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4867 return false;
4868 }
4869
Daniel Sanders7e527422014-07-10 13:38:23 +00004870 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004871 if (ModuleLevelOptions) {
4872 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
4873 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
4874 } else {
4875 setFeatureBits(Mips::FeatureFPXX, "fpxx");
4876 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
4877 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004878 return true;
4879 }
4880
4881 if (Lexer.is(AsmToken::Integer)) {
4882 unsigned Value = Parser.getTok().getIntVal();
4883 Parser.Lex();
4884
4885 if (Value != 32 && Value != 64) {
4886 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4887 return false;
4888 }
4889
4890 if (Value == 32) {
4891 if (!isABI_O32()) {
4892 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4893 return false;
4894 }
4895
Daniel Sanders7e527422014-07-10 13:38:23 +00004896 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004897 if (ModuleLevelOptions) {
4898 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
4899 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
4900 } else {
4901 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
4902 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
4903 }
Toma Tabacua64e5402015-06-25 12:44:38 +00004904 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00004905 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004906 if (ModuleLevelOptions) {
4907 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
4908 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
4909 } else {
4910 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
4911 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
4912 }
Toma Tabacua64e5402015-06-25 12:44:38 +00004913 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004914
Daniel Sanders7e527422014-07-10 13:38:23 +00004915 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004916 }
4917
4918 return false;
4919}
4920
Jack Carter0b744b32012-10-04 02:29:46 +00004921bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004922 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004923 StringRef IDVal = DirectiveID.getString();
4924
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004925 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004926 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004927 if (IDVal == ".dword") {
4928 parseDataDirective(8, DirectiveID.getLoc());
4929 return false;
4930 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004931 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004932 StringRef SymbolName;
4933
4934 if (Parser.parseIdentifier(SymbolName)) {
4935 reportParseError("expected identifier after .ent");
4936 return false;
4937 }
4938
4939 // There's an undocumented extension that allows an integer to
4940 // follow the name of the procedure which AFAICS is ignored by GAS.
4941 // Example: .ent foo,2
4942 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4943 if (getLexer().isNot(AsmToken::Comma)) {
4944 // Even though we accept this undocumented extension for compatibility
4945 // reasons, the additional integer argument does not actually change
4946 // the behaviour of the '.ent' directive, so we would like to discourage
4947 // its use. We do this by not referring to the extended version in
4948 // error messages which are not directly related to its use.
4949 reportParseError("unexpected token, expected end of statement");
4950 return false;
4951 }
4952 Parser.Lex(); // Eat the comma.
4953 const MCExpr *DummyNumber;
4954 int64_t DummyNumberVal;
4955 // If the user was explicitly trying to use the extended version,
4956 // we still give helpful extension-related error messages.
4957 if (Parser.parseExpression(DummyNumber)) {
4958 reportParseError("expected number after comma");
4959 return false;
4960 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004961 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004962 reportParseError("expected an absolute expression after comma");
4963 return false;
4964 }
4965 }
4966
4967 // If this is not the end of the statement, report an error.
4968 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4969 reportParseError("unexpected token, expected end of statement");
4970 return false;
4971 }
4972
Jim Grosbach6f482002015-05-18 18:43:14 +00004973 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004974
4975 getTargetStreamer().emitDirectiveEnt(*Sym);
4976 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004977 return false;
4978 }
4979
Jack Carter07c818d2013-01-25 01:31:34 +00004980 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004981 StringRef SymbolName;
4982
4983 if (Parser.parseIdentifier(SymbolName)) {
4984 reportParseError("expected identifier after .end");
4985 return false;
4986 }
4987
4988 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4989 reportParseError("unexpected token, expected end of statement");
4990 return false;
4991 }
4992
4993 if (CurrentFn == nullptr) {
4994 reportParseError(".end used without .ent");
4995 return false;
4996 }
4997
4998 if ((SymbolName != CurrentFn->getName())) {
4999 reportParseError(".end symbol does not match .ent symbol");
5000 return false;
5001 }
5002
5003 getTargetStreamer().emitDirectiveEnd(SymbolName);
5004 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00005005 return false;
5006 }
5007
Jack Carter07c818d2013-01-25 01:31:34 +00005008 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005009 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5010 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005011 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005012 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5013 reportParseError("expected stack register");
5014 return false;
5015 }
5016
5017 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5018 if (!StackRegOpnd.isGPRAsmReg()) {
5019 reportParseError(StackRegOpnd.getStartLoc(),
5020 "expected general purpose register");
5021 return false;
5022 }
5023 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5024
5025 if (Parser.getTok().is(AsmToken::Comma))
5026 Parser.Lex();
5027 else {
5028 reportParseError("unexpected token, expected comma");
5029 return false;
5030 }
5031
5032 // Parse the frame size.
5033 const MCExpr *FrameSize;
5034 int64_t FrameSizeVal;
5035
5036 if (Parser.parseExpression(FrameSize)) {
5037 reportParseError("expected frame size value");
5038 return false;
5039 }
5040
Jim Grosbach13760bd2015-05-30 01:25:56 +00005041 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005042 reportParseError("frame size not an absolute expression");
5043 return false;
5044 }
5045
5046 if (Parser.getTok().is(AsmToken::Comma))
5047 Parser.Lex();
5048 else {
5049 reportParseError("unexpected token, expected comma");
5050 return false;
5051 }
5052
5053 // Parse the return register.
5054 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005055 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005056 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5057 reportParseError("expected return register");
5058 return false;
5059 }
5060
5061 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5062 if (!ReturnRegOpnd.isGPRAsmReg()) {
5063 reportParseError(ReturnRegOpnd.getStartLoc(),
5064 "expected general purpose register");
5065 return false;
5066 }
5067
5068 // If this is not the end of the statement, report an error.
5069 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5070 reportParseError("unexpected token, expected end of statement");
5071 return false;
5072 }
5073
5074 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5075 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00005076 return false;
5077 }
5078
Jack Carter07c818d2013-01-25 01:31:34 +00005079 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005080 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005081 }
5082
Daniel Sandersd97a6342014-08-13 10:07:34 +00005083 if (IDVal == ".mask" || IDVal == ".fmask") {
5084 // .mask bitmask, frame_offset
5085 // bitmask: One bit for each register used.
5086 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5087 // first register is expected to be saved.
5088 // Examples:
5089 // .mask 0x80000000, -4
5090 // .fmask 0x80000000, -4
5091 //
Jack Carterbe332172012-09-07 00:48:02 +00005092
Daniel Sandersd97a6342014-08-13 10:07:34 +00005093 // Parse the bitmask
5094 const MCExpr *BitMask;
5095 int64_t BitMaskVal;
5096
5097 if (Parser.parseExpression(BitMask)) {
5098 reportParseError("expected bitmask value");
5099 return false;
5100 }
5101
Jim Grosbach13760bd2015-05-30 01:25:56 +00005102 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005103 reportParseError("bitmask not an absolute expression");
5104 return false;
5105 }
5106
5107 if (Parser.getTok().is(AsmToken::Comma))
5108 Parser.Lex();
5109 else {
5110 reportParseError("unexpected token, expected comma");
5111 return false;
5112 }
5113
5114 // Parse the frame_offset
5115 const MCExpr *FrameOffset;
5116 int64_t FrameOffsetVal;
5117
5118 if (Parser.parseExpression(FrameOffset)) {
5119 reportParseError("expected frame offset value");
5120 return false;
5121 }
5122
Jim Grosbach13760bd2015-05-30 01:25:56 +00005123 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005124 reportParseError("frame offset not an absolute expression");
5125 return false;
5126 }
5127
5128 // If this is not the end of the statement, report an error.
5129 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5130 reportParseError("unexpected token, expected end of statement");
5131 return false;
5132 }
5133
5134 if (IDVal == ".mask")
5135 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5136 else
5137 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005138 return false;
5139 }
5140
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005141 if (IDVal == ".nan")
5142 return parseDirectiveNaN();
5143
Jack Carter07c818d2013-01-25 01:31:34 +00005144 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005145 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005146 return false;
5147 }
5148
Rafael Espindolab59fb732014-03-28 18:50:26 +00005149 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005150 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005151 return false;
5152 }
5153
Jack Carter07c818d2013-01-25 01:31:34 +00005154 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005155 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005156 return false;
5157 }
5158
Jack Carter0cd3c192014-01-06 23:27:31 +00005159 if (IDVal == ".option")
5160 return parseDirectiveOption();
5161
5162 if (IDVal == ".abicalls") {
5163 getTargetStreamer().emitDirectiveAbiCalls();
5164 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005165 Error(Parser.getTok().getLoc(),
5166 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005167 // Clear line
5168 Parser.eatToEndOfStatement();
5169 }
5170 return false;
5171 }
5172
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005173 if (IDVal == ".cpsetup")
5174 return parseDirectiveCPSetup();
5175
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005176 if (IDVal == ".module")
5177 return parseDirectiveModule();
5178
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005179 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5180 return parseInternalDirectiveReallowModule();
5181
Toma Tabacu9ca50962015-04-16 09:53:47 +00005182 if (IDVal == ".insn")
5183 return parseInsnDirective();
5184
Rafael Espindola870c4e92012-01-11 03:56:41 +00005185 return true;
5186}
5187
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005188bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5189 // If this is not the end of the statement, report an error.
5190 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5191 reportParseError("unexpected token, expected end of statement");
5192 return false;
5193 }
5194
5195 getTargetStreamer().reallowModuleDirective();
5196
5197 getParser().Lex(); // Eat EndOfStatement token.
5198 return false;
5199}
5200
Rafael Espindola870c4e92012-01-11 03:56:41 +00005201extern "C" void LLVMInitializeMipsAsmParser() {
5202 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5203 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5204 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5205 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5206}
Jack Carterb4dbc172012-09-05 23:34:03 +00005207
5208#define GET_REGISTER_MATCHER
5209#define GET_MATCHER_IMPLEMENTATION
5210#include "MipsGenAsmMatcher.inc"