blob: ec8873289d62d28634f9fbe34d2827f7a08385d3 [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
Simon Dardisaff4d142016-10-18 14:28:00 +0000252 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
253 const MCSubtargetInfo *STI, bool IsLoad);
254
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000255 bool reportParseError(Twine ErrorMsg);
256 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000257
Jack Carterb5cf5902013-04-17 00:18:04 +0000258 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000259
260 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000261 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000262 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000263 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000264 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000265 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000266 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000267 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000268 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000269 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000270 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000271 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000272 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000273 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000274
275 bool parseSetAtDirective();
276 bool parseSetNoAtDirective();
277 bool parseSetMacroDirective();
278 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000279 bool parseSetMsaDirective();
280 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000281 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000282 bool parseSetReorderDirective();
283 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000284 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000285 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000286 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000287 bool parseSetOddSPRegDirective();
288 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000289 bool parseSetPopDirective();
290 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000291 bool parseSetSoftFloatDirective();
292 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000293
Jack Carterd76b2372013-03-21 21:44:16 +0000294 bool parseSetAssignment();
295
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000296 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000297 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000298 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000299 bool parseDirectiveDtpRelWord();
300 bool parseDirectiveDtpRelDWord();
301 bool parseDirectiveTpRelWord();
302 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000303 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000304 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000305 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
306 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000307
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000308 bool parseInternalDirectiveReallowModule();
309
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000310 bool eatComma(StringRef ErrorStr);
311
Jack Carter1ac53222013-02-20 23:11:17 +0000312 int matchCPURegisterName(StringRef Symbol);
313
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000314 int matchHWRegsRegisterName(StringRef Symbol);
315
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000316 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000317
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000318 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000319
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000320 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000321
Jack Carter5dc8ac92013-09-25 23:50:44 +0000322 int matchMSA128RegisterName(StringRef Name);
323
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000324 int matchMSA128CtrlRegisterName(StringRef Name);
325
Jack Carterd0bd6422013-04-18 00:41:53 +0000326 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000327
Toma Tabacu89a712b2015-04-15 10:48:56 +0000328 /// Returns the internal register number for the current AT. Also checks if
329 /// the current AT is unavailable (set to $0) and gives an error if it is.
330 /// This should be used in pseudo-instruction expansions which need AT.
331 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000332
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000333 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
334 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000335
336 // Helper function that checks if the value of a vector index is within the
337 // boundaries of accepted values for each RegisterKind
338 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
339 bool validateMSAIndex(int Val, int RegKind);
340
Daniel Sandersf0df2212014-08-04 12:20:00 +0000341 // Selects a new architecture by updating the FeatureBits with the necessary
342 // info including implied dependencies.
343 // Internally, it clears all the feature bits related to *any* architecture
344 // and selects the new one using the ToggleFeature functionality of the
345 // MCSubtargetInfo object that handles implied dependencies. The reason we
346 // clear all the arch related bits manually is because ToggleFeature only
347 // clears the features that imply the feature being cleared and not the
348 // features implied by the feature being cleared. This is easier to see
349 // with an example:
350 // --------------------------------------------------
351 // | Feature | Implies |
352 // | -------------------------------------------------|
353 // | FeatureMips1 | None |
354 // | FeatureMips2 | FeatureMips1 |
355 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
356 // | FeatureMips4 | FeatureMips3 |
357 // | ... | |
358 // --------------------------------------------------
359 //
360 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
361 // FeatureMipsGP64 | FeatureMips1)
362 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
363 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000364 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000365 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000366 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
367 STI.setFeatureBits(FeatureBits);
368 setAvailableFeatures(
369 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000370 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000371 }
372
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000373 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000374 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000375 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000376 setAvailableFeatures(
377 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000378 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000379 }
380 }
381
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000382 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000383 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000384 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000385 setAvailableFeatures(
386 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000387 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000388 }
389 }
390
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000391 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
392 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000393 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000394 }
395
396 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
397 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000398 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000399 }
400
Rafael Espindola870c4e92012-01-11 03:56:41 +0000401public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000402 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000403 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000404 Match_RequiresDifferentOperands,
405 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000406 Match_RequiresSameSrcAndDst,
Simon Dardisc4463c92016-10-18 14:42:13 +0000407 Match_NonZeroOperandForSync,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000408#define GET_OPERAND_DIAGNOSTIC_TYPES
409#include "MipsGenAsmMatcher.inc"
410#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000411 };
412
Akira Hatanakab11ef082015-11-14 06:35:56 +0000413 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000414 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000415 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000416 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
417 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000418 MCAsmParserExtension::Initialize(parser);
419
Toma Tabacu11e14a92015-04-21 11:50:52 +0000420 parser.addAliasForDirective(".asciiz", ".asciz");
421
Jack Carterb4dbc172012-09-05 23:34:03 +0000422 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000423 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000424
Toma Tabacu9db22db2014-09-09 10:15:38 +0000425 // Remember the initial assembler options. The user can not modify these.
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 Sandersa39ef1c2015-08-17 10:11:55 +0000428
Toma Tabacu9db22db2014-09-09 10:15:38 +0000429 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000430 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000431 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000432
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000433 getTargetStreamer().updateABIInfo(*this);
434
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000435 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000436 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000437
438 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000439
Rafael Espindola699281c2016-05-18 11:58:50 +0000440 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000441
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000442 IsCpRestoreSet = false;
443 CpRestoreOffset = -1;
444
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000445 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000446 if ((TheTriple.getArch() == Triple::mips) ||
447 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000448 IsLittleEndian = false;
449 else
450 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000451 }
452
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000453 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
454 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
455
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000456 bool isGP64bit() const {
457 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
458 }
459 bool isFP64bit() const {
460 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
461 }
Eric Christophera5762812015-01-26 17:33:46 +0000462 const MipsABIInfo &getABI() const { return ABI; }
463 bool isABI_N32() const { return ABI.IsN32(); }
464 bool isABI_N64() const { return ABI.IsN64(); }
465 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000466 bool isABI_FPXX() const {
467 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
468 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000469
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000470 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000471 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000472 }
473
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000474 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000475 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000476 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000477 bool hasMips1() const {
478 return getSTI().getFeatureBits()[Mips::FeatureMips1];
479 }
480 bool hasMips2() const {
481 return getSTI().getFeatureBits()[Mips::FeatureMips2];
482 }
483 bool hasMips3() const {
484 return getSTI().getFeatureBits()[Mips::FeatureMips3];
485 }
486 bool hasMips4() const {
487 return getSTI().getFeatureBits()[Mips::FeatureMips4];
488 }
489 bool hasMips5() const {
490 return getSTI().getFeatureBits()[Mips::FeatureMips5];
491 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000492 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000493 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000494 }
495 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000496 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 }
498 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000500 }
501 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000502 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000503 }
Daniel Sanders17793142015-02-18 16:24:50 +0000504 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000505 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000506 }
507 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000508 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000509 }
510 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000511 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000512 }
513 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000514 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000515 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000516 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000517 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000518 }
519 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000520 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000521 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000522
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000523 bool hasDSP() const {
524 return getSTI().getFeatureBits()[Mips::FeatureDSP];
525 }
526 bool hasDSPR2() const {
527 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
528 }
529 bool hasDSPR3() const {
530 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
531 }
532 bool hasMSA() const {
533 return getSTI().getFeatureBits()[Mips::FeatureMSA];
534 }
Kai Nackee0245392015-01-27 19:11:28 +0000535 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000536 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000537 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000538
Daniel Sandersa6994442015-08-18 12:33:54 +0000539 bool inPicMode() {
540 return IsPicEnabled;
541 }
542
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000543 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000545 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000546
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000547 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000548 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000549 }
550
Eric Christophere8ae3e32015-05-07 23:10:21 +0000551 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000552 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000553 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000554
Toma Tabacud9d344b2015-04-27 14:05:04 +0000555 /// Warn if RegIndex is the same as the current AT.
556 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000557
558 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000559
560 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000561
562 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
563 AsmToken::TokenKind OperatorToken,
564 MCContext &Ctx) override {
565 switch(OperatorToken) {
566 default:
567 llvm_unreachable("Unknown token");
568 return nullptr;
569 case AsmToken::PercentCall16:
570 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
571 case AsmToken::PercentCall_Hi:
572 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
573 case AsmToken::PercentCall_Lo:
574 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
575 case AsmToken::PercentDtprel_Hi:
576 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
577 case AsmToken::PercentDtprel_Lo:
578 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
579 case AsmToken::PercentGot:
580 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
581 case AsmToken::PercentGot_Disp:
582 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
583 case AsmToken::PercentGot_Hi:
584 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
585 case AsmToken::PercentGot_Lo:
586 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
587 case AsmToken::PercentGot_Ofst:
588 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
589 case AsmToken::PercentGot_Page:
590 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
591 case AsmToken::PercentGottprel:
592 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
593 case AsmToken::PercentGp_Rel:
594 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
595 case AsmToken::PercentHi:
596 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
597 case AsmToken::PercentHigher:
598 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
599 case AsmToken::PercentHighest:
600 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
601 case AsmToken::PercentLo:
602 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
603 case AsmToken::PercentNeg:
604 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
605 case AsmToken::PercentPcrel_Hi:
606 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
607 case AsmToken::PercentPcrel_Lo:
608 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
609 case AsmToken::PercentTlsgd:
610 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
611 case AsmToken::PercentTlsldm:
612 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
613 case AsmToken::PercentTprel_Hi:
614 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
615 case AsmToken::PercentTprel_Lo:
616 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
617 }
618 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000619};
620}
621
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000622namespace {
623
624/// MipsOperand - Instances of this class represent a parsed Mips machine
625/// instruction.
626class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000627public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000628 /// Broad categories of register classes
629 /// The exact class is finalized by the render method.
630 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000631 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000632 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000633 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000634 RegKind_FCC = 4, /// FCC
635 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
636 RegKind_MSACtrl = 16, /// MSA control registers
637 RegKind_COP2 = 32, /// COP2
638 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
639 /// context).
640 RegKind_CCR = 128, /// CCR
641 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000642 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000643 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000644 /// Potentially any (e.g. $1)
645 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
646 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000647 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000648 };
649
650private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000651 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000652 k_Immediate, /// An immediate (possibly involving symbol references)
653 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000654 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000655 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000656 k_RegList, /// A physical register list
657 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000658 } Kind;
659
David Blaikie960ea3f2014-06-08 16:18:35 +0000660public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000661 MipsOperand(KindTy K, MipsAsmParser &Parser)
662 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
663
David Blaikie960ea3f2014-06-08 16:18:35 +0000664private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000665 /// For diagnostics, and checking the assembler temporary
666 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000667
Eric Christopher8996c5d2013-03-15 00:42:55 +0000668 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000669 const char *Data;
670 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000671 };
672
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000673 struct RegIdxOp {
674 unsigned Index; /// Index into the register class
675 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000676 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000677 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000678 };
679
680 struct ImmOp {
681 const MCExpr *Val;
682 };
683
684 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000685 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000686 const MCExpr *Off;
687 };
688
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000689 struct RegListOp {
690 SmallVector<unsigned, 10> *List;
691 };
692
Jack Carterb4dbc172012-09-05 23:34:03 +0000693 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000694 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000695 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000696 struct ImmOp Imm;
697 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000698 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000699 };
700
701 SMLoc StartLoc, EndLoc;
702
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000703 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000704 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
705 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000706 const MCRegisterInfo *RegInfo,
707 SMLoc S, SMLoc E,
708 MipsAsmParser &Parser) {
709 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000710 Op->RegIdx.Index = Index;
711 Op->RegIdx.RegInfo = RegInfo;
712 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000713 Op->RegIdx.Tok.Data = Str.data();
714 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000715 Op->StartLoc = S;
716 Op->EndLoc = E;
717 return Op;
718 }
719
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000720public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000721 /// Coerce the register to GPR32 and return the real register for the current
722 /// target.
723 unsigned getGPR32Reg() const {
724 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000725 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000726 unsigned ClassID = Mips::GPR32RegClassID;
727 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000728 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000729
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000730 /// Coerce the register to GPR32 and return the real register for the current
731 /// target.
732 unsigned getGPRMM16Reg() const {
733 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
734 unsigned ClassID = Mips::GPR32RegClassID;
735 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
736 }
737
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000738 /// Coerce the register to GPR64 and return the real register for the current
739 /// target.
740 unsigned getGPR64Reg() const {
741 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
742 unsigned ClassID = Mips::GPR64RegClassID;
743 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000744 }
745
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000746private:
747 /// Coerce the register to AFGR64 and return the real register for the current
748 /// target.
749 unsigned getAFGR64Reg() const {
750 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
751 if (RegIdx.Index % 2 != 0)
752 AsmParser.Warning(StartLoc, "Float register should be even.");
753 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
754 .getRegister(RegIdx.Index / 2);
755 }
756
757 /// Coerce the register to FGR64 and return the real register for the current
758 /// target.
759 unsigned getFGR64Reg() const {
760 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
761 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
762 .getRegister(RegIdx.Index);
763 }
764
765 /// Coerce the register to FGR32 and return the real register for the current
766 /// target.
767 unsigned getFGR32Reg() const {
768 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
769 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
770 .getRegister(RegIdx.Index);
771 }
772
773 /// Coerce the register to FGRH32 and return the real register for the current
774 /// target.
775 unsigned getFGRH32Reg() const {
776 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
777 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
778 .getRegister(RegIdx.Index);
779 }
780
781 /// Coerce the register to FCC and return the real register for the current
782 /// target.
783 unsigned getFCCReg() const {
784 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
785 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
786 .getRegister(RegIdx.Index);
787 }
788
789 /// Coerce the register to MSA128 and return the real register for the current
790 /// target.
791 unsigned getMSA128Reg() const {
792 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
793 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
794 // identical
795 unsigned ClassID = Mips::MSA128BRegClassID;
796 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
797 }
798
799 /// Coerce the register to MSACtrl and return the real register for the
800 /// current target.
801 unsigned getMSACtrlReg() const {
802 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
803 unsigned ClassID = Mips::MSACtrlRegClassID;
804 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
805 }
806
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000807 /// Coerce the register to COP0 and return the real register for the
808 /// current target.
809 unsigned getCOP0Reg() const {
810 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
811 unsigned ClassID = Mips::COP0RegClassID;
812 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
813 }
814
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000815 /// Coerce the register to COP2 and return the real register for the
816 /// current target.
817 unsigned getCOP2Reg() const {
818 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
819 unsigned ClassID = Mips::COP2RegClassID;
820 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
821 }
822
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000823 /// Coerce the register to COP3 and return the real register for the
824 /// current target.
825 unsigned getCOP3Reg() const {
826 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
827 unsigned ClassID = Mips::COP3RegClassID;
828 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
829 }
830
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000831 /// Coerce the register to ACC64DSP and return the real register for the
832 /// current target.
833 unsigned getACC64DSPReg() const {
834 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
835 unsigned ClassID = Mips::ACC64DSPRegClassID;
836 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
837 }
838
839 /// Coerce the register to HI32DSP and return the real register for the
840 /// current target.
841 unsigned getHI32DSPReg() const {
842 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
843 unsigned ClassID = Mips::HI32DSPRegClassID;
844 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
845 }
846
847 /// Coerce the register to LO32DSP and return the real register for the
848 /// current target.
849 unsigned getLO32DSPReg() const {
850 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
851 unsigned ClassID = Mips::LO32DSPRegClassID;
852 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
853 }
854
855 /// Coerce the register to CCR and return the real register for the
856 /// current target.
857 unsigned getCCRReg() const {
858 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
859 unsigned ClassID = Mips::CCRRegClassID;
860 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
861 }
862
863 /// Coerce the register to HWRegs and return the real register for the
864 /// current target.
865 unsigned getHWRegsReg() const {
866 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
867 unsigned ClassID = Mips::HWRegsRegClassID;
868 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
869 }
870
871public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000872 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000873 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000874 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000875 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000876 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000877 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000878 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000879 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000880 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000881
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000882 void addRegOperands(MCInst &Inst, unsigned N) const {
883 llvm_unreachable("Use a custom parser instead");
884 }
885
Daniel Sanders21bce302014-04-01 12:35:23 +0000886 /// Render the operand to an MCInst as a GPR32
887 /// Asserts if the wrong number of operands are requested, or the operand
888 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000889 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
890 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000891 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000892 }
893
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000894 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
895 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000896 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000897 }
898
Jozef Kolek1904fa22014-11-24 14:25:53 +0000899 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
900 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000901 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000902 }
903
Zoran Jovanovic41688672015-02-10 16:36:20 +0000904 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
905 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000906 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000907 }
908
Daniel Sanders21bce302014-04-01 12:35:23 +0000909 /// Render the operand to an MCInst as a GPR64
910 /// Asserts if the wrong number of operands are requested, or the operand
911 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000912 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
913 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000914 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000915 }
916
917 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
918 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000919 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000920 }
921
922 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
923 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000924 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000925 }
926
927 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
928 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000929 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000930 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +0000931 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000932 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +0000933 AsmParser.getParser().printError(
934 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
935 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000936 }
937
938 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
939 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000940 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000941 }
942
943 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
944 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000945 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000946 }
947
948 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
949 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000950 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000951 }
952
953 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
954 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000955 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000956 }
957
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000958 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
959 assert(N == 1 && "Invalid number of operands!");
960 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
961 }
962
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000963 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
964 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000965 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000966 }
967
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000968 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
969 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000970 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000971 }
972
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000973 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
974 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000975 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000976 }
977
978 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
979 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000980 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000981 }
982
983 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
984 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000985 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000986 }
987
988 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
989 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000990 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000991 }
992
993 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
994 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000995 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000996 }
997
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000998 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000999 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1000 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001001 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001002 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001003 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001004 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001005 Inst.addOperand(MCOperand::createImm(Imm));
1006 }
1007
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001008 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001009 void addSImmOperands(MCInst &Inst, unsigned N) const {
1010 if (isImm() && !isConstantImm()) {
1011 addExpr(Inst, getImm());
1012 return;
1013 }
1014 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1015 }
1016
1017 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001018 void addUImmOperands(MCInst &Inst, unsigned N) const {
1019 if (isImm() && !isConstantImm()) {
1020 addExpr(Inst, getImm());
1021 return;
1022 }
1023 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1024 }
1025
Daniel Sanders78e89022016-03-11 11:37:50 +00001026 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1027 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1028 assert(N == 1 && "Invalid number of operands!");
1029 int64_t Imm = getConstantImm() - Offset;
1030 Imm = SignExtend64<Bits>(Imm);
1031 Imm += Offset;
1032 Imm += AdjustOffset;
1033 Inst.addOperand(MCOperand::createImm(Imm));
1034 }
1035
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001036 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001037 assert(N == 1 && "Invalid number of operands!");
1038 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001039 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001040 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001041
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001042 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001043 assert(N == 2 && "Invalid number of operands!");
1044
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001045 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1046 ? getMemBase()->getGPR64Reg()
1047 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001048
1049 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001050 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001051 }
1052
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001053 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1054 assert(N == 2 && "Invalid number of operands!");
1055
Jim Grosbache9119e42015-05-13 18:37:00 +00001056 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001057
1058 const MCExpr *Expr = getMemOff();
1059 addExpr(Inst, Expr);
1060 }
1061
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001062 void addRegListOperands(MCInst &Inst, unsigned N) const {
1063 assert(N == 1 && "Invalid number of operands!");
1064
1065 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001066 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001067 }
1068
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001069 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1070 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001071 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001072 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001073 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1074 Inst.addOperand(MCOperand::createReg(
1075 RegIdx.RegInfo->getRegClass(
1076 AsmParser.getABI().AreGprs64bit()
1077 ? Mips::GPR64RegClassID
1078 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1079 Inst.addOperand(MCOperand::createReg(
1080 RegIdx.RegInfo->getRegClass(
1081 AsmParser.getABI().AreGprs64bit()
1082 ? Mips::GPR64RegClassID
1083 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001084 }
1085
Zoran Jovanovic41688672015-02-10 16:36:20 +00001086 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1087 assert(N == 2 && "Invalid number of operands!");
1088 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001089 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001090 }
1091
Craig Topper56c590a2014-04-29 07:58:02 +00001092 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001093 // As a special case until we sort out the definition of div/divu, accept
1094 // $0/$zero here so that MCK_ZERO works correctly.
1095 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001096 }
1097 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001098 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001099 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001100 int64_t Res;
1101 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001102 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001103 bool isConstantImmz() const {
1104 return isConstantImm() && getConstantImm() == 0;
1105 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001106 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1107 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1108 }
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001109 template <unsigned Bits> bool isSImm() const {
1110 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1111 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001112 template <unsigned Bits> bool isUImm() const {
1113 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1114 }
1115 template <unsigned Bits> bool isAnyImm() const {
1116 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1117 isUInt<Bits>(getConstantImm()))
1118 : isImm();
1119 }
Daniel Sanders78e89022016-03-11 11:37:50 +00001120 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1121 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001122 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001123 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1124 return isConstantImm() && getConstantImm() >= Bottom &&
1125 getConstantImm() <= Top;
1126 }
Craig Topper56c590a2014-04-29 07:58:02 +00001127 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001128 // Note: It's not possible to pretend that other operand kinds are tokens.
1129 // The matcher emitter checks tokens first.
1130 return Kind == k_Token;
1131 }
Craig Topper56c590a2014-04-29 07:58:02 +00001132 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001133 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001134 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001135 }
Simon Dardis4ccda502016-05-27 13:56:36 +00001136 // Allow relocation operators.
1137 // FIXME: This predicate and others need to look through binary expressions
1138 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001139 template <unsigned Bits, unsigned ShiftAmount = 0>
1140 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001141 if (!isMem())
1142 return false;
1143 if (!getMemBase()->isGPRAsmReg())
1144 return false;
1145 if (isa<MCTargetExpr>(getMemOff()) ||
1146 (isConstantMemOff() &&
1147 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1148 return true;
1149 MCValue Res;
1150 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1151 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001152 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001153 bool isMemWithGRPMM16Base() const {
1154 return isMem() && getMemBase()->isMM16AsmReg();
1155 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001156 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1157 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1158 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1159 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001160 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1161 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1162 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1163 && (getMemBase()->getGPR32Reg() == Mips::SP);
1164 }
Daniel Sanderse473dc92016-05-09 13:38:25 +00001165 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1166 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1167 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1168 && (getMemBase()->getGPR32Reg() == Mips::GP);
1169 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001170 template <unsigned Bits, unsigned ShiftLeftAmount>
1171 bool isScaledUImm() const {
1172 return isConstantImm() &&
1173 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001174 }
Daniel Sanders97297772016-03-22 14:40:00 +00001175 template <unsigned Bits, unsigned ShiftLeftAmount>
1176 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001177 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1178 return true;
1179 // Operand can also be a symbol or symbol plus offset in case of relocations.
1180 if (Kind != k_Immediate)
1181 return false;
1182 MCValue Res;
1183 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1184 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001185 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001186 bool isRegList16() const {
1187 if (!isRegList())
1188 return false;
1189
1190 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001191 if (Size < 2 || Size > 5)
1192 return false;
1193
1194 unsigned R0 = RegList.List->front();
1195 unsigned R1 = RegList.List->back();
1196 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1197 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001198 return false;
1199
1200 int PrevReg = *RegList.List->begin();
1201 for (int i = 1; i < Size - 1; i++) {
1202 int Reg = (*(RegList.List))[i];
1203 if ( Reg != PrevReg + 1)
1204 return false;
1205 PrevReg = Reg;
1206 }
1207
1208 return true;
1209 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001210 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001211 bool isLSAImm() const {
1212 if (!isConstantImm())
1213 return false;
1214 int64_t Val = getConstantImm();
1215 return 1 <= Val && Val <= 4;
1216 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001217 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001218 bool isMovePRegPair() const {
1219 if (Kind != k_RegList || RegList.List->size() != 2)
1220 return false;
1221
1222 unsigned R0 = RegList.List->front();
1223 unsigned R1 = RegList.List->back();
1224
1225 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1226 (R0 == Mips::A1 && R1 == Mips::A3) ||
1227 (R0 == Mips::A2 && R1 == Mips::A3) ||
1228 (R0 == Mips::A0 && R1 == Mips::S5) ||
1229 (R0 == Mips::A0 && R1 == Mips::S6) ||
1230 (R0 == Mips::A0 && R1 == Mips::A1) ||
1231 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001232 (R0 == Mips::A0 && R1 == Mips::A3) ||
1233 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1234 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1235 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1236 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1237 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1238 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1239 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1240 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001241 return true;
1242
1243 return false;
1244 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001245
1246 StringRef getToken() const {
1247 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001248 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001249 }
Zlatko Buljanba553a62016-05-09 08:07:28 +00001250 bool isRegPair() const {
1251 return Kind == k_RegPair && RegIdx.Index <= 30;
1252 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001253
Craig Topper56c590a2014-04-29 07:58:02 +00001254 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001255 // As a special case until we sort out the definition of div/divu, accept
1256 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001257 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1258 RegIdx.Kind & RegKind_GPR)
1259 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001260
Daniel Sanders976d9382016-07-05 13:38:40 +00001261 llvm_unreachable("Invalid access!");
1262 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001263 }
1264
Jack Carterb4dbc172012-09-05 23:34:03 +00001265 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001266 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001267 return Imm.Val;
1268 }
1269
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001270 int64_t getConstantImm() const {
1271 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001272 int64_t Value = 0;
1273 (void)Val->evaluateAsAbsolute(Value);
1274 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001275 }
1276
1277 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001278 assert((Kind == k_Memory) && "Invalid access!");
1279 return Mem.Base;
1280 }
1281
1282 const MCExpr *getMemOff() const {
1283 assert((Kind == k_Memory) && "Invalid access!");
1284 return Mem.Off;
1285 }
1286
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001287 int64_t getConstantMemOff() const {
1288 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1289 }
1290
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001291 const SmallVectorImpl<unsigned> &getRegList() const {
1292 assert((Kind == k_RegList) && "Invalid access!");
1293 return *(RegList.List);
1294 }
1295
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001296 unsigned getRegPair() const {
1297 assert((Kind == k_RegPair) && "Invalid access!");
1298 return RegIdx.Index;
1299 }
1300
David Blaikie960ea3f2014-06-08 16:18:35 +00001301 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1302 MipsAsmParser &Parser) {
1303 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001304 Op->Tok.Data = Str.data();
1305 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001306 Op->StartLoc = S;
1307 Op->EndLoc = S;
1308 return Op;
1309 }
1310
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001311 /// Create a numeric register (e.g. $1). The exact register remains
1312 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001313 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001314 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1315 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001316 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001317 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001318 }
1319
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001320 /// Create a register that is definitely a GPR.
1321 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001322 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001323 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1324 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1325 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001326 }
1327
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001328 /// Create a register that is definitely a FGR.
1329 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001330 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001331 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1332 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1333 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001334 }
1335
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001336 /// Create a register that is definitely a HWReg.
1337 /// This is typically only used for named registers such as $hwr_cpunum.
1338 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001339 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001340 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001341 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001342 }
1343
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001344 /// Create a register that is definitely an FCC.
1345 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001346 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001347 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1348 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1349 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001350 }
1351
1352 /// Create a register that is definitely an ACC.
1353 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001354 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001355 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1356 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1357 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001358 }
1359
1360 /// Create a register that is definitely an MSA128.
1361 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001362 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001363 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1364 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1365 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001366 }
1367
1368 /// Create a register that is definitely an MSACtrl.
1369 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001370 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001371 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1372 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1373 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001374 }
1375
David Blaikie960ea3f2014-06-08 16:18:35 +00001376 static std::unique_ptr<MipsOperand>
1377 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1378 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001379 Op->Imm.Val = Val;
1380 Op->StartLoc = S;
1381 Op->EndLoc = E;
1382 return Op;
1383 }
1384
David Blaikie960ea3f2014-06-08 16:18:35 +00001385 static std::unique_ptr<MipsOperand>
1386 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1387 SMLoc E, MipsAsmParser &Parser) {
1388 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1389 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001390 Op->Mem.Off = Off;
1391 Op->StartLoc = S;
1392 Op->EndLoc = E;
1393 return Op;
1394 }
1395
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001396 static std::unique_ptr<MipsOperand>
1397 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1398 MipsAsmParser &Parser) {
1399 assert (Regs.size() > 0 && "Empty list not allowed");
1400
1401 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001402 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001403 Op->StartLoc = StartLoc;
1404 Op->EndLoc = EndLoc;
1405 return Op;
1406 }
1407
Daniel Sandersd044e492016-05-09 13:10:57 +00001408 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1409 SMLoc S, SMLoc E,
1410 MipsAsmParser &Parser) {
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001411 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001412 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001413 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1414 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001415 Op->StartLoc = S;
1416 Op->EndLoc = E;
1417 return Op;
1418 }
1419
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001420 bool isGPRAsmReg() const {
1421 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001422 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001423 bool isMM16AsmReg() const {
1424 if (!(isRegIdx() && RegIdx.Kind))
1425 return false;
1426 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1427 || RegIdx.Index == 16 || RegIdx.Index == 17);
1428 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001429 bool isMM16AsmRegZero() const {
1430 if (!(isRegIdx() && RegIdx.Kind))
1431 return false;
1432 return (RegIdx.Index == 0 ||
1433 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1434 RegIdx.Index == 17);
1435 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001436 bool isMM16AsmRegMoveP() const {
1437 if (!(isRegIdx() && RegIdx.Kind))
1438 return false;
1439 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1440 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1441 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001442 bool isFGRAsmReg() const {
1443 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1444 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001445 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001446 bool isHWRegsAsmReg() const {
1447 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001448 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001449 bool isCCRAsmReg() const {
1450 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001451 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001452 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001453 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1454 return false;
1455 if (!AsmParser.hasEightFccRegisters())
1456 return RegIdx.Index == 0;
1457 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001458 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001459 bool isACCAsmReg() const {
1460 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001461 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001462 bool isCOP0AsmReg() const {
1463 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1464 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001465 bool isCOP2AsmReg() const {
1466 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001467 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001468 bool isCOP3AsmReg() const {
1469 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1470 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001471 bool isMSA128AsmReg() const {
1472 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001473 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001474 bool isMSACtrlAsmReg() const {
1475 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001476 }
1477
Jack Carterb4dbc172012-09-05 23:34:03 +00001478 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001479 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001480 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001481 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001482
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001483 virtual ~MipsOperand() {
1484 switch (Kind) {
1485 case k_Immediate:
1486 break;
1487 case k_Memory:
1488 delete Mem.Base;
1489 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001490 case k_RegList:
1491 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001492 case k_RegisterIndex:
1493 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001494 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001495 break;
1496 }
1497 }
1498
Craig Topper56c590a2014-04-29 07:58:02 +00001499 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001500 switch (Kind) {
1501 case k_Immediate:
1502 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001503 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001504 OS << ">";
1505 break;
1506 case k_Memory:
1507 OS << "Mem<";
1508 Mem.Base->print(OS);
1509 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001510 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001511 OS << ">";
1512 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001513 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001514 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1515 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001516 break;
1517 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001518 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001519 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001520 case k_RegList:
1521 OS << "RegList< ";
1522 for (auto Reg : (*RegList.List))
1523 OS << Reg << " ";
1524 OS << ">";
1525 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001526 case k_RegPair:
1527 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1528 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001529 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001530 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001531
1532 bool isValidForTie(const MipsOperand &Other) const {
1533 if (Kind != Other.Kind)
1534 return false;
1535
1536 switch (Kind) {
1537 default:
1538 llvm_unreachable("Unexpected kind");
1539 return false;
1540 case k_RegisterIndex: {
1541 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1542 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1543 return Token == OtherToken;
1544 }
1545 }
1546 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001547}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001548} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001549
Jack Carter9e65aa32013-03-22 00:05:30 +00001550namespace llvm {
1551extern const MCInstrDesc MipsInsts[];
1552}
1553static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1554 return MipsInsts[Opcode];
1555}
1556
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001557static bool hasShortDelaySlot(unsigned Opcode) {
1558 switch (Opcode) {
1559 case Mips::JALS_MM:
1560 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001561 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001562 case Mips::BGEZALS_MM:
1563 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001564 return true;
1565 default:
1566 return false;
1567 }
1568}
1569
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001570static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1571 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1572 return &SRExpr->getSymbol();
1573 }
1574
1575 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1576 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1577 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1578
1579 if (LHSSym)
1580 return LHSSym;
1581
1582 if (RHSSym)
1583 return RHSSym;
1584
1585 return nullptr;
1586 }
1587
1588 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1589 return getSingleMCSymbol(UExpr->getSubExpr());
1590
1591 return nullptr;
1592}
1593
1594static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1595 if (isa<MCSymbolRefExpr>(Expr))
1596 return 1;
1597
1598 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1599 return countMCSymbolRefExpr(BExpr->getLHS()) +
1600 countMCSymbolRefExpr(BExpr->getRHS());
1601
1602 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1603 return countMCSymbolRefExpr(UExpr->getSubExpr());
1604
1605 return 0;
1606}
1607
Jack Carter9e65aa32013-03-22 00:05:30 +00001608bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001609 MCStreamer &Out,
1610 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001611 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001612 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001613 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001614
Jack Carter9e65aa32013-03-22 00:05:30 +00001615 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001616
1617 if (MCID.isBranch() || MCID.isCall()) {
1618 const unsigned Opcode = Inst.getOpcode();
1619 MCOperand Offset;
1620
1621 switch (Opcode) {
1622 default:
1623 break;
Kai Nackee0245392015-01-27 19:11:28 +00001624 case Mips::BBIT0:
1625 case Mips::BBIT032:
1626 case Mips::BBIT1:
1627 case Mips::BBIT132:
1628 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001629 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001630
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001631 case Mips::BEQ:
1632 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001633 case Mips::BEQ_MM:
1634 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001635 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001636 Offset = Inst.getOperand(2);
1637 if (!Offset.isImm())
1638 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001639 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001640 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001641 if (OffsetToAlignment(Offset.getImm(),
1642 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001643 return Error(IDLoc, "branch to misaligned address");
1644 break;
1645 case Mips::BGEZ:
1646 case Mips::BGTZ:
1647 case Mips::BLEZ:
1648 case Mips::BLTZ:
1649 case Mips::BGEZAL:
1650 case Mips::BLTZAL:
1651 case Mips::BC1F:
1652 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001653 case Mips::BGEZ_MM:
1654 case Mips::BGTZ_MM:
1655 case Mips::BLEZ_MM:
1656 case Mips::BLTZ_MM:
1657 case Mips::BGEZAL_MM:
1658 case Mips::BLTZAL_MM:
1659 case Mips::BC1F_MM:
1660 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001661 case Mips::BC1EQZC_MMR6:
1662 case Mips::BC1NEZC_MMR6:
1663 case Mips::BC2EQZC_MMR6:
1664 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001665 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001666 Offset = Inst.getOperand(1);
1667 if (!Offset.isImm())
1668 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001669 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001670 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001671 if (OffsetToAlignment(Offset.getImm(),
1672 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001673 return Error(IDLoc, "branch to misaligned address");
1674 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001675 case Mips::BGEC: case Mips::BGEC_MMR6:
1676 case Mips::BLTC: case Mips::BLTC_MMR6:
1677 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1678 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1679 case Mips::BEQC: case Mips::BEQC_MMR6:
1680 case Mips::BNEC: case Mips::BNEC_MMR6:
1681 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1682 Offset = Inst.getOperand(2);
1683 if (!Offset.isImm())
1684 break; // We'll deal with this situation later on when applying fixups.
1685 if (!isIntN(18, Offset.getImm()))
1686 return Error(IDLoc, "branch target out of range");
1687 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1688 return Error(IDLoc, "branch to misaligned address");
1689 break;
1690 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1691 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1692 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1693 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1694 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1695 Offset = Inst.getOperand(1);
1696 if (!Offset.isImm())
1697 break; // We'll deal with this situation later on when applying fixups.
1698 if (!isIntN(18, Offset.getImm()))
1699 return Error(IDLoc, "branch target out of range");
1700 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1701 return Error(IDLoc, "branch to misaligned address");
1702 break;
1703 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1704 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1705 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1706 Offset = Inst.getOperand(1);
1707 if (!Offset.isImm())
1708 break; // We'll deal with this situation later on when applying fixups.
1709 if (!isIntN(23, Offset.getImm()))
1710 return Error(IDLoc, "branch target out of range");
1711 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1712 return Error(IDLoc, "branch to misaligned address");
1713 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001714 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001715 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001716 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001717 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001718 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1719 Offset = Inst.getOperand(1);
1720 if (!Offset.isImm())
1721 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001722 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001723 return Error(IDLoc, "branch target out of range");
1724 if (OffsetToAlignment(Offset.getImm(), 2LL))
1725 return Error(IDLoc, "branch to misaligned address");
1726 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001727 }
1728 }
1729
Daniel Sandersa84989a2014-06-16 13:25:35 +00001730 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1731 // We still accept it but it is a normal nop.
1732 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1733 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1734 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1735 "nop instruction");
1736 }
1737
Kai Nackee0245392015-01-27 19:11:28 +00001738 if (hasCnMips()) {
1739 const unsigned Opcode = Inst.getOpcode();
1740 MCOperand Opnd;
1741 int Imm;
1742
1743 switch (Opcode) {
1744 default:
1745 break;
1746
1747 case Mips::BBIT0:
1748 case Mips::BBIT032:
1749 case Mips::BBIT1:
1750 case Mips::BBIT132:
1751 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1752 // The offset is handled above
1753 Opnd = Inst.getOperand(1);
1754 if (!Opnd.isImm())
1755 return Error(IDLoc, "expected immediate operand kind");
1756 Imm = Opnd.getImm();
1757 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1758 Opcode == Mips::BBIT1 ? 63 : 31))
1759 return Error(IDLoc, "immediate operand value out of range");
1760 if (Imm > 31) {
1761 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1762 : Mips::BBIT132);
1763 Inst.getOperand(1).setImm(Imm - 32);
1764 }
1765 break;
1766
Kai Nackee0245392015-01-27 19:11:28 +00001767 case Mips::SEQi:
1768 case Mips::SNEi:
1769 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1770 Opnd = Inst.getOperand(2);
1771 if (!Opnd.isImm())
1772 return Error(IDLoc, "expected immediate operand kind");
1773 Imm = Opnd.getImm();
1774 if (!isInt<10>(Imm))
1775 return Error(IDLoc, "immediate operand value out of range");
1776 break;
1777 }
1778 }
1779
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001780 // This expansion is not in a function called by tryExpandInstruction()
1781 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001782 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1783 inPicMode()) {
1784 warnIfNoMacro(IDLoc);
1785
1786 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1787
1788 // We can do this expansion if there's only 1 symbol in the argument
1789 // expression.
1790 if (countMCSymbolRefExpr(JalExpr) > 1)
1791 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1792
1793 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001794 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001795 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1796
1797 // FIXME: Add support for label+offset operands (currently causes an error).
1798 // FIXME: Add support for forward-declared local symbols.
1799 // FIXME: Add expansion for when the LargeGOT option is enabled.
1800 if (JalSym->isInSection() || JalSym->isTemporary()) {
1801 if (isABI_O32()) {
1802 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001803 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001804 // R_(MICRO)MIPS_GOT16 label
1805 // addiu $25, $25, 0
1806 // R_(MICRO)MIPS_LO16 label
1807 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001808 const MCExpr *Got16RelocExpr =
1809 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1810 const MCExpr *Lo16RelocExpr =
1811 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001812
Daniel Sandersa736b372016-04-29 13:33:12 +00001813 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1814 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1815 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1816 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001817 } else if (isABI_N32() || isABI_N64()) {
1818 // If it's a local symbol and the N32/N64 ABIs are being used,
1819 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001820 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001821 // R_(MICRO)MIPS_GOT_DISP label
1822 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001823 const MCExpr *GotDispRelocExpr =
1824 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001825
Daniel Sandersa736b372016-04-29 13:33:12 +00001826 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1827 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1828 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001829 }
1830 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001831 // If it's an external/weak symbol, we expand to:
1832 // lw/ld $25, 0($gp)
1833 // R_(MICRO)MIPS_CALL16 label
1834 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001835 const MCExpr *Call16RelocExpr =
1836 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001837
Daniel Sandersa736b372016-04-29 13:33:12 +00001838 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1839 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001840 }
1841
1842 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001843 if (IsCpRestoreSet && inMicroMipsMode())
1844 JalrInst.setOpcode(Mips::JALRS_MM);
1845 else
1846 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001847 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1848 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1849
1850 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1851 // This relocation is supposed to be an optimization hint for the linker
1852 // and is not necessary for correctness.
1853
1854 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001855 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001856 }
1857
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001858 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
1859 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001860 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001861 // reference or immediate we may have to expand instructions.
1862 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001863 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001864 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1865 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001866 MCOperand &Op = Inst.getOperand(i);
1867 if (Op.isImm()) {
1868 int MemOffset = Op.getImm();
1869 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001870 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001871 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00001872 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001873 }
1874 } else if (Op.isExpr()) {
1875 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001876 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001877 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001878 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001879 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001880 // Expand symbol.
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 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001884 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001885 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00001886 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001887 }
1888 }
1889 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001890 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001891 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001892
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001893 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001894 if (MCID.mayLoad()) {
1895 // Try to create 16-bit GP relative load instruction.
1896 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1897 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1898 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1899 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1900 MCOperand &Op = Inst.getOperand(i);
1901 if (Op.isImm()) {
1902 int MemOffset = Op.getImm();
1903 MCOperand &DstReg = Inst.getOperand(0);
1904 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001905 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001906 getContext().getRegisterInfo()->getRegClass(
1907 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001908 (BaseReg.getReg() == Mips::GP ||
1909 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001910
Daniel Sandersa736b372016-04-29 13:33:12 +00001911 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1912 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001913 return false;
1914 }
1915 }
1916 }
1917 } // for
1918 } // if load
1919
1920 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1921
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001922 MCOperand Opnd;
1923 int Imm;
1924
1925 switch (Inst.getOpcode()) {
1926 default:
1927 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001928 case Mips::ADDIUSP_MM:
1929 Opnd = Inst.getOperand(0);
1930 if (!Opnd.isImm())
1931 return Error(IDLoc, "expected immediate operand kind");
1932 Imm = Opnd.getImm();
1933 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1934 Imm % 4 != 0)
1935 return Error(IDLoc, "immediate operand value out of range");
1936 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001937 case Mips::SLL16_MM:
1938 case Mips::SRL16_MM:
1939 Opnd = Inst.getOperand(2);
1940 if (!Opnd.isImm())
1941 return Error(IDLoc, "expected immediate operand kind");
1942 Imm = Opnd.getImm();
1943 if (Imm < 1 || Imm > 8)
1944 return Error(IDLoc, "immediate operand value out of range");
1945 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001946 case Mips::LI16_MM:
1947 Opnd = Inst.getOperand(1);
1948 if (!Opnd.isImm())
1949 return Error(IDLoc, "expected immediate operand kind");
1950 Imm = Opnd.getImm();
1951 if (Imm < -1 || Imm > 126)
1952 return Error(IDLoc, "immediate operand value out of range");
1953 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001954 case Mips::ADDIUR2_MM:
1955 Opnd = Inst.getOperand(2);
1956 if (!Opnd.isImm())
1957 return Error(IDLoc, "expected immediate operand kind");
1958 Imm = Opnd.getImm();
1959 if (!(Imm == 1 || Imm == -1 ||
1960 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1961 return Error(IDLoc, "immediate operand value out of range");
1962 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001963 case Mips::ANDI16_MM:
1964 Opnd = Inst.getOperand(2);
1965 if (!Opnd.isImm())
1966 return Error(IDLoc, "expected immediate operand kind");
1967 Imm = Opnd.getImm();
1968 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1969 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1970 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1971 return Error(IDLoc, "immediate operand value out of range");
1972 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001973 case Mips::LBU16_MM:
1974 Opnd = Inst.getOperand(2);
1975 if (!Opnd.isImm())
1976 return Error(IDLoc, "expected immediate operand kind");
1977 Imm = Opnd.getImm();
1978 if (Imm < -1 || Imm > 14)
1979 return Error(IDLoc, "immediate operand value out of range");
1980 break;
1981 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001982 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001983 Opnd = Inst.getOperand(2);
1984 if (!Opnd.isImm())
1985 return Error(IDLoc, "expected immediate operand kind");
1986 Imm = Opnd.getImm();
1987 if (Imm < 0 || Imm > 15)
1988 return Error(IDLoc, "immediate operand value out of range");
1989 break;
1990 case Mips::LHU16_MM:
1991 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001992 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001993 Opnd = Inst.getOperand(2);
1994 if (!Opnd.isImm())
1995 return Error(IDLoc, "expected immediate operand kind");
1996 Imm = Opnd.getImm();
1997 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1998 return Error(IDLoc, "immediate operand value out of range");
1999 break;
2000 case Mips::LW16_MM:
2001 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002002 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002003 Opnd = Inst.getOperand(2);
2004 if (!Opnd.isImm())
2005 return Error(IDLoc, "expected immediate operand kind");
2006 Imm = Opnd.getImm();
2007 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2008 return Error(IDLoc, "immediate operand value out of range");
2009 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002010 case Mips::ADDIUPC_MM:
2011 MCOperand Opnd = Inst.getOperand(1);
2012 if (!Opnd.isImm())
2013 return Error(IDLoc, "expected immediate operand kind");
2014 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002015 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002016 return Error(IDLoc, "immediate operand value out of range");
2017 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002018 }
2019 }
2020
Daniel Sandersd8c07762016-04-18 12:35:36 +00002021 bool FillDelaySlot =
2022 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2023 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002024 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002025
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002026 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002027 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002028 switch (ExpandResult) {
2029 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002030 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002031 break;
2032 case MER_Success:
2033 break;
2034 case MER_Fail:
2035 return true;
2036 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002037
Daniel Sanderscda908a2016-05-16 09:10:13 +00002038 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2039 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2040 if (inMicroMipsMode())
2041 TOut.setUsesMicroMips();
2042
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002043 // If this instruction has a delay slot and .set reorder is active,
2044 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002045 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002046 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2047 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002048 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002049
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002050 if ((Inst.getOpcode() == Mips::JalOneReg ||
2051 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2052 isPicAndNotNxxAbi()) {
2053 if (IsCpRestoreSet) {
2054 // We need a NOP between the JALR and the LW:
2055 // If .set reorder has been used, we've already emitted a NOP.
2056 // If .set noreorder has been used, we need to emit a NOP at this point.
2057 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002058 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2059 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002060
2061 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002062 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002063 } else
2064 Warning(IDLoc, "no .cprestore used in PIC mode");
2065 }
2066
Jack Carter9e65aa32013-03-22 00:05:30 +00002067 return false;
2068}
2069
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002070MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002071MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2072 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002073 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002074 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002075 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002076 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002077 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002078 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002079 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002080 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002081 case Mips::LoadAddrImm64:
2082 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2083 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2084 "expected immediate operand kind");
2085
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002086 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2087 Inst.getOperand(1),
2088 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002089 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002090 ? MER_Fail
2091 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002092 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002093 case Mips::LoadAddrReg64:
2094 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2095 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2096 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2097 "expected immediate operand kind");
2098
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002099 return expandLoadAddress(Inst.getOperand(0).getReg(),
2100 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2101 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002102 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002103 ? MER_Fail
2104 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002105 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002106 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002107 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2108 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002109 case Mips::SWM_MM:
2110 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002111 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2112 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002113 case Mips::JalOneReg:
2114 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002115 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002116 case Mips::BneImm:
2117 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002118 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002119 case Mips::BLT:
2120 case Mips::BLE:
2121 case Mips::BGE:
2122 case Mips::BGT:
2123 case Mips::BLTU:
2124 case Mips::BLEU:
2125 case Mips::BGEU:
2126 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002127 case Mips::BLTL:
2128 case Mips::BLEL:
2129 case Mips::BGEL:
2130 case Mips::BGTL:
2131 case Mips::BLTUL:
2132 case Mips::BLEUL:
2133 case Mips::BGEUL:
2134 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002135 case Mips::BLTImmMacro:
2136 case Mips::BLEImmMacro:
2137 case Mips::BGEImmMacro:
2138 case Mips::BGTImmMacro:
2139 case Mips::BLTUImmMacro:
2140 case Mips::BLEUImmMacro:
2141 case Mips::BGEUImmMacro:
2142 case Mips::BGTUImmMacro:
2143 case Mips::BLTLImmMacro:
2144 case Mips::BLELImmMacro:
2145 case Mips::BGELImmMacro:
2146 case Mips::BGTLImmMacro:
2147 case Mips::BLTULImmMacro:
2148 case Mips::BLEULImmMacro:
2149 case Mips::BGEULImmMacro:
2150 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002151 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002152 case Mips::SDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002153 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2154 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002155 case Mips::DSDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002156 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2157 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002158 case Mips::UDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002159 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2160 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002161 case Mips::DUDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002162 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2163 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002164 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002165 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2166 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002167 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002168 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002169 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002170 case Mips::PseudoTRUNC_W_D:
2171 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2172 : MER_Success;
2173 case Mips::Ulh:
2174 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2175 case Mips::Ulhu:
2176 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2177 case Mips::Ulw:
2178 return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2179 case Mips::NORImm:
2180 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002181 case Mips::ADDi:
2182 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002183 case Mips::SLTi:
2184 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002185 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2186 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2187 int64_t ImmValue = Inst.getOperand(2).getImm();
2188 if (isInt<16>(ImmValue))
2189 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002190 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2191 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002192 }
2193 return MER_NotAMacro;
2194 case Mips::ANDi:
2195 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002196 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002197 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2198 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2199 int64_t ImmValue = Inst.getOperand(2).getImm();
2200 if (isUInt<16>(ImmValue))
2201 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002202 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2203 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002204 }
2205 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002206 case Mips::ROL:
2207 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002208 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002209 case Mips::ROLImm:
2210 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002211 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002212 case Mips::DROL:
2213 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002214 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002215 case Mips::DROLImm:
2216 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002217 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002218 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002219 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002220 case Mips::LDMacro:
2221 case Mips::SDMacro:
2222 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2223 Inst.getOpcode() == Mips::LDMacro)
2224 ? MER_Fail
2225 : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002226 }
Jack Carter30a59822012-10-04 04:03:53 +00002227}
Jack Carter92995f12012-10-06 00:53:28 +00002228
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002229bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002230 MCStreamer &Out,
2231 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002232 MipsTargetStreamer &TOut = getTargetStreamer();
2233
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002234 // Create a JALR instruction which is going to replace the pseudo-JAL.
2235 MCInst JalrInst;
2236 JalrInst.setLoc(IDLoc);
2237 const MCOperand FirstRegOp = Inst.getOperand(0);
2238 const unsigned Opcode = Inst.getOpcode();
2239
2240 if (Opcode == Mips::JalOneReg) {
2241 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002242 if (IsCpRestoreSet && inMicroMipsMode()) {
2243 JalrInst.setOpcode(Mips::JALRS16_MM);
2244 JalrInst.addOperand(FirstRegOp);
2245 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002246 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002247 JalrInst.addOperand(FirstRegOp);
2248 } else {
2249 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002250 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002251 JalrInst.addOperand(FirstRegOp);
2252 }
2253 } else if (Opcode == Mips::JalTwoReg) {
2254 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002255 if (IsCpRestoreSet && inMicroMipsMode())
2256 JalrInst.setOpcode(Mips::JALRS_MM);
2257 else
2258 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002259 JalrInst.addOperand(FirstRegOp);
2260 const MCOperand SecondRegOp = Inst.getOperand(1);
2261 JalrInst.addOperand(SecondRegOp);
2262 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002263 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002264
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002265 // If .set reorder is active and branch instruction has a delay slot,
2266 // emit a NOP after it.
2267 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002268 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2269 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2270 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002271
2272 return false;
2273}
2274
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002275/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002276template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002277 unsigned BitNum = findFirstSet(x);
2278
2279 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2280}
2281
2282/// Load (or add) an immediate into a register.
2283///
2284/// @param ImmValue The immediate to load.
2285/// @param DstReg The register that will hold the immediate.
2286/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2287/// for a simple initialization.
2288/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2289/// @param IsAddress True if the immediate represents an address. False if it
2290/// is an integer.
2291/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002292bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002293 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002294 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2295 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002296 MipsTargetStreamer &TOut = getTargetStreamer();
2297
Toma Tabacu00e98672015-05-01 12:19:27 +00002298 if (!Is32BitImm && !isGP64bit()) {
2299 Error(IDLoc, "instruction requires a 64-bit architecture");
2300 return true;
2301 }
2302
Daniel Sanders03f9c012015-07-14 12:24:22 +00002303 if (Is32BitImm) {
2304 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2305 // Sign extend up to 64-bit so that the predicates match the hardware
2306 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2307 // true.
2308 ImmValue = SignExtend64<32>(ImmValue);
2309 } else {
2310 Error(IDLoc, "instruction requires a 32-bit immediate");
2311 return true;
2312 }
2313 }
2314
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002315 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2316 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2317
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002318 bool UseSrcReg = false;
2319 if (SrcReg != Mips::NoRegister)
2320 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002321
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002322 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002323 if (UseSrcReg &&
2324 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002325 // At this point we need AT to perform the expansions and we exit if it is
2326 // not available.
2327 unsigned ATReg = getATReg(IDLoc);
2328 if (!ATReg)
2329 return true;
2330 TmpReg = ATReg;
2331 }
2332
Daniel Sanders03f9c012015-07-14 12:24:22 +00002333 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002334 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002335 SrcReg = ZeroReg;
2336
2337 // This doesn't quite follow the usual ABI expectations for N32 but matches
2338 // traditional assembler behaviour. N32 would normally use addiu for both
2339 // integers and addresses.
2340 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002341 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002342 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002343 }
2344
Daniel Sandersa736b372016-04-29 13:33:12 +00002345 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002346 return false;
2347 }
2348
2349 if (isUInt<16>(ImmValue)) {
2350 unsigned TmpReg = DstReg;
2351 if (SrcReg == DstReg) {
2352 TmpReg = getATReg(IDLoc);
2353 if (!TmpReg)
2354 return true;
2355 }
2356
Daniel Sandersa736b372016-04-29 13:33:12 +00002357 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002358 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002359 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002360 return false;
2361 }
2362
2363 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002364 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002365
Toma Tabacu79588102015-04-29 10:19:56 +00002366 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2367 uint16_t Bits15To0 = ImmValue & 0xffff;
2368
Toma Tabacua3d056f2015-05-15 09:42:11 +00002369 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002370 // Traditional behaviour seems to special case this particular value. It's
2371 // not clear why other masks are handled differently.
2372 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002373 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2374 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002375 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002376 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002377 return false;
2378 }
2379
2380 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002381 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002382 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2383 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002384 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002385 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002386 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002387 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002388 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002389 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002390
Daniel Sandersa736b372016-04-29 13:33:12 +00002391 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002392 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002393 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002394 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002395 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002396 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002397 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002398
2399 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2400 if (Is32BitImm) {
2401 Error(IDLoc, "instruction requires a 32-bit immediate");
2402 return true;
2403 }
2404
2405 // Traditionally, these immediates are shifted as little as possible and as
2406 // such we align the most significant bit to bit 15 of our temporary.
2407 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2408 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2409 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2410 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002411 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2412 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002413
2414 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002415 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002416
2417 return false;
2418 }
2419
2420 warnIfNoMacro(IDLoc);
2421
2422 // The remaining case is packed with a sequence of dsll and ori with zeros
2423 // being omitted and any neighbouring dsll's being coalesced.
2424 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2425
2426 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2427 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002428 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002429 return false;
2430
2431 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2432 // skip it and defer the shift to the next chunk.
2433 unsigned ShiftCarriedForwards = 16;
2434 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2435 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2436
2437 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002438 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2439 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002440 ShiftCarriedForwards = 0;
2441 }
2442
2443 ShiftCarriedForwards += 16;
2444 }
2445 ShiftCarriedForwards -= 16;
2446
2447 // Finish any remaining shifts left by trailing zeros.
2448 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002449 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002450
2451 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002452 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002453
Matheus Almeida3813d572014-06-19 14:39:14 +00002454 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002455}
Jack Carter92995f12012-10-06 00:53:28 +00002456
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002457bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002458 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002459 const MCOperand &ImmOp = Inst.getOperand(1);
2460 assert(ImmOp.isImm() && "expected immediate operand kind");
2461 const MCOperand &DstRegOp = Inst.getOperand(0);
2462 assert(DstRegOp.isReg() && "expected register operand kind");
2463
2464 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002465 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002466 return true;
2467
2468 return false;
2469}
2470
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002471bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2472 const MCOperand &Offset,
2473 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002474 MCStreamer &Out,
2475 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002476 // la can't produce a usable address when addresses are 64-bit.
2477 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2478 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2479 // We currently can't do this because we depend on the equality
2480 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2481 Error(IDLoc, "la used to load 64-bit address");
2482 // Continue as if we had 'dla' instead.
2483 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002484 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002485 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002486
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002487 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002488 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002489 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002490 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002491 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002492
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002493 if (!Offset.isImm())
2494 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002495 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002496
Scott Egerton24557012016-01-21 15:11:01 +00002497 if (!ABI.ArePtrs64bit()) {
2498 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2499 Is32BitAddress = true;
2500 }
2501
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002502 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002503 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002504}
2505
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002506bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2507 unsigned DstReg, unsigned SrcReg,
2508 bool Is32BitSym, SMLoc IDLoc,
2509 MCStreamer &Out,
2510 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002511 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002512 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002513 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002514
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002515 if (inPicMode() && ABI.IsO32()) {
2516 MCValue Res;
2517 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2518 Error(IDLoc, "expected relocatable expression");
2519 return true;
2520 }
2521 if (Res.getSymB() != nullptr) {
2522 Error(IDLoc, "expected relocatable expression with only one symbol");
2523 return true;
2524 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002525
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002526 // The case where the result register is $25 is somewhat special. If the
2527 // symbol in the final relocation is external and not modified with a
2528 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2529 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2530 Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
2531 !Res.getSymA()->getSymbol().isTemporary()) {
2532 const MCExpr *CallExpr =
2533 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2534 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2535 MCOperand::createExpr(CallExpr), IDLoc, STI);
2536 return false;
2537 }
2538
2539 // The remaining cases are:
2540 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2541 // >addiu $tmp, $tmp, %lo(offset)
2542 // >addiu $rd, $tmp, $rs
2543 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2544 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2545 // >addiu $rd, $tmp, $rs
2546 // The addiu's marked with a '>' may be omitted if they are redundant. If
2547 // this happens then the last instruction must use $rd as the result
2548 // register.
2549 const MipsMCExpr *GotExpr =
2550 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2551 const MCExpr *LoExpr = nullptr;
2552 if (Res.getSymA()->getSymbol().isInSection() ||
2553 Res.getSymA()->getSymbol().isTemporary())
2554 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2555 else if (Res.getConstant() != 0) {
2556 // External symbols fully resolve the symbol with just the %got(symbol)
2557 // but we must still account for any offset to the symbol for expressions
2558 // like symbol+8.
2559 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2560 }
2561
2562 unsigned TmpReg = DstReg;
2563 if (UseSrcReg &&
2564 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2565 SrcReg)) {
2566 // If $rs is the same as $rd, we need to use AT.
2567 // If it is not available we exit.
2568 unsigned ATReg = getATReg(IDLoc);
2569 if (!ATReg)
2570 return true;
2571 TmpReg = ATReg;
2572 }
2573
2574 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2575 MCOperand::createExpr(GotExpr), IDLoc, STI);
2576
2577 if (LoExpr)
2578 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2579 IDLoc, STI);
2580
2581 if (UseSrcReg)
2582 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2583
2584 return false;
2585 }
2586
2587 const MipsMCExpr *HiExpr =
2588 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2589 const MipsMCExpr *LoExpr =
2590 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002591
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002592 // This is the 64-bit symbol address expansion.
2593 if (ABI.ArePtrs64bit() && isGP64bit()) {
2594 // We always need AT for the 64-bit expansion.
2595 // If it is not available we exit.
2596 unsigned ATReg = getATReg(IDLoc);
2597 if (!ATReg)
2598 return true;
2599
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002600 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002601 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002602 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002603 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002604
Scott Egerton24557012016-01-21 15:11:01 +00002605 if (UseSrcReg &&
2606 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2607 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002608 // If $rs is the same as $rd:
2609 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2610 // daddiu $at, $at, %higher(sym)
2611 // dsll $at, $at, 16
2612 // daddiu $at, $at, %hi(sym)
2613 // dsll $at, $at, 16
2614 // daddiu $at, $at, %lo(sym)
2615 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002616 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2617 STI);
2618 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2619 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2620 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2621 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2622 IDLoc, STI);
2623 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2624 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2625 IDLoc, STI);
2626 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002627
2628 return false;
2629 }
2630
2631 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2632 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2633 // lui $at, %hi(sym)
2634 // daddiu $rd, $rd, %higher(sym)
2635 // daddiu $at, $at, %lo(sym)
2636 // dsll32 $rd, $rd, 0
2637 // daddu $rd, $rd, $at
2638 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002639 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2640 STI);
2641 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2642 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2643 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2644 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2645 IDLoc, STI);
2646 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2647 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002648 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002649 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002650
2651 return false;
2652 }
2653
2654 // And now, the 32-bit symbol address expansion:
2655 // If $rs is the same as $rd:
2656 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2657 // ori $at, $at, %lo(sym)
2658 // addu $rd, $at, $rd
2659 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2660 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2661 // ori $rd, $rd, %lo(sym)
2662 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002663 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002664 if (UseSrcReg &&
2665 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002666 // If $rs is the same as $rd, we need to use AT.
2667 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002668 unsigned ATReg = getATReg(IDLoc);
2669 if (!ATReg)
2670 return true;
2671 TmpReg = ATReg;
2672 }
2673
Daniel Sandersa736b372016-04-29 13:33:12 +00002674 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2675 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2676 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002677
Toma Tabacufb9d1252015-06-22 12:08:39 +00002678 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002679 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002680 else
Scott Egerton24557012016-01-21 15:11:01 +00002681 assert(
2682 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002683
Toma Tabacu674825c2015-06-16 12:16:24 +00002684 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002685}
2686
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002687bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2688 MCStreamer &Out,
2689 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002690 MipsTargetStreamer &TOut = getTargetStreamer();
2691
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002692 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2693 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002694
2695 MCOperand Offset = Inst.getOperand(0);
2696 if (Offset.isExpr()) {
2697 Inst.clear();
2698 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002699 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2700 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2701 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002702 } else {
2703 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002704 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002705 // If offset fits into 11 bits then this instruction becomes microMIPS
2706 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002707 if (inMicroMipsMode())
2708 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002709 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002710 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00002711 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002712 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00002713 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002714 Inst.clear();
2715 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002716 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2717 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2718 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002719 }
2720 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002721 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002722
Zoran Jovanovicada70912015-09-07 11:56:37 +00002723 // If .set reorder is active and branch instruction has a delay slot,
2724 // emit a NOP after it.
2725 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2726 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002727 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002728
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002729 return false;
2730}
2731
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002732bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2733 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002734 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002735 const MCOperand &DstRegOp = Inst.getOperand(0);
2736 assert(DstRegOp.isReg() && "expected register operand kind");
2737
2738 const MCOperand &ImmOp = Inst.getOperand(1);
2739 assert(ImmOp.isImm() && "expected immediate operand kind");
2740
2741 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002742 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2743 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002744
2745 unsigned OpCode = 0;
2746 switch(Inst.getOpcode()) {
2747 case Mips::BneImm:
2748 OpCode = Mips::BNE;
2749 break;
2750 case Mips::BeqImm:
2751 OpCode = Mips::BEQ;
2752 break;
2753 default:
2754 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2755 break;
2756 }
2757
2758 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002759 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002760 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2761 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002762 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002763 warnIfNoMacro(IDLoc);
2764
2765 unsigned ATReg = getATReg(IDLoc);
2766 if (!ATReg)
2767 return true;
2768
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002769 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002770 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002771 return true;
2772
Daniel Sandersa736b372016-04-29 13:33:12 +00002773 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002774 }
2775 return false;
2776}
2777
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002778void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002779 const MCSubtargetInfo *STI, bool IsLoad,
2780 bool IsImmOpnd) {
2781 if (IsLoad) {
2782 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2783 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002784 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002785 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2786}
2787
2788void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2789 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2790 MipsTargetStreamer &TOut = getTargetStreamer();
2791
2792 unsigned DstReg = Inst.getOperand(0).getReg();
2793 unsigned BaseReg = Inst.getOperand(1).getReg();
2794
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002795 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002796 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2797 unsigned DstRegClassID =
2798 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2799 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2800 (DstRegClassID == Mips::GPR64RegClassID);
2801
2802 if (IsImmOpnd) {
2803 // Try to use DstReg as the temporary.
2804 if (IsGPR && (BaseReg != DstReg)) {
2805 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2806 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2807 STI);
2808 return;
2809 }
2810
Matheus Almeida7de68e72014-06-18 14:46:05 +00002811 // At this point we need AT to perform the expansions and we exit if it is
2812 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002813 unsigned ATReg = getATReg(IDLoc);
2814 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002815 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002816
2817 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2818 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2819 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002820 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002821
Daniel Sandersfba875f2016-04-29 13:43:45 +00002822 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002823 MCOperand LoOperand = MCOperand::createExpr(
2824 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2825 MCOperand HiOperand = MCOperand::createExpr(
2826 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002827
2828 // Try to use DstReg as the temporary.
2829 if (IsGPR && (BaseReg != DstReg)) {
2830 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2831 LoOperand, DstReg, IDLoc, STI);
2832 return;
2833 }
2834
2835 // At this point we need AT to perform the expansions and we exit if it is
2836 // not available.
2837 unsigned ATReg = getATReg(IDLoc);
2838 if (!ATReg)
2839 return;
2840
2841 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2842 LoOperand, ATReg, IDLoc, STI);
2843}
2844
2845void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2846 const MCSubtargetInfo *STI,
2847 bool IsImmOpnd) {
2848 MipsTargetStreamer &TOut = getTargetStreamer();
2849
2850 unsigned SrcReg = Inst.getOperand(0).getReg();
2851 unsigned BaseReg = Inst.getOperand(1).getReg();
2852
Daniel Sanders241c6792016-05-12 14:01:50 +00002853 if (IsImmOpnd) {
2854 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2855 Inst.getOperand(2).getImm(),
2856 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
2857 return;
2858 }
2859
Daniel Sandersfba875f2016-04-29 13:43:45 +00002860 unsigned ATReg = getATReg(IDLoc);
2861 if (!ATReg)
2862 return;
2863
Daniel Sandersfba875f2016-04-29 13:43:45 +00002864 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002865 MCOperand LoOperand = MCOperand::createExpr(
2866 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2867 MCOperand HiOperand = MCOperand::createExpr(
2868 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002869 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2870 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002871}
2872
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002873bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2874 MCStreamer &Out,
2875 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002876 unsigned OpNum = Inst.getNumOperands();
2877 unsigned Opcode = Inst.getOpcode();
2878 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2879
2880 assert (Inst.getOperand(OpNum - 1).isImm() &&
2881 Inst.getOperand(OpNum - 2).isReg() &&
2882 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2883
2884 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2885 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002886 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2887 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2888 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2889 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002890 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002891 if (inMicroMipsMode() && hasMips32r6())
2892 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2893 else
2894 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2895 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002896
2897 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002898 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002899 return false;
2900}
2901
Toma Tabacu1a108322015-06-17 13:20:24 +00002902bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002903 MCStreamer &Out,
2904 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002905 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002906 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002907 unsigned PseudoOpcode = Inst.getOpcode();
2908 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002909 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002910 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2911
2912 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002913 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002914
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002915 unsigned TrgReg;
2916 if (TrgOp.isReg())
2917 TrgReg = TrgOp.getReg();
2918 else if (TrgOp.isImm()) {
2919 warnIfNoMacro(IDLoc);
2920 EmittedNoMacroWarning = true;
2921
2922 TrgReg = getATReg(IDLoc);
2923 if (!TrgReg)
2924 return true;
2925
2926 switch(PseudoOpcode) {
2927 default:
2928 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2929 case Mips::BLTImmMacro:
2930 PseudoOpcode = Mips::BLT;
2931 break;
2932 case Mips::BLEImmMacro:
2933 PseudoOpcode = Mips::BLE;
2934 break;
2935 case Mips::BGEImmMacro:
2936 PseudoOpcode = Mips::BGE;
2937 break;
2938 case Mips::BGTImmMacro:
2939 PseudoOpcode = Mips::BGT;
2940 break;
2941 case Mips::BLTUImmMacro:
2942 PseudoOpcode = Mips::BLTU;
2943 break;
2944 case Mips::BLEUImmMacro:
2945 PseudoOpcode = Mips::BLEU;
2946 break;
2947 case Mips::BGEUImmMacro:
2948 PseudoOpcode = Mips::BGEU;
2949 break;
2950 case Mips::BGTUImmMacro:
2951 PseudoOpcode = Mips::BGTU;
2952 break;
2953 case Mips::BLTLImmMacro:
2954 PseudoOpcode = Mips::BLTL;
2955 break;
2956 case Mips::BLELImmMacro:
2957 PseudoOpcode = Mips::BLEL;
2958 break;
2959 case Mips::BGELImmMacro:
2960 PseudoOpcode = Mips::BGEL;
2961 break;
2962 case Mips::BGTLImmMacro:
2963 PseudoOpcode = Mips::BGTL;
2964 break;
2965 case Mips::BLTULImmMacro:
2966 PseudoOpcode = Mips::BLTUL;
2967 break;
2968 case Mips::BLEULImmMacro:
2969 PseudoOpcode = Mips::BLEUL;
2970 break;
2971 case Mips::BGEULImmMacro:
2972 PseudoOpcode = Mips::BGEUL;
2973 break;
2974 case Mips::BGTULImmMacro:
2975 PseudoOpcode = Mips::BGTUL;
2976 break;
2977 }
2978
2979 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002980 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002981 return true;
2982 }
2983
Toma Tabacu1a108322015-06-17 13:20:24 +00002984 switch (PseudoOpcode) {
2985 case Mips::BLT:
2986 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002987 case Mips::BLTL:
2988 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002989 AcceptsEquality = false;
2990 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002991 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2992 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002993 ZeroSrcOpcode = Mips::BGTZ;
2994 ZeroTrgOpcode = Mips::BLTZ;
2995 break;
2996 case Mips::BLE:
2997 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002998 case Mips::BLEL:
2999 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003000 AcceptsEquality = true;
3001 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003002 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3003 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003004 ZeroSrcOpcode = Mips::BGEZ;
3005 ZeroTrgOpcode = Mips::BLEZ;
3006 break;
3007 case Mips::BGE:
3008 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003009 case Mips::BGEL:
3010 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003011 AcceptsEquality = true;
3012 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003013 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3014 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003015 ZeroSrcOpcode = Mips::BLEZ;
3016 ZeroTrgOpcode = Mips::BGEZ;
3017 break;
3018 case Mips::BGT:
3019 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003020 case Mips::BGTL:
3021 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003022 AcceptsEquality = false;
3023 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003024 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3025 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003026 ZeroSrcOpcode = Mips::BLTZ;
3027 ZeroTrgOpcode = Mips::BGTZ;
3028 break;
3029 default:
3030 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3031 }
3032
Toma Tabacu1a108322015-06-17 13:20:24 +00003033 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3034 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3035 if (IsSrcRegZero && IsTrgRegZero) {
3036 // FIXME: All of these Opcode-specific if's are needed for compatibility
3037 // with GAS' behaviour. However, they may not generate the most efficient
3038 // code in some circumstances.
3039 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003040 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3041 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003042 return false;
3043 }
3044 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003045 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3046 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003047 Warning(IDLoc, "branch is always taken");
3048 return false;
3049 }
3050 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003051 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3052 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003053 Warning(IDLoc, "branch is always taken");
3054 return false;
3055 }
3056 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003057 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3058 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003059 return false;
3060 }
3061 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003062 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3063 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003064 return false;
3065 }
3066 if (AcceptsEquality) {
3067 // If both registers are $0 and the pseudo-branch accepts equality, it
3068 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003069 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3070 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003071 Warning(IDLoc, "branch is always taken");
3072 return false;
3073 }
3074 // If both registers are $0 and the pseudo-branch does not accept
3075 // equality, it will never be taken, so we don't have to emit anything.
3076 return false;
3077 }
3078 if (IsSrcRegZero || IsTrgRegZero) {
3079 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3080 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3081 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3082 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3083 // the pseudo-branch will never be taken, so we don't emit anything.
3084 // This only applies to unsigned pseudo-branches.
3085 return false;
3086 }
3087 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3088 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3089 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3090 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3091 // the pseudo-branch will always be taken, so we emit an unconditional
3092 // branch.
3093 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003094 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3095 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003096 Warning(IDLoc, "branch is always taken");
3097 return false;
3098 }
3099 if (IsUnsigned) {
3100 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3101 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3102 // the pseudo-branch will be taken only when the non-zero register is
3103 // different from 0, so we emit a BNEZ.
3104 //
3105 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3106 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3107 // the pseudo-branch will be taken only when the non-zero register is
3108 // equal to 0, so we emit a BEQZ.
3109 //
3110 // Because only BLEU and BGEU branch on equality, we can use the
3111 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003112 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3113 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3114 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003115 return false;
3116 }
3117 // If we have a signed pseudo-branch and one of the registers is $0,
3118 // we can use an appropriate compare-to-zero branch. We select which one
3119 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003120 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3121 IsSrcRegZero ? TrgReg : SrcReg,
3122 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003123 return false;
3124 }
3125
3126 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3127 // expansions. If it is not available, we return.
3128 unsigned ATRegNum = getATReg(IDLoc);
3129 if (!ATRegNum)
3130 return true;
3131
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003132 if (!EmittedNoMacroWarning)
3133 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003134
3135 // SLT fits well with 2 of our 4 pseudo-branches:
3136 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3137 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3138 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3139 // This is accomplished by using a BNEZ with the result of the SLT.
3140 //
3141 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3142 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3143 // Because only BGE and BLE branch on equality, we can use the
3144 // AcceptsEquality variable to decide when to emit the BEQZ.
3145 // Note that the order of the SLT arguments doesn't change between
3146 // opposites.
3147 //
3148 // The same applies to the unsigned variants, except that SLTu is used
3149 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003150 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3151 ReverseOrderSLT ? TrgReg : SrcReg,
3152 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003153
Daniel Sandersa736b372016-04-29 13:33:12 +00003154 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3155 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3156 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3157 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003158 return false;
3159}
3160
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003161bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3162 const MCSubtargetInfo *STI, const bool IsMips64,
3163 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003164 MipsTargetStreamer &TOut = getTargetStreamer();
3165
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003166 warnIfNoMacro(IDLoc);
3167
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003168 const MCOperand &RdRegOp = Inst.getOperand(0);
3169 assert(RdRegOp.isReg() && "expected register operand kind");
3170 unsigned RdReg = RdRegOp.getReg();
3171
3172 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003173 assert(RsRegOp.isReg() && "expected register operand kind");
3174 unsigned RsReg = RsRegOp.getReg();
3175
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003176 const MCOperand &RtRegOp = Inst.getOperand(2);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003177 assert(RtRegOp.isReg() && "expected register operand kind");
3178 unsigned RtReg = RtRegOp.getReg();
3179 unsigned DivOp;
3180 unsigned ZeroReg;
3181
3182 if (IsMips64) {
3183 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3184 ZeroReg = Mips::ZERO_64;
3185 } else {
3186 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3187 ZeroReg = Mips::ZERO;
3188 }
3189
3190 bool UseTraps = useTraps();
3191
3192 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
3193 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
3194 Warning(IDLoc, "dividing zero by zero");
3195 if (IsMips64) {
3196 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
3197 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003198 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003199 return false;
3200 }
3201
Daniel Sandersa736b372016-04-29 13:33:12 +00003202 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003203 return false;
3204 }
3205 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00003206 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003207 return false;
3208 }
3209 }
3210
3211 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3212 Warning(IDLoc, "division by zero");
3213 if (Signed) {
3214 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003215 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003216 return false;
3217 }
3218
Daniel Sandersa736b372016-04-29 13:33:12 +00003219 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003220 return false;
3221 }
3222 }
3223
3224 // FIXME: The values for these two BranchTarget variables may be different in
3225 // micromips. These magic numbers need to be removed.
3226 unsigned BranchTargetNoTraps;
3227 unsigned BranchTarget;
3228
3229 if (UseTraps) {
3230 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003231 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003232 } else {
3233 BranchTarget = IsMips64 ? 20 : 16;
3234 BranchTargetNoTraps = 8;
3235 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003236 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003237 }
3238
Daniel Sandersa736b372016-04-29 13:33:12 +00003239 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003240
3241 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003242 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003243
3244 if (!Signed) {
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003245 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003246 return false;
3247 }
3248
3249 unsigned ATReg = getATReg(IDLoc);
3250 if (!ATReg)
3251 return true;
3252
Daniel Sandersa736b372016-04-29 13:33:12 +00003253 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003254 if (IsMips64) {
3255 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003256 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3257 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3258 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003259 } else {
3260 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003261 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3262 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003263 }
3264
3265 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003266 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003267 else {
3268 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003269 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3270 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3271 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003272 }
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003273 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003274 return false;
3275}
3276
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003277bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003278 SMLoc IDLoc, MCStreamer &Out,
3279 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003280 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003281
3282 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3283 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3284 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3285
3286 unsigned FirstReg = Inst.getOperand(0).getReg();
3287 unsigned SecondReg = Inst.getOperand(1).getReg();
3288 unsigned ThirdReg = Inst.getOperand(2).getReg();
3289
3290 if (hasMips1() && !hasMips2()) {
3291 unsigned ATReg = getATReg(IDLoc);
3292 if (!ATReg)
3293 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003294 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3295 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3296 TOut.emitNop(IDLoc, STI);
3297 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3298 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3299 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3300 TOut.emitNop(IDLoc, STI);
3301 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3302 : Mips::CVT_W_S,
3303 FirstReg, SecondReg, IDLoc, STI);
3304 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3305 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003306 return false;
3307 }
3308
Daniel Sandersa736b372016-04-29 13:33:12 +00003309 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3310 : Mips::TRUNC_W_S,
3311 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003312
3313 return false;
3314}
3315
Daniel Sanders6394ee52015-10-15 14:52:58 +00003316bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003317 MCStreamer &Out, const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003318 MipsTargetStreamer &TOut = getTargetStreamer();
3319
Toma Tabacud88d79c2015-06-23 14:39:42 +00003320 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003321 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003322 }
3323
3324 warnIfNoMacro(IDLoc);
3325
3326 const MCOperand &DstRegOp = Inst.getOperand(0);
3327 assert(DstRegOp.isReg() && "expected register operand kind");
3328
3329 const MCOperand &SrcRegOp = Inst.getOperand(1);
3330 assert(SrcRegOp.isReg() && "expected register operand kind");
3331
3332 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3333 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3334
3335 unsigned DstReg = DstRegOp.getReg();
3336 unsigned SrcReg = SrcRegOp.getReg();
3337 int64_t OffsetValue = OffsetImmOp.getImm();
3338
3339 // NOTE: We always need AT for ULHU, as it is always used as the source
3340 // register for one of the LBu's.
3341 unsigned ATReg = getATReg(IDLoc);
3342 if (!ATReg)
3343 return true;
3344
3345 // When the value of offset+1 does not fit in 16 bits, we have to load the
3346 // offset in AT, (D)ADDu the original source register (if there was one), and
3347 // then use AT as the source register for the 2 generated LBu's.
3348 bool LoadedOffsetInAT = false;
3349 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3350 LoadedOffsetInAT = true;
3351
3352 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003353 true, IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003354 return true;
3355
3356 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3357 // because it will make our output more similar to GAS'. For example,
3358 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3359 // instead of just an "ori $1, $9, 32768".
3360 // NOTE: If there is no source register specified in the ULHU, the parser
3361 // will interpret it as $0.
3362 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003363 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003364 }
3365
3366 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3367 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3368 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3369
3370 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3371 if (isLittle()) {
3372 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3373 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3374 } else {
3375 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3376 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3377 }
3378
3379 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3380
Daniel Sandersa736b372016-04-29 13:33:12 +00003381 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3382 FirstLbuOffset, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003383
Daniel Sandersa736b372016-04-29 13:33:12 +00003384 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3385 STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003386
Daniel Sandersa736b372016-04-29 13:33:12 +00003387 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003388
Daniel Sandersa736b372016-04-29 13:33:12 +00003389 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003390
3391 return false;
3392}
3393
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003394bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3395 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003396 MipsTargetStreamer &TOut = getTargetStreamer();
3397
Nirav Dave2364748a2016-09-16 18:30:20 +00003398 if (hasMips32r6() || hasMips64r6())
3399 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003400
3401 const MCOperand &DstRegOp = Inst.getOperand(0);
3402 assert(DstRegOp.isReg() && "expected register operand kind");
3403
3404 const MCOperand &SrcRegOp = Inst.getOperand(1);
3405 assert(SrcRegOp.isReg() && "expected register operand kind");
3406
3407 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3408 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3409
3410 unsigned SrcReg = SrcRegOp.getReg();
3411 int64_t OffsetValue = OffsetImmOp.getImm();
3412 unsigned ATReg = 0;
3413
3414 // When the value of offset+3 does not fit in 16 bits, we have to load the
3415 // offset in AT, (D)ADDu the original source register (if there was one), and
3416 // then use AT as the source register for the generated LWL and LWR.
3417 bool LoadedOffsetInAT = false;
3418 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3419 ATReg = getATReg(IDLoc);
3420 if (!ATReg)
3421 return true;
3422 LoadedOffsetInAT = true;
3423
3424 warnIfNoMacro(IDLoc);
3425
3426 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003427 true, IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003428 return true;
3429
3430 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3431 // because it will make our output more similar to GAS'. For example,
3432 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3433 // instead of just an "ori $1, $9, 32768".
3434 // NOTE: If there is no source register specified in the ULW, the parser
3435 // will interpret it as $0.
3436 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003437 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003438 }
3439
3440 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3441 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3442 if (isLittle()) {
3443 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3444 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3445 } else {
3446 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3447 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3448 }
3449
Daniel Sandersa736b372016-04-29 13:33:12 +00003450 TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3451 STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003452
Daniel Sandersa736b372016-04-29 13:33:12 +00003453 TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
3454 IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003455
3456 return false;
3457}
3458
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003459bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003460 MCStreamer &Out,
3461 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003462 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003463
3464 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3465 assert (Inst.getOperand(0).isReg() &&
3466 Inst.getOperand(1).isReg() &&
3467 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3468
3469 unsigned ATReg = Mips::NoRegister;
3470 unsigned FinalDstReg = Mips::NoRegister;
3471 unsigned DstReg = Inst.getOperand(0).getReg();
3472 unsigned SrcReg = Inst.getOperand(1).getReg();
3473 int64_t ImmValue = Inst.getOperand(2).getImm();
3474
3475 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3476
3477 unsigned FinalOpcode = Inst.getOpcode();
3478
3479 if (DstReg == SrcReg) {
3480 ATReg = getATReg(Inst.getLoc());
3481 if (!ATReg)
3482 return true;
3483 FinalDstReg = DstReg;
3484 DstReg = ATReg;
3485 }
3486
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003487 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003488 switch (FinalOpcode) {
3489 default:
3490 llvm_unreachable("unimplemented expansion");
3491 case (Mips::ADDi):
3492 FinalOpcode = Mips::ADD;
3493 break;
3494 case (Mips::ADDiu):
3495 FinalOpcode = Mips::ADDu;
3496 break;
3497 case (Mips::ANDi):
3498 FinalOpcode = Mips::AND;
3499 break;
3500 case (Mips::NORImm):
3501 FinalOpcode = Mips::NOR;
3502 break;
3503 case (Mips::ORi):
3504 FinalOpcode = Mips::OR;
3505 break;
3506 case (Mips::SLTi):
3507 FinalOpcode = Mips::SLT;
3508 break;
3509 case (Mips::SLTiu):
3510 FinalOpcode = Mips::SLTu;
3511 break;
3512 case (Mips::XORi):
3513 FinalOpcode = Mips::XOR;
3514 break;
3515 }
3516
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003517 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003518 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003519 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003520 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003521 return false;
3522 }
3523 return true;
3524}
3525
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003526bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3527 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003528 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003529 unsigned ATReg = Mips::NoRegister;
3530 unsigned DReg = Inst.getOperand(0).getReg();
3531 unsigned SReg = Inst.getOperand(1).getReg();
3532 unsigned TReg = Inst.getOperand(2).getReg();
3533 unsigned TmpReg = DReg;
3534
3535 unsigned FirstShift = Mips::NOP;
3536 unsigned SecondShift = Mips::NOP;
3537
3538 if (hasMips32r2()) {
3539
3540 if (DReg == SReg) {
3541 TmpReg = getATReg(Inst.getLoc());
3542 if (!TmpReg)
3543 return true;
3544 }
3545
3546 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003547 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3548 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003549 return false;
3550 }
3551
3552 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003553 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003554 return false;
3555 }
3556
3557 return true;
3558 }
3559
3560 if (hasMips32()) {
3561
3562 switch (Inst.getOpcode()) {
3563 default:
3564 llvm_unreachable("unexpected instruction opcode");
3565 case Mips::ROL:
3566 FirstShift = Mips::SRLV;
3567 SecondShift = Mips::SLLV;
3568 break;
3569 case Mips::ROR:
3570 FirstShift = Mips::SLLV;
3571 SecondShift = Mips::SRLV;
3572 break;
3573 }
3574
3575 ATReg = getATReg(Inst.getLoc());
3576 if (!ATReg)
3577 return true;
3578
Daniel Sandersa736b372016-04-29 13:33:12 +00003579 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3580 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3581 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3582 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003583
3584 return false;
3585 }
3586
3587 return true;
3588}
3589
3590bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003591 MCStreamer &Out,
3592 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003593 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003594 unsigned ATReg = Mips::NoRegister;
3595 unsigned DReg = Inst.getOperand(0).getReg();
3596 unsigned SReg = Inst.getOperand(1).getReg();
3597 int64_t ImmValue = Inst.getOperand(2).getImm();
3598
3599 unsigned FirstShift = Mips::NOP;
3600 unsigned SecondShift = Mips::NOP;
3601
3602 if (hasMips32r2()) {
3603
3604 if (Inst.getOpcode() == Mips::ROLImm) {
3605 uint64_t MaxShift = 32;
3606 uint64_t ShiftValue = ImmValue;
3607 if (ImmValue != 0)
3608 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003609 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003610 return false;
3611 }
3612
3613 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003614 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003615 return false;
3616 }
3617
3618 return true;
3619 }
3620
3621 if (hasMips32()) {
3622
3623 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003624 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003625 return false;
3626 }
3627
3628 switch (Inst.getOpcode()) {
3629 default:
3630 llvm_unreachable("unexpected instruction opcode");
3631 case Mips::ROLImm:
3632 FirstShift = Mips::SLL;
3633 SecondShift = Mips::SRL;
3634 break;
3635 case Mips::RORImm:
3636 FirstShift = Mips::SRL;
3637 SecondShift = Mips::SLL;
3638 break;
3639 }
3640
3641 ATReg = getATReg(Inst.getLoc());
3642 if (!ATReg)
3643 return true;
3644
Daniel Sandersa736b372016-04-29 13:33:12 +00003645 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3646 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3647 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003648
3649 return false;
3650 }
3651
3652 return true;
3653}
3654
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003655bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3656 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003657 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003658 unsigned ATReg = Mips::NoRegister;
3659 unsigned DReg = Inst.getOperand(0).getReg();
3660 unsigned SReg = Inst.getOperand(1).getReg();
3661 unsigned TReg = Inst.getOperand(2).getReg();
3662 unsigned TmpReg = DReg;
3663
3664 unsigned FirstShift = Mips::NOP;
3665 unsigned SecondShift = Mips::NOP;
3666
3667 if (hasMips64r2()) {
3668
3669 if (TmpReg == SReg) {
3670 TmpReg = getATReg(Inst.getLoc());
3671 if (!TmpReg)
3672 return true;
3673 }
3674
3675 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003676 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3677 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003678 return false;
3679 }
3680
3681 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003682 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003683 return false;
3684 }
3685
3686 return true;
3687 }
3688
3689 if (hasMips64()) {
3690
3691 switch (Inst.getOpcode()) {
3692 default:
3693 llvm_unreachable("unexpected instruction opcode");
3694 case Mips::DROL:
3695 FirstShift = Mips::DSRLV;
3696 SecondShift = Mips::DSLLV;
3697 break;
3698 case Mips::DROR:
3699 FirstShift = Mips::DSLLV;
3700 SecondShift = Mips::DSRLV;
3701 break;
3702 }
3703
3704 ATReg = getATReg(Inst.getLoc());
3705 if (!ATReg)
3706 return true;
3707
Daniel Sandersa736b372016-04-29 13:33:12 +00003708 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3709 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3710 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3711 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003712
3713 return false;
3714 }
3715
3716 return true;
3717}
3718
3719bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003720 MCStreamer &Out,
3721 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003722 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003723 unsigned ATReg = Mips::NoRegister;
3724 unsigned DReg = Inst.getOperand(0).getReg();
3725 unsigned SReg = Inst.getOperand(1).getReg();
3726 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3727
3728 unsigned FirstShift = Mips::NOP;
3729 unsigned SecondShift = Mips::NOP;
3730
3731 MCInst TmpInst;
3732
3733 if (hasMips64r2()) {
3734
3735 unsigned FinalOpcode = Mips::NOP;
3736 if (ImmValue == 0)
3737 FinalOpcode = Mips::DROTR;
3738 else if (ImmValue % 32 == 0)
3739 FinalOpcode = Mips::DROTR32;
3740 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3741 if (Inst.getOpcode() == Mips::DROLImm)
3742 FinalOpcode = Mips::DROTR32;
3743 else
3744 FinalOpcode = Mips::DROTR;
3745 } else if (ImmValue >= 33) {
3746 if (Inst.getOpcode() == Mips::DROLImm)
3747 FinalOpcode = Mips::DROTR;
3748 else
3749 FinalOpcode = Mips::DROTR32;
3750 }
3751
3752 uint64_t ShiftValue = ImmValue % 32;
3753 if (Inst.getOpcode() == Mips::DROLImm)
3754 ShiftValue = (32 - ImmValue % 32) % 32;
3755
Daniel Sandersa736b372016-04-29 13:33:12 +00003756 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003757
3758 return false;
3759 }
3760
3761 if (hasMips64()) {
3762
3763 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003764 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003765 return false;
3766 }
3767
3768 switch (Inst.getOpcode()) {
3769 default:
3770 llvm_unreachable("unexpected instruction opcode");
3771 case Mips::DROLImm:
3772 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3773 FirstShift = Mips::DSLL;
3774 SecondShift = Mips::DSRL32;
3775 }
3776 if (ImmValue == 32) {
3777 FirstShift = Mips::DSLL32;
3778 SecondShift = Mips::DSRL32;
3779 }
3780 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3781 FirstShift = Mips::DSLL32;
3782 SecondShift = Mips::DSRL;
3783 }
3784 break;
3785 case Mips::DRORImm:
3786 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3787 FirstShift = Mips::DSRL;
3788 SecondShift = Mips::DSLL32;
3789 }
3790 if (ImmValue == 32) {
3791 FirstShift = Mips::DSRL32;
3792 SecondShift = Mips::DSLL32;
3793 }
3794 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3795 FirstShift = Mips::DSRL32;
3796 SecondShift = Mips::DSLL;
3797 }
3798 break;
3799 }
3800
3801 ATReg = getATReg(Inst.getLoc());
3802 if (!ATReg)
3803 return true;
3804
Daniel Sandersa736b372016-04-29 13:33:12 +00003805 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3806 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3807 Inst.getLoc(), STI);
3808 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003809
3810 return false;
3811 }
3812
3813 return true;
3814}
3815
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003816bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3817 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003818 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003819 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3820 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3821
Daniel Sandersa736b372016-04-29 13:33:12 +00003822 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003823 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003824 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003825 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003826 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3827 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003828
3829 return false;
3830}
3831
Simon Dardisaff4d142016-10-18 14:28:00 +00003832static unsigned nextReg(unsigned Reg) {
3833 switch (Reg) {
3834 case Mips::ZERO: return Mips::AT;
3835 case Mips::AT: return Mips::V0;
3836 case Mips::V0: return Mips::V1;
3837 case Mips::V1: return Mips::A0;
3838 case Mips::A0: return Mips::A1;
3839 case Mips::A1: return Mips::A2;
3840 case Mips::A2: return Mips::A3;
3841 case Mips::A3: return Mips::T0;
3842 case Mips::T0: return Mips::T1;
3843 case Mips::T1: return Mips::T2;
3844 case Mips::T2: return Mips::T3;
3845 case Mips::T3: return Mips::T4;
3846 case Mips::T4: return Mips::T5;
3847 case Mips::T5: return Mips::T6;
3848 case Mips::T6: return Mips::T7;
3849 case Mips::T7: return Mips::S0;
3850 case Mips::S0: return Mips::S1;
3851 case Mips::S1: return Mips::S2;
3852 case Mips::S2: return Mips::S3;
3853 case Mips::S3: return Mips::S4;
3854 case Mips::S4: return Mips::S5;
3855 case Mips::S5: return Mips::S6;
3856 case Mips::S6: return Mips::S7;
3857 case Mips::S7: return Mips::T8;
3858 case Mips::T8: return Mips::T9;
3859 case Mips::T9: return Mips::K0;
3860 case Mips::K0: return Mips::K1;
3861 case Mips::K1: return Mips::GP;
3862 case Mips::GP: return Mips::SP;
3863 case Mips::SP: return Mips::FP;
3864 case Mips::FP: return Mips::RA;
3865 case Mips::RA: return Mips::ZERO;
3866 default: return 0;
3867 }
3868
3869}
3870
3871// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
3872// lw $<reg+1>>, offset+4($reg2)'
3873// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
3874// sw $<reg+1>>, offset+4($reg2)'
3875// for O32.
3876bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
3877 MCStreamer &Out,
3878 const MCSubtargetInfo *STI,
3879 bool IsLoad) {
3880 if (!isABI_O32())
3881 return true;
3882
3883 warnIfNoMacro(IDLoc);
3884
3885 MipsTargetStreamer &TOut = getTargetStreamer();
3886 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
3887 unsigned FirstReg = Inst.getOperand(0).getReg();
3888 unsigned SecondReg = nextReg(FirstReg);
3889 unsigned BaseReg = Inst.getOperand(1).getReg();
3890 if (!SecondReg)
3891 return true;
3892
3893 warnIfRegIndexIsAT(FirstReg, IDLoc);
3894
3895 assert(Inst.getOperand(2).isImm() &&
3896 "Offset for load macro is not immediate!");
3897
3898 MCOperand &FirstOffset = Inst.getOperand(2);
3899 signed NextOffset = FirstOffset.getImm() + 4;
3900 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
3901
3902 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
3903 return true;
3904
3905 // For loads, clobber the base register with the second load instead of the
3906 // first if the BaseReg == FirstReg.
3907 if (FirstReg != BaseReg || !IsLoad) {
3908 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
3909 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
3910 } else {
3911 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
3912 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
3913 }
3914
3915 return false;
3916}
3917
Daniel Sandersc5537422016-07-27 13:49:44 +00003918unsigned
3919MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
3920 const OperandVector &Operands) {
3921 switch (Inst.getOpcode()) {
3922 default:
3923 return Match_Success;
3924 case Mips::DATI:
3925 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00003926 case Mips::DATI_MM64R6:
3927 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00003928 if (static_cast<MipsOperand &>(*Operands[1])
3929 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
3930 return Match_Success;
3931 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00003932 }
3933}
Matheus Almeida595fcab2014-06-11 15:05:56 +00003934unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00003935 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00003936 // As described by the MIPSR6 spec, daui must not use the zero operand for
3937 // its source operand.
3938 case Mips::DAUI:
3939 case Mips::DAUI_MM64R6:
3940 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
3941 Inst.getOperand(1).getReg() == Mips::ZERO_64)
3942 return Match_RequiresNoZeroRegister;
3943 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00003944 // As described by the Mips32r2 spec, the registers Rd and Rs for
3945 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00003946 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00003947 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00003948 case Mips::JALR_HB:
3949 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00003950 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00003951 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
3952 return Match_RequiresDifferentSrcAndDst;
3953 return Match_Success;
3954 case Mips::LWP_MM:
3955 case Mips::LWP_MMR6:
3956 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
3957 return Match_RequiresDifferentSrcAndDst;
3958 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00003959 case Mips::SYNC:
3960 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
3961 return Match_NonZeroOperandForSync;
3962 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00003963 // As described the MIPSR6 spec, the compact branches that compare registers
3964 // must:
3965 // a) Not use the zero register.
3966 // b) Not use the same register twice.
3967 // c) rs < rt for bnec, beqc.
3968 // NB: For this case, the encoding will swap the operands as their
3969 // ordering doesn't matter. GAS performs this transformation too.
3970 // Hence, that constraint does not have to be enforced.
3971 //
3972 // The compact branches that branch iff the signed addition of two registers
3973 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
3974 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00003975 case Mips::BLEZC: case Mips::BLEZC_MMR6:
3976 case Mips::BGEZC: case Mips::BGEZC_MMR6:
3977 case Mips::BGTZC: case Mips::BGTZC_MMR6:
3978 case Mips::BLTZC: case Mips::BLTZC_MMR6:
3979 case Mips::BEQZC: case Mips::BEQZC_MMR6:
3980 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00003981 case Mips::BLEZC64:
3982 case Mips::BGEZC64:
3983 case Mips::BGTZC64:
3984 case Mips::BLTZC64:
3985 case Mips::BEQZC64:
3986 case Mips::BNEZC64:
3987 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
3988 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00003989 return Match_RequiresNoZeroRegister;
3990 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00003991 case Mips::BGEC: case Mips::BGEC_MMR6:
3992 case Mips::BLTC: case Mips::BLTC_MMR6:
3993 case Mips::BGEUC: case Mips::BGEUC_MMR6:
3994 case Mips::BLTUC: case Mips::BLTUC_MMR6:
3995 case Mips::BEQC: case Mips::BEQC_MMR6:
3996 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00003997 case Mips::BGEC64:
3998 case Mips::BLTC64:
3999 case Mips::BGEUC64:
4000 case Mips::BLTUC64:
4001 case Mips::BEQC64:
4002 case Mips::BNEC64:
4003 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4004 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004005 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00004006 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4007 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004008 return Match_RequiresNoZeroRegister;
4009 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4010 return Match_RequiresDifferentOperands;
4011 return Match_Success;
4012 default:
4013 return Match_Success;
4014 }
Matheus Almeida595fcab2014-06-11 15:05:56 +00004015}
4016
Daniel Sanders52da7af2015-11-06 12:11:03 +00004017static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
4018 uint64_t ErrorInfo) {
4019 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
4020 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
4021 if (ErrorLoc == SMLoc())
4022 return Loc;
4023 return ErrorLoc;
4024 }
4025 return Loc;
4026}
4027
David Blaikie960ea3f2014-06-08 16:18:35 +00004028bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4029 OperandVector &Operands,
4030 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004031 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00004032 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00004033
Jack Carterb4dbc172012-09-05 23:34:03 +00004034 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00004035 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004036 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00004037
4038 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004039 case Match_Success: {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004040 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00004041 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004042 return false;
4043 }
4044 case Match_MissingFeature:
4045 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4046 return true;
4047 case Match_InvalidOperand: {
4048 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00004049 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004050 if (ErrorInfo >= Operands.size())
4051 return Error(IDLoc, "too few operands for instruction");
4052
Daniel Sanders52da7af2015-11-06 12:11:03 +00004053 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00004054 if (ErrorLoc == SMLoc())
4055 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00004056 }
4057
4058 return Error(ErrorLoc, "invalid operand for instruction");
4059 }
Simon Dardisc4463c92016-10-18 14:42:13 +00004060 case Match_NonZeroOperandForSync:
4061 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00004062 case Match_MnemonicFail:
4063 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00004064 case Match_RequiresDifferentSrcAndDst:
4065 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00004066 case Match_RequiresDifferentOperands:
4067 return Error(IDLoc, "registers must be different");
4068 case Match_RequiresNoZeroRegister:
4069 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00004070 case Match_RequiresSameSrcAndDst:
4071 return Error(IDLoc, "source and destination must match");
Daniel Sanders52da7af2015-11-06 12:11:03 +00004072 case Match_Immz:
4073 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004074 case Match_UImm1_0:
4075 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4076 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00004077 case Match_UImm2_0:
4078 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4079 "expected 2-bit unsigned immediate");
4080 case Match_UImm2_1:
4081 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4082 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00004083 case Match_UImm3_0:
4084 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4085 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004086 case Match_UImm4_0:
4087 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4088 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00004089 case Match_SImm4_0:
4090 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4091 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004092 case Match_UImm5_0:
4093 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4094 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00004095 case Match_SImm5_0:
4096 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4097 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004098 case Match_UImm5_1:
4099 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4100 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004101 case Match_UImm5_32:
4102 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4103 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004104 case Match_UImm5_33:
4105 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4106 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004107 case Match_UImm5_0_Report_UImm6:
4108 // This is used on UImm5 operands that have a corresponding UImm5_32
4109 // operand to avoid confusing the user.
4110 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4111 "expected 6-bit unsigned immediate");
4112 case Match_UImm5_Lsl2:
4113 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4114 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00004115 case Match_UImmRange2_64:
4116 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4117 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00004118 case Match_UImm6_0:
4119 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4120 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00004121 case Match_UImm6_Lsl2:
4122 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4123 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00004124 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00004125 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4126 "expected 6-bit signed immediate");
4127 case Match_UImm7_0:
4128 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4129 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00004130 case Match_UImm7_N1:
4131 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4132 "expected immediate in range -1 .. 126");
4133 case Match_SImm7_Lsl2:
4134 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4135 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00004136 case Match_UImm8_0:
4137 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4138 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00004139 case Match_UImm10_0:
4140 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4141 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00004142 case Match_SImm10_0:
4143 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4144 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00004145 case Match_SImm11_0:
4146 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4147 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00004148 case Match_UImm16:
4149 case Match_UImm16_Relaxed:
4150 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4151 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004152 case Match_SImm16:
4153 case Match_SImm16_Relaxed:
4154 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4155 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00004156 case Match_SImm19_Lsl2:
4157 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4158 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00004159 case Match_UImm20_0:
4160 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4161 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00004162 case Match_UImm26_0:
4163 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4164 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00004165 case Match_SImm32:
4166 case Match_SImm32_Relaxed:
4167 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4168 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00004169 case Match_UImm32_Coerced:
4170 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4171 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00004172 case Match_MemSImm9:
4173 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4174 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00004175 case Match_MemSImm10:
4176 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4177 "expected memory with 10-bit signed offset");
4178 case Match_MemSImm10Lsl1:
4179 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4180 "expected memory with 11-bit signed offset and multiple of 2");
4181 case Match_MemSImm10Lsl2:
4182 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4183 "expected memory with 12-bit signed offset and multiple of 4");
4184 case Match_MemSImm10Lsl3:
4185 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4186 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00004187 case Match_MemSImm11:
4188 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4189 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00004190 case Match_MemSImm12:
4191 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4192 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004193 case Match_MemSImm16:
4194 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4195 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00004196 }
Craig Topper589ceee2015-01-03 08:16:34 +00004197
4198 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00004199}
4200
Toma Tabacud9d344b2015-04-27 14:05:04 +00004201void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
4202 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
4203 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
4204 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004205}
4206
Toma Tabacu81496c12015-05-20 08:54:45 +00004207void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
4208 if (!AssemblerOptions.back()->isMacro())
4209 Warning(Loc, "macro instruction expanded into multiple instructions");
4210}
4211
Daniel Sandersef638fe2014-10-03 15:37:37 +00004212void
4213MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
4214 SMRange Range, bool ShowColors) {
4215 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00004216 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00004217 ShowColors);
4218}
4219
Jack Carter1ac53222013-02-20 23:11:17 +00004220int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004221 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004222
Vladimir Medic4c299852013-11-06 11:27:05 +00004223 CC = StringSwitch<unsigned>(Name)
4224 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004225 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00004226 .Case("a0", 4)
4227 .Case("a1", 5)
4228 .Case("a2", 6)
4229 .Case("a3", 7)
4230 .Case("v0", 2)
4231 .Case("v1", 3)
4232 .Case("s0", 16)
4233 .Case("s1", 17)
4234 .Case("s2", 18)
4235 .Case("s3", 19)
4236 .Case("s4", 20)
4237 .Case("s5", 21)
4238 .Case("s6", 22)
4239 .Case("s7", 23)
4240 .Case("k0", 26)
4241 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004242 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00004243 .Case("sp", 29)
4244 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004245 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00004246 .Case("ra", 31)
4247 .Case("t0", 8)
4248 .Case("t1", 9)
4249 .Case("t2", 10)
4250 .Case("t3", 11)
4251 .Case("t4", 12)
4252 .Case("t5", 13)
4253 .Case("t6", 14)
4254 .Case("t7", 15)
4255 .Case("t8", 24)
4256 .Case("t9", 25)
4257 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004258
Toma Tabacufda445c2014-09-15 15:33:01 +00004259 if (!(isABI_N32() || isABI_N64()))
4260 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004261
Daniel Sandersef638fe2014-10-03 15:37:37 +00004262 if (12 <= CC && CC <= 15) {
4263 // Name is one of t4-t7
4264 AsmToken RegTok = getLexer().peekTok();
4265 SMRange RegRange = RegTok.getLocRange();
4266
4267 StringRef FixedName = StringSwitch<StringRef>(Name)
4268 .Case("t4", "t0")
4269 .Case("t5", "t1")
4270 .Case("t6", "t2")
4271 .Case("t7", "t3")
4272 .Default("");
4273 assert(FixedName != "" && "Register name is not one of t4-t7.");
4274
4275 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
4276 "Did you mean $" + FixedName + "?", RegRange);
4277 }
4278
Toma Tabacufda445c2014-09-15 15:33:01 +00004279 // Although SGI documentation just cuts out t0-t3 for n32/n64,
4280 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
4281 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
4282 if (8 <= CC && CC <= 11)
4283 CC += 4;
4284
4285 if (CC == -1)
4286 CC = StringSwitch<unsigned>(Name)
4287 .Case("a4", 8)
4288 .Case("a5", 9)
4289 .Case("a6", 10)
4290 .Case("a7", 11)
4291 .Case("kt0", 26)
4292 .Case("kt1", 27)
4293 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004294
4295 return CC;
4296}
Jack Carterd0bd6422013-04-18 00:41:53 +00004297
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004298int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
4299 int CC;
4300
4301 CC = StringSwitch<unsigned>(Name)
4302 .Case("hwr_cpunum", 0)
4303 .Case("hwr_synci_step", 1)
4304 .Case("hwr_cc", 2)
4305 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00004306 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004307 .Default(-1);
4308
4309 return CC;
4310}
4311
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004312int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004313
Jack Cartera63b16a2012-09-07 00:23:42 +00004314 if (Name[0] == 'f') {
4315 StringRef NumString = Name.substr(1);
4316 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004317 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004318 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004319 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00004320 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004321 return IntVal;
4322 }
4323 return -1;
4324}
Jack Cartera63b16a2012-09-07 00:23:42 +00004325
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004326int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
4327
4328 if (Name.startswith("fcc")) {
4329 StringRef NumString = Name.substr(3);
4330 unsigned IntVal;
4331 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004332 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004333 if (IntVal > 7) // There are only 8 fcc registers.
4334 return -1;
4335 return IntVal;
4336 }
4337 return -1;
4338}
4339
4340int MipsAsmParser::matchACRegisterName(StringRef Name) {
4341
Akira Hatanaka274d24c2013-08-14 01:15:52 +00004342 if (Name.startswith("ac")) {
4343 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004344 unsigned IntVal;
4345 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004346 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004347 if (IntVal > 3) // There are only 3 acc registers.
4348 return -1;
4349 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00004350 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004351 return -1;
4352}
Jack Carterd0bd6422013-04-18 00:41:53 +00004353
Jack Carter5dc8ac92013-09-25 23:50:44 +00004354int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
4355 unsigned IntVal;
4356
4357 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
4358 return -1;
4359
4360 if (IntVal > 31)
4361 return -1;
4362
4363 return IntVal;
4364}
4365
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004366int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
4367 int CC;
4368
4369 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00004370 .Case("msair", 0)
4371 .Case("msacsr", 1)
4372 .Case("msaaccess", 2)
4373 .Case("msasave", 3)
4374 .Case("msamodify", 4)
4375 .Case("msarequest", 5)
4376 .Case("msamap", 6)
4377 .Case("msaunmap", 7)
4378 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004379
4380 return CC;
4381}
4382
Toma Tabacu89a712b2015-04-15 10:48:56 +00004383unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004384 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004385 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004386 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004387 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004388 return 0;
4389 }
4390 unsigned AT = getReg(
4391 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004392 return AT;
4393}
Jack Carter0b744b32012-10-04 02:29:46 +00004394
Jack Carterd0bd6422013-04-18 00:41:53 +00004395unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004396 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004397}
4398
Toma Tabacu13964452014-09-04 13:23:44 +00004399bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004400 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004401 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004402
Jack Carter30a59822012-10-04 04:03:53 +00004403 // Check if the current operand has a custom associated parser, if so, try to
4404 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004405 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4406 if (ResTy == MatchOperand_Success)
4407 return false;
4408 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4409 // there was a match, but an error occurred, in which case, just return that
4410 // the operand parsing failed.
4411 if (ResTy == MatchOperand_ParseFail)
4412 return true;
4413
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004414 DEBUG(dbgs() << ".. Generic Parser\n");
4415
Jack Carterb4dbc172012-09-05 23:34:03 +00004416 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004417 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004418 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004419 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004420
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004421 // Almost all registers have been parsed by custom parsers. There is only
4422 // one exception to this. $zero (and it's alias $0) will reach this point
4423 // for div, divu, and similar instructions because it is not an operand
4424 // to the instruction definition but an explicit register. Special case
4425 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004426 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004427 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004428
Jack Carterd0bd6422013-04-18 00:41:53 +00004429 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004430 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004431 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004432 return true;
4433
Jack Carter873c7242013-01-12 01:03:14 +00004434 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004435 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004436 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004437 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004438 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004439
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004440 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004441 return false;
4442 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004443 default: {
4444 DEBUG(dbgs() << ".. generic integer expression\n");
4445
4446 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00004447 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004448 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004449 return true;
4450
Jack Carter873c7242013-01-12 01:03:14 +00004451 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4452
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004453 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004454 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004455 }
Jack Carter0b744b32012-10-04 02:29:46 +00004456 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004457 return true;
4458}
4459
Jack Carterb5cf5902013-04-17 00:18:04 +00004460bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4461
4462 switch (Expr->getKind()) {
4463 case MCExpr::Constant:
4464 return true;
4465 case MCExpr::SymbolRef:
4466 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4467 case MCExpr::Binary:
4468 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4469 if (!isEvaluated(BE->getLHS()))
4470 return false;
4471 return isEvaluated(BE->getRHS());
4472 }
4473 case MCExpr::Unary:
4474 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004475 case MCExpr::Target:
4476 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004477 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004478 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004479}
Jack Carterd0bd6422013-04-18 00:41:53 +00004480
Jack Carterb4dbc172012-09-05 23:34:03 +00004481bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4482 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004483 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004484 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004485 if (ResTy == MatchOperand_Success) {
4486 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004487 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004488 StartLoc = Operand.getStartLoc();
4489 EndLoc = Operand.getEndLoc();
4490
4491 // AFAIK, we only support numeric registers and named GPR's in CFI
4492 // directives.
4493 // Don't worry about eating tokens before failing. Using an unrecognised
4494 // register is a parse error.
4495 if (Operand.isGPRAsmReg()) {
4496 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004497 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004498 }
4499
4500 return (RegNo == (unsigned)-1);
4501 }
4502
4503 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004504 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004505}
4506
Jack Carterb5cf5902013-04-17 00:18:04 +00004507bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00004508 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004509
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004510 if (isParenExpr)
4511 return getParser().parseParenExprOfDepth(0, Res, S);
4512 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004513}
4514
David Blaikie960ea3f2014-06-08 16:18:35 +00004515MipsAsmParser::OperandMatchResultTy
4516MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004517 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004518 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004519 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004520 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004521 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004522 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004523 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004524 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004525
Jack Carterb5cf5902013-04-17 00:18:04 +00004526 if (getLexer().getKind() == AsmToken::LParen) {
4527 Parser.Lex();
4528 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004529 }
4530
Jack Carterb5cf5902013-04-17 00:18:04 +00004531 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004532 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004533 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004534
Jack Carterd0bd6422013-04-18 00:41:53 +00004535 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004536 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004537 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004538 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004539 SMLoc E =
4540 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004541 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004542 return MatchOperand_Success;
4543 }
4544 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004545 SMLoc E =
4546 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004547
Jack Carterd0bd6422013-04-18 00:41:53 +00004548 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004549 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00004550 auto Base = MipsOperand::createGPRReg(
4551 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00004552 Operands.push_back(
4553 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004554 return MatchOperand_Success;
4555 }
4556 Error(Parser.getTok().getLoc(), "'(' expected");
4557 return MatchOperand_ParseFail;
4558 }
4559
Jack Carterd0bd6422013-04-18 00:41:53 +00004560 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004561 }
4562
Toma Tabacu13964452014-09-04 13:23:44 +00004563 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004564 if (Res != MatchOperand_Success)
4565 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004566
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004567 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004568 Error(Parser.getTok().getLoc(), "')' expected");
4569 return MatchOperand_ParseFail;
4570 }
4571
Jack Carter873c7242013-01-12 01:03:14 +00004572 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4573
Jack Carterd0bd6422013-04-18 00:41:53 +00004574 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004575
Craig Topper062a2ba2014-04-25 05:30:21 +00004576 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004577 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004578
Jack Carterd0bd6422013-04-18 00:41:53 +00004579 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004580 std::unique_ptr<MipsOperand> op(
4581 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004582 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004583 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004584 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004585 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004586 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4587 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004588 if (IdVal->evaluateAsAbsolute(Imm))
4589 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004590 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004591 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004592 getContext());
4593 }
4594
David Blaikie960ea3f2014-06-08 16:18:35 +00004595 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004596 return MatchOperand_Success;
4597}
4598
David Blaikie960ea3f2014-06-08 16:18:35 +00004599bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004600 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004601 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004602 if (Sym) {
4603 SMLoc S = Parser.getTok().getLoc();
4604 const MCExpr *Expr;
4605 if (Sym->isVariable())
4606 Expr = Sym->getVariableValue();
4607 else
4608 return false;
4609 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004610 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004611 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004612 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004613 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004614 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004615 if (ResTy == MatchOperand_Success) {
4616 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004617 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004618 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004619 llvm_unreachable("Should never ParseFail");
4620 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004621 }
Jack Carterd76b2372013-03-21 21:44:16 +00004622 }
4623 }
4624 return false;
4625}
Jack Carterd0bd6422013-04-18 00:41:53 +00004626
Jack Carter873c7242013-01-12 01:03:14 +00004627MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004628MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004629 StringRef Identifier,
4630 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004631 int Index = matchCPURegisterName(Identifier);
4632 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004633 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004634 Index, Identifier, getContext().getRegisterInfo(), S,
4635 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004636 return MatchOperand_Success;
4637 }
4638
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004639 Index = matchHWRegsRegisterName(Identifier);
4640 if (Index != -1) {
4641 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004642 Index, Identifier, getContext().getRegisterInfo(), S,
4643 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004644 return MatchOperand_Success;
4645 }
4646
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004647 Index = matchFPURegisterName(Identifier);
4648 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004649 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004650 Index, Identifier, getContext().getRegisterInfo(), S,
4651 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004652 return MatchOperand_Success;
4653 }
4654
4655 Index = matchFCCRegisterName(Identifier);
4656 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004657 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004658 Index, Identifier, getContext().getRegisterInfo(), S,
4659 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004660 return MatchOperand_Success;
4661 }
4662
4663 Index = matchACRegisterName(Identifier);
4664 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004665 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004666 Index, Identifier, getContext().getRegisterInfo(), S,
4667 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004668 return MatchOperand_Success;
4669 }
4670
4671 Index = matchMSA128RegisterName(Identifier);
4672 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004673 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004674 Index, Identifier, getContext().getRegisterInfo(), S,
4675 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004676 return MatchOperand_Success;
4677 }
4678
4679 Index = matchMSA128CtrlRegisterName(Identifier);
4680 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004681 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004682 Index, Identifier, getContext().getRegisterInfo(), S,
4683 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004684 return MatchOperand_Success;
4685 }
4686
4687 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004688}
4689
4690MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004691MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004692 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004693 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004694
4695 if (Token.is(AsmToken::Identifier)) {
4696 DEBUG(dbgs() << ".. identifier\n");
4697 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004698 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004699 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004700 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004701 } else if (Token.is(AsmToken::Integer)) {
4702 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004703 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004704 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
4705 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004706 return MatchOperand_Success;
4707 }
4708
4709 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4710
4711 return MatchOperand_NoMatch;
4712}
4713
David Blaikie960ea3f2014-06-08 16:18:35 +00004714MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004715MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004716 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004717 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004718
4719 auto Token = Parser.getTok();
4720
4721 SMLoc S = Token.getLoc();
4722
4723 if (Token.isNot(AsmToken::Dollar)) {
4724 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4725 if (Token.is(AsmToken::Identifier)) {
4726 if (searchSymbolAlias(Operands))
4727 return MatchOperand_Success;
4728 }
4729 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4730 return MatchOperand_NoMatch;
4731 }
4732 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004733
Toma Tabacu13964452014-09-04 13:23:44 +00004734 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004735 if (ResTy == MatchOperand_Success) {
4736 Parser.Lex(); // $
4737 Parser.Lex(); // identifier
4738 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004739 return ResTy;
4740}
4741
4742MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004743MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004744 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004745 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004746
4747 SMLoc S = getLexer().getLoc();
4748
Daniel Sanderscae9aee2016-08-08 09:33:14 +00004749 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004750 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00004751 if (ResTy != MatchOperand_NoMatch)
4752 return ResTy;
4753
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004754 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00004755 const MCExpr *Expr = nullptr;
4756 if (Parser.parseExpression(Expr)) {
4757 // We have no way of knowing if a symbol was consumed so we must ParseFail
4758 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004759 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004760 Operands.push_back(
4761 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004762 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004763}
4764
Vladimir Medic2b953d02013-10-01 09:48:56 +00004765MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004766MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004767 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004768 const MCExpr *IdVal;
4769 // If the first token is '$' we may have register operand.
4770 if (Parser.getTok().is(AsmToken::Dollar))
4771 return MatchOperand_NoMatch;
4772 SMLoc S = Parser.getTok().getLoc();
4773 if (getParser().parseExpression(IdVal))
4774 return MatchOperand_ParseFail;
4775 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004776 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004777 int64_t Val = MCE->getValue();
4778 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4779 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004780 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004781 return MatchOperand_Success;
4782}
4783
Matheus Almeida779c5932013-11-18 12:32:49 +00004784MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004785MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4786 MCAsmParser &Parser = getParser();
4787 SmallVector<unsigned, 10> Regs;
4788 unsigned RegNo;
4789 unsigned PrevReg = Mips::NoRegister;
4790 bool RegRange = false;
4791 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4792
4793 if (Parser.getTok().isNot(AsmToken::Dollar))
4794 return MatchOperand_ParseFail;
4795
4796 SMLoc S = Parser.getTok().getLoc();
4797 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4798 SMLoc E = getLexer().getLoc();
4799 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4800 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4801 if (RegRange) {
4802 // Remove last register operand because registers from register range
4803 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004804 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4805 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004806 Regs.push_back(RegNo);
4807 } else {
4808 unsigned TmpReg = PrevReg + 1;
4809 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004810 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4811 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4812 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004813 Error(E, "invalid register operand");
4814 return MatchOperand_ParseFail;
4815 }
4816
4817 PrevReg = TmpReg;
4818 Regs.push_back(TmpReg++);
4819 }
4820 }
4821
4822 RegRange = false;
4823 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004824 if ((PrevReg == Mips::NoRegister) &&
4825 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4826 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004827 Error(E, "$16 or $31 expected");
4828 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004829 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4830 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4831 !isGP64bit()) ||
4832 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4833 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4834 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004835 Error(E, "invalid register operand");
4836 return MatchOperand_ParseFail;
4837 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004838 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4839 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4840 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004841 Error(E, "consecutive register numbers expected");
4842 return MatchOperand_ParseFail;
4843 }
4844
4845 Regs.push_back(RegNo);
4846 }
4847
4848 if (Parser.getTok().is(AsmToken::Minus))
4849 RegRange = true;
4850
4851 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4852 !Parser.getTok().isNot(AsmToken::Comma)) {
4853 Error(E, "',' or '-' expected");
4854 return MatchOperand_ParseFail;
4855 }
4856
4857 Lex(); // Consume comma or minus
4858 if (Parser.getTok().isNot(AsmToken::Dollar))
4859 break;
4860
4861 PrevReg = RegNo;
4862 }
4863
4864 SMLoc E = Parser.getTok().getLoc();
4865 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4866 parseMemOperand(Operands);
4867 return MatchOperand_Success;
4868}
4869
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004870MipsAsmParser::OperandMatchResultTy
4871MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4872 MCAsmParser &Parser = getParser();
4873
4874 SMLoc S = Parser.getTok().getLoc();
4875 if (parseAnyRegister(Operands) != MatchOperand_Success)
4876 return MatchOperand_ParseFail;
4877
4878 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00004879 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00004880
Benjamin Kramer2b68d152016-05-09 10:31:17 +00004881 Operands.pop_back();
4882 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004883 return MatchOperand_Success;
4884}
4885
Zoran Jovanovic41688672015-02-10 16:36:20 +00004886MipsAsmParser::OperandMatchResultTy
4887MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4888 MCAsmParser &Parser = getParser();
4889 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4890 SmallVector<unsigned, 10> Regs;
4891
4892 if (Parser.getTok().isNot(AsmToken::Dollar))
4893 return MatchOperand_ParseFail;
4894
4895 SMLoc S = Parser.getTok().getLoc();
4896
4897 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4898 return MatchOperand_ParseFail;
4899
4900 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4901 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4902 Regs.push_back(RegNo);
4903
4904 SMLoc E = Parser.getTok().getLoc();
4905 if (Parser.getTok().isNot(AsmToken::Comma)) {
4906 Error(E, "',' expected");
4907 return MatchOperand_ParseFail;
4908 }
4909
4910 // Remove comma.
4911 Parser.Lex();
4912
4913 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4914 return MatchOperand_ParseFail;
4915
4916 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4917 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4918 Regs.push_back(RegNo);
4919
4920 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4921
4922 return MatchOperand_Success;
4923}
4924
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004925/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4926/// either this.
4927/// ::= '(', register, ')'
4928/// handle it before we iterate so we don't get tripped up by the lack of
4929/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004930bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004931 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004932 if (getLexer().is(AsmToken::LParen)) {
4933 Operands.push_back(
4934 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4935 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004936 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004937 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004938 return Error(Loc, "unexpected token in argument list");
4939 }
4940 if (Parser.getTok().isNot(AsmToken::RParen)) {
4941 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004942 return Error(Loc, "unexpected token, expected ')'");
4943 }
4944 Operands.push_back(
4945 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4946 Parser.Lex();
4947 }
4948 return false;
4949}
4950
4951/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4952/// either one of these.
4953/// ::= '[', register, ']'
4954/// ::= '[', integer, ']'
4955/// handle it before we iterate so we don't get tripped up by the lack of
4956/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004957bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004958 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004959 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004960 if (getLexer().is(AsmToken::LBrac)) {
4961 Operands.push_back(
4962 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4963 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004964 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004965 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004966 return Error(Loc, "unexpected token in argument list");
4967 }
4968 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4969 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004970 return Error(Loc, "unexpected token, expected ']'");
4971 }
4972 Operands.push_back(
4973 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4974 Parser.Lex();
4975 }
4976 return false;
4977}
4978
David Blaikie960ea3f2014-06-08 16:18:35 +00004979bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4980 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004981 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004982 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004983
4984 // We have reached first instruction, module directive are now forbidden.
4985 getTargetStreamer().forbidModuleDirective();
4986
Vladimir Medic74593e62013-07-17 15:00:42 +00004987 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004988 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004989 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004990 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004991 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004992 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004993
4994 // Read the remaining operands.
4995 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4996 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004997 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004998 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004999 return Error(Loc, "unexpected token in argument list");
5000 }
Toma Tabacu13964452014-09-04 13:23:44 +00005001 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005002 return true;
5003 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00005004
Jack Carterd0bd6422013-04-18 00:41:53 +00005005 while (getLexer().is(AsmToken::Comma)) {
5006 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00005007 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005008 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005009 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005010 return Error(Loc, "unexpected token in argument list");
5011 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005012 // Parse bracket and parenthesis suffixes before we iterate
5013 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00005014 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005015 return true;
5016 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00005017 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005018 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005019 }
5020 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005021 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5022 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005023 return Error(Loc, "unexpected token in argument list");
5024 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005025 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00005026 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00005027}
5028
Nirav Dave996fc132016-05-05 14:15:46 +00005029// FIXME: Given that these have the same name, these should both be
5030// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005031bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005032 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005033 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00005034}
5035
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005036bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005037 return Error(Loc, ErrorMsg);
5038}
5039
Jack Carter0b744b32012-10-04 02:29:46 +00005040bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005041 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005042 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00005043
5044 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00005045 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00005046
5047 Parser.Lex(); // Eat "noat".
5048
Jack Carterd0bd6422013-04-18 00:41:53 +00005049 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005050 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005051 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005052 return false;
5053 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005054
5055 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005056 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005057 return false;
5058}
Jack Carterd0bd6422013-04-18 00:41:53 +00005059
Jack Carter0b744b32012-10-04 02:29:46 +00005060bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00005061 // Line can be: ".set at", which sets $at to $1
5062 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00005063 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00005064 Parser.Lex(); // Eat "at".
5065
Jack Carter0b744b32012-10-04 02:29:46 +00005066 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005067 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00005068 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00005069
5070 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005071 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005072 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00005073 }
5074
5075 if (getLexer().isNot(AsmToken::Equal)) {
5076 reportParseError("unexpected token, expected equals sign");
5077 return false;
5078 }
5079 Parser.Lex(); // Eat "=".
5080
5081 if (getLexer().isNot(AsmToken::Dollar)) {
5082 if (getLexer().is(AsmToken::EndOfStatement)) {
5083 reportParseError("no register specified");
5084 return false;
5085 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00005086 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00005087 return false;
5088 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005089 }
5090 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00005091
Toma Tabacu16a74492015-02-13 10:30:57 +00005092 // Find out what "reg" is.
5093 unsigned AtRegNo;
5094 const AsmToken &Reg = Parser.getTok();
5095 if (Reg.is(AsmToken::Identifier)) {
5096 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
5097 } else if (Reg.is(AsmToken::Integer)) {
5098 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00005099 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00005100 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00005101 return false;
5102 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005103
5104 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00005105 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005106 reportParseError("invalid register");
5107 return false;
5108 }
5109 Parser.Lex(); // Eat "reg".
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 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
5118
5119 Parser.Lex(); // Consume the EndOfStatement.
5120 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005121}
5122
5123bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005124 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005125 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005126 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005127 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005128 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005129 return false;
5130 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005131 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00005132 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005133 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005134 return false;
5135}
5136
5137bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005138 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005139 Parser.Lex();
5140 // If this is not the end of the statement, report an error.
5141 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005142 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005143 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005144 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005145 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005146 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005147 Parser.Lex(); // Consume the EndOfStatement.
5148 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005149}
5150
5151bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005152 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005153 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005154 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005155 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005156 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005157 return false;
5158 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005159 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005160 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005161 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005162 return false;
5163}
5164
5165bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005166 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005167 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005168 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005169 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005170 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005171 return false;
5172 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005173 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005174 reportParseError("`noreorder' must be set before `nomacro'");
5175 return false;
5176 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005177 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005178 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005179 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005180 return false;
5181}
Jack Carterd76b2372013-03-21 21:44:16 +00005182
Daniel Sanders44934432014-08-07 12:03:36 +00005183bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005184 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005185 Parser.Lex();
5186
5187 // If this is not the end of the statement, report an error.
5188 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005189 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005190
5191 setFeatureBits(Mips::FeatureMSA, "msa");
5192 getTargetStreamer().emitDirectiveSetMsa();
5193 return false;
5194}
5195
5196bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005197 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005198 Parser.Lex();
5199
5200 // If this is not the end of the statement, report an error.
5201 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005202 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005203
5204 clearFeatureBits(Mips::FeatureMSA, "msa");
5205 getTargetStreamer().emitDirectiveSetNoMsa();
5206 return false;
5207}
5208
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005209bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005210 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005211 Parser.Lex(); // Eat "nodsp".
5212
5213 // If this is not the end of the statement, report an error.
5214 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5215 reportParseError("unexpected token, expected end of statement");
5216 return false;
5217 }
5218
5219 clearFeatureBits(Mips::FeatureDSP, "dsp");
5220 getTargetStreamer().emitDirectiveSetNoDsp();
5221 return false;
5222}
5223
Toma Tabacucc2502d2014-11-04 17:18:07 +00005224bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005225 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005226 Parser.Lex(); // Eat "mips16".
5227
Jack Carter39536722014-01-22 23:08:42 +00005228 // If this is not the end of the statement, report an error.
5229 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005230 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005231 return false;
5232 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005233
5234 setFeatureBits(Mips::FeatureMips16, "mips16");
5235 getTargetStreamer().emitDirectiveSetMips16();
5236 Parser.Lex(); // Consume the EndOfStatement.
5237 return false;
5238}
5239
5240bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005241 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005242 Parser.Lex(); // Eat "nomips16".
5243
5244 // If this is not the end of the statement, report an error.
5245 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5246 reportParseError("unexpected token, expected end of statement");
5247 return false;
5248 }
5249
5250 clearFeatureBits(Mips::FeatureMips16, "mips16");
5251 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005252 Parser.Lex(); // Consume the EndOfStatement.
5253 return false;
5254}
5255
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005256bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005257 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005258 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005259 // Line can be: .set fp=32
5260 // .set fp=xx
5261 // .set fp=64
5262 Parser.Lex(); // Eat fp token
5263 AsmToken Tok = Parser.getTok();
5264 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005265 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005266 return false;
5267 }
5268 Parser.Lex(); // Eat '=' token.
5269 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005270
5271 if (!parseFpABIValue(FpAbiVal, ".set"))
5272 return false;
5273
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005274 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005275 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005276 return false;
5277 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005278 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005279 Parser.Lex(); // Consume the EndOfStatement.
5280 return false;
5281}
5282
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005283bool MipsAsmParser::parseSetOddSPRegDirective() {
5284 MCAsmParser &Parser = getParser();
5285
5286 Parser.Lex(); // Eat "oddspreg".
5287 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5288 reportParseError("unexpected token, expected end of statement");
5289 return false;
5290 }
5291
5292 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5293 getTargetStreamer().emitDirectiveSetOddSPReg();
5294 return false;
5295}
5296
5297bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5298 MCAsmParser &Parser = getParser();
5299
5300 Parser.Lex(); // Eat "nooddspreg".
5301 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5302 reportParseError("unexpected token, expected end of statement");
5303 return false;
5304 }
5305
5306 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5307 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5308 return false;
5309}
5310
Toma Tabacu9db22db2014-09-09 10:15:38 +00005311bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005312 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005313 SMLoc Loc = getLexer().getLoc();
5314
5315 Parser.Lex();
5316 if (getLexer().isNot(AsmToken::EndOfStatement))
5317 return reportParseError("unexpected token, expected end of statement");
5318
5319 // Always keep an element on the options "stack" to prevent the user
5320 // from changing the initial options. This is how we remember them.
5321 if (AssemblerOptions.size() == 2)
5322 return reportParseError(Loc, ".set pop with no .set push");
5323
Akira Hatanakab11ef082015-11-14 06:35:56 +00005324 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005325 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005326 setAvailableFeatures(
5327 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5328 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005329
5330 getTargetStreamer().emitDirectiveSetPop();
5331 return false;
5332}
5333
5334bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005335 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005336 Parser.Lex();
5337 if (getLexer().isNot(AsmToken::EndOfStatement))
5338 return reportParseError("unexpected token, expected end of statement");
5339
5340 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005341 AssemblerOptions.push_back(
5342 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005343
5344 getTargetStreamer().emitDirectiveSetPush();
5345 return false;
5346}
5347
Toma Tabacu29696502015-06-02 09:48:04 +00005348bool MipsAsmParser::parseSetSoftFloatDirective() {
5349 MCAsmParser &Parser = getParser();
5350 Parser.Lex();
5351 if (getLexer().isNot(AsmToken::EndOfStatement))
5352 return reportParseError("unexpected token, expected end of statement");
5353
5354 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5355 getTargetStreamer().emitDirectiveSetSoftFloat();
5356 return false;
5357}
5358
5359bool MipsAsmParser::parseSetHardFloatDirective() {
5360 MCAsmParser &Parser = getParser();
5361 Parser.Lex();
5362 if (getLexer().isNot(AsmToken::EndOfStatement))
5363 return reportParseError("unexpected token, expected end of statement");
5364
5365 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5366 getTargetStreamer().emitDirectiveSetHardFloat();
5367 return false;
5368}
5369
Jack Carterd76b2372013-03-21 21:44:16 +00005370bool MipsAsmParser::parseSetAssignment() {
5371 StringRef Name;
5372 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005373 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005374
5375 if (Parser.parseIdentifier(Name))
5376 reportParseError("expected identifier after .set");
5377
5378 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005379 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005380 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005381
Jack Carter3b2c96e2014-01-22 23:31:38 +00005382 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005383 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005384
Jim Grosbach6f482002015-05-18 18:43:14 +00005385 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005386 Sym->setVariableValue(Value);
5387
5388 return false;
5389}
Jack Carterd0bd6422013-04-18 00:41:53 +00005390
Toma Tabacu26647792014-09-09 12:52:14 +00005391bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005392 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005393 Parser.Lex();
5394 if (getLexer().isNot(AsmToken::EndOfStatement))
5395 return reportParseError("unexpected token, expected end of statement");
5396
5397 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005398 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005399 setAvailableFeatures(
5400 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5401 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005402 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5403
5404 getTargetStreamer().emitDirectiveSetMips0();
5405 return false;
5406}
5407
Toma Tabacu85618b32014-08-19 14:22:52 +00005408bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005409 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005410 Parser.Lex();
5411 if (getLexer().isNot(AsmToken::Equal))
5412 return reportParseError("unexpected token, expected equals sign");
5413
5414 Parser.Lex();
5415 StringRef Arch;
5416 if (Parser.parseIdentifier(Arch))
5417 return reportParseError("expected arch identifier");
5418
5419 StringRef ArchFeatureName =
5420 StringSwitch<StringRef>(Arch)
5421 .Case("mips1", "mips1")
5422 .Case("mips2", "mips2")
5423 .Case("mips3", "mips3")
5424 .Case("mips4", "mips4")
5425 .Case("mips5", "mips5")
5426 .Case("mips32", "mips32")
5427 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005428 .Case("mips32r3", "mips32r3")
5429 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005430 .Case("mips32r6", "mips32r6")
5431 .Case("mips64", "mips64")
5432 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005433 .Case("mips64r3", "mips64r3")
5434 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005435 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005436 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005437 .Case("r4000", "mips3") // This is an implementation of Mips3.
5438 .Default("");
5439
5440 if (ArchFeatureName.empty())
5441 return reportParseError("unsupported architecture");
5442
5443 selectArch(ArchFeatureName);
5444 getTargetStreamer().emitDirectiveSetArch(Arch);
5445 return false;
5446}
5447
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005448bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005449 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005450 Parser.Lex();
5451 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005452 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005453
Matheus Almeida2852af82014-04-22 10:15:54 +00005454 switch (Feature) {
5455 default:
5456 llvm_unreachable("Unimplemented feature");
5457 case Mips::FeatureDSP:
5458 setFeatureBits(Mips::FeatureDSP, "dsp");
5459 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005460 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005461 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00005462 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00005463 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005464 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005465 case Mips::FeatureMips1:
5466 selectArch("mips1");
5467 getTargetStreamer().emitDirectiveSetMips1();
5468 break;
5469 case Mips::FeatureMips2:
5470 selectArch("mips2");
5471 getTargetStreamer().emitDirectiveSetMips2();
5472 break;
5473 case Mips::FeatureMips3:
5474 selectArch("mips3");
5475 getTargetStreamer().emitDirectiveSetMips3();
5476 break;
5477 case Mips::FeatureMips4:
5478 selectArch("mips4");
5479 getTargetStreamer().emitDirectiveSetMips4();
5480 break;
5481 case Mips::FeatureMips5:
5482 selectArch("mips5");
5483 getTargetStreamer().emitDirectiveSetMips5();
5484 break;
5485 case Mips::FeatureMips32:
5486 selectArch("mips32");
5487 getTargetStreamer().emitDirectiveSetMips32();
5488 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005489 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005490 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005491 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005492 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005493 case Mips::FeatureMips32r3:
5494 selectArch("mips32r3");
5495 getTargetStreamer().emitDirectiveSetMips32R3();
5496 break;
5497 case Mips::FeatureMips32r5:
5498 selectArch("mips32r5");
5499 getTargetStreamer().emitDirectiveSetMips32R5();
5500 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005501 case Mips::FeatureMips32r6:
5502 selectArch("mips32r6");
5503 getTargetStreamer().emitDirectiveSetMips32R6();
5504 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005505 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005506 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005507 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005508 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005509 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005510 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005511 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005512 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005513 case Mips::FeatureMips64r3:
5514 selectArch("mips64r3");
5515 getTargetStreamer().emitDirectiveSetMips64R3();
5516 break;
5517 case Mips::FeatureMips64r5:
5518 selectArch("mips64r5");
5519 getTargetStreamer().emitDirectiveSetMips64R5();
5520 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005521 case Mips::FeatureMips64r6:
5522 selectArch("mips64r6");
5523 getTargetStreamer().emitDirectiveSetMips64R6();
5524 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005525 }
5526 return false;
5527}
5528
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005529bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005530 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005531 if (getLexer().isNot(AsmToken::Comma)) {
5532 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005533 return Error(Loc, ErrorStr);
5534 }
5535
Matheus Almeida2852af82014-04-22 10:15:54 +00005536 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005537 return true;
5538}
5539
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005540// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5541// In this class, it is only used for .cprestore.
5542// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5543// MipsTargetELFStreamer and MipsAsmParser.
5544bool MipsAsmParser::isPicAndNotNxxAbi() {
5545 return inPicMode() && !(isABI_N32() || isABI_N64());
5546}
5547
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005548bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005549 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005550 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005551
Toma Tabacudde4c462014-11-06 10:02:45 +00005552 if (inMips16Mode()) {
5553 reportParseError(".cpload is not supported in Mips16 mode");
5554 return false;
5555 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005556
David Blaikie960ea3f2014-06-08 16:18:35 +00005557 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005558 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005559 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5560 reportParseError("expected register containing function address");
5561 return false;
5562 }
5563
David Blaikie960ea3f2014-06-08 16:18:35 +00005564 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5565 if (!RegOpnd.isGPRAsmReg()) {
5566 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005567 return false;
5568 }
5569
Toma Tabacudde4c462014-11-06 10:02:45 +00005570 // If this is not the end of the statement, report an error.
5571 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5572 reportParseError("unexpected token, expected end of statement");
5573 return false;
5574 }
5575
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005576 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005577 return false;
5578}
5579
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005580bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5581 MCAsmParser &Parser = getParser();
5582
5583 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5584 // is used in non-PIC mode.
5585
5586 if (inMips16Mode()) {
5587 reportParseError(".cprestore is not supported in Mips16 mode");
5588 return false;
5589 }
5590
5591 // Get the stack offset value.
5592 const MCExpr *StackOffset;
5593 int64_t StackOffsetVal;
5594 if (Parser.parseExpression(StackOffset)) {
5595 reportParseError("expected stack offset value");
5596 return false;
5597 }
5598
5599 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5600 reportParseError("stack offset is not an absolute expression");
5601 return false;
5602 }
5603
5604 if (StackOffsetVal < 0) {
5605 Warning(Loc, ".cprestore with negative stack offset has no effect");
5606 IsCpRestoreSet = false;
5607 } else {
5608 IsCpRestoreSet = true;
5609 CpRestoreOffset = StackOffsetVal;
5610 }
5611
5612 // If this is not the end of the statement, report an error.
5613 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5614 reportParseError("unexpected token, expected end of statement");
5615 return false;
5616 }
5617
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005618 if (!getTargetStreamer().emitDirectiveCpRestore(
5619 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005620 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005621 Parser.Lex(); // Consume the EndOfStatement.
5622 return false;
5623}
5624
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005625bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005626 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005627 unsigned FuncReg;
5628 unsigned Save;
5629 bool SaveIsReg = true;
5630
Matheus Almeida7e815762014-06-18 13:08:59 +00005631 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005632 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005633 if (ResTy == MatchOperand_NoMatch) {
5634 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005635 return false;
5636 }
5637
5638 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5639 if (!FuncRegOpnd.isGPRAsmReg()) {
5640 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005641 return false;
5642 }
5643
5644 FuncReg = FuncRegOpnd.getGPR32Reg();
5645 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005646
Toma Tabacu65f10572014-09-16 15:00:52 +00005647 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005648 return true;
5649
Toma Tabacu13964452014-09-04 13:23:44 +00005650 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005651 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005652 const MCExpr *OffsetExpr;
5653 int64_t OffsetVal;
5654 SMLoc ExprLoc = getLexer().getLoc();
5655
5656 if (Parser.parseExpression(OffsetExpr) ||
5657 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5658 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005659 return false;
5660 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005661
5662 Save = OffsetVal;
5663 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005664 } else {
5665 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5666 if (!SaveOpnd.isGPRAsmReg()) {
5667 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005668 return false;
5669 }
5670 Save = SaveOpnd.getGPR32Reg();
5671 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005672
Toma Tabacu65f10572014-09-16 15:00:52 +00005673 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005674 return true;
5675
Toma Tabacu8874eac2015-02-18 13:46:53 +00005676 const MCExpr *Expr;
5677 if (Parser.parseExpression(Expr)) {
5678 reportParseError("expected expression");
5679 return false;
5680 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005681
Toma Tabacu8874eac2015-02-18 13:46:53 +00005682 if (Expr->getKind() != MCExpr::SymbolRef) {
5683 reportParseError("expected symbol");
5684 return false;
5685 }
5686 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5687
Daniel Sandersf173dda2015-09-22 10:50:09 +00005688 CpSaveLocation = Save;
5689 CpSaveLocationIsRegister = SaveIsReg;
5690
Toma Tabacu8874eac2015-02-18 13:46:53 +00005691 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5692 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005693 return false;
5694}
5695
Daniel Sandersf173dda2015-09-22 10:50:09 +00005696bool MipsAsmParser::parseDirectiveCPReturn() {
5697 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5698 CpSaveLocationIsRegister);
5699 return false;
5700}
5701
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005702bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005703 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005704 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5705 const AsmToken &Tok = Parser.getTok();
5706
5707 if (Tok.getString() == "2008") {
5708 Parser.Lex();
5709 getTargetStreamer().emitDirectiveNaN2008();
5710 return false;
5711 } else if (Tok.getString() == "legacy") {
5712 Parser.Lex();
5713 getTargetStreamer().emitDirectiveNaNLegacy();
5714 return false;
5715 }
5716 }
5717 // If we don't recognize the option passed to the .nan
5718 // directive (e.g. no option or unknown option), emit an error.
5719 reportParseError("invalid option in .nan directive");
5720 return false;
5721}
5722
Jack Carter0b744b32012-10-04 02:29:46 +00005723bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005724 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005725 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005726 const AsmToken &Tok = Parser.getTok();
5727
5728 if (Tok.getString() == "noat") {
5729 return parseSetNoAtDirective();
5730 } else if (Tok.getString() == "at") {
5731 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005732 } else if (Tok.getString() == "arch") {
5733 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005734 } else if (Tok.getString() == "fp") {
5735 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005736 } else if (Tok.getString() == "oddspreg") {
5737 return parseSetOddSPRegDirective();
5738 } else if (Tok.getString() == "nooddspreg") {
5739 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005740 } else if (Tok.getString() == "pop") {
5741 return parseSetPopDirective();
5742 } else if (Tok.getString() == "push") {
5743 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005744 } else if (Tok.getString() == "reorder") {
5745 return parseSetReorderDirective();
5746 } else if (Tok.getString() == "noreorder") {
5747 return parseSetNoReorderDirective();
5748 } else if (Tok.getString() == "macro") {
5749 return parseSetMacroDirective();
5750 } else if (Tok.getString() == "nomacro") {
5751 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005752 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005753 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005754 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005755 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005756 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00005757 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005758 getTargetStreamer().emitDirectiveSetNoMicroMips();
5759 Parser.eatToEndOfStatement();
5760 return false;
5761 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005762 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005763 } else if (Tok.getString() == "mips0") {
5764 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005765 } else if (Tok.getString() == "mips1") {
5766 return parseSetFeature(Mips::FeatureMips1);
5767 } else if (Tok.getString() == "mips2") {
5768 return parseSetFeature(Mips::FeatureMips2);
5769 } else if (Tok.getString() == "mips3") {
5770 return parseSetFeature(Mips::FeatureMips3);
5771 } else if (Tok.getString() == "mips4") {
5772 return parseSetFeature(Mips::FeatureMips4);
5773 } else if (Tok.getString() == "mips5") {
5774 return parseSetFeature(Mips::FeatureMips5);
5775 } else if (Tok.getString() == "mips32") {
5776 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005777 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005778 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005779 } else if (Tok.getString() == "mips32r3") {
5780 return parseSetFeature(Mips::FeatureMips32r3);
5781 } else if (Tok.getString() == "mips32r5") {
5782 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005783 } else if (Tok.getString() == "mips32r6") {
5784 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005785 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005786 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005787 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005788 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005789 } else if (Tok.getString() == "mips64r3") {
5790 return parseSetFeature(Mips::FeatureMips64r3);
5791 } else if (Tok.getString() == "mips64r5") {
5792 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005793 } else if (Tok.getString() == "mips64r6") {
5794 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005795 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005796 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005797 } else if (Tok.getString() == "nodsp") {
5798 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005799 } else if (Tok.getString() == "msa") {
5800 return parseSetMsaDirective();
5801 } else if (Tok.getString() == "nomsa") {
5802 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005803 } else if (Tok.getString() == "softfloat") {
5804 return parseSetSoftFloatDirective();
5805 } else if (Tok.getString() == "hardfloat") {
5806 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005807 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005808 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005809 parseSetAssignment();
5810 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005811 }
Jack Carter07c818d2013-01-25 01:31:34 +00005812
Jack Carter0b744b32012-10-04 02:29:46 +00005813 return true;
5814}
5815
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005816/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005817/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005818bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005819 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005820 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5821 for (;;) {
5822 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005823 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005824 return true;
5825
5826 getParser().getStreamer().EmitValue(Value, Size);
5827
5828 if (getLexer().is(AsmToken::EndOfStatement))
5829 break;
5830
Jack Carter07c818d2013-01-25 01:31:34 +00005831 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005832 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005833 Parser.Lex();
5834 }
5835 }
5836
5837 Parser.Lex();
5838 return false;
5839}
5840
Vladimir Medic4c299852013-11-06 11:27:05 +00005841/// parseDirectiveGpWord
5842/// ::= .gpword local_sym
5843bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005844 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005845 const MCExpr *Value;
5846 // EmitGPRel32Value requires an expression, so we are using base class
5847 // method to evaluate the expression.
5848 if (getParser().parseExpression(Value))
5849 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005850 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005851
Vladimir Medice10c1122013-11-13 13:18:04 +00005852 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005853 return Error(getLexer().getLoc(),
5854 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005855 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005856 return false;
5857}
5858
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005859/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005860/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005861bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005862 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005863 const MCExpr *Value;
5864 // EmitGPRel64Value requires an expression, so we are using base class
5865 // method to evaluate the expression.
5866 if (getParser().parseExpression(Value))
5867 return true;
5868 getParser().getStreamer().EmitGPRel64Value(Value);
5869
5870 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00005871 return Error(getLexer().getLoc(),
5872 "unexpected token, expected end of statement");
5873 Parser.Lex(); // Eat EndOfStatement token.
5874 return false;
5875}
5876
5877/// parseDirectiveDtpRelWord
5878/// ::= .dtprelword tls_sym
5879bool MipsAsmParser::parseDirectiveDtpRelWord() {
5880 MCAsmParser &Parser = getParser();
5881 const MCExpr *Value;
5882 // EmitDTPRel32Value requires an expression, so we are using base class
5883 // method to evaluate the expression.
5884 if (getParser().parseExpression(Value))
5885 return true;
5886 getParser().getStreamer().EmitDTPRel32Value(Value);
5887
5888 if (getLexer().isNot(AsmToken::EndOfStatement))
5889 return Error(getLexer().getLoc(),
5890 "unexpected token, expected end of statement");
5891 Parser.Lex(); // Eat EndOfStatement token.
5892 return false;
5893}
5894
5895/// parseDirectiveDtpRelDWord
5896/// ::= .dtpreldword tls_sym
5897bool MipsAsmParser::parseDirectiveDtpRelDWord() {
5898 MCAsmParser &Parser = getParser();
5899 const MCExpr *Value;
5900 // EmitDTPRel64Value requires an expression, so we are using base class
5901 // method to evaluate the expression.
5902 if (getParser().parseExpression(Value))
5903 return true;
5904 getParser().getStreamer().EmitDTPRel64Value(Value);
5905
5906 if (getLexer().isNot(AsmToken::EndOfStatement))
5907 return Error(getLexer().getLoc(),
5908 "unexpected token, expected end of statement");
5909 Parser.Lex(); // Eat EndOfStatement token.
5910 return false;
5911}
5912
5913/// parseDirectiveTpRelWord
5914/// ::= .tprelword tls_sym
5915bool MipsAsmParser::parseDirectiveTpRelWord() {
5916 MCAsmParser &Parser = getParser();
5917 const MCExpr *Value;
5918 // EmitTPRel32Value requires an expression, so we are using base class
5919 // method to evaluate the expression.
5920 if (getParser().parseExpression(Value))
5921 return true;
5922 getParser().getStreamer().EmitTPRel32Value(Value);
5923
5924 if (getLexer().isNot(AsmToken::EndOfStatement))
5925 return Error(getLexer().getLoc(),
5926 "unexpected token, expected end of statement");
5927 Parser.Lex(); // Eat EndOfStatement token.
5928 return false;
5929}
5930
5931/// parseDirectiveTpRelDWord
5932/// ::= .tpreldword tls_sym
5933bool MipsAsmParser::parseDirectiveTpRelDWord() {
5934 MCAsmParser &Parser = getParser();
5935 const MCExpr *Value;
5936 // EmitTPRel64Value requires an expression, so we are using base class
5937 // method to evaluate the expression.
5938 if (getParser().parseExpression(Value))
5939 return true;
5940 getParser().getStreamer().EmitTPRel64Value(Value);
5941
5942 if (getLexer().isNot(AsmToken::EndOfStatement))
5943 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005944 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005945 Parser.Lex(); // Eat EndOfStatement token.
5946 return false;
5947}
5948
Jack Carter0cd3c192014-01-06 23:27:31 +00005949bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005950 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005951 // Get the option token.
5952 AsmToken Tok = Parser.getTok();
5953 // At the moment only identifiers are supported.
5954 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00005955 return Error(Parser.getTok().getLoc(),
5956 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005957 }
5958
5959 StringRef Option = Tok.getIdentifier();
5960
5961 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005962 // MipsAsmParser needs to know if the current PIC mode changes.
5963 IsPicEnabled = false;
5964
Jack Carter0cd3c192014-01-06 23:27:31 +00005965 getTargetStreamer().emitDirectiveOptionPic0();
5966 Parser.Lex();
5967 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00005968 return Error(Parser.getTok().getLoc(),
5969 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005970 }
5971 return false;
5972 }
5973
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005974 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005975 // MipsAsmParser needs to know if the current PIC mode changes.
5976 IsPicEnabled = true;
5977
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005978 getTargetStreamer().emitDirectiveOptionPic2();
5979 Parser.Lex();
5980 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00005981 return Error(Parser.getTok().getLoc(),
5982 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005983 }
5984 return false;
5985 }
5986
Jack Carter0cd3c192014-01-06 23:27:31 +00005987 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005988 Warning(Parser.getTok().getLoc(),
5989 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005990 Parser.eatToEndOfStatement();
5991 return false;
5992}
5993
Toma Tabacu9ca50962015-04-16 09:53:47 +00005994/// parseInsnDirective
5995/// ::= .insn
5996bool MipsAsmParser::parseInsnDirective() {
5997 // If this is not the end of the statement, report an error.
5998 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5999 reportParseError("unexpected token, expected end of statement");
6000 return false;
6001 }
6002
6003 // The actual label marking happens in
6004 // MipsELFStreamer::createPendingLabelRelocs().
6005 getTargetStreamer().emitDirectiveInsn();
6006
6007 getParser().Lex(); // Eat EndOfStatement token.
6008 return false;
6009}
6010
Simon Atanasyanbe186202016-02-11 06:45:54 +00006011/// parseSSectionDirective
6012/// ::= .sbss
6013/// ::= .sdata
6014bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
6015 // If this is not the end of the statement, report an error.
6016 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6017 reportParseError("unexpected token, expected end of statement");
6018 return false;
6019 }
6020
6021 MCSection *ELFSection = getContext().getELFSection(
6022 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
6023 getParser().getStreamer().SwitchSection(ELFSection);
6024
6025 getParser().Lex(); // Eat EndOfStatement token.
6026 return false;
6027}
6028
Daniel Sanders7e527422014-07-10 13:38:23 +00006029/// parseDirectiveModule
6030/// ::= .module oddspreg
6031/// ::= .module nooddspreg
6032/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00006033/// ::= .module softfloat
6034/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006035bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006036 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006037 MCAsmLexer &Lexer = getLexer();
6038 SMLoc L = Lexer.getLoc();
6039
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006040 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006041 // TODO : get a better message.
6042 reportParseError(".module directive must appear before any code");
6043 return false;
6044 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006045
Toma Tabacuc405c822015-01-23 10:40:19 +00006046 StringRef Option;
6047 if (Parser.parseIdentifier(Option)) {
6048 reportParseError("expected .module option identifier");
6049 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006050 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006051
Toma Tabacuc405c822015-01-23 10:40:19 +00006052 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006053 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006054
Toma Tabacu3c499582015-06-25 10:56:57 +00006055 // Synchronize the abiflags information with the FeatureBits information we
6056 // changed above.
6057 getTargetStreamer().updateABIInfo(*this);
6058
6059 // If printing assembly, use the recently updated abiflags information.
6060 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6061 // emitted at the end).
6062 getTargetStreamer().emitDirectiveModuleOddSPReg();
6063
Toma Tabacuc405c822015-01-23 10:40:19 +00006064 // If this is not the end of the statement, report an error.
6065 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6066 reportParseError("unexpected token, expected end of statement");
6067 return false;
6068 }
6069
6070 return false; // parseDirectiveModule has finished successfully.
6071 } else if (Option == "nooddspreg") {
6072 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006073 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00006074 }
6075
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006076 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006077
Toma Tabacu3c499582015-06-25 10:56:57 +00006078 // Synchronize the abiflags information with the FeatureBits information we
6079 // changed above.
6080 getTargetStreamer().updateABIInfo(*this);
6081
6082 // If printing assembly, use the recently updated abiflags information.
6083 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6084 // emitted at the end).
6085 getTargetStreamer().emitDirectiveModuleOddSPReg();
6086
Toma Tabacuc405c822015-01-23 10:40:19 +00006087 // If this is not the end of the statement, report an error.
6088 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6089 reportParseError("unexpected token, expected end of statement");
6090 return false;
6091 }
6092
6093 return false; // parseDirectiveModule has finished successfully.
6094 } else if (Option == "fp") {
6095 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00006096 } else if (Option == "softfloat") {
6097 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6098
6099 // Synchronize the ABI Flags information with the FeatureBits information we
6100 // updated above.
6101 getTargetStreamer().updateABIInfo(*this);
6102
6103 // If printing assembly, use the recently updated ABI Flags information.
6104 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6105 // emitted later).
6106 getTargetStreamer().emitDirectiveModuleSoftFloat();
6107
6108 // If this is not the end of the statement, report an error.
6109 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6110 reportParseError("unexpected token, expected end of statement");
6111 return false;
6112 }
6113
6114 return false; // parseDirectiveModule has finished successfully.
6115 } else if (Option == "hardfloat") {
6116 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6117
6118 // Synchronize the ABI Flags information with the FeatureBits information we
6119 // updated above.
6120 getTargetStreamer().updateABIInfo(*this);
6121
6122 // If printing assembly, use the recently updated ABI Flags information.
6123 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6124 // emitted later).
6125 getTargetStreamer().emitDirectiveModuleHardFloat();
6126
6127 // If this is not the end of the statement, report an error.
6128 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6129 reportParseError("unexpected token, expected end of statement");
6130 return false;
6131 }
6132
6133 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00006134 } else {
6135 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
6136 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006137}
6138
6139/// parseDirectiveModuleFP
6140/// ::= =32
6141/// ::= =xx
6142/// ::= =64
6143bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006144 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006145 MCAsmLexer &Lexer = getLexer();
6146
6147 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006148 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006149 return false;
6150 }
6151 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006152
Daniel Sanders7e527422014-07-10 13:38:23 +00006153 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006154 if (!parseFpABIValue(FpABI, ".module"))
6155 return false;
6156
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006157 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006158 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006159 return false;
6160 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006161
Toma Tabacua64e5402015-06-25 12:44:38 +00006162 // Synchronize the abiflags information with the FeatureBits information we
6163 // changed above.
6164 getTargetStreamer().updateABIInfo(*this);
6165
6166 // If printing assembly, use the recently updated abiflags information.
6167 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6168 // emitted at the end).
6169 getTargetStreamer().emitDirectiveModuleFP();
6170
Daniel Sanders7e527422014-07-10 13:38:23 +00006171 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006172 return false;
6173}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006174
Daniel Sanders7e527422014-07-10 13:38:23 +00006175bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006176 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006177 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006178 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006179 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006180
6181 if (Lexer.is(AsmToken::Identifier)) {
6182 StringRef Value = Parser.getTok().getString();
6183 Parser.Lex();
6184
6185 if (Value != "xx") {
6186 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6187 return false;
6188 }
6189
6190 if (!isABI_O32()) {
6191 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
6192 return false;
6193 }
6194
Daniel Sanders7e527422014-07-10 13:38:23 +00006195 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006196 if (ModuleLevelOptions) {
6197 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6198 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6199 } else {
6200 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6201 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6202 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006203 return true;
6204 }
6205
6206 if (Lexer.is(AsmToken::Integer)) {
6207 unsigned Value = Parser.getTok().getIntVal();
6208 Parser.Lex();
6209
6210 if (Value != 32 && Value != 64) {
6211 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6212 return false;
6213 }
6214
6215 if (Value == 32) {
6216 if (!isABI_O32()) {
6217 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6218 return false;
6219 }
6220
Daniel Sanders7e527422014-07-10 13:38:23 +00006221 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006222 if (ModuleLevelOptions) {
6223 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6224 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6225 } else {
6226 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6227 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6228 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006229 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006230 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006231 if (ModuleLevelOptions) {
6232 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6233 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6234 } else {
6235 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6236 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6237 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006238 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006239
Daniel Sanders7e527422014-07-10 13:38:23 +00006240 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006241 }
6242
6243 return false;
6244}
6245
Jack Carter0b744b32012-10-04 02:29:46 +00006246bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006247 // This returns false if this function recognizes the directive
6248 // regardless of whether it is successfully handles or reports an
6249 // error. Otherwise it returns true to give the generic parser a
6250 // chance at recognizing it.
6251
Rafael Espindola961d4692014-11-11 05:18:41 +00006252 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006253 StringRef IDVal = DirectiveID.getString();
6254
Nirav Dave996fc132016-05-05 14:15:46 +00006255 if (IDVal == ".cpload") {
6256 parseDirectiveCpLoad(DirectiveID.getLoc());
6257 return false;
6258 }
6259 if (IDVal == ".cprestore") {
6260 parseDirectiveCpRestore(DirectiveID.getLoc());
6261 return false;
6262 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006263 if (IDVal == ".dword") {
6264 parseDataDirective(8, DirectiveID.getLoc());
6265 return false;
6266 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006267 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006268 StringRef SymbolName;
6269
6270 if (Parser.parseIdentifier(SymbolName)) {
6271 reportParseError("expected identifier after .ent");
6272 return false;
6273 }
6274
6275 // There's an undocumented extension that allows an integer to
6276 // follow the name of the procedure which AFAICS is ignored by GAS.
6277 // Example: .ent foo,2
6278 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6279 if (getLexer().isNot(AsmToken::Comma)) {
6280 // Even though we accept this undocumented extension for compatibility
6281 // reasons, the additional integer argument does not actually change
6282 // the behaviour of the '.ent' directive, so we would like to discourage
6283 // its use. We do this by not referring to the extended version in
6284 // error messages which are not directly related to its use.
6285 reportParseError("unexpected token, expected end of statement");
6286 return false;
6287 }
6288 Parser.Lex(); // Eat the comma.
6289 const MCExpr *DummyNumber;
6290 int64_t DummyNumberVal;
6291 // If the user was explicitly trying to use the extended version,
6292 // we still give helpful extension-related error messages.
6293 if (Parser.parseExpression(DummyNumber)) {
6294 reportParseError("expected number after comma");
6295 return false;
6296 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006297 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006298 reportParseError("expected an absolute expression after comma");
6299 return false;
6300 }
6301 }
6302
6303 // If this is not the end of the statement, report an error.
6304 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6305 reportParseError("unexpected token, expected end of statement");
6306 return false;
6307 }
6308
Jim Grosbach6f482002015-05-18 18:43:14 +00006309 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006310
6311 getTargetStreamer().emitDirectiveEnt(*Sym);
6312 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006313 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006314 return false;
6315 }
6316
Jack Carter07c818d2013-01-25 01:31:34 +00006317 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006318 StringRef SymbolName;
6319
6320 if (Parser.parseIdentifier(SymbolName)) {
6321 reportParseError("expected identifier after .end");
6322 return false;
6323 }
6324
6325 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6326 reportParseError("unexpected token, expected end of statement");
6327 return false;
6328 }
6329
6330 if (CurrentFn == nullptr) {
6331 reportParseError(".end used without .ent");
6332 return false;
6333 }
6334
6335 if ((SymbolName != CurrentFn->getName())) {
6336 reportParseError(".end symbol does not match .ent symbol");
6337 return false;
6338 }
6339
6340 getTargetStreamer().emitDirectiveEnd(SymbolName);
6341 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006342 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006343 return false;
6344 }
6345
Jack Carter07c818d2013-01-25 01:31:34 +00006346 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006347 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6348 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006349 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006350 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6351 reportParseError("expected stack register");
6352 return false;
6353 }
6354
6355 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6356 if (!StackRegOpnd.isGPRAsmReg()) {
6357 reportParseError(StackRegOpnd.getStartLoc(),
6358 "expected general purpose register");
6359 return false;
6360 }
6361 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6362
6363 if (Parser.getTok().is(AsmToken::Comma))
6364 Parser.Lex();
6365 else {
6366 reportParseError("unexpected token, expected comma");
6367 return false;
6368 }
6369
6370 // Parse the frame size.
6371 const MCExpr *FrameSize;
6372 int64_t FrameSizeVal;
6373
6374 if (Parser.parseExpression(FrameSize)) {
6375 reportParseError("expected frame size value");
6376 return false;
6377 }
6378
Jim Grosbach13760bd2015-05-30 01:25:56 +00006379 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006380 reportParseError("frame size not an absolute expression");
6381 return false;
6382 }
6383
6384 if (Parser.getTok().is(AsmToken::Comma))
6385 Parser.Lex();
6386 else {
6387 reportParseError("unexpected token, expected comma");
6388 return false;
6389 }
6390
6391 // Parse the return register.
6392 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006393 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006394 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6395 reportParseError("expected return register");
6396 return false;
6397 }
6398
6399 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6400 if (!ReturnRegOpnd.isGPRAsmReg()) {
6401 reportParseError(ReturnRegOpnd.getStartLoc(),
6402 "expected general purpose register");
6403 return false;
6404 }
6405
6406 // If this is not the end of the statement, report an error.
6407 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6408 reportParseError("unexpected token, expected end of statement");
6409 return false;
6410 }
6411
6412 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6413 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006414 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006415 return false;
6416 }
6417
Jack Carter07c818d2013-01-25 01:31:34 +00006418 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006419 parseDirectiveSet();
6420 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006421 }
6422
Daniel Sandersd97a6342014-08-13 10:07:34 +00006423 if (IDVal == ".mask" || IDVal == ".fmask") {
6424 // .mask bitmask, frame_offset
6425 // bitmask: One bit for each register used.
6426 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6427 // first register is expected to be saved.
6428 // Examples:
6429 // .mask 0x80000000, -4
6430 // .fmask 0x80000000, -4
6431 //
Jack Carterbe332172012-09-07 00:48:02 +00006432
Daniel Sandersd97a6342014-08-13 10:07:34 +00006433 // Parse the bitmask
6434 const MCExpr *BitMask;
6435 int64_t BitMaskVal;
6436
6437 if (Parser.parseExpression(BitMask)) {
6438 reportParseError("expected bitmask value");
6439 return false;
6440 }
6441
Jim Grosbach13760bd2015-05-30 01:25:56 +00006442 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006443 reportParseError("bitmask not an absolute expression");
6444 return false;
6445 }
6446
6447 if (Parser.getTok().is(AsmToken::Comma))
6448 Parser.Lex();
6449 else {
6450 reportParseError("unexpected token, expected comma");
6451 return false;
6452 }
6453
6454 // Parse the frame_offset
6455 const MCExpr *FrameOffset;
6456 int64_t FrameOffsetVal;
6457
6458 if (Parser.parseExpression(FrameOffset)) {
6459 reportParseError("expected frame offset value");
6460 return false;
6461 }
6462
Jim Grosbach13760bd2015-05-30 01:25:56 +00006463 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006464 reportParseError("frame offset not an absolute expression");
6465 return false;
6466 }
6467
6468 // If this is not the end of the statement, report an error.
6469 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6470 reportParseError("unexpected token, expected end of statement");
6471 return false;
6472 }
6473
6474 if (IDVal == ".mask")
6475 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6476 else
6477 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006478 return false;
6479 }
6480
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006481 if (IDVal == ".nan")
6482 return parseDirectiveNaN();
6483
Jack Carter07c818d2013-01-25 01:31:34 +00006484 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006485 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006486 return false;
6487 }
6488
Rafael Espindolab59fb732014-03-28 18:50:26 +00006489 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006490 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006491 return false;
6492 }
6493
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006494 if (IDVal == ".dtprelword") {
6495 parseDirectiveDtpRelWord();
6496 return false;
6497 }
6498
6499 if (IDVal == ".dtpreldword") {
6500 parseDirectiveDtpRelDWord();
6501 return false;
6502 }
6503
6504 if (IDVal == ".tprelword") {
6505 parseDirectiveTpRelWord();
6506 return false;
6507 }
6508
6509 if (IDVal == ".tpreldword") {
6510 parseDirectiveTpRelDWord();
6511 return false;
6512 }
6513
Jack Carter07c818d2013-01-25 01:31:34 +00006514 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006515 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006516 return false;
6517 }
6518
Scott Egertond1aeb052016-02-15 16:11:51 +00006519 if (IDVal == ".hword") {
6520 parseDataDirective(2, DirectiveID.getLoc());
6521 return false;
6522 }
6523
Nirav Dave996fc132016-05-05 14:15:46 +00006524 if (IDVal == ".option") {
6525 parseDirectiveOption();
6526 return false;
6527 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006528
6529 if (IDVal == ".abicalls") {
6530 getTargetStreamer().emitDirectiveAbiCalls();
6531 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006532 Error(Parser.getTok().getLoc(),
6533 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006534 }
6535 return false;
6536 }
6537
Nirav Dave996fc132016-05-05 14:15:46 +00006538 if (IDVal == ".cpsetup") {
6539 parseDirectiveCPSetup();
6540 return false;
6541 }
6542 if (IDVal == ".cpreturn") {
6543 parseDirectiveCPReturn();
6544 return false;
6545 }
6546 if (IDVal == ".module") {
6547 parseDirectiveModule();
6548 return false;
6549 }
6550 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6551 parseInternalDirectiveReallowModule();
6552 return false;
6553 }
6554 if (IDVal == ".insn") {
6555 parseInsnDirective();
6556 return false;
6557 }
6558 if (IDVal == ".sbss") {
6559 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6560 return false;
6561 }
6562 if (IDVal == ".sdata") {
6563 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6564 return false;
6565 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006566
Rafael Espindola870c4e92012-01-11 03:56:41 +00006567 return true;
6568}
6569
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006570bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6571 // If this is not the end of the statement, report an error.
6572 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6573 reportParseError("unexpected token, expected end of statement");
6574 return false;
6575 }
6576
6577 getTargetStreamer().reallowModuleDirective();
6578
6579 getParser().Lex(); // Eat EndOfStatement token.
6580 return false;
6581}
6582
Rafael Espindola870c4e92012-01-11 03:56:41 +00006583extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00006584 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
6585 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
6586 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
6587 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00006588}
Jack Carterb4dbc172012-09-05 23:34:03 +00006589
6590#define GET_REGISTER_MATCHER
6591#define GET_MATCHER_IMPLEMENTATION
6592#include "MipsGenAsmMatcher.inc"