blob: 70a5e50748b5a232c84988f70deb085735dd6bf2 [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 }
Simon Dardis858915f2016-10-18 15:17:17 +00004556 MCBinaryExpr::Opcode Opcode;
4557 // GAS and LLVM treat comparison operators different. GAS will generate -1
4558 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
4559 // highly unlikely to be found in a memory offset expression, we don't
4560 // handle them.
4561 switch (Tok.getKind()) {
4562 case AsmToken::Plus:
4563 Opcode = MCBinaryExpr::Add;
4564 Parser.Lex();
4565 break;
4566 case AsmToken::Minus:
4567 Opcode = MCBinaryExpr::Sub;
4568 Parser.Lex();
4569 break;
4570 case AsmToken::Star:
4571 Opcode = MCBinaryExpr::Mul;
4572 Parser.Lex();
4573 break;
4574 case AsmToken::Pipe:
4575 Opcode = MCBinaryExpr::Or;
4576 Parser.Lex();
4577 break;
4578 case AsmToken::Amp:
4579 Opcode = MCBinaryExpr::And;
4580 Parser.Lex();
4581 break;
4582 case AsmToken::LessLess:
4583 Opcode = MCBinaryExpr::Shl;
4584 Parser.Lex();
4585 break;
4586 case AsmToken::GreaterGreater:
4587 Opcode = MCBinaryExpr::LShr;
4588 Parser.Lex();
4589 break;
4590 case AsmToken::Caret:
4591 Opcode = MCBinaryExpr::Xor;
4592 Parser.Lex();
4593 break;
4594 case AsmToken::Slash:
4595 Opcode = MCBinaryExpr::Div;
4596 Parser.Lex();
4597 break;
4598 case AsmToken::Percent:
4599 Opcode = MCBinaryExpr::Mod;
4600 Parser.Lex();
4601 break;
4602 default:
4603 Error(Parser.getTok().getLoc(), "'(' or expression expected");
4604 return MatchOperand_ParseFail;
4605 }
4606 const MCExpr * NextExpr;
4607 if (getParser().parseExpression(NextExpr))
4608 return MatchOperand_ParseFail;
4609 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004610 }
4611
Jack Carterd0bd6422013-04-18 00:41:53 +00004612 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004613 }
4614
Toma Tabacu13964452014-09-04 13:23:44 +00004615 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004616 if (Res != MatchOperand_Success)
4617 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004618
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004619 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004620 Error(Parser.getTok().getLoc(), "')' expected");
4621 return MatchOperand_ParseFail;
4622 }
4623
Jack Carter873c7242013-01-12 01:03:14 +00004624 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4625
Jack Carterd0bd6422013-04-18 00:41:53 +00004626 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004627
Craig Topper062a2ba2014-04-25 05:30:21 +00004628 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004629 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004630
Jack Carterd0bd6422013-04-18 00:41:53 +00004631 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004632 std::unique_ptr<MipsOperand> op(
4633 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004634 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004635 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004636 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004637 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004638 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4639 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004640 if (IdVal->evaluateAsAbsolute(Imm))
4641 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004642 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004643 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004644 getContext());
4645 }
4646
David Blaikie960ea3f2014-06-08 16:18:35 +00004647 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004648 return MatchOperand_Success;
4649}
4650
David Blaikie960ea3f2014-06-08 16:18:35 +00004651bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004652 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004653 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004654 if (Sym) {
4655 SMLoc S = Parser.getTok().getLoc();
4656 const MCExpr *Expr;
4657 if (Sym->isVariable())
4658 Expr = Sym->getVariableValue();
4659 else
4660 return false;
4661 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004662 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004663 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004664 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004665 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004666 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004667 if (ResTy == MatchOperand_Success) {
4668 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004669 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004670 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004671 llvm_unreachable("Should never ParseFail");
4672 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004673 }
Jack Carterd76b2372013-03-21 21:44:16 +00004674 }
4675 }
4676 return false;
4677}
Jack Carterd0bd6422013-04-18 00:41:53 +00004678
Jack Carter873c7242013-01-12 01:03:14 +00004679MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004680MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004681 StringRef Identifier,
4682 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004683 int Index = matchCPURegisterName(Identifier);
4684 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004685 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004686 Index, Identifier, getContext().getRegisterInfo(), S,
4687 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004688 return MatchOperand_Success;
4689 }
4690
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004691 Index = matchHWRegsRegisterName(Identifier);
4692 if (Index != -1) {
4693 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004694 Index, Identifier, getContext().getRegisterInfo(), S,
4695 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004696 return MatchOperand_Success;
4697 }
4698
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004699 Index = matchFPURegisterName(Identifier);
4700 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004701 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004702 Index, Identifier, getContext().getRegisterInfo(), S,
4703 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004704 return MatchOperand_Success;
4705 }
4706
4707 Index = matchFCCRegisterName(Identifier);
4708 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004709 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004710 Index, Identifier, getContext().getRegisterInfo(), S,
4711 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004712 return MatchOperand_Success;
4713 }
4714
4715 Index = matchACRegisterName(Identifier);
4716 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004717 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004718 Index, Identifier, getContext().getRegisterInfo(), S,
4719 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004720 return MatchOperand_Success;
4721 }
4722
4723 Index = matchMSA128RegisterName(Identifier);
4724 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004725 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004726 Index, Identifier, getContext().getRegisterInfo(), S,
4727 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004728 return MatchOperand_Success;
4729 }
4730
4731 Index = matchMSA128CtrlRegisterName(Identifier);
4732 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004733 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004734 Index, Identifier, getContext().getRegisterInfo(), S,
4735 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004736 return MatchOperand_Success;
4737 }
4738
4739 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004740}
4741
4742MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004743MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004744 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004745 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004746
4747 if (Token.is(AsmToken::Identifier)) {
4748 DEBUG(dbgs() << ".. identifier\n");
4749 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004750 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004751 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004752 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004753 } else if (Token.is(AsmToken::Integer)) {
4754 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004755 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004756 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
4757 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004758 return MatchOperand_Success;
4759 }
4760
4761 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4762
4763 return MatchOperand_NoMatch;
4764}
4765
David Blaikie960ea3f2014-06-08 16:18:35 +00004766MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004767MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004768 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004769 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004770
4771 auto Token = Parser.getTok();
4772
4773 SMLoc S = Token.getLoc();
4774
4775 if (Token.isNot(AsmToken::Dollar)) {
4776 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4777 if (Token.is(AsmToken::Identifier)) {
4778 if (searchSymbolAlias(Operands))
4779 return MatchOperand_Success;
4780 }
4781 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4782 return MatchOperand_NoMatch;
4783 }
4784 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004785
Toma Tabacu13964452014-09-04 13:23:44 +00004786 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004787 if (ResTy == MatchOperand_Success) {
4788 Parser.Lex(); // $
4789 Parser.Lex(); // identifier
4790 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004791 return ResTy;
4792}
4793
4794MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004795MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004796 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004797 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004798
4799 SMLoc S = getLexer().getLoc();
4800
Daniel Sanderscae9aee2016-08-08 09:33:14 +00004801 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004802 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00004803 if (ResTy != MatchOperand_NoMatch)
4804 return ResTy;
4805
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004806 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00004807 const MCExpr *Expr = nullptr;
4808 if (Parser.parseExpression(Expr)) {
4809 // We have no way of knowing if a symbol was consumed so we must ParseFail
4810 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004811 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004812 Operands.push_back(
4813 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004814 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004815}
4816
Vladimir Medic2b953d02013-10-01 09:48:56 +00004817MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004818MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004819 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004820 const MCExpr *IdVal;
4821 // If the first token is '$' we may have register operand.
4822 if (Parser.getTok().is(AsmToken::Dollar))
4823 return MatchOperand_NoMatch;
4824 SMLoc S = Parser.getTok().getLoc();
4825 if (getParser().parseExpression(IdVal))
4826 return MatchOperand_ParseFail;
4827 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004828 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004829 int64_t Val = MCE->getValue();
4830 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4831 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004832 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004833 return MatchOperand_Success;
4834}
4835
Matheus Almeida779c5932013-11-18 12:32:49 +00004836MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004837MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4838 MCAsmParser &Parser = getParser();
4839 SmallVector<unsigned, 10> Regs;
4840 unsigned RegNo;
4841 unsigned PrevReg = Mips::NoRegister;
4842 bool RegRange = false;
4843 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4844
4845 if (Parser.getTok().isNot(AsmToken::Dollar))
4846 return MatchOperand_ParseFail;
4847
4848 SMLoc S = Parser.getTok().getLoc();
4849 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4850 SMLoc E = getLexer().getLoc();
4851 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4852 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4853 if (RegRange) {
4854 // Remove last register operand because registers from register range
4855 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004856 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4857 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004858 Regs.push_back(RegNo);
4859 } else {
4860 unsigned TmpReg = PrevReg + 1;
4861 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004862 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4863 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4864 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004865 Error(E, "invalid register operand");
4866 return MatchOperand_ParseFail;
4867 }
4868
4869 PrevReg = TmpReg;
4870 Regs.push_back(TmpReg++);
4871 }
4872 }
4873
4874 RegRange = false;
4875 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004876 if ((PrevReg == Mips::NoRegister) &&
4877 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4878 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004879 Error(E, "$16 or $31 expected");
4880 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004881 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4882 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4883 !isGP64bit()) ||
4884 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4885 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4886 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004887 Error(E, "invalid register operand");
4888 return MatchOperand_ParseFail;
4889 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004890 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4891 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4892 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004893 Error(E, "consecutive register numbers expected");
4894 return MatchOperand_ParseFail;
4895 }
4896
4897 Regs.push_back(RegNo);
4898 }
4899
4900 if (Parser.getTok().is(AsmToken::Minus))
4901 RegRange = true;
4902
4903 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4904 !Parser.getTok().isNot(AsmToken::Comma)) {
4905 Error(E, "',' or '-' expected");
4906 return MatchOperand_ParseFail;
4907 }
4908
4909 Lex(); // Consume comma or minus
4910 if (Parser.getTok().isNot(AsmToken::Dollar))
4911 break;
4912
4913 PrevReg = RegNo;
4914 }
4915
4916 SMLoc E = Parser.getTok().getLoc();
4917 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4918 parseMemOperand(Operands);
4919 return MatchOperand_Success;
4920}
4921
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004922MipsAsmParser::OperandMatchResultTy
4923MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4924 MCAsmParser &Parser = getParser();
4925
4926 SMLoc S = Parser.getTok().getLoc();
4927 if (parseAnyRegister(Operands) != MatchOperand_Success)
4928 return MatchOperand_ParseFail;
4929
4930 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00004931 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00004932
Benjamin Kramer2b68d152016-05-09 10:31:17 +00004933 Operands.pop_back();
4934 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004935 return MatchOperand_Success;
4936}
4937
Zoran Jovanovic41688672015-02-10 16:36:20 +00004938MipsAsmParser::OperandMatchResultTy
4939MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4940 MCAsmParser &Parser = getParser();
4941 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4942 SmallVector<unsigned, 10> Regs;
4943
4944 if (Parser.getTok().isNot(AsmToken::Dollar))
4945 return MatchOperand_ParseFail;
4946
4947 SMLoc S = Parser.getTok().getLoc();
4948
4949 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4950 return MatchOperand_ParseFail;
4951
4952 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4953 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4954 Regs.push_back(RegNo);
4955
4956 SMLoc E = Parser.getTok().getLoc();
4957 if (Parser.getTok().isNot(AsmToken::Comma)) {
4958 Error(E, "',' expected");
4959 return MatchOperand_ParseFail;
4960 }
4961
4962 // Remove comma.
4963 Parser.Lex();
4964
4965 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4966 return MatchOperand_ParseFail;
4967
4968 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4969 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4970 Regs.push_back(RegNo);
4971
4972 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4973
4974 return MatchOperand_Success;
4975}
4976
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004977/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4978/// either this.
4979/// ::= '(', register, ')'
4980/// handle it before we iterate so we don't get tripped up by the lack of
4981/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004982bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004983 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004984 if (getLexer().is(AsmToken::LParen)) {
4985 Operands.push_back(
4986 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4987 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004988 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004989 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004990 return Error(Loc, "unexpected token in argument list");
4991 }
4992 if (Parser.getTok().isNot(AsmToken::RParen)) {
4993 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004994 return Error(Loc, "unexpected token, expected ')'");
4995 }
4996 Operands.push_back(
4997 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4998 Parser.Lex();
4999 }
5000 return false;
5001}
5002
5003/// Sometimes (i.e. in MSA) the operand may be followed immediately by
5004/// either one of these.
5005/// ::= '[', register, ']'
5006/// ::= '[', integer, ']'
5007/// handle it before we iterate so we don't get tripped up by the lack of
5008/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005009bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00005010 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005011 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005012 if (getLexer().is(AsmToken::LBrac)) {
5013 Operands.push_back(
5014 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
5015 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005016 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005017 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005018 return Error(Loc, "unexpected token in argument list");
5019 }
5020 if (Parser.getTok().isNot(AsmToken::RBrac)) {
5021 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005022 return Error(Loc, "unexpected token, expected ']'");
5023 }
5024 Operands.push_back(
5025 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
5026 Parser.Lex();
5027 }
5028 return false;
5029}
5030
David Blaikie960ea3f2014-06-08 16:18:35 +00005031bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
5032 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005033 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005034 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005035
5036 // We have reached first instruction, module directive are now forbidden.
5037 getTargetStreamer().forbidModuleDirective();
5038
Vladimir Medic74593e62013-07-17 15:00:42 +00005039 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00005040 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005041 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00005042 }
Vladimir Medic64828a12013-07-16 10:07:14 +00005043 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005044 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005045
5046 // Read the remaining operands.
5047 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5048 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005049 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005050 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005051 return Error(Loc, "unexpected token in argument list");
5052 }
Toma Tabacu13964452014-09-04 13:23:44 +00005053 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005054 return true;
5055 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00005056
Jack Carterd0bd6422013-04-18 00:41:53 +00005057 while (getLexer().is(AsmToken::Comma)) {
5058 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00005059 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005060 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005061 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005062 return Error(Loc, "unexpected token in argument list");
5063 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005064 // Parse bracket and parenthesis suffixes before we iterate
5065 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00005066 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005067 return true;
5068 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00005069 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005070 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005071 }
5072 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005073 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5074 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005075 return Error(Loc, "unexpected token in argument list");
5076 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005077 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00005078 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00005079}
5080
Nirav Dave996fc132016-05-05 14:15:46 +00005081// FIXME: Given that these have the same name, these should both be
5082// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005083bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005084 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005085 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00005086}
5087
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005088bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005089 return Error(Loc, ErrorMsg);
5090}
5091
Jack Carter0b744b32012-10-04 02:29:46 +00005092bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005093 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005094 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00005095
5096 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00005097 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00005098
5099 Parser.Lex(); // Eat "noat".
5100
Jack Carterd0bd6422013-04-18 00:41:53 +00005101 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005102 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005103 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005104 return false;
5105 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005106
5107 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005108 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005109 return false;
5110}
Jack Carterd0bd6422013-04-18 00:41:53 +00005111
Jack Carter0b744b32012-10-04 02:29:46 +00005112bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00005113 // Line can be: ".set at", which sets $at to $1
5114 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00005115 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00005116 Parser.Lex(); // Eat "at".
5117
Jack Carter0b744b32012-10-04 02:29:46 +00005118 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005119 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00005120 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00005121
5122 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005123 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005124 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00005125 }
5126
5127 if (getLexer().isNot(AsmToken::Equal)) {
5128 reportParseError("unexpected token, expected equals sign");
5129 return false;
5130 }
5131 Parser.Lex(); // Eat "=".
5132
5133 if (getLexer().isNot(AsmToken::Dollar)) {
5134 if (getLexer().is(AsmToken::EndOfStatement)) {
5135 reportParseError("no register specified");
5136 return false;
5137 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00005138 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00005139 return false;
5140 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005141 }
5142 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00005143
Toma Tabacu16a74492015-02-13 10:30:57 +00005144 // Find out what "reg" is.
5145 unsigned AtRegNo;
5146 const AsmToken &Reg = Parser.getTok();
5147 if (Reg.is(AsmToken::Identifier)) {
5148 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
5149 } else if (Reg.is(AsmToken::Integer)) {
5150 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00005151 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00005152 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00005153 return false;
5154 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005155
5156 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00005157 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005158 reportParseError("invalid register");
5159 return false;
5160 }
5161 Parser.Lex(); // Eat "reg".
5162
5163 // If this is not the end of the statement, report an error.
5164 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5165 reportParseError("unexpected token, expected end of statement");
5166 return false;
5167 }
5168
5169 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
5170
5171 Parser.Lex(); // Consume the EndOfStatement.
5172 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005173}
5174
5175bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005176 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005177 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005178 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005179 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005180 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005181 return false;
5182 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005183 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00005184 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005185 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005186 return false;
5187}
5188
5189bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005190 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005191 Parser.Lex();
5192 // If this is not the end of the statement, report an error.
5193 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005194 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005195 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005196 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005197 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005198 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005199 Parser.Lex(); // Consume the EndOfStatement.
5200 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005201}
5202
5203bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005204 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005205 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005206 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005207 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005208 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005209 return false;
5210 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005211 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005212 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005213 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005214 return false;
5215}
5216
5217bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005218 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005219 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005220 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005221 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005222 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005223 return false;
5224 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005225 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005226 reportParseError("`noreorder' must be set before `nomacro'");
5227 return false;
5228 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005229 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005230 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005231 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005232 return false;
5233}
Jack Carterd76b2372013-03-21 21:44:16 +00005234
Daniel Sanders44934432014-08-07 12:03:36 +00005235bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005236 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005237 Parser.Lex();
5238
5239 // If this is not the end of the statement, report an error.
5240 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005241 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005242
5243 setFeatureBits(Mips::FeatureMSA, "msa");
5244 getTargetStreamer().emitDirectiveSetMsa();
5245 return false;
5246}
5247
5248bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005249 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005250 Parser.Lex();
5251
5252 // If this is not the end of the statement, report an error.
5253 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005254 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005255
5256 clearFeatureBits(Mips::FeatureMSA, "msa");
5257 getTargetStreamer().emitDirectiveSetNoMsa();
5258 return false;
5259}
5260
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005261bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005262 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005263 Parser.Lex(); // Eat "nodsp".
5264
5265 // If this is not the end of the statement, report an error.
5266 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5267 reportParseError("unexpected token, expected end of statement");
5268 return false;
5269 }
5270
5271 clearFeatureBits(Mips::FeatureDSP, "dsp");
5272 getTargetStreamer().emitDirectiveSetNoDsp();
5273 return false;
5274}
5275
Toma Tabacucc2502d2014-11-04 17:18:07 +00005276bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005277 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005278 Parser.Lex(); // Eat "mips16".
5279
Jack Carter39536722014-01-22 23:08:42 +00005280 // If this is not the end of the statement, report an error.
5281 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005282 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005283 return false;
5284 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005285
5286 setFeatureBits(Mips::FeatureMips16, "mips16");
5287 getTargetStreamer().emitDirectiveSetMips16();
5288 Parser.Lex(); // Consume the EndOfStatement.
5289 return false;
5290}
5291
5292bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005293 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005294 Parser.Lex(); // Eat "nomips16".
5295
5296 // If this is not the end of the statement, report an error.
5297 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5298 reportParseError("unexpected token, expected end of statement");
5299 return false;
5300 }
5301
5302 clearFeatureBits(Mips::FeatureMips16, "mips16");
5303 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005304 Parser.Lex(); // Consume the EndOfStatement.
5305 return false;
5306}
5307
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005308bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005309 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005310 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005311 // Line can be: .set fp=32
5312 // .set fp=xx
5313 // .set fp=64
5314 Parser.Lex(); // Eat fp token
5315 AsmToken Tok = Parser.getTok();
5316 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005317 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005318 return false;
5319 }
5320 Parser.Lex(); // Eat '=' token.
5321 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005322
5323 if (!parseFpABIValue(FpAbiVal, ".set"))
5324 return false;
5325
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005326 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005327 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005328 return false;
5329 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005330 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005331 Parser.Lex(); // Consume the EndOfStatement.
5332 return false;
5333}
5334
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005335bool MipsAsmParser::parseSetOddSPRegDirective() {
5336 MCAsmParser &Parser = getParser();
5337
5338 Parser.Lex(); // Eat "oddspreg".
5339 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5340 reportParseError("unexpected token, expected end of statement");
5341 return false;
5342 }
5343
5344 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5345 getTargetStreamer().emitDirectiveSetOddSPReg();
5346 return false;
5347}
5348
5349bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5350 MCAsmParser &Parser = getParser();
5351
5352 Parser.Lex(); // Eat "nooddspreg".
5353 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5354 reportParseError("unexpected token, expected end of statement");
5355 return false;
5356 }
5357
5358 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5359 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5360 return false;
5361}
5362
Toma Tabacu9db22db2014-09-09 10:15:38 +00005363bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005364 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005365 SMLoc Loc = getLexer().getLoc();
5366
5367 Parser.Lex();
5368 if (getLexer().isNot(AsmToken::EndOfStatement))
5369 return reportParseError("unexpected token, expected end of statement");
5370
5371 // Always keep an element on the options "stack" to prevent the user
5372 // from changing the initial options. This is how we remember them.
5373 if (AssemblerOptions.size() == 2)
5374 return reportParseError(Loc, ".set pop with no .set push");
5375
Akira Hatanakab11ef082015-11-14 06:35:56 +00005376 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005377 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005378 setAvailableFeatures(
5379 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5380 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005381
5382 getTargetStreamer().emitDirectiveSetPop();
5383 return false;
5384}
5385
5386bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005387 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005388 Parser.Lex();
5389 if (getLexer().isNot(AsmToken::EndOfStatement))
5390 return reportParseError("unexpected token, expected end of statement");
5391
5392 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005393 AssemblerOptions.push_back(
5394 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005395
5396 getTargetStreamer().emitDirectiveSetPush();
5397 return false;
5398}
5399
Toma Tabacu29696502015-06-02 09:48:04 +00005400bool MipsAsmParser::parseSetSoftFloatDirective() {
5401 MCAsmParser &Parser = getParser();
5402 Parser.Lex();
5403 if (getLexer().isNot(AsmToken::EndOfStatement))
5404 return reportParseError("unexpected token, expected end of statement");
5405
5406 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5407 getTargetStreamer().emitDirectiveSetSoftFloat();
5408 return false;
5409}
5410
5411bool MipsAsmParser::parseSetHardFloatDirective() {
5412 MCAsmParser &Parser = getParser();
5413 Parser.Lex();
5414 if (getLexer().isNot(AsmToken::EndOfStatement))
5415 return reportParseError("unexpected token, expected end of statement");
5416
5417 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5418 getTargetStreamer().emitDirectiveSetHardFloat();
5419 return false;
5420}
5421
Jack Carterd76b2372013-03-21 21:44:16 +00005422bool MipsAsmParser::parseSetAssignment() {
5423 StringRef Name;
5424 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005425 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005426
5427 if (Parser.parseIdentifier(Name))
5428 reportParseError("expected identifier after .set");
5429
5430 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005431 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005432 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005433
Jack Carter3b2c96e2014-01-22 23:31:38 +00005434 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005435 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005436
Jim Grosbach6f482002015-05-18 18:43:14 +00005437 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005438 Sym->setVariableValue(Value);
5439
5440 return false;
5441}
Jack Carterd0bd6422013-04-18 00:41:53 +00005442
Toma Tabacu26647792014-09-09 12:52:14 +00005443bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005444 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005445 Parser.Lex();
5446 if (getLexer().isNot(AsmToken::EndOfStatement))
5447 return reportParseError("unexpected token, expected end of statement");
5448
5449 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005450 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005451 setAvailableFeatures(
5452 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5453 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005454 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5455
5456 getTargetStreamer().emitDirectiveSetMips0();
5457 return false;
5458}
5459
Toma Tabacu85618b32014-08-19 14:22:52 +00005460bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005461 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005462 Parser.Lex();
5463 if (getLexer().isNot(AsmToken::Equal))
5464 return reportParseError("unexpected token, expected equals sign");
5465
5466 Parser.Lex();
5467 StringRef Arch;
5468 if (Parser.parseIdentifier(Arch))
5469 return reportParseError("expected arch identifier");
5470
5471 StringRef ArchFeatureName =
5472 StringSwitch<StringRef>(Arch)
5473 .Case("mips1", "mips1")
5474 .Case("mips2", "mips2")
5475 .Case("mips3", "mips3")
5476 .Case("mips4", "mips4")
5477 .Case("mips5", "mips5")
5478 .Case("mips32", "mips32")
5479 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005480 .Case("mips32r3", "mips32r3")
5481 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005482 .Case("mips32r6", "mips32r6")
5483 .Case("mips64", "mips64")
5484 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005485 .Case("mips64r3", "mips64r3")
5486 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005487 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005488 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005489 .Case("r4000", "mips3") // This is an implementation of Mips3.
5490 .Default("");
5491
5492 if (ArchFeatureName.empty())
5493 return reportParseError("unsupported architecture");
5494
5495 selectArch(ArchFeatureName);
5496 getTargetStreamer().emitDirectiveSetArch(Arch);
5497 return false;
5498}
5499
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005500bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005501 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005502 Parser.Lex();
5503 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005504 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005505
Matheus Almeida2852af82014-04-22 10:15:54 +00005506 switch (Feature) {
5507 default:
5508 llvm_unreachable("Unimplemented feature");
5509 case Mips::FeatureDSP:
5510 setFeatureBits(Mips::FeatureDSP, "dsp");
5511 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005512 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005513 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00005514 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00005515 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005516 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005517 case Mips::FeatureMips1:
5518 selectArch("mips1");
5519 getTargetStreamer().emitDirectiveSetMips1();
5520 break;
5521 case Mips::FeatureMips2:
5522 selectArch("mips2");
5523 getTargetStreamer().emitDirectiveSetMips2();
5524 break;
5525 case Mips::FeatureMips3:
5526 selectArch("mips3");
5527 getTargetStreamer().emitDirectiveSetMips3();
5528 break;
5529 case Mips::FeatureMips4:
5530 selectArch("mips4");
5531 getTargetStreamer().emitDirectiveSetMips4();
5532 break;
5533 case Mips::FeatureMips5:
5534 selectArch("mips5");
5535 getTargetStreamer().emitDirectiveSetMips5();
5536 break;
5537 case Mips::FeatureMips32:
5538 selectArch("mips32");
5539 getTargetStreamer().emitDirectiveSetMips32();
5540 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005541 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005542 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005543 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005544 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005545 case Mips::FeatureMips32r3:
5546 selectArch("mips32r3");
5547 getTargetStreamer().emitDirectiveSetMips32R3();
5548 break;
5549 case Mips::FeatureMips32r5:
5550 selectArch("mips32r5");
5551 getTargetStreamer().emitDirectiveSetMips32R5();
5552 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005553 case Mips::FeatureMips32r6:
5554 selectArch("mips32r6");
5555 getTargetStreamer().emitDirectiveSetMips32R6();
5556 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005557 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005558 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005559 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005560 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005561 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005562 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005563 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005564 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005565 case Mips::FeatureMips64r3:
5566 selectArch("mips64r3");
5567 getTargetStreamer().emitDirectiveSetMips64R3();
5568 break;
5569 case Mips::FeatureMips64r5:
5570 selectArch("mips64r5");
5571 getTargetStreamer().emitDirectiveSetMips64R5();
5572 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005573 case Mips::FeatureMips64r6:
5574 selectArch("mips64r6");
5575 getTargetStreamer().emitDirectiveSetMips64R6();
5576 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005577 }
5578 return false;
5579}
5580
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005581bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005582 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005583 if (getLexer().isNot(AsmToken::Comma)) {
5584 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005585 return Error(Loc, ErrorStr);
5586 }
5587
Matheus Almeida2852af82014-04-22 10:15:54 +00005588 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005589 return true;
5590}
5591
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005592// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5593// In this class, it is only used for .cprestore.
5594// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5595// MipsTargetELFStreamer and MipsAsmParser.
5596bool MipsAsmParser::isPicAndNotNxxAbi() {
5597 return inPicMode() && !(isABI_N32() || isABI_N64());
5598}
5599
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005600bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005601 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005602 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005603
Toma Tabacudde4c462014-11-06 10:02:45 +00005604 if (inMips16Mode()) {
5605 reportParseError(".cpload is not supported in Mips16 mode");
5606 return false;
5607 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005608
David Blaikie960ea3f2014-06-08 16:18:35 +00005609 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005610 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005611 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5612 reportParseError("expected register containing function address");
5613 return false;
5614 }
5615
David Blaikie960ea3f2014-06-08 16:18:35 +00005616 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5617 if (!RegOpnd.isGPRAsmReg()) {
5618 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005619 return false;
5620 }
5621
Toma Tabacudde4c462014-11-06 10:02:45 +00005622 // If this is not the end of the statement, report an error.
5623 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5624 reportParseError("unexpected token, expected end of statement");
5625 return false;
5626 }
5627
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005628 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005629 return false;
5630}
5631
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005632bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5633 MCAsmParser &Parser = getParser();
5634
5635 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5636 // is used in non-PIC mode.
5637
5638 if (inMips16Mode()) {
5639 reportParseError(".cprestore is not supported in Mips16 mode");
5640 return false;
5641 }
5642
5643 // Get the stack offset value.
5644 const MCExpr *StackOffset;
5645 int64_t StackOffsetVal;
5646 if (Parser.parseExpression(StackOffset)) {
5647 reportParseError("expected stack offset value");
5648 return false;
5649 }
5650
5651 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5652 reportParseError("stack offset is not an absolute expression");
5653 return false;
5654 }
5655
5656 if (StackOffsetVal < 0) {
5657 Warning(Loc, ".cprestore with negative stack offset has no effect");
5658 IsCpRestoreSet = false;
5659 } else {
5660 IsCpRestoreSet = true;
5661 CpRestoreOffset = StackOffsetVal;
5662 }
5663
5664 // If this is not the end of the statement, report an error.
5665 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5666 reportParseError("unexpected token, expected end of statement");
5667 return false;
5668 }
5669
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005670 if (!getTargetStreamer().emitDirectiveCpRestore(
5671 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005672 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005673 Parser.Lex(); // Consume the EndOfStatement.
5674 return false;
5675}
5676
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005677bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005678 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005679 unsigned FuncReg;
5680 unsigned Save;
5681 bool SaveIsReg = true;
5682
Matheus Almeida7e815762014-06-18 13:08:59 +00005683 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005684 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005685 if (ResTy == MatchOperand_NoMatch) {
5686 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005687 return false;
5688 }
5689
5690 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5691 if (!FuncRegOpnd.isGPRAsmReg()) {
5692 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005693 return false;
5694 }
5695
5696 FuncReg = FuncRegOpnd.getGPR32Reg();
5697 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005698
Toma Tabacu65f10572014-09-16 15:00:52 +00005699 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005700 return true;
5701
Toma Tabacu13964452014-09-04 13:23:44 +00005702 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005703 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005704 const MCExpr *OffsetExpr;
5705 int64_t OffsetVal;
5706 SMLoc ExprLoc = getLexer().getLoc();
5707
5708 if (Parser.parseExpression(OffsetExpr) ||
5709 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5710 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005711 return false;
5712 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005713
5714 Save = OffsetVal;
5715 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005716 } else {
5717 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5718 if (!SaveOpnd.isGPRAsmReg()) {
5719 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005720 return false;
5721 }
5722 Save = SaveOpnd.getGPR32Reg();
5723 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005724
Toma Tabacu65f10572014-09-16 15:00:52 +00005725 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005726 return true;
5727
Toma Tabacu8874eac2015-02-18 13:46:53 +00005728 const MCExpr *Expr;
5729 if (Parser.parseExpression(Expr)) {
5730 reportParseError("expected expression");
5731 return false;
5732 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005733
Toma Tabacu8874eac2015-02-18 13:46:53 +00005734 if (Expr->getKind() != MCExpr::SymbolRef) {
5735 reportParseError("expected symbol");
5736 return false;
5737 }
5738 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5739
Daniel Sandersf173dda2015-09-22 10:50:09 +00005740 CpSaveLocation = Save;
5741 CpSaveLocationIsRegister = SaveIsReg;
5742
Toma Tabacu8874eac2015-02-18 13:46:53 +00005743 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5744 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005745 return false;
5746}
5747
Daniel Sandersf173dda2015-09-22 10:50:09 +00005748bool MipsAsmParser::parseDirectiveCPReturn() {
5749 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5750 CpSaveLocationIsRegister);
5751 return false;
5752}
5753
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005754bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005755 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005756 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5757 const AsmToken &Tok = Parser.getTok();
5758
5759 if (Tok.getString() == "2008") {
5760 Parser.Lex();
5761 getTargetStreamer().emitDirectiveNaN2008();
5762 return false;
5763 } else if (Tok.getString() == "legacy") {
5764 Parser.Lex();
5765 getTargetStreamer().emitDirectiveNaNLegacy();
5766 return false;
5767 }
5768 }
5769 // If we don't recognize the option passed to the .nan
5770 // directive (e.g. no option or unknown option), emit an error.
5771 reportParseError("invalid option in .nan directive");
5772 return false;
5773}
5774
Jack Carter0b744b32012-10-04 02:29:46 +00005775bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005776 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005777 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005778 const AsmToken &Tok = Parser.getTok();
5779
5780 if (Tok.getString() == "noat") {
5781 return parseSetNoAtDirective();
5782 } else if (Tok.getString() == "at") {
5783 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005784 } else if (Tok.getString() == "arch") {
5785 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005786 } else if (Tok.getString() == "fp") {
5787 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005788 } else if (Tok.getString() == "oddspreg") {
5789 return parseSetOddSPRegDirective();
5790 } else if (Tok.getString() == "nooddspreg") {
5791 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005792 } else if (Tok.getString() == "pop") {
5793 return parseSetPopDirective();
5794 } else if (Tok.getString() == "push") {
5795 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005796 } else if (Tok.getString() == "reorder") {
5797 return parseSetReorderDirective();
5798 } else if (Tok.getString() == "noreorder") {
5799 return parseSetNoReorderDirective();
5800 } else if (Tok.getString() == "macro") {
5801 return parseSetMacroDirective();
5802 } else if (Tok.getString() == "nomacro") {
5803 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005804 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005805 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005806 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005807 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005808 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00005809 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005810 getTargetStreamer().emitDirectiveSetNoMicroMips();
5811 Parser.eatToEndOfStatement();
5812 return false;
5813 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005814 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005815 } else if (Tok.getString() == "mips0") {
5816 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005817 } else if (Tok.getString() == "mips1") {
5818 return parseSetFeature(Mips::FeatureMips1);
5819 } else if (Tok.getString() == "mips2") {
5820 return parseSetFeature(Mips::FeatureMips2);
5821 } else if (Tok.getString() == "mips3") {
5822 return parseSetFeature(Mips::FeatureMips3);
5823 } else if (Tok.getString() == "mips4") {
5824 return parseSetFeature(Mips::FeatureMips4);
5825 } else if (Tok.getString() == "mips5") {
5826 return parseSetFeature(Mips::FeatureMips5);
5827 } else if (Tok.getString() == "mips32") {
5828 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005829 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005830 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005831 } else if (Tok.getString() == "mips32r3") {
5832 return parseSetFeature(Mips::FeatureMips32r3);
5833 } else if (Tok.getString() == "mips32r5") {
5834 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005835 } else if (Tok.getString() == "mips32r6") {
5836 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005837 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005838 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005839 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005840 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005841 } else if (Tok.getString() == "mips64r3") {
5842 return parseSetFeature(Mips::FeatureMips64r3);
5843 } else if (Tok.getString() == "mips64r5") {
5844 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005845 } else if (Tok.getString() == "mips64r6") {
5846 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005847 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005848 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005849 } else if (Tok.getString() == "nodsp") {
5850 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005851 } else if (Tok.getString() == "msa") {
5852 return parseSetMsaDirective();
5853 } else if (Tok.getString() == "nomsa") {
5854 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005855 } else if (Tok.getString() == "softfloat") {
5856 return parseSetSoftFloatDirective();
5857 } else if (Tok.getString() == "hardfloat") {
5858 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005859 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005860 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005861 parseSetAssignment();
5862 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005863 }
Jack Carter07c818d2013-01-25 01:31:34 +00005864
Jack Carter0b744b32012-10-04 02:29:46 +00005865 return true;
5866}
5867
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005868/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005869/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005870bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005871 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005872 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5873 for (;;) {
5874 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005875 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005876 return true;
5877
5878 getParser().getStreamer().EmitValue(Value, Size);
5879
5880 if (getLexer().is(AsmToken::EndOfStatement))
5881 break;
5882
Jack Carter07c818d2013-01-25 01:31:34 +00005883 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005884 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005885 Parser.Lex();
5886 }
5887 }
5888
5889 Parser.Lex();
5890 return false;
5891}
5892
Vladimir Medic4c299852013-11-06 11:27:05 +00005893/// parseDirectiveGpWord
5894/// ::= .gpword local_sym
5895bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005896 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005897 const MCExpr *Value;
5898 // EmitGPRel32Value requires an expression, so we are using base class
5899 // method to evaluate the expression.
5900 if (getParser().parseExpression(Value))
5901 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005902 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005903
Vladimir Medice10c1122013-11-13 13:18:04 +00005904 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005905 return Error(getLexer().getLoc(),
5906 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005907 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005908 return false;
5909}
5910
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005911/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005912/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005913bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005914 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005915 const MCExpr *Value;
5916 // EmitGPRel64Value requires an expression, so we are using base class
5917 // method to evaluate the expression.
5918 if (getParser().parseExpression(Value))
5919 return true;
5920 getParser().getStreamer().EmitGPRel64Value(Value);
5921
5922 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00005923 return Error(getLexer().getLoc(),
5924 "unexpected token, expected end of statement");
5925 Parser.Lex(); // Eat EndOfStatement token.
5926 return false;
5927}
5928
5929/// parseDirectiveDtpRelWord
5930/// ::= .dtprelword tls_sym
5931bool MipsAsmParser::parseDirectiveDtpRelWord() {
5932 MCAsmParser &Parser = getParser();
5933 const MCExpr *Value;
5934 // EmitDTPRel32Value requires an expression, so we are using base class
5935 // method to evaluate the expression.
5936 if (getParser().parseExpression(Value))
5937 return true;
5938 getParser().getStreamer().EmitDTPRel32Value(Value);
5939
5940 if (getLexer().isNot(AsmToken::EndOfStatement))
5941 return Error(getLexer().getLoc(),
5942 "unexpected token, expected end of statement");
5943 Parser.Lex(); // Eat EndOfStatement token.
5944 return false;
5945}
5946
5947/// parseDirectiveDtpRelDWord
5948/// ::= .dtpreldword tls_sym
5949bool MipsAsmParser::parseDirectiveDtpRelDWord() {
5950 MCAsmParser &Parser = getParser();
5951 const MCExpr *Value;
5952 // EmitDTPRel64Value requires an expression, so we are using base class
5953 // method to evaluate the expression.
5954 if (getParser().parseExpression(Value))
5955 return true;
5956 getParser().getStreamer().EmitDTPRel64Value(Value);
5957
5958 if (getLexer().isNot(AsmToken::EndOfStatement))
5959 return Error(getLexer().getLoc(),
5960 "unexpected token, expected end of statement");
5961 Parser.Lex(); // Eat EndOfStatement token.
5962 return false;
5963}
5964
5965/// parseDirectiveTpRelWord
5966/// ::= .tprelword tls_sym
5967bool MipsAsmParser::parseDirectiveTpRelWord() {
5968 MCAsmParser &Parser = getParser();
5969 const MCExpr *Value;
5970 // EmitTPRel32Value requires an expression, so we are using base class
5971 // method to evaluate the expression.
5972 if (getParser().parseExpression(Value))
5973 return true;
5974 getParser().getStreamer().EmitTPRel32Value(Value);
5975
5976 if (getLexer().isNot(AsmToken::EndOfStatement))
5977 return Error(getLexer().getLoc(),
5978 "unexpected token, expected end of statement");
5979 Parser.Lex(); // Eat EndOfStatement token.
5980 return false;
5981}
5982
5983/// parseDirectiveTpRelDWord
5984/// ::= .tpreldword tls_sym
5985bool MipsAsmParser::parseDirectiveTpRelDWord() {
5986 MCAsmParser &Parser = getParser();
5987 const MCExpr *Value;
5988 // EmitTPRel64Value requires an expression, so we are using base class
5989 // method to evaluate the expression.
5990 if (getParser().parseExpression(Value))
5991 return true;
5992 getParser().getStreamer().EmitTPRel64Value(Value);
5993
5994 if (getLexer().isNot(AsmToken::EndOfStatement))
5995 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005996 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005997 Parser.Lex(); // Eat EndOfStatement token.
5998 return false;
5999}
6000
Jack Carter0cd3c192014-01-06 23:27:31 +00006001bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006002 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00006003 // Get the option token.
6004 AsmToken Tok = Parser.getTok();
6005 // At the moment only identifiers are supported.
6006 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006007 return Error(Parser.getTok().getLoc(),
6008 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00006009 }
6010
6011 StringRef Option = Tok.getIdentifier();
6012
6013 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006014 // MipsAsmParser needs to know if the current PIC mode changes.
6015 IsPicEnabled = false;
6016
Jack Carter0cd3c192014-01-06 23:27:31 +00006017 getTargetStreamer().emitDirectiveOptionPic0();
6018 Parser.Lex();
6019 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006020 return Error(Parser.getTok().getLoc(),
6021 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006022 }
6023 return false;
6024 }
6025
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006026 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006027 // MipsAsmParser needs to know if the current PIC mode changes.
6028 IsPicEnabled = true;
6029
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006030 getTargetStreamer().emitDirectiveOptionPic2();
6031 Parser.Lex();
6032 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006033 return Error(Parser.getTok().getLoc(),
6034 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006035 }
6036 return false;
6037 }
6038
Jack Carter0cd3c192014-01-06 23:27:31 +00006039 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00006040 Warning(Parser.getTok().getLoc(),
6041 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00006042 Parser.eatToEndOfStatement();
6043 return false;
6044}
6045
Toma Tabacu9ca50962015-04-16 09:53:47 +00006046/// parseInsnDirective
6047/// ::= .insn
6048bool MipsAsmParser::parseInsnDirective() {
6049 // If this is not the end of the statement, report an error.
6050 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6051 reportParseError("unexpected token, expected end of statement");
6052 return false;
6053 }
6054
6055 // The actual label marking happens in
6056 // MipsELFStreamer::createPendingLabelRelocs().
6057 getTargetStreamer().emitDirectiveInsn();
6058
6059 getParser().Lex(); // Eat EndOfStatement token.
6060 return false;
6061}
6062
Simon Atanasyanbe186202016-02-11 06:45:54 +00006063/// parseSSectionDirective
6064/// ::= .sbss
6065/// ::= .sdata
6066bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
6067 // If this is not the end of the statement, report an error.
6068 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6069 reportParseError("unexpected token, expected end of statement");
6070 return false;
6071 }
6072
6073 MCSection *ELFSection = getContext().getELFSection(
6074 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
6075 getParser().getStreamer().SwitchSection(ELFSection);
6076
6077 getParser().Lex(); // Eat EndOfStatement token.
6078 return false;
6079}
6080
Daniel Sanders7e527422014-07-10 13:38:23 +00006081/// parseDirectiveModule
6082/// ::= .module oddspreg
6083/// ::= .module nooddspreg
6084/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00006085/// ::= .module softfloat
6086/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006087bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006088 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006089 MCAsmLexer &Lexer = getLexer();
6090 SMLoc L = Lexer.getLoc();
6091
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006092 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006093 // TODO : get a better message.
6094 reportParseError(".module directive must appear before any code");
6095 return false;
6096 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006097
Toma Tabacuc405c822015-01-23 10:40:19 +00006098 StringRef Option;
6099 if (Parser.parseIdentifier(Option)) {
6100 reportParseError("expected .module option identifier");
6101 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006102 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006103
Toma Tabacuc405c822015-01-23 10:40:19 +00006104 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006105 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006106
Toma Tabacu3c499582015-06-25 10:56:57 +00006107 // Synchronize the abiflags information with the FeatureBits information we
6108 // changed above.
6109 getTargetStreamer().updateABIInfo(*this);
6110
6111 // If printing assembly, use the recently updated abiflags information.
6112 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6113 // emitted at the end).
6114 getTargetStreamer().emitDirectiveModuleOddSPReg();
6115
Toma Tabacuc405c822015-01-23 10:40:19 +00006116 // If this is not the end of the statement, report an error.
6117 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6118 reportParseError("unexpected token, expected end of statement");
6119 return false;
6120 }
6121
6122 return false; // parseDirectiveModule has finished successfully.
6123 } else if (Option == "nooddspreg") {
6124 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006125 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00006126 }
6127
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006128 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006129
Toma Tabacu3c499582015-06-25 10:56:57 +00006130 // Synchronize the abiflags information with the FeatureBits information we
6131 // changed above.
6132 getTargetStreamer().updateABIInfo(*this);
6133
6134 // If printing assembly, use the recently updated abiflags information.
6135 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6136 // emitted at the end).
6137 getTargetStreamer().emitDirectiveModuleOddSPReg();
6138
Toma Tabacuc405c822015-01-23 10:40:19 +00006139 // If this is not the end of the statement, report an error.
6140 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6141 reportParseError("unexpected token, expected end of statement");
6142 return false;
6143 }
6144
6145 return false; // parseDirectiveModule has finished successfully.
6146 } else if (Option == "fp") {
6147 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00006148 } else if (Option == "softfloat") {
6149 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6150
6151 // Synchronize the ABI Flags information with the FeatureBits information we
6152 // updated above.
6153 getTargetStreamer().updateABIInfo(*this);
6154
6155 // If printing assembly, use the recently updated ABI Flags information.
6156 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6157 // emitted later).
6158 getTargetStreamer().emitDirectiveModuleSoftFloat();
6159
6160 // If this is not the end of the statement, report an error.
6161 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6162 reportParseError("unexpected token, expected end of statement");
6163 return false;
6164 }
6165
6166 return false; // parseDirectiveModule has finished successfully.
6167 } else if (Option == "hardfloat") {
6168 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6169
6170 // Synchronize the ABI Flags information with the FeatureBits information we
6171 // updated above.
6172 getTargetStreamer().updateABIInfo(*this);
6173
6174 // If printing assembly, use the recently updated ABI Flags information.
6175 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6176 // emitted later).
6177 getTargetStreamer().emitDirectiveModuleHardFloat();
6178
6179 // If this is not the end of the statement, report an error.
6180 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6181 reportParseError("unexpected token, expected end of statement");
6182 return false;
6183 }
6184
6185 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00006186 } else {
6187 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
6188 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006189}
6190
6191/// parseDirectiveModuleFP
6192/// ::= =32
6193/// ::= =xx
6194/// ::= =64
6195bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006196 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006197 MCAsmLexer &Lexer = getLexer();
6198
6199 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006200 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006201 return false;
6202 }
6203 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006204
Daniel Sanders7e527422014-07-10 13:38:23 +00006205 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006206 if (!parseFpABIValue(FpABI, ".module"))
6207 return false;
6208
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006209 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006210 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006211 return false;
6212 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006213
Toma Tabacua64e5402015-06-25 12:44:38 +00006214 // Synchronize the abiflags information with the FeatureBits information we
6215 // changed above.
6216 getTargetStreamer().updateABIInfo(*this);
6217
6218 // If printing assembly, use the recently updated abiflags information.
6219 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6220 // emitted at the end).
6221 getTargetStreamer().emitDirectiveModuleFP();
6222
Daniel Sanders7e527422014-07-10 13:38:23 +00006223 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006224 return false;
6225}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006226
Daniel Sanders7e527422014-07-10 13:38:23 +00006227bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006228 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006229 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006230 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006231 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006232
6233 if (Lexer.is(AsmToken::Identifier)) {
6234 StringRef Value = Parser.getTok().getString();
6235 Parser.Lex();
6236
6237 if (Value != "xx") {
6238 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6239 return false;
6240 }
6241
6242 if (!isABI_O32()) {
6243 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
6244 return false;
6245 }
6246
Daniel Sanders7e527422014-07-10 13:38:23 +00006247 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006248 if (ModuleLevelOptions) {
6249 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6250 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6251 } else {
6252 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6253 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6254 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006255 return true;
6256 }
6257
6258 if (Lexer.is(AsmToken::Integer)) {
6259 unsigned Value = Parser.getTok().getIntVal();
6260 Parser.Lex();
6261
6262 if (Value != 32 && Value != 64) {
6263 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6264 return false;
6265 }
6266
6267 if (Value == 32) {
6268 if (!isABI_O32()) {
6269 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6270 return false;
6271 }
6272
Daniel Sanders7e527422014-07-10 13:38:23 +00006273 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006274 if (ModuleLevelOptions) {
6275 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6276 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6277 } else {
6278 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6279 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6280 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006281 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006282 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006283 if (ModuleLevelOptions) {
6284 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6285 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6286 } else {
6287 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6288 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6289 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006290 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006291
Daniel Sanders7e527422014-07-10 13:38:23 +00006292 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006293 }
6294
6295 return false;
6296}
6297
Jack Carter0b744b32012-10-04 02:29:46 +00006298bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006299 // This returns false if this function recognizes the directive
6300 // regardless of whether it is successfully handles or reports an
6301 // error. Otherwise it returns true to give the generic parser a
6302 // chance at recognizing it.
6303
Rafael Espindola961d4692014-11-11 05:18:41 +00006304 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006305 StringRef IDVal = DirectiveID.getString();
6306
Nirav Dave996fc132016-05-05 14:15:46 +00006307 if (IDVal == ".cpload") {
6308 parseDirectiveCpLoad(DirectiveID.getLoc());
6309 return false;
6310 }
6311 if (IDVal == ".cprestore") {
6312 parseDirectiveCpRestore(DirectiveID.getLoc());
6313 return false;
6314 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006315 if (IDVal == ".dword") {
6316 parseDataDirective(8, DirectiveID.getLoc());
6317 return false;
6318 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006319 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006320 StringRef SymbolName;
6321
6322 if (Parser.parseIdentifier(SymbolName)) {
6323 reportParseError("expected identifier after .ent");
6324 return false;
6325 }
6326
6327 // There's an undocumented extension that allows an integer to
6328 // follow the name of the procedure which AFAICS is ignored by GAS.
6329 // Example: .ent foo,2
6330 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6331 if (getLexer().isNot(AsmToken::Comma)) {
6332 // Even though we accept this undocumented extension for compatibility
6333 // reasons, the additional integer argument does not actually change
6334 // the behaviour of the '.ent' directive, so we would like to discourage
6335 // its use. We do this by not referring to the extended version in
6336 // error messages which are not directly related to its use.
6337 reportParseError("unexpected token, expected end of statement");
6338 return false;
6339 }
6340 Parser.Lex(); // Eat the comma.
6341 const MCExpr *DummyNumber;
6342 int64_t DummyNumberVal;
6343 // If the user was explicitly trying to use the extended version,
6344 // we still give helpful extension-related error messages.
6345 if (Parser.parseExpression(DummyNumber)) {
6346 reportParseError("expected number after comma");
6347 return false;
6348 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006349 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006350 reportParseError("expected an absolute expression after comma");
6351 return false;
6352 }
6353 }
6354
6355 // If this is not the end of the statement, report an error.
6356 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6357 reportParseError("unexpected token, expected end of statement");
6358 return false;
6359 }
6360
Jim Grosbach6f482002015-05-18 18:43:14 +00006361 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006362
6363 getTargetStreamer().emitDirectiveEnt(*Sym);
6364 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006365 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006366 return false;
6367 }
6368
Jack Carter07c818d2013-01-25 01:31:34 +00006369 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006370 StringRef SymbolName;
6371
6372 if (Parser.parseIdentifier(SymbolName)) {
6373 reportParseError("expected identifier after .end");
6374 return false;
6375 }
6376
6377 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6378 reportParseError("unexpected token, expected end of statement");
6379 return false;
6380 }
6381
6382 if (CurrentFn == nullptr) {
6383 reportParseError(".end used without .ent");
6384 return false;
6385 }
6386
6387 if ((SymbolName != CurrentFn->getName())) {
6388 reportParseError(".end symbol does not match .ent symbol");
6389 return false;
6390 }
6391
6392 getTargetStreamer().emitDirectiveEnd(SymbolName);
6393 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006394 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006395 return false;
6396 }
6397
Jack Carter07c818d2013-01-25 01:31:34 +00006398 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006399 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6400 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006401 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006402 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6403 reportParseError("expected stack register");
6404 return false;
6405 }
6406
6407 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6408 if (!StackRegOpnd.isGPRAsmReg()) {
6409 reportParseError(StackRegOpnd.getStartLoc(),
6410 "expected general purpose register");
6411 return false;
6412 }
6413 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6414
6415 if (Parser.getTok().is(AsmToken::Comma))
6416 Parser.Lex();
6417 else {
6418 reportParseError("unexpected token, expected comma");
6419 return false;
6420 }
6421
6422 // Parse the frame size.
6423 const MCExpr *FrameSize;
6424 int64_t FrameSizeVal;
6425
6426 if (Parser.parseExpression(FrameSize)) {
6427 reportParseError("expected frame size value");
6428 return false;
6429 }
6430
Jim Grosbach13760bd2015-05-30 01:25:56 +00006431 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006432 reportParseError("frame size not an absolute expression");
6433 return false;
6434 }
6435
6436 if (Parser.getTok().is(AsmToken::Comma))
6437 Parser.Lex();
6438 else {
6439 reportParseError("unexpected token, expected comma");
6440 return false;
6441 }
6442
6443 // Parse the return register.
6444 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006445 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006446 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6447 reportParseError("expected return register");
6448 return false;
6449 }
6450
6451 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6452 if (!ReturnRegOpnd.isGPRAsmReg()) {
6453 reportParseError(ReturnRegOpnd.getStartLoc(),
6454 "expected general purpose register");
6455 return false;
6456 }
6457
6458 // If this is not the end of the statement, report an error.
6459 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6460 reportParseError("unexpected token, expected end of statement");
6461 return false;
6462 }
6463
6464 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6465 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006466 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006467 return false;
6468 }
6469
Jack Carter07c818d2013-01-25 01:31:34 +00006470 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006471 parseDirectiveSet();
6472 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006473 }
6474
Daniel Sandersd97a6342014-08-13 10:07:34 +00006475 if (IDVal == ".mask" || IDVal == ".fmask") {
6476 // .mask bitmask, frame_offset
6477 // bitmask: One bit for each register used.
6478 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6479 // first register is expected to be saved.
6480 // Examples:
6481 // .mask 0x80000000, -4
6482 // .fmask 0x80000000, -4
6483 //
Jack Carterbe332172012-09-07 00:48:02 +00006484
Daniel Sandersd97a6342014-08-13 10:07:34 +00006485 // Parse the bitmask
6486 const MCExpr *BitMask;
6487 int64_t BitMaskVal;
6488
6489 if (Parser.parseExpression(BitMask)) {
6490 reportParseError("expected bitmask value");
6491 return false;
6492 }
6493
Jim Grosbach13760bd2015-05-30 01:25:56 +00006494 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006495 reportParseError("bitmask not an absolute expression");
6496 return false;
6497 }
6498
6499 if (Parser.getTok().is(AsmToken::Comma))
6500 Parser.Lex();
6501 else {
6502 reportParseError("unexpected token, expected comma");
6503 return false;
6504 }
6505
6506 // Parse the frame_offset
6507 const MCExpr *FrameOffset;
6508 int64_t FrameOffsetVal;
6509
6510 if (Parser.parseExpression(FrameOffset)) {
6511 reportParseError("expected frame offset value");
6512 return false;
6513 }
6514
Jim Grosbach13760bd2015-05-30 01:25:56 +00006515 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006516 reportParseError("frame offset not an absolute expression");
6517 return false;
6518 }
6519
6520 // If this is not the end of the statement, report an error.
6521 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6522 reportParseError("unexpected token, expected end of statement");
6523 return false;
6524 }
6525
6526 if (IDVal == ".mask")
6527 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6528 else
6529 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006530 return false;
6531 }
6532
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006533 if (IDVal == ".nan")
6534 return parseDirectiveNaN();
6535
Jack Carter07c818d2013-01-25 01:31:34 +00006536 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006537 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006538 return false;
6539 }
6540
Rafael Espindolab59fb732014-03-28 18:50:26 +00006541 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006542 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006543 return false;
6544 }
6545
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006546 if (IDVal == ".dtprelword") {
6547 parseDirectiveDtpRelWord();
6548 return false;
6549 }
6550
6551 if (IDVal == ".dtpreldword") {
6552 parseDirectiveDtpRelDWord();
6553 return false;
6554 }
6555
6556 if (IDVal == ".tprelword") {
6557 parseDirectiveTpRelWord();
6558 return false;
6559 }
6560
6561 if (IDVal == ".tpreldword") {
6562 parseDirectiveTpRelDWord();
6563 return false;
6564 }
6565
Jack Carter07c818d2013-01-25 01:31:34 +00006566 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006567 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006568 return false;
6569 }
6570
Scott Egertond1aeb052016-02-15 16:11:51 +00006571 if (IDVal == ".hword") {
6572 parseDataDirective(2, DirectiveID.getLoc());
6573 return false;
6574 }
6575
Nirav Dave996fc132016-05-05 14:15:46 +00006576 if (IDVal == ".option") {
6577 parseDirectiveOption();
6578 return false;
6579 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006580
6581 if (IDVal == ".abicalls") {
6582 getTargetStreamer().emitDirectiveAbiCalls();
6583 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006584 Error(Parser.getTok().getLoc(),
6585 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006586 }
6587 return false;
6588 }
6589
Nirav Dave996fc132016-05-05 14:15:46 +00006590 if (IDVal == ".cpsetup") {
6591 parseDirectiveCPSetup();
6592 return false;
6593 }
6594 if (IDVal == ".cpreturn") {
6595 parseDirectiveCPReturn();
6596 return false;
6597 }
6598 if (IDVal == ".module") {
6599 parseDirectiveModule();
6600 return false;
6601 }
6602 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6603 parseInternalDirectiveReallowModule();
6604 return false;
6605 }
6606 if (IDVal == ".insn") {
6607 parseInsnDirective();
6608 return false;
6609 }
6610 if (IDVal == ".sbss") {
6611 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6612 return false;
6613 }
6614 if (IDVal == ".sdata") {
6615 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6616 return false;
6617 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006618
Rafael Espindola870c4e92012-01-11 03:56:41 +00006619 return true;
6620}
6621
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006622bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6623 // If this is not the end of the statement, report an error.
6624 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6625 reportParseError("unexpected token, expected end of statement");
6626 return false;
6627 }
6628
6629 getTargetStreamer().reallowModuleDirective();
6630
6631 getParser().Lex(); // Eat EndOfStatement token.
6632 return false;
6633}
6634
Rafael Espindola870c4e92012-01-11 03:56:41 +00006635extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00006636 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
6637 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
6638 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
6639 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00006640}
Jack Carterb4dbc172012-09-05 23:34:03 +00006641
6642#define GET_REGISTER_MATCHER
6643#define GET_MATCHER_IMPLEMENTATION
6644#include "MipsGenAsmMatcher.inc"