blob: 13e80707da22b37a1386a830fa787e77ce49f096 [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"
Daniel Sandersa6994442015-08-18 12:33:54 +000014#include "MipsTargetObjectFile.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Hrvoje Vargadbe4d962016-09-08 07:41:43 +000016#include "MCTargetDesc/MipsBaseInfo.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000017#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000022#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000023#include "llvm/MC/MCParser/MCAsmLexer.h"
24#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000025#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000026#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000027#include "llvm/MC/MCStreamer.h"
28#include "llvm/MC/MCSubtargetInfo.h"
29#include "llvm/MC/MCSymbol.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000030#include "llvm/Support/Debug.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000031#include "llvm/Support/ELF.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000032#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000033#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000034#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000035#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000036#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000037
38using namespace llvm;
39
Chandler Carruthe96dd892014-04-21 22:55:11 +000040#define DEBUG_TYPE "mips-asm-parser"
41
Joey Gouly0e76fa72013-09-12 10:28:05 +000042namespace llvm {
43class MCInstrInfo;
44}
45
Rafael Espindola870c4e92012-01-11 03:56:41 +000046namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000047class MipsAssemblerOptions {
48public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000049 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000050 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000051
Toma Tabacu9db22db2014-09-09 10:15:38 +000052 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000053 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000054 Reorder = Opts->isReorder();
55 Macro = Opts->isMacro();
56 Features = Opts->getFeatures();
57 }
58
Toma Tabacub19cf202015-04-27 13:12:59 +000059 unsigned getATRegIndex() const { return ATReg; }
60 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000061 if (Reg > 31)
62 return false;
63
64 ATReg = Reg;
65 return true;
66 }
Jack Carter0b744b32012-10-04 02:29:46 +000067
Toma Tabacu9db22db2014-09-09 10:15:38 +000068 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000069 void setReorder() { Reorder = true; }
70 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000071
Toma Tabacu9db22db2014-09-09 10:15:38 +000072 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000073 void setMacro() { Macro = true; }
74 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000075
Toma Tabacu465acfd2015-06-09 13:33:26 +000076 const FeatureBitset &getFeatures() const { return Features; }
77 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000078
Daniel Sandersf0df2212014-08-04 12:20:00 +000079 // Set of features that are either architecture features or referenced
80 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
81 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
82 // The reason we need this mask is explained in the selectArch function.
83 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000084 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000085
Jack Carter0b744b32012-10-04 02:29:46 +000086private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000087 unsigned ATReg;
88 bool Reorder;
89 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000090 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000091};
92}
93
Michael Kupersteindb0712f2015-05-26 10:47:10 +000094const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
95 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
96 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
97 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
98 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
99 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
100 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
101 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
102 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
103};
104
Jack Carter0b744b32012-10-04 02:29:46 +0000105namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000106class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000107 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000108 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000109 return static_cast<MipsTargetStreamer &>(TS);
110 }
111
Eric Christophera5762812015-01-26 17:33:46 +0000112 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000113 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000114 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
115 // nullptr, which indicates that no function is currently
116 // selected. This usually happens after an '.end func'
117 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000118 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000119 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000120 bool IsCpRestoreSet;
121 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000122 unsigned CpSaveLocation;
123 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
124 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000125
Daniel Sandersef638fe2014-10-03 15:37:37 +0000126 // Print a warning along with its fix-it message at the given range.
127 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
128 SMRange Range, bool ShowColors = true);
129
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000130#define GET_ASSEMBLER_HEADER
131#include "MipsGenAsmMatcher.inc"
132
Daniel Sandersc5537422016-07-27 13:49:44 +0000133 unsigned
134 checkEarlyTargetMatchPredicate(MCInst &Inst,
135 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000136 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
137
Chad Rosier49963552012-10-13 00:26:04 +0000138 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000139 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000140 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000141 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000142
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000143 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000144 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000145
Toma Tabacu13964452014-09-04 13:23:44 +0000146 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000147
Toma Tabacu13964452014-09-04 13:23:44 +0000148 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000149
David Blaikie960ea3f2014-06-08 16:18:35 +0000150 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
151 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000152
Craig Topper56c590a2014-04-29 07:58:02 +0000153 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000154
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000155 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
156 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000157 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000158 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000159 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
160 SMLoc S);
161 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
162 OperandMatchResultTy parseImm(OperandVector &Operands);
163 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
164 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000165 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
166 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
167 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000168
David Blaikie960ea3f2014-06-08 16:18:35 +0000169 bool searchSymbolAlias(OperandVector &Operands);
170
Toma Tabacu13964452014-09-04 13:23:44 +0000171 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000172
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000173 enum MacroExpanderResultTy {
174 MER_NotAMacro,
175 MER_Success,
176 MER_Fail,
177 };
Jack Carter30a59822012-10-04 04:03:53 +0000178
Matheus Almeida3813d572014-06-19 14:39:14 +0000179 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000180 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
181 MCStreamer &Out,
182 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000183
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000184 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
185 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000186
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000187 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000188 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000189 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000190
Toma Tabacuf712ede2015-06-17 14:31:51 +0000191 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
192 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000193 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000194
Toma Tabacu00e98672015-05-01 12:19:27 +0000195 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000196 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000197
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000198 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
199 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000200 SMLoc IDLoc, MCStreamer &Out,
201 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000202
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000203 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
204 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000205
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000206 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000207 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
208
209 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
210 const MCSubtargetInfo *STI, bool IsImmOpnd);
211
212 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
213 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000214
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000215 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
216 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000217
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
219 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000220
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000221 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
222 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000223
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000224 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
225 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000226
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000227 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
228 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000229 const bool Signed);
230
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000231 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000232 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000233
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000234 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000236
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000237 bool expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
238 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000239
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000240 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000241 MCStreamer &Out, const MCSubtargetInfo *STI);
242 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
243 const MCSubtargetInfo *STI);
244 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
245 const MCSubtargetInfo *STI);
246 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000248
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000249 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
250 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000251
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000252 bool reportParseError(Twine ErrorMsg);
253 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000254
Jack Carterb5cf5902013-04-17 00:18:04 +0000255 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000256
257 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000258 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000259 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000260 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000261 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000262 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000263 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000264 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000265 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000266 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000267 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000268 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000269 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000270 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000271
272 bool parseSetAtDirective();
273 bool parseSetNoAtDirective();
274 bool parseSetMacroDirective();
275 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000276 bool parseSetMsaDirective();
277 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000278 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000279 bool parseSetReorderDirective();
280 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000281 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000282 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000283 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000284 bool parseSetOddSPRegDirective();
285 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000286 bool parseSetPopDirective();
287 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000288 bool parseSetSoftFloatDirective();
289 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000290
Jack Carterd76b2372013-03-21 21:44:16 +0000291 bool parseSetAssignment();
292
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000293 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000294 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000295 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000296 bool parseDirectiveDtpRelWord();
297 bool parseDirectiveDtpRelDWord();
298 bool parseDirectiveTpRelWord();
299 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000300 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000301 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000302 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
303 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000304
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000305 bool parseInternalDirectiveReallowModule();
306
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000307 bool eatComma(StringRef ErrorStr);
308
Jack Carter1ac53222013-02-20 23:11:17 +0000309 int matchCPURegisterName(StringRef Symbol);
310
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000311 int matchHWRegsRegisterName(StringRef Symbol);
312
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000313 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000314
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000315 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000316
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000317 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000318
Jack Carter5dc8ac92013-09-25 23:50:44 +0000319 int matchMSA128RegisterName(StringRef Name);
320
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000321 int matchMSA128CtrlRegisterName(StringRef Name);
322
Jack Carterd0bd6422013-04-18 00:41:53 +0000323 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000324
Toma Tabacu89a712b2015-04-15 10:48:56 +0000325 /// Returns the internal register number for the current AT. Also checks if
326 /// the current AT is unavailable (set to $0) and gives an error if it is.
327 /// This should be used in pseudo-instruction expansions which need AT.
328 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000329
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000330 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
331 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000332
333 // Helper function that checks if the value of a vector index is within the
334 // boundaries of accepted values for each RegisterKind
335 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
336 bool validateMSAIndex(int Val, int RegKind);
337
Daniel Sandersf0df2212014-08-04 12:20:00 +0000338 // Selects a new architecture by updating the FeatureBits with the necessary
339 // info including implied dependencies.
340 // Internally, it clears all the feature bits related to *any* architecture
341 // and selects the new one using the ToggleFeature functionality of the
342 // MCSubtargetInfo object that handles implied dependencies. The reason we
343 // clear all the arch related bits manually is because ToggleFeature only
344 // clears the features that imply the feature being cleared and not the
345 // features implied by the feature being cleared. This is easier to see
346 // with an example:
347 // --------------------------------------------------
348 // | Feature | Implies |
349 // | -------------------------------------------------|
350 // | FeatureMips1 | None |
351 // | FeatureMips2 | FeatureMips1 |
352 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
353 // | FeatureMips4 | FeatureMips3 |
354 // | ... | |
355 // --------------------------------------------------
356 //
357 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
358 // FeatureMipsGP64 | FeatureMips1)
359 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
360 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000361 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000362 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000363 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
364 STI.setFeatureBits(FeatureBits);
365 setAvailableFeatures(
366 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000367 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000368 }
369
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000370 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000371 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000372 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000373 setAvailableFeatures(
374 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000375 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000376 }
377 }
378
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000379 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000380 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000381 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000382 setAvailableFeatures(
383 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000384 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000385 }
386 }
387
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000388 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
389 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000390 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000391 }
392
393 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
394 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000395 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000396 }
397
Rafael Espindola870c4e92012-01-11 03:56:41 +0000398public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000399 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000400 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000401 Match_RequiresDifferentOperands,
402 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000403 Match_RequiresSameSrcAndDst,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000404#define GET_OPERAND_DIAGNOSTIC_TYPES
405#include "MipsGenAsmMatcher.inc"
406#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000407 };
408
Akira Hatanakab11ef082015-11-14 06:35:56 +0000409 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000410 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000411 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000412 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
413 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000414 MCAsmParserExtension::Initialize(parser);
415
Toma Tabacu11e14a92015-04-21 11:50:52 +0000416 parser.addAliasForDirective(".asciiz", ".asciz");
417
Jack Carterb4dbc172012-09-05 23:34:03 +0000418 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000419 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000420
Toma Tabacu9db22db2014-09-09 10:15:38 +0000421 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000422 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000423 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000424
Toma Tabacu9db22db2014-09-09 10:15:38 +0000425 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000426 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000427 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000428
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000429 getTargetStreamer().updateABIInfo(*this);
430
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000431 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000432 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000433
434 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000435
Rafael Espindola699281c2016-05-18 11:58:50 +0000436 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000437
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000438 IsCpRestoreSet = false;
439 CpRestoreOffset = -1;
440
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000441 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000442 if ((TheTriple.getArch() == Triple::mips) ||
443 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000444 IsLittleEndian = false;
445 else
446 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000447 }
448
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000449 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
450 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
451
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000452 bool isGP64bit() const {
453 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
454 }
455 bool isFP64bit() const {
456 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
457 }
Eric Christophera5762812015-01-26 17:33:46 +0000458 const MipsABIInfo &getABI() const { return ABI; }
459 bool isABI_N32() const { return ABI.IsN32(); }
460 bool isABI_N64() const { return ABI.IsN64(); }
461 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000462 bool isABI_FPXX() const {
463 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
464 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000465
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000466 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000467 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000468 }
469
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000470 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000471 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000472 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000473 bool hasMips1() const {
474 return getSTI().getFeatureBits()[Mips::FeatureMips1];
475 }
476 bool hasMips2() const {
477 return getSTI().getFeatureBits()[Mips::FeatureMips2];
478 }
479 bool hasMips3() const {
480 return getSTI().getFeatureBits()[Mips::FeatureMips3];
481 }
482 bool hasMips4() const {
483 return getSTI().getFeatureBits()[Mips::FeatureMips4];
484 }
485 bool hasMips5() const {
486 return getSTI().getFeatureBits()[Mips::FeatureMips5];
487 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000488 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000489 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000490 }
491 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000492 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000493 }
494 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000495 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000496 }
497 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000498 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000499 }
Daniel Sanders17793142015-02-18 16:24:50 +0000500 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000501 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000502 }
503 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000504 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000505 }
506 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000507 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000508 }
509 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000510 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000511 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000512 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000513 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000514 }
515 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000516 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000517 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000518
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000519 bool hasDSP() const {
520 return getSTI().getFeatureBits()[Mips::FeatureDSP];
521 }
522 bool hasDSPR2() const {
523 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
524 }
525 bool hasDSPR3() const {
526 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
527 }
528 bool hasMSA() const {
529 return getSTI().getFeatureBits()[Mips::FeatureMSA];
530 }
Kai Nackee0245392015-01-27 19:11:28 +0000531 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000532 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000533 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000534
Daniel Sandersa6994442015-08-18 12:33:54 +0000535 bool inPicMode() {
536 return IsPicEnabled;
537 }
538
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000539 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000540 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000541 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000542
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000543 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000545 }
546
Eric Christophere8ae3e32015-05-07 23:10:21 +0000547 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000548 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000549 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000550
Toma Tabacud9d344b2015-04-27 14:05:04 +0000551 /// Warn if RegIndex is the same as the current AT.
552 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000553
554 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000555
556 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000557
558 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
559 AsmToken::TokenKind OperatorToken,
560 MCContext &Ctx) override {
561 switch(OperatorToken) {
562 default:
563 llvm_unreachable("Unknown token");
564 return nullptr;
565 case AsmToken::PercentCall16:
566 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
567 case AsmToken::PercentCall_Hi:
568 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
569 case AsmToken::PercentCall_Lo:
570 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
571 case AsmToken::PercentDtprel_Hi:
572 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
573 case AsmToken::PercentDtprel_Lo:
574 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
575 case AsmToken::PercentGot:
576 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
577 case AsmToken::PercentGot_Disp:
578 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
579 case AsmToken::PercentGot_Hi:
580 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
581 case AsmToken::PercentGot_Lo:
582 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
583 case AsmToken::PercentGot_Ofst:
584 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
585 case AsmToken::PercentGot_Page:
586 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
587 case AsmToken::PercentGottprel:
588 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
589 case AsmToken::PercentGp_Rel:
590 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
591 case AsmToken::PercentHi:
592 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
593 case AsmToken::PercentHigher:
594 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
595 case AsmToken::PercentHighest:
596 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
597 case AsmToken::PercentLo:
598 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
599 case AsmToken::PercentNeg:
600 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
601 case AsmToken::PercentPcrel_Hi:
602 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
603 case AsmToken::PercentPcrel_Lo:
604 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
605 case AsmToken::PercentTlsgd:
606 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
607 case AsmToken::PercentTlsldm:
608 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
609 case AsmToken::PercentTprel_Hi:
610 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
611 case AsmToken::PercentTprel_Lo:
612 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
613 }
614 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000615};
616}
617
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000618namespace {
619
620/// MipsOperand - Instances of this class represent a parsed Mips machine
621/// instruction.
622class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000623public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000624 /// Broad categories of register classes
625 /// The exact class is finalized by the render method.
626 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000627 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000628 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000629 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000630 RegKind_FCC = 4, /// FCC
631 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
632 RegKind_MSACtrl = 16, /// MSA control registers
633 RegKind_COP2 = 32, /// COP2
634 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
635 /// context).
636 RegKind_CCR = 128, /// CCR
637 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000638 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000639 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000640 /// Potentially any (e.g. $1)
641 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
642 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000643 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000644 };
645
646private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000647 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000648 k_Immediate, /// An immediate (possibly involving symbol references)
649 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000650 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000651 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000652 k_RegList, /// A physical register list
653 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000654 } Kind;
655
David Blaikie960ea3f2014-06-08 16:18:35 +0000656public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000657 MipsOperand(KindTy K, MipsAsmParser &Parser)
658 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
659
David Blaikie960ea3f2014-06-08 16:18:35 +0000660private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000661 /// For diagnostics, and checking the assembler temporary
662 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000663
Eric Christopher8996c5d2013-03-15 00:42:55 +0000664 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000665 const char *Data;
666 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000667 };
668
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000669 struct RegIdxOp {
670 unsigned Index; /// Index into the register class
671 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000672 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000673 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000674 };
675
676 struct ImmOp {
677 const MCExpr *Val;
678 };
679
680 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000681 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000682 const MCExpr *Off;
683 };
684
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000685 struct RegListOp {
686 SmallVector<unsigned, 10> *List;
687 };
688
Jack Carterb4dbc172012-09-05 23:34:03 +0000689 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000690 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000691 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000692 struct ImmOp Imm;
693 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000694 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000695 };
696
697 SMLoc StartLoc, EndLoc;
698
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000699 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000700 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
701 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000702 const MCRegisterInfo *RegInfo,
703 SMLoc S, SMLoc E,
704 MipsAsmParser &Parser) {
705 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000706 Op->RegIdx.Index = Index;
707 Op->RegIdx.RegInfo = RegInfo;
708 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000709 Op->RegIdx.Tok.Data = Str.data();
710 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000711 Op->StartLoc = S;
712 Op->EndLoc = E;
713 return Op;
714 }
715
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000716public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000717 /// Coerce the register to GPR32 and return the real register for the current
718 /// target.
719 unsigned getGPR32Reg() const {
720 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000721 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000722 unsigned ClassID = Mips::GPR32RegClassID;
723 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000724 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000725
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000726 /// Coerce the register to GPR32 and return the real register for the current
727 /// target.
728 unsigned getGPRMM16Reg() const {
729 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
730 unsigned ClassID = Mips::GPR32RegClassID;
731 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
732 }
733
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000734 /// Coerce the register to GPR64 and return the real register for the current
735 /// target.
736 unsigned getGPR64Reg() const {
737 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
738 unsigned ClassID = Mips::GPR64RegClassID;
739 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000740 }
741
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000742private:
743 /// Coerce the register to AFGR64 and return the real register for the current
744 /// target.
745 unsigned getAFGR64Reg() const {
746 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
747 if (RegIdx.Index % 2 != 0)
748 AsmParser.Warning(StartLoc, "Float register should be even.");
749 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
750 .getRegister(RegIdx.Index / 2);
751 }
752
753 /// Coerce the register to FGR64 and return the real register for the current
754 /// target.
755 unsigned getFGR64Reg() const {
756 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
757 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
758 .getRegister(RegIdx.Index);
759 }
760
761 /// Coerce the register to FGR32 and return the real register for the current
762 /// target.
763 unsigned getFGR32Reg() const {
764 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
765 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
766 .getRegister(RegIdx.Index);
767 }
768
769 /// Coerce the register to FGRH32 and return the real register for the current
770 /// target.
771 unsigned getFGRH32Reg() const {
772 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
773 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
774 .getRegister(RegIdx.Index);
775 }
776
777 /// Coerce the register to FCC and return the real register for the current
778 /// target.
779 unsigned getFCCReg() const {
780 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
781 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
782 .getRegister(RegIdx.Index);
783 }
784
785 /// Coerce the register to MSA128 and return the real register for the current
786 /// target.
787 unsigned getMSA128Reg() const {
788 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
789 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
790 // identical
791 unsigned ClassID = Mips::MSA128BRegClassID;
792 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
793 }
794
795 /// Coerce the register to MSACtrl and return the real register for the
796 /// current target.
797 unsigned getMSACtrlReg() const {
798 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
799 unsigned ClassID = Mips::MSACtrlRegClassID;
800 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
801 }
802
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000803 /// Coerce the register to COP0 and return the real register for the
804 /// current target.
805 unsigned getCOP0Reg() const {
806 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
807 unsigned ClassID = Mips::COP0RegClassID;
808 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
809 }
810
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000811 /// Coerce the register to COP2 and return the real register for the
812 /// current target.
813 unsigned getCOP2Reg() const {
814 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
815 unsigned ClassID = Mips::COP2RegClassID;
816 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
817 }
818
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000819 /// Coerce the register to COP3 and return the real register for the
820 /// current target.
821 unsigned getCOP3Reg() const {
822 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
823 unsigned ClassID = Mips::COP3RegClassID;
824 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
825 }
826
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000827 /// Coerce the register to ACC64DSP and return the real register for the
828 /// current target.
829 unsigned getACC64DSPReg() const {
830 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
831 unsigned ClassID = Mips::ACC64DSPRegClassID;
832 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
833 }
834
835 /// Coerce the register to HI32DSP and return the real register for the
836 /// current target.
837 unsigned getHI32DSPReg() const {
838 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
839 unsigned ClassID = Mips::HI32DSPRegClassID;
840 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
841 }
842
843 /// Coerce the register to LO32DSP and return the real register for the
844 /// current target.
845 unsigned getLO32DSPReg() const {
846 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
847 unsigned ClassID = Mips::LO32DSPRegClassID;
848 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
849 }
850
851 /// Coerce the register to CCR and return the real register for the
852 /// current target.
853 unsigned getCCRReg() const {
854 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
855 unsigned ClassID = Mips::CCRRegClassID;
856 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
857 }
858
859 /// Coerce the register to HWRegs and return the real register for the
860 /// current target.
861 unsigned getHWRegsReg() const {
862 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
863 unsigned ClassID = Mips::HWRegsRegClassID;
864 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
865 }
866
867public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000868 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000869 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000870 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000871 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000872 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000873 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000874 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000875 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000876 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000877
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000878 void addRegOperands(MCInst &Inst, unsigned N) const {
879 llvm_unreachable("Use a custom parser instead");
880 }
881
Daniel Sanders21bce302014-04-01 12:35:23 +0000882 /// Render the operand to an MCInst as a GPR32
883 /// Asserts if the wrong number of operands are requested, or the operand
884 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000885 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
886 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000887 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000888 }
889
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000890 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
891 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000892 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000893 }
894
Jozef Kolek1904fa22014-11-24 14:25:53 +0000895 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
896 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000897 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000898 }
899
Zoran Jovanovic41688672015-02-10 16:36:20 +0000900 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
901 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000902 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000903 }
904
Daniel Sanders21bce302014-04-01 12:35:23 +0000905 /// Render the operand to an MCInst as a GPR64
906 /// Asserts if the wrong number of operands are requested, or the operand
907 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000908 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
909 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000910 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000911 }
912
913 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
914 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000915 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000916 }
917
918 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
919 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000920 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000921 }
922
923 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
924 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000925 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000926 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +0000927 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000928 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +0000929 AsmParser.getParser().printError(
930 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
931 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000932 }
933
934 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
935 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000936 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000937 }
938
939 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
940 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000941 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000942 }
943
944 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
945 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000946 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000947 }
948
949 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
950 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000951 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000952 }
953
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000954 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
955 assert(N == 1 && "Invalid number of operands!");
956 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
957 }
958
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000959 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
960 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000961 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000962 }
963
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000964 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
965 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000966 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000967 }
968
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000969 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
970 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000971 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000972 }
973
974 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
975 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000976 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000977 }
978
979 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
980 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000981 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000982 }
983
984 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
985 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000986 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000987 }
988
989 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
990 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000991 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000992 }
993
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000994 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000995 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
996 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000997 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +0000998 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +0000999 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001000 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001001 Inst.addOperand(MCOperand::createImm(Imm));
1002 }
1003
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001004 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001005 void addSImmOperands(MCInst &Inst, unsigned N) const {
1006 if (isImm() && !isConstantImm()) {
1007 addExpr(Inst, getImm());
1008 return;
1009 }
1010 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1011 }
1012
1013 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001014 void addUImmOperands(MCInst &Inst, unsigned N) const {
1015 if (isImm() && !isConstantImm()) {
1016 addExpr(Inst, getImm());
1017 return;
1018 }
1019 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1020 }
1021
Daniel Sanders78e89022016-03-11 11:37:50 +00001022 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1023 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1024 assert(N == 1 && "Invalid number of operands!");
1025 int64_t Imm = getConstantImm() - Offset;
1026 Imm = SignExtend64<Bits>(Imm);
1027 Imm += Offset;
1028 Imm += AdjustOffset;
1029 Inst.addOperand(MCOperand::createImm(Imm));
1030 }
1031
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001032 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001033 assert(N == 1 && "Invalid number of operands!");
1034 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001035 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001036 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001037
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001038 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001039 assert(N == 2 && "Invalid number of operands!");
1040
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001041 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1042 ? getMemBase()->getGPR64Reg()
1043 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001044
1045 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001046 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001047 }
1048
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001049 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1050 assert(N == 2 && "Invalid number of operands!");
1051
Jim Grosbache9119e42015-05-13 18:37:00 +00001052 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001053
1054 const MCExpr *Expr = getMemOff();
1055 addExpr(Inst, Expr);
1056 }
1057
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001058 void addRegListOperands(MCInst &Inst, unsigned N) const {
1059 assert(N == 1 && "Invalid number of operands!");
1060
1061 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001062 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001063 }
1064
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001065 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1066 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001067 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001068 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001069 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1070 Inst.addOperand(MCOperand::createReg(
1071 RegIdx.RegInfo->getRegClass(
1072 AsmParser.getABI().AreGprs64bit()
1073 ? Mips::GPR64RegClassID
1074 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1075 Inst.addOperand(MCOperand::createReg(
1076 RegIdx.RegInfo->getRegClass(
1077 AsmParser.getABI().AreGprs64bit()
1078 ? Mips::GPR64RegClassID
1079 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001080 }
1081
Zoran Jovanovic41688672015-02-10 16:36:20 +00001082 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1083 assert(N == 2 && "Invalid number of operands!");
1084 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001085 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001086 }
1087
Craig Topper56c590a2014-04-29 07:58:02 +00001088 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001089 // As a special case until we sort out the definition of div/divu, accept
1090 // $0/$zero here so that MCK_ZERO works correctly.
1091 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001092 }
1093 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001094 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001095 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001096 int64_t Res;
1097 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001098 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001099 bool isConstantImmz() const {
1100 return isConstantImm() && getConstantImm() == 0;
1101 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001102 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1103 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1104 }
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001105 template <unsigned Bits> bool isSImm() const {
1106 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1107 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001108 template <unsigned Bits> bool isUImm() const {
1109 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1110 }
1111 template <unsigned Bits> bool isAnyImm() const {
1112 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1113 isUInt<Bits>(getConstantImm()))
1114 : isImm();
1115 }
Daniel Sanders78e89022016-03-11 11:37:50 +00001116 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1117 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001118 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001119 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1120 return isConstantImm() && getConstantImm() >= Bottom &&
1121 getConstantImm() <= Top;
1122 }
Craig Topper56c590a2014-04-29 07:58:02 +00001123 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001124 // Note: It's not possible to pretend that other operand kinds are tokens.
1125 // The matcher emitter checks tokens first.
1126 return Kind == k_Token;
1127 }
Craig Topper56c590a2014-04-29 07:58:02 +00001128 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001129 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001130 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001131 }
Simon Dardis4ccda502016-05-27 13:56:36 +00001132 // Allow relocation operators.
1133 // FIXME: This predicate and others need to look through binary expressions
1134 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001135 template <unsigned Bits, unsigned ShiftAmount = 0>
1136 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001137 if (!isMem())
1138 return false;
1139 if (!getMemBase()->isGPRAsmReg())
1140 return false;
1141 if (isa<MCTargetExpr>(getMemOff()) ||
1142 (isConstantMemOff() &&
1143 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1144 return true;
1145 MCValue Res;
1146 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1147 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001148 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001149 bool isMemWithGRPMM16Base() const {
1150 return isMem() && getMemBase()->isMM16AsmReg();
1151 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001152 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1153 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1154 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1155 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001156 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1157 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1158 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1159 && (getMemBase()->getGPR32Reg() == Mips::SP);
1160 }
Daniel Sanderse473dc92016-05-09 13:38:25 +00001161 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1162 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1163 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1164 && (getMemBase()->getGPR32Reg() == Mips::GP);
1165 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001166 template <unsigned Bits, unsigned ShiftLeftAmount>
1167 bool isScaledUImm() const {
1168 return isConstantImm() &&
1169 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001170 }
Daniel Sanders97297772016-03-22 14:40:00 +00001171 template <unsigned Bits, unsigned ShiftLeftAmount>
1172 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001173 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1174 return true;
1175 // Operand can also be a symbol or symbol plus offset in case of relocations.
1176 if (Kind != k_Immediate)
1177 return false;
1178 MCValue Res;
1179 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1180 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001181 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001182 bool isRegList16() const {
1183 if (!isRegList())
1184 return false;
1185
1186 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001187 if (Size < 2 || Size > 5)
1188 return false;
1189
1190 unsigned R0 = RegList.List->front();
1191 unsigned R1 = RegList.List->back();
1192 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1193 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001194 return false;
1195
1196 int PrevReg = *RegList.List->begin();
1197 for (int i = 1; i < Size - 1; i++) {
1198 int Reg = (*(RegList.List))[i];
1199 if ( Reg != PrevReg + 1)
1200 return false;
1201 PrevReg = Reg;
1202 }
1203
1204 return true;
1205 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001206 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001207 bool isLSAImm() const {
1208 if (!isConstantImm())
1209 return false;
1210 int64_t Val = getConstantImm();
1211 return 1 <= Val && Val <= 4;
1212 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001213 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001214 bool isMovePRegPair() const {
1215 if (Kind != k_RegList || RegList.List->size() != 2)
1216 return false;
1217
1218 unsigned R0 = RegList.List->front();
1219 unsigned R1 = RegList.List->back();
1220
1221 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1222 (R0 == Mips::A1 && R1 == Mips::A3) ||
1223 (R0 == Mips::A2 && R1 == Mips::A3) ||
1224 (R0 == Mips::A0 && R1 == Mips::S5) ||
1225 (R0 == Mips::A0 && R1 == Mips::S6) ||
1226 (R0 == Mips::A0 && R1 == Mips::A1) ||
1227 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001228 (R0 == Mips::A0 && R1 == Mips::A3) ||
1229 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1230 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1231 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1232 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1233 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1234 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1235 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1236 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001237 return true;
1238
1239 return false;
1240 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001241
1242 StringRef getToken() const {
1243 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001244 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001245 }
Zlatko Buljanba553a62016-05-09 08:07:28 +00001246 bool isRegPair() const {
1247 return Kind == k_RegPair && RegIdx.Index <= 30;
1248 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001249
Craig Topper56c590a2014-04-29 07:58:02 +00001250 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001251 // As a special case until we sort out the definition of div/divu, accept
1252 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001253 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1254 RegIdx.Kind & RegKind_GPR)
1255 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001256
Daniel Sanders976d9382016-07-05 13:38:40 +00001257 llvm_unreachable("Invalid access!");
1258 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001259 }
1260
Jack Carterb4dbc172012-09-05 23:34:03 +00001261 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001262 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001263 return Imm.Val;
1264 }
1265
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001266 int64_t getConstantImm() const {
1267 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001268 int64_t Value = 0;
1269 (void)Val->evaluateAsAbsolute(Value);
1270 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001271 }
1272
1273 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001274 assert((Kind == k_Memory) && "Invalid access!");
1275 return Mem.Base;
1276 }
1277
1278 const MCExpr *getMemOff() const {
1279 assert((Kind == k_Memory) && "Invalid access!");
1280 return Mem.Off;
1281 }
1282
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001283 int64_t getConstantMemOff() const {
1284 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1285 }
1286
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001287 const SmallVectorImpl<unsigned> &getRegList() const {
1288 assert((Kind == k_RegList) && "Invalid access!");
1289 return *(RegList.List);
1290 }
1291
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001292 unsigned getRegPair() const {
1293 assert((Kind == k_RegPair) && "Invalid access!");
1294 return RegIdx.Index;
1295 }
1296
David Blaikie960ea3f2014-06-08 16:18:35 +00001297 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1298 MipsAsmParser &Parser) {
1299 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001300 Op->Tok.Data = Str.data();
1301 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001302 Op->StartLoc = S;
1303 Op->EndLoc = S;
1304 return Op;
1305 }
1306
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001307 /// Create a numeric register (e.g. $1). The exact register remains
1308 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001309 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001310 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1311 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001312 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001313 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001314 }
1315
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001316 /// Create a register that is definitely a GPR.
1317 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001318 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001319 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1320 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1321 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001322 }
1323
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001324 /// Create a register that is definitely a FGR.
1325 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001326 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001327 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1328 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1329 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001330 }
1331
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001332 /// Create a register that is definitely a HWReg.
1333 /// This is typically only used for named registers such as $hwr_cpunum.
1334 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001335 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001336 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001337 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001338 }
1339
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001340 /// Create a register that is definitely an FCC.
1341 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001342 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001343 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1344 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1345 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001346 }
1347
1348 /// Create a register that is definitely an ACC.
1349 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001350 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001351 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1352 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1353 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001354 }
1355
1356 /// Create a register that is definitely an MSA128.
1357 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001358 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001359 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1360 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1361 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001362 }
1363
1364 /// Create a register that is definitely an MSACtrl.
1365 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001366 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001367 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1368 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1369 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001370 }
1371
David Blaikie960ea3f2014-06-08 16:18:35 +00001372 static std::unique_ptr<MipsOperand>
1373 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1374 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001375 Op->Imm.Val = Val;
1376 Op->StartLoc = S;
1377 Op->EndLoc = E;
1378 return Op;
1379 }
1380
David Blaikie960ea3f2014-06-08 16:18:35 +00001381 static std::unique_ptr<MipsOperand>
1382 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1383 SMLoc E, MipsAsmParser &Parser) {
1384 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1385 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001386 Op->Mem.Off = Off;
1387 Op->StartLoc = S;
1388 Op->EndLoc = E;
1389 return Op;
1390 }
1391
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001392 static std::unique_ptr<MipsOperand>
1393 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1394 MipsAsmParser &Parser) {
1395 assert (Regs.size() > 0 && "Empty list not allowed");
1396
1397 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001398 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001399 Op->StartLoc = StartLoc;
1400 Op->EndLoc = EndLoc;
1401 return Op;
1402 }
1403
Daniel Sandersd044e492016-05-09 13:10:57 +00001404 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1405 SMLoc S, SMLoc E,
1406 MipsAsmParser &Parser) {
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001407 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001408 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001409 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1410 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001411 Op->StartLoc = S;
1412 Op->EndLoc = E;
1413 return Op;
1414 }
1415
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001416 bool isGPRAsmReg() const {
1417 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001418 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001419 bool isMM16AsmReg() const {
1420 if (!(isRegIdx() && RegIdx.Kind))
1421 return false;
1422 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1423 || RegIdx.Index == 16 || RegIdx.Index == 17);
1424 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001425 bool isMM16AsmRegZero() const {
1426 if (!(isRegIdx() && RegIdx.Kind))
1427 return false;
1428 return (RegIdx.Index == 0 ||
1429 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1430 RegIdx.Index == 17);
1431 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001432 bool isMM16AsmRegMoveP() const {
1433 if (!(isRegIdx() && RegIdx.Kind))
1434 return false;
1435 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1436 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1437 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001438 bool isFGRAsmReg() const {
1439 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1440 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001441 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001442 bool isHWRegsAsmReg() const {
1443 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001444 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001445 bool isCCRAsmReg() const {
1446 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001447 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001448 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001449 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1450 return false;
1451 if (!AsmParser.hasEightFccRegisters())
1452 return RegIdx.Index == 0;
1453 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001454 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001455 bool isACCAsmReg() const {
1456 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001457 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001458 bool isCOP0AsmReg() const {
1459 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1460 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001461 bool isCOP2AsmReg() const {
1462 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001463 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001464 bool isCOP3AsmReg() const {
1465 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1466 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001467 bool isMSA128AsmReg() const {
1468 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001469 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001470 bool isMSACtrlAsmReg() const {
1471 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001472 }
1473
Jack Carterb4dbc172012-09-05 23:34:03 +00001474 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001475 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001476 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001477 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001478
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001479 virtual ~MipsOperand() {
1480 switch (Kind) {
1481 case k_Immediate:
1482 break;
1483 case k_Memory:
1484 delete Mem.Base;
1485 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001486 case k_RegList:
1487 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001488 case k_RegisterIndex:
1489 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001490 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001491 break;
1492 }
1493 }
1494
Craig Topper56c590a2014-04-29 07:58:02 +00001495 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001496 switch (Kind) {
1497 case k_Immediate:
1498 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001499 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001500 OS << ">";
1501 break;
1502 case k_Memory:
1503 OS << "Mem<";
1504 Mem.Base->print(OS);
1505 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001506 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001507 OS << ">";
1508 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001509 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001510 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1511 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001512 break;
1513 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001514 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001515 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001516 case k_RegList:
1517 OS << "RegList< ";
1518 for (auto Reg : (*RegList.List))
1519 OS << Reg << " ";
1520 OS << ">";
1521 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001522 case k_RegPair:
1523 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1524 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001525 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001526 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001527
1528 bool isValidForTie(const MipsOperand &Other) const {
1529 if (Kind != Other.Kind)
1530 return false;
1531
1532 switch (Kind) {
1533 default:
1534 llvm_unreachable("Unexpected kind");
1535 return false;
1536 case k_RegisterIndex: {
1537 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1538 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1539 return Token == OtherToken;
1540 }
1541 }
1542 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001543}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001544} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001545
Jack Carter9e65aa32013-03-22 00:05:30 +00001546namespace llvm {
1547extern const MCInstrDesc MipsInsts[];
1548}
1549static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1550 return MipsInsts[Opcode];
1551}
1552
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001553static bool hasShortDelaySlot(unsigned Opcode) {
1554 switch (Opcode) {
1555 case Mips::JALS_MM:
1556 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001557 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001558 case Mips::BGEZALS_MM:
1559 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001560 return true;
1561 default:
1562 return false;
1563 }
1564}
1565
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001566static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1567 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1568 return &SRExpr->getSymbol();
1569 }
1570
1571 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1572 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1573 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1574
1575 if (LHSSym)
1576 return LHSSym;
1577
1578 if (RHSSym)
1579 return RHSSym;
1580
1581 return nullptr;
1582 }
1583
1584 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1585 return getSingleMCSymbol(UExpr->getSubExpr());
1586
1587 return nullptr;
1588}
1589
1590static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1591 if (isa<MCSymbolRefExpr>(Expr))
1592 return 1;
1593
1594 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1595 return countMCSymbolRefExpr(BExpr->getLHS()) +
1596 countMCSymbolRefExpr(BExpr->getRHS());
1597
1598 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1599 return countMCSymbolRefExpr(UExpr->getSubExpr());
1600
1601 return 0;
1602}
1603
Jack Carter9e65aa32013-03-22 00:05:30 +00001604bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001605 MCStreamer &Out,
1606 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001607 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001608 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001609 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001610
Jack Carter9e65aa32013-03-22 00:05:30 +00001611 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001612
1613 if (MCID.isBranch() || MCID.isCall()) {
1614 const unsigned Opcode = Inst.getOpcode();
1615 MCOperand Offset;
1616
1617 switch (Opcode) {
1618 default:
1619 break;
Kai Nackee0245392015-01-27 19:11:28 +00001620 case Mips::BBIT0:
1621 case Mips::BBIT032:
1622 case Mips::BBIT1:
1623 case Mips::BBIT132:
1624 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001625 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001626
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001627 case Mips::BEQ:
1628 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001629 case Mips::BEQ_MM:
1630 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001631 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001632 Offset = Inst.getOperand(2);
1633 if (!Offset.isImm())
1634 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001635 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001636 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001637 if (OffsetToAlignment(Offset.getImm(),
1638 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001639 return Error(IDLoc, "branch to misaligned address");
1640 break;
1641 case Mips::BGEZ:
1642 case Mips::BGTZ:
1643 case Mips::BLEZ:
1644 case Mips::BLTZ:
1645 case Mips::BGEZAL:
1646 case Mips::BLTZAL:
1647 case Mips::BC1F:
1648 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001649 case Mips::BGEZ_MM:
1650 case Mips::BGTZ_MM:
1651 case Mips::BLEZ_MM:
1652 case Mips::BLTZ_MM:
1653 case Mips::BGEZAL_MM:
1654 case Mips::BLTZAL_MM:
1655 case Mips::BC1F_MM:
1656 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001657 case Mips::BC1EQZC_MMR6:
1658 case Mips::BC1NEZC_MMR6:
1659 case Mips::BC2EQZC_MMR6:
1660 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001661 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001662 Offset = Inst.getOperand(1);
1663 if (!Offset.isImm())
1664 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001665 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001666 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001667 if (OffsetToAlignment(Offset.getImm(),
1668 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001669 return Error(IDLoc, "branch to misaligned address");
1670 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001671 case Mips::BGEC: case Mips::BGEC_MMR6:
1672 case Mips::BLTC: case Mips::BLTC_MMR6:
1673 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1674 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1675 case Mips::BEQC: case Mips::BEQC_MMR6:
1676 case Mips::BNEC: case Mips::BNEC_MMR6:
1677 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1678 Offset = Inst.getOperand(2);
1679 if (!Offset.isImm())
1680 break; // We'll deal with this situation later on when applying fixups.
1681 if (!isIntN(18, Offset.getImm()))
1682 return Error(IDLoc, "branch target out of range");
1683 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1684 return Error(IDLoc, "branch to misaligned address");
1685 break;
1686 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1687 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1688 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1689 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1690 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1691 Offset = Inst.getOperand(1);
1692 if (!Offset.isImm())
1693 break; // We'll deal with this situation later on when applying fixups.
1694 if (!isIntN(18, Offset.getImm()))
1695 return Error(IDLoc, "branch target out of range");
1696 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1697 return Error(IDLoc, "branch to misaligned address");
1698 break;
1699 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1700 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1701 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1702 Offset = Inst.getOperand(1);
1703 if (!Offset.isImm())
1704 break; // We'll deal with this situation later on when applying fixups.
1705 if (!isIntN(23, Offset.getImm()))
1706 return Error(IDLoc, "branch target out of range");
1707 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1708 return Error(IDLoc, "branch to misaligned address");
1709 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001710 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001711 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001712 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001713 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001714 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1715 Offset = Inst.getOperand(1);
1716 if (!Offset.isImm())
1717 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001718 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001719 return Error(IDLoc, "branch target out of range");
1720 if (OffsetToAlignment(Offset.getImm(), 2LL))
1721 return Error(IDLoc, "branch to misaligned address");
1722 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001723 }
1724 }
1725
Daniel Sandersa84989a2014-06-16 13:25:35 +00001726 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1727 // We still accept it but it is a normal nop.
1728 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1729 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1730 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1731 "nop instruction");
1732 }
1733
Kai Nackee0245392015-01-27 19:11:28 +00001734 if (hasCnMips()) {
1735 const unsigned Opcode = Inst.getOpcode();
1736 MCOperand Opnd;
1737 int Imm;
1738
1739 switch (Opcode) {
1740 default:
1741 break;
1742
1743 case Mips::BBIT0:
1744 case Mips::BBIT032:
1745 case Mips::BBIT1:
1746 case Mips::BBIT132:
1747 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1748 // The offset is handled above
1749 Opnd = Inst.getOperand(1);
1750 if (!Opnd.isImm())
1751 return Error(IDLoc, "expected immediate operand kind");
1752 Imm = Opnd.getImm();
1753 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1754 Opcode == Mips::BBIT1 ? 63 : 31))
1755 return Error(IDLoc, "immediate operand value out of range");
1756 if (Imm > 31) {
1757 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1758 : Mips::BBIT132);
1759 Inst.getOperand(1).setImm(Imm - 32);
1760 }
1761 break;
1762
Kai Nackee0245392015-01-27 19:11:28 +00001763 case Mips::SEQi:
1764 case Mips::SNEi:
1765 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1766 Opnd = Inst.getOperand(2);
1767 if (!Opnd.isImm())
1768 return Error(IDLoc, "expected immediate operand kind");
1769 Imm = Opnd.getImm();
1770 if (!isInt<10>(Imm))
1771 return Error(IDLoc, "immediate operand value out of range");
1772 break;
1773 }
1774 }
1775
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001776 // This expansion is not in a function called by tryExpandInstruction()
1777 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001778 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1779 inPicMode()) {
1780 warnIfNoMacro(IDLoc);
1781
1782 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1783
1784 // We can do this expansion if there's only 1 symbol in the argument
1785 // expression.
1786 if (countMCSymbolRefExpr(JalExpr) > 1)
1787 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1788
1789 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001790 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001791 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1792
1793 // FIXME: Add support for label+offset operands (currently causes an error).
1794 // FIXME: Add support for forward-declared local symbols.
1795 // FIXME: Add expansion for when the LargeGOT option is enabled.
1796 if (JalSym->isInSection() || JalSym->isTemporary()) {
1797 if (isABI_O32()) {
1798 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001799 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001800 // R_(MICRO)MIPS_GOT16 label
1801 // addiu $25, $25, 0
1802 // R_(MICRO)MIPS_LO16 label
1803 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001804 const MCExpr *Got16RelocExpr =
1805 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1806 const MCExpr *Lo16RelocExpr =
1807 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001808
Daniel Sandersa736b372016-04-29 13:33:12 +00001809 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1810 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1811 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1812 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001813 } else if (isABI_N32() || isABI_N64()) {
1814 // If it's a local symbol and the N32/N64 ABIs are being used,
1815 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001816 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001817 // R_(MICRO)MIPS_GOT_DISP label
1818 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001819 const MCExpr *GotDispRelocExpr =
1820 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001821
Daniel Sandersa736b372016-04-29 13:33:12 +00001822 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1823 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1824 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001825 }
1826 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001827 // If it's an external/weak symbol, we expand to:
1828 // lw/ld $25, 0($gp)
1829 // R_(MICRO)MIPS_CALL16 label
1830 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001831 const MCExpr *Call16RelocExpr =
1832 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001833
Daniel Sandersa736b372016-04-29 13:33:12 +00001834 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1835 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001836 }
1837
1838 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001839 if (IsCpRestoreSet && inMicroMipsMode())
1840 JalrInst.setOpcode(Mips::JALRS_MM);
1841 else
1842 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001843 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1844 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1845
1846 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1847 // This relocation is supposed to be an optimization hint for the linker
1848 // and is not necessary for correctness.
1849
1850 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001851 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001852 }
1853
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001854 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
1855 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001856 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001857 // reference or immediate we may have to expand instructions.
1858 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001859 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001860 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1861 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001862 MCOperand &Op = Inst.getOperand(i);
1863 if (Op.isImm()) {
1864 int MemOffset = Op.getImm();
1865 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001866 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001867 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00001868 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001869 }
1870 } else if (Op.isExpr()) {
1871 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001872 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001873 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001874 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001875 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001876 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001877 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00001878 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001879 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001880 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001881 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00001882 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001883 }
1884 }
1885 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001886 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001887 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001888
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001889 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001890 if (MCID.mayLoad()) {
1891 // Try to create 16-bit GP relative load instruction.
1892 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1893 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1894 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1895 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1896 MCOperand &Op = Inst.getOperand(i);
1897 if (Op.isImm()) {
1898 int MemOffset = Op.getImm();
1899 MCOperand &DstReg = Inst.getOperand(0);
1900 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001901 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001902 getContext().getRegisterInfo()->getRegClass(
1903 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001904 (BaseReg.getReg() == Mips::GP ||
1905 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001906
Daniel Sandersa736b372016-04-29 13:33:12 +00001907 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1908 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001909 return false;
1910 }
1911 }
1912 }
1913 } // for
1914 } // if load
1915
1916 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1917
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001918 MCOperand Opnd;
1919 int Imm;
1920
1921 switch (Inst.getOpcode()) {
1922 default:
1923 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001924 case Mips::ADDIUSP_MM:
1925 Opnd = Inst.getOperand(0);
1926 if (!Opnd.isImm())
1927 return Error(IDLoc, "expected immediate operand kind");
1928 Imm = Opnd.getImm();
1929 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1930 Imm % 4 != 0)
1931 return Error(IDLoc, "immediate operand value out of range");
1932 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001933 case Mips::SLL16_MM:
1934 case Mips::SRL16_MM:
1935 Opnd = Inst.getOperand(2);
1936 if (!Opnd.isImm())
1937 return Error(IDLoc, "expected immediate operand kind");
1938 Imm = Opnd.getImm();
1939 if (Imm < 1 || Imm > 8)
1940 return Error(IDLoc, "immediate operand value out of range");
1941 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001942 case Mips::LI16_MM:
1943 Opnd = Inst.getOperand(1);
1944 if (!Opnd.isImm())
1945 return Error(IDLoc, "expected immediate operand kind");
1946 Imm = Opnd.getImm();
1947 if (Imm < -1 || Imm > 126)
1948 return Error(IDLoc, "immediate operand value out of range");
1949 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001950 case Mips::ADDIUR2_MM:
1951 Opnd = Inst.getOperand(2);
1952 if (!Opnd.isImm())
1953 return Error(IDLoc, "expected immediate operand kind");
1954 Imm = Opnd.getImm();
1955 if (!(Imm == 1 || Imm == -1 ||
1956 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1957 return Error(IDLoc, "immediate operand value out of range");
1958 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001959 case Mips::ANDI16_MM:
1960 Opnd = Inst.getOperand(2);
1961 if (!Opnd.isImm())
1962 return Error(IDLoc, "expected immediate operand kind");
1963 Imm = Opnd.getImm();
1964 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1965 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1966 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1967 return Error(IDLoc, "immediate operand value out of range");
1968 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001969 case Mips::LBU16_MM:
1970 Opnd = Inst.getOperand(2);
1971 if (!Opnd.isImm())
1972 return Error(IDLoc, "expected immediate operand kind");
1973 Imm = Opnd.getImm();
1974 if (Imm < -1 || Imm > 14)
1975 return Error(IDLoc, "immediate operand value out of range");
1976 break;
1977 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001978 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001979 Opnd = Inst.getOperand(2);
1980 if (!Opnd.isImm())
1981 return Error(IDLoc, "expected immediate operand kind");
1982 Imm = Opnd.getImm();
1983 if (Imm < 0 || Imm > 15)
1984 return Error(IDLoc, "immediate operand value out of range");
1985 break;
1986 case Mips::LHU16_MM:
1987 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001988 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001989 Opnd = Inst.getOperand(2);
1990 if (!Opnd.isImm())
1991 return Error(IDLoc, "expected immediate operand kind");
1992 Imm = Opnd.getImm();
1993 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1994 return Error(IDLoc, "immediate operand value out of range");
1995 break;
1996 case Mips::LW16_MM:
1997 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001998 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001999 Opnd = Inst.getOperand(2);
2000 if (!Opnd.isImm())
2001 return Error(IDLoc, "expected immediate operand kind");
2002 Imm = Opnd.getImm();
2003 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2004 return Error(IDLoc, "immediate operand value out of range");
2005 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002006 case Mips::ADDIUPC_MM:
2007 MCOperand Opnd = Inst.getOperand(1);
2008 if (!Opnd.isImm())
2009 return Error(IDLoc, "expected immediate operand kind");
2010 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002011 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002012 return Error(IDLoc, "immediate operand value out of range");
2013 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002014 }
2015 }
2016
Daniel Sandersd8c07762016-04-18 12:35:36 +00002017 bool FillDelaySlot =
2018 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2019 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002020 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002021
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002022 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002023 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002024 switch (ExpandResult) {
2025 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002026 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002027 break;
2028 case MER_Success:
2029 break;
2030 case MER_Fail:
2031 return true;
2032 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002033
Daniel Sanderscda908a2016-05-16 09:10:13 +00002034 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2035 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2036 if (inMicroMipsMode())
2037 TOut.setUsesMicroMips();
2038
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002039 // If this instruction has a delay slot and .set reorder is active,
2040 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002041 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002042 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2043 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002044 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002045
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002046 if ((Inst.getOpcode() == Mips::JalOneReg ||
2047 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2048 isPicAndNotNxxAbi()) {
2049 if (IsCpRestoreSet) {
2050 // We need a NOP between the JALR and the LW:
2051 // If .set reorder has been used, we've already emitted a NOP.
2052 // If .set noreorder has been used, we need to emit a NOP at this point.
2053 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002054 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2055 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002056
2057 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002058 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002059 } else
2060 Warning(IDLoc, "no .cprestore used in PIC mode");
2061 }
2062
Jack Carter9e65aa32013-03-22 00:05:30 +00002063 return false;
2064}
2065
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002066MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002067MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2068 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002069 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002070 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002071 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002072 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002073 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002074 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002075 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002076 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002077 case Mips::LoadAddrImm64:
2078 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2079 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2080 "expected immediate operand kind");
2081
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002082 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2083 Inst.getOperand(1),
2084 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002085 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002086 ? MER_Fail
2087 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002088 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002089 case Mips::LoadAddrReg64:
2090 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2091 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2092 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2093 "expected immediate operand kind");
2094
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002095 return expandLoadAddress(Inst.getOperand(0).getReg(),
2096 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2097 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002098 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002099 ? MER_Fail
2100 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002101 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002102 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002103 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2104 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002105 case Mips::SWM_MM:
2106 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002107 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2108 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002109 case Mips::JalOneReg:
2110 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002111 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002112 case Mips::BneImm:
2113 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002114 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002115 case Mips::BLT:
2116 case Mips::BLE:
2117 case Mips::BGE:
2118 case Mips::BGT:
2119 case Mips::BLTU:
2120 case Mips::BLEU:
2121 case Mips::BGEU:
2122 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002123 case Mips::BLTL:
2124 case Mips::BLEL:
2125 case Mips::BGEL:
2126 case Mips::BGTL:
2127 case Mips::BLTUL:
2128 case Mips::BLEUL:
2129 case Mips::BGEUL:
2130 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002131 case Mips::BLTImmMacro:
2132 case Mips::BLEImmMacro:
2133 case Mips::BGEImmMacro:
2134 case Mips::BGTImmMacro:
2135 case Mips::BLTUImmMacro:
2136 case Mips::BLEUImmMacro:
2137 case Mips::BGEUImmMacro:
2138 case Mips::BGTUImmMacro:
2139 case Mips::BLTLImmMacro:
2140 case Mips::BLELImmMacro:
2141 case Mips::BGELImmMacro:
2142 case Mips::BGTLImmMacro:
2143 case Mips::BLTULImmMacro:
2144 case Mips::BLEULImmMacro:
2145 case Mips::BGEULImmMacro:
2146 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002147 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002148 case Mips::SDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002149 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2150 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002151 case Mips::DSDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002152 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2153 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002154 case Mips::UDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002155 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2156 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002157 case Mips::DUDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002158 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2159 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002160 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002161 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2162 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002163 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002164 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002165 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002166 case Mips::PseudoTRUNC_W_D:
2167 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2168 : MER_Success;
2169 case Mips::Ulh:
2170 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2171 case Mips::Ulhu:
2172 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2173 case Mips::Ulw:
2174 return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2175 case Mips::NORImm:
2176 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002177 case Mips::ADDi:
2178 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002179 case Mips::SLTi:
2180 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002181 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2182 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2183 int64_t ImmValue = Inst.getOperand(2).getImm();
2184 if (isInt<16>(ImmValue))
2185 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002186 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2187 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002188 }
2189 return MER_NotAMacro;
2190 case Mips::ANDi:
2191 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002192 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002193 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2194 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2195 int64_t ImmValue = Inst.getOperand(2).getImm();
2196 if (isUInt<16>(ImmValue))
2197 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002198 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2199 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002200 }
2201 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002202 case Mips::ROL:
2203 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002204 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002205 case Mips::ROLImm:
2206 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002207 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002208 case Mips::DROL:
2209 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002210 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002211 case Mips::DROLImm:
2212 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002213 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002214 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002215 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002216 }
Jack Carter30a59822012-10-04 04:03:53 +00002217}
Jack Carter92995f12012-10-06 00:53:28 +00002218
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002219bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002220 MCStreamer &Out,
2221 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002222 MipsTargetStreamer &TOut = getTargetStreamer();
2223
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002224 // Create a JALR instruction which is going to replace the pseudo-JAL.
2225 MCInst JalrInst;
2226 JalrInst.setLoc(IDLoc);
2227 const MCOperand FirstRegOp = Inst.getOperand(0);
2228 const unsigned Opcode = Inst.getOpcode();
2229
2230 if (Opcode == Mips::JalOneReg) {
2231 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002232 if (IsCpRestoreSet && inMicroMipsMode()) {
2233 JalrInst.setOpcode(Mips::JALRS16_MM);
2234 JalrInst.addOperand(FirstRegOp);
2235 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002236 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002237 JalrInst.addOperand(FirstRegOp);
2238 } else {
2239 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002240 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002241 JalrInst.addOperand(FirstRegOp);
2242 }
2243 } else if (Opcode == Mips::JalTwoReg) {
2244 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002245 if (IsCpRestoreSet && inMicroMipsMode())
2246 JalrInst.setOpcode(Mips::JALRS_MM);
2247 else
2248 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002249 JalrInst.addOperand(FirstRegOp);
2250 const MCOperand SecondRegOp = Inst.getOperand(1);
2251 JalrInst.addOperand(SecondRegOp);
2252 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002253 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002254
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002255 // If .set reorder is active and branch instruction has a delay slot,
2256 // emit a NOP after it.
2257 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002258 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2259 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2260 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002261
2262 return false;
2263}
2264
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002265/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002266template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002267 unsigned BitNum = findFirstSet(x);
2268
2269 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2270}
2271
2272/// Load (or add) an immediate into a register.
2273///
2274/// @param ImmValue The immediate to load.
2275/// @param DstReg The register that will hold the immediate.
2276/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2277/// for a simple initialization.
2278/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2279/// @param IsAddress True if the immediate represents an address. False if it
2280/// is an integer.
2281/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002282bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002283 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002284 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2285 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002286 MipsTargetStreamer &TOut = getTargetStreamer();
2287
Toma Tabacu00e98672015-05-01 12:19:27 +00002288 if (!Is32BitImm && !isGP64bit()) {
2289 Error(IDLoc, "instruction requires a 64-bit architecture");
2290 return true;
2291 }
2292
Daniel Sanders03f9c012015-07-14 12:24:22 +00002293 if (Is32BitImm) {
2294 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2295 // Sign extend up to 64-bit so that the predicates match the hardware
2296 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2297 // true.
2298 ImmValue = SignExtend64<32>(ImmValue);
2299 } else {
2300 Error(IDLoc, "instruction requires a 32-bit immediate");
2301 return true;
2302 }
2303 }
2304
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002305 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2306 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2307
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002308 bool UseSrcReg = false;
2309 if (SrcReg != Mips::NoRegister)
2310 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002311
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002312 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002313 if (UseSrcReg &&
2314 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002315 // At this point we need AT to perform the expansions and we exit if it is
2316 // not available.
2317 unsigned ATReg = getATReg(IDLoc);
2318 if (!ATReg)
2319 return true;
2320 TmpReg = ATReg;
2321 }
2322
Daniel Sanders03f9c012015-07-14 12:24:22 +00002323 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002324 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002325 SrcReg = ZeroReg;
2326
2327 // This doesn't quite follow the usual ABI expectations for N32 but matches
2328 // traditional assembler behaviour. N32 would normally use addiu for both
2329 // integers and addresses.
2330 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002331 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002332 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002333 }
2334
Daniel Sandersa736b372016-04-29 13:33:12 +00002335 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002336 return false;
2337 }
2338
2339 if (isUInt<16>(ImmValue)) {
2340 unsigned TmpReg = DstReg;
2341 if (SrcReg == DstReg) {
2342 TmpReg = getATReg(IDLoc);
2343 if (!TmpReg)
2344 return true;
2345 }
2346
Daniel Sandersa736b372016-04-29 13:33:12 +00002347 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002348 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002349 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002350 return false;
2351 }
2352
2353 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002354 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002355
Toma Tabacu79588102015-04-29 10:19:56 +00002356 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2357 uint16_t Bits15To0 = ImmValue & 0xffff;
2358
Toma Tabacua3d056f2015-05-15 09:42:11 +00002359 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002360 // Traditional behaviour seems to special case this particular value. It's
2361 // not clear why other masks are handled differently.
2362 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002363 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2364 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002365 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002366 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002367 return false;
2368 }
2369
2370 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002371 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002372 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2373 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002374 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002375 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002376 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002377 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002378 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002379 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002380
Daniel Sandersa736b372016-04-29 13:33:12 +00002381 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002382 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002383 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002384 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002385 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002386 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002387 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002388
2389 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2390 if (Is32BitImm) {
2391 Error(IDLoc, "instruction requires a 32-bit immediate");
2392 return true;
2393 }
2394
2395 // Traditionally, these immediates are shifted as little as possible and as
2396 // such we align the most significant bit to bit 15 of our temporary.
2397 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2398 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2399 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2400 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002401 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2402 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002403
2404 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002405 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002406
2407 return false;
2408 }
2409
2410 warnIfNoMacro(IDLoc);
2411
2412 // The remaining case is packed with a sequence of dsll and ori with zeros
2413 // being omitted and any neighbouring dsll's being coalesced.
2414 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2415
2416 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2417 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002418 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002419 return false;
2420
2421 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2422 // skip it and defer the shift to the next chunk.
2423 unsigned ShiftCarriedForwards = 16;
2424 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2425 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2426
2427 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002428 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2429 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002430 ShiftCarriedForwards = 0;
2431 }
2432
2433 ShiftCarriedForwards += 16;
2434 }
2435 ShiftCarriedForwards -= 16;
2436
2437 // Finish any remaining shifts left by trailing zeros.
2438 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002439 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002440
2441 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002442 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002443
Matheus Almeida3813d572014-06-19 14:39:14 +00002444 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002445}
Jack Carter92995f12012-10-06 00:53:28 +00002446
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002447bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002448 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002449 const MCOperand &ImmOp = Inst.getOperand(1);
2450 assert(ImmOp.isImm() && "expected immediate operand kind");
2451 const MCOperand &DstRegOp = Inst.getOperand(0);
2452 assert(DstRegOp.isReg() && "expected register operand kind");
2453
2454 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002455 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002456 return true;
2457
2458 return false;
2459}
2460
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002461bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2462 const MCOperand &Offset,
2463 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002464 MCStreamer &Out,
2465 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002466 // la can't produce a usable address when addresses are 64-bit.
2467 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2468 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2469 // We currently can't do this because we depend on the equality
2470 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2471 Error(IDLoc, "la used to load 64-bit address");
2472 // Continue as if we had 'dla' instead.
2473 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002474 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002475 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002476
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002477 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002478 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002479 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002480 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002481 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002482
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002483 if (!Offset.isImm())
2484 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002485 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002486
Scott Egerton24557012016-01-21 15:11:01 +00002487 if (!ABI.ArePtrs64bit()) {
2488 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2489 Is32BitAddress = true;
2490 }
2491
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002492 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002493 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002494}
2495
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002496bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2497 unsigned DstReg, unsigned SrcReg,
2498 bool Is32BitSym, SMLoc IDLoc,
2499 MCStreamer &Out,
2500 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002501 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002502 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002503 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002504
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002505 if (inPicMode() && ABI.IsO32()) {
2506 MCValue Res;
2507 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2508 Error(IDLoc, "expected relocatable expression");
2509 return true;
2510 }
2511 if (Res.getSymB() != nullptr) {
2512 Error(IDLoc, "expected relocatable expression with only one symbol");
2513 return true;
2514 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002515
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002516 // The case where the result register is $25 is somewhat special. If the
2517 // symbol in the final relocation is external and not modified with a
2518 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2519 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2520 Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
2521 !Res.getSymA()->getSymbol().isTemporary()) {
2522 const MCExpr *CallExpr =
2523 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2524 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2525 MCOperand::createExpr(CallExpr), IDLoc, STI);
2526 return false;
2527 }
2528
2529 // The remaining cases are:
2530 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2531 // >addiu $tmp, $tmp, %lo(offset)
2532 // >addiu $rd, $tmp, $rs
2533 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2534 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2535 // >addiu $rd, $tmp, $rs
2536 // The addiu's marked with a '>' may be omitted if they are redundant. If
2537 // this happens then the last instruction must use $rd as the result
2538 // register.
2539 const MipsMCExpr *GotExpr =
2540 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2541 const MCExpr *LoExpr = nullptr;
2542 if (Res.getSymA()->getSymbol().isInSection() ||
2543 Res.getSymA()->getSymbol().isTemporary())
2544 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2545 else if (Res.getConstant() != 0) {
2546 // External symbols fully resolve the symbol with just the %got(symbol)
2547 // but we must still account for any offset to the symbol for expressions
2548 // like symbol+8.
2549 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2550 }
2551
2552 unsigned TmpReg = DstReg;
2553 if (UseSrcReg &&
2554 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2555 SrcReg)) {
2556 // If $rs is the same as $rd, we need to use AT.
2557 // If it is not available we exit.
2558 unsigned ATReg = getATReg(IDLoc);
2559 if (!ATReg)
2560 return true;
2561 TmpReg = ATReg;
2562 }
2563
2564 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2565 MCOperand::createExpr(GotExpr), IDLoc, STI);
2566
2567 if (LoExpr)
2568 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2569 IDLoc, STI);
2570
2571 if (UseSrcReg)
2572 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2573
2574 return false;
2575 }
2576
2577 const MipsMCExpr *HiExpr =
2578 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2579 const MipsMCExpr *LoExpr =
2580 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002581
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002582 // This is the 64-bit symbol address expansion.
2583 if (ABI.ArePtrs64bit() && isGP64bit()) {
2584 // We always need AT for the 64-bit expansion.
2585 // If it is not available we exit.
2586 unsigned ATReg = getATReg(IDLoc);
2587 if (!ATReg)
2588 return true;
2589
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002590 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002591 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002592 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002593 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002594
Scott Egerton24557012016-01-21 15:11:01 +00002595 if (UseSrcReg &&
2596 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2597 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002598 // If $rs is the same as $rd:
2599 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2600 // daddiu $at, $at, %higher(sym)
2601 // dsll $at, $at, 16
2602 // daddiu $at, $at, %hi(sym)
2603 // dsll $at, $at, 16
2604 // daddiu $at, $at, %lo(sym)
2605 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002606 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2607 STI);
2608 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2609 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2610 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2611 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2612 IDLoc, STI);
2613 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2614 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2615 IDLoc, STI);
2616 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002617
2618 return false;
2619 }
2620
2621 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2622 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2623 // lui $at, %hi(sym)
2624 // daddiu $rd, $rd, %higher(sym)
2625 // daddiu $at, $at, %lo(sym)
2626 // dsll32 $rd, $rd, 0
2627 // daddu $rd, $rd, $at
2628 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002629 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2630 STI);
2631 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2632 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2633 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2634 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2635 IDLoc, STI);
2636 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2637 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002638 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002639 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002640
2641 return false;
2642 }
2643
2644 // And now, the 32-bit symbol address expansion:
2645 // If $rs is the same as $rd:
2646 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2647 // ori $at, $at, %lo(sym)
2648 // addu $rd, $at, $rd
2649 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2650 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2651 // ori $rd, $rd, %lo(sym)
2652 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002653 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002654 if (UseSrcReg &&
2655 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002656 // If $rs is the same as $rd, we need to use AT.
2657 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002658 unsigned ATReg = getATReg(IDLoc);
2659 if (!ATReg)
2660 return true;
2661 TmpReg = ATReg;
2662 }
2663
Daniel Sandersa736b372016-04-29 13:33:12 +00002664 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2665 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2666 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002667
Toma Tabacufb9d1252015-06-22 12:08:39 +00002668 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002669 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002670 else
Scott Egerton24557012016-01-21 15:11:01 +00002671 assert(
2672 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002673
Toma Tabacu674825c2015-06-16 12:16:24 +00002674 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002675}
2676
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002677bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2678 MCStreamer &Out,
2679 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002680 MipsTargetStreamer &TOut = getTargetStreamer();
2681
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002682 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2683 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002684
2685 MCOperand Offset = Inst.getOperand(0);
2686 if (Offset.isExpr()) {
2687 Inst.clear();
2688 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002689 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2690 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2691 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002692 } else {
2693 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002694 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002695 // If offset fits into 11 bits then this instruction becomes microMIPS
2696 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002697 if (inMicroMipsMode())
2698 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002699 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002700 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00002701 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002702 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00002703 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002704 Inst.clear();
2705 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002706 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2707 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2708 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002709 }
2710 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002711 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002712
Zoran Jovanovicada70912015-09-07 11:56:37 +00002713 // If .set reorder is active and branch instruction has a delay slot,
2714 // emit a NOP after it.
2715 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2716 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002717 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002718
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002719 return false;
2720}
2721
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002722bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2723 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002724 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002725 const MCOperand &DstRegOp = Inst.getOperand(0);
2726 assert(DstRegOp.isReg() && "expected register operand kind");
2727
2728 const MCOperand &ImmOp = Inst.getOperand(1);
2729 assert(ImmOp.isImm() && "expected immediate operand kind");
2730
2731 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002732 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2733 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002734
2735 unsigned OpCode = 0;
2736 switch(Inst.getOpcode()) {
2737 case Mips::BneImm:
2738 OpCode = Mips::BNE;
2739 break;
2740 case Mips::BeqImm:
2741 OpCode = Mips::BEQ;
2742 break;
2743 default:
2744 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2745 break;
2746 }
2747
2748 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002749 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002750 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2751 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002752 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002753 warnIfNoMacro(IDLoc);
2754
2755 unsigned ATReg = getATReg(IDLoc);
2756 if (!ATReg)
2757 return true;
2758
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002759 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002760 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002761 return true;
2762
Daniel Sandersa736b372016-04-29 13:33:12 +00002763 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002764 }
2765 return false;
2766}
2767
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002768void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002769 const MCSubtargetInfo *STI, bool IsLoad,
2770 bool IsImmOpnd) {
2771 if (IsLoad) {
2772 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2773 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002774 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002775 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2776}
2777
2778void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2779 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2780 MipsTargetStreamer &TOut = getTargetStreamer();
2781
2782 unsigned DstReg = Inst.getOperand(0).getReg();
2783 unsigned BaseReg = Inst.getOperand(1).getReg();
2784
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002785 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002786 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2787 unsigned DstRegClassID =
2788 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2789 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2790 (DstRegClassID == Mips::GPR64RegClassID);
2791
2792 if (IsImmOpnd) {
2793 // Try to use DstReg as the temporary.
2794 if (IsGPR && (BaseReg != DstReg)) {
2795 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2796 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2797 STI);
2798 return;
2799 }
2800
Matheus Almeida7de68e72014-06-18 14:46:05 +00002801 // At this point we need AT to perform the expansions and we exit if it is
2802 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002803 unsigned ATReg = getATReg(IDLoc);
2804 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002805 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002806
2807 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2808 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2809 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002810 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002811
Daniel Sandersfba875f2016-04-29 13:43:45 +00002812 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002813 MCOperand LoOperand = MCOperand::createExpr(
2814 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2815 MCOperand HiOperand = MCOperand::createExpr(
2816 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002817
2818 // Try to use DstReg as the temporary.
2819 if (IsGPR && (BaseReg != DstReg)) {
2820 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2821 LoOperand, DstReg, IDLoc, STI);
2822 return;
2823 }
2824
2825 // At this point we need AT to perform the expansions and we exit if it is
2826 // not available.
2827 unsigned ATReg = getATReg(IDLoc);
2828 if (!ATReg)
2829 return;
2830
2831 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2832 LoOperand, ATReg, IDLoc, STI);
2833}
2834
2835void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2836 const MCSubtargetInfo *STI,
2837 bool IsImmOpnd) {
2838 MipsTargetStreamer &TOut = getTargetStreamer();
2839
2840 unsigned SrcReg = Inst.getOperand(0).getReg();
2841 unsigned BaseReg = Inst.getOperand(1).getReg();
2842
Daniel Sanders241c6792016-05-12 14:01:50 +00002843 if (IsImmOpnd) {
2844 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2845 Inst.getOperand(2).getImm(),
2846 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
2847 return;
2848 }
2849
Daniel Sandersfba875f2016-04-29 13:43:45 +00002850 unsigned ATReg = getATReg(IDLoc);
2851 if (!ATReg)
2852 return;
2853
Daniel Sandersfba875f2016-04-29 13:43:45 +00002854 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002855 MCOperand LoOperand = MCOperand::createExpr(
2856 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2857 MCOperand HiOperand = MCOperand::createExpr(
2858 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002859 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2860 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002861}
2862
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002863bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2864 MCStreamer &Out,
2865 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002866 unsigned OpNum = Inst.getNumOperands();
2867 unsigned Opcode = Inst.getOpcode();
2868 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2869
2870 assert (Inst.getOperand(OpNum - 1).isImm() &&
2871 Inst.getOperand(OpNum - 2).isReg() &&
2872 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2873
2874 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2875 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002876 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2877 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2878 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2879 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002880 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002881 if (inMicroMipsMode() && hasMips32r6())
2882 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2883 else
2884 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2885 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002886
2887 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002888 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002889 return false;
2890}
2891
Toma Tabacu1a108322015-06-17 13:20:24 +00002892bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002893 MCStreamer &Out,
2894 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002895 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002896 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002897 unsigned PseudoOpcode = Inst.getOpcode();
2898 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002899 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002900 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2901
2902 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002903 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002904
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002905 unsigned TrgReg;
2906 if (TrgOp.isReg())
2907 TrgReg = TrgOp.getReg();
2908 else if (TrgOp.isImm()) {
2909 warnIfNoMacro(IDLoc);
2910 EmittedNoMacroWarning = true;
2911
2912 TrgReg = getATReg(IDLoc);
2913 if (!TrgReg)
2914 return true;
2915
2916 switch(PseudoOpcode) {
2917 default:
2918 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2919 case Mips::BLTImmMacro:
2920 PseudoOpcode = Mips::BLT;
2921 break;
2922 case Mips::BLEImmMacro:
2923 PseudoOpcode = Mips::BLE;
2924 break;
2925 case Mips::BGEImmMacro:
2926 PseudoOpcode = Mips::BGE;
2927 break;
2928 case Mips::BGTImmMacro:
2929 PseudoOpcode = Mips::BGT;
2930 break;
2931 case Mips::BLTUImmMacro:
2932 PseudoOpcode = Mips::BLTU;
2933 break;
2934 case Mips::BLEUImmMacro:
2935 PseudoOpcode = Mips::BLEU;
2936 break;
2937 case Mips::BGEUImmMacro:
2938 PseudoOpcode = Mips::BGEU;
2939 break;
2940 case Mips::BGTUImmMacro:
2941 PseudoOpcode = Mips::BGTU;
2942 break;
2943 case Mips::BLTLImmMacro:
2944 PseudoOpcode = Mips::BLTL;
2945 break;
2946 case Mips::BLELImmMacro:
2947 PseudoOpcode = Mips::BLEL;
2948 break;
2949 case Mips::BGELImmMacro:
2950 PseudoOpcode = Mips::BGEL;
2951 break;
2952 case Mips::BGTLImmMacro:
2953 PseudoOpcode = Mips::BGTL;
2954 break;
2955 case Mips::BLTULImmMacro:
2956 PseudoOpcode = Mips::BLTUL;
2957 break;
2958 case Mips::BLEULImmMacro:
2959 PseudoOpcode = Mips::BLEUL;
2960 break;
2961 case Mips::BGEULImmMacro:
2962 PseudoOpcode = Mips::BGEUL;
2963 break;
2964 case Mips::BGTULImmMacro:
2965 PseudoOpcode = Mips::BGTUL;
2966 break;
2967 }
2968
2969 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002970 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002971 return true;
2972 }
2973
Toma Tabacu1a108322015-06-17 13:20:24 +00002974 switch (PseudoOpcode) {
2975 case Mips::BLT:
2976 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002977 case Mips::BLTL:
2978 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002979 AcceptsEquality = false;
2980 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002981 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2982 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002983 ZeroSrcOpcode = Mips::BGTZ;
2984 ZeroTrgOpcode = Mips::BLTZ;
2985 break;
2986 case Mips::BLE:
2987 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002988 case Mips::BLEL:
2989 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002990 AcceptsEquality = true;
2991 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002992 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2993 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002994 ZeroSrcOpcode = Mips::BGEZ;
2995 ZeroTrgOpcode = Mips::BLEZ;
2996 break;
2997 case Mips::BGE:
2998 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002999 case Mips::BGEL:
3000 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003001 AcceptsEquality = true;
3002 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003003 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3004 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003005 ZeroSrcOpcode = Mips::BLEZ;
3006 ZeroTrgOpcode = Mips::BGEZ;
3007 break;
3008 case Mips::BGT:
3009 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003010 case Mips::BGTL:
3011 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003012 AcceptsEquality = false;
3013 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003014 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3015 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003016 ZeroSrcOpcode = Mips::BLTZ;
3017 ZeroTrgOpcode = Mips::BGTZ;
3018 break;
3019 default:
3020 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3021 }
3022
Toma Tabacu1a108322015-06-17 13:20:24 +00003023 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3024 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3025 if (IsSrcRegZero && IsTrgRegZero) {
3026 // FIXME: All of these Opcode-specific if's are needed for compatibility
3027 // with GAS' behaviour. However, they may not generate the most efficient
3028 // code in some circumstances.
3029 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003030 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3031 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003032 return false;
3033 }
3034 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003035 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3036 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003037 Warning(IDLoc, "branch is always taken");
3038 return false;
3039 }
3040 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003041 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3042 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003043 Warning(IDLoc, "branch is always taken");
3044 return false;
3045 }
3046 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003047 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3048 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003049 return false;
3050 }
3051 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003052 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3053 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003054 return false;
3055 }
3056 if (AcceptsEquality) {
3057 // If both registers are $0 and the pseudo-branch accepts equality, it
3058 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003059 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3060 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003061 Warning(IDLoc, "branch is always taken");
3062 return false;
3063 }
3064 // If both registers are $0 and the pseudo-branch does not accept
3065 // equality, it will never be taken, so we don't have to emit anything.
3066 return false;
3067 }
3068 if (IsSrcRegZero || IsTrgRegZero) {
3069 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3070 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3071 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3072 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3073 // the pseudo-branch will never be taken, so we don't emit anything.
3074 // This only applies to unsigned pseudo-branches.
3075 return false;
3076 }
3077 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3078 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3079 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3080 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3081 // the pseudo-branch will always be taken, so we emit an unconditional
3082 // branch.
3083 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003084 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3085 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003086 Warning(IDLoc, "branch is always taken");
3087 return false;
3088 }
3089 if (IsUnsigned) {
3090 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3091 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3092 // the pseudo-branch will be taken only when the non-zero register is
3093 // different from 0, so we emit a BNEZ.
3094 //
3095 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3096 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3097 // the pseudo-branch will be taken only when the non-zero register is
3098 // equal to 0, so we emit a BEQZ.
3099 //
3100 // Because only BLEU and BGEU branch on equality, we can use the
3101 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003102 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3103 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3104 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003105 return false;
3106 }
3107 // If we have a signed pseudo-branch and one of the registers is $0,
3108 // we can use an appropriate compare-to-zero branch. We select which one
3109 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003110 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3111 IsSrcRegZero ? TrgReg : SrcReg,
3112 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003113 return false;
3114 }
3115
3116 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3117 // expansions. If it is not available, we return.
3118 unsigned ATRegNum = getATReg(IDLoc);
3119 if (!ATRegNum)
3120 return true;
3121
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003122 if (!EmittedNoMacroWarning)
3123 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003124
3125 // SLT fits well with 2 of our 4 pseudo-branches:
3126 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3127 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3128 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3129 // This is accomplished by using a BNEZ with the result of the SLT.
3130 //
3131 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3132 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3133 // Because only BGE and BLE branch on equality, we can use the
3134 // AcceptsEquality variable to decide when to emit the BEQZ.
3135 // Note that the order of the SLT arguments doesn't change between
3136 // opposites.
3137 //
3138 // The same applies to the unsigned variants, except that SLTu is used
3139 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003140 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3141 ReverseOrderSLT ? TrgReg : SrcReg,
3142 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003143
Daniel Sandersa736b372016-04-29 13:33:12 +00003144 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3145 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3146 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3147 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003148 return false;
3149}
3150
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003151bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3152 const MCSubtargetInfo *STI, const bool IsMips64,
3153 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003154 MipsTargetStreamer &TOut = getTargetStreamer();
3155
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003156 warnIfNoMacro(IDLoc);
3157
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003158 const MCOperand &RdRegOp = Inst.getOperand(0);
3159 assert(RdRegOp.isReg() && "expected register operand kind");
3160 unsigned RdReg = RdRegOp.getReg();
3161
3162 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003163 assert(RsRegOp.isReg() && "expected register operand kind");
3164 unsigned RsReg = RsRegOp.getReg();
3165
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003166 const MCOperand &RtRegOp = Inst.getOperand(2);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003167 assert(RtRegOp.isReg() && "expected register operand kind");
3168 unsigned RtReg = RtRegOp.getReg();
3169 unsigned DivOp;
3170 unsigned ZeroReg;
3171
3172 if (IsMips64) {
3173 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3174 ZeroReg = Mips::ZERO_64;
3175 } else {
3176 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3177 ZeroReg = Mips::ZERO;
3178 }
3179
3180 bool UseTraps = useTraps();
3181
3182 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
3183 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
3184 Warning(IDLoc, "dividing zero by zero");
3185 if (IsMips64) {
3186 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
3187 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003188 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003189 return false;
3190 }
3191
Daniel Sandersa736b372016-04-29 13:33:12 +00003192 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003193 return false;
3194 }
3195 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00003196 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003197 return false;
3198 }
3199 }
3200
3201 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3202 Warning(IDLoc, "division by zero");
3203 if (Signed) {
3204 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003205 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003206 return false;
3207 }
3208
Daniel Sandersa736b372016-04-29 13:33:12 +00003209 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003210 return false;
3211 }
3212 }
3213
3214 // FIXME: The values for these two BranchTarget variables may be different in
3215 // micromips. These magic numbers need to be removed.
3216 unsigned BranchTargetNoTraps;
3217 unsigned BranchTarget;
3218
3219 if (UseTraps) {
3220 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003221 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003222 } else {
3223 BranchTarget = IsMips64 ? 20 : 16;
3224 BranchTargetNoTraps = 8;
3225 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003226 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003227 }
3228
Daniel Sandersa736b372016-04-29 13:33:12 +00003229 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003230
3231 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003232 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003233
3234 if (!Signed) {
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003235 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003236 return false;
3237 }
3238
3239 unsigned ATReg = getATReg(IDLoc);
3240 if (!ATReg)
3241 return true;
3242
Daniel Sandersa736b372016-04-29 13:33:12 +00003243 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003244 if (IsMips64) {
3245 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003246 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3247 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3248 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003249 } else {
3250 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003251 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3252 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003253 }
3254
3255 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003256 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003257 else {
3258 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003259 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3260 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3261 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003262 }
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003263 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003264 return false;
3265}
3266
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003267bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003268 SMLoc IDLoc, MCStreamer &Out,
3269 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003270 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003271
3272 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3273 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3274 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3275
3276 unsigned FirstReg = Inst.getOperand(0).getReg();
3277 unsigned SecondReg = Inst.getOperand(1).getReg();
3278 unsigned ThirdReg = Inst.getOperand(2).getReg();
3279
3280 if (hasMips1() && !hasMips2()) {
3281 unsigned ATReg = getATReg(IDLoc);
3282 if (!ATReg)
3283 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003284 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3285 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3286 TOut.emitNop(IDLoc, STI);
3287 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3288 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3289 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3290 TOut.emitNop(IDLoc, STI);
3291 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3292 : Mips::CVT_W_S,
3293 FirstReg, SecondReg, IDLoc, STI);
3294 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3295 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003296 return false;
3297 }
3298
Daniel Sandersa736b372016-04-29 13:33:12 +00003299 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3300 : Mips::TRUNC_W_S,
3301 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003302
3303 return false;
3304}
3305
Daniel Sanders6394ee52015-10-15 14:52:58 +00003306bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003307 MCStreamer &Out, const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003308 MipsTargetStreamer &TOut = getTargetStreamer();
3309
Toma Tabacud88d79c2015-06-23 14:39:42 +00003310 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003311 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003312 }
3313
3314 warnIfNoMacro(IDLoc);
3315
3316 const MCOperand &DstRegOp = Inst.getOperand(0);
3317 assert(DstRegOp.isReg() && "expected register operand kind");
3318
3319 const MCOperand &SrcRegOp = Inst.getOperand(1);
3320 assert(SrcRegOp.isReg() && "expected register operand kind");
3321
3322 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3323 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3324
3325 unsigned DstReg = DstRegOp.getReg();
3326 unsigned SrcReg = SrcRegOp.getReg();
3327 int64_t OffsetValue = OffsetImmOp.getImm();
3328
3329 // NOTE: We always need AT for ULHU, as it is always used as the source
3330 // register for one of the LBu's.
3331 unsigned ATReg = getATReg(IDLoc);
3332 if (!ATReg)
3333 return true;
3334
3335 // When the value of offset+1 does not fit in 16 bits, we have to load the
3336 // offset in AT, (D)ADDu the original source register (if there was one), and
3337 // then use AT as the source register for the 2 generated LBu's.
3338 bool LoadedOffsetInAT = false;
3339 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3340 LoadedOffsetInAT = true;
3341
3342 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003343 true, IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003344 return true;
3345
3346 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3347 // because it will make our output more similar to GAS'. For example,
3348 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3349 // instead of just an "ori $1, $9, 32768".
3350 // NOTE: If there is no source register specified in the ULHU, the parser
3351 // will interpret it as $0.
3352 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003353 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003354 }
3355
3356 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3357 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3358 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3359
3360 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3361 if (isLittle()) {
3362 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3363 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3364 } else {
3365 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3366 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3367 }
3368
3369 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3370
Daniel Sandersa736b372016-04-29 13:33:12 +00003371 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3372 FirstLbuOffset, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003373
Daniel Sandersa736b372016-04-29 13:33:12 +00003374 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3375 STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003376
Daniel Sandersa736b372016-04-29 13:33:12 +00003377 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003378
Daniel Sandersa736b372016-04-29 13:33:12 +00003379 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003380
3381 return false;
3382}
3383
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003384bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3385 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003386 MipsTargetStreamer &TOut = getTargetStreamer();
3387
Nirav Dave2364748a2016-09-16 18:30:20 +00003388 if (hasMips32r6() || hasMips64r6())
3389 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003390
3391 const MCOperand &DstRegOp = Inst.getOperand(0);
3392 assert(DstRegOp.isReg() && "expected register operand kind");
3393
3394 const MCOperand &SrcRegOp = Inst.getOperand(1);
3395 assert(SrcRegOp.isReg() && "expected register operand kind");
3396
3397 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3398 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3399
3400 unsigned SrcReg = SrcRegOp.getReg();
3401 int64_t OffsetValue = OffsetImmOp.getImm();
3402 unsigned ATReg = 0;
3403
3404 // When the value of offset+3 does not fit in 16 bits, we have to load the
3405 // offset in AT, (D)ADDu the original source register (if there was one), and
3406 // then use AT as the source register for the generated LWL and LWR.
3407 bool LoadedOffsetInAT = false;
3408 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3409 ATReg = getATReg(IDLoc);
3410 if (!ATReg)
3411 return true;
3412 LoadedOffsetInAT = true;
3413
3414 warnIfNoMacro(IDLoc);
3415
3416 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003417 true, IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003418 return true;
3419
3420 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3421 // because it will make our output more similar to GAS'. For example,
3422 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3423 // instead of just an "ori $1, $9, 32768".
3424 // NOTE: If there is no source register specified in the ULW, the parser
3425 // will interpret it as $0.
3426 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003427 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003428 }
3429
3430 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3431 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3432 if (isLittle()) {
3433 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3434 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3435 } else {
3436 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3437 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3438 }
3439
Daniel Sandersa736b372016-04-29 13:33:12 +00003440 TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3441 STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003442
Daniel Sandersa736b372016-04-29 13:33:12 +00003443 TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
3444 IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003445
3446 return false;
3447}
3448
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003449bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003450 MCStreamer &Out,
3451 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003452 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003453
3454 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3455 assert (Inst.getOperand(0).isReg() &&
3456 Inst.getOperand(1).isReg() &&
3457 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3458
3459 unsigned ATReg = Mips::NoRegister;
3460 unsigned FinalDstReg = Mips::NoRegister;
3461 unsigned DstReg = Inst.getOperand(0).getReg();
3462 unsigned SrcReg = Inst.getOperand(1).getReg();
3463 int64_t ImmValue = Inst.getOperand(2).getImm();
3464
3465 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3466
3467 unsigned FinalOpcode = Inst.getOpcode();
3468
3469 if (DstReg == SrcReg) {
3470 ATReg = getATReg(Inst.getLoc());
3471 if (!ATReg)
3472 return true;
3473 FinalDstReg = DstReg;
3474 DstReg = ATReg;
3475 }
3476
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003477 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003478 switch (FinalOpcode) {
3479 default:
3480 llvm_unreachable("unimplemented expansion");
3481 case (Mips::ADDi):
3482 FinalOpcode = Mips::ADD;
3483 break;
3484 case (Mips::ADDiu):
3485 FinalOpcode = Mips::ADDu;
3486 break;
3487 case (Mips::ANDi):
3488 FinalOpcode = Mips::AND;
3489 break;
3490 case (Mips::NORImm):
3491 FinalOpcode = Mips::NOR;
3492 break;
3493 case (Mips::ORi):
3494 FinalOpcode = Mips::OR;
3495 break;
3496 case (Mips::SLTi):
3497 FinalOpcode = Mips::SLT;
3498 break;
3499 case (Mips::SLTiu):
3500 FinalOpcode = Mips::SLTu;
3501 break;
3502 case (Mips::XORi):
3503 FinalOpcode = Mips::XOR;
3504 break;
3505 }
3506
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003507 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003508 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003509 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003510 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003511 return false;
3512 }
3513 return true;
3514}
3515
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003516bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3517 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003518 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003519 unsigned ATReg = Mips::NoRegister;
3520 unsigned DReg = Inst.getOperand(0).getReg();
3521 unsigned SReg = Inst.getOperand(1).getReg();
3522 unsigned TReg = Inst.getOperand(2).getReg();
3523 unsigned TmpReg = DReg;
3524
3525 unsigned FirstShift = Mips::NOP;
3526 unsigned SecondShift = Mips::NOP;
3527
3528 if (hasMips32r2()) {
3529
3530 if (DReg == SReg) {
3531 TmpReg = getATReg(Inst.getLoc());
3532 if (!TmpReg)
3533 return true;
3534 }
3535
3536 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003537 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3538 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003539 return false;
3540 }
3541
3542 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003543 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003544 return false;
3545 }
3546
3547 return true;
3548 }
3549
3550 if (hasMips32()) {
3551
3552 switch (Inst.getOpcode()) {
3553 default:
3554 llvm_unreachable("unexpected instruction opcode");
3555 case Mips::ROL:
3556 FirstShift = Mips::SRLV;
3557 SecondShift = Mips::SLLV;
3558 break;
3559 case Mips::ROR:
3560 FirstShift = Mips::SLLV;
3561 SecondShift = Mips::SRLV;
3562 break;
3563 }
3564
3565 ATReg = getATReg(Inst.getLoc());
3566 if (!ATReg)
3567 return true;
3568
Daniel Sandersa736b372016-04-29 13:33:12 +00003569 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3570 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3571 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3572 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003573
3574 return false;
3575 }
3576
3577 return true;
3578}
3579
3580bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003581 MCStreamer &Out,
3582 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003583 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003584 unsigned ATReg = Mips::NoRegister;
3585 unsigned DReg = Inst.getOperand(0).getReg();
3586 unsigned SReg = Inst.getOperand(1).getReg();
3587 int64_t ImmValue = Inst.getOperand(2).getImm();
3588
3589 unsigned FirstShift = Mips::NOP;
3590 unsigned SecondShift = Mips::NOP;
3591
3592 if (hasMips32r2()) {
3593
3594 if (Inst.getOpcode() == Mips::ROLImm) {
3595 uint64_t MaxShift = 32;
3596 uint64_t ShiftValue = ImmValue;
3597 if (ImmValue != 0)
3598 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003599 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003600 return false;
3601 }
3602
3603 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003604 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003605 return false;
3606 }
3607
3608 return true;
3609 }
3610
3611 if (hasMips32()) {
3612
3613 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003614 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003615 return false;
3616 }
3617
3618 switch (Inst.getOpcode()) {
3619 default:
3620 llvm_unreachable("unexpected instruction opcode");
3621 case Mips::ROLImm:
3622 FirstShift = Mips::SLL;
3623 SecondShift = Mips::SRL;
3624 break;
3625 case Mips::RORImm:
3626 FirstShift = Mips::SRL;
3627 SecondShift = Mips::SLL;
3628 break;
3629 }
3630
3631 ATReg = getATReg(Inst.getLoc());
3632 if (!ATReg)
3633 return true;
3634
Daniel Sandersa736b372016-04-29 13:33:12 +00003635 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3636 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3637 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003638
3639 return false;
3640 }
3641
3642 return true;
3643}
3644
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003645bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3646 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003647 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003648 unsigned ATReg = Mips::NoRegister;
3649 unsigned DReg = Inst.getOperand(0).getReg();
3650 unsigned SReg = Inst.getOperand(1).getReg();
3651 unsigned TReg = Inst.getOperand(2).getReg();
3652 unsigned TmpReg = DReg;
3653
3654 unsigned FirstShift = Mips::NOP;
3655 unsigned SecondShift = Mips::NOP;
3656
3657 if (hasMips64r2()) {
3658
3659 if (TmpReg == SReg) {
3660 TmpReg = getATReg(Inst.getLoc());
3661 if (!TmpReg)
3662 return true;
3663 }
3664
3665 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003666 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3667 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003668 return false;
3669 }
3670
3671 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003672 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003673 return false;
3674 }
3675
3676 return true;
3677 }
3678
3679 if (hasMips64()) {
3680
3681 switch (Inst.getOpcode()) {
3682 default:
3683 llvm_unreachable("unexpected instruction opcode");
3684 case Mips::DROL:
3685 FirstShift = Mips::DSRLV;
3686 SecondShift = Mips::DSLLV;
3687 break;
3688 case Mips::DROR:
3689 FirstShift = Mips::DSLLV;
3690 SecondShift = Mips::DSRLV;
3691 break;
3692 }
3693
3694 ATReg = getATReg(Inst.getLoc());
3695 if (!ATReg)
3696 return true;
3697
Daniel Sandersa736b372016-04-29 13:33:12 +00003698 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3699 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3700 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3701 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003702
3703 return false;
3704 }
3705
3706 return true;
3707}
3708
3709bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003710 MCStreamer &Out,
3711 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003712 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003713 unsigned ATReg = Mips::NoRegister;
3714 unsigned DReg = Inst.getOperand(0).getReg();
3715 unsigned SReg = Inst.getOperand(1).getReg();
3716 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3717
3718 unsigned FirstShift = Mips::NOP;
3719 unsigned SecondShift = Mips::NOP;
3720
3721 MCInst TmpInst;
3722
3723 if (hasMips64r2()) {
3724
3725 unsigned FinalOpcode = Mips::NOP;
3726 if (ImmValue == 0)
3727 FinalOpcode = Mips::DROTR;
3728 else if (ImmValue % 32 == 0)
3729 FinalOpcode = Mips::DROTR32;
3730 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3731 if (Inst.getOpcode() == Mips::DROLImm)
3732 FinalOpcode = Mips::DROTR32;
3733 else
3734 FinalOpcode = Mips::DROTR;
3735 } else if (ImmValue >= 33) {
3736 if (Inst.getOpcode() == Mips::DROLImm)
3737 FinalOpcode = Mips::DROTR;
3738 else
3739 FinalOpcode = Mips::DROTR32;
3740 }
3741
3742 uint64_t ShiftValue = ImmValue % 32;
3743 if (Inst.getOpcode() == Mips::DROLImm)
3744 ShiftValue = (32 - ImmValue % 32) % 32;
3745
Daniel Sandersa736b372016-04-29 13:33:12 +00003746 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003747
3748 return false;
3749 }
3750
3751 if (hasMips64()) {
3752
3753 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003754 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003755 return false;
3756 }
3757
3758 switch (Inst.getOpcode()) {
3759 default:
3760 llvm_unreachable("unexpected instruction opcode");
3761 case Mips::DROLImm:
3762 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3763 FirstShift = Mips::DSLL;
3764 SecondShift = Mips::DSRL32;
3765 }
3766 if (ImmValue == 32) {
3767 FirstShift = Mips::DSLL32;
3768 SecondShift = Mips::DSRL32;
3769 }
3770 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3771 FirstShift = Mips::DSLL32;
3772 SecondShift = Mips::DSRL;
3773 }
3774 break;
3775 case Mips::DRORImm:
3776 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3777 FirstShift = Mips::DSRL;
3778 SecondShift = Mips::DSLL32;
3779 }
3780 if (ImmValue == 32) {
3781 FirstShift = Mips::DSRL32;
3782 SecondShift = Mips::DSLL32;
3783 }
3784 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3785 FirstShift = Mips::DSRL32;
3786 SecondShift = Mips::DSLL;
3787 }
3788 break;
3789 }
3790
3791 ATReg = getATReg(Inst.getLoc());
3792 if (!ATReg)
3793 return true;
3794
Daniel Sandersa736b372016-04-29 13:33:12 +00003795 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3796 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3797 Inst.getLoc(), STI);
3798 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003799
3800 return false;
3801 }
3802
3803 return true;
3804}
3805
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003806bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3807 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003808 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003809 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3810 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3811
Daniel Sandersa736b372016-04-29 13:33:12 +00003812 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003813 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003814 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003815 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003816 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3817 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003818
3819 return false;
3820}
3821
Daniel Sandersc5537422016-07-27 13:49:44 +00003822unsigned
3823MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
3824 const OperandVector &Operands) {
3825 switch (Inst.getOpcode()) {
3826 default:
3827 return Match_Success;
3828 case Mips::DATI:
3829 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00003830 case Mips::DATI_MM64R6:
3831 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00003832 if (static_cast<MipsOperand &>(*Operands[1])
3833 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
3834 return Match_Success;
3835 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00003836 }
3837}
Matheus Almeida595fcab2014-06-11 15:05:56 +00003838unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00003839 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00003840 // As described by the MIPSR6 spec, daui must not use the zero operand for
3841 // its source operand.
3842 case Mips::DAUI:
3843 case Mips::DAUI_MM64R6:
3844 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
3845 Inst.getOperand(1).getReg() == Mips::ZERO_64)
3846 return Match_RequiresNoZeroRegister;
3847 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00003848 // As described by the Mips32r2 spec, the registers Rd and Rs for
3849 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00003850 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00003851 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00003852 case Mips::JALR_HB:
3853 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00003854 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00003855 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
3856 return Match_RequiresDifferentSrcAndDst;
3857 return Match_Success;
3858 case Mips::LWP_MM:
3859 case Mips::LWP_MMR6:
3860 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
3861 return Match_RequiresDifferentSrcAndDst;
3862 return Match_Success;
3863 // As described the MIPSR6 spec, the compact branches that compare registers
3864 // must:
3865 // a) Not use the zero register.
3866 // b) Not use the same register twice.
3867 // c) rs < rt for bnec, beqc.
3868 // NB: For this case, the encoding will swap the operands as their
3869 // ordering doesn't matter. GAS performs this transformation too.
3870 // Hence, that constraint does not have to be enforced.
3871 //
3872 // The compact branches that branch iff the signed addition of two registers
3873 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
3874 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00003875 case Mips::BLEZC: case Mips::BLEZC_MMR6:
3876 case Mips::BGEZC: case Mips::BGEZC_MMR6:
3877 case Mips::BGTZC: case Mips::BGTZC_MMR6:
3878 case Mips::BLTZC: case Mips::BLTZC_MMR6:
3879 case Mips::BEQZC: case Mips::BEQZC_MMR6:
3880 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00003881 case Mips::BLEZC64:
3882 case Mips::BGEZC64:
3883 case Mips::BGTZC64:
3884 case Mips::BLTZC64:
3885 case Mips::BEQZC64:
3886 case Mips::BNEZC64:
3887 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
3888 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00003889 return Match_RequiresNoZeroRegister;
3890 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00003891 case Mips::BGEC: case Mips::BGEC_MMR6:
3892 case Mips::BLTC: case Mips::BLTC_MMR6:
3893 case Mips::BGEUC: case Mips::BGEUC_MMR6:
3894 case Mips::BLTUC: case Mips::BLTUC_MMR6:
3895 case Mips::BEQC: case Mips::BEQC_MMR6:
3896 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00003897 case Mips::BGEC64:
3898 case Mips::BLTC64:
3899 case Mips::BGEUC64:
3900 case Mips::BLTUC64:
3901 case Mips::BEQC64:
3902 case Mips::BNEC64:
3903 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
3904 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00003905 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00003906 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
3907 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00003908 return Match_RequiresNoZeroRegister;
3909 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
3910 return Match_RequiresDifferentOperands;
3911 return Match_Success;
3912 default:
3913 return Match_Success;
3914 }
Matheus Almeida595fcab2014-06-11 15:05:56 +00003915}
3916
Daniel Sanders52da7af2015-11-06 12:11:03 +00003917static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3918 uint64_t ErrorInfo) {
3919 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3920 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3921 if (ErrorLoc == SMLoc())
3922 return Loc;
3923 return ErrorLoc;
3924 }
3925 return Loc;
3926}
3927
David Blaikie960ea3f2014-06-08 16:18:35 +00003928bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3929 OperandVector &Operands,
3930 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003931 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003932 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003933
Jack Carterb4dbc172012-09-05 23:34:03 +00003934 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00003935 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003936 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003937
3938 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003939 case Match_Success: {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003940 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00003941 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003942 return false;
3943 }
3944 case Match_MissingFeature:
3945 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3946 return true;
3947 case Match_InvalidOperand: {
3948 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003949 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003950 if (ErrorInfo >= Operands.size())
3951 return Error(IDLoc, "too few operands for instruction");
3952
Daniel Sanders52da7af2015-11-06 12:11:03 +00003953 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003954 if (ErrorLoc == SMLoc())
3955 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003956 }
3957
3958 return Error(ErrorLoc, "invalid operand for instruction");
3959 }
3960 case Match_MnemonicFail:
3961 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003962 case Match_RequiresDifferentSrcAndDst:
3963 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00003964 case Match_RequiresDifferentOperands:
3965 return Error(IDLoc, "registers must be different");
3966 case Match_RequiresNoZeroRegister:
3967 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00003968 case Match_RequiresSameSrcAndDst:
3969 return Error(IDLoc, "source and destination must match");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003970 case Match_Immz:
3971 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003972 case Match_UImm1_0:
3973 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3974 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003975 case Match_UImm2_0:
3976 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3977 "expected 2-bit unsigned immediate");
3978 case Match_UImm2_1:
3979 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3980 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003981 case Match_UImm3_0:
3982 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3983 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003984 case Match_UImm4_0:
3985 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3986 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003987 case Match_SImm4_0:
3988 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3989 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003990 case Match_UImm5_0:
3991 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3992 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00003993 case Match_SImm5_0:
3994 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3995 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003996 case Match_UImm5_1:
3997 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3998 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003999 case Match_UImm5_32:
4000 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4001 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004002 case Match_UImm5_33:
4003 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4004 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004005 case Match_UImm5_0_Report_UImm6:
4006 // This is used on UImm5 operands that have a corresponding UImm5_32
4007 // operand to avoid confusing the user.
4008 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4009 "expected 6-bit unsigned immediate");
4010 case Match_UImm5_Lsl2:
4011 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4012 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00004013 case Match_UImmRange2_64:
4014 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4015 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00004016 case Match_UImm6_0:
4017 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4018 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00004019 case Match_UImm6_Lsl2:
4020 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4021 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00004022 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00004023 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4024 "expected 6-bit signed immediate");
4025 case Match_UImm7_0:
4026 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4027 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00004028 case Match_UImm7_N1:
4029 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4030 "expected immediate in range -1 .. 126");
4031 case Match_SImm7_Lsl2:
4032 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4033 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00004034 case Match_UImm8_0:
4035 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4036 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00004037 case Match_UImm10_0:
4038 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4039 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00004040 case Match_SImm10_0:
4041 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4042 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00004043 case Match_SImm11_0:
4044 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4045 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00004046 case Match_UImm16:
4047 case Match_UImm16_Relaxed:
4048 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4049 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004050 case Match_SImm16:
4051 case Match_SImm16_Relaxed:
4052 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4053 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00004054 case Match_SImm19_Lsl2:
4055 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4056 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00004057 case Match_UImm20_0:
4058 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4059 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00004060 case Match_UImm26_0:
4061 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4062 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00004063 case Match_SImm32:
4064 case Match_SImm32_Relaxed:
4065 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4066 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00004067 case Match_UImm32_Coerced:
4068 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4069 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00004070 case Match_MemSImm9:
4071 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4072 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00004073 case Match_MemSImm10:
4074 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4075 "expected memory with 10-bit signed offset");
4076 case Match_MemSImm10Lsl1:
4077 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4078 "expected memory with 11-bit signed offset and multiple of 2");
4079 case Match_MemSImm10Lsl2:
4080 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4081 "expected memory with 12-bit signed offset and multiple of 4");
4082 case Match_MemSImm10Lsl3:
4083 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4084 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00004085 case Match_MemSImm11:
4086 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4087 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00004088 case Match_MemSImm12:
4089 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4090 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004091 case Match_MemSImm16:
4092 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4093 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00004094 }
Craig Topper589ceee2015-01-03 08:16:34 +00004095
4096 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00004097}
4098
Toma Tabacud9d344b2015-04-27 14:05:04 +00004099void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
4100 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
4101 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
4102 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004103}
4104
Toma Tabacu81496c12015-05-20 08:54:45 +00004105void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
4106 if (!AssemblerOptions.back()->isMacro())
4107 Warning(Loc, "macro instruction expanded into multiple instructions");
4108}
4109
Daniel Sandersef638fe2014-10-03 15:37:37 +00004110void
4111MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
4112 SMRange Range, bool ShowColors) {
4113 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00004114 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00004115 ShowColors);
4116}
4117
Jack Carter1ac53222013-02-20 23:11:17 +00004118int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004119 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004120
Vladimir Medic4c299852013-11-06 11:27:05 +00004121 CC = StringSwitch<unsigned>(Name)
4122 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004123 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00004124 .Case("a0", 4)
4125 .Case("a1", 5)
4126 .Case("a2", 6)
4127 .Case("a3", 7)
4128 .Case("v0", 2)
4129 .Case("v1", 3)
4130 .Case("s0", 16)
4131 .Case("s1", 17)
4132 .Case("s2", 18)
4133 .Case("s3", 19)
4134 .Case("s4", 20)
4135 .Case("s5", 21)
4136 .Case("s6", 22)
4137 .Case("s7", 23)
4138 .Case("k0", 26)
4139 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004140 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00004141 .Case("sp", 29)
4142 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004143 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00004144 .Case("ra", 31)
4145 .Case("t0", 8)
4146 .Case("t1", 9)
4147 .Case("t2", 10)
4148 .Case("t3", 11)
4149 .Case("t4", 12)
4150 .Case("t5", 13)
4151 .Case("t6", 14)
4152 .Case("t7", 15)
4153 .Case("t8", 24)
4154 .Case("t9", 25)
4155 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004156
Toma Tabacufda445c2014-09-15 15:33:01 +00004157 if (!(isABI_N32() || isABI_N64()))
4158 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004159
Daniel Sandersef638fe2014-10-03 15:37:37 +00004160 if (12 <= CC && CC <= 15) {
4161 // Name is one of t4-t7
4162 AsmToken RegTok = getLexer().peekTok();
4163 SMRange RegRange = RegTok.getLocRange();
4164
4165 StringRef FixedName = StringSwitch<StringRef>(Name)
4166 .Case("t4", "t0")
4167 .Case("t5", "t1")
4168 .Case("t6", "t2")
4169 .Case("t7", "t3")
4170 .Default("");
4171 assert(FixedName != "" && "Register name is not one of t4-t7.");
4172
4173 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
4174 "Did you mean $" + FixedName + "?", RegRange);
4175 }
4176
Toma Tabacufda445c2014-09-15 15:33:01 +00004177 // Although SGI documentation just cuts out t0-t3 for n32/n64,
4178 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
4179 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
4180 if (8 <= CC && CC <= 11)
4181 CC += 4;
4182
4183 if (CC == -1)
4184 CC = StringSwitch<unsigned>(Name)
4185 .Case("a4", 8)
4186 .Case("a5", 9)
4187 .Case("a6", 10)
4188 .Case("a7", 11)
4189 .Case("kt0", 26)
4190 .Case("kt1", 27)
4191 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004192
4193 return CC;
4194}
Jack Carterd0bd6422013-04-18 00:41:53 +00004195
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004196int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
4197 int CC;
4198
4199 CC = StringSwitch<unsigned>(Name)
4200 .Case("hwr_cpunum", 0)
4201 .Case("hwr_synci_step", 1)
4202 .Case("hwr_cc", 2)
4203 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00004204 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004205 .Default(-1);
4206
4207 return CC;
4208}
4209
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004210int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004211
Jack Cartera63b16a2012-09-07 00:23:42 +00004212 if (Name[0] == 'f') {
4213 StringRef NumString = Name.substr(1);
4214 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004215 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004216 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004217 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00004218 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004219 return IntVal;
4220 }
4221 return -1;
4222}
Jack Cartera63b16a2012-09-07 00:23:42 +00004223
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004224int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
4225
4226 if (Name.startswith("fcc")) {
4227 StringRef NumString = Name.substr(3);
4228 unsigned IntVal;
4229 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004230 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004231 if (IntVal > 7) // There are only 8 fcc registers.
4232 return -1;
4233 return IntVal;
4234 }
4235 return -1;
4236}
4237
4238int MipsAsmParser::matchACRegisterName(StringRef Name) {
4239
Akira Hatanaka274d24c2013-08-14 01:15:52 +00004240 if (Name.startswith("ac")) {
4241 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004242 unsigned IntVal;
4243 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004244 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004245 if (IntVal > 3) // There are only 3 acc registers.
4246 return -1;
4247 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00004248 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004249 return -1;
4250}
Jack Carterd0bd6422013-04-18 00:41:53 +00004251
Jack Carter5dc8ac92013-09-25 23:50:44 +00004252int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
4253 unsigned IntVal;
4254
4255 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
4256 return -1;
4257
4258 if (IntVal > 31)
4259 return -1;
4260
4261 return IntVal;
4262}
4263
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004264int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
4265 int CC;
4266
4267 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00004268 .Case("msair", 0)
4269 .Case("msacsr", 1)
4270 .Case("msaaccess", 2)
4271 .Case("msasave", 3)
4272 .Case("msamodify", 4)
4273 .Case("msarequest", 5)
4274 .Case("msamap", 6)
4275 .Case("msaunmap", 7)
4276 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004277
4278 return CC;
4279}
4280
Toma Tabacu89a712b2015-04-15 10:48:56 +00004281unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004282 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004283 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004284 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004285 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004286 return 0;
4287 }
4288 unsigned AT = getReg(
4289 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004290 return AT;
4291}
Jack Carter0b744b32012-10-04 02:29:46 +00004292
Jack Carterd0bd6422013-04-18 00:41:53 +00004293unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004294 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004295}
4296
Toma Tabacu13964452014-09-04 13:23:44 +00004297bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004298 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004299 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004300
Jack Carter30a59822012-10-04 04:03:53 +00004301 // Check if the current operand has a custom associated parser, if so, try to
4302 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004303 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4304 if (ResTy == MatchOperand_Success)
4305 return false;
4306 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4307 // there was a match, but an error occurred, in which case, just return that
4308 // the operand parsing failed.
4309 if (ResTy == MatchOperand_ParseFail)
4310 return true;
4311
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004312 DEBUG(dbgs() << ".. Generic Parser\n");
4313
Jack Carterb4dbc172012-09-05 23:34:03 +00004314 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004315 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004316 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004317 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004318
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004319 // Almost all registers have been parsed by custom parsers. There is only
4320 // one exception to this. $zero (and it's alias $0) will reach this point
4321 // for div, divu, and similar instructions because it is not an operand
4322 // to the instruction definition but an explicit register. Special case
4323 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004324 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004325 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004326
Jack Carterd0bd6422013-04-18 00:41:53 +00004327 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004328 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004329 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004330 return true;
4331
Jack Carter873c7242013-01-12 01:03:14 +00004332 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004333 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004334 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004335 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004336 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004337
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004338 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004339 return false;
4340 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004341 default: {
4342 DEBUG(dbgs() << ".. generic integer expression\n");
4343
4344 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00004345 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004346 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004347 return true;
4348
Jack Carter873c7242013-01-12 01:03:14 +00004349 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4350
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004351 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004352 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004353 }
Jack Carter0b744b32012-10-04 02:29:46 +00004354 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004355 return true;
4356}
4357
Jack Carterb5cf5902013-04-17 00:18:04 +00004358bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4359
4360 switch (Expr->getKind()) {
4361 case MCExpr::Constant:
4362 return true;
4363 case MCExpr::SymbolRef:
4364 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4365 case MCExpr::Binary:
4366 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4367 if (!isEvaluated(BE->getLHS()))
4368 return false;
4369 return isEvaluated(BE->getRHS());
4370 }
4371 case MCExpr::Unary:
4372 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004373 case MCExpr::Target:
4374 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004375 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004376 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004377}
Jack Carterd0bd6422013-04-18 00:41:53 +00004378
Jack Carterb4dbc172012-09-05 23:34:03 +00004379bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4380 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004381 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004382 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004383 if (ResTy == MatchOperand_Success) {
4384 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004385 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004386 StartLoc = Operand.getStartLoc();
4387 EndLoc = Operand.getEndLoc();
4388
4389 // AFAIK, we only support numeric registers and named GPR's in CFI
4390 // directives.
4391 // Don't worry about eating tokens before failing. Using an unrecognised
4392 // register is a parse error.
4393 if (Operand.isGPRAsmReg()) {
4394 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004395 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004396 }
4397
4398 return (RegNo == (unsigned)-1);
4399 }
4400
4401 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004402 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004403}
4404
Jack Carterb5cf5902013-04-17 00:18:04 +00004405bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00004406 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004407
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004408 if (isParenExpr)
4409 return getParser().parseParenExprOfDepth(0, Res, S);
4410 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004411}
4412
David Blaikie960ea3f2014-06-08 16:18:35 +00004413MipsAsmParser::OperandMatchResultTy
4414MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004415 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004416 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004417 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004418 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004419 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004420 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004421 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004422 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004423
Jack Carterb5cf5902013-04-17 00:18:04 +00004424 if (getLexer().getKind() == AsmToken::LParen) {
4425 Parser.Lex();
4426 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004427 }
4428
Jack Carterb5cf5902013-04-17 00:18:04 +00004429 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004430 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004431 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004432
Jack Carterd0bd6422013-04-18 00:41:53 +00004433 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004434 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004435 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004436 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004437 SMLoc E =
4438 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004439 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004440 return MatchOperand_Success;
4441 }
4442 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004443 SMLoc E =
4444 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004445
Jack Carterd0bd6422013-04-18 00:41:53 +00004446 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004447 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00004448 auto Base = MipsOperand::createGPRReg(
4449 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00004450 Operands.push_back(
4451 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004452 return MatchOperand_Success;
4453 }
4454 Error(Parser.getTok().getLoc(), "'(' expected");
4455 return MatchOperand_ParseFail;
4456 }
4457
Jack Carterd0bd6422013-04-18 00:41:53 +00004458 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004459 }
4460
Toma Tabacu13964452014-09-04 13:23:44 +00004461 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004462 if (Res != MatchOperand_Success)
4463 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004464
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004465 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004466 Error(Parser.getTok().getLoc(), "')' expected");
4467 return MatchOperand_ParseFail;
4468 }
4469
Jack Carter873c7242013-01-12 01:03:14 +00004470 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4471
Jack Carterd0bd6422013-04-18 00:41:53 +00004472 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004473
Craig Topper062a2ba2014-04-25 05:30:21 +00004474 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004475 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004476
Jack Carterd0bd6422013-04-18 00:41:53 +00004477 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004478 std::unique_ptr<MipsOperand> op(
4479 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004480 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004481 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004482 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004483 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004484 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4485 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004486 if (IdVal->evaluateAsAbsolute(Imm))
4487 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004488 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004489 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004490 getContext());
4491 }
4492
David Blaikie960ea3f2014-06-08 16:18:35 +00004493 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004494 return MatchOperand_Success;
4495}
4496
David Blaikie960ea3f2014-06-08 16:18:35 +00004497bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004498 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004499 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004500 if (Sym) {
4501 SMLoc S = Parser.getTok().getLoc();
4502 const MCExpr *Expr;
4503 if (Sym->isVariable())
4504 Expr = Sym->getVariableValue();
4505 else
4506 return false;
4507 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004508 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004509 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004510 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004511 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004512 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004513 if (ResTy == MatchOperand_Success) {
4514 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004515 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004516 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004517 llvm_unreachable("Should never ParseFail");
4518 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004519 }
Jack Carterd76b2372013-03-21 21:44:16 +00004520 }
4521 }
4522 return false;
4523}
Jack Carterd0bd6422013-04-18 00:41:53 +00004524
Jack Carter873c7242013-01-12 01:03:14 +00004525MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004526MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004527 StringRef Identifier,
4528 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004529 int Index = matchCPURegisterName(Identifier);
4530 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004531 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004532 Index, Identifier, getContext().getRegisterInfo(), S,
4533 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004534 return MatchOperand_Success;
4535 }
4536
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004537 Index = matchHWRegsRegisterName(Identifier);
4538 if (Index != -1) {
4539 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004540 Index, Identifier, getContext().getRegisterInfo(), S,
4541 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004542 return MatchOperand_Success;
4543 }
4544
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004545 Index = matchFPURegisterName(Identifier);
4546 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004547 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004548 Index, Identifier, getContext().getRegisterInfo(), S,
4549 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004550 return MatchOperand_Success;
4551 }
4552
4553 Index = matchFCCRegisterName(Identifier);
4554 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004555 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004556 Index, Identifier, getContext().getRegisterInfo(), S,
4557 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004558 return MatchOperand_Success;
4559 }
4560
4561 Index = matchACRegisterName(Identifier);
4562 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004563 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004564 Index, Identifier, getContext().getRegisterInfo(), S,
4565 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004566 return MatchOperand_Success;
4567 }
4568
4569 Index = matchMSA128RegisterName(Identifier);
4570 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004571 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004572 Index, Identifier, getContext().getRegisterInfo(), S,
4573 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004574 return MatchOperand_Success;
4575 }
4576
4577 Index = matchMSA128CtrlRegisterName(Identifier);
4578 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004579 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004580 Index, Identifier, getContext().getRegisterInfo(), S,
4581 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004582 return MatchOperand_Success;
4583 }
4584
4585 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004586}
4587
4588MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004589MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004590 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004591 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004592
4593 if (Token.is(AsmToken::Identifier)) {
4594 DEBUG(dbgs() << ".. identifier\n");
4595 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004596 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004597 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004598 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004599 } else if (Token.is(AsmToken::Integer)) {
4600 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004601 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004602 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
4603 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004604 return MatchOperand_Success;
4605 }
4606
4607 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4608
4609 return MatchOperand_NoMatch;
4610}
4611
David Blaikie960ea3f2014-06-08 16:18:35 +00004612MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004613MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004614 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004615 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004616
4617 auto Token = Parser.getTok();
4618
4619 SMLoc S = Token.getLoc();
4620
4621 if (Token.isNot(AsmToken::Dollar)) {
4622 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4623 if (Token.is(AsmToken::Identifier)) {
4624 if (searchSymbolAlias(Operands))
4625 return MatchOperand_Success;
4626 }
4627 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4628 return MatchOperand_NoMatch;
4629 }
4630 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004631
Toma Tabacu13964452014-09-04 13:23:44 +00004632 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004633 if (ResTy == MatchOperand_Success) {
4634 Parser.Lex(); // $
4635 Parser.Lex(); // identifier
4636 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004637 return ResTy;
4638}
4639
4640MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004641MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004642 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004643 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004644
4645 SMLoc S = getLexer().getLoc();
4646
Daniel Sanderscae9aee2016-08-08 09:33:14 +00004647 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004648 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00004649 if (ResTy != MatchOperand_NoMatch)
4650 return ResTy;
4651
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004652 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00004653 const MCExpr *Expr = nullptr;
4654 if (Parser.parseExpression(Expr)) {
4655 // We have no way of knowing if a symbol was consumed so we must ParseFail
4656 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004657 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004658 Operands.push_back(
4659 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004660 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004661}
4662
Vladimir Medic2b953d02013-10-01 09:48:56 +00004663MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004664MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004665 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004666 const MCExpr *IdVal;
4667 // If the first token is '$' we may have register operand.
4668 if (Parser.getTok().is(AsmToken::Dollar))
4669 return MatchOperand_NoMatch;
4670 SMLoc S = Parser.getTok().getLoc();
4671 if (getParser().parseExpression(IdVal))
4672 return MatchOperand_ParseFail;
4673 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004674 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004675 int64_t Val = MCE->getValue();
4676 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4677 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004678 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004679 return MatchOperand_Success;
4680}
4681
Matheus Almeida779c5932013-11-18 12:32:49 +00004682MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004683MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4684 MCAsmParser &Parser = getParser();
4685 SmallVector<unsigned, 10> Regs;
4686 unsigned RegNo;
4687 unsigned PrevReg = Mips::NoRegister;
4688 bool RegRange = false;
4689 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4690
4691 if (Parser.getTok().isNot(AsmToken::Dollar))
4692 return MatchOperand_ParseFail;
4693
4694 SMLoc S = Parser.getTok().getLoc();
4695 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4696 SMLoc E = getLexer().getLoc();
4697 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4698 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4699 if (RegRange) {
4700 // Remove last register operand because registers from register range
4701 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004702 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4703 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004704 Regs.push_back(RegNo);
4705 } else {
4706 unsigned TmpReg = PrevReg + 1;
4707 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004708 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4709 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4710 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004711 Error(E, "invalid register operand");
4712 return MatchOperand_ParseFail;
4713 }
4714
4715 PrevReg = TmpReg;
4716 Regs.push_back(TmpReg++);
4717 }
4718 }
4719
4720 RegRange = false;
4721 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004722 if ((PrevReg == Mips::NoRegister) &&
4723 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4724 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004725 Error(E, "$16 or $31 expected");
4726 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004727 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4728 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4729 !isGP64bit()) ||
4730 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4731 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4732 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004733 Error(E, "invalid register operand");
4734 return MatchOperand_ParseFail;
4735 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004736 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4737 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4738 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004739 Error(E, "consecutive register numbers expected");
4740 return MatchOperand_ParseFail;
4741 }
4742
4743 Regs.push_back(RegNo);
4744 }
4745
4746 if (Parser.getTok().is(AsmToken::Minus))
4747 RegRange = true;
4748
4749 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4750 !Parser.getTok().isNot(AsmToken::Comma)) {
4751 Error(E, "',' or '-' expected");
4752 return MatchOperand_ParseFail;
4753 }
4754
4755 Lex(); // Consume comma or minus
4756 if (Parser.getTok().isNot(AsmToken::Dollar))
4757 break;
4758
4759 PrevReg = RegNo;
4760 }
4761
4762 SMLoc E = Parser.getTok().getLoc();
4763 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4764 parseMemOperand(Operands);
4765 return MatchOperand_Success;
4766}
4767
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004768MipsAsmParser::OperandMatchResultTy
4769MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4770 MCAsmParser &Parser = getParser();
4771
4772 SMLoc S = Parser.getTok().getLoc();
4773 if (parseAnyRegister(Operands) != MatchOperand_Success)
4774 return MatchOperand_ParseFail;
4775
4776 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00004777 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00004778
Benjamin Kramer2b68d152016-05-09 10:31:17 +00004779 Operands.pop_back();
4780 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004781 return MatchOperand_Success;
4782}
4783
Zoran Jovanovic41688672015-02-10 16:36:20 +00004784MipsAsmParser::OperandMatchResultTy
4785MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4786 MCAsmParser &Parser = getParser();
4787 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4788 SmallVector<unsigned, 10> Regs;
4789
4790 if (Parser.getTok().isNot(AsmToken::Dollar))
4791 return MatchOperand_ParseFail;
4792
4793 SMLoc S = Parser.getTok().getLoc();
4794
4795 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4796 return MatchOperand_ParseFail;
4797
4798 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4799 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4800 Regs.push_back(RegNo);
4801
4802 SMLoc E = Parser.getTok().getLoc();
4803 if (Parser.getTok().isNot(AsmToken::Comma)) {
4804 Error(E, "',' expected");
4805 return MatchOperand_ParseFail;
4806 }
4807
4808 // Remove comma.
4809 Parser.Lex();
4810
4811 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4812 return MatchOperand_ParseFail;
4813
4814 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4815 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4816 Regs.push_back(RegNo);
4817
4818 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4819
4820 return MatchOperand_Success;
4821}
4822
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004823/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4824/// either this.
4825/// ::= '(', register, ')'
4826/// handle it before we iterate so we don't get tripped up by the lack of
4827/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004828bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004829 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004830 if (getLexer().is(AsmToken::LParen)) {
4831 Operands.push_back(
4832 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4833 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004834 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004835 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004836 return Error(Loc, "unexpected token in argument list");
4837 }
4838 if (Parser.getTok().isNot(AsmToken::RParen)) {
4839 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004840 return Error(Loc, "unexpected token, expected ')'");
4841 }
4842 Operands.push_back(
4843 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4844 Parser.Lex();
4845 }
4846 return false;
4847}
4848
4849/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4850/// either one of these.
4851/// ::= '[', register, ']'
4852/// ::= '[', integer, ']'
4853/// handle it before we iterate so we don't get tripped up by the lack of
4854/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004855bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004856 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004857 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004858 if (getLexer().is(AsmToken::LBrac)) {
4859 Operands.push_back(
4860 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4861 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004862 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004863 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004864 return Error(Loc, "unexpected token in argument list");
4865 }
4866 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4867 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004868 return Error(Loc, "unexpected token, expected ']'");
4869 }
4870 Operands.push_back(
4871 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4872 Parser.Lex();
4873 }
4874 return false;
4875}
4876
David Blaikie960ea3f2014-06-08 16:18:35 +00004877bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4878 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004879 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004880 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004881
4882 // We have reached first instruction, module directive are now forbidden.
4883 getTargetStreamer().forbidModuleDirective();
4884
Vladimir Medic74593e62013-07-17 15:00:42 +00004885 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004886 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004887 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004888 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004889 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004890 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004891
4892 // Read the remaining operands.
4893 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4894 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004895 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004896 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004897 return Error(Loc, "unexpected token in argument list");
4898 }
Toma Tabacu13964452014-09-04 13:23:44 +00004899 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004900 return true;
4901 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004902
Jack Carterd0bd6422013-04-18 00:41:53 +00004903 while (getLexer().is(AsmToken::Comma)) {
4904 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004905 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004906 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004907 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004908 return Error(Loc, "unexpected token in argument list");
4909 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004910 // Parse bracket and parenthesis suffixes before we iterate
4911 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004912 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004913 return true;
4914 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004915 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004916 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004917 }
4918 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004919 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4920 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004921 return Error(Loc, "unexpected token in argument list");
4922 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004923 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004924 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004925}
4926
Nirav Dave996fc132016-05-05 14:15:46 +00004927// FIXME: Given that these have the same name, these should both be
4928// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004929bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004930 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00004931 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004932}
4933
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004934bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004935 return Error(Loc, ErrorMsg);
4936}
4937
Jack Carter0b744b32012-10-04 02:29:46 +00004938bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004939 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004940 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004941
4942 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004943 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004944
4945 Parser.Lex(); // Eat "noat".
4946
Jack Carterd0bd6422013-04-18 00:41:53 +00004947 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004948 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004949 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004950 return false;
4951 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004952
4953 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004954 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004955 return false;
4956}
Jack Carterd0bd6422013-04-18 00:41:53 +00004957
Jack Carter0b744b32012-10-04 02:29:46 +00004958bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004959 // Line can be: ".set at", which sets $at to $1
4960 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004961 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004962 Parser.Lex(); // Eat "at".
4963
Jack Carter0b744b32012-10-04 02:29:46 +00004964 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004965 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004966 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004967
4968 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004969 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004970 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004971 }
4972
4973 if (getLexer().isNot(AsmToken::Equal)) {
4974 reportParseError("unexpected token, expected equals sign");
4975 return false;
4976 }
4977 Parser.Lex(); // Eat "=".
4978
4979 if (getLexer().isNot(AsmToken::Dollar)) {
4980 if (getLexer().is(AsmToken::EndOfStatement)) {
4981 reportParseError("no register specified");
4982 return false;
4983 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004984 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004985 return false;
4986 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004987 }
4988 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004989
Toma Tabacu16a74492015-02-13 10:30:57 +00004990 // Find out what "reg" is.
4991 unsigned AtRegNo;
4992 const AsmToken &Reg = Parser.getTok();
4993 if (Reg.is(AsmToken::Identifier)) {
4994 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4995 } else if (Reg.is(AsmToken::Integer)) {
4996 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004997 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004998 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004999 return false;
5000 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005001
5002 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00005003 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005004 reportParseError("invalid register");
5005 return false;
5006 }
5007 Parser.Lex(); // Eat "reg".
5008
5009 // If this is not the end of the statement, report an error.
5010 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5011 reportParseError("unexpected token, expected end of statement");
5012 return false;
5013 }
5014
5015 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
5016
5017 Parser.Lex(); // Consume the EndOfStatement.
5018 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005019}
5020
5021bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005022 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005023 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005024 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005025 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005026 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005027 return false;
5028 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005029 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00005030 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005031 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005032 return false;
5033}
5034
5035bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005036 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005037 Parser.Lex();
5038 // If this is not the end of the statement, report an error.
5039 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005040 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005041 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005042 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005043 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005044 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005045 Parser.Lex(); // Consume the EndOfStatement.
5046 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005047}
5048
5049bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005050 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005051 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005052 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005053 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005054 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005055 return false;
5056 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005057 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005058 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005059 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005060 return false;
5061}
5062
5063bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005064 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005065 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005066 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005067 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005068 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005069 return false;
5070 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005071 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005072 reportParseError("`noreorder' must be set before `nomacro'");
5073 return false;
5074 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005075 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005076 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005077 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005078 return false;
5079}
Jack Carterd76b2372013-03-21 21:44:16 +00005080
Daniel Sanders44934432014-08-07 12:03:36 +00005081bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005082 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005083 Parser.Lex();
5084
5085 // If this is not the end of the statement, report an error.
5086 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005087 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005088
5089 setFeatureBits(Mips::FeatureMSA, "msa");
5090 getTargetStreamer().emitDirectiveSetMsa();
5091 return false;
5092}
5093
5094bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005095 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005096 Parser.Lex();
5097
5098 // If this is not the end of the statement, report an error.
5099 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005100 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005101
5102 clearFeatureBits(Mips::FeatureMSA, "msa");
5103 getTargetStreamer().emitDirectiveSetNoMsa();
5104 return false;
5105}
5106
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005107bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005108 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005109 Parser.Lex(); // Eat "nodsp".
5110
5111 // If this is not the end of the statement, report an error.
5112 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5113 reportParseError("unexpected token, expected end of statement");
5114 return false;
5115 }
5116
5117 clearFeatureBits(Mips::FeatureDSP, "dsp");
5118 getTargetStreamer().emitDirectiveSetNoDsp();
5119 return false;
5120}
5121
Toma Tabacucc2502d2014-11-04 17:18:07 +00005122bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005123 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005124 Parser.Lex(); // Eat "mips16".
5125
Jack Carter39536722014-01-22 23:08:42 +00005126 // If this is not the end of the statement, report an error.
5127 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005128 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005129 return false;
5130 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005131
5132 setFeatureBits(Mips::FeatureMips16, "mips16");
5133 getTargetStreamer().emitDirectiveSetMips16();
5134 Parser.Lex(); // Consume the EndOfStatement.
5135 return false;
5136}
5137
5138bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005139 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005140 Parser.Lex(); // Eat "nomips16".
5141
5142 // If this is not the end of the statement, report an error.
5143 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5144 reportParseError("unexpected token, expected end of statement");
5145 return false;
5146 }
5147
5148 clearFeatureBits(Mips::FeatureMips16, "mips16");
5149 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005150 Parser.Lex(); // Consume the EndOfStatement.
5151 return false;
5152}
5153
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005154bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005155 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005156 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005157 // Line can be: .set fp=32
5158 // .set fp=xx
5159 // .set fp=64
5160 Parser.Lex(); // Eat fp token
5161 AsmToken Tok = Parser.getTok();
5162 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005163 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005164 return false;
5165 }
5166 Parser.Lex(); // Eat '=' token.
5167 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005168
5169 if (!parseFpABIValue(FpAbiVal, ".set"))
5170 return false;
5171
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005172 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005173 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005174 return false;
5175 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005176 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005177 Parser.Lex(); // Consume the EndOfStatement.
5178 return false;
5179}
5180
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005181bool MipsAsmParser::parseSetOddSPRegDirective() {
5182 MCAsmParser &Parser = getParser();
5183
5184 Parser.Lex(); // Eat "oddspreg".
5185 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5186 reportParseError("unexpected token, expected end of statement");
5187 return false;
5188 }
5189
5190 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5191 getTargetStreamer().emitDirectiveSetOddSPReg();
5192 return false;
5193}
5194
5195bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5196 MCAsmParser &Parser = getParser();
5197
5198 Parser.Lex(); // Eat "nooddspreg".
5199 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5200 reportParseError("unexpected token, expected end of statement");
5201 return false;
5202 }
5203
5204 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5205 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5206 return false;
5207}
5208
Toma Tabacu9db22db2014-09-09 10:15:38 +00005209bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005210 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005211 SMLoc Loc = getLexer().getLoc();
5212
5213 Parser.Lex();
5214 if (getLexer().isNot(AsmToken::EndOfStatement))
5215 return reportParseError("unexpected token, expected end of statement");
5216
5217 // Always keep an element on the options "stack" to prevent the user
5218 // from changing the initial options. This is how we remember them.
5219 if (AssemblerOptions.size() == 2)
5220 return reportParseError(Loc, ".set pop with no .set push");
5221
Akira Hatanakab11ef082015-11-14 06:35:56 +00005222 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005223 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005224 setAvailableFeatures(
5225 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5226 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005227
5228 getTargetStreamer().emitDirectiveSetPop();
5229 return false;
5230}
5231
5232bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005233 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005234 Parser.Lex();
5235 if (getLexer().isNot(AsmToken::EndOfStatement))
5236 return reportParseError("unexpected token, expected end of statement");
5237
5238 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005239 AssemblerOptions.push_back(
5240 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005241
5242 getTargetStreamer().emitDirectiveSetPush();
5243 return false;
5244}
5245
Toma Tabacu29696502015-06-02 09:48:04 +00005246bool MipsAsmParser::parseSetSoftFloatDirective() {
5247 MCAsmParser &Parser = getParser();
5248 Parser.Lex();
5249 if (getLexer().isNot(AsmToken::EndOfStatement))
5250 return reportParseError("unexpected token, expected end of statement");
5251
5252 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5253 getTargetStreamer().emitDirectiveSetSoftFloat();
5254 return false;
5255}
5256
5257bool MipsAsmParser::parseSetHardFloatDirective() {
5258 MCAsmParser &Parser = getParser();
5259 Parser.Lex();
5260 if (getLexer().isNot(AsmToken::EndOfStatement))
5261 return reportParseError("unexpected token, expected end of statement");
5262
5263 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5264 getTargetStreamer().emitDirectiveSetHardFloat();
5265 return false;
5266}
5267
Jack Carterd76b2372013-03-21 21:44:16 +00005268bool MipsAsmParser::parseSetAssignment() {
5269 StringRef Name;
5270 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005271 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005272
5273 if (Parser.parseIdentifier(Name))
5274 reportParseError("expected identifier after .set");
5275
5276 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005277 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005278 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005279
Jack Carter3b2c96e2014-01-22 23:31:38 +00005280 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005281 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005282
Jim Grosbach6f482002015-05-18 18:43:14 +00005283 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005284 Sym->setVariableValue(Value);
5285
5286 return false;
5287}
Jack Carterd0bd6422013-04-18 00:41:53 +00005288
Toma Tabacu26647792014-09-09 12:52:14 +00005289bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005290 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005291 Parser.Lex();
5292 if (getLexer().isNot(AsmToken::EndOfStatement))
5293 return reportParseError("unexpected token, expected end of statement");
5294
5295 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005296 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005297 setAvailableFeatures(
5298 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5299 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005300 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5301
5302 getTargetStreamer().emitDirectiveSetMips0();
5303 return false;
5304}
5305
Toma Tabacu85618b32014-08-19 14:22:52 +00005306bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005307 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005308 Parser.Lex();
5309 if (getLexer().isNot(AsmToken::Equal))
5310 return reportParseError("unexpected token, expected equals sign");
5311
5312 Parser.Lex();
5313 StringRef Arch;
5314 if (Parser.parseIdentifier(Arch))
5315 return reportParseError("expected arch identifier");
5316
5317 StringRef ArchFeatureName =
5318 StringSwitch<StringRef>(Arch)
5319 .Case("mips1", "mips1")
5320 .Case("mips2", "mips2")
5321 .Case("mips3", "mips3")
5322 .Case("mips4", "mips4")
5323 .Case("mips5", "mips5")
5324 .Case("mips32", "mips32")
5325 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005326 .Case("mips32r3", "mips32r3")
5327 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005328 .Case("mips32r6", "mips32r6")
5329 .Case("mips64", "mips64")
5330 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005331 .Case("mips64r3", "mips64r3")
5332 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005333 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005334 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005335 .Case("r4000", "mips3") // This is an implementation of Mips3.
5336 .Default("");
5337
5338 if (ArchFeatureName.empty())
5339 return reportParseError("unsupported architecture");
5340
5341 selectArch(ArchFeatureName);
5342 getTargetStreamer().emitDirectiveSetArch(Arch);
5343 return false;
5344}
5345
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005346bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005347 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005348 Parser.Lex();
5349 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005350 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005351
Matheus Almeida2852af82014-04-22 10:15:54 +00005352 switch (Feature) {
5353 default:
5354 llvm_unreachable("Unimplemented feature");
5355 case Mips::FeatureDSP:
5356 setFeatureBits(Mips::FeatureDSP, "dsp");
5357 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005358 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005359 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00005360 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00005361 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005362 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005363 case Mips::FeatureMips1:
5364 selectArch("mips1");
5365 getTargetStreamer().emitDirectiveSetMips1();
5366 break;
5367 case Mips::FeatureMips2:
5368 selectArch("mips2");
5369 getTargetStreamer().emitDirectiveSetMips2();
5370 break;
5371 case Mips::FeatureMips3:
5372 selectArch("mips3");
5373 getTargetStreamer().emitDirectiveSetMips3();
5374 break;
5375 case Mips::FeatureMips4:
5376 selectArch("mips4");
5377 getTargetStreamer().emitDirectiveSetMips4();
5378 break;
5379 case Mips::FeatureMips5:
5380 selectArch("mips5");
5381 getTargetStreamer().emitDirectiveSetMips5();
5382 break;
5383 case Mips::FeatureMips32:
5384 selectArch("mips32");
5385 getTargetStreamer().emitDirectiveSetMips32();
5386 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005387 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005388 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005389 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005390 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005391 case Mips::FeatureMips32r3:
5392 selectArch("mips32r3");
5393 getTargetStreamer().emitDirectiveSetMips32R3();
5394 break;
5395 case Mips::FeatureMips32r5:
5396 selectArch("mips32r5");
5397 getTargetStreamer().emitDirectiveSetMips32R5();
5398 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005399 case Mips::FeatureMips32r6:
5400 selectArch("mips32r6");
5401 getTargetStreamer().emitDirectiveSetMips32R6();
5402 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005403 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005404 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005405 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005406 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005407 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005408 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005409 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005410 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005411 case Mips::FeatureMips64r3:
5412 selectArch("mips64r3");
5413 getTargetStreamer().emitDirectiveSetMips64R3();
5414 break;
5415 case Mips::FeatureMips64r5:
5416 selectArch("mips64r5");
5417 getTargetStreamer().emitDirectiveSetMips64R5();
5418 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005419 case Mips::FeatureMips64r6:
5420 selectArch("mips64r6");
5421 getTargetStreamer().emitDirectiveSetMips64R6();
5422 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005423 }
5424 return false;
5425}
5426
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005427bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005428 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005429 if (getLexer().isNot(AsmToken::Comma)) {
5430 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005431 return Error(Loc, ErrorStr);
5432 }
5433
Matheus Almeida2852af82014-04-22 10:15:54 +00005434 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005435 return true;
5436}
5437
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005438// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5439// In this class, it is only used for .cprestore.
5440// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5441// MipsTargetELFStreamer and MipsAsmParser.
5442bool MipsAsmParser::isPicAndNotNxxAbi() {
5443 return inPicMode() && !(isABI_N32() || isABI_N64());
5444}
5445
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005446bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005447 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005448 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005449
Toma Tabacudde4c462014-11-06 10:02:45 +00005450 if (inMips16Mode()) {
5451 reportParseError(".cpload is not supported in Mips16 mode");
5452 return false;
5453 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005454
David Blaikie960ea3f2014-06-08 16:18:35 +00005455 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005456 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005457 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5458 reportParseError("expected register containing function address");
5459 return false;
5460 }
5461
David Blaikie960ea3f2014-06-08 16:18:35 +00005462 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5463 if (!RegOpnd.isGPRAsmReg()) {
5464 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005465 return false;
5466 }
5467
Toma Tabacudde4c462014-11-06 10:02:45 +00005468 // If this is not the end of the statement, report an error.
5469 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5470 reportParseError("unexpected token, expected end of statement");
5471 return false;
5472 }
5473
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005474 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005475 return false;
5476}
5477
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005478bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5479 MCAsmParser &Parser = getParser();
5480
5481 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5482 // is used in non-PIC mode.
5483
5484 if (inMips16Mode()) {
5485 reportParseError(".cprestore is not supported in Mips16 mode");
5486 return false;
5487 }
5488
5489 // Get the stack offset value.
5490 const MCExpr *StackOffset;
5491 int64_t StackOffsetVal;
5492 if (Parser.parseExpression(StackOffset)) {
5493 reportParseError("expected stack offset value");
5494 return false;
5495 }
5496
5497 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5498 reportParseError("stack offset is not an absolute expression");
5499 return false;
5500 }
5501
5502 if (StackOffsetVal < 0) {
5503 Warning(Loc, ".cprestore with negative stack offset has no effect");
5504 IsCpRestoreSet = false;
5505 } else {
5506 IsCpRestoreSet = true;
5507 CpRestoreOffset = StackOffsetVal;
5508 }
5509
5510 // If this is not the end of the statement, report an error.
5511 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5512 reportParseError("unexpected token, expected end of statement");
5513 return false;
5514 }
5515
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005516 if (!getTargetStreamer().emitDirectiveCpRestore(
5517 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005518 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005519 Parser.Lex(); // Consume the EndOfStatement.
5520 return false;
5521}
5522
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005523bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005524 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005525 unsigned FuncReg;
5526 unsigned Save;
5527 bool SaveIsReg = true;
5528
Matheus Almeida7e815762014-06-18 13:08:59 +00005529 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005530 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005531 if (ResTy == MatchOperand_NoMatch) {
5532 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005533 return false;
5534 }
5535
5536 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5537 if (!FuncRegOpnd.isGPRAsmReg()) {
5538 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005539 return false;
5540 }
5541
5542 FuncReg = FuncRegOpnd.getGPR32Reg();
5543 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005544
Toma Tabacu65f10572014-09-16 15:00:52 +00005545 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005546 return true;
5547
Toma Tabacu13964452014-09-04 13:23:44 +00005548 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005549 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005550 const MCExpr *OffsetExpr;
5551 int64_t OffsetVal;
5552 SMLoc ExprLoc = getLexer().getLoc();
5553
5554 if (Parser.parseExpression(OffsetExpr) ||
5555 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5556 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005557 return false;
5558 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005559
5560 Save = OffsetVal;
5561 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005562 } else {
5563 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5564 if (!SaveOpnd.isGPRAsmReg()) {
5565 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005566 return false;
5567 }
5568 Save = SaveOpnd.getGPR32Reg();
5569 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005570
Toma Tabacu65f10572014-09-16 15:00:52 +00005571 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005572 return true;
5573
Toma Tabacu8874eac2015-02-18 13:46:53 +00005574 const MCExpr *Expr;
5575 if (Parser.parseExpression(Expr)) {
5576 reportParseError("expected expression");
5577 return false;
5578 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005579
Toma Tabacu8874eac2015-02-18 13:46:53 +00005580 if (Expr->getKind() != MCExpr::SymbolRef) {
5581 reportParseError("expected symbol");
5582 return false;
5583 }
5584 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5585
Daniel Sandersf173dda2015-09-22 10:50:09 +00005586 CpSaveLocation = Save;
5587 CpSaveLocationIsRegister = SaveIsReg;
5588
Toma Tabacu8874eac2015-02-18 13:46:53 +00005589 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5590 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005591 return false;
5592}
5593
Daniel Sandersf173dda2015-09-22 10:50:09 +00005594bool MipsAsmParser::parseDirectiveCPReturn() {
5595 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5596 CpSaveLocationIsRegister);
5597 return false;
5598}
5599
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005600bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005601 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005602 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5603 const AsmToken &Tok = Parser.getTok();
5604
5605 if (Tok.getString() == "2008") {
5606 Parser.Lex();
5607 getTargetStreamer().emitDirectiveNaN2008();
5608 return false;
5609 } else if (Tok.getString() == "legacy") {
5610 Parser.Lex();
5611 getTargetStreamer().emitDirectiveNaNLegacy();
5612 return false;
5613 }
5614 }
5615 // If we don't recognize the option passed to the .nan
5616 // directive (e.g. no option or unknown option), emit an error.
5617 reportParseError("invalid option in .nan directive");
5618 return false;
5619}
5620
Jack Carter0b744b32012-10-04 02:29:46 +00005621bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005622 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005623 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005624 const AsmToken &Tok = Parser.getTok();
5625
5626 if (Tok.getString() == "noat") {
5627 return parseSetNoAtDirective();
5628 } else if (Tok.getString() == "at") {
5629 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005630 } else if (Tok.getString() == "arch") {
5631 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005632 } else if (Tok.getString() == "fp") {
5633 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005634 } else if (Tok.getString() == "oddspreg") {
5635 return parseSetOddSPRegDirective();
5636 } else if (Tok.getString() == "nooddspreg") {
5637 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005638 } else if (Tok.getString() == "pop") {
5639 return parseSetPopDirective();
5640 } else if (Tok.getString() == "push") {
5641 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005642 } else if (Tok.getString() == "reorder") {
5643 return parseSetReorderDirective();
5644 } else if (Tok.getString() == "noreorder") {
5645 return parseSetNoReorderDirective();
5646 } else if (Tok.getString() == "macro") {
5647 return parseSetMacroDirective();
5648 } else if (Tok.getString() == "nomacro") {
5649 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005650 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005651 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005652 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005653 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005654 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00005655 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005656 getTargetStreamer().emitDirectiveSetNoMicroMips();
5657 Parser.eatToEndOfStatement();
5658 return false;
5659 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005660 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005661 } else if (Tok.getString() == "mips0") {
5662 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005663 } else if (Tok.getString() == "mips1") {
5664 return parseSetFeature(Mips::FeatureMips1);
5665 } else if (Tok.getString() == "mips2") {
5666 return parseSetFeature(Mips::FeatureMips2);
5667 } else if (Tok.getString() == "mips3") {
5668 return parseSetFeature(Mips::FeatureMips3);
5669 } else if (Tok.getString() == "mips4") {
5670 return parseSetFeature(Mips::FeatureMips4);
5671 } else if (Tok.getString() == "mips5") {
5672 return parseSetFeature(Mips::FeatureMips5);
5673 } else if (Tok.getString() == "mips32") {
5674 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005675 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005676 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005677 } else if (Tok.getString() == "mips32r3") {
5678 return parseSetFeature(Mips::FeatureMips32r3);
5679 } else if (Tok.getString() == "mips32r5") {
5680 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005681 } else if (Tok.getString() == "mips32r6") {
5682 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005683 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005684 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005685 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005686 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005687 } else if (Tok.getString() == "mips64r3") {
5688 return parseSetFeature(Mips::FeatureMips64r3);
5689 } else if (Tok.getString() == "mips64r5") {
5690 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005691 } else if (Tok.getString() == "mips64r6") {
5692 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005693 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005694 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005695 } else if (Tok.getString() == "nodsp") {
5696 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005697 } else if (Tok.getString() == "msa") {
5698 return parseSetMsaDirective();
5699 } else if (Tok.getString() == "nomsa") {
5700 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005701 } else if (Tok.getString() == "softfloat") {
5702 return parseSetSoftFloatDirective();
5703 } else if (Tok.getString() == "hardfloat") {
5704 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005705 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005706 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005707 parseSetAssignment();
5708 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005709 }
Jack Carter07c818d2013-01-25 01:31:34 +00005710
Jack Carter0b744b32012-10-04 02:29:46 +00005711 return true;
5712}
5713
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005714/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005715/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005716bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005717 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005718 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5719 for (;;) {
5720 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005721 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005722 return true;
5723
5724 getParser().getStreamer().EmitValue(Value, Size);
5725
5726 if (getLexer().is(AsmToken::EndOfStatement))
5727 break;
5728
Jack Carter07c818d2013-01-25 01:31:34 +00005729 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005730 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005731 Parser.Lex();
5732 }
5733 }
5734
5735 Parser.Lex();
5736 return false;
5737}
5738
Vladimir Medic4c299852013-11-06 11:27:05 +00005739/// parseDirectiveGpWord
5740/// ::= .gpword local_sym
5741bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005742 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005743 const MCExpr *Value;
5744 // EmitGPRel32Value requires an expression, so we are using base class
5745 // method to evaluate the expression.
5746 if (getParser().parseExpression(Value))
5747 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005748 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005749
Vladimir Medice10c1122013-11-13 13:18:04 +00005750 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005751 return Error(getLexer().getLoc(),
5752 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005753 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005754 return false;
5755}
5756
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005757/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005758/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005759bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005760 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005761 const MCExpr *Value;
5762 // EmitGPRel64Value requires an expression, so we are using base class
5763 // method to evaluate the expression.
5764 if (getParser().parseExpression(Value))
5765 return true;
5766 getParser().getStreamer().EmitGPRel64Value(Value);
5767
5768 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00005769 return Error(getLexer().getLoc(),
5770 "unexpected token, expected end of statement");
5771 Parser.Lex(); // Eat EndOfStatement token.
5772 return false;
5773}
5774
5775/// parseDirectiveDtpRelWord
5776/// ::= .dtprelword tls_sym
5777bool MipsAsmParser::parseDirectiveDtpRelWord() {
5778 MCAsmParser &Parser = getParser();
5779 const MCExpr *Value;
5780 // EmitDTPRel32Value requires an expression, so we are using base class
5781 // method to evaluate the expression.
5782 if (getParser().parseExpression(Value))
5783 return true;
5784 getParser().getStreamer().EmitDTPRel32Value(Value);
5785
5786 if (getLexer().isNot(AsmToken::EndOfStatement))
5787 return Error(getLexer().getLoc(),
5788 "unexpected token, expected end of statement");
5789 Parser.Lex(); // Eat EndOfStatement token.
5790 return false;
5791}
5792
5793/// parseDirectiveDtpRelDWord
5794/// ::= .dtpreldword tls_sym
5795bool MipsAsmParser::parseDirectiveDtpRelDWord() {
5796 MCAsmParser &Parser = getParser();
5797 const MCExpr *Value;
5798 // EmitDTPRel64Value requires an expression, so we are using base class
5799 // method to evaluate the expression.
5800 if (getParser().parseExpression(Value))
5801 return true;
5802 getParser().getStreamer().EmitDTPRel64Value(Value);
5803
5804 if (getLexer().isNot(AsmToken::EndOfStatement))
5805 return Error(getLexer().getLoc(),
5806 "unexpected token, expected end of statement");
5807 Parser.Lex(); // Eat EndOfStatement token.
5808 return false;
5809}
5810
5811/// parseDirectiveTpRelWord
5812/// ::= .tprelword tls_sym
5813bool MipsAsmParser::parseDirectiveTpRelWord() {
5814 MCAsmParser &Parser = getParser();
5815 const MCExpr *Value;
5816 // EmitTPRel32Value requires an expression, so we are using base class
5817 // method to evaluate the expression.
5818 if (getParser().parseExpression(Value))
5819 return true;
5820 getParser().getStreamer().EmitTPRel32Value(Value);
5821
5822 if (getLexer().isNot(AsmToken::EndOfStatement))
5823 return Error(getLexer().getLoc(),
5824 "unexpected token, expected end of statement");
5825 Parser.Lex(); // Eat EndOfStatement token.
5826 return false;
5827}
5828
5829/// parseDirectiveTpRelDWord
5830/// ::= .tpreldword tls_sym
5831bool MipsAsmParser::parseDirectiveTpRelDWord() {
5832 MCAsmParser &Parser = getParser();
5833 const MCExpr *Value;
5834 // EmitTPRel64Value requires an expression, so we are using base class
5835 // method to evaluate the expression.
5836 if (getParser().parseExpression(Value))
5837 return true;
5838 getParser().getStreamer().EmitTPRel64Value(Value);
5839
5840 if (getLexer().isNot(AsmToken::EndOfStatement))
5841 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005842 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005843 Parser.Lex(); // Eat EndOfStatement token.
5844 return false;
5845}
5846
Jack Carter0cd3c192014-01-06 23:27:31 +00005847bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005848 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005849 // Get the option token.
5850 AsmToken Tok = Parser.getTok();
5851 // At the moment only identifiers are supported.
5852 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00005853 return Error(Parser.getTok().getLoc(),
5854 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005855 }
5856
5857 StringRef Option = Tok.getIdentifier();
5858
5859 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005860 // MipsAsmParser needs to know if the current PIC mode changes.
5861 IsPicEnabled = false;
5862
Jack Carter0cd3c192014-01-06 23:27:31 +00005863 getTargetStreamer().emitDirectiveOptionPic0();
5864 Parser.Lex();
5865 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00005866 return Error(Parser.getTok().getLoc(),
5867 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005868 }
5869 return false;
5870 }
5871
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005872 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005873 // MipsAsmParser needs to know if the current PIC mode changes.
5874 IsPicEnabled = true;
5875
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005876 getTargetStreamer().emitDirectiveOptionPic2();
5877 Parser.Lex();
5878 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00005879 return Error(Parser.getTok().getLoc(),
5880 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005881 }
5882 return false;
5883 }
5884
Jack Carter0cd3c192014-01-06 23:27:31 +00005885 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005886 Warning(Parser.getTok().getLoc(),
5887 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005888 Parser.eatToEndOfStatement();
5889 return false;
5890}
5891
Toma Tabacu9ca50962015-04-16 09:53:47 +00005892/// parseInsnDirective
5893/// ::= .insn
5894bool MipsAsmParser::parseInsnDirective() {
5895 // If this is not the end of the statement, report an error.
5896 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5897 reportParseError("unexpected token, expected end of statement");
5898 return false;
5899 }
5900
5901 // The actual label marking happens in
5902 // MipsELFStreamer::createPendingLabelRelocs().
5903 getTargetStreamer().emitDirectiveInsn();
5904
5905 getParser().Lex(); // Eat EndOfStatement token.
5906 return false;
5907}
5908
Simon Atanasyanbe186202016-02-11 06:45:54 +00005909/// parseSSectionDirective
5910/// ::= .sbss
5911/// ::= .sdata
5912bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5913 // If this is not the end of the statement, report an error.
5914 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5915 reportParseError("unexpected token, expected end of statement");
5916 return false;
5917 }
5918
5919 MCSection *ELFSection = getContext().getELFSection(
5920 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5921 getParser().getStreamer().SwitchSection(ELFSection);
5922
5923 getParser().Lex(); // Eat EndOfStatement token.
5924 return false;
5925}
5926
Daniel Sanders7e527422014-07-10 13:38:23 +00005927/// parseDirectiveModule
5928/// ::= .module oddspreg
5929/// ::= .module nooddspreg
5930/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005931/// ::= .module softfloat
5932/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005933bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005934 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005935 MCAsmLexer &Lexer = getLexer();
5936 SMLoc L = Lexer.getLoc();
5937
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005938 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005939 // TODO : get a better message.
5940 reportParseError(".module directive must appear before any code");
5941 return false;
5942 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005943
Toma Tabacuc405c822015-01-23 10:40:19 +00005944 StringRef Option;
5945 if (Parser.parseIdentifier(Option)) {
5946 reportParseError("expected .module option identifier");
5947 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005948 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005949
Toma Tabacuc405c822015-01-23 10:40:19 +00005950 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005951 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005952
Toma Tabacu3c499582015-06-25 10:56:57 +00005953 // Synchronize the abiflags information with the FeatureBits information we
5954 // changed above.
5955 getTargetStreamer().updateABIInfo(*this);
5956
5957 // If printing assembly, use the recently updated abiflags information.
5958 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5959 // emitted at the end).
5960 getTargetStreamer().emitDirectiveModuleOddSPReg();
5961
Toma Tabacuc405c822015-01-23 10:40:19 +00005962 // If this is not the end of the statement, report an error.
5963 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5964 reportParseError("unexpected token, expected end of statement");
5965 return false;
5966 }
5967
5968 return false; // parseDirectiveModule has finished successfully.
5969 } else if (Option == "nooddspreg") {
5970 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00005971 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00005972 }
5973
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005974 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005975
Toma Tabacu3c499582015-06-25 10:56:57 +00005976 // Synchronize the abiflags information with the FeatureBits information we
5977 // changed above.
5978 getTargetStreamer().updateABIInfo(*this);
5979
5980 // If printing assembly, use the recently updated abiflags information.
5981 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5982 // emitted at the end).
5983 getTargetStreamer().emitDirectiveModuleOddSPReg();
5984
Toma Tabacuc405c822015-01-23 10:40:19 +00005985 // If this is not the end of the statement, report an error.
5986 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5987 reportParseError("unexpected token, expected end of statement");
5988 return false;
5989 }
5990
5991 return false; // parseDirectiveModule has finished successfully.
5992 } else if (Option == "fp") {
5993 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005994 } else if (Option == "softfloat") {
5995 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5996
5997 // Synchronize the ABI Flags information with the FeatureBits information we
5998 // updated above.
5999 getTargetStreamer().updateABIInfo(*this);
6000
6001 // If printing assembly, use the recently updated ABI Flags information.
6002 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6003 // emitted later).
6004 getTargetStreamer().emitDirectiveModuleSoftFloat();
6005
6006 // If this is not the end of the statement, report an error.
6007 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6008 reportParseError("unexpected token, expected end of statement");
6009 return false;
6010 }
6011
6012 return false; // parseDirectiveModule has finished successfully.
6013 } else if (Option == "hardfloat") {
6014 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6015
6016 // Synchronize the ABI Flags information with the FeatureBits information we
6017 // updated above.
6018 getTargetStreamer().updateABIInfo(*this);
6019
6020 // If printing assembly, use the recently updated ABI Flags information.
6021 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6022 // emitted later).
6023 getTargetStreamer().emitDirectiveModuleHardFloat();
6024
6025 // If this is not the end of the statement, report an error.
6026 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6027 reportParseError("unexpected token, expected end of statement");
6028 return false;
6029 }
6030
6031 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00006032 } else {
6033 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
6034 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006035}
6036
6037/// parseDirectiveModuleFP
6038/// ::= =32
6039/// ::= =xx
6040/// ::= =64
6041bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006042 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006043 MCAsmLexer &Lexer = getLexer();
6044
6045 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006046 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006047 return false;
6048 }
6049 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006050
Daniel Sanders7e527422014-07-10 13:38:23 +00006051 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006052 if (!parseFpABIValue(FpABI, ".module"))
6053 return false;
6054
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006055 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006056 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006057 return false;
6058 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006059
Toma Tabacua64e5402015-06-25 12:44:38 +00006060 // Synchronize the abiflags information with the FeatureBits information we
6061 // changed above.
6062 getTargetStreamer().updateABIInfo(*this);
6063
6064 // If printing assembly, use the recently updated abiflags information.
6065 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6066 // emitted at the end).
6067 getTargetStreamer().emitDirectiveModuleFP();
6068
Daniel Sanders7e527422014-07-10 13:38:23 +00006069 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006070 return false;
6071}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006072
Daniel Sanders7e527422014-07-10 13:38:23 +00006073bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006074 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006075 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006076 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006077 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006078
6079 if (Lexer.is(AsmToken::Identifier)) {
6080 StringRef Value = Parser.getTok().getString();
6081 Parser.Lex();
6082
6083 if (Value != "xx") {
6084 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6085 return false;
6086 }
6087
6088 if (!isABI_O32()) {
6089 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
6090 return false;
6091 }
6092
Daniel Sanders7e527422014-07-10 13:38:23 +00006093 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006094 if (ModuleLevelOptions) {
6095 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6096 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6097 } else {
6098 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6099 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6100 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006101 return true;
6102 }
6103
6104 if (Lexer.is(AsmToken::Integer)) {
6105 unsigned Value = Parser.getTok().getIntVal();
6106 Parser.Lex();
6107
6108 if (Value != 32 && Value != 64) {
6109 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6110 return false;
6111 }
6112
6113 if (Value == 32) {
6114 if (!isABI_O32()) {
6115 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6116 return false;
6117 }
6118
Daniel Sanders7e527422014-07-10 13:38:23 +00006119 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006120 if (ModuleLevelOptions) {
6121 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6122 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6123 } else {
6124 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6125 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6126 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006127 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006128 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006129 if (ModuleLevelOptions) {
6130 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6131 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6132 } else {
6133 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6134 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6135 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006136 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006137
Daniel Sanders7e527422014-07-10 13:38:23 +00006138 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006139 }
6140
6141 return false;
6142}
6143
Jack Carter0b744b32012-10-04 02:29:46 +00006144bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006145 // This returns false if this function recognizes the directive
6146 // regardless of whether it is successfully handles or reports an
6147 // error. Otherwise it returns true to give the generic parser a
6148 // chance at recognizing it.
6149
Rafael Espindola961d4692014-11-11 05:18:41 +00006150 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006151 StringRef IDVal = DirectiveID.getString();
6152
Nirav Dave996fc132016-05-05 14:15:46 +00006153 if (IDVal == ".cpload") {
6154 parseDirectiveCpLoad(DirectiveID.getLoc());
6155 return false;
6156 }
6157 if (IDVal == ".cprestore") {
6158 parseDirectiveCpRestore(DirectiveID.getLoc());
6159 return false;
6160 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006161 if (IDVal == ".dword") {
6162 parseDataDirective(8, DirectiveID.getLoc());
6163 return false;
6164 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006165 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006166 StringRef SymbolName;
6167
6168 if (Parser.parseIdentifier(SymbolName)) {
6169 reportParseError("expected identifier after .ent");
6170 return false;
6171 }
6172
6173 // There's an undocumented extension that allows an integer to
6174 // follow the name of the procedure which AFAICS is ignored by GAS.
6175 // Example: .ent foo,2
6176 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6177 if (getLexer().isNot(AsmToken::Comma)) {
6178 // Even though we accept this undocumented extension for compatibility
6179 // reasons, the additional integer argument does not actually change
6180 // the behaviour of the '.ent' directive, so we would like to discourage
6181 // its use. We do this by not referring to the extended version in
6182 // error messages which are not directly related to its use.
6183 reportParseError("unexpected token, expected end of statement");
6184 return false;
6185 }
6186 Parser.Lex(); // Eat the comma.
6187 const MCExpr *DummyNumber;
6188 int64_t DummyNumberVal;
6189 // If the user was explicitly trying to use the extended version,
6190 // we still give helpful extension-related error messages.
6191 if (Parser.parseExpression(DummyNumber)) {
6192 reportParseError("expected number after comma");
6193 return false;
6194 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006195 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006196 reportParseError("expected an absolute expression after comma");
6197 return false;
6198 }
6199 }
6200
6201 // If this is not the end of the statement, report an error.
6202 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6203 reportParseError("unexpected token, expected end of statement");
6204 return false;
6205 }
6206
Jim Grosbach6f482002015-05-18 18:43:14 +00006207 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006208
6209 getTargetStreamer().emitDirectiveEnt(*Sym);
6210 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006211 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006212 return false;
6213 }
6214
Jack Carter07c818d2013-01-25 01:31:34 +00006215 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006216 StringRef SymbolName;
6217
6218 if (Parser.parseIdentifier(SymbolName)) {
6219 reportParseError("expected identifier after .end");
6220 return false;
6221 }
6222
6223 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6224 reportParseError("unexpected token, expected end of statement");
6225 return false;
6226 }
6227
6228 if (CurrentFn == nullptr) {
6229 reportParseError(".end used without .ent");
6230 return false;
6231 }
6232
6233 if ((SymbolName != CurrentFn->getName())) {
6234 reportParseError(".end symbol does not match .ent symbol");
6235 return false;
6236 }
6237
6238 getTargetStreamer().emitDirectiveEnd(SymbolName);
6239 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006240 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006241 return false;
6242 }
6243
Jack Carter07c818d2013-01-25 01:31:34 +00006244 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006245 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6246 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006247 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006248 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6249 reportParseError("expected stack register");
6250 return false;
6251 }
6252
6253 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6254 if (!StackRegOpnd.isGPRAsmReg()) {
6255 reportParseError(StackRegOpnd.getStartLoc(),
6256 "expected general purpose register");
6257 return false;
6258 }
6259 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6260
6261 if (Parser.getTok().is(AsmToken::Comma))
6262 Parser.Lex();
6263 else {
6264 reportParseError("unexpected token, expected comma");
6265 return false;
6266 }
6267
6268 // Parse the frame size.
6269 const MCExpr *FrameSize;
6270 int64_t FrameSizeVal;
6271
6272 if (Parser.parseExpression(FrameSize)) {
6273 reportParseError("expected frame size value");
6274 return false;
6275 }
6276
Jim Grosbach13760bd2015-05-30 01:25:56 +00006277 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006278 reportParseError("frame size not an absolute expression");
6279 return false;
6280 }
6281
6282 if (Parser.getTok().is(AsmToken::Comma))
6283 Parser.Lex();
6284 else {
6285 reportParseError("unexpected token, expected comma");
6286 return false;
6287 }
6288
6289 // Parse the return register.
6290 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006291 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006292 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6293 reportParseError("expected return register");
6294 return false;
6295 }
6296
6297 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6298 if (!ReturnRegOpnd.isGPRAsmReg()) {
6299 reportParseError(ReturnRegOpnd.getStartLoc(),
6300 "expected general purpose register");
6301 return false;
6302 }
6303
6304 // If this is not the end of the statement, report an error.
6305 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6306 reportParseError("unexpected token, expected end of statement");
6307 return false;
6308 }
6309
6310 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6311 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006312 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006313 return false;
6314 }
6315
Jack Carter07c818d2013-01-25 01:31:34 +00006316 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006317 parseDirectiveSet();
6318 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006319 }
6320
Daniel Sandersd97a6342014-08-13 10:07:34 +00006321 if (IDVal == ".mask" || IDVal == ".fmask") {
6322 // .mask bitmask, frame_offset
6323 // bitmask: One bit for each register used.
6324 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6325 // first register is expected to be saved.
6326 // Examples:
6327 // .mask 0x80000000, -4
6328 // .fmask 0x80000000, -4
6329 //
Jack Carterbe332172012-09-07 00:48:02 +00006330
Daniel Sandersd97a6342014-08-13 10:07:34 +00006331 // Parse the bitmask
6332 const MCExpr *BitMask;
6333 int64_t BitMaskVal;
6334
6335 if (Parser.parseExpression(BitMask)) {
6336 reportParseError("expected bitmask value");
6337 return false;
6338 }
6339
Jim Grosbach13760bd2015-05-30 01:25:56 +00006340 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006341 reportParseError("bitmask not an absolute expression");
6342 return false;
6343 }
6344
6345 if (Parser.getTok().is(AsmToken::Comma))
6346 Parser.Lex();
6347 else {
6348 reportParseError("unexpected token, expected comma");
6349 return false;
6350 }
6351
6352 // Parse the frame_offset
6353 const MCExpr *FrameOffset;
6354 int64_t FrameOffsetVal;
6355
6356 if (Parser.parseExpression(FrameOffset)) {
6357 reportParseError("expected frame offset value");
6358 return false;
6359 }
6360
Jim Grosbach13760bd2015-05-30 01:25:56 +00006361 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006362 reportParseError("frame offset not an absolute expression");
6363 return false;
6364 }
6365
6366 // If this is not the end of the statement, report an error.
6367 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6368 reportParseError("unexpected token, expected end of statement");
6369 return false;
6370 }
6371
6372 if (IDVal == ".mask")
6373 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6374 else
6375 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006376 return false;
6377 }
6378
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006379 if (IDVal == ".nan")
6380 return parseDirectiveNaN();
6381
Jack Carter07c818d2013-01-25 01:31:34 +00006382 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006383 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006384 return false;
6385 }
6386
Rafael Espindolab59fb732014-03-28 18:50:26 +00006387 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006388 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006389 return false;
6390 }
6391
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006392 if (IDVal == ".dtprelword") {
6393 parseDirectiveDtpRelWord();
6394 return false;
6395 }
6396
6397 if (IDVal == ".dtpreldword") {
6398 parseDirectiveDtpRelDWord();
6399 return false;
6400 }
6401
6402 if (IDVal == ".tprelword") {
6403 parseDirectiveTpRelWord();
6404 return false;
6405 }
6406
6407 if (IDVal == ".tpreldword") {
6408 parseDirectiveTpRelDWord();
6409 return false;
6410 }
6411
Jack Carter07c818d2013-01-25 01:31:34 +00006412 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006413 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006414 return false;
6415 }
6416
Scott Egertond1aeb052016-02-15 16:11:51 +00006417 if (IDVal == ".hword") {
6418 parseDataDirective(2, DirectiveID.getLoc());
6419 return false;
6420 }
6421
Nirav Dave996fc132016-05-05 14:15:46 +00006422 if (IDVal == ".option") {
6423 parseDirectiveOption();
6424 return false;
6425 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006426
6427 if (IDVal == ".abicalls") {
6428 getTargetStreamer().emitDirectiveAbiCalls();
6429 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006430 Error(Parser.getTok().getLoc(),
6431 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006432 }
6433 return false;
6434 }
6435
Nirav Dave996fc132016-05-05 14:15:46 +00006436 if (IDVal == ".cpsetup") {
6437 parseDirectiveCPSetup();
6438 return false;
6439 }
6440 if (IDVal == ".cpreturn") {
6441 parseDirectiveCPReturn();
6442 return false;
6443 }
6444 if (IDVal == ".module") {
6445 parseDirectiveModule();
6446 return false;
6447 }
6448 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6449 parseInternalDirectiveReallowModule();
6450 return false;
6451 }
6452 if (IDVal == ".insn") {
6453 parseInsnDirective();
6454 return false;
6455 }
6456 if (IDVal == ".sbss") {
6457 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6458 return false;
6459 }
6460 if (IDVal == ".sdata") {
6461 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6462 return false;
6463 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006464
Rafael Espindola870c4e92012-01-11 03:56:41 +00006465 return true;
6466}
6467
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006468bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6469 // If this is not the end of the statement, report an error.
6470 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6471 reportParseError("unexpected token, expected end of statement");
6472 return false;
6473 }
6474
6475 getTargetStreamer().reallowModuleDirective();
6476
6477 getParser().Lex(); // Eat EndOfStatement token.
6478 return false;
6479}
6480
Rafael Espindola870c4e92012-01-11 03:56:41 +00006481extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00006482 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
6483 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
6484 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
6485 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00006486}
Jack Carterb4dbc172012-09-05 23:34:03 +00006487
6488#define GET_REGISTER_MATCHER
6489#define GET_MATCHER_IMPLEMENTATION
6490#include "MipsGenAsmMatcher.inc"