blob: 16ec118aba6d11348a6f8e0c82629b3b390c227d [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:
Zlatko Buljane663e342016-05-19 07:31:28 +00001569 case Mips::BC1EQZC_MMR6:
1570 case Mips::BC1NEZC_MMR6:
1571 case Mips::BC2EQZC_MMR6:
1572 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001573 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001574 Offset = Inst.getOperand(1);
1575 if (!Offset.isImm())
1576 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001577 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001578 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001579 if (OffsetToAlignment(Offset.getImm(),
1580 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001581 return Error(IDLoc, "branch to misaligned address");
1582 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001583 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001584 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001585 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001586 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001587 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1588 Offset = Inst.getOperand(1);
1589 if (!Offset.isImm())
1590 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001591 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001592 return Error(IDLoc, "branch target out of range");
1593 if (OffsetToAlignment(Offset.getImm(), 2LL))
1594 return Error(IDLoc, "branch to misaligned address");
1595 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001596 }
1597 }
1598
Daniel Sandersa84989a2014-06-16 13:25:35 +00001599 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1600 // We still accept it but it is a normal nop.
1601 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1602 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1603 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1604 "nop instruction");
1605 }
1606
Kai Nackee0245392015-01-27 19:11:28 +00001607 if (hasCnMips()) {
1608 const unsigned Opcode = Inst.getOpcode();
1609 MCOperand Opnd;
1610 int Imm;
1611
1612 switch (Opcode) {
1613 default:
1614 break;
1615
1616 case Mips::BBIT0:
1617 case Mips::BBIT032:
1618 case Mips::BBIT1:
1619 case Mips::BBIT132:
1620 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1621 // The offset is handled above
1622 Opnd = Inst.getOperand(1);
1623 if (!Opnd.isImm())
1624 return Error(IDLoc, "expected immediate operand kind");
1625 Imm = Opnd.getImm();
1626 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1627 Opcode == Mips::BBIT1 ? 63 : 31))
1628 return Error(IDLoc, "immediate operand value out of range");
1629 if (Imm > 31) {
1630 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1631 : Mips::BBIT132);
1632 Inst.getOperand(1).setImm(Imm - 32);
1633 }
1634 break;
1635
Kai Nackee0245392015-01-27 19:11:28 +00001636 case Mips::SEQi:
1637 case Mips::SNEi:
1638 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1639 Opnd = Inst.getOperand(2);
1640 if (!Opnd.isImm())
1641 return Error(IDLoc, "expected immediate operand kind");
1642 Imm = Opnd.getImm();
1643 if (!isInt<10>(Imm))
1644 return Error(IDLoc, "immediate operand value out of range");
1645 break;
1646 }
1647 }
1648
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001649 // This expansion is not in a function called by tryExpandInstruction()
1650 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001651 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1652 inPicMode()) {
1653 warnIfNoMacro(IDLoc);
1654
1655 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1656
1657 // We can do this expansion if there's only 1 symbol in the argument
1658 // expression.
1659 if (countMCSymbolRefExpr(JalExpr) > 1)
1660 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1661
1662 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001663 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001664 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1665
1666 // FIXME: Add support for label+offset operands (currently causes an error).
1667 // FIXME: Add support for forward-declared local symbols.
1668 // FIXME: Add expansion for when the LargeGOT option is enabled.
1669 if (JalSym->isInSection() || JalSym->isTemporary()) {
1670 if (isABI_O32()) {
1671 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001672 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001673 // R_(MICRO)MIPS_GOT16 label
1674 // addiu $25, $25, 0
1675 // R_(MICRO)MIPS_LO16 label
1676 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001677 const MCExpr *Got16RelocExpr =
1678 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1679 const MCExpr *Lo16RelocExpr =
1680 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001681
Daniel Sandersa736b372016-04-29 13:33:12 +00001682 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1683 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1684 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1685 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001686 } else if (isABI_N32() || isABI_N64()) {
1687 // If it's a local symbol and the N32/N64 ABIs are being used,
1688 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001689 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001690 // R_(MICRO)MIPS_GOT_DISP label
1691 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001692 const MCExpr *GotDispRelocExpr =
1693 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001694
Daniel Sandersa736b372016-04-29 13:33:12 +00001695 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1696 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1697 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001698 }
1699 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001700 // If it's an external/weak symbol, we expand to:
1701 // lw/ld $25, 0($gp)
1702 // R_(MICRO)MIPS_CALL16 label
1703 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001704 const MCExpr *Call16RelocExpr =
1705 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001706
Daniel Sandersa736b372016-04-29 13:33:12 +00001707 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1708 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001709 }
1710
1711 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001712 if (IsCpRestoreSet && inMicroMipsMode())
1713 JalrInst.setOpcode(Mips::JALRS_MM);
1714 else
1715 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001716 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1717 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1718
1719 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1720 // This relocation is supposed to be an optimization hint for the linker
1721 // and is not necessary for correctness.
1722
1723 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001724 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001725 }
1726
Jack Carter9e65aa32013-03-22 00:05:30 +00001727 if (MCID.mayLoad() || MCID.mayStore()) {
1728 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001729 // reference or immediate we may have to expand instructions.
1730 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001731 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001732 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1733 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001734 MCOperand &Op = Inst.getOperand(i);
1735 if (Op.isImm()) {
1736 int MemOffset = Op.getImm();
1737 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001738 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001739 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001740 return false;
1741 }
1742 } else if (Op.isExpr()) {
1743 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001744 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001745 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001746 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001747 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001748 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001749 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001750 return false;
1751 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001752 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001753 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001754 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001755 }
1756 }
1757 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001758 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001759 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001760
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001761 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001762 if (MCID.mayLoad()) {
1763 // Try to create 16-bit GP relative load instruction.
1764 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1765 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1766 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1767 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1768 MCOperand &Op = Inst.getOperand(i);
1769 if (Op.isImm()) {
1770 int MemOffset = Op.getImm();
1771 MCOperand &DstReg = Inst.getOperand(0);
1772 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001773 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001774 getContext().getRegisterInfo()->getRegClass(
1775 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001776 (BaseReg.getReg() == Mips::GP ||
1777 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001778
Daniel Sandersa736b372016-04-29 13:33:12 +00001779 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1780 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001781 return false;
1782 }
1783 }
1784 }
1785 } // for
1786 } // if load
1787
1788 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1789
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001790 MCOperand Opnd;
1791 int Imm;
1792
1793 switch (Inst.getOpcode()) {
1794 default:
1795 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001796 case Mips::ADDIUSP_MM:
1797 Opnd = Inst.getOperand(0);
1798 if (!Opnd.isImm())
1799 return Error(IDLoc, "expected immediate operand kind");
1800 Imm = Opnd.getImm();
1801 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1802 Imm % 4 != 0)
1803 return Error(IDLoc, "immediate operand value out of range");
1804 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001805 case Mips::SLL16_MM:
1806 case Mips::SRL16_MM:
1807 Opnd = Inst.getOperand(2);
1808 if (!Opnd.isImm())
1809 return Error(IDLoc, "expected immediate operand kind");
1810 Imm = Opnd.getImm();
1811 if (Imm < 1 || Imm > 8)
1812 return Error(IDLoc, "immediate operand value out of range");
1813 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001814 case Mips::LI16_MM:
1815 Opnd = Inst.getOperand(1);
1816 if (!Opnd.isImm())
1817 return Error(IDLoc, "expected immediate operand kind");
1818 Imm = Opnd.getImm();
1819 if (Imm < -1 || Imm > 126)
1820 return Error(IDLoc, "immediate operand value out of range");
1821 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001822 case Mips::ADDIUR2_MM:
1823 Opnd = Inst.getOperand(2);
1824 if (!Opnd.isImm())
1825 return Error(IDLoc, "expected immediate operand kind");
1826 Imm = Opnd.getImm();
1827 if (!(Imm == 1 || Imm == -1 ||
1828 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1829 return Error(IDLoc, "immediate operand value out of range");
1830 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001831 case Mips::ANDI16_MM:
1832 Opnd = Inst.getOperand(2);
1833 if (!Opnd.isImm())
1834 return Error(IDLoc, "expected immediate operand kind");
1835 Imm = Opnd.getImm();
1836 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1837 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1838 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1839 return Error(IDLoc, "immediate operand value out of range");
1840 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001841 case Mips::LBU16_MM:
1842 Opnd = Inst.getOperand(2);
1843 if (!Opnd.isImm())
1844 return Error(IDLoc, "expected immediate operand kind");
1845 Imm = Opnd.getImm();
1846 if (Imm < -1 || Imm > 14)
1847 return Error(IDLoc, "immediate operand value out of range");
1848 break;
1849 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001850 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001851 Opnd = Inst.getOperand(2);
1852 if (!Opnd.isImm())
1853 return Error(IDLoc, "expected immediate operand kind");
1854 Imm = Opnd.getImm();
1855 if (Imm < 0 || Imm > 15)
1856 return Error(IDLoc, "immediate operand value out of range");
1857 break;
1858 case Mips::LHU16_MM:
1859 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001860 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001861 Opnd = Inst.getOperand(2);
1862 if (!Opnd.isImm())
1863 return Error(IDLoc, "expected immediate operand kind");
1864 Imm = Opnd.getImm();
1865 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1866 return Error(IDLoc, "immediate operand value out of range");
1867 break;
1868 case Mips::LW16_MM:
1869 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001870 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001871 Opnd = Inst.getOperand(2);
1872 if (!Opnd.isImm())
1873 return Error(IDLoc, "expected immediate operand kind");
1874 Imm = Opnd.getImm();
1875 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1876 return Error(IDLoc, "immediate operand value out of range");
1877 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001878 case Mips::ADDIUPC_MM:
1879 MCOperand Opnd = Inst.getOperand(1);
1880 if (!Opnd.isImm())
1881 return Error(IDLoc, "expected immediate operand kind");
1882 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001883 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001884 return Error(IDLoc, "immediate operand value out of range");
1885 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001886 }
1887 }
1888
Daniel Sandersd8c07762016-04-18 12:35:36 +00001889 bool FillDelaySlot =
1890 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
1891 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00001892 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001893
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001894 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001895 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001896 switch (ExpandResult) {
1897 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001898 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001899 break;
1900 case MER_Success:
1901 break;
1902 case MER_Fail:
1903 return true;
1904 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001905
Daniel Sanderscda908a2016-05-16 09:10:13 +00001906 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
1907 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
1908 if (inMicroMipsMode())
1909 TOut.setUsesMicroMips();
1910
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001911 // If this instruction has a delay slot and .set reorder is active,
1912 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00001913 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001914 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
1915 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001916 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001917
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001918 if ((Inst.getOpcode() == Mips::JalOneReg ||
1919 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1920 isPicAndNotNxxAbi()) {
1921 if (IsCpRestoreSet) {
1922 // We need a NOP between the JALR and the LW:
1923 // If .set reorder has been used, we've already emitted a NOP.
1924 // If .set noreorder has been used, we need to emit a NOP at this point.
1925 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00001926 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
1927 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001928
1929 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00001930 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001931 } else
1932 Warning(IDLoc, "no .cprestore used in PIC mode");
1933 }
1934
Jack Carter9e65aa32013-03-22 00:05:30 +00001935 return false;
1936}
1937
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001938MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001939MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
1940 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001941 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001942 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001943 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001944 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001945 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001946 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001947 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001948 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001949 case Mips::LoadAddrImm64:
1950 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1951 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1952 "expected immediate operand kind");
1953
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001954 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1955 Inst.getOperand(1),
1956 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001957 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001958 ? MER_Fail
1959 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001960 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001961 case Mips::LoadAddrReg64:
1962 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1963 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1964 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1965 "expected immediate operand kind");
1966
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001967 return expandLoadAddress(Inst.getOperand(0).getReg(),
1968 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1969 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001970 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001971 ? MER_Fail
1972 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001973 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001974 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001975 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
1976 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001977 case Mips::SWM_MM:
1978 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001979 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
1980 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001981 case Mips::JalOneReg:
1982 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001983 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00001984 case Mips::BneImm:
1985 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001986 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00001987 case Mips::BLT:
1988 case Mips::BLE:
1989 case Mips::BGE:
1990 case Mips::BGT:
1991 case Mips::BLTU:
1992 case Mips::BLEU:
1993 case Mips::BGEU:
1994 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001995 case Mips::BLTL:
1996 case Mips::BLEL:
1997 case Mips::BGEL:
1998 case Mips::BGTL:
1999 case Mips::BLTUL:
2000 case Mips::BLEUL:
2001 case Mips::BGEUL:
2002 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002003 case Mips::BLTImmMacro:
2004 case Mips::BLEImmMacro:
2005 case Mips::BGEImmMacro:
2006 case Mips::BGTImmMacro:
2007 case Mips::BLTUImmMacro:
2008 case Mips::BLEUImmMacro:
2009 case Mips::BGEUImmMacro:
2010 case Mips::BGTUImmMacro:
2011 case Mips::BLTLImmMacro:
2012 case Mips::BLELImmMacro:
2013 case Mips::BGELImmMacro:
2014 case Mips::BGTLImmMacro:
2015 case Mips::BLTULImmMacro:
2016 case Mips::BLEULImmMacro:
2017 case Mips::BGEULImmMacro:
2018 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002019 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002020 case Mips::SDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002021 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2022 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002023 case Mips::DSDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002024 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2025 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002026 case Mips::UDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002027 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2028 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002029 case Mips::DUDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002030 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2031 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002032 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002033 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2034 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002035 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002036 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002037 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002038 case Mips::PseudoTRUNC_W_D:
2039 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2040 : MER_Success;
2041 case Mips::Ulh:
2042 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2043 case Mips::Ulhu:
2044 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2045 case Mips::Ulw:
2046 return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2047 case Mips::NORImm:
2048 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002049 case Mips::ADDi:
2050 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002051 case Mips::SLTi:
2052 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002053 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2054 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2055 int64_t ImmValue = Inst.getOperand(2).getImm();
2056 if (isInt<16>(ImmValue))
2057 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002058 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2059 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002060 }
2061 return MER_NotAMacro;
2062 case Mips::ANDi:
2063 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002064 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002065 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2066 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2067 int64_t ImmValue = Inst.getOperand(2).getImm();
2068 if (isUInt<16>(ImmValue))
2069 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002070 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2071 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002072 }
2073 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002074 case Mips::ROL:
2075 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002076 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002077 case Mips::ROLImm:
2078 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002079 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002080 case Mips::DROL:
2081 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002082 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002083 case Mips::DROLImm:
2084 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002085 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002086 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002087 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002088 }
Jack Carter30a59822012-10-04 04:03:53 +00002089}
Jack Carter92995f12012-10-06 00:53:28 +00002090
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002091bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002092 MCStreamer &Out,
2093 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002094 MipsTargetStreamer &TOut = getTargetStreamer();
2095
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002096 // Create a JALR instruction which is going to replace the pseudo-JAL.
2097 MCInst JalrInst;
2098 JalrInst.setLoc(IDLoc);
2099 const MCOperand FirstRegOp = Inst.getOperand(0);
2100 const unsigned Opcode = Inst.getOpcode();
2101
2102 if (Opcode == Mips::JalOneReg) {
2103 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002104 if (IsCpRestoreSet && inMicroMipsMode()) {
2105 JalrInst.setOpcode(Mips::JALRS16_MM);
2106 JalrInst.addOperand(FirstRegOp);
2107 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002108 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002109 JalrInst.addOperand(FirstRegOp);
2110 } else {
2111 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002112 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002113 JalrInst.addOperand(FirstRegOp);
2114 }
2115 } else if (Opcode == Mips::JalTwoReg) {
2116 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002117 if (IsCpRestoreSet && inMicroMipsMode())
2118 JalrInst.setOpcode(Mips::JALRS_MM);
2119 else
2120 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002121 JalrInst.addOperand(FirstRegOp);
2122 const MCOperand SecondRegOp = Inst.getOperand(1);
2123 JalrInst.addOperand(SecondRegOp);
2124 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002125 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002126
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002127 // If .set reorder is active and branch instruction has a delay slot,
2128 // emit a NOP after it.
2129 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002130 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2131 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2132 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002133
2134 return false;
2135}
2136
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002137/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002138template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002139 unsigned BitNum = findFirstSet(x);
2140
2141 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2142}
2143
2144/// Load (or add) an immediate into a register.
2145///
2146/// @param ImmValue The immediate to load.
2147/// @param DstReg The register that will hold the immediate.
2148/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2149/// for a simple initialization.
2150/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2151/// @param IsAddress True if the immediate represents an address. False if it
2152/// is an integer.
2153/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002154bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002155 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002156 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2157 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002158 MipsTargetStreamer &TOut = getTargetStreamer();
2159
Toma Tabacu00e98672015-05-01 12:19:27 +00002160 if (!Is32BitImm && !isGP64bit()) {
2161 Error(IDLoc, "instruction requires a 64-bit architecture");
2162 return true;
2163 }
2164
Daniel Sanders03f9c012015-07-14 12:24:22 +00002165 if (Is32BitImm) {
2166 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2167 // Sign extend up to 64-bit so that the predicates match the hardware
2168 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2169 // true.
2170 ImmValue = SignExtend64<32>(ImmValue);
2171 } else {
2172 Error(IDLoc, "instruction requires a 32-bit immediate");
2173 return true;
2174 }
2175 }
2176
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002177 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2178 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2179
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002180 bool UseSrcReg = false;
2181 if (SrcReg != Mips::NoRegister)
2182 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002183
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002184 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002185 if (UseSrcReg &&
2186 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002187 // At this point we need AT to perform the expansions and we exit if it is
2188 // not available.
2189 unsigned ATReg = getATReg(IDLoc);
2190 if (!ATReg)
2191 return true;
2192 TmpReg = ATReg;
2193 }
2194
Daniel Sanders03f9c012015-07-14 12:24:22 +00002195 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002196 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002197 SrcReg = ZeroReg;
2198
2199 // This doesn't quite follow the usual ABI expectations for N32 but matches
2200 // traditional assembler behaviour. N32 would normally use addiu for both
2201 // integers and addresses.
2202 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002203 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002204 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002205 }
2206
Daniel Sandersa736b372016-04-29 13:33:12 +00002207 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002208 return false;
2209 }
2210
2211 if (isUInt<16>(ImmValue)) {
2212 unsigned TmpReg = DstReg;
2213 if (SrcReg == DstReg) {
2214 TmpReg = getATReg(IDLoc);
2215 if (!TmpReg)
2216 return true;
2217 }
2218
Daniel Sandersa736b372016-04-29 13:33:12 +00002219 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002220 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002221 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002222 return false;
2223 }
2224
2225 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002226 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002227
Toma Tabacu79588102015-04-29 10:19:56 +00002228 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2229 uint16_t Bits15To0 = ImmValue & 0xffff;
2230
Toma Tabacua3d056f2015-05-15 09:42:11 +00002231 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002232 // Traditional behaviour seems to special case this particular value. It's
2233 // not clear why other masks are handled differently.
2234 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002235 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2236 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002237 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002238 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002239 return false;
2240 }
2241
2242 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002243 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002244 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2245 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002246 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002247 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002248 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002249 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002250 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002251 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002252
Daniel Sandersa736b372016-04-29 13:33:12 +00002253 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002254 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002255 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002256 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002257 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002258 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002259 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002260
2261 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2262 if (Is32BitImm) {
2263 Error(IDLoc, "instruction requires a 32-bit immediate");
2264 return true;
2265 }
2266
2267 // Traditionally, these immediates are shifted as little as possible and as
2268 // such we align the most significant bit to bit 15 of our temporary.
2269 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2270 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2271 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2272 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002273 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2274 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002275
2276 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002277 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002278
2279 return false;
2280 }
2281
2282 warnIfNoMacro(IDLoc);
2283
2284 // The remaining case is packed with a sequence of dsll and ori with zeros
2285 // being omitted and any neighbouring dsll's being coalesced.
2286 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2287
2288 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2289 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002290 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002291 return false;
2292
2293 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2294 // skip it and defer the shift to the next chunk.
2295 unsigned ShiftCarriedForwards = 16;
2296 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2297 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2298
2299 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002300 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2301 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002302 ShiftCarriedForwards = 0;
2303 }
2304
2305 ShiftCarriedForwards += 16;
2306 }
2307 ShiftCarriedForwards -= 16;
2308
2309 // Finish any remaining shifts left by trailing zeros.
2310 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002311 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002312
2313 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002314 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002315
Matheus Almeida3813d572014-06-19 14:39:14 +00002316 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002317}
Jack Carter92995f12012-10-06 00:53:28 +00002318
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002319bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002320 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002321 const MCOperand &ImmOp = Inst.getOperand(1);
2322 assert(ImmOp.isImm() && "expected immediate operand kind");
2323 const MCOperand &DstRegOp = Inst.getOperand(0);
2324 assert(DstRegOp.isReg() && "expected register operand kind");
2325
2326 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002327 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002328 return true;
2329
2330 return false;
2331}
2332
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002333bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2334 const MCOperand &Offset,
2335 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002336 MCStreamer &Out,
2337 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002338 // la can't produce a usable address when addresses are 64-bit.
2339 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2340 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2341 // We currently can't do this because we depend on the equality
2342 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2343 Error(IDLoc, "la used to load 64-bit address");
2344 // Continue as if we had 'dla' instead.
2345 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002346 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002347
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002348 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002349 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002350 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002351 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002352 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002353
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002354 if (!Offset.isImm())
2355 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002356 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002357
Scott Egerton24557012016-01-21 15:11:01 +00002358 if (!ABI.ArePtrs64bit()) {
2359 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2360 Is32BitAddress = true;
2361 }
2362
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002363 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002364 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002365}
2366
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002367bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2368 unsigned DstReg, unsigned SrcReg,
2369 bool Is32BitSym, SMLoc IDLoc,
2370 MCStreamer &Out,
2371 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002372 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacu81496c12015-05-20 08:54:45 +00002373 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002374
Daniel Sandersd5a89412015-10-05 13:19:29 +00002375 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002376 const MipsMCExpr *HiExpr =
2377 MipsMCExpr::create(MipsMCExpr::MEK_HI, Symbol, getContext());
2378 const MipsMCExpr *LoExpr =
2379 MipsMCExpr::create(MipsMCExpr::MEK_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002380
Toma Tabacufb9d1252015-06-22 12:08:39 +00002381 bool UseSrcReg = SrcReg != Mips::NoRegister;
2382
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002383 // This is the 64-bit symbol address expansion.
2384 if (ABI.ArePtrs64bit() && isGP64bit()) {
2385 // We always need AT for the 64-bit expansion.
2386 // If it is not available we exit.
2387 unsigned ATReg = getATReg(IDLoc);
2388 if (!ATReg)
2389 return true;
2390
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002391 const MipsMCExpr *HighestExpr =
2392 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, Symbol, getContext());
2393 const MipsMCExpr *HigherExpr =
2394 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002395
Scott Egerton24557012016-01-21 15:11:01 +00002396 if (UseSrcReg &&
2397 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2398 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002399 // If $rs is the same as $rd:
2400 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2401 // daddiu $at, $at, %higher(sym)
2402 // dsll $at, $at, 16
2403 // daddiu $at, $at, %hi(sym)
2404 // dsll $at, $at, 16
2405 // daddiu $at, $at, %lo(sym)
2406 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002407 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2408 STI);
2409 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2410 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2411 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2412 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2413 IDLoc, STI);
2414 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2415 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2416 IDLoc, STI);
2417 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002418
2419 return false;
2420 }
2421
2422 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2423 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2424 // lui $at, %hi(sym)
2425 // daddiu $rd, $rd, %higher(sym)
2426 // daddiu $at, $at, %lo(sym)
2427 // dsll32 $rd, $rd, 0
2428 // daddu $rd, $rd, $at
2429 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002430 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2431 STI);
2432 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2433 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2434 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2435 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2436 IDLoc, STI);
2437 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2438 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002439 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002440 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002441
2442 return false;
2443 }
2444
2445 // And now, the 32-bit symbol address expansion:
2446 // If $rs is the same as $rd:
2447 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2448 // ori $at, $at, %lo(sym)
2449 // addu $rd, $at, $rd
2450 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2451 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2452 // ori $rd, $rd, %lo(sym)
2453 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002454 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002455 if (UseSrcReg &&
2456 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002457 // If $rs is the same as $rd, we need to use AT.
2458 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002459 unsigned ATReg = getATReg(IDLoc);
2460 if (!ATReg)
2461 return true;
2462 TmpReg = ATReg;
2463 }
2464
Daniel Sandersa736b372016-04-29 13:33:12 +00002465 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2466 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2467 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002468
Toma Tabacufb9d1252015-06-22 12:08:39 +00002469 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002470 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002471 else
Scott Egerton24557012016-01-21 15:11:01 +00002472 assert(
2473 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002474
Toma Tabacu674825c2015-06-16 12:16:24 +00002475 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002476}
2477
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002478bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2479 MCStreamer &Out,
2480 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002481 MipsTargetStreamer &TOut = getTargetStreamer();
2482
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002483 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2484 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002485
2486 MCOperand Offset = Inst.getOperand(0);
2487 if (Offset.isExpr()) {
2488 Inst.clear();
2489 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002490 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2491 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2492 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002493 } else {
2494 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002495 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002496 // If offset fits into 11 bits then this instruction becomes microMIPS
2497 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002498 if (inMicroMipsMode())
2499 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002500 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002501 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002502 Error(IDLoc, "branch target out of range");
2503 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2504 Error(IDLoc, "branch to misaligned address");
2505 Inst.clear();
2506 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002507 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2508 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2509 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002510 }
2511 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002512 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002513
Zoran Jovanovicada70912015-09-07 11:56:37 +00002514 // If .set reorder is active and branch instruction has a delay slot,
2515 // emit a NOP after it.
2516 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2517 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002518 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002519
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002520 return false;
2521}
2522
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002523bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2524 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002525 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002526 const MCOperand &DstRegOp = Inst.getOperand(0);
2527 assert(DstRegOp.isReg() && "expected register operand kind");
2528
2529 const MCOperand &ImmOp = Inst.getOperand(1);
2530 assert(ImmOp.isImm() && "expected immediate operand kind");
2531
2532 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002533 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2534 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002535
2536 unsigned OpCode = 0;
2537 switch(Inst.getOpcode()) {
2538 case Mips::BneImm:
2539 OpCode = Mips::BNE;
2540 break;
2541 case Mips::BeqImm:
2542 OpCode = Mips::BEQ;
2543 break;
2544 default:
2545 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2546 break;
2547 }
2548
2549 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002550 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002551 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2552 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002553 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002554 warnIfNoMacro(IDLoc);
2555
2556 unsigned ATReg = getATReg(IDLoc);
2557 if (!ATReg)
2558 return true;
2559
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002560 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002561 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002562 return true;
2563
Daniel Sandersa736b372016-04-29 13:33:12 +00002564 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002565 }
2566 return false;
2567}
2568
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002569void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002570 const MCSubtargetInfo *STI, bool IsLoad,
2571 bool IsImmOpnd) {
2572 if (IsLoad) {
2573 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2574 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002575 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002576 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2577}
2578
2579void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2580 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2581 MipsTargetStreamer &TOut = getTargetStreamer();
2582
2583 unsigned DstReg = Inst.getOperand(0).getReg();
2584 unsigned BaseReg = Inst.getOperand(1).getReg();
2585
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002586 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002587 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2588 unsigned DstRegClassID =
2589 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2590 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2591 (DstRegClassID == Mips::GPR64RegClassID);
2592
2593 if (IsImmOpnd) {
2594 // Try to use DstReg as the temporary.
2595 if (IsGPR && (BaseReg != DstReg)) {
2596 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2597 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2598 STI);
2599 return;
2600 }
2601
Matheus Almeida7de68e72014-06-18 14:46:05 +00002602 // At this point we need AT to perform the expansions and we exit if it is
2603 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002604 unsigned ATReg = getATReg(IDLoc);
2605 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002606 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002607
2608 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2609 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2610 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002611 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002612
Daniel Sandersfba875f2016-04-29 13:43:45 +00002613 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002614 MCOperand LoOperand = MCOperand::createExpr(
2615 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2616 MCOperand HiOperand = MCOperand::createExpr(
2617 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002618
2619 // Try to use DstReg as the temporary.
2620 if (IsGPR && (BaseReg != DstReg)) {
2621 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2622 LoOperand, DstReg, IDLoc, STI);
2623 return;
2624 }
2625
2626 // At this point we need AT to perform the expansions and we exit if it is
2627 // not available.
2628 unsigned ATReg = getATReg(IDLoc);
2629 if (!ATReg)
2630 return;
2631
2632 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2633 LoOperand, ATReg, IDLoc, STI);
2634}
2635
2636void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2637 const MCSubtargetInfo *STI,
2638 bool IsImmOpnd) {
2639 MipsTargetStreamer &TOut = getTargetStreamer();
2640
2641 unsigned SrcReg = Inst.getOperand(0).getReg();
2642 unsigned BaseReg = Inst.getOperand(1).getReg();
2643
Daniel Sanders241c6792016-05-12 14:01:50 +00002644 if (IsImmOpnd) {
2645 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2646 Inst.getOperand(2).getImm(),
2647 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
2648 return;
2649 }
2650
Daniel Sandersfba875f2016-04-29 13:43:45 +00002651 unsigned ATReg = getATReg(IDLoc);
2652 if (!ATReg)
2653 return;
2654
Daniel Sandersfba875f2016-04-29 13:43:45 +00002655 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002656 MCOperand LoOperand = MCOperand::createExpr(
2657 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2658 MCOperand HiOperand = MCOperand::createExpr(
2659 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002660 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2661 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002662}
2663
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002664bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2665 MCStreamer &Out,
2666 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002667 unsigned OpNum = Inst.getNumOperands();
2668 unsigned Opcode = Inst.getOpcode();
2669 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2670
2671 assert (Inst.getOperand(OpNum - 1).isImm() &&
2672 Inst.getOperand(OpNum - 2).isReg() &&
2673 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2674
2675 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2676 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002677 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2678 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2679 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2680 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002681 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002682 if (inMicroMipsMode() && hasMips32r6())
2683 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2684 else
2685 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2686 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002687
2688 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002689 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002690 return false;
2691}
2692
Toma Tabacu1a108322015-06-17 13:20:24 +00002693bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002694 MCStreamer &Out,
2695 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002696 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002697 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002698 unsigned PseudoOpcode = Inst.getOpcode();
2699 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002700 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002701 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2702
2703 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002704 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002705
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002706 unsigned TrgReg;
2707 if (TrgOp.isReg())
2708 TrgReg = TrgOp.getReg();
2709 else if (TrgOp.isImm()) {
2710 warnIfNoMacro(IDLoc);
2711 EmittedNoMacroWarning = true;
2712
2713 TrgReg = getATReg(IDLoc);
2714 if (!TrgReg)
2715 return true;
2716
2717 switch(PseudoOpcode) {
2718 default:
2719 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2720 case Mips::BLTImmMacro:
2721 PseudoOpcode = Mips::BLT;
2722 break;
2723 case Mips::BLEImmMacro:
2724 PseudoOpcode = Mips::BLE;
2725 break;
2726 case Mips::BGEImmMacro:
2727 PseudoOpcode = Mips::BGE;
2728 break;
2729 case Mips::BGTImmMacro:
2730 PseudoOpcode = Mips::BGT;
2731 break;
2732 case Mips::BLTUImmMacro:
2733 PseudoOpcode = Mips::BLTU;
2734 break;
2735 case Mips::BLEUImmMacro:
2736 PseudoOpcode = Mips::BLEU;
2737 break;
2738 case Mips::BGEUImmMacro:
2739 PseudoOpcode = Mips::BGEU;
2740 break;
2741 case Mips::BGTUImmMacro:
2742 PseudoOpcode = Mips::BGTU;
2743 break;
2744 case Mips::BLTLImmMacro:
2745 PseudoOpcode = Mips::BLTL;
2746 break;
2747 case Mips::BLELImmMacro:
2748 PseudoOpcode = Mips::BLEL;
2749 break;
2750 case Mips::BGELImmMacro:
2751 PseudoOpcode = Mips::BGEL;
2752 break;
2753 case Mips::BGTLImmMacro:
2754 PseudoOpcode = Mips::BGTL;
2755 break;
2756 case Mips::BLTULImmMacro:
2757 PseudoOpcode = Mips::BLTUL;
2758 break;
2759 case Mips::BLEULImmMacro:
2760 PseudoOpcode = Mips::BLEUL;
2761 break;
2762 case Mips::BGEULImmMacro:
2763 PseudoOpcode = Mips::BGEUL;
2764 break;
2765 case Mips::BGTULImmMacro:
2766 PseudoOpcode = Mips::BGTUL;
2767 break;
2768 }
2769
2770 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002771 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002772 return true;
2773 }
2774
Toma Tabacu1a108322015-06-17 13:20:24 +00002775 switch (PseudoOpcode) {
2776 case Mips::BLT:
2777 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002778 case Mips::BLTL:
2779 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002780 AcceptsEquality = false;
2781 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002782 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2783 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002784 ZeroSrcOpcode = Mips::BGTZ;
2785 ZeroTrgOpcode = Mips::BLTZ;
2786 break;
2787 case Mips::BLE:
2788 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002789 case Mips::BLEL:
2790 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002791 AcceptsEquality = true;
2792 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002793 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2794 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002795 ZeroSrcOpcode = Mips::BGEZ;
2796 ZeroTrgOpcode = Mips::BLEZ;
2797 break;
2798 case Mips::BGE:
2799 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002800 case Mips::BGEL:
2801 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002802 AcceptsEquality = true;
2803 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002804 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2805 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002806 ZeroSrcOpcode = Mips::BLEZ;
2807 ZeroTrgOpcode = Mips::BGEZ;
2808 break;
2809 case Mips::BGT:
2810 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002811 case Mips::BGTL:
2812 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002813 AcceptsEquality = false;
2814 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002815 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2816 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002817 ZeroSrcOpcode = Mips::BLTZ;
2818 ZeroTrgOpcode = Mips::BGTZ;
2819 break;
2820 default:
2821 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2822 }
2823
Toma Tabacu1a108322015-06-17 13:20:24 +00002824 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2825 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2826 if (IsSrcRegZero && IsTrgRegZero) {
2827 // FIXME: All of these Opcode-specific if's are needed for compatibility
2828 // with GAS' behaviour. However, they may not generate the most efficient
2829 // code in some circumstances.
2830 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002831 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2832 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002833 return false;
2834 }
2835 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002836 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2837 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002838 Warning(IDLoc, "branch is always taken");
2839 return false;
2840 }
2841 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002842 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2843 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002844 Warning(IDLoc, "branch is always taken");
2845 return false;
2846 }
2847 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002848 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2849 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002850 return false;
2851 }
2852 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002853 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2854 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002855 return false;
2856 }
2857 if (AcceptsEquality) {
2858 // If both registers are $0 and the pseudo-branch accepts equality, it
2859 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00002860 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2861 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002862 Warning(IDLoc, "branch is always taken");
2863 return false;
2864 }
2865 // If both registers are $0 and the pseudo-branch does not accept
2866 // equality, it will never be taken, so we don't have to emit anything.
2867 return false;
2868 }
2869 if (IsSrcRegZero || IsTrgRegZero) {
2870 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2871 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2872 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2873 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2874 // the pseudo-branch will never be taken, so we don't emit anything.
2875 // This only applies to unsigned pseudo-branches.
2876 return false;
2877 }
2878 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2879 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2880 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2881 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2882 // the pseudo-branch will always be taken, so we emit an unconditional
2883 // branch.
2884 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00002885 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2886 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002887 Warning(IDLoc, "branch is always taken");
2888 return false;
2889 }
2890 if (IsUnsigned) {
2891 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2892 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2893 // the pseudo-branch will be taken only when the non-zero register is
2894 // different from 0, so we emit a BNEZ.
2895 //
2896 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2897 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2898 // the pseudo-branch will be taken only when the non-zero register is
2899 // equal to 0, so we emit a BEQZ.
2900 //
2901 // Because only BLEU and BGEU branch on equality, we can use the
2902 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00002903 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2904 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2905 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002906 return false;
2907 }
2908 // If we have a signed pseudo-branch and one of the registers is $0,
2909 // we can use an appropriate compare-to-zero branch. We select which one
2910 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00002911 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2912 IsSrcRegZero ? TrgReg : SrcReg,
2913 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002914 return false;
2915 }
2916
2917 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2918 // expansions. If it is not available, we return.
2919 unsigned ATRegNum = getATReg(IDLoc);
2920 if (!ATRegNum)
2921 return true;
2922
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002923 if (!EmittedNoMacroWarning)
2924 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002925
2926 // SLT fits well with 2 of our 4 pseudo-branches:
2927 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2928 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2929 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2930 // This is accomplished by using a BNEZ with the result of the SLT.
2931 //
2932 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2933 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2934 // Because only BGE and BLE branch on equality, we can use the
2935 // AcceptsEquality variable to decide when to emit the BEQZ.
2936 // Note that the order of the SLT arguments doesn't change between
2937 // opposites.
2938 //
2939 // The same applies to the unsigned variants, except that SLTu is used
2940 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00002941 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2942 ReverseOrderSLT ? TrgReg : SrcReg,
2943 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002944
Daniel Sandersa736b372016-04-29 13:33:12 +00002945 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2946 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2947 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2948 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002949 return false;
2950}
2951
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002952bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2953 const MCSubtargetInfo *STI, const bool IsMips64,
2954 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002955 MipsTargetStreamer &TOut = getTargetStreamer();
2956
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002957 warnIfNoMacro(IDLoc);
2958
Zoran Jovanovic973405b2016-05-16 08:57:59 +00002959 const MCOperand &RdRegOp = Inst.getOperand(0);
2960 assert(RdRegOp.isReg() && "expected register operand kind");
2961 unsigned RdReg = RdRegOp.getReg();
2962
2963 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002964 assert(RsRegOp.isReg() && "expected register operand kind");
2965 unsigned RsReg = RsRegOp.getReg();
2966
Zoran Jovanovic973405b2016-05-16 08:57:59 +00002967 const MCOperand &RtRegOp = Inst.getOperand(2);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002968 assert(RtRegOp.isReg() && "expected register operand kind");
2969 unsigned RtReg = RtRegOp.getReg();
2970 unsigned DivOp;
2971 unsigned ZeroReg;
2972
2973 if (IsMips64) {
2974 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2975 ZeroReg = Mips::ZERO_64;
2976 } else {
2977 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2978 ZeroReg = Mips::ZERO;
2979 }
2980
2981 bool UseTraps = useTraps();
2982
2983 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2984 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2985 Warning(IDLoc, "dividing zero by zero");
2986 if (IsMips64) {
2987 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2988 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002989 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002990 return false;
2991 }
2992
Daniel Sandersa736b372016-04-29 13:33:12 +00002993 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002994 return false;
2995 }
2996 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00002997 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002998 return false;
2999 }
3000 }
3001
3002 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3003 Warning(IDLoc, "division by zero");
3004 if (Signed) {
3005 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003006 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003007 return false;
3008 }
3009
Daniel Sandersa736b372016-04-29 13:33:12 +00003010 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003011 return false;
3012 }
3013 }
3014
3015 // FIXME: The values for these two BranchTarget variables may be different in
3016 // micromips. These magic numbers need to be removed.
3017 unsigned BranchTargetNoTraps;
3018 unsigned BranchTarget;
3019
3020 if (UseTraps) {
3021 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003022 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003023 } else {
3024 BranchTarget = IsMips64 ? 20 : 16;
3025 BranchTargetNoTraps = 8;
3026 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003027 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003028 }
3029
Daniel Sandersa736b372016-04-29 13:33:12 +00003030 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003031
3032 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003033 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003034
3035 if (!Signed) {
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003036 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003037 return false;
3038 }
3039
3040 unsigned ATReg = getATReg(IDLoc);
3041 if (!ATReg)
3042 return true;
3043
Daniel Sandersa736b372016-04-29 13:33:12 +00003044 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003045 if (IsMips64) {
3046 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003047 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3048 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3049 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003050 } else {
3051 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003052 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3053 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003054 }
3055
3056 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003057 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003058 else {
3059 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003060 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3061 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3062 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003063 }
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003064 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003065 return false;
3066}
3067
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003068bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003069 SMLoc IDLoc, MCStreamer &Out,
3070 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003071 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003072
3073 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3074 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3075 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3076
3077 unsigned FirstReg = Inst.getOperand(0).getReg();
3078 unsigned SecondReg = Inst.getOperand(1).getReg();
3079 unsigned ThirdReg = Inst.getOperand(2).getReg();
3080
3081 if (hasMips1() && !hasMips2()) {
3082 unsigned ATReg = getATReg(IDLoc);
3083 if (!ATReg)
3084 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003085 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3086 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3087 TOut.emitNop(IDLoc, STI);
3088 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3089 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3090 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3091 TOut.emitNop(IDLoc, STI);
3092 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3093 : Mips::CVT_W_S,
3094 FirstReg, SecondReg, IDLoc, STI);
3095 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3096 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003097 return false;
3098 }
3099
Daniel Sandersa736b372016-04-29 13:33:12 +00003100 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3101 : Mips::TRUNC_W_S,
3102 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003103
3104 return false;
3105}
3106
Daniel Sanders6394ee52015-10-15 14:52:58 +00003107bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003108 MCStreamer &Out, const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003109 MipsTargetStreamer &TOut = getTargetStreamer();
3110
Toma Tabacud88d79c2015-06-23 14:39:42 +00003111 if (hasMips32r6() || hasMips64r6()) {
3112 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3113 return false;
3114 }
3115
3116 warnIfNoMacro(IDLoc);
3117
3118 const MCOperand &DstRegOp = Inst.getOperand(0);
3119 assert(DstRegOp.isReg() && "expected register operand kind");
3120
3121 const MCOperand &SrcRegOp = Inst.getOperand(1);
3122 assert(SrcRegOp.isReg() && "expected register operand kind");
3123
3124 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3125 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3126
3127 unsigned DstReg = DstRegOp.getReg();
3128 unsigned SrcReg = SrcRegOp.getReg();
3129 int64_t OffsetValue = OffsetImmOp.getImm();
3130
3131 // NOTE: We always need AT for ULHU, as it is always used as the source
3132 // register for one of the LBu's.
3133 unsigned ATReg = getATReg(IDLoc);
3134 if (!ATReg)
3135 return true;
3136
3137 // When the value of offset+1 does not fit in 16 bits, we have to load the
3138 // offset in AT, (D)ADDu the original source register (if there was one), and
3139 // then use AT as the source register for the 2 generated LBu's.
3140 bool LoadedOffsetInAT = false;
3141 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3142 LoadedOffsetInAT = true;
3143
3144 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003145 true, IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003146 return true;
3147
3148 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3149 // because it will make our output more similar to GAS'. For example,
3150 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3151 // instead of just an "ori $1, $9, 32768".
3152 // NOTE: If there is no source register specified in the ULHU, the parser
3153 // will interpret it as $0.
3154 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003155 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003156 }
3157
3158 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3159 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3160 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3161
3162 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3163 if (isLittle()) {
3164 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3165 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3166 } else {
3167 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3168 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3169 }
3170
3171 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3172
Daniel Sandersa736b372016-04-29 13:33:12 +00003173 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3174 FirstLbuOffset, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003175
Daniel Sandersa736b372016-04-29 13:33:12 +00003176 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3177 STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003178
Daniel Sandersa736b372016-04-29 13:33:12 +00003179 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003180
Daniel Sandersa736b372016-04-29 13:33:12 +00003181 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003182
3183 return false;
3184}
3185
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003186bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3187 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003188 MipsTargetStreamer &TOut = getTargetStreamer();
3189
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003190 if (hasMips32r6() || hasMips64r6()) {
3191 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3192 return false;
3193 }
3194
3195 const MCOperand &DstRegOp = Inst.getOperand(0);
3196 assert(DstRegOp.isReg() && "expected register operand kind");
3197
3198 const MCOperand &SrcRegOp = Inst.getOperand(1);
3199 assert(SrcRegOp.isReg() && "expected register operand kind");
3200
3201 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3202 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3203
3204 unsigned SrcReg = SrcRegOp.getReg();
3205 int64_t OffsetValue = OffsetImmOp.getImm();
3206 unsigned ATReg = 0;
3207
3208 // When the value of offset+3 does not fit in 16 bits, we have to load the
3209 // offset in AT, (D)ADDu the original source register (if there was one), and
3210 // then use AT as the source register for the generated LWL and LWR.
3211 bool LoadedOffsetInAT = false;
3212 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3213 ATReg = getATReg(IDLoc);
3214 if (!ATReg)
3215 return true;
3216 LoadedOffsetInAT = true;
3217
3218 warnIfNoMacro(IDLoc);
3219
3220 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003221 true, IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003222 return true;
3223
3224 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3225 // because it will make our output more similar to GAS'. For example,
3226 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3227 // instead of just an "ori $1, $9, 32768".
3228 // NOTE: If there is no source register specified in the ULW, the parser
3229 // will interpret it as $0.
3230 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003231 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003232 }
3233
3234 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3235 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3236 if (isLittle()) {
3237 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3238 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3239 } else {
3240 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3241 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3242 }
3243
Daniel Sandersa736b372016-04-29 13:33:12 +00003244 TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3245 STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003246
Daniel Sandersa736b372016-04-29 13:33:12 +00003247 TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
3248 IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003249
3250 return false;
3251}
3252
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003253bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003254 MCStreamer &Out,
3255 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003256 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003257
3258 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3259 assert (Inst.getOperand(0).isReg() &&
3260 Inst.getOperand(1).isReg() &&
3261 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3262
3263 unsigned ATReg = Mips::NoRegister;
3264 unsigned FinalDstReg = Mips::NoRegister;
3265 unsigned DstReg = Inst.getOperand(0).getReg();
3266 unsigned SrcReg = Inst.getOperand(1).getReg();
3267 int64_t ImmValue = Inst.getOperand(2).getImm();
3268
3269 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3270
3271 unsigned FinalOpcode = Inst.getOpcode();
3272
3273 if (DstReg == SrcReg) {
3274 ATReg = getATReg(Inst.getLoc());
3275 if (!ATReg)
3276 return true;
3277 FinalDstReg = DstReg;
3278 DstReg = ATReg;
3279 }
3280
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003281 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003282 switch (FinalOpcode) {
3283 default:
3284 llvm_unreachable("unimplemented expansion");
3285 case (Mips::ADDi):
3286 FinalOpcode = Mips::ADD;
3287 break;
3288 case (Mips::ADDiu):
3289 FinalOpcode = Mips::ADDu;
3290 break;
3291 case (Mips::ANDi):
3292 FinalOpcode = Mips::AND;
3293 break;
3294 case (Mips::NORImm):
3295 FinalOpcode = Mips::NOR;
3296 break;
3297 case (Mips::ORi):
3298 FinalOpcode = Mips::OR;
3299 break;
3300 case (Mips::SLTi):
3301 FinalOpcode = Mips::SLT;
3302 break;
3303 case (Mips::SLTiu):
3304 FinalOpcode = Mips::SLTu;
3305 break;
3306 case (Mips::XORi):
3307 FinalOpcode = Mips::XOR;
3308 break;
3309 }
3310
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003311 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003312 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003313 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003314 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003315 return false;
3316 }
3317 return true;
3318}
3319
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003320bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3321 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003322 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003323 unsigned ATReg = Mips::NoRegister;
3324 unsigned DReg = Inst.getOperand(0).getReg();
3325 unsigned SReg = Inst.getOperand(1).getReg();
3326 unsigned TReg = Inst.getOperand(2).getReg();
3327 unsigned TmpReg = DReg;
3328
3329 unsigned FirstShift = Mips::NOP;
3330 unsigned SecondShift = Mips::NOP;
3331
3332 if (hasMips32r2()) {
3333
3334 if (DReg == SReg) {
3335 TmpReg = getATReg(Inst.getLoc());
3336 if (!TmpReg)
3337 return true;
3338 }
3339
3340 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003341 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3342 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003343 return false;
3344 }
3345
3346 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003347 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003348 return false;
3349 }
3350
3351 return true;
3352 }
3353
3354 if (hasMips32()) {
3355
3356 switch (Inst.getOpcode()) {
3357 default:
3358 llvm_unreachable("unexpected instruction opcode");
3359 case Mips::ROL:
3360 FirstShift = Mips::SRLV;
3361 SecondShift = Mips::SLLV;
3362 break;
3363 case Mips::ROR:
3364 FirstShift = Mips::SLLV;
3365 SecondShift = Mips::SRLV;
3366 break;
3367 }
3368
3369 ATReg = getATReg(Inst.getLoc());
3370 if (!ATReg)
3371 return true;
3372
Daniel Sandersa736b372016-04-29 13:33:12 +00003373 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3374 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3375 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3376 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003377
3378 return false;
3379 }
3380
3381 return true;
3382}
3383
3384bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003385 MCStreamer &Out,
3386 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003387 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003388 unsigned ATReg = Mips::NoRegister;
3389 unsigned DReg = Inst.getOperand(0).getReg();
3390 unsigned SReg = Inst.getOperand(1).getReg();
3391 int64_t ImmValue = Inst.getOperand(2).getImm();
3392
3393 unsigned FirstShift = Mips::NOP;
3394 unsigned SecondShift = Mips::NOP;
3395
3396 if (hasMips32r2()) {
3397
3398 if (Inst.getOpcode() == Mips::ROLImm) {
3399 uint64_t MaxShift = 32;
3400 uint64_t ShiftValue = ImmValue;
3401 if (ImmValue != 0)
3402 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003403 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003404 return false;
3405 }
3406
3407 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003408 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003409 return false;
3410 }
3411
3412 return true;
3413 }
3414
3415 if (hasMips32()) {
3416
3417 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003418 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003419 return false;
3420 }
3421
3422 switch (Inst.getOpcode()) {
3423 default:
3424 llvm_unreachable("unexpected instruction opcode");
3425 case Mips::ROLImm:
3426 FirstShift = Mips::SLL;
3427 SecondShift = Mips::SRL;
3428 break;
3429 case Mips::RORImm:
3430 FirstShift = Mips::SRL;
3431 SecondShift = Mips::SLL;
3432 break;
3433 }
3434
3435 ATReg = getATReg(Inst.getLoc());
3436 if (!ATReg)
3437 return true;
3438
Daniel Sandersa736b372016-04-29 13:33:12 +00003439 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3440 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3441 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003442
3443 return false;
3444 }
3445
3446 return true;
3447}
3448
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003449bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3450 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003451 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003452 unsigned ATReg = Mips::NoRegister;
3453 unsigned DReg = Inst.getOperand(0).getReg();
3454 unsigned SReg = Inst.getOperand(1).getReg();
3455 unsigned TReg = Inst.getOperand(2).getReg();
3456 unsigned TmpReg = DReg;
3457
3458 unsigned FirstShift = Mips::NOP;
3459 unsigned SecondShift = Mips::NOP;
3460
3461 if (hasMips64r2()) {
3462
3463 if (TmpReg == SReg) {
3464 TmpReg = getATReg(Inst.getLoc());
3465 if (!TmpReg)
3466 return true;
3467 }
3468
3469 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003470 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3471 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003472 return false;
3473 }
3474
3475 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003476 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003477 return false;
3478 }
3479
3480 return true;
3481 }
3482
3483 if (hasMips64()) {
3484
3485 switch (Inst.getOpcode()) {
3486 default:
3487 llvm_unreachable("unexpected instruction opcode");
3488 case Mips::DROL:
3489 FirstShift = Mips::DSRLV;
3490 SecondShift = Mips::DSLLV;
3491 break;
3492 case Mips::DROR:
3493 FirstShift = Mips::DSLLV;
3494 SecondShift = Mips::DSRLV;
3495 break;
3496 }
3497
3498 ATReg = getATReg(Inst.getLoc());
3499 if (!ATReg)
3500 return true;
3501
Daniel Sandersa736b372016-04-29 13:33:12 +00003502 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3503 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3504 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3505 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003506
3507 return false;
3508 }
3509
3510 return true;
3511}
3512
3513bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003514 MCStreamer &Out,
3515 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003516 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003517 unsigned ATReg = Mips::NoRegister;
3518 unsigned DReg = Inst.getOperand(0).getReg();
3519 unsigned SReg = Inst.getOperand(1).getReg();
3520 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3521
3522 unsigned FirstShift = Mips::NOP;
3523 unsigned SecondShift = Mips::NOP;
3524
3525 MCInst TmpInst;
3526
3527 if (hasMips64r2()) {
3528
3529 unsigned FinalOpcode = Mips::NOP;
3530 if (ImmValue == 0)
3531 FinalOpcode = Mips::DROTR;
3532 else if (ImmValue % 32 == 0)
3533 FinalOpcode = Mips::DROTR32;
3534 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3535 if (Inst.getOpcode() == Mips::DROLImm)
3536 FinalOpcode = Mips::DROTR32;
3537 else
3538 FinalOpcode = Mips::DROTR;
3539 } else if (ImmValue >= 33) {
3540 if (Inst.getOpcode() == Mips::DROLImm)
3541 FinalOpcode = Mips::DROTR;
3542 else
3543 FinalOpcode = Mips::DROTR32;
3544 }
3545
3546 uint64_t ShiftValue = ImmValue % 32;
3547 if (Inst.getOpcode() == Mips::DROLImm)
3548 ShiftValue = (32 - ImmValue % 32) % 32;
3549
Daniel Sandersa736b372016-04-29 13:33:12 +00003550 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003551
3552 return false;
3553 }
3554
3555 if (hasMips64()) {
3556
3557 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003558 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003559 return false;
3560 }
3561
3562 switch (Inst.getOpcode()) {
3563 default:
3564 llvm_unreachable("unexpected instruction opcode");
3565 case Mips::DROLImm:
3566 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3567 FirstShift = Mips::DSLL;
3568 SecondShift = Mips::DSRL32;
3569 }
3570 if (ImmValue == 32) {
3571 FirstShift = Mips::DSLL32;
3572 SecondShift = Mips::DSRL32;
3573 }
3574 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3575 FirstShift = Mips::DSLL32;
3576 SecondShift = Mips::DSRL;
3577 }
3578 break;
3579 case Mips::DRORImm:
3580 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3581 FirstShift = Mips::DSRL;
3582 SecondShift = Mips::DSLL32;
3583 }
3584 if (ImmValue == 32) {
3585 FirstShift = Mips::DSRL32;
3586 SecondShift = Mips::DSLL32;
3587 }
3588 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3589 FirstShift = Mips::DSRL32;
3590 SecondShift = Mips::DSLL;
3591 }
3592 break;
3593 }
3594
3595 ATReg = getATReg(Inst.getLoc());
3596 if (!ATReg)
3597 return true;
3598
Daniel Sandersa736b372016-04-29 13:33:12 +00003599 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3600 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3601 Inst.getLoc(), STI);
3602 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003603
3604 return false;
3605 }
3606
3607 return true;
3608}
3609
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003610bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3611 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003612 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003613 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3614 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3615
Daniel Sandersa736b372016-04-29 13:33:12 +00003616 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003617 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003618 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003619 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003620 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3621 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003622
3623 return false;
3624}
3625
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003626void MipsAsmParser::createCpRestoreMemOp(bool IsLoad, int StackOffset,
3627 SMLoc IDLoc, MCStreamer &Out,
3628 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003629 MipsTargetStreamer &TOut = getTargetStreamer();
3630
Daniel Sanders7225cd52016-04-29 16:16:49 +00003631 if (IsLoad) {
3632 TOut.emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, StackOffset,
3633 Mips::GP, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003634 return;
3635 }
3636
Daniel Sanders241c6792016-05-12 14:01:50 +00003637 TOut.emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, StackOffset,
3638 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003639}
3640
Matheus Almeida595fcab2014-06-11 15:05:56 +00003641unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3642 // As described by the Mips32r2 spec, the registers Rd and Rs for
3643 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00003644 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00003645 // and registers Rd and Base for microMIPS lwp instruction
Matheus Almeida595fcab2014-06-11 15:05:56 +00003646 unsigned Opcode = Inst.getOpcode();
3647
Zlatko Buljanae720db2016-04-22 06:44:34 +00003648 if ((Opcode == Mips::JALR_HB || Opcode == Mips::JALRC_HB_MMR6) &&
Matheus Almeida595fcab2014-06-11 15:05:56 +00003649 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3650 return Match_RequiresDifferentSrcAndDst;
Zlatko Buljanba553a62016-05-09 08:07:28 +00003651 else if ((Opcode == Mips::LWP_MM || Opcode == Mips::LWP_MMR6) &&
3652 (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()))
3653 return Match_RequiresDifferentSrcAndDst;
Matheus Almeida595fcab2014-06-11 15:05:56 +00003654
3655 return Match_Success;
3656}
3657
Daniel Sanders52da7af2015-11-06 12:11:03 +00003658static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3659 uint64_t ErrorInfo) {
3660 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3661 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3662 if (ErrorLoc == SMLoc())
3663 return Loc;
3664 return ErrorLoc;
3665 }
3666 return Loc;
3667}
3668
David Blaikie960ea3f2014-06-08 16:18:35 +00003669bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3670 OperandVector &Operands,
3671 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003672 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003673 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003674
Jack Carterb4dbc172012-09-05 23:34:03 +00003675 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00003676 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003677 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003678
3679 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003680 case Match_Success: {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003681 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00003682 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003683 return false;
3684 }
3685 case Match_MissingFeature:
3686 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3687 return true;
3688 case Match_InvalidOperand: {
3689 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003690 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003691 if (ErrorInfo >= Operands.size())
3692 return Error(IDLoc, "too few operands for instruction");
3693
Daniel Sanders52da7af2015-11-06 12:11:03 +00003694 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003695 if (ErrorLoc == SMLoc())
3696 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003697 }
3698
3699 return Error(ErrorLoc, "invalid operand for instruction");
3700 }
3701 case Match_MnemonicFail:
3702 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003703 case Match_RequiresDifferentSrcAndDst:
3704 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003705 case Match_Immz:
3706 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003707 case Match_UImm1_0:
3708 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3709 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003710 case Match_UImm2_0:
3711 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3712 "expected 2-bit unsigned immediate");
3713 case Match_UImm2_1:
3714 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3715 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003716 case Match_UImm3_0:
3717 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3718 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003719 case Match_UImm4_0:
3720 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3721 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003722 case Match_SImm4_0:
3723 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3724 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003725 case Match_UImm5_0:
3726 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3727 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00003728 case Match_SImm5_0:
3729 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3730 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003731 case Match_UImm5_1:
3732 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3733 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003734 case Match_UImm5_32:
3735 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3736 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003737 case Match_UImm5_33:
3738 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3739 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003740 case Match_UImm5_0_Report_UImm6:
3741 // This is used on UImm5 operands that have a corresponding UImm5_32
3742 // operand to avoid confusing the user.
3743 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3744 "expected 6-bit unsigned immediate");
3745 case Match_UImm5_Lsl2:
3746 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3747 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003748 case Match_UImmRange2_64:
3749 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3750 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003751 case Match_UImm6_0:
3752 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3753 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00003754 case Match_UImm6_Lsl2:
3755 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3756 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00003757 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00003758 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3759 "expected 6-bit signed immediate");
3760 case Match_UImm7_0:
3761 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3762 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00003763 case Match_UImm7_N1:
3764 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3765 "expected immediate in range -1 .. 126");
3766 case Match_SImm7_Lsl2:
3767 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3768 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003769 case Match_UImm8_0:
3770 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3771 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003772 case Match_UImm10_0:
3773 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3774 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00003775 case Match_SImm10_0:
3776 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3777 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00003778 case Match_SImm11_0:
3779 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3780 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003781 case Match_UImm16:
3782 case Match_UImm16_Relaxed:
3783 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3784 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003785 case Match_SImm16:
3786 case Match_SImm16_Relaxed:
3787 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3788 "expected 16-bit signed immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003789 case Match_UImm20_0:
3790 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3791 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00003792 case Match_UImm26_0:
3793 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3794 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00003795 case Match_SImm32:
3796 case Match_SImm32_Relaxed:
3797 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3798 "expected 32-bit signed immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00003799 case Match_MemSImm9:
3800 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3801 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00003802 case Match_MemSImm10:
3803 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3804 "expected memory with 10-bit signed offset");
3805 case Match_MemSImm10Lsl1:
3806 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3807 "expected memory with 11-bit signed offset and multiple of 2");
3808 case Match_MemSImm10Lsl2:
3809 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3810 "expected memory with 12-bit signed offset and multiple of 4");
3811 case Match_MemSImm10Lsl3:
3812 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3813 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00003814 case Match_MemSImm11:
3815 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3816 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00003817 case Match_MemSImm12:
3818 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3819 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003820 case Match_MemSImm16:
3821 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3822 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00003823 }
Craig Topper589ceee2015-01-03 08:16:34 +00003824
3825 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003826}
3827
Toma Tabacud9d344b2015-04-27 14:05:04 +00003828void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3829 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3830 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3831 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003832}
3833
Toma Tabacu81496c12015-05-20 08:54:45 +00003834void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3835 if (!AssemblerOptions.back()->isMacro())
3836 Warning(Loc, "macro instruction expanded into multiple instructions");
3837}
3838
Daniel Sandersef638fe2014-10-03 15:37:37 +00003839void
3840MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3841 SMRange Range, bool ShowColors) {
3842 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003843 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003844 ShowColors);
3845}
3846
Jack Carter1ac53222013-02-20 23:11:17 +00003847int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003848 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003849
Vladimir Medic4c299852013-11-06 11:27:05 +00003850 CC = StringSwitch<unsigned>(Name)
3851 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003852 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003853 .Case("a0", 4)
3854 .Case("a1", 5)
3855 .Case("a2", 6)
3856 .Case("a3", 7)
3857 .Case("v0", 2)
3858 .Case("v1", 3)
3859 .Case("s0", 16)
3860 .Case("s1", 17)
3861 .Case("s2", 18)
3862 .Case("s3", 19)
3863 .Case("s4", 20)
3864 .Case("s5", 21)
3865 .Case("s6", 22)
3866 .Case("s7", 23)
3867 .Case("k0", 26)
3868 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003869 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003870 .Case("sp", 29)
3871 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003872 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003873 .Case("ra", 31)
3874 .Case("t0", 8)
3875 .Case("t1", 9)
3876 .Case("t2", 10)
3877 .Case("t3", 11)
3878 .Case("t4", 12)
3879 .Case("t5", 13)
3880 .Case("t6", 14)
3881 .Case("t7", 15)
3882 .Case("t8", 24)
3883 .Case("t9", 25)
3884 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003885
Toma Tabacufda445c2014-09-15 15:33:01 +00003886 if (!(isABI_N32() || isABI_N64()))
3887 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003888
Daniel Sandersef638fe2014-10-03 15:37:37 +00003889 if (12 <= CC && CC <= 15) {
3890 // Name is one of t4-t7
3891 AsmToken RegTok = getLexer().peekTok();
3892 SMRange RegRange = RegTok.getLocRange();
3893
3894 StringRef FixedName = StringSwitch<StringRef>(Name)
3895 .Case("t4", "t0")
3896 .Case("t5", "t1")
3897 .Case("t6", "t2")
3898 .Case("t7", "t3")
3899 .Default("");
3900 assert(FixedName != "" && "Register name is not one of t4-t7.");
3901
3902 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3903 "Did you mean $" + FixedName + "?", RegRange);
3904 }
3905
Toma Tabacufda445c2014-09-15 15:33:01 +00003906 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3907 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3908 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3909 if (8 <= CC && CC <= 11)
3910 CC += 4;
3911
3912 if (CC == -1)
3913 CC = StringSwitch<unsigned>(Name)
3914 .Case("a4", 8)
3915 .Case("a5", 9)
3916 .Case("a6", 10)
3917 .Case("a7", 11)
3918 .Case("kt0", 26)
3919 .Case("kt1", 27)
3920 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003921
3922 return CC;
3923}
Jack Carterd0bd6422013-04-18 00:41:53 +00003924
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003925int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3926 int CC;
3927
3928 CC = StringSwitch<unsigned>(Name)
3929 .Case("hwr_cpunum", 0)
3930 .Case("hwr_synci_step", 1)
3931 .Case("hwr_cc", 2)
3932 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003933 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003934 .Default(-1);
3935
3936 return CC;
3937}
3938
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003939int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003940
Jack Cartera63b16a2012-09-07 00:23:42 +00003941 if (Name[0] == 'f') {
3942 StringRef NumString = Name.substr(1);
3943 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003944 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003945 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003946 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003947 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003948 return IntVal;
3949 }
3950 return -1;
3951}
Jack Cartera63b16a2012-09-07 00:23:42 +00003952
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003953int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3954
3955 if (Name.startswith("fcc")) {
3956 StringRef NumString = Name.substr(3);
3957 unsigned IntVal;
3958 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003959 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003960 if (IntVal > 7) // There are only 8 fcc registers.
3961 return -1;
3962 return IntVal;
3963 }
3964 return -1;
3965}
3966
3967int MipsAsmParser::matchACRegisterName(StringRef Name) {
3968
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003969 if (Name.startswith("ac")) {
3970 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003971 unsigned IntVal;
3972 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003973 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003974 if (IntVal > 3) // There are only 3 acc registers.
3975 return -1;
3976 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003977 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003978 return -1;
3979}
Jack Carterd0bd6422013-04-18 00:41:53 +00003980
Jack Carter5dc8ac92013-09-25 23:50:44 +00003981int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3982 unsigned IntVal;
3983
3984 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3985 return -1;
3986
3987 if (IntVal > 31)
3988 return -1;
3989
3990 return IntVal;
3991}
3992
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003993int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3994 int CC;
3995
3996 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003997 .Case("msair", 0)
3998 .Case("msacsr", 1)
3999 .Case("msaaccess", 2)
4000 .Case("msasave", 3)
4001 .Case("msamodify", 4)
4002 .Case("msarequest", 5)
4003 .Case("msamap", 6)
4004 .Case("msaunmap", 7)
4005 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004006
4007 return CC;
4008}
4009
Toma Tabacu89a712b2015-04-15 10:48:56 +00004010unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004011 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004012 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004013 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004014 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004015 return 0;
4016 }
4017 unsigned AT = getReg(
4018 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004019 return AT;
4020}
Jack Carter0b744b32012-10-04 02:29:46 +00004021
Jack Carterd0bd6422013-04-18 00:41:53 +00004022unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004023 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004024}
4025
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004026unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004027 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00004028 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004029}
4030
Jack Carter873c7242013-01-12 01:03:14 +00004031int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004032 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00004033 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00004034 return -1;
4035
Jack Carter873c7242013-01-12 01:03:14 +00004036 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00004037}
4038
Toma Tabacu13964452014-09-04 13:23:44 +00004039bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004040 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004041 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004042
Jack Carter30a59822012-10-04 04:03:53 +00004043 // Check if the current operand has a custom associated parser, if so, try to
4044 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004045 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4046 if (ResTy == MatchOperand_Success)
4047 return false;
4048 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4049 // there was a match, but an error occurred, in which case, just return that
4050 // the operand parsing failed.
4051 if (ResTy == MatchOperand_ParseFail)
4052 return true;
4053
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004054 DEBUG(dbgs() << ".. Generic Parser\n");
4055
Jack Carterb4dbc172012-09-05 23:34:03 +00004056 switch (getLexer().getKind()) {
4057 default:
4058 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4059 return true;
4060 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004061 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004062 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004063
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004064 // Almost all registers have been parsed by custom parsers. There is only
4065 // one exception to this. $zero (and it's alias $0) will reach this point
4066 // for div, divu, and similar instructions because it is not an operand
4067 // to the instruction definition but an explicit register. Special case
4068 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004069 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004070 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004071
Jack Carterd0bd6422013-04-18 00:41:53 +00004072 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004073 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004074 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004075 return true;
4076
Jack Carter873c7242013-01-12 01:03:14 +00004077 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004078 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004079 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004080 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004081 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004082
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004083 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004084 return false;
4085 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004086 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004087 case AsmToken::LParen:
4088 case AsmToken::Minus:
4089 case AsmToken::Plus:
4090 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004091 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004092 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004093 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004094 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004095 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004096 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004097 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004098 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004099 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004100 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004101 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004102 return true;
4103
Jack Carter873c7242013-01-12 01:03:14 +00004104 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4105
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004106 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004107 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004108 } // case AsmToken::Percent
4109 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004110 return true;
4111}
4112
Vladimir Medic4c299852013-11-06 11:27:05 +00004113const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004114 StringRef RelocStr) {
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004115 if (RelocStr == "hi(%neg(%gp_rel")
4116 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext());
4117 else if (RelocStr == "lo(%neg(%gp_rel")
4118 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004119
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004120 MipsMCExpr::MipsExprKind Kind =
4121 StringSwitch<MipsMCExpr::MipsExprKind>(RelocStr)
4122 .Case("call16", MipsMCExpr::MEK_GOT_CALL)
4123 .Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
4124 .Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
4125 .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
4126 .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
4127 .Case("got", MipsMCExpr::MEK_GOT)
4128 .Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
4129 .Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
4130 .Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
4131 .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
4132 .Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
4133 .Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
4134 .Case("gp_rel", MipsMCExpr::MEK_GPREL)
4135 .Case("hi", MipsMCExpr::MEK_HI)
4136 .Case("higher", MipsMCExpr::MEK_HIGHER)
4137 .Case("highest", MipsMCExpr::MEK_HIGHEST)
4138 .Case("lo", MipsMCExpr::MEK_LO)
4139 .Case("neg", MipsMCExpr::MEK_NEG)
4140 .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
4141 .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
4142 .Case("tlsgd", MipsMCExpr::MEK_TLSGD)
4143 .Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
4144 .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
4145 .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
4146 .Default(MipsMCExpr::MEK_None);
Jack Carterb5cf5902013-04-17 00:18:04 +00004147
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004148 assert(Kind != MipsMCExpr::MEK_None);
4149 return MipsMCExpr::create(Kind, Expr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004150}
4151
4152bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4153
4154 switch (Expr->getKind()) {
4155 case MCExpr::Constant:
4156 return true;
4157 case MCExpr::SymbolRef:
4158 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4159 case MCExpr::Binary:
4160 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4161 if (!isEvaluated(BE->getLHS()))
4162 return false;
4163 return isEvaluated(BE->getRHS());
4164 }
4165 case MCExpr::Unary:
4166 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004167 case MCExpr::Target:
4168 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004169 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004170 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004171}
Jack Carterd0bd6422013-04-18 00:41:53 +00004172
Jack Carterb5cf5902013-04-17 00:18:04 +00004173bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004174 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004175 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004176 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004177 if (Tok.isNot(AsmToken::Identifier))
4178 return true;
4179
Yaron Keren075759a2015-03-30 15:42:36 +00004180 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004181
Jack Carterd0bd6422013-04-18 00:41:53 +00004182 Parser.Lex(); // Eat the identifier.
4183 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004184 const MCExpr *IdVal;
4185 SMLoc EndLoc;
4186
4187 if (getLexer().getKind() == AsmToken::LParen) {
4188 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004189 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004190 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004191 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004192 const AsmToken &nextTok = Parser.getTok();
4193 if (nextTok.isNot(AsmToken::Identifier))
4194 return true;
4195 Str += "(%";
4196 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004197 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004198 if (getLexer().getKind() != AsmToken::LParen)
4199 return true;
4200 } else
4201 break;
4202 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004203 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004204 return true;
4205
4206 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004207 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004208
4209 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004210 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004211
Jack Carterd0bd6422013-04-18 00:41:53 +00004212 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004213 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004214}
4215
Jack Carterb4dbc172012-09-05 23:34:03 +00004216bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4217 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004218 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004219 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004220 if (ResTy == MatchOperand_Success) {
4221 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004222 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004223 StartLoc = Operand.getStartLoc();
4224 EndLoc = Operand.getEndLoc();
4225
4226 // AFAIK, we only support numeric registers and named GPR's in CFI
4227 // directives.
4228 // Don't worry about eating tokens before failing. Using an unrecognised
4229 // register is a parse error.
4230 if (Operand.isGPRAsmReg()) {
4231 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004232 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004233 }
4234
4235 return (RegNo == (unsigned)-1);
4236 }
4237
4238 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004239 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004240}
4241
Jack Carterb5cf5902013-04-17 00:18:04 +00004242bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004243 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004244 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004245 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004246 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004247
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004248 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004249 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004250 ++NumOfLParen;
4251 }
Jack Carter873c7242013-01-12 01:03:14 +00004252
Jack Carterd0bd6422013-04-18 00:41:53 +00004253 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004254 default:
4255 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004256 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004257 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004258 case AsmToken::Integer:
4259 case AsmToken::Minus:
4260 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004261 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004262 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004263 else
4264 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004265 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004266 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004267 break;
Jack Carter873c7242013-01-12 01:03:14 +00004268 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004269 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004270 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004271 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004272}
4273
David Blaikie960ea3f2014-06-08 16:18:35 +00004274MipsAsmParser::OperandMatchResultTy
4275MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004276 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004277 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004278 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004279 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004280 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004281 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004282 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004283 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004284
Jack Carterb5cf5902013-04-17 00:18:04 +00004285 if (getLexer().getKind() == AsmToken::LParen) {
4286 Parser.Lex();
4287 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004288 }
4289
Jack Carterb5cf5902013-04-17 00:18:04 +00004290 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004291 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004292 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004293
Jack Carterd0bd6422013-04-18 00:41:53 +00004294 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004295 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004296 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004297 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004298 SMLoc E =
4299 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004300 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004301 return MatchOperand_Success;
4302 }
4303 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004304 SMLoc E =
4305 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004306
Jack Carterd0bd6422013-04-18 00:41:53 +00004307 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004308 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004309 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004310 S, E, *this);
4311 Operands.push_back(
4312 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004313 return MatchOperand_Success;
4314 }
4315 Error(Parser.getTok().getLoc(), "'(' expected");
4316 return MatchOperand_ParseFail;
4317 }
4318
Jack Carterd0bd6422013-04-18 00:41:53 +00004319 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004320 }
4321
Toma Tabacu13964452014-09-04 13:23:44 +00004322 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004323 if (Res != MatchOperand_Success)
4324 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004325
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004326 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004327 Error(Parser.getTok().getLoc(), "')' expected");
4328 return MatchOperand_ParseFail;
4329 }
4330
Jack Carter873c7242013-01-12 01:03:14 +00004331 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4332
Jack Carterd0bd6422013-04-18 00:41:53 +00004333 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004334
Craig Topper062a2ba2014-04-25 05:30:21 +00004335 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004336 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004337
Jack Carterd0bd6422013-04-18 00:41:53 +00004338 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004339 std::unique_ptr<MipsOperand> op(
4340 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004341 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004342 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004343 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004344 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004345 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4346 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004347 if (IdVal->evaluateAsAbsolute(Imm))
4348 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004349 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004350 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004351 getContext());
4352 }
4353
David Blaikie960ea3f2014-06-08 16:18:35 +00004354 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004355 return MatchOperand_Success;
4356}
4357
David Blaikie960ea3f2014-06-08 16:18:35 +00004358bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004359 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004360 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004361 if (Sym) {
4362 SMLoc S = Parser.getTok().getLoc();
4363 const MCExpr *Expr;
4364 if (Sym->isVariable())
4365 Expr = Sym->getVariableValue();
4366 else
4367 return false;
4368 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004369 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004370 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004371 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004372 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004373 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004374 if (ResTy == MatchOperand_Success) {
4375 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004376 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004377 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004378 llvm_unreachable("Should never ParseFail");
4379 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004380 }
4381 } else if (Expr->getKind() == MCExpr::Constant) {
4382 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004383 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004384 Operands.push_back(
4385 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004386 return true;
4387 }
4388 }
4389 return false;
4390}
Jack Carterd0bd6422013-04-18 00:41:53 +00004391
Jack Carter873c7242013-01-12 01:03:14 +00004392MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004393MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004394 StringRef Identifier,
4395 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004396 int Index = matchCPURegisterName(Identifier);
4397 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004398 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004399 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4400 return MatchOperand_Success;
4401 }
4402
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004403 Index = matchHWRegsRegisterName(Identifier);
4404 if (Index != -1) {
4405 Operands.push_back(MipsOperand::createHWRegsReg(
4406 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4407 return MatchOperand_Success;
4408 }
4409
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004410 Index = matchFPURegisterName(Identifier);
4411 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004412 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004413 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4414 return MatchOperand_Success;
4415 }
4416
4417 Index = matchFCCRegisterName(Identifier);
4418 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004419 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004420 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4421 return MatchOperand_Success;
4422 }
4423
4424 Index = matchACRegisterName(Identifier);
4425 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004426 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004427 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4428 return MatchOperand_Success;
4429 }
4430
4431 Index = matchMSA128RegisterName(Identifier);
4432 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004433 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004434 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4435 return MatchOperand_Success;
4436 }
4437
4438 Index = matchMSA128CtrlRegisterName(Identifier);
4439 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004440 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004441 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4442 return MatchOperand_Success;
4443 }
4444
4445 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004446}
4447
4448MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004449MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004450 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004451 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004452
4453 if (Token.is(AsmToken::Identifier)) {
4454 DEBUG(dbgs() << ".. identifier\n");
4455 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004456 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004457 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004458 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004459 } else if (Token.is(AsmToken::Integer)) {
4460 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004461 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004462 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4463 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004464 return MatchOperand_Success;
4465 }
4466
4467 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4468
4469 return MatchOperand_NoMatch;
4470}
4471
David Blaikie960ea3f2014-06-08 16:18:35 +00004472MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004473MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004474 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004475 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004476
4477 auto Token = Parser.getTok();
4478
4479 SMLoc S = Token.getLoc();
4480
4481 if (Token.isNot(AsmToken::Dollar)) {
4482 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4483 if (Token.is(AsmToken::Identifier)) {
4484 if (searchSymbolAlias(Operands))
4485 return MatchOperand_Success;
4486 }
4487 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4488 return MatchOperand_NoMatch;
4489 }
4490 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004491
Toma Tabacu13964452014-09-04 13:23:44 +00004492 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004493 if (ResTy == MatchOperand_Success) {
4494 Parser.Lex(); // $
4495 Parser.Lex(); // identifier
4496 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004497 return ResTy;
4498}
4499
4500MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004501MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004502 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004503 switch (getLexer().getKind()) {
4504 default:
4505 return MatchOperand_NoMatch;
4506 case AsmToken::LParen:
4507 case AsmToken::Minus:
4508 case AsmToken::Plus:
4509 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004510 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004511 case AsmToken::String:
4512 break;
4513 }
4514
4515 const MCExpr *IdVal;
4516 SMLoc S = Parser.getTok().getLoc();
4517 if (getParser().parseExpression(IdVal))
4518 return MatchOperand_ParseFail;
4519
4520 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4521 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4522 return MatchOperand_Success;
4523}
4524
David Blaikie960ea3f2014-06-08 16:18:35 +00004525MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004526MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004527 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004528 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004529
4530 SMLoc S = getLexer().getLoc();
4531
4532 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004533 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004534 if (ResTy != MatchOperand_NoMatch)
4535 return ResTy;
4536
Daniel Sanders315386c2014-04-01 10:40:14 +00004537 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004538 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004539 if (ResTy != MatchOperand_NoMatch)
4540 return ResTy;
4541
Daniel Sandersffd84362014-04-01 10:41:48 +00004542 const MCExpr *Expr = nullptr;
4543 if (Parser.parseExpression(Expr)) {
4544 // We have no way of knowing if a symbol was consumed so we must ParseFail
4545 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004546 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004547 Operands.push_back(
4548 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004549 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004550}
4551
Vladimir Medic2b953d02013-10-01 09:48:56 +00004552MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004553MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004554 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004555 const MCExpr *IdVal;
4556 // If the first token is '$' we may have register operand.
4557 if (Parser.getTok().is(AsmToken::Dollar))
4558 return MatchOperand_NoMatch;
4559 SMLoc S = Parser.getTok().getLoc();
4560 if (getParser().parseExpression(IdVal))
4561 return MatchOperand_ParseFail;
4562 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004563 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004564 int64_t Val = MCE->getValue();
4565 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4566 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004567 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004568 return MatchOperand_Success;
4569}
4570
Matheus Almeida779c5932013-11-18 12:32:49 +00004571MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004572MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004573 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004574 switch (getLexer().getKind()) {
4575 default:
4576 return MatchOperand_NoMatch;
4577 case AsmToken::LParen:
4578 case AsmToken::Plus:
4579 case AsmToken::Minus:
4580 case AsmToken::Integer:
4581 break;
4582 }
4583
4584 const MCExpr *Expr;
4585 SMLoc S = Parser.getTok().getLoc();
4586
4587 if (getParser().parseExpression(Expr))
4588 return MatchOperand_ParseFail;
4589
4590 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004591 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004592 Error(S, "expected immediate value");
4593 return MatchOperand_ParseFail;
4594 }
4595
4596 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4597 // and because the CPU always adds one to the immediate field, the allowed
4598 // range becomes 1..4. We'll only check the range here and will deal
4599 // with the addition/subtraction when actually decoding/encoding
4600 // the instruction.
4601 if (Val < 1 || Val > 4) {
4602 Error(S, "immediate not in range (1..4)");
4603 return MatchOperand_ParseFail;
4604 }
4605
Jack Carter3b2c96e2014-01-22 23:31:38 +00004606 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004607 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004608 return MatchOperand_Success;
4609}
4610
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004611MipsAsmParser::OperandMatchResultTy
4612MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4613 MCAsmParser &Parser = getParser();
4614 SmallVector<unsigned, 10> Regs;
4615 unsigned RegNo;
4616 unsigned PrevReg = Mips::NoRegister;
4617 bool RegRange = false;
4618 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4619
4620 if (Parser.getTok().isNot(AsmToken::Dollar))
4621 return MatchOperand_ParseFail;
4622
4623 SMLoc S = Parser.getTok().getLoc();
4624 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4625 SMLoc E = getLexer().getLoc();
4626 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4627 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4628 if (RegRange) {
4629 // Remove last register operand because registers from register range
4630 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004631 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4632 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004633 Regs.push_back(RegNo);
4634 } else {
4635 unsigned TmpReg = PrevReg + 1;
4636 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004637 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4638 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4639 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004640 Error(E, "invalid register operand");
4641 return MatchOperand_ParseFail;
4642 }
4643
4644 PrevReg = TmpReg;
4645 Regs.push_back(TmpReg++);
4646 }
4647 }
4648
4649 RegRange = false;
4650 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004651 if ((PrevReg == Mips::NoRegister) &&
4652 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4653 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004654 Error(E, "$16 or $31 expected");
4655 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004656 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4657 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4658 !isGP64bit()) ||
4659 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4660 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4661 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004662 Error(E, "invalid register operand");
4663 return MatchOperand_ParseFail;
4664 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004665 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4666 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4667 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004668 Error(E, "consecutive register numbers expected");
4669 return MatchOperand_ParseFail;
4670 }
4671
4672 Regs.push_back(RegNo);
4673 }
4674
4675 if (Parser.getTok().is(AsmToken::Minus))
4676 RegRange = true;
4677
4678 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4679 !Parser.getTok().isNot(AsmToken::Comma)) {
4680 Error(E, "',' or '-' expected");
4681 return MatchOperand_ParseFail;
4682 }
4683
4684 Lex(); // Consume comma or minus
4685 if (Parser.getTok().isNot(AsmToken::Dollar))
4686 break;
4687
4688 PrevReg = RegNo;
4689 }
4690
4691 SMLoc E = Parser.getTok().getLoc();
4692 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4693 parseMemOperand(Operands);
4694 return MatchOperand_Success;
4695}
4696
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004697MipsAsmParser::OperandMatchResultTy
4698MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4699 MCAsmParser &Parser = getParser();
4700
4701 SMLoc S = Parser.getTok().getLoc();
4702 if (parseAnyRegister(Operands) != MatchOperand_Success)
4703 return MatchOperand_ParseFail;
4704
4705 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00004706 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00004707
Benjamin Kramer2b68d152016-05-09 10:31:17 +00004708 Operands.pop_back();
4709 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004710 return MatchOperand_Success;
4711}
4712
Zoran Jovanovic41688672015-02-10 16:36:20 +00004713MipsAsmParser::OperandMatchResultTy
4714MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4715 MCAsmParser &Parser = getParser();
4716 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4717 SmallVector<unsigned, 10> Regs;
4718
4719 if (Parser.getTok().isNot(AsmToken::Dollar))
4720 return MatchOperand_ParseFail;
4721
4722 SMLoc S = Parser.getTok().getLoc();
4723
4724 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4725 return MatchOperand_ParseFail;
4726
4727 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4728 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4729 Regs.push_back(RegNo);
4730
4731 SMLoc E = Parser.getTok().getLoc();
4732 if (Parser.getTok().isNot(AsmToken::Comma)) {
4733 Error(E, "',' expected");
4734 return MatchOperand_ParseFail;
4735 }
4736
4737 // Remove comma.
4738 Parser.Lex();
4739
4740 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4741 return MatchOperand_ParseFail;
4742
4743 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4744 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4745 Regs.push_back(RegNo);
4746
4747 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4748
4749 return MatchOperand_Success;
4750}
4751
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004752/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4753/// either this.
4754/// ::= '(', register, ')'
4755/// handle it before we iterate so we don't get tripped up by the lack of
4756/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004757bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004758 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004759 if (getLexer().is(AsmToken::LParen)) {
4760 Operands.push_back(
4761 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4762 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004763 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004764 SMLoc Loc = getLexer().getLoc();
4765 Parser.eatToEndOfStatement();
4766 return Error(Loc, "unexpected token in argument list");
4767 }
4768 if (Parser.getTok().isNot(AsmToken::RParen)) {
4769 SMLoc Loc = getLexer().getLoc();
4770 Parser.eatToEndOfStatement();
4771 return Error(Loc, "unexpected token, expected ')'");
4772 }
4773 Operands.push_back(
4774 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4775 Parser.Lex();
4776 }
4777 return false;
4778}
4779
4780/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4781/// either one of these.
4782/// ::= '[', register, ']'
4783/// ::= '[', integer, ']'
4784/// handle it before we iterate so we don't get tripped up by the lack of
4785/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004786bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004787 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004788 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004789 if (getLexer().is(AsmToken::LBrac)) {
4790 Operands.push_back(
4791 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4792 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004793 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004794 SMLoc Loc = getLexer().getLoc();
4795 Parser.eatToEndOfStatement();
4796 return Error(Loc, "unexpected token in argument list");
4797 }
4798 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4799 SMLoc Loc = getLexer().getLoc();
4800 Parser.eatToEndOfStatement();
4801 return Error(Loc, "unexpected token, expected ']'");
4802 }
4803 Operands.push_back(
4804 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4805 Parser.Lex();
4806 }
4807 return false;
4808}
4809
David Blaikie960ea3f2014-06-08 16:18:35 +00004810bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4811 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004812 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004813 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004814
4815 // We have reached first instruction, module directive are now forbidden.
4816 getTargetStreamer().forbidModuleDirective();
4817
Vladimir Medic74593e62013-07-17 15:00:42 +00004818 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004819 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004820 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004821 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004822 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004823 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004824 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004825
4826 // Read the remaining operands.
4827 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4828 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004829 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004830 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004831 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004832 return Error(Loc, "unexpected token in argument list");
4833 }
Toma Tabacu13964452014-09-04 13:23:44 +00004834 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004835 return true;
4836 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004837
Jack Carterd0bd6422013-04-18 00:41:53 +00004838 while (getLexer().is(AsmToken::Comma)) {
4839 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004840 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004841 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004842 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004843 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004844 return Error(Loc, "unexpected token in argument list");
4845 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004846 // Parse bracket and parenthesis suffixes before we iterate
4847 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004848 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004849 return true;
4850 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004851 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004852 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004853 }
4854 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004855 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4856 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004857 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004858 return Error(Loc, "unexpected token in argument list");
4859 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004860 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004861 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004862}
4863
Nirav Dave996fc132016-05-05 14:15:46 +00004864// FIXME: Given that these have the same name, these should both be
4865// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004866bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004867 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004868 SMLoc Loc = getLexer().getLoc();
4869 Parser.eatToEndOfStatement();
4870 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004871}
4872
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004873bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004874 return Error(Loc, ErrorMsg);
4875}
4876
Jack Carter0b744b32012-10-04 02:29:46 +00004877bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004878 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004879 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004880
4881 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004882 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004883
4884 Parser.Lex(); // Eat "noat".
4885
Jack Carterd0bd6422013-04-18 00:41:53 +00004886 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004887 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004888 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004889 return false;
4890 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004891
4892 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004893 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004894 return false;
4895}
Jack Carterd0bd6422013-04-18 00:41:53 +00004896
Jack Carter0b744b32012-10-04 02:29:46 +00004897bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004898 // Line can be: ".set at", which sets $at to $1
4899 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004900 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004901 Parser.Lex(); // Eat "at".
4902
Jack Carter0b744b32012-10-04 02:29:46 +00004903 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004904 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004905 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004906
4907 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004908 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004909 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004910 }
4911
4912 if (getLexer().isNot(AsmToken::Equal)) {
4913 reportParseError("unexpected token, expected equals sign");
4914 return false;
4915 }
4916 Parser.Lex(); // Eat "=".
4917
4918 if (getLexer().isNot(AsmToken::Dollar)) {
4919 if (getLexer().is(AsmToken::EndOfStatement)) {
4920 reportParseError("no register specified");
4921 return false;
4922 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004923 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004924 return false;
4925 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004926 }
4927 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004928
Toma Tabacu16a74492015-02-13 10:30:57 +00004929 // Find out what "reg" is.
4930 unsigned AtRegNo;
4931 const AsmToken &Reg = Parser.getTok();
4932 if (Reg.is(AsmToken::Identifier)) {
4933 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4934 } else if (Reg.is(AsmToken::Integer)) {
4935 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004936 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004937 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004938 return false;
4939 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004940
4941 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004942 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004943 reportParseError("invalid register");
4944 return false;
4945 }
4946 Parser.Lex(); // Eat "reg".
4947
4948 // If this is not the end of the statement, report an error.
4949 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4950 reportParseError("unexpected token, expected end of statement");
4951 return false;
4952 }
4953
4954 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4955
4956 Parser.Lex(); // Consume the EndOfStatement.
4957 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004958}
4959
4960bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004961 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004962 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004963 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004964 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004965 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004966 return false;
4967 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004968 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004969 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004970 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004971 return false;
4972}
4973
4974bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004975 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004976 Parser.Lex();
4977 // If this is not the end of the statement, report an error.
4978 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004979 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004980 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004981 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004982 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004983 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004984 Parser.Lex(); // Consume the EndOfStatement.
4985 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004986}
4987
4988bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004989 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004990 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004991 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004992 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004993 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004994 return false;
4995 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004996 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004997 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004998 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004999 return false;
5000}
5001
5002bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005003 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005004 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005005 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005006 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005007 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005008 return false;
5009 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005010 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005011 reportParseError("`noreorder' must be set before `nomacro'");
5012 return false;
5013 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005014 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005015 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005016 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005017 return false;
5018}
Jack Carterd76b2372013-03-21 21:44:16 +00005019
Daniel Sanders44934432014-08-07 12:03:36 +00005020bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005021 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005022 Parser.Lex();
5023
5024 // If this is not the end of the statement, report an error.
5025 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005026 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005027
5028 setFeatureBits(Mips::FeatureMSA, "msa");
5029 getTargetStreamer().emitDirectiveSetMsa();
5030 return false;
5031}
5032
5033bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005034 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005035 Parser.Lex();
5036
5037 // If this is not the end of the statement, report an error.
5038 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005039 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005040
5041 clearFeatureBits(Mips::FeatureMSA, "msa");
5042 getTargetStreamer().emitDirectiveSetNoMsa();
5043 return false;
5044}
5045
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005046bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005047 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005048 Parser.Lex(); // Eat "nodsp".
5049
5050 // If this is not the end of the statement, report an error.
5051 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5052 reportParseError("unexpected token, expected end of statement");
5053 return false;
5054 }
5055
5056 clearFeatureBits(Mips::FeatureDSP, "dsp");
5057 getTargetStreamer().emitDirectiveSetNoDsp();
5058 return false;
5059}
5060
Toma Tabacucc2502d2014-11-04 17:18:07 +00005061bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005062 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005063 Parser.Lex(); // Eat "mips16".
5064
Jack Carter39536722014-01-22 23:08:42 +00005065 // If this is not the end of the statement, report an error.
5066 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005067 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005068 return false;
5069 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005070
5071 setFeatureBits(Mips::FeatureMips16, "mips16");
5072 getTargetStreamer().emitDirectiveSetMips16();
5073 Parser.Lex(); // Consume the EndOfStatement.
5074 return false;
5075}
5076
5077bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005078 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005079 Parser.Lex(); // Eat "nomips16".
5080
5081 // If this is not the end of the statement, report an error.
5082 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5083 reportParseError("unexpected token, expected end of statement");
5084 return false;
5085 }
5086
5087 clearFeatureBits(Mips::FeatureMips16, "mips16");
5088 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005089 Parser.Lex(); // Consume the EndOfStatement.
5090 return false;
5091}
5092
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005093bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005094 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005095 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005096 // Line can be: .set fp=32
5097 // .set fp=xx
5098 // .set fp=64
5099 Parser.Lex(); // Eat fp token
5100 AsmToken Tok = Parser.getTok();
5101 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005102 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005103 return false;
5104 }
5105 Parser.Lex(); // Eat '=' token.
5106 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005107
5108 if (!parseFpABIValue(FpAbiVal, ".set"))
5109 return false;
5110
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005111 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005112 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005113 return false;
5114 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005115 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005116 Parser.Lex(); // Consume the EndOfStatement.
5117 return false;
5118}
5119
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005120bool MipsAsmParser::parseSetOddSPRegDirective() {
5121 MCAsmParser &Parser = getParser();
5122
5123 Parser.Lex(); // Eat "oddspreg".
5124 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5125 reportParseError("unexpected token, expected end of statement");
5126 return false;
5127 }
5128
5129 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5130 getTargetStreamer().emitDirectiveSetOddSPReg();
5131 return false;
5132}
5133
5134bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5135 MCAsmParser &Parser = getParser();
5136
5137 Parser.Lex(); // Eat "nooddspreg".
5138 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5139 reportParseError("unexpected token, expected end of statement");
5140 return false;
5141 }
5142
5143 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5144 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5145 return false;
5146}
5147
Toma Tabacu9db22db2014-09-09 10:15:38 +00005148bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005149 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005150 SMLoc Loc = getLexer().getLoc();
5151
5152 Parser.Lex();
5153 if (getLexer().isNot(AsmToken::EndOfStatement))
5154 return reportParseError("unexpected token, expected end of statement");
5155
5156 // Always keep an element on the options "stack" to prevent the user
5157 // from changing the initial options. This is how we remember them.
5158 if (AssemblerOptions.size() == 2)
5159 return reportParseError(Loc, ".set pop with no .set push");
5160
Akira Hatanakab11ef082015-11-14 06:35:56 +00005161 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005162 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005163 setAvailableFeatures(
5164 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5165 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005166
5167 getTargetStreamer().emitDirectiveSetPop();
5168 return false;
5169}
5170
5171bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005172 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005173 Parser.Lex();
5174 if (getLexer().isNot(AsmToken::EndOfStatement))
5175 return reportParseError("unexpected token, expected end of statement");
5176
5177 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005178 AssemblerOptions.push_back(
5179 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005180
5181 getTargetStreamer().emitDirectiveSetPush();
5182 return false;
5183}
5184
Toma Tabacu29696502015-06-02 09:48:04 +00005185bool MipsAsmParser::parseSetSoftFloatDirective() {
5186 MCAsmParser &Parser = getParser();
5187 Parser.Lex();
5188 if (getLexer().isNot(AsmToken::EndOfStatement))
5189 return reportParseError("unexpected token, expected end of statement");
5190
5191 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5192 getTargetStreamer().emitDirectiveSetSoftFloat();
5193 return false;
5194}
5195
5196bool MipsAsmParser::parseSetHardFloatDirective() {
5197 MCAsmParser &Parser = getParser();
5198 Parser.Lex();
5199 if (getLexer().isNot(AsmToken::EndOfStatement))
5200 return reportParseError("unexpected token, expected end of statement");
5201
5202 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5203 getTargetStreamer().emitDirectiveSetHardFloat();
5204 return false;
5205}
5206
Jack Carterd76b2372013-03-21 21:44:16 +00005207bool MipsAsmParser::parseSetAssignment() {
5208 StringRef Name;
5209 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005210 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005211
5212 if (Parser.parseIdentifier(Name))
5213 reportParseError("expected identifier after .set");
5214
5215 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005216 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005217 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005218
Jack Carter3b2c96e2014-01-22 23:31:38 +00005219 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005220 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005221
Jim Grosbach6f482002015-05-18 18:43:14 +00005222 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005223 Sym->setVariableValue(Value);
5224
5225 return false;
5226}
Jack Carterd0bd6422013-04-18 00:41:53 +00005227
Toma Tabacu26647792014-09-09 12:52:14 +00005228bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005229 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005230 Parser.Lex();
5231 if (getLexer().isNot(AsmToken::EndOfStatement))
5232 return reportParseError("unexpected token, expected end of statement");
5233
5234 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005235 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005236 setAvailableFeatures(
5237 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5238 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005239 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5240
5241 getTargetStreamer().emitDirectiveSetMips0();
5242 return false;
5243}
5244
Toma Tabacu85618b32014-08-19 14:22:52 +00005245bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005246 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005247 Parser.Lex();
5248 if (getLexer().isNot(AsmToken::Equal))
5249 return reportParseError("unexpected token, expected equals sign");
5250
5251 Parser.Lex();
5252 StringRef Arch;
5253 if (Parser.parseIdentifier(Arch))
5254 return reportParseError("expected arch identifier");
5255
5256 StringRef ArchFeatureName =
5257 StringSwitch<StringRef>(Arch)
5258 .Case("mips1", "mips1")
5259 .Case("mips2", "mips2")
5260 .Case("mips3", "mips3")
5261 .Case("mips4", "mips4")
5262 .Case("mips5", "mips5")
5263 .Case("mips32", "mips32")
5264 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005265 .Case("mips32r3", "mips32r3")
5266 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005267 .Case("mips32r6", "mips32r6")
5268 .Case("mips64", "mips64")
5269 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005270 .Case("mips64r3", "mips64r3")
5271 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005272 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005273 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005274 .Case("r4000", "mips3") // This is an implementation of Mips3.
5275 .Default("");
5276
5277 if (ArchFeatureName.empty())
5278 return reportParseError("unsupported architecture");
5279
5280 selectArch(ArchFeatureName);
5281 getTargetStreamer().emitDirectiveSetArch(Arch);
5282 return false;
5283}
5284
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005285bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005286 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005287 Parser.Lex();
5288 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005289 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005290
Matheus Almeida2852af82014-04-22 10:15:54 +00005291 switch (Feature) {
5292 default:
5293 llvm_unreachable("Unimplemented feature");
5294 case Mips::FeatureDSP:
5295 setFeatureBits(Mips::FeatureDSP, "dsp");
5296 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005297 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005298 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00005299 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00005300 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005301 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005302 case Mips::FeatureMips1:
5303 selectArch("mips1");
5304 getTargetStreamer().emitDirectiveSetMips1();
5305 break;
5306 case Mips::FeatureMips2:
5307 selectArch("mips2");
5308 getTargetStreamer().emitDirectiveSetMips2();
5309 break;
5310 case Mips::FeatureMips3:
5311 selectArch("mips3");
5312 getTargetStreamer().emitDirectiveSetMips3();
5313 break;
5314 case Mips::FeatureMips4:
5315 selectArch("mips4");
5316 getTargetStreamer().emitDirectiveSetMips4();
5317 break;
5318 case Mips::FeatureMips5:
5319 selectArch("mips5");
5320 getTargetStreamer().emitDirectiveSetMips5();
5321 break;
5322 case Mips::FeatureMips32:
5323 selectArch("mips32");
5324 getTargetStreamer().emitDirectiveSetMips32();
5325 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005326 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005327 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005328 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005329 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005330 case Mips::FeatureMips32r3:
5331 selectArch("mips32r3");
5332 getTargetStreamer().emitDirectiveSetMips32R3();
5333 break;
5334 case Mips::FeatureMips32r5:
5335 selectArch("mips32r5");
5336 getTargetStreamer().emitDirectiveSetMips32R5();
5337 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005338 case Mips::FeatureMips32r6:
5339 selectArch("mips32r6");
5340 getTargetStreamer().emitDirectiveSetMips32R6();
5341 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005342 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005343 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005344 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005345 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005346 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005347 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005348 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005349 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005350 case Mips::FeatureMips64r3:
5351 selectArch("mips64r3");
5352 getTargetStreamer().emitDirectiveSetMips64R3();
5353 break;
5354 case Mips::FeatureMips64r5:
5355 selectArch("mips64r5");
5356 getTargetStreamer().emitDirectiveSetMips64R5();
5357 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005358 case Mips::FeatureMips64r6:
5359 selectArch("mips64r6");
5360 getTargetStreamer().emitDirectiveSetMips64R6();
5361 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005362 }
5363 return false;
5364}
5365
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005366bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005367 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005368 if (getLexer().isNot(AsmToken::Comma)) {
5369 SMLoc Loc = getLexer().getLoc();
5370 Parser.eatToEndOfStatement();
5371 return Error(Loc, ErrorStr);
5372 }
5373
Matheus Almeida2852af82014-04-22 10:15:54 +00005374 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005375 return true;
5376}
5377
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005378// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5379// In this class, it is only used for .cprestore.
5380// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5381// MipsTargetELFStreamer and MipsAsmParser.
5382bool MipsAsmParser::isPicAndNotNxxAbi() {
5383 return inPicMode() && !(isABI_N32() || isABI_N64());
5384}
5385
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005386bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005387 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005388 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005389
Toma Tabacudde4c462014-11-06 10:02:45 +00005390 if (inMips16Mode()) {
5391 reportParseError(".cpload is not supported in Mips16 mode");
5392 return false;
5393 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005394
David Blaikie960ea3f2014-06-08 16:18:35 +00005395 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005396 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005397 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5398 reportParseError("expected register containing function address");
5399 return false;
5400 }
5401
David Blaikie960ea3f2014-06-08 16:18:35 +00005402 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5403 if (!RegOpnd.isGPRAsmReg()) {
5404 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005405 return false;
5406 }
5407
Toma Tabacudde4c462014-11-06 10:02:45 +00005408 // If this is not the end of the statement, report an error.
5409 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5410 reportParseError("unexpected token, expected end of statement");
5411 return false;
5412 }
5413
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005414 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005415 return false;
5416}
5417
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005418bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5419 MCAsmParser &Parser = getParser();
5420
5421 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5422 // is used in non-PIC mode.
5423
5424 if (inMips16Mode()) {
5425 reportParseError(".cprestore is not supported in Mips16 mode");
5426 return false;
5427 }
5428
5429 // Get the stack offset value.
5430 const MCExpr *StackOffset;
5431 int64_t StackOffsetVal;
5432 if (Parser.parseExpression(StackOffset)) {
5433 reportParseError("expected stack offset value");
5434 return false;
5435 }
5436
5437 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5438 reportParseError("stack offset is not an absolute expression");
5439 return false;
5440 }
5441
5442 if (StackOffsetVal < 0) {
5443 Warning(Loc, ".cprestore with negative stack offset has no effect");
5444 IsCpRestoreSet = false;
5445 } else {
5446 IsCpRestoreSet = true;
5447 CpRestoreOffset = StackOffsetVal;
5448 }
5449
5450 // If this is not the end of the statement, report an error.
5451 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5452 reportParseError("unexpected token, expected end of statement");
5453 return false;
5454 }
5455
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005456 if (!getTargetStreamer().emitDirectiveCpRestore(
5457 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005458 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005459 Parser.Lex(); // Consume the EndOfStatement.
5460 return false;
5461}
5462
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005463bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005464 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005465 unsigned FuncReg;
5466 unsigned Save;
5467 bool SaveIsReg = true;
5468
Matheus Almeida7e815762014-06-18 13:08:59 +00005469 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005470 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005471 if (ResTy == MatchOperand_NoMatch) {
5472 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005473 return false;
5474 }
5475
5476 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5477 if (!FuncRegOpnd.isGPRAsmReg()) {
5478 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5479 Parser.eatToEndOfStatement();
5480 return false;
5481 }
5482
5483 FuncReg = FuncRegOpnd.getGPR32Reg();
5484 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005485
Toma Tabacu65f10572014-09-16 15:00:52 +00005486 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005487 return true;
5488
Toma Tabacu13964452014-09-04 13:23:44 +00005489 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005490 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005491 const MCExpr *OffsetExpr;
5492 int64_t OffsetVal;
5493 SMLoc ExprLoc = getLexer().getLoc();
5494
5495 if (Parser.parseExpression(OffsetExpr) ||
5496 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5497 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005498 Parser.eatToEndOfStatement();
5499 return false;
5500 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005501
5502 Save = OffsetVal;
5503 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005504 } else {
5505 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5506 if (!SaveOpnd.isGPRAsmReg()) {
5507 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5508 Parser.eatToEndOfStatement();
5509 return false;
5510 }
5511 Save = SaveOpnd.getGPR32Reg();
5512 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005513
Toma Tabacu65f10572014-09-16 15:00:52 +00005514 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005515 return true;
5516
Toma Tabacu8874eac2015-02-18 13:46:53 +00005517 const MCExpr *Expr;
5518 if (Parser.parseExpression(Expr)) {
5519 reportParseError("expected expression");
5520 return false;
5521 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005522
Toma Tabacu8874eac2015-02-18 13:46:53 +00005523 if (Expr->getKind() != MCExpr::SymbolRef) {
5524 reportParseError("expected symbol");
5525 return false;
5526 }
5527 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5528
Daniel Sandersf173dda2015-09-22 10:50:09 +00005529 CpSaveLocation = Save;
5530 CpSaveLocationIsRegister = SaveIsReg;
5531
Toma Tabacu8874eac2015-02-18 13:46:53 +00005532 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5533 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005534 return false;
5535}
5536
Daniel Sandersf173dda2015-09-22 10:50:09 +00005537bool MipsAsmParser::parseDirectiveCPReturn() {
5538 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5539 CpSaveLocationIsRegister);
5540 return false;
5541}
5542
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005543bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005544 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005545 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5546 const AsmToken &Tok = Parser.getTok();
5547
5548 if (Tok.getString() == "2008") {
5549 Parser.Lex();
5550 getTargetStreamer().emitDirectiveNaN2008();
5551 return false;
5552 } else if (Tok.getString() == "legacy") {
5553 Parser.Lex();
5554 getTargetStreamer().emitDirectiveNaNLegacy();
5555 return false;
5556 }
5557 }
5558 // If we don't recognize the option passed to the .nan
5559 // directive (e.g. no option or unknown option), emit an error.
5560 reportParseError("invalid option in .nan directive");
5561 return false;
5562}
5563
Jack Carter0b744b32012-10-04 02:29:46 +00005564bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005565 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005566 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005567 const AsmToken &Tok = Parser.getTok();
5568
5569 if (Tok.getString() == "noat") {
5570 return parseSetNoAtDirective();
5571 } else if (Tok.getString() == "at") {
5572 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005573 } else if (Tok.getString() == "arch") {
5574 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005575 } else if (Tok.getString() == "fp") {
5576 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005577 } else if (Tok.getString() == "oddspreg") {
5578 return parseSetOddSPRegDirective();
5579 } else if (Tok.getString() == "nooddspreg") {
5580 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005581 } else if (Tok.getString() == "pop") {
5582 return parseSetPopDirective();
5583 } else if (Tok.getString() == "push") {
5584 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005585 } else if (Tok.getString() == "reorder") {
5586 return parseSetReorderDirective();
5587 } else if (Tok.getString() == "noreorder") {
5588 return parseSetNoReorderDirective();
5589 } else if (Tok.getString() == "macro") {
5590 return parseSetMacroDirective();
5591 } else if (Tok.getString() == "nomacro") {
5592 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005593 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005594 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005595 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005596 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005597 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00005598 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005599 getTargetStreamer().emitDirectiveSetNoMicroMips();
5600 Parser.eatToEndOfStatement();
5601 return false;
5602 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005603 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005604 } else if (Tok.getString() == "mips0") {
5605 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005606 } else if (Tok.getString() == "mips1") {
5607 return parseSetFeature(Mips::FeatureMips1);
5608 } else if (Tok.getString() == "mips2") {
5609 return parseSetFeature(Mips::FeatureMips2);
5610 } else if (Tok.getString() == "mips3") {
5611 return parseSetFeature(Mips::FeatureMips3);
5612 } else if (Tok.getString() == "mips4") {
5613 return parseSetFeature(Mips::FeatureMips4);
5614 } else if (Tok.getString() == "mips5") {
5615 return parseSetFeature(Mips::FeatureMips5);
5616 } else if (Tok.getString() == "mips32") {
5617 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005618 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005619 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005620 } else if (Tok.getString() == "mips32r3") {
5621 return parseSetFeature(Mips::FeatureMips32r3);
5622 } else if (Tok.getString() == "mips32r5") {
5623 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005624 } else if (Tok.getString() == "mips32r6") {
5625 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005626 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005627 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005628 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005629 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005630 } else if (Tok.getString() == "mips64r3") {
5631 return parseSetFeature(Mips::FeatureMips64r3);
5632 } else if (Tok.getString() == "mips64r5") {
5633 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005634 } else if (Tok.getString() == "mips64r6") {
5635 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005636 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005637 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005638 } else if (Tok.getString() == "nodsp") {
5639 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005640 } else if (Tok.getString() == "msa") {
5641 return parseSetMsaDirective();
5642 } else if (Tok.getString() == "nomsa") {
5643 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005644 } else if (Tok.getString() == "softfloat") {
5645 return parseSetSoftFloatDirective();
5646 } else if (Tok.getString() == "hardfloat") {
5647 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005648 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005649 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005650 parseSetAssignment();
5651 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005652 }
Jack Carter07c818d2013-01-25 01:31:34 +00005653
Jack Carter0b744b32012-10-04 02:29:46 +00005654 return true;
5655}
5656
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005657/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005658/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005659bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005660 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005661 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5662 for (;;) {
5663 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005664 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005665 return true;
5666
5667 getParser().getStreamer().EmitValue(Value, Size);
5668
5669 if (getLexer().is(AsmToken::EndOfStatement))
5670 break;
5671
Jack Carter07c818d2013-01-25 01:31:34 +00005672 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005673 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005674 Parser.Lex();
5675 }
5676 }
5677
5678 Parser.Lex();
5679 return false;
5680}
5681
Vladimir Medic4c299852013-11-06 11:27:05 +00005682/// parseDirectiveGpWord
5683/// ::= .gpword local_sym
5684bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005685 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005686 const MCExpr *Value;
5687 // EmitGPRel32Value requires an expression, so we are using base class
5688 // method to evaluate the expression.
5689 if (getParser().parseExpression(Value))
5690 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005691 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005692
Vladimir Medice10c1122013-11-13 13:18:04 +00005693 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005694 return Error(getLexer().getLoc(),
5695 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005696 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005697 return false;
5698}
5699
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005700/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005701/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005702bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005703 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005704 const MCExpr *Value;
5705 // EmitGPRel64Value requires an expression, so we are using base class
5706 // method to evaluate the expression.
5707 if (getParser().parseExpression(Value))
5708 return true;
5709 getParser().getStreamer().EmitGPRel64Value(Value);
5710
5711 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005712 return Error(getLexer().getLoc(),
5713 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005714 Parser.Lex(); // Eat EndOfStatement token.
5715 return false;
5716}
5717
Jack Carter0cd3c192014-01-06 23:27:31 +00005718bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005719 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005720 // Get the option token.
5721 AsmToken Tok = Parser.getTok();
5722 // At the moment only identifiers are supported.
5723 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005724 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005725 Parser.eatToEndOfStatement();
5726 return false;
5727 }
5728
5729 StringRef Option = Tok.getIdentifier();
5730
5731 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005732 // MipsAsmParser needs to know if the current PIC mode changes.
5733 IsPicEnabled = false;
5734
Jack Carter0cd3c192014-01-06 23:27:31 +00005735 getTargetStreamer().emitDirectiveOptionPic0();
5736 Parser.Lex();
5737 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5738 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005739 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005740 Parser.eatToEndOfStatement();
5741 }
5742 return false;
5743 }
5744
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005745 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005746 // MipsAsmParser needs to know if the current PIC mode changes.
5747 IsPicEnabled = true;
5748
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005749 getTargetStreamer().emitDirectiveOptionPic2();
5750 Parser.Lex();
5751 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5752 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005753 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005754 Parser.eatToEndOfStatement();
5755 }
5756 return false;
5757 }
5758
Jack Carter0cd3c192014-01-06 23:27:31 +00005759 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005760 Warning(Parser.getTok().getLoc(),
5761 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005762 Parser.eatToEndOfStatement();
5763 return false;
5764}
5765
Toma Tabacu9ca50962015-04-16 09:53:47 +00005766/// parseInsnDirective
5767/// ::= .insn
5768bool MipsAsmParser::parseInsnDirective() {
5769 // If this is not the end of the statement, report an error.
5770 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5771 reportParseError("unexpected token, expected end of statement");
5772 return false;
5773 }
5774
5775 // The actual label marking happens in
5776 // MipsELFStreamer::createPendingLabelRelocs().
5777 getTargetStreamer().emitDirectiveInsn();
5778
5779 getParser().Lex(); // Eat EndOfStatement token.
5780 return false;
5781}
5782
Simon Atanasyanbe186202016-02-11 06:45:54 +00005783/// parseSSectionDirective
5784/// ::= .sbss
5785/// ::= .sdata
5786bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5787 // If this is not the end of the statement, report an error.
5788 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5789 reportParseError("unexpected token, expected end of statement");
5790 return false;
5791 }
5792
5793 MCSection *ELFSection = getContext().getELFSection(
5794 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5795 getParser().getStreamer().SwitchSection(ELFSection);
5796
5797 getParser().Lex(); // Eat EndOfStatement token.
5798 return false;
5799}
5800
Daniel Sanders7e527422014-07-10 13:38:23 +00005801/// parseDirectiveModule
5802/// ::= .module oddspreg
5803/// ::= .module nooddspreg
5804/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005805/// ::= .module softfloat
5806/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005807bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005808 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005809 MCAsmLexer &Lexer = getLexer();
5810 SMLoc L = Lexer.getLoc();
5811
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005812 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005813 // TODO : get a better message.
5814 reportParseError(".module directive must appear before any code");
5815 return false;
5816 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005817
Toma Tabacuc405c822015-01-23 10:40:19 +00005818 StringRef Option;
5819 if (Parser.parseIdentifier(Option)) {
5820 reportParseError("expected .module option identifier");
5821 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005822 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005823
Toma Tabacuc405c822015-01-23 10:40:19 +00005824 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005825 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005826
Toma Tabacu3c499582015-06-25 10:56:57 +00005827 // Synchronize the abiflags information with the FeatureBits information we
5828 // changed above.
5829 getTargetStreamer().updateABIInfo(*this);
5830
5831 // If printing assembly, use the recently updated abiflags information.
5832 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5833 // emitted at the end).
5834 getTargetStreamer().emitDirectiveModuleOddSPReg();
5835
Toma Tabacuc405c822015-01-23 10:40:19 +00005836 // If this is not the end of the statement, report an error.
5837 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5838 reportParseError("unexpected token, expected end of statement");
5839 return false;
5840 }
5841
5842 return false; // parseDirectiveModule has finished successfully.
5843 } else if (Option == "nooddspreg") {
5844 if (!isABI_O32()) {
5845 Error(L, "'.module nooddspreg' requires the O32 ABI");
5846 return false;
5847 }
5848
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005849 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005850
Toma Tabacu3c499582015-06-25 10:56:57 +00005851 // Synchronize the abiflags information with the FeatureBits information we
5852 // changed above.
5853 getTargetStreamer().updateABIInfo(*this);
5854
5855 // If printing assembly, use the recently updated abiflags information.
5856 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5857 // emitted at the end).
5858 getTargetStreamer().emitDirectiveModuleOddSPReg();
5859
Toma Tabacuc405c822015-01-23 10:40:19 +00005860 // If this is not the end of the statement, report an error.
5861 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5862 reportParseError("unexpected token, expected end of statement");
5863 return false;
5864 }
5865
5866 return false; // parseDirectiveModule has finished successfully.
5867 } else if (Option == "fp") {
5868 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005869 } else if (Option == "softfloat") {
5870 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5871
5872 // Synchronize the ABI Flags information with the FeatureBits information we
5873 // updated above.
5874 getTargetStreamer().updateABIInfo(*this);
5875
5876 // If printing assembly, use the recently updated ABI Flags information.
5877 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5878 // emitted later).
5879 getTargetStreamer().emitDirectiveModuleSoftFloat();
5880
5881 // If this is not the end of the statement, report an error.
5882 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5883 reportParseError("unexpected token, expected end of statement");
5884 return false;
5885 }
5886
5887 return false; // parseDirectiveModule has finished successfully.
5888 } else if (Option == "hardfloat") {
5889 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5890
5891 // Synchronize the ABI Flags information with the FeatureBits information we
5892 // updated above.
5893 getTargetStreamer().updateABIInfo(*this);
5894
5895 // If printing assembly, use the recently updated ABI Flags information.
5896 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5897 // emitted later).
5898 getTargetStreamer().emitDirectiveModuleHardFloat();
5899
5900 // If this is not the end of the statement, report an error.
5901 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5902 reportParseError("unexpected token, expected end of statement");
5903 return false;
5904 }
5905
5906 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005907 } else {
5908 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5909 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005910}
5911
5912/// parseDirectiveModuleFP
5913/// ::= =32
5914/// ::= =xx
5915/// ::= =64
5916bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005917 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005918 MCAsmLexer &Lexer = getLexer();
5919
5920 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005921 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005922 return false;
5923 }
5924 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005925
Daniel Sanders7e527422014-07-10 13:38:23 +00005926 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005927 if (!parseFpABIValue(FpABI, ".module"))
5928 return false;
5929
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005930 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005931 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005932 return false;
5933 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005934
Toma Tabacua64e5402015-06-25 12:44:38 +00005935 // Synchronize the abiflags information with the FeatureBits information we
5936 // changed above.
5937 getTargetStreamer().updateABIInfo(*this);
5938
5939 // If printing assembly, use the recently updated abiflags information.
5940 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5941 // emitted at the end).
5942 getTargetStreamer().emitDirectiveModuleFP();
5943
Daniel Sanders7e527422014-07-10 13:38:23 +00005944 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005945 return false;
5946}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005947
Daniel Sanders7e527422014-07-10 13:38:23 +00005948bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005949 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005950 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005951 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005952 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005953
5954 if (Lexer.is(AsmToken::Identifier)) {
5955 StringRef Value = Parser.getTok().getString();
5956 Parser.Lex();
5957
5958 if (Value != "xx") {
5959 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5960 return false;
5961 }
5962
5963 if (!isABI_O32()) {
5964 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5965 return false;
5966 }
5967
Daniel Sanders7e527422014-07-10 13:38:23 +00005968 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005969 if (ModuleLevelOptions) {
5970 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5971 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5972 } else {
5973 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5974 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5975 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005976 return true;
5977 }
5978
5979 if (Lexer.is(AsmToken::Integer)) {
5980 unsigned Value = Parser.getTok().getIntVal();
5981 Parser.Lex();
5982
5983 if (Value != 32 && Value != 64) {
5984 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5985 return false;
5986 }
5987
5988 if (Value == 32) {
5989 if (!isABI_O32()) {
5990 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5991 return false;
5992 }
5993
Daniel Sanders7e527422014-07-10 13:38:23 +00005994 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005995 if (ModuleLevelOptions) {
5996 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5997 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5998 } else {
5999 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6000 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6001 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006002 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006003 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006004 if (ModuleLevelOptions) {
6005 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6006 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6007 } else {
6008 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6009 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6010 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006011 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006012
Daniel Sanders7e527422014-07-10 13:38:23 +00006013 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006014 }
6015
6016 return false;
6017}
6018
Jack Carter0b744b32012-10-04 02:29:46 +00006019bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006020 // This returns false if this function recognizes the directive
6021 // regardless of whether it is successfully handles or reports an
6022 // error. Otherwise it returns true to give the generic parser a
6023 // chance at recognizing it.
6024
Rafael Espindola961d4692014-11-11 05:18:41 +00006025 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006026 StringRef IDVal = DirectiveID.getString();
6027
Nirav Dave996fc132016-05-05 14:15:46 +00006028 if (IDVal == ".cpload") {
6029 parseDirectiveCpLoad(DirectiveID.getLoc());
6030 return false;
6031 }
6032 if (IDVal == ".cprestore") {
6033 parseDirectiveCpRestore(DirectiveID.getLoc());
6034 return false;
6035 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006036 if (IDVal == ".dword") {
6037 parseDataDirective(8, DirectiveID.getLoc());
6038 return false;
6039 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006040 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006041 StringRef SymbolName;
6042
6043 if (Parser.parseIdentifier(SymbolName)) {
6044 reportParseError("expected identifier after .ent");
6045 return false;
6046 }
6047
6048 // There's an undocumented extension that allows an integer to
6049 // follow the name of the procedure which AFAICS is ignored by GAS.
6050 // Example: .ent foo,2
6051 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6052 if (getLexer().isNot(AsmToken::Comma)) {
6053 // Even though we accept this undocumented extension for compatibility
6054 // reasons, the additional integer argument does not actually change
6055 // the behaviour of the '.ent' directive, so we would like to discourage
6056 // its use. We do this by not referring to the extended version in
6057 // error messages which are not directly related to its use.
6058 reportParseError("unexpected token, expected end of statement");
6059 return false;
6060 }
6061 Parser.Lex(); // Eat the comma.
6062 const MCExpr *DummyNumber;
6063 int64_t DummyNumberVal;
6064 // If the user was explicitly trying to use the extended version,
6065 // we still give helpful extension-related error messages.
6066 if (Parser.parseExpression(DummyNumber)) {
6067 reportParseError("expected number after comma");
6068 return false;
6069 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006070 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006071 reportParseError("expected an absolute expression after comma");
6072 return false;
6073 }
6074 }
6075
6076 // If this is not the end of the statement, report an error.
6077 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6078 reportParseError("unexpected token, expected end of statement");
6079 return false;
6080 }
6081
Jim Grosbach6f482002015-05-18 18:43:14 +00006082 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006083
6084 getTargetStreamer().emitDirectiveEnt(*Sym);
6085 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006086 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006087 return false;
6088 }
6089
Jack Carter07c818d2013-01-25 01:31:34 +00006090 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006091 StringRef SymbolName;
6092
6093 if (Parser.parseIdentifier(SymbolName)) {
6094 reportParseError("expected identifier after .end");
6095 return false;
6096 }
6097
6098 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6099 reportParseError("unexpected token, expected end of statement");
6100 return false;
6101 }
6102
6103 if (CurrentFn == nullptr) {
6104 reportParseError(".end used without .ent");
6105 return false;
6106 }
6107
6108 if ((SymbolName != CurrentFn->getName())) {
6109 reportParseError(".end symbol does not match .ent symbol");
6110 return false;
6111 }
6112
6113 getTargetStreamer().emitDirectiveEnd(SymbolName);
6114 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006115 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006116 return false;
6117 }
6118
Jack Carter07c818d2013-01-25 01:31:34 +00006119 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006120 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6121 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006122 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006123 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6124 reportParseError("expected stack register");
6125 return false;
6126 }
6127
6128 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6129 if (!StackRegOpnd.isGPRAsmReg()) {
6130 reportParseError(StackRegOpnd.getStartLoc(),
6131 "expected general purpose register");
6132 return false;
6133 }
6134 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6135
6136 if (Parser.getTok().is(AsmToken::Comma))
6137 Parser.Lex();
6138 else {
6139 reportParseError("unexpected token, expected comma");
6140 return false;
6141 }
6142
6143 // Parse the frame size.
6144 const MCExpr *FrameSize;
6145 int64_t FrameSizeVal;
6146
6147 if (Parser.parseExpression(FrameSize)) {
6148 reportParseError("expected frame size value");
6149 return false;
6150 }
6151
Jim Grosbach13760bd2015-05-30 01:25:56 +00006152 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006153 reportParseError("frame size not an absolute expression");
6154 return false;
6155 }
6156
6157 if (Parser.getTok().is(AsmToken::Comma))
6158 Parser.Lex();
6159 else {
6160 reportParseError("unexpected token, expected comma");
6161 return false;
6162 }
6163
6164 // Parse the return register.
6165 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006166 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006167 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6168 reportParseError("expected return register");
6169 return false;
6170 }
6171
6172 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6173 if (!ReturnRegOpnd.isGPRAsmReg()) {
6174 reportParseError(ReturnRegOpnd.getStartLoc(),
6175 "expected general purpose register");
6176 return false;
6177 }
6178
6179 // If this is not the end of the statement, report an error.
6180 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6181 reportParseError("unexpected token, expected end of statement");
6182 return false;
6183 }
6184
6185 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6186 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006187 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006188 return false;
6189 }
6190
Jack Carter07c818d2013-01-25 01:31:34 +00006191 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006192 parseDirectiveSet();
6193 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006194 }
6195
Daniel Sandersd97a6342014-08-13 10:07:34 +00006196 if (IDVal == ".mask" || IDVal == ".fmask") {
6197 // .mask bitmask, frame_offset
6198 // bitmask: One bit for each register used.
6199 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6200 // first register is expected to be saved.
6201 // Examples:
6202 // .mask 0x80000000, -4
6203 // .fmask 0x80000000, -4
6204 //
Jack Carterbe332172012-09-07 00:48:02 +00006205
Daniel Sandersd97a6342014-08-13 10:07:34 +00006206 // Parse the bitmask
6207 const MCExpr *BitMask;
6208 int64_t BitMaskVal;
6209
6210 if (Parser.parseExpression(BitMask)) {
6211 reportParseError("expected bitmask value");
6212 return false;
6213 }
6214
Jim Grosbach13760bd2015-05-30 01:25:56 +00006215 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006216 reportParseError("bitmask not an absolute expression");
6217 return false;
6218 }
6219
6220 if (Parser.getTok().is(AsmToken::Comma))
6221 Parser.Lex();
6222 else {
6223 reportParseError("unexpected token, expected comma");
6224 return false;
6225 }
6226
6227 // Parse the frame_offset
6228 const MCExpr *FrameOffset;
6229 int64_t FrameOffsetVal;
6230
6231 if (Parser.parseExpression(FrameOffset)) {
6232 reportParseError("expected frame offset value");
6233 return false;
6234 }
6235
Jim Grosbach13760bd2015-05-30 01:25:56 +00006236 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006237 reportParseError("frame offset not an absolute expression");
6238 return false;
6239 }
6240
6241 // If this is not the end of the statement, report an error.
6242 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6243 reportParseError("unexpected token, expected end of statement");
6244 return false;
6245 }
6246
6247 if (IDVal == ".mask")
6248 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6249 else
6250 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006251 return false;
6252 }
6253
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006254 if (IDVal == ".nan")
6255 return parseDirectiveNaN();
6256
Jack Carter07c818d2013-01-25 01:31:34 +00006257 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006258 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006259 return false;
6260 }
6261
Rafael Espindolab59fb732014-03-28 18:50:26 +00006262 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006263 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006264 return false;
6265 }
6266
Jack Carter07c818d2013-01-25 01:31:34 +00006267 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006268 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006269 return false;
6270 }
6271
Scott Egertond1aeb052016-02-15 16:11:51 +00006272 if (IDVal == ".hword") {
6273 parseDataDirective(2, DirectiveID.getLoc());
6274 return false;
6275 }
6276
Nirav Dave996fc132016-05-05 14:15:46 +00006277 if (IDVal == ".option") {
6278 parseDirectiveOption();
6279 return false;
6280 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006281
6282 if (IDVal == ".abicalls") {
6283 getTargetStreamer().emitDirectiveAbiCalls();
6284 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006285 Error(Parser.getTok().getLoc(),
6286 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006287 // Clear line
6288 Parser.eatToEndOfStatement();
6289 }
6290 return false;
6291 }
6292
Nirav Dave996fc132016-05-05 14:15:46 +00006293 if (IDVal == ".cpsetup") {
6294 parseDirectiveCPSetup();
6295 return false;
6296 }
6297 if (IDVal == ".cpreturn") {
6298 parseDirectiveCPReturn();
6299 return false;
6300 }
6301 if (IDVal == ".module") {
6302 parseDirectiveModule();
6303 return false;
6304 }
6305 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6306 parseInternalDirectiveReallowModule();
6307 return false;
6308 }
6309 if (IDVal == ".insn") {
6310 parseInsnDirective();
6311 return false;
6312 }
6313 if (IDVal == ".sbss") {
6314 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6315 return false;
6316 }
6317 if (IDVal == ".sdata") {
6318 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6319 return false;
6320 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006321
Rafael Espindola870c4e92012-01-11 03:56:41 +00006322 return true;
6323}
6324
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006325bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6326 // If this is not the end of the statement, report an error.
6327 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6328 reportParseError("unexpected token, expected end of statement");
6329 return false;
6330 }
6331
6332 getTargetStreamer().reallowModuleDirective();
6333
6334 getParser().Lex(); // Eat EndOfStatement token.
6335 return false;
6336}
6337
Rafael Espindola870c4e92012-01-11 03:56:41 +00006338extern "C" void LLVMInitializeMipsAsmParser() {
6339 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6340 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6341 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6342 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6343}
Jack Carterb4dbc172012-09-05 23:34:03 +00006344
6345#define GET_REGISTER_MATCHER
6346#define GET_MATCHER_IMPLEMENTATION
6347#include "MipsGenAsmMatcher.inc"