blob: 00e0b3b7e00a5f0cc2f57f271d310fe785d2dfd9 [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"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000017#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000021#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/MC/MCParser/MCAsmLexer.h"
23#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000024#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000025#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000026#include "llvm/MC/MCStreamer.h"
27#include "llvm/MC/MCSubtargetInfo.h"
28#include "llvm/MC/MCSymbol.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000029#include "llvm/Support/Debug.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000030#include "llvm/Support/ELF.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000031#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000032#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000033#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000034#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000035#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000036
37using namespace llvm;
38
Chandler Carruthe96dd892014-04-21 22:55:11 +000039#define DEBUG_TYPE "mips-asm-parser"
40
Joey Gouly0e76fa72013-09-12 10:28:05 +000041namespace llvm {
42class MCInstrInfo;
43}
44
Rafael Espindola870c4e92012-01-11 03:56:41 +000045namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000046class MipsAssemblerOptions {
47public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000048 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000049 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000050
Toma Tabacu9db22db2014-09-09 10:15:38 +000051 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000052 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000053 Reorder = Opts->isReorder();
54 Macro = Opts->isMacro();
55 Features = Opts->getFeatures();
56 }
57
Toma Tabacub19cf202015-04-27 13:12:59 +000058 unsigned getATRegIndex() const { return ATReg; }
59 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000060 if (Reg > 31)
61 return false;
62
63 ATReg = Reg;
64 return true;
65 }
Jack Carter0b744b32012-10-04 02:29:46 +000066
Toma Tabacu9db22db2014-09-09 10:15:38 +000067 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000068 void setReorder() { Reorder = true; }
69 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000070
Toma Tabacu9db22db2014-09-09 10:15:38 +000071 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000072 void setMacro() { Macro = true; }
73 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000074
Toma Tabacu465acfd2015-06-09 13:33:26 +000075 const FeatureBitset &getFeatures() const { return Features; }
76 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000077
Daniel Sandersf0df2212014-08-04 12:20:00 +000078 // Set of features that are either architecture features or referenced
79 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
80 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
81 // The reason we need this mask is explained in the selectArch function.
82 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000083 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000084
Jack Carter0b744b32012-10-04 02:29:46 +000085private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000086 unsigned ATReg;
87 bool Reorder;
88 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000089 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000090};
91}
92
Michael Kupersteindb0712f2015-05-26 10:47:10 +000093const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
94 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
95 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
96 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
97 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
98 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
99 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
100 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
101 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
102};
103
Jack Carter0b744b32012-10-04 02:29:46 +0000104namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000105class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000106 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000107 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000108 return static_cast<MipsTargetStreamer &>(TS);
109 }
110
Eric Christophera5762812015-01-26 17:33:46 +0000111 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000112 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000113 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
114 // nullptr, which indicates that no function is currently
115 // selected. This usually happens after an '.end func'
116 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000117 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000118 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000119 bool IsCpRestoreSet;
120 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000121 unsigned CpSaveLocation;
122 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
123 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000124
Daniel Sandersef638fe2014-10-03 15:37:37 +0000125 // Print a warning along with its fix-it message at the given range.
126 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
127 SMRange Range, bool ShowColors = true);
128
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000129#define GET_ASSEMBLER_HEADER
130#include "MipsGenAsmMatcher.inc"
131
Matheus Almeida595fcab2014-06-11 15:05:56 +0000132 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
133
Chad Rosier49963552012-10-13 00:26:04 +0000134 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000135 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000136 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000137 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000138
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000139 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000140 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000141
Toma Tabacu13964452014-09-04 13:23:44 +0000142 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000143
Toma Tabacu13964452014-09-04 13:23:44 +0000144 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000145
David Blaikie960ea3f2014-06-08 16:18:35 +0000146 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
147 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000148
Craig Topper56c590a2014-04-29 07:58:02 +0000149 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000150
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000151 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
152 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000153 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000154 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000155 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
156 SMLoc S);
157 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
158 OperandMatchResultTy parseImm(OperandVector &Operands);
159 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
160 OperandMatchResultTy parseInvNum(OperandVector &Operands);
161 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
162 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
163 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
164 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000165
David Blaikie960ea3f2014-06-08 16:18:35 +0000166 bool searchSymbolAlias(OperandVector &Operands);
167
Toma Tabacu13964452014-09-04 13:23:44 +0000168 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000169
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000170 enum MacroExpanderResultTy {
171 MER_NotAMacro,
172 MER_Success,
173 MER_Fail,
174 };
Jack Carter30a59822012-10-04 04:03:53 +0000175
Matheus Almeida3813d572014-06-19 14:39:14 +0000176 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000177 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
178 MCStreamer &Out,
179 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000180
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000181 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
182 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000183
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000184 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000185 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000186 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000187
Toma Tabacuf712ede2015-06-17 14:31:51 +0000188 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
189 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000190 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000191
Toma Tabacu00e98672015-05-01 12:19:27 +0000192 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000193 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000194
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000195 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
196 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000197 SMLoc IDLoc, MCStreamer &Out,
198 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000199
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000200 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
201 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000202
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000203 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000204 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
205
206 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
207 const MCSubtargetInfo *STI, bool IsImmOpnd);
208
209 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
210 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000211
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000212 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
213 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000214
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000215 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
216 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000217
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
219 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000220
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000221 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
222 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000223
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000224 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
225 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000226 const bool Signed);
227
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000228 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000229 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000230
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000231 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
232 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000233
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000234 bool expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000236
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000237 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000238 MCStreamer &Out, const MCSubtargetInfo *STI);
239 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
240 const MCSubtargetInfo *STI);
241 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
242 const MCSubtargetInfo *STI);
243 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000245
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000246 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000248
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000249 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000250 MCStreamer &Out, const MCSubtargetInfo *STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000251
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000252 bool reportParseError(Twine ErrorMsg);
253 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000254
Jack Carterb5cf5902013-04-17 00:18:04 +0000255 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000256 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000257
Vladimir Medic4c299852013-11-06 11:27:05 +0000258 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
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();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000299 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000300 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000301 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
302 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000303
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000304 bool parseInternalDirectiveReallowModule();
305
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000306 bool eatComma(StringRef ErrorStr);
307
Jack Carter1ac53222013-02-20 23:11:17 +0000308 int matchCPURegisterName(StringRef Symbol);
309
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000310 int matchHWRegsRegisterName(StringRef Symbol);
311
Jack Carter873c7242013-01-12 01:03:14 +0000312 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000313
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000314 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000315
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000316 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000317
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000318 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000319
Jack Carter5dc8ac92013-09-25 23:50:44 +0000320 int matchMSA128RegisterName(StringRef Name);
321
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000322 int matchMSA128CtrlRegisterName(StringRef Name);
323
Jack Carterd0bd6422013-04-18 00:41:53 +0000324 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000325
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000326 unsigned getGPR(int RegNo);
327
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,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000404#define GET_OPERAND_DIAGNOSTIC_TYPES
405#include "MipsGenAsmMatcher.inc"
406#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000407 };
408
Akira Hatanakab11ef082015-11-14 06:35:56 +0000409 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000410 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000411 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000412 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
413 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000414 MCAsmParserExtension::Initialize(parser);
415
Toma Tabacu11e14a92015-04-21 11:50:52 +0000416 parser.addAliasForDirective(".asciiz", ".asciz");
417
Jack Carterb4dbc172012-09-05 23:34:03 +0000418 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000419 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000420
Toma Tabacu9db22db2014-09-09 10:15:38 +0000421 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000422 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000423 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000424
Toma Tabacu9db22db2014-09-09 10:15:38 +0000425 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000426 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000427 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000428
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000429 getTargetStreamer().updateABIInfo(*this);
430
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000431 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000432 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000433
434 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000435
Rafael Espindola699281c2016-05-18 11:58:50 +0000436 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000437
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000438 IsCpRestoreSet = false;
439 CpRestoreOffset = -1;
440
Daniel Sanders50f17232015-09-15 16:17:27 +0000441 Triple TheTriple(sti.getTargetTriple());
442 if ((TheTriple.getArch() == Triple::mips) ||
443 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000444 IsLittleEndian = false;
445 else
446 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000447 }
448
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000449 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
450 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
451
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000452 bool isGP64bit() const {
453 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
454 }
455 bool isFP64bit() const {
456 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
457 }
Eric Christophera5762812015-01-26 17:33:46 +0000458 const MipsABIInfo &getABI() const { return ABI; }
459 bool isABI_N32() const { return ABI.IsN32(); }
460 bool isABI_N64() const { return ABI.IsN64(); }
461 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000462 bool isABI_FPXX() const {
463 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
464 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000465
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000466 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000467 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000468 }
469
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000470 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000471 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000472 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000473 bool hasMips1() const {
474 return getSTI().getFeatureBits()[Mips::FeatureMips1];
475 }
476 bool hasMips2() const {
477 return getSTI().getFeatureBits()[Mips::FeatureMips2];
478 }
479 bool hasMips3() const {
480 return getSTI().getFeatureBits()[Mips::FeatureMips3];
481 }
482 bool hasMips4() const {
483 return getSTI().getFeatureBits()[Mips::FeatureMips4];
484 }
485 bool hasMips5() const {
486 return getSTI().getFeatureBits()[Mips::FeatureMips5];
487 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000488 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000489 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000490 }
491 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000492 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000493 }
494 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000495 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000496 }
497 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000498 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000499 }
Daniel Sanders17793142015-02-18 16:24:50 +0000500 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000501 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000502 }
503 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000504 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000505 }
506 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000507 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000508 }
509 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000510 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000511 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000512 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000513 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000514 }
515 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000516 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000517 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000518
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000519 bool hasDSP() const {
520 return getSTI().getFeatureBits()[Mips::FeatureDSP];
521 }
522 bool hasDSPR2() const {
523 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
524 }
525 bool hasDSPR3() const {
526 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
527 }
528 bool hasMSA() const {
529 return getSTI().getFeatureBits()[Mips::FeatureMSA];
530 }
Kai Nackee0245392015-01-27 19:11:28 +0000531 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000532 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000533 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000534
Daniel Sandersa6994442015-08-18 12:33:54 +0000535 bool inPicMode() {
536 return IsPicEnabled;
537 }
538
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000539 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000540 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000541 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000542
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000543 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000545 }
546
Eric Christophere8ae3e32015-05-07 23:10:21 +0000547 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000548 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000549 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000550
Toma Tabacud9d344b2015-04-27 14:05:04 +0000551 /// Warn if RegIndex is the same as the current AT.
552 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000553
554 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000555
556 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000557};
558}
559
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000560namespace {
561
562/// MipsOperand - Instances of this class represent a parsed Mips machine
563/// instruction.
564class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000565public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000566 /// Broad categories of register classes
567 /// The exact class is finalized by the render method.
568 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000569 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000570 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000571 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000572 RegKind_FCC = 4, /// FCC
573 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
574 RegKind_MSACtrl = 16, /// MSA control registers
575 RegKind_COP2 = 32, /// COP2
576 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
577 /// context).
578 RegKind_CCR = 128, /// CCR
579 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000580 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000581 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000582 /// Potentially any (e.g. $1)
583 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
584 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000585 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000586 };
587
588private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000589 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000590 k_Immediate, /// An immediate (possibly involving symbol references)
591 k_Memory, /// Base + Offset Memory Address
592 k_PhysRegister, /// A physical register from the Mips namespace
593 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000594 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000595 k_RegList, /// A physical register list
596 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000597 } Kind;
598
David Blaikie960ea3f2014-06-08 16:18:35 +0000599public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000600 MipsOperand(KindTy K, MipsAsmParser &Parser)
601 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
602
David Blaikie960ea3f2014-06-08 16:18:35 +0000603private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000604 /// For diagnostics, and checking the assembler temporary
605 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000606
Eric Christopher8996c5d2013-03-15 00:42:55 +0000607 struct Token {
608 const char *Data;
609 unsigned Length;
610 };
611
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000612 struct PhysRegOp {
613 unsigned Num; /// Register Number
614 };
615
616 struct RegIdxOp {
617 unsigned Index; /// Index into the register class
618 RegKind Kind; /// Bitfield of the kinds it could possibly be
619 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000620 };
621
622 struct ImmOp {
623 const MCExpr *Val;
624 };
625
626 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000627 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000628 const MCExpr *Off;
629 };
630
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000631 struct RegListOp {
632 SmallVector<unsigned, 10> *List;
633 };
634
Jack Carterb4dbc172012-09-05 23:34:03 +0000635 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000636 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000637 struct PhysRegOp PhysReg;
638 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000639 struct ImmOp Imm;
640 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000641 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000642 };
643
644 SMLoc StartLoc, EndLoc;
645
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000646 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000647 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
648 const MCRegisterInfo *RegInfo,
649 SMLoc S, SMLoc E,
650 MipsAsmParser &Parser) {
651 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000652 Op->RegIdx.Index = Index;
653 Op->RegIdx.RegInfo = RegInfo;
654 Op->RegIdx.Kind = RegKind;
655 Op->StartLoc = S;
656 Op->EndLoc = E;
657 return Op;
658 }
659
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000660public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000661 /// Coerce the register to GPR32 and return the real register for the current
662 /// target.
663 unsigned getGPR32Reg() const {
664 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000665 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000666 unsigned ClassID = Mips::GPR32RegClassID;
667 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000668 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000669
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000670 /// Coerce the register to GPR32 and return the real register for the current
671 /// target.
672 unsigned getGPRMM16Reg() const {
673 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
674 unsigned ClassID = Mips::GPR32RegClassID;
675 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
676 }
677
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000678 /// Coerce the register to GPR64 and return the real register for the current
679 /// target.
680 unsigned getGPR64Reg() const {
681 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
682 unsigned ClassID = Mips::GPR64RegClassID;
683 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000684 }
685
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000686private:
687 /// Coerce the register to AFGR64 and return the real register for the current
688 /// target.
689 unsigned getAFGR64Reg() const {
690 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
691 if (RegIdx.Index % 2 != 0)
692 AsmParser.Warning(StartLoc, "Float register should be even.");
693 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
694 .getRegister(RegIdx.Index / 2);
695 }
696
697 /// Coerce the register to FGR64 and return the real register for the current
698 /// target.
699 unsigned getFGR64Reg() const {
700 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
701 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
702 .getRegister(RegIdx.Index);
703 }
704
705 /// Coerce the register to FGR32 and return the real register for the current
706 /// target.
707 unsigned getFGR32Reg() const {
708 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
709 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
710 .getRegister(RegIdx.Index);
711 }
712
713 /// Coerce the register to FGRH32 and return the real register for the current
714 /// target.
715 unsigned getFGRH32Reg() const {
716 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
717 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
718 .getRegister(RegIdx.Index);
719 }
720
721 /// Coerce the register to FCC and return the real register for the current
722 /// target.
723 unsigned getFCCReg() const {
724 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
725 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
726 .getRegister(RegIdx.Index);
727 }
728
729 /// Coerce the register to MSA128 and return the real register for the current
730 /// target.
731 unsigned getMSA128Reg() const {
732 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
733 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
734 // identical
735 unsigned ClassID = Mips::MSA128BRegClassID;
736 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
737 }
738
739 /// Coerce the register to MSACtrl and return the real register for the
740 /// current target.
741 unsigned getMSACtrlReg() const {
742 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
743 unsigned ClassID = Mips::MSACtrlRegClassID;
744 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
745 }
746
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000747 /// Coerce the register to COP0 and return the real register for the
748 /// current target.
749 unsigned getCOP0Reg() const {
750 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
751 unsigned ClassID = Mips::COP0RegClassID;
752 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
753 }
754
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000755 /// Coerce the register to COP2 and return the real register for the
756 /// current target.
757 unsigned getCOP2Reg() const {
758 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
759 unsigned ClassID = Mips::COP2RegClassID;
760 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
761 }
762
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000763 /// Coerce the register to COP3 and return the real register for the
764 /// current target.
765 unsigned getCOP3Reg() const {
766 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
767 unsigned ClassID = Mips::COP3RegClassID;
768 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
769 }
770
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000771 /// Coerce the register to ACC64DSP and return the real register for the
772 /// current target.
773 unsigned getACC64DSPReg() const {
774 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
775 unsigned ClassID = Mips::ACC64DSPRegClassID;
776 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
777 }
778
779 /// Coerce the register to HI32DSP and return the real register for the
780 /// current target.
781 unsigned getHI32DSPReg() const {
782 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
783 unsigned ClassID = Mips::HI32DSPRegClassID;
784 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
785 }
786
787 /// Coerce the register to LO32DSP and return the real register for the
788 /// current target.
789 unsigned getLO32DSPReg() const {
790 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
791 unsigned ClassID = Mips::LO32DSPRegClassID;
792 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
793 }
794
795 /// Coerce the register to CCR and return the real register for the
796 /// current target.
797 unsigned getCCRReg() const {
798 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
799 unsigned ClassID = Mips::CCRRegClassID;
800 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
801 }
802
803 /// Coerce the register to HWRegs and return the real register for the
804 /// current target.
805 unsigned getHWRegsReg() const {
806 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
807 unsigned ClassID = Mips::HWRegsRegClassID;
808 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
809 }
810
811public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000812 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000813 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000814 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000815 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000816 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000817 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000818 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000819 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000820 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000821
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000822 void addRegOperands(MCInst &Inst, unsigned N) const {
823 llvm_unreachable("Use a custom parser instead");
824 }
825
Daniel Sanders21bce302014-04-01 12:35:23 +0000826 /// Render the operand to an MCInst as a GPR32
827 /// Asserts if the wrong number of operands are requested, or the operand
828 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000829 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
830 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000831 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000832 }
833
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000834 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
835 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000836 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000837 }
838
Jozef Kolek1904fa22014-11-24 14:25:53 +0000839 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
840 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000841 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000842 }
843
Zoran Jovanovic41688672015-02-10 16:36:20 +0000844 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
845 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000846 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000847 }
848
Daniel Sanders21bce302014-04-01 12:35:23 +0000849 /// Render the operand to an MCInst as a GPR64
850 /// Asserts if the wrong number of operands are requested, or the operand
851 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000852 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
853 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000854 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000855 }
856
857 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
858 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000859 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000860 }
861
862 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
863 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000864 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000865 }
866
867 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
868 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000869 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000870 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000871 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000872 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
873 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000874 }
875
876 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
877 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000878 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000879 }
880
881 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
882 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000883 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000884 }
885
886 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
887 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000888 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000889 }
890
891 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
892 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000893 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000894 }
895
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000896 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
897 assert(N == 1 && "Invalid number of operands!");
898 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
899 }
900
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000901 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
902 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000903 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000904 }
905
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000906 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
907 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000908 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000909 }
910
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000911 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
912 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000913 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000914 }
915
916 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
917 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000918 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000919 }
920
921 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
922 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000923 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000924 }
925
926 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
927 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000928 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000929 }
930
931 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
932 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000933 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000934 }
935
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000936 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000937 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
938 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000939 uint64_t Imm = getConstantImm() - Offset;
940 Imm &= (1 << Bits) - 1;
941 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000942 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000943 Inst.addOperand(MCOperand::createImm(Imm));
944 }
945
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000946 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +0000947 void addSImmOperands(MCInst &Inst, unsigned N) const {
948 if (isImm() && !isConstantImm()) {
949 addExpr(Inst, getImm());
950 return;
951 }
952 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
953 }
954
955 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000956 void addUImmOperands(MCInst &Inst, unsigned N) const {
957 if (isImm() && !isConstantImm()) {
958 addExpr(Inst, getImm());
959 return;
960 }
961 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
962 }
963
Daniel Sanders78e89022016-03-11 11:37:50 +0000964 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
965 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
966 assert(N == 1 && "Invalid number of operands!");
967 int64_t Imm = getConstantImm() - Offset;
968 Imm = SignExtend64<Bits>(Imm);
969 Imm += Offset;
970 Imm += AdjustOffset;
971 Inst.addOperand(MCOperand::createImm(Imm));
972 }
973
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000974 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000975 assert(N == 1 && "Invalid number of operands!");
976 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000977 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000978 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000979
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000980 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000981 assert(N == 2 && "Invalid number of operands!");
982
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000983 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
984 ? getMemBase()->getGPR64Reg()
985 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000986
987 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000988 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000989 }
990
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000991 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
992 assert(N == 2 && "Invalid number of operands!");
993
Jim Grosbache9119e42015-05-13 18:37:00 +0000994 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000995
996 const MCExpr *Expr = getMemOff();
997 addExpr(Inst, Expr);
998 }
999
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001000 void addRegListOperands(MCInst &Inst, unsigned N) const {
1001 assert(N == 1 && "Invalid number of operands!");
1002
1003 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001004 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001005 }
1006
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001007 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1008 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001009 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001010 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001011 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1012 Inst.addOperand(MCOperand::createReg(
1013 RegIdx.RegInfo->getRegClass(
1014 AsmParser.getABI().AreGprs64bit()
1015 ? Mips::GPR64RegClassID
1016 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1017 Inst.addOperand(MCOperand::createReg(
1018 RegIdx.RegInfo->getRegClass(
1019 AsmParser.getABI().AreGprs64bit()
1020 ? Mips::GPR64RegClassID
1021 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001022 }
1023
Zoran Jovanovic41688672015-02-10 16:36:20 +00001024 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1025 assert(N == 2 && "Invalid number of operands!");
1026 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001027 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001028 }
1029
Craig Topper56c590a2014-04-29 07:58:02 +00001030 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001031 // As a special case until we sort out the definition of div/divu, pretend
1032 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1033 if (isGPRAsmReg() && RegIdx.Index == 0)
1034 return true;
1035
1036 return Kind == k_PhysRegister;
1037 }
1038 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001039 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001040 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +00001041 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001042 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001043 bool isConstantImmz() const {
1044 return isConstantImm() && getConstantImm() == 0;
1045 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001046 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1047 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1048 }
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001049 template <unsigned Bits> bool isSImm() const {
1050 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1051 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001052 template <unsigned Bits> bool isUImm() const {
1053 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1054 }
1055 template <unsigned Bits> bool isAnyImm() const {
1056 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1057 isUInt<Bits>(getConstantImm()))
1058 : isImm();
1059 }
Daniel Sanders78e89022016-03-11 11:37:50 +00001060 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1061 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001062 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001063 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1064 return isConstantImm() && getConstantImm() >= Bottom &&
1065 getConstantImm() <= Top;
1066 }
Craig Topper56c590a2014-04-29 07:58:02 +00001067 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001068 // Note: It's not possible to pretend that other operand kinds are tokens.
1069 // The matcher emitter checks tokens first.
1070 return Kind == k_Token;
1071 }
Craig Topper56c590a2014-04-29 07:58:02 +00001072 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001073 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001074 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001075 }
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001076 template <unsigned Bits, unsigned ShiftAmount = 0>
1077 bool isMemWithSimmOffset() const {
1078 return isMem() && isConstantMemOff() &&
1079 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff()) &&
1080 getMemBase()->isGPRAsmReg();
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001081 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001082 bool isMemWithGRPMM16Base() const {
1083 return isMem() && getMemBase()->isMM16AsmReg();
1084 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001085 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1086 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1087 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1088 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001089 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1090 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1091 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1092 && (getMemBase()->getGPR32Reg() == Mips::SP);
1093 }
Daniel Sanderse473dc92016-05-09 13:38:25 +00001094 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1095 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1096 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1097 && (getMemBase()->getGPR32Reg() == Mips::GP);
1098 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001099 template <unsigned Bits, unsigned ShiftLeftAmount>
1100 bool isScaledUImm() const {
1101 return isConstantImm() &&
1102 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001103 }
Daniel Sanders97297772016-03-22 14:40:00 +00001104 template <unsigned Bits, unsigned ShiftLeftAmount>
1105 bool isScaledSImm() const {
1106 return isConstantImm() &&
1107 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
1108 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001109 bool isRegList16() const {
1110 if (!isRegList())
1111 return false;
1112
1113 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001114 if (Size < 2 || Size > 5)
1115 return false;
1116
1117 unsigned R0 = RegList.List->front();
1118 unsigned R1 = RegList.List->back();
1119 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1120 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001121 return false;
1122
1123 int PrevReg = *RegList.List->begin();
1124 for (int i = 1; i < Size - 1; i++) {
1125 int Reg = (*(RegList.List))[i];
1126 if ( Reg != PrevReg + 1)
1127 return false;
1128 PrevReg = Reg;
1129 }
1130
1131 return true;
1132 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001133 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001134 bool isLSAImm() const {
1135 if (!isConstantImm())
1136 return false;
1137 int64_t Val = getConstantImm();
1138 return 1 <= Val && Val <= 4;
1139 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001140 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001141 bool isMovePRegPair() const {
1142 if (Kind != k_RegList || RegList.List->size() != 2)
1143 return false;
1144
1145 unsigned R0 = RegList.List->front();
1146 unsigned R1 = RegList.List->back();
1147
1148 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1149 (R0 == Mips::A1 && R1 == Mips::A3) ||
1150 (R0 == Mips::A2 && R1 == Mips::A3) ||
1151 (R0 == Mips::A0 && R1 == Mips::S5) ||
1152 (R0 == Mips::A0 && R1 == Mips::S6) ||
1153 (R0 == Mips::A0 && R1 == Mips::A1) ||
1154 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001155 (R0 == Mips::A0 && R1 == Mips::A3) ||
1156 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1157 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1158 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1159 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1160 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1161 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1162 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1163 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001164 return true;
1165
1166 return false;
1167 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001168
1169 StringRef getToken() const {
1170 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001171 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001172 }
Zlatko Buljanba553a62016-05-09 08:07:28 +00001173 bool isRegPair() const {
1174 return Kind == k_RegPair && RegIdx.Index <= 30;
1175 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001176
Craig Topper56c590a2014-04-29 07:58:02 +00001177 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001178 // As a special case until we sort out the definition of div/divu, pretend
1179 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1180 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1181 RegIdx.Kind & RegKind_GPR)
1182 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001183
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001184 assert(Kind == k_PhysRegister && "Invalid access!");
1185 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001186 }
1187
Jack Carterb4dbc172012-09-05 23:34:03 +00001188 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001189 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001190 return Imm.Val;
1191 }
1192
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001193 int64_t getConstantImm() const {
1194 const MCExpr *Val = getImm();
1195 return static_cast<const MCConstantExpr *>(Val)->getValue();
1196 }
1197
1198 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001199 assert((Kind == k_Memory) && "Invalid access!");
1200 return Mem.Base;
1201 }
1202
1203 const MCExpr *getMemOff() const {
1204 assert((Kind == k_Memory) && "Invalid access!");
1205 return Mem.Off;
1206 }
1207
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001208 int64_t getConstantMemOff() const {
1209 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1210 }
1211
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001212 const SmallVectorImpl<unsigned> &getRegList() const {
1213 assert((Kind == k_RegList) && "Invalid access!");
1214 return *(RegList.List);
1215 }
1216
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001217 unsigned getRegPair() const {
1218 assert((Kind == k_RegPair) && "Invalid access!");
1219 return RegIdx.Index;
1220 }
1221
David Blaikie960ea3f2014-06-08 16:18:35 +00001222 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1223 MipsAsmParser &Parser) {
1224 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001225 Op->Tok.Data = Str.data();
1226 Op->Tok.Length = Str.size();
1227 Op->StartLoc = S;
1228 Op->EndLoc = S;
1229 return Op;
1230 }
1231
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001232 /// Create a numeric register (e.g. $1). The exact register remains
1233 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001234 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001235 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001236 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001237 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001238 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001239 }
1240
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001241 /// Create a register that is definitely a GPR.
1242 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001243 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001244 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001245 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001246 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001247 }
1248
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001249 /// Create a register that is definitely a FGR.
1250 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001251 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001252 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001253 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001254 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1255 }
1256
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001257 /// Create a register that is definitely a HWReg.
1258 /// This is typically only used for named registers such as $hwr_cpunum.
1259 static std::unique_ptr<MipsOperand>
1260 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1261 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1262 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1263 }
1264
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001265 /// Create a register that is definitely an FCC.
1266 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001267 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001268 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001269 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001270 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1271 }
1272
1273 /// Create a register that is definitely an ACC.
1274 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001275 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001276 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001277 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001278 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1279 }
1280
1281 /// Create a register that is definitely an MSA128.
1282 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001283 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001284 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001285 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001286 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1287 }
1288
1289 /// Create a register that is definitely an MSACtrl.
1290 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001291 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001292 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001293 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001294 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1295 }
1296
David Blaikie960ea3f2014-06-08 16:18:35 +00001297 static std::unique_ptr<MipsOperand>
1298 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1299 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001300 Op->Imm.Val = Val;
1301 Op->StartLoc = S;
1302 Op->EndLoc = E;
1303 return Op;
1304 }
1305
David Blaikie960ea3f2014-06-08 16:18:35 +00001306 static std::unique_ptr<MipsOperand>
1307 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1308 SMLoc E, MipsAsmParser &Parser) {
1309 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1310 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001311 Op->Mem.Off = Off;
1312 Op->StartLoc = S;
1313 Op->EndLoc = E;
1314 return Op;
1315 }
1316
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001317 static std::unique_ptr<MipsOperand>
1318 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1319 MipsAsmParser &Parser) {
1320 assert (Regs.size() > 0 && "Empty list not allowed");
1321
1322 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001323 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001324 Op->StartLoc = StartLoc;
1325 Op->EndLoc = EndLoc;
1326 return Op;
1327 }
1328
Daniel Sandersd044e492016-05-09 13:10:57 +00001329 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1330 SMLoc S, SMLoc E,
1331 MipsAsmParser &Parser) {
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001332 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001333 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001334 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1335 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001336 Op->StartLoc = S;
1337 Op->EndLoc = E;
1338 return Op;
1339 }
1340
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001341 bool isGPRAsmReg() const {
1342 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001343 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001344 bool isMM16AsmReg() const {
1345 if (!(isRegIdx() && RegIdx.Kind))
1346 return false;
1347 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1348 || RegIdx.Index == 16 || RegIdx.Index == 17);
1349 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001350 bool isMM16AsmRegZero() const {
1351 if (!(isRegIdx() && RegIdx.Kind))
1352 return false;
1353 return (RegIdx.Index == 0 ||
1354 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1355 RegIdx.Index == 17);
1356 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001357 bool isMM16AsmRegMoveP() const {
1358 if (!(isRegIdx() && RegIdx.Kind))
1359 return false;
1360 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1361 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1362 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001363 bool isFGRAsmReg() const {
1364 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1365 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001366 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001367 bool isHWRegsAsmReg() const {
1368 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001369 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001370 bool isCCRAsmReg() const {
1371 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001372 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001373 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001374 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1375 return false;
1376 if (!AsmParser.hasEightFccRegisters())
1377 return RegIdx.Index == 0;
1378 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001379 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001380 bool isACCAsmReg() const {
1381 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001382 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001383 bool isCOP0AsmReg() const {
1384 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1385 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001386 bool isCOP2AsmReg() const {
1387 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001388 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001389 bool isCOP3AsmReg() const {
1390 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1391 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001392 bool isMSA128AsmReg() const {
1393 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001394 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001395 bool isMSACtrlAsmReg() const {
1396 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001397 }
1398
Jack Carterb4dbc172012-09-05 23:34:03 +00001399 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001400 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001401 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001402 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001403
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001404 virtual ~MipsOperand() {
1405 switch (Kind) {
1406 case k_Immediate:
1407 break;
1408 case k_Memory:
1409 delete Mem.Base;
1410 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001411 case k_RegList:
1412 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001413 case k_PhysRegister:
1414 case k_RegisterIndex:
1415 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001416 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001417 break;
1418 }
1419 }
1420
Craig Topper56c590a2014-04-29 07:58:02 +00001421 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001422 switch (Kind) {
1423 case k_Immediate:
1424 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001425 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001426 OS << ">";
1427 break;
1428 case k_Memory:
1429 OS << "Mem<";
1430 Mem.Base->print(OS);
1431 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001432 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001433 OS << ">";
1434 break;
1435 case k_PhysRegister:
1436 OS << "PhysReg<" << PhysReg.Num << ">";
1437 break;
1438 case k_RegisterIndex:
1439 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1440 break;
1441 case k_Token:
1442 OS << Tok.Data;
1443 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001444 case k_RegList:
1445 OS << "RegList< ";
1446 for (auto Reg : (*RegList.List))
1447 OS << Reg << " ";
1448 OS << ">";
1449 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001450 case k_RegPair:
1451 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1452 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001453 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001454 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001455}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001456} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001457
Jack Carter9e65aa32013-03-22 00:05:30 +00001458namespace llvm {
1459extern const MCInstrDesc MipsInsts[];
1460}
1461static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1462 return MipsInsts[Opcode];
1463}
1464
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001465static bool hasShortDelaySlot(unsigned Opcode) {
1466 switch (Opcode) {
1467 case Mips::JALS_MM:
1468 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001469 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001470 case Mips::BGEZALS_MM:
1471 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001472 return true;
1473 default:
1474 return false;
1475 }
1476}
1477
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001478static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1479 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1480 return &SRExpr->getSymbol();
1481 }
1482
1483 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1484 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1485 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1486
1487 if (LHSSym)
1488 return LHSSym;
1489
1490 if (RHSSym)
1491 return RHSSym;
1492
1493 return nullptr;
1494 }
1495
1496 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1497 return getSingleMCSymbol(UExpr->getSubExpr());
1498
1499 return nullptr;
1500}
1501
1502static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1503 if (isa<MCSymbolRefExpr>(Expr))
1504 return 1;
1505
1506 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1507 return countMCSymbolRefExpr(BExpr->getLHS()) +
1508 countMCSymbolRefExpr(BExpr->getRHS());
1509
1510 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1511 return countMCSymbolRefExpr(UExpr->getSubExpr());
1512
1513 return 0;
1514}
1515
Jack Carter9e65aa32013-03-22 00:05:30 +00001516bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001517 MCStreamer &Out,
1518 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001519 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001520 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001521 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001522
Jack Carter9e65aa32013-03-22 00:05:30 +00001523 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001524
1525 if (MCID.isBranch() || MCID.isCall()) {
1526 const unsigned Opcode = Inst.getOpcode();
1527 MCOperand Offset;
1528
1529 switch (Opcode) {
1530 default:
1531 break;
Kai Nackee0245392015-01-27 19:11:28 +00001532 case Mips::BBIT0:
1533 case Mips::BBIT032:
1534 case Mips::BBIT1:
1535 case Mips::BBIT132:
1536 assert(hasCnMips() && "instruction only valid for octeon cpus");
1537 // Fall through
1538
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001539 case Mips::BEQ:
1540 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001541 case Mips::BEQ_MM:
1542 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001543 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001544 Offset = Inst.getOperand(2);
1545 if (!Offset.isImm())
1546 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001547 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001548 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001549 if (OffsetToAlignment(Offset.getImm(),
1550 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001551 return Error(IDLoc, "branch to misaligned address");
1552 break;
1553 case Mips::BGEZ:
1554 case Mips::BGTZ:
1555 case Mips::BLEZ:
1556 case Mips::BLTZ:
1557 case Mips::BGEZAL:
1558 case Mips::BLTZAL:
1559 case Mips::BC1F:
1560 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001561 case Mips::BGEZ_MM:
1562 case Mips::BGTZ_MM:
1563 case Mips::BLEZ_MM:
1564 case Mips::BLTZ_MM:
1565 case Mips::BGEZAL_MM:
1566 case Mips::BLTZAL_MM:
1567 case Mips::BC1F_MM:
1568 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001569 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001570 Offset = Inst.getOperand(1);
1571 if (!Offset.isImm())
1572 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001573 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001574 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001575 if (OffsetToAlignment(Offset.getImm(),
1576 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001577 return Error(IDLoc, "branch to misaligned address");
1578 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001579 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001580 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001581 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001582 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001583 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1584 Offset = Inst.getOperand(1);
1585 if (!Offset.isImm())
1586 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001587 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001588 return Error(IDLoc, "branch target out of range");
1589 if (OffsetToAlignment(Offset.getImm(), 2LL))
1590 return Error(IDLoc, "branch to misaligned address");
1591 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001592 }
1593 }
1594
Daniel Sandersa84989a2014-06-16 13:25:35 +00001595 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1596 // We still accept it but it is a normal nop.
1597 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1598 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1599 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1600 "nop instruction");
1601 }
1602
Kai Nackee0245392015-01-27 19:11:28 +00001603 if (hasCnMips()) {
1604 const unsigned Opcode = Inst.getOpcode();
1605 MCOperand Opnd;
1606 int Imm;
1607
1608 switch (Opcode) {
1609 default:
1610 break;
1611
1612 case Mips::BBIT0:
1613 case Mips::BBIT032:
1614 case Mips::BBIT1:
1615 case Mips::BBIT132:
1616 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1617 // The offset is handled above
1618 Opnd = Inst.getOperand(1);
1619 if (!Opnd.isImm())
1620 return Error(IDLoc, "expected immediate operand kind");
1621 Imm = Opnd.getImm();
1622 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1623 Opcode == Mips::BBIT1 ? 63 : 31))
1624 return Error(IDLoc, "immediate operand value out of range");
1625 if (Imm > 31) {
1626 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1627 : Mips::BBIT132);
1628 Inst.getOperand(1).setImm(Imm - 32);
1629 }
1630 break;
1631
Kai Nackee0245392015-01-27 19:11:28 +00001632 case Mips::SEQi:
1633 case Mips::SNEi:
1634 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1635 Opnd = Inst.getOperand(2);
1636 if (!Opnd.isImm())
1637 return Error(IDLoc, "expected immediate operand kind");
1638 Imm = Opnd.getImm();
1639 if (!isInt<10>(Imm))
1640 return Error(IDLoc, "immediate operand value out of range");
1641 break;
1642 }
1643 }
1644
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001645 // This expansion is not in a function called by tryExpandInstruction()
1646 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001647 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1648 inPicMode()) {
1649 warnIfNoMacro(IDLoc);
1650
1651 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1652
1653 // We can do this expansion if there's only 1 symbol in the argument
1654 // expression.
1655 if (countMCSymbolRefExpr(JalExpr) > 1)
1656 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1657
1658 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001659 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001660 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1661
1662 // FIXME: Add support for label+offset operands (currently causes an error).
1663 // FIXME: Add support for forward-declared local symbols.
1664 // FIXME: Add expansion for when the LargeGOT option is enabled.
1665 if (JalSym->isInSection() || JalSym->isTemporary()) {
1666 if (isABI_O32()) {
1667 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001668 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001669 // R_(MICRO)MIPS_GOT16 label
1670 // addiu $25, $25, 0
1671 // R_(MICRO)MIPS_LO16 label
1672 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001673 const MCExpr *Got16RelocExpr =
1674 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1675 const MCExpr *Lo16RelocExpr =
1676 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001677
Daniel Sandersa736b372016-04-29 13:33:12 +00001678 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1679 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1680 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1681 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001682 } else if (isABI_N32() || isABI_N64()) {
1683 // If it's a local symbol and the N32/N64 ABIs are being used,
1684 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001685 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001686 // R_(MICRO)MIPS_GOT_DISP label
1687 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001688 const MCExpr *GotDispRelocExpr =
1689 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001690
Daniel Sandersa736b372016-04-29 13:33:12 +00001691 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1692 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1693 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001694 }
1695 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001696 // If it's an external/weak symbol, we expand to:
1697 // lw/ld $25, 0($gp)
1698 // R_(MICRO)MIPS_CALL16 label
1699 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001700 const MCExpr *Call16RelocExpr =
1701 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001702
Daniel Sandersa736b372016-04-29 13:33:12 +00001703 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1704 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001705 }
1706
1707 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001708 if (IsCpRestoreSet && inMicroMipsMode())
1709 JalrInst.setOpcode(Mips::JALRS_MM);
1710 else
1711 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001712 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1713 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1714
1715 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1716 // This relocation is supposed to be an optimization hint for the linker
1717 // and is not necessary for correctness.
1718
1719 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001720 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001721 }
1722
Jack Carter9e65aa32013-03-22 00:05:30 +00001723 if (MCID.mayLoad() || MCID.mayStore()) {
1724 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001725 // reference or immediate we may have to expand instructions.
1726 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001727 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001728 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1729 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001730 MCOperand &Op = Inst.getOperand(i);
1731 if (Op.isImm()) {
1732 int MemOffset = Op.getImm();
1733 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001734 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001735 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001736 return false;
1737 }
1738 } else if (Op.isExpr()) {
1739 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001740 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001741 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001742 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001743 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001744 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001745 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001746 return false;
1747 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001748 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001749 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001750 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001751 }
1752 }
1753 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001754 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001755 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001756
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001757 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001758 if (MCID.mayLoad()) {
1759 // Try to create 16-bit GP relative load instruction.
1760 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1761 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1762 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1763 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1764 MCOperand &Op = Inst.getOperand(i);
1765 if (Op.isImm()) {
1766 int MemOffset = Op.getImm();
1767 MCOperand &DstReg = Inst.getOperand(0);
1768 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001769 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001770 getContext().getRegisterInfo()->getRegClass(
1771 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001772 (BaseReg.getReg() == Mips::GP ||
1773 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001774
Daniel Sandersa736b372016-04-29 13:33:12 +00001775 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1776 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001777 return false;
1778 }
1779 }
1780 }
1781 } // for
1782 } // if load
1783
1784 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1785
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001786 MCOperand Opnd;
1787 int Imm;
1788
1789 switch (Inst.getOpcode()) {
1790 default:
1791 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001792 case Mips::ADDIUSP_MM:
1793 Opnd = Inst.getOperand(0);
1794 if (!Opnd.isImm())
1795 return Error(IDLoc, "expected immediate operand kind");
1796 Imm = Opnd.getImm();
1797 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1798 Imm % 4 != 0)
1799 return Error(IDLoc, "immediate operand value out of range");
1800 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001801 case Mips::SLL16_MM:
1802 case Mips::SRL16_MM:
1803 Opnd = Inst.getOperand(2);
1804 if (!Opnd.isImm())
1805 return Error(IDLoc, "expected immediate operand kind");
1806 Imm = Opnd.getImm();
1807 if (Imm < 1 || Imm > 8)
1808 return Error(IDLoc, "immediate operand value out of range");
1809 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001810 case Mips::LI16_MM:
1811 Opnd = Inst.getOperand(1);
1812 if (!Opnd.isImm())
1813 return Error(IDLoc, "expected immediate operand kind");
1814 Imm = Opnd.getImm();
1815 if (Imm < -1 || Imm > 126)
1816 return Error(IDLoc, "immediate operand value out of range");
1817 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001818 case Mips::ADDIUR2_MM:
1819 Opnd = Inst.getOperand(2);
1820 if (!Opnd.isImm())
1821 return Error(IDLoc, "expected immediate operand kind");
1822 Imm = Opnd.getImm();
1823 if (!(Imm == 1 || Imm == -1 ||
1824 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1825 return Error(IDLoc, "immediate operand value out of range");
1826 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001827 case Mips::ANDI16_MM:
1828 Opnd = Inst.getOperand(2);
1829 if (!Opnd.isImm())
1830 return Error(IDLoc, "expected immediate operand kind");
1831 Imm = Opnd.getImm();
1832 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1833 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1834 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1835 return Error(IDLoc, "immediate operand value out of range");
1836 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001837 case Mips::LBU16_MM:
1838 Opnd = Inst.getOperand(2);
1839 if (!Opnd.isImm())
1840 return Error(IDLoc, "expected immediate operand kind");
1841 Imm = Opnd.getImm();
1842 if (Imm < -1 || Imm > 14)
1843 return Error(IDLoc, "immediate operand value out of range");
1844 break;
1845 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001846 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001847 Opnd = Inst.getOperand(2);
1848 if (!Opnd.isImm())
1849 return Error(IDLoc, "expected immediate operand kind");
1850 Imm = Opnd.getImm();
1851 if (Imm < 0 || Imm > 15)
1852 return Error(IDLoc, "immediate operand value out of range");
1853 break;
1854 case Mips::LHU16_MM:
1855 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001856 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001857 Opnd = Inst.getOperand(2);
1858 if (!Opnd.isImm())
1859 return Error(IDLoc, "expected immediate operand kind");
1860 Imm = Opnd.getImm();
1861 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1862 return Error(IDLoc, "immediate operand value out of range");
1863 break;
1864 case Mips::LW16_MM:
1865 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001866 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001867 Opnd = Inst.getOperand(2);
1868 if (!Opnd.isImm())
1869 return Error(IDLoc, "expected immediate operand kind");
1870 Imm = Opnd.getImm();
1871 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1872 return Error(IDLoc, "immediate operand value out of range");
1873 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001874 case Mips::ADDIUPC_MM:
1875 MCOperand Opnd = Inst.getOperand(1);
1876 if (!Opnd.isImm())
1877 return Error(IDLoc, "expected immediate operand kind");
1878 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001879 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001880 return Error(IDLoc, "immediate operand value out of range");
1881 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001882 }
1883 }
1884
Daniel Sandersd8c07762016-04-18 12:35:36 +00001885 bool FillDelaySlot =
1886 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
1887 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00001888 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001889
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001890 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001891 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001892 switch (ExpandResult) {
1893 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001894 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001895 break;
1896 case MER_Success:
1897 break;
1898 case MER_Fail:
1899 return true;
1900 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001901
Daniel Sanderscda908a2016-05-16 09:10:13 +00001902 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
1903 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
1904 if (inMicroMipsMode())
1905 TOut.setUsesMicroMips();
1906
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001907 // If this instruction has a delay slot and .set reorder is active,
1908 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00001909 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001910 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
1911 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001912 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001913
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001914 if ((Inst.getOpcode() == Mips::JalOneReg ||
1915 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1916 isPicAndNotNxxAbi()) {
1917 if (IsCpRestoreSet) {
1918 // We need a NOP between the JALR and the LW:
1919 // If .set reorder has been used, we've already emitted a NOP.
1920 // If .set noreorder has been used, we need to emit a NOP at this point.
1921 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00001922 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
1923 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001924
1925 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00001926 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001927 } else
1928 Warning(IDLoc, "no .cprestore used in PIC mode");
1929 }
1930
Jack Carter9e65aa32013-03-22 00:05:30 +00001931 return false;
1932}
1933
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001934MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001935MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
1936 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001937 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001938 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001939 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001940 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001941 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001942 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001943 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001944 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001945 case Mips::LoadAddrImm64:
1946 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1947 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1948 "expected immediate operand kind");
1949
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001950 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1951 Inst.getOperand(1),
1952 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001953 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001954 ? MER_Fail
1955 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001956 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001957 case Mips::LoadAddrReg64:
1958 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1959 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1960 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1961 "expected immediate operand kind");
1962
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001963 return expandLoadAddress(Inst.getOperand(0).getReg(),
1964 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1965 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001966 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001967 ? MER_Fail
1968 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001969 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001970 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001971 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
1972 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001973 case Mips::SWM_MM:
1974 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001975 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
1976 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001977 case Mips::JalOneReg:
1978 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001979 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00001980 case Mips::BneImm:
1981 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001982 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00001983 case Mips::BLT:
1984 case Mips::BLE:
1985 case Mips::BGE:
1986 case Mips::BGT:
1987 case Mips::BLTU:
1988 case Mips::BLEU:
1989 case Mips::BGEU:
1990 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001991 case Mips::BLTL:
1992 case Mips::BLEL:
1993 case Mips::BGEL:
1994 case Mips::BGTL:
1995 case Mips::BLTUL:
1996 case Mips::BLEUL:
1997 case Mips::BGEUL:
1998 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00001999 case Mips::BLTImmMacro:
2000 case Mips::BLEImmMacro:
2001 case Mips::BGEImmMacro:
2002 case Mips::BGTImmMacro:
2003 case Mips::BLTUImmMacro:
2004 case Mips::BLEUImmMacro:
2005 case Mips::BGEUImmMacro:
2006 case Mips::BGTUImmMacro:
2007 case Mips::BLTLImmMacro:
2008 case Mips::BLELImmMacro:
2009 case Mips::BGELImmMacro:
2010 case Mips::BGTLImmMacro:
2011 case Mips::BLTULImmMacro:
2012 case Mips::BLEULImmMacro:
2013 case Mips::BGEULImmMacro:
2014 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002015 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002016 case Mips::SDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002017 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2018 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002019 case Mips::DSDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002020 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2021 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002022 case Mips::UDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002023 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2024 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002025 case Mips::DUDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002026 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2027 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002028 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002029 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2030 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002031 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002032 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002033 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002034 case Mips::PseudoTRUNC_W_D:
2035 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2036 : MER_Success;
2037 case Mips::Ulh:
2038 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2039 case Mips::Ulhu:
2040 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2041 case Mips::Ulw:
2042 return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2043 case Mips::NORImm:
2044 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002045 case Mips::ADDi:
2046 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002047 case Mips::SLTi:
2048 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002049 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2050 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2051 int64_t ImmValue = Inst.getOperand(2).getImm();
2052 if (isInt<16>(ImmValue))
2053 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002054 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2055 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002056 }
2057 return MER_NotAMacro;
2058 case Mips::ANDi:
2059 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002060 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002061 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2062 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2063 int64_t ImmValue = Inst.getOperand(2).getImm();
2064 if (isUInt<16>(ImmValue))
2065 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002066 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2067 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002068 }
2069 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002070 case Mips::ROL:
2071 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002072 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002073 case Mips::ROLImm:
2074 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002075 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002076 case Mips::DROL:
2077 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002078 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002079 case Mips::DROLImm:
2080 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002081 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002082 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002083 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002084 }
Jack Carter30a59822012-10-04 04:03:53 +00002085}
Jack Carter92995f12012-10-06 00:53:28 +00002086
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002087bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002088 MCStreamer &Out,
2089 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002090 MipsTargetStreamer &TOut = getTargetStreamer();
2091
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002092 // Create a JALR instruction which is going to replace the pseudo-JAL.
2093 MCInst JalrInst;
2094 JalrInst.setLoc(IDLoc);
2095 const MCOperand FirstRegOp = Inst.getOperand(0);
2096 const unsigned Opcode = Inst.getOpcode();
2097
2098 if (Opcode == Mips::JalOneReg) {
2099 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002100 if (IsCpRestoreSet && inMicroMipsMode()) {
2101 JalrInst.setOpcode(Mips::JALRS16_MM);
2102 JalrInst.addOperand(FirstRegOp);
2103 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002104 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002105 JalrInst.addOperand(FirstRegOp);
2106 } else {
2107 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002108 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002109 JalrInst.addOperand(FirstRegOp);
2110 }
2111 } else if (Opcode == Mips::JalTwoReg) {
2112 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002113 if (IsCpRestoreSet && inMicroMipsMode())
2114 JalrInst.setOpcode(Mips::JALRS_MM);
2115 else
2116 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002117 JalrInst.addOperand(FirstRegOp);
2118 const MCOperand SecondRegOp = Inst.getOperand(1);
2119 JalrInst.addOperand(SecondRegOp);
2120 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002121 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002122
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002123 // If .set reorder is active and branch instruction has a delay slot,
2124 // emit a NOP after it.
2125 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002126 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2127 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2128 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002129
2130 return false;
2131}
2132
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002133/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002134template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002135 unsigned BitNum = findFirstSet(x);
2136
2137 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2138}
2139
2140/// Load (or add) an immediate into a register.
2141///
2142/// @param ImmValue The immediate to load.
2143/// @param DstReg The register that will hold the immediate.
2144/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2145/// for a simple initialization.
2146/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2147/// @param IsAddress True if the immediate represents an address. False if it
2148/// is an integer.
2149/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002150bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002151 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002152 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2153 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002154 MipsTargetStreamer &TOut = getTargetStreamer();
2155
Toma Tabacu00e98672015-05-01 12:19:27 +00002156 if (!Is32BitImm && !isGP64bit()) {
2157 Error(IDLoc, "instruction requires a 64-bit architecture");
2158 return true;
2159 }
2160
Daniel Sanders03f9c012015-07-14 12:24:22 +00002161 if (Is32BitImm) {
2162 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2163 // Sign extend up to 64-bit so that the predicates match the hardware
2164 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2165 // true.
2166 ImmValue = SignExtend64<32>(ImmValue);
2167 } else {
2168 Error(IDLoc, "instruction requires a 32-bit immediate");
2169 return true;
2170 }
2171 }
2172
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002173 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2174 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2175
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002176 bool UseSrcReg = false;
2177 if (SrcReg != Mips::NoRegister)
2178 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002179
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002180 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002181 if (UseSrcReg &&
2182 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002183 // At this point we need AT to perform the expansions and we exit if it is
2184 // not available.
2185 unsigned ATReg = getATReg(IDLoc);
2186 if (!ATReg)
2187 return true;
2188 TmpReg = ATReg;
2189 }
2190
Daniel Sanders03f9c012015-07-14 12:24:22 +00002191 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002192 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002193 SrcReg = ZeroReg;
2194
2195 // This doesn't quite follow the usual ABI expectations for N32 but matches
2196 // traditional assembler behaviour. N32 would normally use addiu for both
2197 // integers and addresses.
2198 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002199 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002200 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002201 }
2202
Daniel Sandersa736b372016-04-29 13:33:12 +00002203 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002204 return false;
2205 }
2206
2207 if (isUInt<16>(ImmValue)) {
2208 unsigned TmpReg = DstReg;
2209 if (SrcReg == DstReg) {
2210 TmpReg = getATReg(IDLoc);
2211 if (!TmpReg)
2212 return true;
2213 }
2214
Daniel Sandersa736b372016-04-29 13:33:12 +00002215 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002216 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002217 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002218 return false;
2219 }
2220
2221 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002222 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002223
Toma Tabacu79588102015-04-29 10:19:56 +00002224 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2225 uint16_t Bits15To0 = ImmValue & 0xffff;
2226
Toma Tabacua3d056f2015-05-15 09:42:11 +00002227 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002228 // Traditional behaviour seems to special case this particular value. It's
2229 // not clear why other masks are handled differently.
2230 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002231 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2232 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002233 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002234 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002235 return false;
2236 }
2237
2238 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002239 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002240 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2241 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002242 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002243 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002244 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002245 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002246 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002247 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002248
Daniel Sandersa736b372016-04-29 13:33:12 +00002249 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002250 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002251 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002252 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002253 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002254 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002255 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002256
2257 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2258 if (Is32BitImm) {
2259 Error(IDLoc, "instruction requires a 32-bit immediate");
2260 return true;
2261 }
2262
2263 // Traditionally, these immediates are shifted as little as possible and as
2264 // such we align the most significant bit to bit 15 of our temporary.
2265 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2266 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2267 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2268 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002269 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2270 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002271
2272 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002273 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002274
2275 return false;
2276 }
2277
2278 warnIfNoMacro(IDLoc);
2279
2280 // The remaining case is packed with a sequence of dsll and ori with zeros
2281 // being omitted and any neighbouring dsll's being coalesced.
2282 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2283
2284 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2285 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002286 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002287 return false;
2288
2289 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2290 // skip it and defer the shift to the next chunk.
2291 unsigned ShiftCarriedForwards = 16;
2292 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2293 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2294
2295 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002296 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2297 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002298 ShiftCarriedForwards = 0;
2299 }
2300
2301 ShiftCarriedForwards += 16;
2302 }
2303 ShiftCarriedForwards -= 16;
2304
2305 // Finish any remaining shifts left by trailing zeros.
2306 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002307 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002308
2309 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002310 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002311
Matheus Almeida3813d572014-06-19 14:39:14 +00002312 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002313}
Jack Carter92995f12012-10-06 00:53:28 +00002314
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002315bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002316 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002317 const MCOperand &ImmOp = Inst.getOperand(1);
2318 assert(ImmOp.isImm() && "expected immediate operand kind");
2319 const MCOperand &DstRegOp = Inst.getOperand(0);
2320 assert(DstRegOp.isReg() && "expected register operand kind");
2321
2322 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002323 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002324 return true;
2325
2326 return false;
2327}
2328
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002329bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2330 const MCOperand &Offset,
2331 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002332 MCStreamer &Out,
2333 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002334 // la can't produce a usable address when addresses are 64-bit.
2335 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2336 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2337 // We currently can't do this because we depend on the equality
2338 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2339 Error(IDLoc, "la used to load 64-bit address");
2340 // Continue as if we had 'dla' instead.
2341 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002342 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002343
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002344 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002345 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002346 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002347 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002348 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002349
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002350 if (!Offset.isImm())
2351 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002352 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002353
Scott Egerton24557012016-01-21 15:11:01 +00002354 if (!ABI.ArePtrs64bit()) {
2355 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2356 Is32BitAddress = true;
2357 }
2358
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002359 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002360 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002361}
2362
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002363bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2364 unsigned DstReg, unsigned SrcReg,
2365 bool Is32BitSym, SMLoc IDLoc,
2366 MCStreamer &Out,
2367 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002368 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacu81496c12015-05-20 08:54:45 +00002369 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002370
Daniel Sandersd5a89412015-10-05 13:19:29 +00002371 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002372 const MipsMCExpr *HiExpr =
2373 MipsMCExpr::create(MipsMCExpr::MEK_HI, Symbol, getContext());
2374 const MipsMCExpr *LoExpr =
2375 MipsMCExpr::create(MipsMCExpr::MEK_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002376
Toma Tabacufb9d1252015-06-22 12:08:39 +00002377 bool UseSrcReg = SrcReg != Mips::NoRegister;
2378
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002379 // This is the 64-bit symbol address expansion.
2380 if (ABI.ArePtrs64bit() && isGP64bit()) {
2381 // We always need AT for the 64-bit expansion.
2382 // If it is not available we exit.
2383 unsigned ATReg = getATReg(IDLoc);
2384 if (!ATReg)
2385 return true;
2386
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002387 const MipsMCExpr *HighestExpr =
2388 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, Symbol, getContext());
2389 const MipsMCExpr *HigherExpr =
2390 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002391
Scott Egerton24557012016-01-21 15:11:01 +00002392 if (UseSrcReg &&
2393 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2394 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002395 // If $rs is the same as $rd:
2396 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2397 // daddiu $at, $at, %higher(sym)
2398 // dsll $at, $at, 16
2399 // daddiu $at, $at, %hi(sym)
2400 // dsll $at, $at, 16
2401 // daddiu $at, $at, %lo(sym)
2402 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002403 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2404 STI);
2405 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2406 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2407 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2408 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2409 IDLoc, STI);
2410 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2411 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2412 IDLoc, STI);
2413 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002414
2415 return false;
2416 }
2417
2418 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2419 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2420 // lui $at, %hi(sym)
2421 // daddiu $rd, $rd, %higher(sym)
2422 // daddiu $at, $at, %lo(sym)
2423 // dsll32 $rd, $rd, 0
2424 // daddu $rd, $rd, $at
2425 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002426 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2427 STI);
2428 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2429 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2430 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2431 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2432 IDLoc, STI);
2433 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2434 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002435 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002436 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002437
2438 return false;
2439 }
2440
2441 // And now, the 32-bit symbol address expansion:
2442 // If $rs is the same as $rd:
2443 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2444 // ori $at, $at, %lo(sym)
2445 // addu $rd, $at, $rd
2446 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2447 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2448 // ori $rd, $rd, %lo(sym)
2449 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002450 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002451 if (UseSrcReg &&
2452 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002453 // If $rs is the same as $rd, we need to use AT.
2454 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002455 unsigned ATReg = getATReg(IDLoc);
2456 if (!ATReg)
2457 return true;
2458 TmpReg = ATReg;
2459 }
2460
Daniel Sandersa736b372016-04-29 13:33:12 +00002461 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2462 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2463 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002464
Toma Tabacufb9d1252015-06-22 12:08:39 +00002465 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002466 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002467 else
Scott Egerton24557012016-01-21 15:11:01 +00002468 assert(
2469 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002470
Toma Tabacu674825c2015-06-16 12:16:24 +00002471 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002472}
2473
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002474bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2475 MCStreamer &Out,
2476 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002477 MipsTargetStreamer &TOut = getTargetStreamer();
2478
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002479 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2480 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002481
2482 MCOperand Offset = Inst.getOperand(0);
2483 if (Offset.isExpr()) {
2484 Inst.clear();
2485 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002486 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2487 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2488 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002489 } else {
2490 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002491 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002492 // If offset fits into 11 bits then this instruction becomes microMIPS
2493 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002494 if (inMicroMipsMode())
2495 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002496 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002497 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002498 Error(IDLoc, "branch target out of range");
2499 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2500 Error(IDLoc, "branch to misaligned address");
2501 Inst.clear();
2502 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002503 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2504 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2505 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002506 }
2507 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002508 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002509
Zoran Jovanovicada70912015-09-07 11:56:37 +00002510 // If .set reorder is active and branch instruction has a delay slot,
2511 // emit a NOP after it.
2512 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2513 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002514 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002515
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002516 return false;
2517}
2518
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002519bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2520 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002521 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002522 const MCOperand &DstRegOp = Inst.getOperand(0);
2523 assert(DstRegOp.isReg() && "expected register operand kind");
2524
2525 const MCOperand &ImmOp = Inst.getOperand(1);
2526 assert(ImmOp.isImm() && "expected immediate operand kind");
2527
2528 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002529 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2530 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002531
2532 unsigned OpCode = 0;
2533 switch(Inst.getOpcode()) {
2534 case Mips::BneImm:
2535 OpCode = Mips::BNE;
2536 break;
2537 case Mips::BeqImm:
2538 OpCode = Mips::BEQ;
2539 break;
2540 default:
2541 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2542 break;
2543 }
2544
2545 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002546 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002547 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2548 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002549 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002550 warnIfNoMacro(IDLoc);
2551
2552 unsigned ATReg = getATReg(IDLoc);
2553 if (!ATReg)
2554 return true;
2555
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002556 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002557 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002558 return true;
2559
Daniel Sandersa736b372016-04-29 13:33:12 +00002560 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002561 }
2562 return false;
2563}
2564
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002565void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002566 const MCSubtargetInfo *STI, bool IsLoad,
2567 bool IsImmOpnd) {
2568 if (IsLoad) {
2569 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2570 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002571 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002572 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2573}
2574
2575void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2576 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2577 MipsTargetStreamer &TOut = getTargetStreamer();
2578
2579 unsigned DstReg = Inst.getOperand(0).getReg();
2580 unsigned BaseReg = Inst.getOperand(1).getReg();
2581
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002582 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002583 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2584 unsigned DstRegClassID =
2585 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2586 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2587 (DstRegClassID == Mips::GPR64RegClassID);
2588
2589 if (IsImmOpnd) {
2590 // Try to use DstReg as the temporary.
2591 if (IsGPR && (BaseReg != DstReg)) {
2592 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2593 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2594 STI);
2595 return;
2596 }
2597
Matheus Almeida7de68e72014-06-18 14:46:05 +00002598 // At this point we need AT to perform the expansions and we exit if it is
2599 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002600 unsigned ATReg = getATReg(IDLoc);
2601 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002602 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002603
2604 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2605 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2606 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002607 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002608
Daniel Sandersfba875f2016-04-29 13:43:45 +00002609 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002610 MCOperand LoOperand = MCOperand::createExpr(
2611 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2612 MCOperand HiOperand = MCOperand::createExpr(
2613 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002614
2615 // Try to use DstReg as the temporary.
2616 if (IsGPR && (BaseReg != DstReg)) {
2617 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2618 LoOperand, DstReg, IDLoc, STI);
2619 return;
2620 }
2621
2622 // At this point we need AT to perform the expansions and we exit if it is
2623 // not available.
2624 unsigned ATReg = getATReg(IDLoc);
2625 if (!ATReg)
2626 return;
2627
2628 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2629 LoOperand, ATReg, IDLoc, STI);
2630}
2631
2632void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2633 const MCSubtargetInfo *STI,
2634 bool IsImmOpnd) {
2635 MipsTargetStreamer &TOut = getTargetStreamer();
2636
2637 unsigned SrcReg = Inst.getOperand(0).getReg();
2638 unsigned BaseReg = Inst.getOperand(1).getReg();
2639
Daniel Sanders241c6792016-05-12 14:01:50 +00002640 if (IsImmOpnd) {
2641 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2642 Inst.getOperand(2).getImm(),
2643 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
2644 return;
2645 }
2646
Daniel Sandersfba875f2016-04-29 13:43:45 +00002647 unsigned ATReg = getATReg(IDLoc);
2648 if (!ATReg)
2649 return;
2650
Daniel Sandersfba875f2016-04-29 13:43:45 +00002651 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002652 MCOperand LoOperand = MCOperand::createExpr(
2653 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2654 MCOperand HiOperand = MCOperand::createExpr(
2655 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002656 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2657 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002658}
2659
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002660bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2661 MCStreamer &Out,
2662 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002663 unsigned OpNum = Inst.getNumOperands();
2664 unsigned Opcode = Inst.getOpcode();
2665 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2666
2667 assert (Inst.getOperand(OpNum - 1).isImm() &&
2668 Inst.getOperand(OpNum - 2).isReg() &&
2669 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2670
2671 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2672 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002673 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2674 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2675 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2676 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002677 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002678 if (inMicroMipsMode() && hasMips32r6())
2679 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2680 else
2681 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2682 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002683
2684 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002685 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002686 return false;
2687}
2688
Toma Tabacu1a108322015-06-17 13:20:24 +00002689bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002690 MCStreamer &Out,
2691 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002692 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002693 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002694 unsigned PseudoOpcode = Inst.getOpcode();
2695 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002696 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002697 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2698
2699 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002700 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002701
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002702 unsigned TrgReg;
2703 if (TrgOp.isReg())
2704 TrgReg = TrgOp.getReg();
2705 else if (TrgOp.isImm()) {
2706 warnIfNoMacro(IDLoc);
2707 EmittedNoMacroWarning = true;
2708
2709 TrgReg = getATReg(IDLoc);
2710 if (!TrgReg)
2711 return true;
2712
2713 switch(PseudoOpcode) {
2714 default:
2715 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2716 case Mips::BLTImmMacro:
2717 PseudoOpcode = Mips::BLT;
2718 break;
2719 case Mips::BLEImmMacro:
2720 PseudoOpcode = Mips::BLE;
2721 break;
2722 case Mips::BGEImmMacro:
2723 PseudoOpcode = Mips::BGE;
2724 break;
2725 case Mips::BGTImmMacro:
2726 PseudoOpcode = Mips::BGT;
2727 break;
2728 case Mips::BLTUImmMacro:
2729 PseudoOpcode = Mips::BLTU;
2730 break;
2731 case Mips::BLEUImmMacro:
2732 PseudoOpcode = Mips::BLEU;
2733 break;
2734 case Mips::BGEUImmMacro:
2735 PseudoOpcode = Mips::BGEU;
2736 break;
2737 case Mips::BGTUImmMacro:
2738 PseudoOpcode = Mips::BGTU;
2739 break;
2740 case Mips::BLTLImmMacro:
2741 PseudoOpcode = Mips::BLTL;
2742 break;
2743 case Mips::BLELImmMacro:
2744 PseudoOpcode = Mips::BLEL;
2745 break;
2746 case Mips::BGELImmMacro:
2747 PseudoOpcode = Mips::BGEL;
2748 break;
2749 case Mips::BGTLImmMacro:
2750 PseudoOpcode = Mips::BGTL;
2751 break;
2752 case Mips::BLTULImmMacro:
2753 PseudoOpcode = Mips::BLTUL;
2754 break;
2755 case Mips::BLEULImmMacro:
2756 PseudoOpcode = Mips::BLEUL;
2757 break;
2758 case Mips::BGEULImmMacro:
2759 PseudoOpcode = Mips::BGEUL;
2760 break;
2761 case Mips::BGTULImmMacro:
2762 PseudoOpcode = Mips::BGTUL;
2763 break;
2764 }
2765
2766 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002767 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002768 return true;
2769 }
2770
Toma Tabacu1a108322015-06-17 13:20:24 +00002771 switch (PseudoOpcode) {
2772 case Mips::BLT:
2773 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002774 case Mips::BLTL:
2775 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002776 AcceptsEquality = false;
2777 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002778 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2779 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002780 ZeroSrcOpcode = Mips::BGTZ;
2781 ZeroTrgOpcode = Mips::BLTZ;
2782 break;
2783 case Mips::BLE:
2784 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002785 case Mips::BLEL:
2786 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002787 AcceptsEquality = true;
2788 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002789 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2790 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002791 ZeroSrcOpcode = Mips::BGEZ;
2792 ZeroTrgOpcode = Mips::BLEZ;
2793 break;
2794 case Mips::BGE:
2795 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002796 case Mips::BGEL:
2797 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002798 AcceptsEquality = true;
2799 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002800 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2801 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002802 ZeroSrcOpcode = Mips::BLEZ;
2803 ZeroTrgOpcode = Mips::BGEZ;
2804 break;
2805 case Mips::BGT:
2806 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002807 case Mips::BGTL:
2808 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002809 AcceptsEquality = false;
2810 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002811 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2812 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002813 ZeroSrcOpcode = Mips::BLTZ;
2814 ZeroTrgOpcode = Mips::BGTZ;
2815 break;
2816 default:
2817 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2818 }
2819
Toma Tabacu1a108322015-06-17 13:20:24 +00002820 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2821 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2822 if (IsSrcRegZero && IsTrgRegZero) {
2823 // FIXME: All of these Opcode-specific if's are needed for compatibility
2824 // with GAS' behaviour. However, they may not generate the most efficient
2825 // code in some circumstances.
2826 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002827 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2828 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002829 return false;
2830 }
2831 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002832 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2833 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002834 Warning(IDLoc, "branch is always taken");
2835 return false;
2836 }
2837 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002838 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2839 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002840 Warning(IDLoc, "branch is always taken");
2841 return false;
2842 }
2843 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002844 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2845 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002846 return false;
2847 }
2848 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002849 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2850 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002851 return false;
2852 }
2853 if (AcceptsEquality) {
2854 // If both registers are $0 and the pseudo-branch accepts equality, it
2855 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00002856 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2857 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002858 Warning(IDLoc, "branch is always taken");
2859 return false;
2860 }
2861 // If both registers are $0 and the pseudo-branch does not accept
2862 // equality, it will never be taken, so we don't have to emit anything.
2863 return false;
2864 }
2865 if (IsSrcRegZero || IsTrgRegZero) {
2866 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2867 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2868 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2869 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2870 // the pseudo-branch will never be taken, so we don't emit anything.
2871 // This only applies to unsigned pseudo-branches.
2872 return false;
2873 }
2874 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2875 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2876 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2877 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2878 // the pseudo-branch will always be taken, so we emit an unconditional
2879 // branch.
2880 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00002881 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2882 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002883 Warning(IDLoc, "branch is always taken");
2884 return false;
2885 }
2886 if (IsUnsigned) {
2887 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2888 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2889 // the pseudo-branch will be taken only when the non-zero register is
2890 // different from 0, so we emit a BNEZ.
2891 //
2892 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2893 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2894 // the pseudo-branch will be taken only when the non-zero register is
2895 // equal to 0, so we emit a BEQZ.
2896 //
2897 // Because only BLEU and BGEU branch on equality, we can use the
2898 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00002899 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2900 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2901 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002902 return false;
2903 }
2904 // If we have a signed pseudo-branch and one of the registers is $0,
2905 // we can use an appropriate compare-to-zero branch. We select which one
2906 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00002907 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2908 IsSrcRegZero ? TrgReg : SrcReg,
2909 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002910 return false;
2911 }
2912
2913 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2914 // expansions. If it is not available, we return.
2915 unsigned ATRegNum = getATReg(IDLoc);
2916 if (!ATRegNum)
2917 return true;
2918
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002919 if (!EmittedNoMacroWarning)
2920 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002921
2922 // SLT fits well with 2 of our 4 pseudo-branches:
2923 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2924 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2925 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2926 // This is accomplished by using a BNEZ with the result of the SLT.
2927 //
2928 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2929 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2930 // Because only BGE and BLE branch on equality, we can use the
2931 // AcceptsEquality variable to decide when to emit the BEQZ.
2932 // Note that the order of the SLT arguments doesn't change between
2933 // opposites.
2934 //
2935 // The same applies to the unsigned variants, except that SLTu is used
2936 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00002937 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2938 ReverseOrderSLT ? TrgReg : SrcReg,
2939 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002940
Daniel Sandersa736b372016-04-29 13:33:12 +00002941 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2942 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2943 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2944 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002945 return false;
2946}
2947
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002948bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2949 const MCSubtargetInfo *STI, const bool IsMips64,
2950 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002951 MipsTargetStreamer &TOut = getTargetStreamer();
2952
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002953 warnIfNoMacro(IDLoc);
2954
Zoran Jovanovic973405b2016-05-16 08:57:59 +00002955 const MCOperand &RdRegOp = Inst.getOperand(0);
2956 assert(RdRegOp.isReg() && "expected register operand kind");
2957 unsigned RdReg = RdRegOp.getReg();
2958
2959 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002960 assert(RsRegOp.isReg() && "expected register operand kind");
2961 unsigned RsReg = RsRegOp.getReg();
2962
Zoran Jovanovic973405b2016-05-16 08:57:59 +00002963 const MCOperand &RtRegOp = Inst.getOperand(2);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002964 assert(RtRegOp.isReg() && "expected register operand kind");
2965 unsigned RtReg = RtRegOp.getReg();
2966 unsigned DivOp;
2967 unsigned ZeroReg;
2968
2969 if (IsMips64) {
2970 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2971 ZeroReg = Mips::ZERO_64;
2972 } else {
2973 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2974 ZeroReg = Mips::ZERO;
2975 }
2976
2977 bool UseTraps = useTraps();
2978
2979 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2980 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2981 Warning(IDLoc, "dividing zero by zero");
2982 if (IsMips64) {
2983 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2984 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002985 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002986 return false;
2987 }
2988
Daniel Sandersa736b372016-04-29 13:33:12 +00002989 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002990 return false;
2991 }
2992 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00002993 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002994 return false;
2995 }
2996 }
2997
2998 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2999 Warning(IDLoc, "division by zero");
3000 if (Signed) {
3001 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003002 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003003 return false;
3004 }
3005
Daniel Sandersa736b372016-04-29 13:33:12 +00003006 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003007 return false;
3008 }
3009 }
3010
3011 // FIXME: The values for these two BranchTarget variables may be different in
3012 // micromips. These magic numbers need to be removed.
3013 unsigned BranchTargetNoTraps;
3014 unsigned BranchTarget;
3015
3016 if (UseTraps) {
3017 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003018 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003019 } else {
3020 BranchTarget = IsMips64 ? 20 : 16;
3021 BranchTargetNoTraps = 8;
3022 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003023 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003024 }
3025
Daniel Sandersa736b372016-04-29 13:33:12 +00003026 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003027
3028 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003029 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003030
3031 if (!Signed) {
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003032 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003033 return false;
3034 }
3035
3036 unsigned ATReg = getATReg(IDLoc);
3037 if (!ATReg)
3038 return true;
3039
Daniel Sandersa736b372016-04-29 13:33:12 +00003040 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003041 if (IsMips64) {
3042 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003043 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3044 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3045 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003046 } else {
3047 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003048 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3049 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003050 }
3051
3052 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003053 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003054 else {
3055 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003056 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3057 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3058 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003059 }
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003060 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003061 return false;
3062}
3063
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003064bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003065 SMLoc IDLoc, MCStreamer &Out,
3066 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003067 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003068
3069 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3070 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3071 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3072
3073 unsigned FirstReg = Inst.getOperand(0).getReg();
3074 unsigned SecondReg = Inst.getOperand(1).getReg();
3075 unsigned ThirdReg = Inst.getOperand(2).getReg();
3076
3077 if (hasMips1() && !hasMips2()) {
3078 unsigned ATReg = getATReg(IDLoc);
3079 if (!ATReg)
3080 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003081 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3082 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3083 TOut.emitNop(IDLoc, STI);
3084 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3085 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3086 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3087 TOut.emitNop(IDLoc, STI);
3088 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3089 : Mips::CVT_W_S,
3090 FirstReg, SecondReg, IDLoc, STI);
3091 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3092 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003093 return false;
3094 }
3095
Daniel Sandersa736b372016-04-29 13:33:12 +00003096 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3097 : Mips::TRUNC_W_S,
3098 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003099
3100 return false;
3101}
3102
Daniel Sanders6394ee52015-10-15 14:52:58 +00003103bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003104 MCStreamer &Out, const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003105 MipsTargetStreamer &TOut = getTargetStreamer();
3106
Toma Tabacud88d79c2015-06-23 14:39:42 +00003107 if (hasMips32r6() || hasMips64r6()) {
3108 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3109 return false;
3110 }
3111
3112 warnIfNoMacro(IDLoc);
3113
3114 const MCOperand &DstRegOp = Inst.getOperand(0);
3115 assert(DstRegOp.isReg() && "expected register operand kind");
3116
3117 const MCOperand &SrcRegOp = Inst.getOperand(1);
3118 assert(SrcRegOp.isReg() && "expected register operand kind");
3119
3120 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3121 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3122
3123 unsigned DstReg = DstRegOp.getReg();
3124 unsigned SrcReg = SrcRegOp.getReg();
3125 int64_t OffsetValue = OffsetImmOp.getImm();
3126
3127 // NOTE: We always need AT for ULHU, as it is always used as the source
3128 // register for one of the LBu's.
3129 unsigned ATReg = getATReg(IDLoc);
3130 if (!ATReg)
3131 return true;
3132
3133 // When the value of offset+1 does not fit in 16 bits, we have to load the
3134 // offset in AT, (D)ADDu the original source register (if there was one), and
3135 // then use AT as the source register for the 2 generated LBu's.
3136 bool LoadedOffsetInAT = false;
3137 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3138 LoadedOffsetInAT = true;
3139
3140 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003141 true, IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003142 return true;
3143
3144 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3145 // because it will make our output more similar to GAS'. For example,
3146 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3147 // instead of just an "ori $1, $9, 32768".
3148 // NOTE: If there is no source register specified in the ULHU, the parser
3149 // will interpret it as $0.
3150 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003151 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003152 }
3153
3154 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3155 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3156 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3157
3158 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3159 if (isLittle()) {
3160 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3161 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3162 } else {
3163 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3164 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3165 }
3166
3167 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3168
Daniel Sandersa736b372016-04-29 13:33:12 +00003169 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3170 FirstLbuOffset, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003171
Daniel Sandersa736b372016-04-29 13:33:12 +00003172 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3173 STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003174
Daniel Sandersa736b372016-04-29 13:33:12 +00003175 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003176
Daniel Sandersa736b372016-04-29 13:33:12 +00003177 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003178
3179 return false;
3180}
3181
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003182bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3183 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003184 MipsTargetStreamer &TOut = getTargetStreamer();
3185
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003186 if (hasMips32r6() || hasMips64r6()) {
3187 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3188 return false;
3189 }
3190
3191 const MCOperand &DstRegOp = Inst.getOperand(0);
3192 assert(DstRegOp.isReg() && "expected register operand kind");
3193
3194 const MCOperand &SrcRegOp = Inst.getOperand(1);
3195 assert(SrcRegOp.isReg() && "expected register operand kind");
3196
3197 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3198 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3199
3200 unsigned SrcReg = SrcRegOp.getReg();
3201 int64_t OffsetValue = OffsetImmOp.getImm();
3202 unsigned ATReg = 0;
3203
3204 // When the value of offset+3 does not fit in 16 bits, we have to load the
3205 // offset in AT, (D)ADDu the original source register (if there was one), and
3206 // then use AT as the source register for the generated LWL and LWR.
3207 bool LoadedOffsetInAT = false;
3208 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3209 ATReg = getATReg(IDLoc);
3210 if (!ATReg)
3211 return true;
3212 LoadedOffsetInAT = true;
3213
3214 warnIfNoMacro(IDLoc);
3215
3216 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003217 true, IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003218 return true;
3219
3220 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3221 // because it will make our output more similar to GAS'. For example,
3222 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3223 // instead of just an "ori $1, $9, 32768".
3224 // NOTE: If there is no source register specified in the ULW, the parser
3225 // will interpret it as $0.
3226 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003227 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003228 }
3229
3230 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3231 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3232 if (isLittle()) {
3233 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3234 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3235 } else {
3236 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3237 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3238 }
3239
Daniel Sandersa736b372016-04-29 13:33:12 +00003240 TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3241 STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003242
Daniel Sandersa736b372016-04-29 13:33:12 +00003243 TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
3244 IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003245
3246 return false;
3247}
3248
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003249bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003250 MCStreamer &Out,
3251 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003252 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003253
3254 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3255 assert (Inst.getOperand(0).isReg() &&
3256 Inst.getOperand(1).isReg() &&
3257 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3258
3259 unsigned ATReg = Mips::NoRegister;
3260 unsigned FinalDstReg = Mips::NoRegister;
3261 unsigned DstReg = Inst.getOperand(0).getReg();
3262 unsigned SrcReg = Inst.getOperand(1).getReg();
3263 int64_t ImmValue = Inst.getOperand(2).getImm();
3264
3265 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3266
3267 unsigned FinalOpcode = Inst.getOpcode();
3268
3269 if (DstReg == SrcReg) {
3270 ATReg = getATReg(Inst.getLoc());
3271 if (!ATReg)
3272 return true;
3273 FinalDstReg = DstReg;
3274 DstReg = ATReg;
3275 }
3276
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003277 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003278 switch (FinalOpcode) {
3279 default:
3280 llvm_unreachable("unimplemented expansion");
3281 case (Mips::ADDi):
3282 FinalOpcode = Mips::ADD;
3283 break;
3284 case (Mips::ADDiu):
3285 FinalOpcode = Mips::ADDu;
3286 break;
3287 case (Mips::ANDi):
3288 FinalOpcode = Mips::AND;
3289 break;
3290 case (Mips::NORImm):
3291 FinalOpcode = Mips::NOR;
3292 break;
3293 case (Mips::ORi):
3294 FinalOpcode = Mips::OR;
3295 break;
3296 case (Mips::SLTi):
3297 FinalOpcode = Mips::SLT;
3298 break;
3299 case (Mips::SLTiu):
3300 FinalOpcode = Mips::SLTu;
3301 break;
3302 case (Mips::XORi):
3303 FinalOpcode = Mips::XOR;
3304 break;
3305 }
3306
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003307 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003308 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003309 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003310 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003311 return false;
3312 }
3313 return true;
3314}
3315
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003316bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3317 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003318 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003319 unsigned ATReg = Mips::NoRegister;
3320 unsigned DReg = Inst.getOperand(0).getReg();
3321 unsigned SReg = Inst.getOperand(1).getReg();
3322 unsigned TReg = Inst.getOperand(2).getReg();
3323 unsigned TmpReg = DReg;
3324
3325 unsigned FirstShift = Mips::NOP;
3326 unsigned SecondShift = Mips::NOP;
3327
3328 if (hasMips32r2()) {
3329
3330 if (DReg == SReg) {
3331 TmpReg = getATReg(Inst.getLoc());
3332 if (!TmpReg)
3333 return true;
3334 }
3335
3336 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003337 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3338 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003339 return false;
3340 }
3341
3342 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003343 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003344 return false;
3345 }
3346
3347 return true;
3348 }
3349
3350 if (hasMips32()) {
3351
3352 switch (Inst.getOpcode()) {
3353 default:
3354 llvm_unreachable("unexpected instruction opcode");
3355 case Mips::ROL:
3356 FirstShift = Mips::SRLV;
3357 SecondShift = Mips::SLLV;
3358 break;
3359 case Mips::ROR:
3360 FirstShift = Mips::SLLV;
3361 SecondShift = Mips::SRLV;
3362 break;
3363 }
3364
3365 ATReg = getATReg(Inst.getLoc());
3366 if (!ATReg)
3367 return true;
3368
Daniel Sandersa736b372016-04-29 13:33:12 +00003369 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3370 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3371 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3372 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003373
3374 return false;
3375 }
3376
3377 return true;
3378}
3379
3380bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003381 MCStreamer &Out,
3382 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003383 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003384 unsigned ATReg = Mips::NoRegister;
3385 unsigned DReg = Inst.getOperand(0).getReg();
3386 unsigned SReg = Inst.getOperand(1).getReg();
3387 int64_t ImmValue = Inst.getOperand(2).getImm();
3388
3389 unsigned FirstShift = Mips::NOP;
3390 unsigned SecondShift = Mips::NOP;
3391
3392 if (hasMips32r2()) {
3393
3394 if (Inst.getOpcode() == Mips::ROLImm) {
3395 uint64_t MaxShift = 32;
3396 uint64_t ShiftValue = ImmValue;
3397 if (ImmValue != 0)
3398 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003399 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003400 return false;
3401 }
3402
3403 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003404 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003405 return false;
3406 }
3407
3408 return true;
3409 }
3410
3411 if (hasMips32()) {
3412
3413 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003414 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003415 return false;
3416 }
3417
3418 switch (Inst.getOpcode()) {
3419 default:
3420 llvm_unreachable("unexpected instruction opcode");
3421 case Mips::ROLImm:
3422 FirstShift = Mips::SLL;
3423 SecondShift = Mips::SRL;
3424 break;
3425 case Mips::RORImm:
3426 FirstShift = Mips::SRL;
3427 SecondShift = Mips::SLL;
3428 break;
3429 }
3430
3431 ATReg = getATReg(Inst.getLoc());
3432 if (!ATReg)
3433 return true;
3434
Daniel Sandersa736b372016-04-29 13:33:12 +00003435 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3436 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3437 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003438
3439 return false;
3440 }
3441
3442 return true;
3443}
3444
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003445bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3446 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003447 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003448 unsigned ATReg = Mips::NoRegister;
3449 unsigned DReg = Inst.getOperand(0).getReg();
3450 unsigned SReg = Inst.getOperand(1).getReg();
3451 unsigned TReg = Inst.getOperand(2).getReg();
3452 unsigned TmpReg = DReg;
3453
3454 unsigned FirstShift = Mips::NOP;
3455 unsigned SecondShift = Mips::NOP;
3456
3457 if (hasMips64r2()) {
3458
3459 if (TmpReg == SReg) {
3460 TmpReg = getATReg(Inst.getLoc());
3461 if (!TmpReg)
3462 return true;
3463 }
3464
3465 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003466 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3467 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003468 return false;
3469 }
3470
3471 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003472 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003473 return false;
3474 }
3475
3476 return true;
3477 }
3478
3479 if (hasMips64()) {
3480
3481 switch (Inst.getOpcode()) {
3482 default:
3483 llvm_unreachable("unexpected instruction opcode");
3484 case Mips::DROL:
3485 FirstShift = Mips::DSRLV;
3486 SecondShift = Mips::DSLLV;
3487 break;
3488 case Mips::DROR:
3489 FirstShift = Mips::DSLLV;
3490 SecondShift = Mips::DSRLV;
3491 break;
3492 }
3493
3494 ATReg = getATReg(Inst.getLoc());
3495 if (!ATReg)
3496 return true;
3497
Daniel Sandersa736b372016-04-29 13:33:12 +00003498 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3499 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3500 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3501 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003502
3503 return false;
3504 }
3505
3506 return true;
3507}
3508
3509bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003510 MCStreamer &Out,
3511 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003512 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003513 unsigned ATReg = Mips::NoRegister;
3514 unsigned DReg = Inst.getOperand(0).getReg();
3515 unsigned SReg = Inst.getOperand(1).getReg();
3516 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3517
3518 unsigned FirstShift = Mips::NOP;
3519 unsigned SecondShift = Mips::NOP;
3520
3521 MCInst TmpInst;
3522
3523 if (hasMips64r2()) {
3524
3525 unsigned FinalOpcode = Mips::NOP;
3526 if (ImmValue == 0)
3527 FinalOpcode = Mips::DROTR;
3528 else if (ImmValue % 32 == 0)
3529 FinalOpcode = Mips::DROTR32;
3530 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3531 if (Inst.getOpcode() == Mips::DROLImm)
3532 FinalOpcode = Mips::DROTR32;
3533 else
3534 FinalOpcode = Mips::DROTR;
3535 } else if (ImmValue >= 33) {
3536 if (Inst.getOpcode() == Mips::DROLImm)
3537 FinalOpcode = Mips::DROTR;
3538 else
3539 FinalOpcode = Mips::DROTR32;
3540 }
3541
3542 uint64_t ShiftValue = ImmValue % 32;
3543 if (Inst.getOpcode() == Mips::DROLImm)
3544 ShiftValue = (32 - ImmValue % 32) % 32;
3545
Daniel Sandersa736b372016-04-29 13:33:12 +00003546 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003547
3548 return false;
3549 }
3550
3551 if (hasMips64()) {
3552
3553 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003554 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003555 return false;
3556 }
3557
3558 switch (Inst.getOpcode()) {
3559 default:
3560 llvm_unreachable("unexpected instruction opcode");
3561 case Mips::DROLImm:
3562 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3563 FirstShift = Mips::DSLL;
3564 SecondShift = Mips::DSRL32;
3565 }
3566 if (ImmValue == 32) {
3567 FirstShift = Mips::DSLL32;
3568 SecondShift = Mips::DSRL32;
3569 }
3570 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3571 FirstShift = Mips::DSLL32;
3572 SecondShift = Mips::DSRL;
3573 }
3574 break;
3575 case Mips::DRORImm:
3576 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3577 FirstShift = Mips::DSRL;
3578 SecondShift = Mips::DSLL32;
3579 }
3580 if (ImmValue == 32) {
3581 FirstShift = Mips::DSRL32;
3582 SecondShift = Mips::DSLL32;
3583 }
3584 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3585 FirstShift = Mips::DSRL32;
3586 SecondShift = Mips::DSLL;
3587 }
3588 break;
3589 }
3590
3591 ATReg = getATReg(Inst.getLoc());
3592 if (!ATReg)
3593 return true;
3594
Daniel Sandersa736b372016-04-29 13:33:12 +00003595 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3596 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3597 Inst.getLoc(), STI);
3598 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003599
3600 return false;
3601 }
3602
3603 return true;
3604}
3605
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003606bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3607 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003608 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003609 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3610 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3611
Daniel Sandersa736b372016-04-29 13:33:12 +00003612 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003613 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003614 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003615 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003616 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3617 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003618
3619 return false;
3620}
3621
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003622void MipsAsmParser::createCpRestoreMemOp(bool IsLoad, int StackOffset,
3623 SMLoc IDLoc, MCStreamer &Out,
3624 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003625 MipsTargetStreamer &TOut = getTargetStreamer();
3626
Daniel Sanders7225cd52016-04-29 16:16:49 +00003627 if (IsLoad) {
3628 TOut.emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, StackOffset,
3629 Mips::GP, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003630 return;
3631 }
3632
Daniel Sanders241c6792016-05-12 14:01:50 +00003633 TOut.emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, StackOffset,
3634 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003635}
3636
Matheus Almeida595fcab2014-06-11 15:05:56 +00003637unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3638 // As described by the Mips32r2 spec, the registers Rd and Rs for
3639 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00003640 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00003641 // and registers Rd and Base for microMIPS lwp instruction
Matheus Almeida595fcab2014-06-11 15:05:56 +00003642 unsigned Opcode = Inst.getOpcode();
3643
Zlatko Buljanae720db2016-04-22 06:44:34 +00003644 if ((Opcode == Mips::JALR_HB || Opcode == Mips::JALRC_HB_MMR6) &&
Matheus Almeida595fcab2014-06-11 15:05:56 +00003645 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3646 return Match_RequiresDifferentSrcAndDst;
Zlatko Buljanba553a62016-05-09 08:07:28 +00003647 else if ((Opcode == Mips::LWP_MM || Opcode == Mips::LWP_MMR6) &&
3648 (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()))
3649 return Match_RequiresDifferentSrcAndDst;
Matheus Almeida595fcab2014-06-11 15:05:56 +00003650
3651 return Match_Success;
3652}
3653
Daniel Sanders52da7af2015-11-06 12:11:03 +00003654static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3655 uint64_t ErrorInfo) {
3656 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3657 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3658 if (ErrorLoc == SMLoc())
3659 return Loc;
3660 return ErrorLoc;
3661 }
3662 return Loc;
3663}
3664
David Blaikie960ea3f2014-06-08 16:18:35 +00003665bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3666 OperandVector &Operands,
3667 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003668 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003669 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003670
Jack Carterb4dbc172012-09-05 23:34:03 +00003671 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00003672 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003673 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003674
3675 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003676 case Match_Success: {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003677 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00003678 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003679 return false;
3680 }
3681 case Match_MissingFeature:
3682 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3683 return true;
3684 case Match_InvalidOperand: {
3685 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003686 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003687 if (ErrorInfo >= Operands.size())
3688 return Error(IDLoc, "too few operands for instruction");
3689
Daniel Sanders52da7af2015-11-06 12:11:03 +00003690 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003691 if (ErrorLoc == SMLoc())
3692 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003693 }
3694
3695 return Error(ErrorLoc, "invalid operand for instruction");
3696 }
3697 case Match_MnemonicFail:
3698 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003699 case Match_RequiresDifferentSrcAndDst:
3700 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003701 case Match_Immz:
3702 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003703 case Match_UImm1_0:
3704 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3705 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003706 case Match_UImm2_0:
3707 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3708 "expected 2-bit unsigned immediate");
3709 case Match_UImm2_1:
3710 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3711 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003712 case Match_UImm3_0:
3713 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3714 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003715 case Match_UImm4_0:
3716 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3717 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003718 case Match_SImm4_0:
3719 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3720 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003721 case Match_UImm5_0:
3722 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3723 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00003724 case Match_SImm5_0:
3725 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3726 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003727 case Match_UImm5_1:
3728 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3729 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003730 case Match_UImm5_32:
3731 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3732 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003733 case Match_UImm5_33:
3734 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3735 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003736 case Match_UImm5_0_Report_UImm6:
3737 // This is used on UImm5 operands that have a corresponding UImm5_32
3738 // operand to avoid confusing the user.
3739 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3740 "expected 6-bit unsigned immediate");
3741 case Match_UImm5_Lsl2:
3742 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3743 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003744 case Match_UImmRange2_64:
3745 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3746 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003747 case Match_UImm6_0:
3748 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3749 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00003750 case Match_UImm6_Lsl2:
3751 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3752 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00003753 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00003754 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3755 "expected 6-bit signed immediate");
3756 case Match_UImm7_0:
3757 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3758 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00003759 case Match_UImm7_N1:
3760 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3761 "expected immediate in range -1 .. 126");
3762 case Match_SImm7_Lsl2:
3763 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3764 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003765 case Match_UImm8_0:
3766 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3767 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003768 case Match_UImm10_0:
3769 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3770 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00003771 case Match_SImm10_0:
3772 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3773 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00003774 case Match_SImm11_0:
3775 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3776 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003777 case Match_UImm16:
3778 case Match_UImm16_Relaxed:
3779 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3780 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003781 case Match_SImm16:
3782 case Match_SImm16_Relaxed:
3783 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3784 "expected 16-bit signed immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003785 case Match_UImm20_0:
3786 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3787 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00003788 case Match_UImm26_0:
3789 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3790 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00003791 case Match_SImm32:
3792 case Match_SImm32_Relaxed:
3793 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3794 "expected 32-bit signed immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00003795 case Match_MemSImm9:
3796 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3797 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00003798 case Match_MemSImm10:
3799 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3800 "expected memory with 10-bit signed offset");
3801 case Match_MemSImm10Lsl1:
3802 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3803 "expected memory with 11-bit signed offset and multiple of 2");
3804 case Match_MemSImm10Lsl2:
3805 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3806 "expected memory with 12-bit signed offset and multiple of 4");
3807 case Match_MemSImm10Lsl3:
3808 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3809 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00003810 case Match_MemSImm11:
3811 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3812 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00003813 case Match_MemSImm12:
3814 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3815 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003816 case Match_MemSImm16:
3817 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3818 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00003819 }
Craig Topper589ceee2015-01-03 08:16:34 +00003820
3821 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003822}
3823
Toma Tabacud9d344b2015-04-27 14:05:04 +00003824void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3825 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3826 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3827 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003828}
3829
Toma Tabacu81496c12015-05-20 08:54:45 +00003830void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3831 if (!AssemblerOptions.back()->isMacro())
3832 Warning(Loc, "macro instruction expanded into multiple instructions");
3833}
3834
Daniel Sandersef638fe2014-10-03 15:37:37 +00003835void
3836MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3837 SMRange Range, bool ShowColors) {
3838 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003839 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003840 ShowColors);
3841}
3842
Jack Carter1ac53222013-02-20 23:11:17 +00003843int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003844 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003845
Vladimir Medic4c299852013-11-06 11:27:05 +00003846 CC = StringSwitch<unsigned>(Name)
3847 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003848 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003849 .Case("a0", 4)
3850 .Case("a1", 5)
3851 .Case("a2", 6)
3852 .Case("a3", 7)
3853 .Case("v0", 2)
3854 .Case("v1", 3)
3855 .Case("s0", 16)
3856 .Case("s1", 17)
3857 .Case("s2", 18)
3858 .Case("s3", 19)
3859 .Case("s4", 20)
3860 .Case("s5", 21)
3861 .Case("s6", 22)
3862 .Case("s7", 23)
3863 .Case("k0", 26)
3864 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003865 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003866 .Case("sp", 29)
3867 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003868 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003869 .Case("ra", 31)
3870 .Case("t0", 8)
3871 .Case("t1", 9)
3872 .Case("t2", 10)
3873 .Case("t3", 11)
3874 .Case("t4", 12)
3875 .Case("t5", 13)
3876 .Case("t6", 14)
3877 .Case("t7", 15)
3878 .Case("t8", 24)
3879 .Case("t9", 25)
3880 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003881
Toma Tabacufda445c2014-09-15 15:33:01 +00003882 if (!(isABI_N32() || isABI_N64()))
3883 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003884
Daniel Sandersef638fe2014-10-03 15:37:37 +00003885 if (12 <= CC && CC <= 15) {
3886 // Name is one of t4-t7
3887 AsmToken RegTok = getLexer().peekTok();
3888 SMRange RegRange = RegTok.getLocRange();
3889
3890 StringRef FixedName = StringSwitch<StringRef>(Name)
3891 .Case("t4", "t0")
3892 .Case("t5", "t1")
3893 .Case("t6", "t2")
3894 .Case("t7", "t3")
3895 .Default("");
3896 assert(FixedName != "" && "Register name is not one of t4-t7.");
3897
3898 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3899 "Did you mean $" + FixedName + "?", RegRange);
3900 }
3901
Toma Tabacufda445c2014-09-15 15:33:01 +00003902 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3903 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3904 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3905 if (8 <= CC && CC <= 11)
3906 CC += 4;
3907
3908 if (CC == -1)
3909 CC = StringSwitch<unsigned>(Name)
3910 .Case("a4", 8)
3911 .Case("a5", 9)
3912 .Case("a6", 10)
3913 .Case("a7", 11)
3914 .Case("kt0", 26)
3915 .Case("kt1", 27)
3916 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003917
3918 return CC;
3919}
Jack Carterd0bd6422013-04-18 00:41:53 +00003920
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003921int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3922 int CC;
3923
3924 CC = StringSwitch<unsigned>(Name)
3925 .Case("hwr_cpunum", 0)
3926 .Case("hwr_synci_step", 1)
3927 .Case("hwr_cc", 2)
3928 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003929 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003930 .Default(-1);
3931
3932 return CC;
3933}
3934
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003935int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003936
Jack Cartera63b16a2012-09-07 00:23:42 +00003937 if (Name[0] == 'f') {
3938 StringRef NumString = Name.substr(1);
3939 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003940 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003941 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003942 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003943 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003944 return IntVal;
3945 }
3946 return -1;
3947}
Jack Cartera63b16a2012-09-07 00:23:42 +00003948
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003949int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3950
3951 if (Name.startswith("fcc")) {
3952 StringRef NumString = Name.substr(3);
3953 unsigned IntVal;
3954 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003955 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003956 if (IntVal > 7) // There are only 8 fcc registers.
3957 return -1;
3958 return IntVal;
3959 }
3960 return -1;
3961}
3962
3963int MipsAsmParser::matchACRegisterName(StringRef Name) {
3964
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003965 if (Name.startswith("ac")) {
3966 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003967 unsigned IntVal;
3968 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003969 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003970 if (IntVal > 3) // There are only 3 acc registers.
3971 return -1;
3972 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003973 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003974 return -1;
3975}
Jack Carterd0bd6422013-04-18 00:41:53 +00003976
Jack Carter5dc8ac92013-09-25 23:50:44 +00003977int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3978 unsigned IntVal;
3979
3980 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3981 return -1;
3982
3983 if (IntVal > 31)
3984 return -1;
3985
3986 return IntVal;
3987}
3988
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003989int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3990 int CC;
3991
3992 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003993 .Case("msair", 0)
3994 .Case("msacsr", 1)
3995 .Case("msaaccess", 2)
3996 .Case("msasave", 3)
3997 .Case("msamodify", 4)
3998 .Case("msarequest", 5)
3999 .Case("msamap", 6)
4000 .Case("msaunmap", 7)
4001 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004002
4003 return CC;
4004}
4005
Toma Tabacu89a712b2015-04-15 10:48:56 +00004006unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004007 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004008 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004009 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004010 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004011 return 0;
4012 }
4013 unsigned AT = getReg(
4014 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004015 return AT;
4016}
Jack Carter0b744b32012-10-04 02:29:46 +00004017
Jack Carterd0bd6422013-04-18 00:41:53 +00004018unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004019 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004020}
4021
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004022unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004023 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00004024 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004025}
4026
Jack Carter873c7242013-01-12 01:03:14 +00004027int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004028 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00004029 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00004030 return -1;
4031
Jack Carter873c7242013-01-12 01:03:14 +00004032 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00004033}
4034
Toma Tabacu13964452014-09-04 13:23:44 +00004035bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004036 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004037 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004038
Jack Carter30a59822012-10-04 04:03:53 +00004039 // Check if the current operand has a custom associated parser, if so, try to
4040 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004041 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4042 if (ResTy == MatchOperand_Success)
4043 return false;
4044 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4045 // there was a match, but an error occurred, in which case, just return that
4046 // the operand parsing failed.
4047 if (ResTy == MatchOperand_ParseFail)
4048 return true;
4049
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004050 DEBUG(dbgs() << ".. Generic Parser\n");
4051
Jack Carterb4dbc172012-09-05 23:34:03 +00004052 switch (getLexer().getKind()) {
4053 default:
4054 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4055 return true;
4056 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004057 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004058 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004059
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004060 // Almost all registers have been parsed by custom parsers. There is only
4061 // one exception to this. $zero (and it's alias $0) will reach this point
4062 // for div, divu, and similar instructions because it is not an operand
4063 // to the instruction definition but an explicit register. Special case
4064 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004065 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004066 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004067
Jack Carterd0bd6422013-04-18 00:41:53 +00004068 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004069 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004070 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004071 return true;
4072
Jack Carter873c7242013-01-12 01:03:14 +00004073 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004074 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004075 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004076 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004077 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004078
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004079 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004080 return false;
4081 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004082 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004083 case AsmToken::LParen:
4084 case AsmToken::Minus:
4085 case AsmToken::Plus:
4086 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004087 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004088 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004089 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004090 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004091 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004092 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004093 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004094 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004095 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004096 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004097 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004098 return true;
4099
Jack Carter873c7242013-01-12 01:03:14 +00004100 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4101
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004102 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004103 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004104 } // case AsmToken::Percent
4105 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004106 return true;
4107}
4108
Vladimir Medic4c299852013-11-06 11:27:05 +00004109const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004110 StringRef RelocStr) {
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004111 if (RelocStr == "hi(%neg(%gp_rel")
4112 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext());
4113 else if (RelocStr == "lo(%neg(%gp_rel")
4114 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004115
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004116 MipsMCExpr::MipsExprKind Kind =
4117 StringSwitch<MipsMCExpr::MipsExprKind>(RelocStr)
4118 .Case("call16", MipsMCExpr::MEK_GOT_CALL)
4119 .Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
4120 .Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
4121 .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
4122 .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
4123 .Case("got", MipsMCExpr::MEK_GOT)
4124 .Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
4125 .Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
4126 .Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
4127 .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
4128 .Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
4129 .Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
4130 .Case("gp_rel", MipsMCExpr::MEK_GPREL)
4131 .Case("hi", MipsMCExpr::MEK_HI)
4132 .Case("higher", MipsMCExpr::MEK_HIGHER)
4133 .Case("highest", MipsMCExpr::MEK_HIGHEST)
4134 .Case("lo", MipsMCExpr::MEK_LO)
4135 .Case("neg", MipsMCExpr::MEK_NEG)
4136 .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
4137 .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
4138 .Case("tlsgd", MipsMCExpr::MEK_TLSGD)
4139 .Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
4140 .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
4141 .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
4142 .Default(MipsMCExpr::MEK_None);
Jack Carterb5cf5902013-04-17 00:18:04 +00004143
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004144 assert(Kind != MipsMCExpr::MEK_None);
4145 return MipsMCExpr::create(Kind, Expr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004146}
4147
4148bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4149
4150 switch (Expr->getKind()) {
4151 case MCExpr::Constant:
4152 return true;
4153 case MCExpr::SymbolRef:
4154 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4155 case MCExpr::Binary:
4156 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4157 if (!isEvaluated(BE->getLHS()))
4158 return false;
4159 return isEvaluated(BE->getRHS());
4160 }
4161 case MCExpr::Unary:
4162 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004163 case MCExpr::Target:
4164 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004165 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004166 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004167}
Jack Carterd0bd6422013-04-18 00:41:53 +00004168
Jack Carterb5cf5902013-04-17 00:18:04 +00004169bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004170 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004171 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004172 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004173 if (Tok.isNot(AsmToken::Identifier))
4174 return true;
4175
Yaron Keren075759a2015-03-30 15:42:36 +00004176 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004177
Jack Carterd0bd6422013-04-18 00:41:53 +00004178 Parser.Lex(); // Eat the identifier.
4179 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004180 const MCExpr *IdVal;
4181 SMLoc EndLoc;
4182
4183 if (getLexer().getKind() == AsmToken::LParen) {
4184 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004185 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004186 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004187 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004188 const AsmToken &nextTok = Parser.getTok();
4189 if (nextTok.isNot(AsmToken::Identifier))
4190 return true;
4191 Str += "(%";
4192 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004193 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004194 if (getLexer().getKind() != AsmToken::LParen)
4195 return true;
4196 } else
4197 break;
4198 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004199 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004200 return true;
4201
4202 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004203 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004204
4205 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004206 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004207
Jack Carterd0bd6422013-04-18 00:41:53 +00004208 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004209 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004210}
4211
Jack Carterb4dbc172012-09-05 23:34:03 +00004212bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4213 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004214 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004215 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004216 if (ResTy == MatchOperand_Success) {
4217 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004218 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004219 StartLoc = Operand.getStartLoc();
4220 EndLoc = Operand.getEndLoc();
4221
4222 // AFAIK, we only support numeric registers and named GPR's in CFI
4223 // directives.
4224 // Don't worry about eating tokens before failing. Using an unrecognised
4225 // register is a parse error.
4226 if (Operand.isGPRAsmReg()) {
4227 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004228 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004229 }
4230
4231 return (RegNo == (unsigned)-1);
4232 }
4233
4234 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004235 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004236}
4237
Jack Carterb5cf5902013-04-17 00:18:04 +00004238bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004239 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004240 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004241 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004242 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004243
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004244 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004245 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004246 ++NumOfLParen;
4247 }
Jack Carter873c7242013-01-12 01:03:14 +00004248
Jack Carterd0bd6422013-04-18 00:41:53 +00004249 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004250 default:
4251 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004252 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004253 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004254 case AsmToken::Integer:
4255 case AsmToken::Minus:
4256 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004257 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004258 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004259 else
4260 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004261 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004262 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004263 break;
Jack Carter873c7242013-01-12 01:03:14 +00004264 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004265 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004266 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004267 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004268}
4269
David Blaikie960ea3f2014-06-08 16:18:35 +00004270MipsAsmParser::OperandMatchResultTy
4271MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004272 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004273 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004274 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004275 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004276 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004277 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004278 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004279 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004280
Jack Carterb5cf5902013-04-17 00:18:04 +00004281 if (getLexer().getKind() == AsmToken::LParen) {
4282 Parser.Lex();
4283 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004284 }
4285
Jack Carterb5cf5902013-04-17 00:18:04 +00004286 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004287 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004288 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004289
Jack Carterd0bd6422013-04-18 00:41:53 +00004290 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004291 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004292 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004293 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004294 SMLoc E =
4295 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004296 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004297 return MatchOperand_Success;
4298 }
4299 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004300 SMLoc E =
4301 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004302
Jack Carterd0bd6422013-04-18 00:41:53 +00004303 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004304 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004305 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004306 S, E, *this);
4307 Operands.push_back(
4308 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004309 return MatchOperand_Success;
4310 }
4311 Error(Parser.getTok().getLoc(), "'(' expected");
4312 return MatchOperand_ParseFail;
4313 }
4314
Jack Carterd0bd6422013-04-18 00:41:53 +00004315 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004316 }
4317
Toma Tabacu13964452014-09-04 13:23:44 +00004318 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004319 if (Res != MatchOperand_Success)
4320 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004321
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004322 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004323 Error(Parser.getTok().getLoc(), "')' expected");
4324 return MatchOperand_ParseFail;
4325 }
4326
Jack Carter873c7242013-01-12 01:03:14 +00004327 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4328
Jack Carterd0bd6422013-04-18 00:41:53 +00004329 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004330
Craig Topper062a2ba2014-04-25 05:30:21 +00004331 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004332 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004333
Jack Carterd0bd6422013-04-18 00:41:53 +00004334 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004335 std::unique_ptr<MipsOperand> op(
4336 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004337 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004338 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004339 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004340 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004341 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4342 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004343 if (IdVal->evaluateAsAbsolute(Imm))
4344 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004345 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004346 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004347 getContext());
4348 }
4349
David Blaikie960ea3f2014-06-08 16:18:35 +00004350 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004351 return MatchOperand_Success;
4352}
4353
David Blaikie960ea3f2014-06-08 16:18:35 +00004354bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004355 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004356 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004357 if (Sym) {
4358 SMLoc S = Parser.getTok().getLoc();
4359 const MCExpr *Expr;
4360 if (Sym->isVariable())
4361 Expr = Sym->getVariableValue();
4362 else
4363 return false;
4364 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004365 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004366 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004367 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004368 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004369 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004370 if (ResTy == MatchOperand_Success) {
4371 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004372 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004373 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004374 llvm_unreachable("Should never ParseFail");
4375 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004376 }
4377 } else if (Expr->getKind() == MCExpr::Constant) {
4378 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004379 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004380 Operands.push_back(
4381 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004382 return true;
4383 }
4384 }
4385 return false;
4386}
Jack Carterd0bd6422013-04-18 00:41:53 +00004387
Jack Carter873c7242013-01-12 01:03:14 +00004388MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004389MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004390 StringRef Identifier,
4391 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004392 int Index = matchCPURegisterName(Identifier);
4393 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004394 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004395 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4396 return MatchOperand_Success;
4397 }
4398
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004399 Index = matchHWRegsRegisterName(Identifier);
4400 if (Index != -1) {
4401 Operands.push_back(MipsOperand::createHWRegsReg(
4402 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4403 return MatchOperand_Success;
4404 }
4405
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004406 Index = matchFPURegisterName(Identifier);
4407 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004408 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004409 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4410 return MatchOperand_Success;
4411 }
4412
4413 Index = matchFCCRegisterName(Identifier);
4414 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004415 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004416 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4417 return MatchOperand_Success;
4418 }
4419
4420 Index = matchACRegisterName(Identifier);
4421 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004422 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004423 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4424 return MatchOperand_Success;
4425 }
4426
4427 Index = matchMSA128RegisterName(Identifier);
4428 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004429 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004430 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4431 return MatchOperand_Success;
4432 }
4433
4434 Index = matchMSA128CtrlRegisterName(Identifier);
4435 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004436 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004437 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4438 return MatchOperand_Success;
4439 }
4440
4441 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004442}
4443
4444MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004445MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004446 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004447 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004448
4449 if (Token.is(AsmToken::Identifier)) {
4450 DEBUG(dbgs() << ".. identifier\n");
4451 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004452 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004453 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004454 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004455 } else if (Token.is(AsmToken::Integer)) {
4456 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004457 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004458 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4459 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004460 return MatchOperand_Success;
4461 }
4462
4463 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4464
4465 return MatchOperand_NoMatch;
4466}
4467
David Blaikie960ea3f2014-06-08 16:18:35 +00004468MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004469MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004470 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004471 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004472
4473 auto Token = Parser.getTok();
4474
4475 SMLoc S = Token.getLoc();
4476
4477 if (Token.isNot(AsmToken::Dollar)) {
4478 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4479 if (Token.is(AsmToken::Identifier)) {
4480 if (searchSymbolAlias(Operands))
4481 return MatchOperand_Success;
4482 }
4483 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4484 return MatchOperand_NoMatch;
4485 }
4486 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004487
Toma Tabacu13964452014-09-04 13:23:44 +00004488 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004489 if (ResTy == MatchOperand_Success) {
4490 Parser.Lex(); // $
4491 Parser.Lex(); // identifier
4492 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004493 return ResTy;
4494}
4495
4496MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004497MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004498 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004499 switch (getLexer().getKind()) {
4500 default:
4501 return MatchOperand_NoMatch;
4502 case AsmToken::LParen:
4503 case AsmToken::Minus:
4504 case AsmToken::Plus:
4505 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004506 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004507 case AsmToken::String:
4508 break;
4509 }
4510
4511 const MCExpr *IdVal;
4512 SMLoc S = Parser.getTok().getLoc();
4513 if (getParser().parseExpression(IdVal))
4514 return MatchOperand_ParseFail;
4515
4516 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4517 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4518 return MatchOperand_Success;
4519}
4520
David Blaikie960ea3f2014-06-08 16:18:35 +00004521MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004522MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004523 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004524 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004525
4526 SMLoc S = getLexer().getLoc();
4527
4528 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004529 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004530 if (ResTy != MatchOperand_NoMatch)
4531 return ResTy;
4532
Daniel Sanders315386c2014-04-01 10:40:14 +00004533 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004534 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004535 if (ResTy != MatchOperand_NoMatch)
4536 return ResTy;
4537
Daniel Sandersffd84362014-04-01 10:41:48 +00004538 const MCExpr *Expr = nullptr;
4539 if (Parser.parseExpression(Expr)) {
4540 // We have no way of knowing if a symbol was consumed so we must ParseFail
4541 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004542 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004543 Operands.push_back(
4544 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004545 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004546}
4547
Vladimir Medic2b953d02013-10-01 09:48:56 +00004548MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004549MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004550 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004551 const MCExpr *IdVal;
4552 // If the first token is '$' we may have register operand.
4553 if (Parser.getTok().is(AsmToken::Dollar))
4554 return MatchOperand_NoMatch;
4555 SMLoc S = Parser.getTok().getLoc();
4556 if (getParser().parseExpression(IdVal))
4557 return MatchOperand_ParseFail;
4558 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004559 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004560 int64_t Val = MCE->getValue();
4561 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4562 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004563 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004564 return MatchOperand_Success;
4565}
4566
Matheus Almeida779c5932013-11-18 12:32:49 +00004567MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004568MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004569 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004570 switch (getLexer().getKind()) {
4571 default:
4572 return MatchOperand_NoMatch;
4573 case AsmToken::LParen:
4574 case AsmToken::Plus:
4575 case AsmToken::Minus:
4576 case AsmToken::Integer:
4577 break;
4578 }
4579
4580 const MCExpr *Expr;
4581 SMLoc S = Parser.getTok().getLoc();
4582
4583 if (getParser().parseExpression(Expr))
4584 return MatchOperand_ParseFail;
4585
4586 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004587 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004588 Error(S, "expected immediate value");
4589 return MatchOperand_ParseFail;
4590 }
4591
4592 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4593 // and because the CPU always adds one to the immediate field, the allowed
4594 // range becomes 1..4. We'll only check the range here and will deal
4595 // with the addition/subtraction when actually decoding/encoding
4596 // the instruction.
4597 if (Val < 1 || Val > 4) {
4598 Error(S, "immediate not in range (1..4)");
4599 return MatchOperand_ParseFail;
4600 }
4601
Jack Carter3b2c96e2014-01-22 23:31:38 +00004602 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004603 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004604 return MatchOperand_Success;
4605}
4606
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004607MipsAsmParser::OperandMatchResultTy
4608MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4609 MCAsmParser &Parser = getParser();
4610 SmallVector<unsigned, 10> Regs;
4611 unsigned RegNo;
4612 unsigned PrevReg = Mips::NoRegister;
4613 bool RegRange = false;
4614 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4615
4616 if (Parser.getTok().isNot(AsmToken::Dollar))
4617 return MatchOperand_ParseFail;
4618
4619 SMLoc S = Parser.getTok().getLoc();
4620 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4621 SMLoc E = getLexer().getLoc();
4622 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4623 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4624 if (RegRange) {
4625 // Remove last register operand because registers from register range
4626 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004627 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4628 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004629 Regs.push_back(RegNo);
4630 } else {
4631 unsigned TmpReg = PrevReg + 1;
4632 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004633 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4634 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4635 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004636 Error(E, "invalid register operand");
4637 return MatchOperand_ParseFail;
4638 }
4639
4640 PrevReg = TmpReg;
4641 Regs.push_back(TmpReg++);
4642 }
4643 }
4644
4645 RegRange = false;
4646 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004647 if ((PrevReg == Mips::NoRegister) &&
4648 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4649 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004650 Error(E, "$16 or $31 expected");
4651 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004652 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4653 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4654 !isGP64bit()) ||
4655 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4656 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4657 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004658 Error(E, "invalid register operand");
4659 return MatchOperand_ParseFail;
4660 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004661 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4662 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4663 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004664 Error(E, "consecutive register numbers expected");
4665 return MatchOperand_ParseFail;
4666 }
4667
4668 Regs.push_back(RegNo);
4669 }
4670
4671 if (Parser.getTok().is(AsmToken::Minus))
4672 RegRange = true;
4673
4674 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4675 !Parser.getTok().isNot(AsmToken::Comma)) {
4676 Error(E, "',' or '-' expected");
4677 return MatchOperand_ParseFail;
4678 }
4679
4680 Lex(); // Consume comma or minus
4681 if (Parser.getTok().isNot(AsmToken::Dollar))
4682 break;
4683
4684 PrevReg = RegNo;
4685 }
4686
4687 SMLoc E = Parser.getTok().getLoc();
4688 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4689 parseMemOperand(Operands);
4690 return MatchOperand_Success;
4691}
4692
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004693MipsAsmParser::OperandMatchResultTy
4694MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4695 MCAsmParser &Parser = getParser();
4696
4697 SMLoc S = Parser.getTok().getLoc();
4698 if (parseAnyRegister(Operands) != MatchOperand_Success)
4699 return MatchOperand_ParseFail;
4700
4701 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00004702 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00004703
Benjamin Kramer2b68d152016-05-09 10:31:17 +00004704 Operands.pop_back();
4705 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004706 return MatchOperand_Success;
4707}
4708
Zoran Jovanovic41688672015-02-10 16:36:20 +00004709MipsAsmParser::OperandMatchResultTy
4710MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4711 MCAsmParser &Parser = getParser();
4712 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4713 SmallVector<unsigned, 10> Regs;
4714
4715 if (Parser.getTok().isNot(AsmToken::Dollar))
4716 return MatchOperand_ParseFail;
4717
4718 SMLoc S = Parser.getTok().getLoc();
4719
4720 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4721 return MatchOperand_ParseFail;
4722
4723 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4724 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4725 Regs.push_back(RegNo);
4726
4727 SMLoc E = Parser.getTok().getLoc();
4728 if (Parser.getTok().isNot(AsmToken::Comma)) {
4729 Error(E, "',' expected");
4730 return MatchOperand_ParseFail;
4731 }
4732
4733 // Remove comma.
4734 Parser.Lex();
4735
4736 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4737 return MatchOperand_ParseFail;
4738
4739 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4740 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4741 Regs.push_back(RegNo);
4742
4743 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4744
4745 return MatchOperand_Success;
4746}
4747
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004748/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4749/// either this.
4750/// ::= '(', register, ')'
4751/// handle it before we iterate so we don't get tripped up by the lack of
4752/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004753bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004754 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004755 if (getLexer().is(AsmToken::LParen)) {
4756 Operands.push_back(
4757 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4758 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004759 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004760 SMLoc Loc = getLexer().getLoc();
4761 Parser.eatToEndOfStatement();
4762 return Error(Loc, "unexpected token in argument list");
4763 }
4764 if (Parser.getTok().isNot(AsmToken::RParen)) {
4765 SMLoc Loc = getLexer().getLoc();
4766 Parser.eatToEndOfStatement();
4767 return Error(Loc, "unexpected token, expected ')'");
4768 }
4769 Operands.push_back(
4770 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4771 Parser.Lex();
4772 }
4773 return false;
4774}
4775
4776/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4777/// either one of these.
4778/// ::= '[', register, ']'
4779/// ::= '[', integer, ']'
4780/// handle it before we iterate so we don't get tripped up by the lack of
4781/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004782bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004783 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004784 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004785 if (getLexer().is(AsmToken::LBrac)) {
4786 Operands.push_back(
4787 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4788 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004789 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004790 SMLoc Loc = getLexer().getLoc();
4791 Parser.eatToEndOfStatement();
4792 return Error(Loc, "unexpected token in argument list");
4793 }
4794 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4795 SMLoc Loc = getLexer().getLoc();
4796 Parser.eatToEndOfStatement();
4797 return Error(Loc, "unexpected token, expected ']'");
4798 }
4799 Operands.push_back(
4800 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4801 Parser.Lex();
4802 }
4803 return false;
4804}
4805
David Blaikie960ea3f2014-06-08 16:18:35 +00004806bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4807 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004808 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004809 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004810
4811 // We have reached first instruction, module directive are now forbidden.
4812 getTargetStreamer().forbidModuleDirective();
4813
Vladimir Medic74593e62013-07-17 15:00:42 +00004814 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004815 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004816 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004817 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004818 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004819 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004820 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004821
4822 // Read the remaining operands.
4823 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4824 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004825 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004826 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004827 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004828 return Error(Loc, "unexpected token in argument list");
4829 }
Toma Tabacu13964452014-09-04 13:23:44 +00004830 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004831 return true;
4832 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004833
Jack Carterd0bd6422013-04-18 00:41:53 +00004834 while (getLexer().is(AsmToken::Comma)) {
4835 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004836 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004837 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004838 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004839 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004840 return Error(Loc, "unexpected token in argument list");
4841 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004842 // Parse bracket and parenthesis suffixes before we iterate
4843 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004844 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004845 return true;
4846 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004847 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004848 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004849 }
4850 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004851 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4852 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004853 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004854 return Error(Loc, "unexpected token in argument list");
4855 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004856 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004857 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004858}
4859
Nirav Dave996fc132016-05-05 14:15:46 +00004860// FIXME: Given that these have the same name, these should both be
4861// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004862bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004863 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004864 SMLoc Loc = getLexer().getLoc();
4865 Parser.eatToEndOfStatement();
4866 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004867}
4868
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004869bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004870 return Error(Loc, ErrorMsg);
4871}
4872
Jack Carter0b744b32012-10-04 02:29:46 +00004873bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004874 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004875 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004876
4877 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004878 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004879
4880 Parser.Lex(); // Eat "noat".
4881
Jack Carterd0bd6422013-04-18 00:41:53 +00004882 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004883 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004884 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004885 return false;
4886 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004887
4888 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004889 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004890 return false;
4891}
Jack Carterd0bd6422013-04-18 00:41:53 +00004892
Jack Carter0b744b32012-10-04 02:29:46 +00004893bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004894 // Line can be: ".set at", which sets $at to $1
4895 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004896 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004897 Parser.Lex(); // Eat "at".
4898
Jack Carter0b744b32012-10-04 02:29:46 +00004899 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004900 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004901 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004902
4903 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004904 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004905 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004906 }
4907
4908 if (getLexer().isNot(AsmToken::Equal)) {
4909 reportParseError("unexpected token, expected equals sign");
4910 return false;
4911 }
4912 Parser.Lex(); // Eat "=".
4913
4914 if (getLexer().isNot(AsmToken::Dollar)) {
4915 if (getLexer().is(AsmToken::EndOfStatement)) {
4916 reportParseError("no register specified");
4917 return false;
4918 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004919 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004920 return false;
4921 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004922 }
4923 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004924
Toma Tabacu16a74492015-02-13 10:30:57 +00004925 // Find out what "reg" is.
4926 unsigned AtRegNo;
4927 const AsmToken &Reg = Parser.getTok();
4928 if (Reg.is(AsmToken::Identifier)) {
4929 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4930 } else if (Reg.is(AsmToken::Integer)) {
4931 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004932 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004933 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004934 return false;
4935 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004936
4937 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004938 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004939 reportParseError("invalid register");
4940 return false;
4941 }
4942 Parser.Lex(); // Eat "reg".
4943
4944 // If this is not the end of the statement, report an error.
4945 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4946 reportParseError("unexpected token, expected end of statement");
4947 return false;
4948 }
4949
4950 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4951
4952 Parser.Lex(); // Consume the EndOfStatement.
4953 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004954}
4955
4956bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004957 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004958 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004959 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004960 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004961 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004962 return false;
4963 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004964 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004965 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004966 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004967 return false;
4968}
4969
4970bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004971 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004972 Parser.Lex();
4973 // If this is not the end of the statement, report an error.
4974 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004975 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004976 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004977 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004978 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004979 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004980 Parser.Lex(); // Consume the EndOfStatement.
4981 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004982}
4983
4984bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004985 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004986 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004987 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004988 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004989 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004990 return false;
4991 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004992 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004993 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004994 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004995 return false;
4996}
4997
4998bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004999 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005000 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005001 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005002 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005003 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005004 return false;
5005 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005006 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005007 reportParseError("`noreorder' must be set before `nomacro'");
5008 return false;
5009 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005010 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005011 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005012 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005013 return false;
5014}
Jack Carterd76b2372013-03-21 21:44:16 +00005015
Daniel Sanders44934432014-08-07 12:03:36 +00005016bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005017 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005018 Parser.Lex();
5019
5020 // If this is not the end of the statement, report an error.
5021 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005022 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005023
5024 setFeatureBits(Mips::FeatureMSA, "msa");
5025 getTargetStreamer().emitDirectiveSetMsa();
5026 return false;
5027}
5028
5029bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005030 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005031 Parser.Lex();
5032
5033 // If this is not the end of the statement, report an error.
5034 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005035 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005036
5037 clearFeatureBits(Mips::FeatureMSA, "msa");
5038 getTargetStreamer().emitDirectiveSetNoMsa();
5039 return false;
5040}
5041
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005042bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005043 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005044 Parser.Lex(); // Eat "nodsp".
5045
5046 // If this is not the end of the statement, report an error.
5047 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5048 reportParseError("unexpected token, expected end of statement");
5049 return false;
5050 }
5051
5052 clearFeatureBits(Mips::FeatureDSP, "dsp");
5053 getTargetStreamer().emitDirectiveSetNoDsp();
5054 return false;
5055}
5056
Toma Tabacucc2502d2014-11-04 17:18:07 +00005057bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005058 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005059 Parser.Lex(); // Eat "mips16".
5060
Jack Carter39536722014-01-22 23:08:42 +00005061 // If this is not the end of the statement, report an error.
5062 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005063 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005064 return false;
5065 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005066
5067 setFeatureBits(Mips::FeatureMips16, "mips16");
5068 getTargetStreamer().emitDirectiveSetMips16();
5069 Parser.Lex(); // Consume the EndOfStatement.
5070 return false;
5071}
5072
5073bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005074 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005075 Parser.Lex(); // Eat "nomips16".
5076
5077 // If this is not the end of the statement, report an error.
5078 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5079 reportParseError("unexpected token, expected end of statement");
5080 return false;
5081 }
5082
5083 clearFeatureBits(Mips::FeatureMips16, "mips16");
5084 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005085 Parser.Lex(); // Consume the EndOfStatement.
5086 return false;
5087}
5088
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005089bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005090 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005091 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005092 // Line can be: .set fp=32
5093 // .set fp=xx
5094 // .set fp=64
5095 Parser.Lex(); // Eat fp token
5096 AsmToken Tok = Parser.getTok();
5097 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005098 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005099 return false;
5100 }
5101 Parser.Lex(); // Eat '=' token.
5102 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005103
5104 if (!parseFpABIValue(FpAbiVal, ".set"))
5105 return false;
5106
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005107 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005108 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005109 return false;
5110 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005111 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005112 Parser.Lex(); // Consume the EndOfStatement.
5113 return false;
5114}
5115
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005116bool MipsAsmParser::parseSetOddSPRegDirective() {
5117 MCAsmParser &Parser = getParser();
5118
5119 Parser.Lex(); // Eat "oddspreg".
5120 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5121 reportParseError("unexpected token, expected end of statement");
5122 return false;
5123 }
5124
5125 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5126 getTargetStreamer().emitDirectiveSetOddSPReg();
5127 return false;
5128}
5129
5130bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5131 MCAsmParser &Parser = getParser();
5132
5133 Parser.Lex(); // Eat "nooddspreg".
5134 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5135 reportParseError("unexpected token, expected end of statement");
5136 return false;
5137 }
5138
5139 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5140 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5141 return false;
5142}
5143
Toma Tabacu9db22db2014-09-09 10:15:38 +00005144bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005145 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005146 SMLoc Loc = getLexer().getLoc();
5147
5148 Parser.Lex();
5149 if (getLexer().isNot(AsmToken::EndOfStatement))
5150 return reportParseError("unexpected token, expected end of statement");
5151
5152 // Always keep an element on the options "stack" to prevent the user
5153 // from changing the initial options. This is how we remember them.
5154 if (AssemblerOptions.size() == 2)
5155 return reportParseError(Loc, ".set pop with no .set push");
5156
Akira Hatanakab11ef082015-11-14 06:35:56 +00005157 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005158 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005159 setAvailableFeatures(
5160 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5161 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005162
5163 getTargetStreamer().emitDirectiveSetPop();
5164 return false;
5165}
5166
5167bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005168 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005169 Parser.Lex();
5170 if (getLexer().isNot(AsmToken::EndOfStatement))
5171 return reportParseError("unexpected token, expected end of statement");
5172
5173 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005174 AssemblerOptions.push_back(
5175 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005176
5177 getTargetStreamer().emitDirectiveSetPush();
5178 return false;
5179}
5180
Toma Tabacu29696502015-06-02 09:48:04 +00005181bool MipsAsmParser::parseSetSoftFloatDirective() {
5182 MCAsmParser &Parser = getParser();
5183 Parser.Lex();
5184 if (getLexer().isNot(AsmToken::EndOfStatement))
5185 return reportParseError("unexpected token, expected end of statement");
5186
5187 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5188 getTargetStreamer().emitDirectiveSetSoftFloat();
5189 return false;
5190}
5191
5192bool MipsAsmParser::parseSetHardFloatDirective() {
5193 MCAsmParser &Parser = getParser();
5194 Parser.Lex();
5195 if (getLexer().isNot(AsmToken::EndOfStatement))
5196 return reportParseError("unexpected token, expected end of statement");
5197
5198 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5199 getTargetStreamer().emitDirectiveSetHardFloat();
5200 return false;
5201}
5202
Jack Carterd76b2372013-03-21 21:44:16 +00005203bool MipsAsmParser::parseSetAssignment() {
5204 StringRef Name;
5205 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005206 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005207
5208 if (Parser.parseIdentifier(Name))
5209 reportParseError("expected identifier after .set");
5210
5211 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005212 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005213 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005214
Jack Carter3b2c96e2014-01-22 23:31:38 +00005215 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005216 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005217
Jim Grosbach6f482002015-05-18 18:43:14 +00005218 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005219 Sym->setVariableValue(Value);
5220
5221 return false;
5222}
Jack Carterd0bd6422013-04-18 00:41:53 +00005223
Toma Tabacu26647792014-09-09 12:52:14 +00005224bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005225 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005226 Parser.Lex();
5227 if (getLexer().isNot(AsmToken::EndOfStatement))
5228 return reportParseError("unexpected token, expected end of statement");
5229
5230 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005231 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005232 setAvailableFeatures(
5233 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5234 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005235 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5236
5237 getTargetStreamer().emitDirectiveSetMips0();
5238 return false;
5239}
5240
Toma Tabacu85618b32014-08-19 14:22:52 +00005241bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005242 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005243 Parser.Lex();
5244 if (getLexer().isNot(AsmToken::Equal))
5245 return reportParseError("unexpected token, expected equals sign");
5246
5247 Parser.Lex();
5248 StringRef Arch;
5249 if (Parser.parseIdentifier(Arch))
5250 return reportParseError("expected arch identifier");
5251
5252 StringRef ArchFeatureName =
5253 StringSwitch<StringRef>(Arch)
5254 .Case("mips1", "mips1")
5255 .Case("mips2", "mips2")
5256 .Case("mips3", "mips3")
5257 .Case("mips4", "mips4")
5258 .Case("mips5", "mips5")
5259 .Case("mips32", "mips32")
5260 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005261 .Case("mips32r3", "mips32r3")
5262 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005263 .Case("mips32r6", "mips32r6")
5264 .Case("mips64", "mips64")
5265 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005266 .Case("mips64r3", "mips64r3")
5267 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005268 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005269 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005270 .Case("r4000", "mips3") // This is an implementation of Mips3.
5271 .Default("");
5272
5273 if (ArchFeatureName.empty())
5274 return reportParseError("unsupported architecture");
5275
5276 selectArch(ArchFeatureName);
5277 getTargetStreamer().emitDirectiveSetArch(Arch);
5278 return false;
5279}
5280
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005281bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005282 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005283 Parser.Lex();
5284 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005285 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005286
Matheus Almeida2852af82014-04-22 10:15:54 +00005287 switch (Feature) {
5288 default:
5289 llvm_unreachable("Unimplemented feature");
5290 case Mips::FeatureDSP:
5291 setFeatureBits(Mips::FeatureDSP, "dsp");
5292 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005293 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005294 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00005295 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00005296 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005297 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005298 case Mips::FeatureMips1:
5299 selectArch("mips1");
5300 getTargetStreamer().emitDirectiveSetMips1();
5301 break;
5302 case Mips::FeatureMips2:
5303 selectArch("mips2");
5304 getTargetStreamer().emitDirectiveSetMips2();
5305 break;
5306 case Mips::FeatureMips3:
5307 selectArch("mips3");
5308 getTargetStreamer().emitDirectiveSetMips3();
5309 break;
5310 case Mips::FeatureMips4:
5311 selectArch("mips4");
5312 getTargetStreamer().emitDirectiveSetMips4();
5313 break;
5314 case Mips::FeatureMips5:
5315 selectArch("mips5");
5316 getTargetStreamer().emitDirectiveSetMips5();
5317 break;
5318 case Mips::FeatureMips32:
5319 selectArch("mips32");
5320 getTargetStreamer().emitDirectiveSetMips32();
5321 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005322 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005323 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005324 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005325 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005326 case Mips::FeatureMips32r3:
5327 selectArch("mips32r3");
5328 getTargetStreamer().emitDirectiveSetMips32R3();
5329 break;
5330 case Mips::FeatureMips32r5:
5331 selectArch("mips32r5");
5332 getTargetStreamer().emitDirectiveSetMips32R5();
5333 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005334 case Mips::FeatureMips32r6:
5335 selectArch("mips32r6");
5336 getTargetStreamer().emitDirectiveSetMips32R6();
5337 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005338 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005339 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005340 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005341 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005342 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005343 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005344 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005345 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005346 case Mips::FeatureMips64r3:
5347 selectArch("mips64r3");
5348 getTargetStreamer().emitDirectiveSetMips64R3();
5349 break;
5350 case Mips::FeatureMips64r5:
5351 selectArch("mips64r5");
5352 getTargetStreamer().emitDirectiveSetMips64R5();
5353 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005354 case Mips::FeatureMips64r6:
5355 selectArch("mips64r6");
5356 getTargetStreamer().emitDirectiveSetMips64R6();
5357 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005358 }
5359 return false;
5360}
5361
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005362bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005363 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005364 if (getLexer().isNot(AsmToken::Comma)) {
5365 SMLoc Loc = getLexer().getLoc();
5366 Parser.eatToEndOfStatement();
5367 return Error(Loc, ErrorStr);
5368 }
5369
Matheus Almeida2852af82014-04-22 10:15:54 +00005370 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005371 return true;
5372}
5373
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005374// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5375// In this class, it is only used for .cprestore.
5376// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5377// MipsTargetELFStreamer and MipsAsmParser.
5378bool MipsAsmParser::isPicAndNotNxxAbi() {
5379 return inPicMode() && !(isABI_N32() || isABI_N64());
5380}
5381
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005382bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005383 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005384 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005385
Toma Tabacudde4c462014-11-06 10:02:45 +00005386 if (inMips16Mode()) {
5387 reportParseError(".cpload is not supported in Mips16 mode");
5388 return false;
5389 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005390
David Blaikie960ea3f2014-06-08 16:18:35 +00005391 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005392 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005393 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5394 reportParseError("expected register containing function address");
5395 return false;
5396 }
5397
David Blaikie960ea3f2014-06-08 16:18:35 +00005398 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5399 if (!RegOpnd.isGPRAsmReg()) {
5400 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005401 return false;
5402 }
5403
Toma Tabacudde4c462014-11-06 10:02:45 +00005404 // If this is not the end of the statement, report an error.
5405 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5406 reportParseError("unexpected token, expected end of statement");
5407 return false;
5408 }
5409
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005410 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005411 return false;
5412}
5413
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005414bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5415 MCAsmParser &Parser = getParser();
5416
5417 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5418 // is used in non-PIC mode.
5419
5420 if (inMips16Mode()) {
5421 reportParseError(".cprestore is not supported in Mips16 mode");
5422 return false;
5423 }
5424
5425 // Get the stack offset value.
5426 const MCExpr *StackOffset;
5427 int64_t StackOffsetVal;
5428 if (Parser.parseExpression(StackOffset)) {
5429 reportParseError("expected stack offset value");
5430 return false;
5431 }
5432
5433 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5434 reportParseError("stack offset is not an absolute expression");
5435 return false;
5436 }
5437
5438 if (StackOffsetVal < 0) {
5439 Warning(Loc, ".cprestore with negative stack offset has no effect");
5440 IsCpRestoreSet = false;
5441 } else {
5442 IsCpRestoreSet = true;
5443 CpRestoreOffset = StackOffsetVal;
5444 }
5445
5446 // If this is not the end of the statement, report an error.
5447 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5448 reportParseError("unexpected token, expected end of statement");
5449 return false;
5450 }
5451
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005452 if (!getTargetStreamer().emitDirectiveCpRestore(
5453 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005454 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005455 Parser.Lex(); // Consume the EndOfStatement.
5456 return false;
5457}
5458
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005459bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005460 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005461 unsigned FuncReg;
5462 unsigned Save;
5463 bool SaveIsReg = true;
5464
Matheus Almeida7e815762014-06-18 13:08:59 +00005465 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005466 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005467 if (ResTy == MatchOperand_NoMatch) {
5468 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005469 return false;
5470 }
5471
5472 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5473 if (!FuncRegOpnd.isGPRAsmReg()) {
5474 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5475 Parser.eatToEndOfStatement();
5476 return false;
5477 }
5478
5479 FuncReg = FuncRegOpnd.getGPR32Reg();
5480 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005481
Toma Tabacu65f10572014-09-16 15:00:52 +00005482 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005483 return true;
5484
Toma Tabacu13964452014-09-04 13:23:44 +00005485 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005486 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005487 const MCExpr *OffsetExpr;
5488 int64_t OffsetVal;
5489 SMLoc ExprLoc = getLexer().getLoc();
5490
5491 if (Parser.parseExpression(OffsetExpr) ||
5492 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5493 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005494 Parser.eatToEndOfStatement();
5495 return false;
5496 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005497
5498 Save = OffsetVal;
5499 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005500 } else {
5501 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5502 if (!SaveOpnd.isGPRAsmReg()) {
5503 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5504 Parser.eatToEndOfStatement();
5505 return false;
5506 }
5507 Save = SaveOpnd.getGPR32Reg();
5508 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005509
Toma Tabacu65f10572014-09-16 15:00:52 +00005510 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005511 return true;
5512
Toma Tabacu8874eac2015-02-18 13:46:53 +00005513 const MCExpr *Expr;
5514 if (Parser.parseExpression(Expr)) {
5515 reportParseError("expected expression");
5516 return false;
5517 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005518
Toma Tabacu8874eac2015-02-18 13:46:53 +00005519 if (Expr->getKind() != MCExpr::SymbolRef) {
5520 reportParseError("expected symbol");
5521 return false;
5522 }
5523 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5524
Daniel Sandersf173dda2015-09-22 10:50:09 +00005525 CpSaveLocation = Save;
5526 CpSaveLocationIsRegister = SaveIsReg;
5527
Toma Tabacu8874eac2015-02-18 13:46:53 +00005528 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5529 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005530 return false;
5531}
5532
Daniel Sandersf173dda2015-09-22 10:50:09 +00005533bool MipsAsmParser::parseDirectiveCPReturn() {
5534 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5535 CpSaveLocationIsRegister);
5536 return false;
5537}
5538
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005539bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005540 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005541 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5542 const AsmToken &Tok = Parser.getTok();
5543
5544 if (Tok.getString() == "2008") {
5545 Parser.Lex();
5546 getTargetStreamer().emitDirectiveNaN2008();
5547 return false;
5548 } else if (Tok.getString() == "legacy") {
5549 Parser.Lex();
5550 getTargetStreamer().emitDirectiveNaNLegacy();
5551 return false;
5552 }
5553 }
5554 // If we don't recognize the option passed to the .nan
5555 // directive (e.g. no option or unknown option), emit an error.
5556 reportParseError("invalid option in .nan directive");
5557 return false;
5558}
5559
Jack Carter0b744b32012-10-04 02:29:46 +00005560bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005561 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005562 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005563 const AsmToken &Tok = Parser.getTok();
5564
5565 if (Tok.getString() == "noat") {
5566 return parseSetNoAtDirective();
5567 } else if (Tok.getString() == "at") {
5568 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005569 } else if (Tok.getString() == "arch") {
5570 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005571 } else if (Tok.getString() == "fp") {
5572 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005573 } else if (Tok.getString() == "oddspreg") {
5574 return parseSetOddSPRegDirective();
5575 } else if (Tok.getString() == "nooddspreg") {
5576 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005577 } else if (Tok.getString() == "pop") {
5578 return parseSetPopDirective();
5579 } else if (Tok.getString() == "push") {
5580 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005581 } else if (Tok.getString() == "reorder") {
5582 return parseSetReorderDirective();
5583 } else if (Tok.getString() == "noreorder") {
5584 return parseSetNoReorderDirective();
5585 } else if (Tok.getString() == "macro") {
5586 return parseSetMacroDirective();
5587 } else if (Tok.getString() == "nomacro") {
5588 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005589 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005590 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005591 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005592 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005593 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00005594 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005595 getTargetStreamer().emitDirectiveSetNoMicroMips();
5596 Parser.eatToEndOfStatement();
5597 return false;
5598 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005599 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005600 } else if (Tok.getString() == "mips0") {
5601 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005602 } else if (Tok.getString() == "mips1") {
5603 return parseSetFeature(Mips::FeatureMips1);
5604 } else if (Tok.getString() == "mips2") {
5605 return parseSetFeature(Mips::FeatureMips2);
5606 } else if (Tok.getString() == "mips3") {
5607 return parseSetFeature(Mips::FeatureMips3);
5608 } else if (Tok.getString() == "mips4") {
5609 return parseSetFeature(Mips::FeatureMips4);
5610 } else if (Tok.getString() == "mips5") {
5611 return parseSetFeature(Mips::FeatureMips5);
5612 } else if (Tok.getString() == "mips32") {
5613 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005614 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005615 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005616 } else if (Tok.getString() == "mips32r3") {
5617 return parseSetFeature(Mips::FeatureMips32r3);
5618 } else if (Tok.getString() == "mips32r5") {
5619 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005620 } else if (Tok.getString() == "mips32r6") {
5621 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005622 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005623 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005624 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005625 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005626 } else if (Tok.getString() == "mips64r3") {
5627 return parseSetFeature(Mips::FeatureMips64r3);
5628 } else if (Tok.getString() == "mips64r5") {
5629 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005630 } else if (Tok.getString() == "mips64r6") {
5631 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005632 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005633 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005634 } else if (Tok.getString() == "nodsp") {
5635 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005636 } else if (Tok.getString() == "msa") {
5637 return parseSetMsaDirective();
5638 } else if (Tok.getString() == "nomsa") {
5639 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005640 } else if (Tok.getString() == "softfloat") {
5641 return parseSetSoftFloatDirective();
5642 } else if (Tok.getString() == "hardfloat") {
5643 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005644 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005645 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005646 parseSetAssignment();
5647 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005648 }
Jack Carter07c818d2013-01-25 01:31:34 +00005649
Jack Carter0b744b32012-10-04 02:29:46 +00005650 return true;
5651}
5652
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005653/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005654/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005655bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005656 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005657 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5658 for (;;) {
5659 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005660 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005661 return true;
5662
5663 getParser().getStreamer().EmitValue(Value, Size);
5664
5665 if (getLexer().is(AsmToken::EndOfStatement))
5666 break;
5667
Jack Carter07c818d2013-01-25 01:31:34 +00005668 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005669 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005670 Parser.Lex();
5671 }
5672 }
5673
5674 Parser.Lex();
5675 return false;
5676}
5677
Vladimir Medic4c299852013-11-06 11:27:05 +00005678/// parseDirectiveGpWord
5679/// ::= .gpword local_sym
5680bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005681 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005682 const MCExpr *Value;
5683 // EmitGPRel32Value requires an expression, so we are using base class
5684 // method to evaluate the expression.
5685 if (getParser().parseExpression(Value))
5686 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005687 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005688
Vladimir Medice10c1122013-11-13 13:18:04 +00005689 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005690 return Error(getLexer().getLoc(),
5691 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005692 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005693 return false;
5694}
5695
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005696/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005697/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005698bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005699 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005700 const MCExpr *Value;
5701 // EmitGPRel64Value requires an expression, so we are using base class
5702 // method to evaluate the expression.
5703 if (getParser().parseExpression(Value))
5704 return true;
5705 getParser().getStreamer().EmitGPRel64Value(Value);
5706
5707 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005708 return Error(getLexer().getLoc(),
5709 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005710 Parser.Lex(); // Eat EndOfStatement token.
5711 return false;
5712}
5713
Jack Carter0cd3c192014-01-06 23:27:31 +00005714bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005715 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005716 // Get the option token.
5717 AsmToken Tok = Parser.getTok();
5718 // At the moment only identifiers are supported.
5719 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005720 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005721 Parser.eatToEndOfStatement();
5722 return false;
5723 }
5724
5725 StringRef Option = Tok.getIdentifier();
5726
5727 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005728 // MipsAsmParser needs to know if the current PIC mode changes.
5729 IsPicEnabled = false;
5730
Jack Carter0cd3c192014-01-06 23:27:31 +00005731 getTargetStreamer().emitDirectiveOptionPic0();
5732 Parser.Lex();
5733 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5734 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005735 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005736 Parser.eatToEndOfStatement();
5737 }
5738 return false;
5739 }
5740
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005741 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005742 // MipsAsmParser needs to know if the current PIC mode changes.
5743 IsPicEnabled = true;
5744
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005745 getTargetStreamer().emitDirectiveOptionPic2();
5746 Parser.Lex();
5747 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5748 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005749 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005750 Parser.eatToEndOfStatement();
5751 }
5752 return false;
5753 }
5754
Jack Carter0cd3c192014-01-06 23:27:31 +00005755 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005756 Warning(Parser.getTok().getLoc(),
5757 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005758 Parser.eatToEndOfStatement();
5759 return false;
5760}
5761
Toma Tabacu9ca50962015-04-16 09:53:47 +00005762/// parseInsnDirective
5763/// ::= .insn
5764bool MipsAsmParser::parseInsnDirective() {
5765 // If this is not the end of the statement, report an error.
5766 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5767 reportParseError("unexpected token, expected end of statement");
5768 return false;
5769 }
5770
5771 // The actual label marking happens in
5772 // MipsELFStreamer::createPendingLabelRelocs().
5773 getTargetStreamer().emitDirectiveInsn();
5774
5775 getParser().Lex(); // Eat EndOfStatement token.
5776 return false;
5777}
5778
Simon Atanasyanbe186202016-02-11 06:45:54 +00005779/// parseSSectionDirective
5780/// ::= .sbss
5781/// ::= .sdata
5782bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5783 // If this is not the end of the statement, report an error.
5784 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5785 reportParseError("unexpected token, expected end of statement");
5786 return false;
5787 }
5788
5789 MCSection *ELFSection = getContext().getELFSection(
5790 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5791 getParser().getStreamer().SwitchSection(ELFSection);
5792
5793 getParser().Lex(); // Eat EndOfStatement token.
5794 return false;
5795}
5796
Daniel Sanders7e527422014-07-10 13:38:23 +00005797/// parseDirectiveModule
5798/// ::= .module oddspreg
5799/// ::= .module nooddspreg
5800/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005801/// ::= .module softfloat
5802/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005803bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005804 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005805 MCAsmLexer &Lexer = getLexer();
5806 SMLoc L = Lexer.getLoc();
5807
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005808 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005809 // TODO : get a better message.
5810 reportParseError(".module directive must appear before any code");
5811 return false;
5812 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005813
Toma Tabacuc405c822015-01-23 10:40:19 +00005814 StringRef Option;
5815 if (Parser.parseIdentifier(Option)) {
5816 reportParseError("expected .module option identifier");
5817 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005818 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005819
Toma Tabacuc405c822015-01-23 10:40:19 +00005820 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005821 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005822
Toma Tabacu3c499582015-06-25 10:56:57 +00005823 // Synchronize the abiflags information with the FeatureBits information we
5824 // changed above.
5825 getTargetStreamer().updateABIInfo(*this);
5826
5827 // If printing assembly, use the recently updated abiflags information.
5828 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5829 // emitted at the end).
5830 getTargetStreamer().emitDirectiveModuleOddSPReg();
5831
Toma Tabacuc405c822015-01-23 10:40:19 +00005832 // If this is not the end of the statement, report an error.
5833 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5834 reportParseError("unexpected token, expected end of statement");
5835 return false;
5836 }
5837
5838 return false; // parseDirectiveModule has finished successfully.
5839 } else if (Option == "nooddspreg") {
5840 if (!isABI_O32()) {
5841 Error(L, "'.module nooddspreg' requires the O32 ABI");
5842 return false;
5843 }
5844
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005845 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005846
Toma Tabacu3c499582015-06-25 10:56:57 +00005847 // Synchronize the abiflags information with the FeatureBits information we
5848 // changed above.
5849 getTargetStreamer().updateABIInfo(*this);
5850
5851 // If printing assembly, use the recently updated abiflags information.
5852 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5853 // emitted at the end).
5854 getTargetStreamer().emitDirectiveModuleOddSPReg();
5855
Toma Tabacuc405c822015-01-23 10:40:19 +00005856 // If this is not the end of the statement, report an error.
5857 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5858 reportParseError("unexpected token, expected end of statement");
5859 return false;
5860 }
5861
5862 return false; // parseDirectiveModule has finished successfully.
5863 } else if (Option == "fp") {
5864 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005865 } else if (Option == "softfloat") {
5866 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5867
5868 // Synchronize the ABI Flags information with the FeatureBits information we
5869 // updated above.
5870 getTargetStreamer().updateABIInfo(*this);
5871
5872 // If printing assembly, use the recently updated ABI Flags information.
5873 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5874 // emitted later).
5875 getTargetStreamer().emitDirectiveModuleSoftFloat();
5876
5877 // If this is not the end of the statement, report an error.
5878 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5879 reportParseError("unexpected token, expected end of statement");
5880 return false;
5881 }
5882
5883 return false; // parseDirectiveModule has finished successfully.
5884 } else if (Option == "hardfloat") {
5885 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5886
5887 // Synchronize the ABI Flags information with the FeatureBits information we
5888 // updated above.
5889 getTargetStreamer().updateABIInfo(*this);
5890
5891 // If printing assembly, use the recently updated ABI Flags information.
5892 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5893 // emitted later).
5894 getTargetStreamer().emitDirectiveModuleHardFloat();
5895
5896 // If this is not the end of the statement, report an error.
5897 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5898 reportParseError("unexpected token, expected end of statement");
5899 return false;
5900 }
5901
5902 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005903 } else {
5904 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5905 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005906}
5907
5908/// parseDirectiveModuleFP
5909/// ::= =32
5910/// ::= =xx
5911/// ::= =64
5912bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005913 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005914 MCAsmLexer &Lexer = getLexer();
5915
5916 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005917 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005918 return false;
5919 }
5920 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005921
Daniel Sanders7e527422014-07-10 13:38:23 +00005922 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005923 if (!parseFpABIValue(FpABI, ".module"))
5924 return false;
5925
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005926 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005927 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005928 return false;
5929 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005930
Toma Tabacua64e5402015-06-25 12:44:38 +00005931 // Synchronize the abiflags information with the FeatureBits information we
5932 // changed above.
5933 getTargetStreamer().updateABIInfo(*this);
5934
5935 // If printing assembly, use the recently updated abiflags information.
5936 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5937 // emitted at the end).
5938 getTargetStreamer().emitDirectiveModuleFP();
5939
Daniel Sanders7e527422014-07-10 13:38:23 +00005940 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005941 return false;
5942}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005943
Daniel Sanders7e527422014-07-10 13:38:23 +00005944bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005945 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005946 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005947 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005948 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005949
5950 if (Lexer.is(AsmToken::Identifier)) {
5951 StringRef Value = Parser.getTok().getString();
5952 Parser.Lex();
5953
5954 if (Value != "xx") {
5955 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5956 return false;
5957 }
5958
5959 if (!isABI_O32()) {
5960 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5961 return false;
5962 }
5963
Daniel Sanders7e527422014-07-10 13:38:23 +00005964 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005965 if (ModuleLevelOptions) {
5966 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5967 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5968 } else {
5969 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5970 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5971 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005972 return true;
5973 }
5974
5975 if (Lexer.is(AsmToken::Integer)) {
5976 unsigned Value = Parser.getTok().getIntVal();
5977 Parser.Lex();
5978
5979 if (Value != 32 && Value != 64) {
5980 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5981 return false;
5982 }
5983
5984 if (Value == 32) {
5985 if (!isABI_O32()) {
5986 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5987 return false;
5988 }
5989
Daniel Sanders7e527422014-07-10 13:38:23 +00005990 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005991 if (ModuleLevelOptions) {
5992 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5993 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5994 } else {
5995 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5996 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5997 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005998 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005999 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006000 if (ModuleLevelOptions) {
6001 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6002 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6003 } else {
6004 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6005 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6006 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006007 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006008
Daniel Sanders7e527422014-07-10 13:38:23 +00006009 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006010 }
6011
6012 return false;
6013}
6014
Jack Carter0b744b32012-10-04 02:29:46 +00006015bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006016 // This returns false if this function recognizes the directive
6017 // regardless of whether it is successfully handles or reports an
6018 // error. Otherwise it returns true to give the generic parser a
6019 // chance at recognizing it.
6020
Rafael Espindola961d4692014-11-11 05:18:41 +00006021 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006022 StringRef IDVal = DirectiveID.getString();
6023
Nirav Dave996fc132016-05-05 14:15:46 +00006024 if (IDVal == ".cpload") {
6025 parseDirectiveCpLoad(DirectiveID.getLoc());
6026 return false;
6027 }
6028 if (IDVal == ".cprestore") {
6029 parseDirectiveCpRestore(DirectiveID.getLoc());
6030 return false;
6031 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006032 if (IDVal == ".dword") {
6033 parseDataDirective(8, DirectiveID.getLoc());
6034 return false;
6035 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006036 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006037 StringRef SymbolName;
6038
6039 if (Parser.parseIdentifier(SymbolName)) {
6040 reportParseError("expected identifier after .ent");
6041 return false;
6042 }
6043
6044 // There's an undocumented extension that allows an integer to
6045 // follow the name of the procedure which AFAICS is ignored by GAS.
6046 // Example: .ent foo,2
6047 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6048 if (getLexer().isNot(AsmToken::Comma)) {
6049 // Even though we accept this undocumented extension for compatibility
6050 // reasons, the additional integer argument does not actually change
6051 // the behaviour of the '.ent' directive, so we would like to discourage
6052 // its use. We do this by not referring to the extended version in
6053 // error messages which are not directly related to its use.
6054 reportParseError("unexpected token, expected end of statement");
6055 return false;
6056 }
6057 Parser.Lex(); // Eat the comma.
6058 const MCExpr *DummyNumber;
6059 int64_t DummyNumberVal;
6060 // If the user was explicitly trying to use the extended version,
6061 // we still give helpful extension-related error messages.
6062 if (Parser.parseExpression(DummyNumber)) {
6063 reportParseError("expected number after comma");
6064 return false;
6065 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006066 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006067 reportParseError("expected an absolute expression after comma");
6068 return false;
6069 }
6070 }
6071
6072 // If this is not the end of the statement, report an error.
6073 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6074 reportParseError("unexpected token, expected end of statement");
6075 return false;
6076 }
6077
Jim Grosbach6f482002015-05-18 18:43:14 +00006078 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006079
6080 getTargetStreamer().emitDirectiveEnt(*Sym);
6081 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006082 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006083 return false;
6084 }
6085
Jack Carter07c818d2013-01-25 01:31:34 +00006086 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006087 StringRef SymbolName;
6088
6089 if (Parser.parseIdentifier(SymbolName)) {
6090 reportParseError("expected identifier after .end");
6091 return false;
6092 }
6093
6094 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6095 reportParseError("unexpected token, expected end of statement");
6096 return false;
6097 }
6098
6099 if (CurrentFn == nullptr) {
6100 reportParseError(".end used without .ent");
6101 return false;
6102 }
6103
6104 if ((SymbolName != CurrentFn->getName())) {
6105 reportParseError(".end symbol does not match .ent symbol");
6106 return false;
6107 }
6108
6109 getTargetStreamer().emitDirectiveEnd(SymbolName);
6110 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006111 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006112 return false;
6113 }
6114
Jack Carter07c818d2013-01-25 01:31:34 +00006115 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006116 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6117 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006118 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006119 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6120 reportParseError("expected stack register");
6121 return false;
6122 }
6123
6124 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6125 if (!StackRegOpnd.isGPRAsmReg()) {
6126 reportParseError(StackRegOpnd.getStartLoc(),
6127 "expected general purpose register");
6128 return false;
6129 }
6130 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6131
6132 if (Parser.getTok().is(AsmToken::Comma))
6133 Parser.Lex();
6134 else {
6135 reportParseError("unexpected token, expected comma");
6136 return false;
6137 }
6138
6139 // Parse the frame size.
6140 const MCExpr *FrameSize;
6141 int64_t FrameSizeVal;
6142
6143 if (Parser.parseExpression(FrameSize)) {
6144 reportParseError("expected frame size value");
6145 return false;
6146 }
6147
Jim Grosbach13760bd2015-05-30 01:25:56 +00006148 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006149 reportParseError("frame size not an absolute expression");
6150 return false;
6151 }
6152
6153 if (Parser.getTok().is(AsmToken::Comma))
6154 Parser.Lex();
6155 else {
6156 reportParseError("unexpected token, expected comma");
6157 return false;
6158 }
6159
6160 // Parse the return register.
6161 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006162 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006163 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6164 reportParseError("expected return register");
6165 return false;
6166 }
6167
6168 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6169 if (!ReturnRegOpnd.isGPRAsmReg()) {
6170 reportParseError(ReturnRegOpnd.getStartLoc(),
6171 "expected general purpose register");
6172 return false;
6173 }
6174
6175 // If this is not the end of the statement, report an error.
6176 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6177 reportParseError("unexpected token, expected end of statement");
6178 return false;
6179 }
6180
6181 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6182 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006183 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006184 return false;
6185 }
6186
Jack Carter07c818d2013-01-25 01:31:34 +00006187 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006188 parseDirectiveSet();
6189 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006190 }
6191
Daniel Sandersd97a6342014-08-13 10:07:34 +00006192 if (IDVal == ".mask" || IDVal == ".fmask") {
6193 // .mask bitmask, frame_offset
6194 // bitmask: One bit for each register used.
6195 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6196 // first register is expected to be saved.
6197 // Examples:
6198 // .mask 0x80000000, -4
6199 // .fmask 0x80000000, -4
6200 //
Jack Carterbe332172012-09-07 00:48:02 +00006201
Daniel Sandersd97a6342014-08-13 10:07:34 +00006202 // Parse the bitmask
6203 const MCExpr *BitMask;
6204 int64_t BitMaskVal;
6205
6206 if (Parser.parseExpression(BitMask)) {
6207 reportParseError("expected bitmask value");
6208 return false;
6209 }
6210
Jim Grosbach13760bd2015-05-30 01:25:56 +00006211 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006212 reportParseError("bitmask not an absolute expression");
6213 return false;
6214 }
6215
6216 if (Parser.getTok().is(AsmToken::Comma))
6217 Parser.Lex();
6218 else {
6219 reportParseError("unexpected token, expected comma");
6220 return false;
6221 }
6222
6223 // Parse the frame_offset
6224 const MCExpr *FrameOffset;
6225 int64_t FrameOffsetVal;
6226
6227 if (Parser.parseExpression(FrameOffset)) {
6228 reportParseError("expected frame offset value");
6229 return false;
6230 }
6231
Jim Grosbach13760bd2015-05-30 01:25:56 +00006232 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006233 reportParseError("frame offset not an absolute expression");
6234 return false;
6235 }
6236
6237 // If this is not the end of the statement, report an error.
6238 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6239 reportParseError("unexpected token, expected end of statement");
6240 return false;
6241 }
6242
6243 if (IDVal == ".mask")
6244 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6245 else
6246 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006247 return false;
6248 }
6249
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006250 if (IDVal == ".nan")
6251 return parseDirectiveNaN();
6252
Jack Carter07c818d2013-01-25 01:31:34 +00006253 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006254 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006255 return false;
6256 }
6257
Rafael Espindolab59fb732014-03-28 18:50:26 +00006258 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006259 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006260 return false;
6261 }
6262
Jack Carter07c818d2013-01-25 01:31:34 +00006263 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006264 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006265 return false;
6266 }
6267
Scott Egertond1aeb052016-02-15 16:11:51 +00006268 if (IDVal == ".hword") {
6269 parseDataDirective(2, DirectiveID.getLoc());
6270 return false;
6271 }
6272
Nirav Dave996fc132016-05-05 14:15:46 +00006273 if (IDVal == ".option") {
6274 parseDirectiveOption();
6275 return false;
6276 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006277
6278 if (IDVal == ".abicalls") {
6279 getTargetStreamer().emitDirectiveAbiCalls();
6280 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006281 Error(Parser.getTok().getLoc(),
6282 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006283 // Clear line
6284 Parser.eatToEndOfStatement();
6285 }
6286 return false;
6287 }
6288
Nirav Dave996fc132016-05-05 14:15:46 +00006289 if (IDVal == ".cpsetup") {
6290 parseDirectiveCPSetup();
6291 return false;
6292 }
6293 if (IDVal == ".cpreturn") {
6294 parseDirectiveCPReturn();
6295 return false;
6296 }
6297 if (IDVal == ".module") {
6298 parseDirectiveModule();
6299 return false;
6300 }
6301 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6302 parseInternalDirectiveReallowModule();
6303 return false;
6304 }
6305 if (IDVal == ".insn") {
6306 parseInsnDirective();
6307 return false;
6308 }
6309 if (IDVal == ".sbss") {
6310 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6311 return false;
6312 }
6313 if (IDVal == ".sdata") {
6314 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6315 return false;
6316 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006317
Rafael Espindola870c4e92012-01-11 03:56:41 +00006318 return true;
6319}
6320
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006321bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6322 // If this is not the end of the statement, report an error.
6323 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6324 reportParseError("unexpected token, expected end of statement");
6325 return false;
6326 }
6327
6328 getTargetStreamer().reallowModuleDirective();
6329
6330 getParser().Lex(); // Eat EndOfStatement token.
6331 return false;
6332}
6333
Rafael Espindola870c4e92012-01-11 03:56:41 +00006334extern "C" void LLVMInitializeMipsAsmParser() {
6335 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6336 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6337 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6338 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6339}
Jack Carterb4dbc172012-09-05 23:34:03 +00006340
6341#define GET_REGISTER_MATCHER
6342#define GET_MATCHER_IMPLEMENTATION
6343#include "MipsGenAsmMatcher.inc"