blob: 523cdd4098a5e02c44b71e895c7480fbd564e00b [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
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000441 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000442 if ((TheTriple.getArch() == Triple::mips) ||
443 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000444 IsLittleEndian = false;
445 else
446 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000447 }
448
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000449 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
450 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
451
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000452 bool isGP64bit() const {
453 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
454 }
455 bool isFP64bit() const {
456 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
457 }
Eric Christophera5762812015-01-26 17:33:46 +0000458 const MipsABIInfo &getABI() const { return ABI; }
459 bool isABI_N32() const { return ABI.IsN32(); }
460 bool isABI_N64() const { return ABI.IsN64(); }
461 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000462 bool isABI_FPXX() const {
463 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
464 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000465
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000466 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000467 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000468 }
469
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000470 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000471 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000472 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000473 bool hasMips1() const {
474 return getSTI().getFeatureBits()[Mips::FeatureMips1];
475 }
476 bool hasMips2() const {
477 return getSTI().getFeatureBits()[Mips::FeatureMips2];
478 }
479 bool hasMips3() const {
480 return getSTI().getFeatureBits()[Mips::FeatureMips3];
481 }
482 bool hasMips4() const {
483 return getSTI().getFeatureBits()[Mips::FeatureMips4];
484 }
485 bool hasMips5() const {
486 return getSTI().getFeatureBits()[Mips::FeatureMips5];
487 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000488 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000489 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000490 }
491 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000492 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000493 }
494 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000495 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000496 }
497 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000498 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000499 }
Daniel Sanders17793142015-02-18 16:24:50 +0000500 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000501 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000502 }
503 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000504 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000505 }
506 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000507 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000508 }
509 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000510 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000511 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000512 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000513 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000514 }
515 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000516 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000517 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000518
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000519 bool hasDSP() const {
520 return getSTI().getFeatureBits()[Mips::FeatureDSP];
521 }
522 bool hasDSPR2() const {
523 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
524 }
525 bool hasDSPR3() const {
526 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
527 }
528 bool hasMSA() const {
529 return getSTI().getFeatureBits()[Mips::FeatureMSA];
530 }
Kai Nackee0245392015-01-27 19:11:28 +0000531 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000532 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000533 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000534
Daniel Sandersa6994442015-08-18 12:33:54 +0000535 bool inPicMode() {
536 return IsPicEnabled;
537 }
538
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000539 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000540 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000541 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000542
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000543 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000544 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000545 }
546
Eric Christophere8ae3e32015-05-07 23:10:21 +0000547 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000548 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000549 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000550
Toma Tabacud9d344b2015-04-27 14:05:04 +0000551 /// Warn if RegIndex is the same as the current AT.
552 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000553
554 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000555
556 bool isLittle() const { return IsLittleEndian; }
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 }
Simon Dardis4ccda502016-05-27 13:56:36 +00001076 // Allow relocation operators.
1077 // FIXME: This predicate and others need to look through binary expressions
1078 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001079 template <unsigned Bits, unsigned ShiftAmount = 0>
1080 bool isMemWithSimmOffset() const {
Simon Dardis4ccda502016-05-27 13:56:36 +00001081 return isMem() && getMemBase()->isGPRAsmReg() &&
1082 (isa<MCTargetExpr>(getMemOff()) ||
1083 (isConstantMemOff() &&
1084 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())));
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001085 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001086 bool isMemWithGRPMM16Base() const {
1087 return isMem() && getMemBase()->isMM16AsmReg();
1088 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001089 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1090 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1091 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1092 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001093 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1094 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1095 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1096 && (getMemBase()->getGPR32Reg() == Mips::SP);
1097 }
Daniel Sanderse473dc92016-05-09 13:38:25 +00001098 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1099 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1100 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1101 && (getMemBase()->getGPR32Reg() == Mips::GP);
1102 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001103 template <unsigned Bits, unsigned ShiftLeftAmount>
1104 bool isScaledUImm() const {
1105 return isConstantImm() &&
1106 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001107 }
Daniel Sanders97297772016-03-22 14:40:00 +00001108 template <unsigned Bits, unsigned ShiftLeftAmount>
1109 bool isScaledSImm() const {
1110 return isConstantImm() &&
1111 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
1112 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001113 bool isRegList16() const {
1114 if (!isRegList())
1115 return false;
1116
1117 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001118 if (Size < 2 || Size > 5)
1119 return false;
1120
1121 unsigned R0 = RegList.List->front();
1122 unsigned R1 = RegList.List->back();
1123 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1124 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001125 return false;
1126
1127 int PrevReg = *RegList.List->begin();
1128 for (int i = 1; i < Size - 1; i++) {
1129 int Reg = (*(RegList.List))[i];
1130 if ( Reg != PrevReg + 1)
1131 return false;
1132 PrevReg = Reg;
1133 }
1134
1135 return true;
1136 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001137 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001138 bool isLSAImm() const {
1139 if (!isConstantImm())
1140 return false;
1141 int64_t Val = getConstantImm();
1142 return 1 <= Val && Val <= 4;
1143 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001144 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001145 bool isMovePRegPair() const {
1146 if (Kind != k_RegList || RegList.List->size() != 2)
1147 return false;
1148
1149 unsigned R0 = RegList.List->front();
1150 unsigned R1 = RegList.List->back();
1151
1152 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1153 (R0 == Mips::A1 && R1 == Mips::A3) ||
1154 (R0 == Mips::A2 && R1 == Mips::A3) ||
1155 (R0 == Mips::A0 && R1 == Mips::S5) ||
1156 (R0 == Mips::A0 && R1 == Mips::S6) ||
1157 (R0 == Mips::A0 && R1 == Mips::A1) ||
1158 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001159 (R0 == Mips::A0 && R1 == Mips::A3) ||
1160 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1161 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1162 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1163 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1164 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1165 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1166 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1167 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001168 return true;
1169
1170 return false;
1171 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001172
1173 StringRef getToken() const {
1174 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001175 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001176 }
Zlatko Buljanba553a62016-05-09 08:07:28 +00001177 bool isRegPair() const {
1178 return Kind == k_RegPair && RegIdx.Index <= 30;
1179 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001180
Craig Topper56c590a2014-04-29 07:58:02 +00001181 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001182 // As a special case until we sort out the definition of div/divu, pretend
1183 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1184 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1185 RegIdx.Kind & RegKind_GPR)
1186 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001187
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001188 assert(Kind == k_PhysRegister && "Invalid access!");
1189 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001190 }
1191
Jack Carterb4dbc172012-09-05 23:34:03 +00001192 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001193 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001194 return Imm.Val;
1195 }
1196
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001197 int64_t getConstantImm() const {
1198 const MCExpr *Val = getImm();
1199 return static_cast<const MCConstantExpr *>(Val)->getValue();
1200 }
1201
1202 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001203 assert((Kind == k_Memory) && "Invalid access!");
1204 return Mem.Base;
1205 }
1206
1207 const MCExpr *getMemOff() const {
1208 assert((Kind == k_Memory) && "Invalid access!");
1209 return Mem.Off;
1210 }
1211
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001212 int64_t getConstantMemOff() const {
1213 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1214 }
1215
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001216 const SmallVectorImpl<unsigned> &getRegList() const {
1217 assert((Kind == k_RegList) && "Invalid access!");
1218 return *(RegList.List);
1219 }
1220
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001221 unsigned getRegPair() const {
1222 assert((Kind == k_RegPair) && "Invalid access!");
1223 return RegIdx.Index;
1224 }
1225
David Blaikie960ea3f2014-06-08 16:18:35 +00001226 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1227 MipsAsmParser &Parser) {
1228 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001229 Op->Tok.Data = Str.data();
1230 Op->Tok.Length = Str.size();
1231 Op->StartLoc = S;
1232 Op->EndLoc = S;
1233 return Op;
1234 }
1235
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001236 /// Create a numeric register (e.g. $1). The exact register remains
1237 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001238 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001239 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001240 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001241 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001242 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001243 }
1244
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001245 /// Create a register that is definitely a GPR.
1246 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001247 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001248 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001249 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001250 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001251 }
1252
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001253 /// Create a register that is definitely a FGR.
1254 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001255 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001256 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001257 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001258 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1259 }
1260
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001261 /// Create a register that is definitely a HWReg.
1262 /// This is typically only used for named registers such as $hwr_cpunum.
1263 static std::unique_ptr<MipsOperand>
1264 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1265 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1266 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1267 }
1268
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001269 /// Create a register that is definitely an FCC.
1270 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001271 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001272 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001273 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001274 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1275 }
1276
1277 /// Create a register that is definitely an ACC.
1278 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001279 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001280 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001281 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001282 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1283 }
1284
1285 /// Create a register that is definitely an MSA128.
1286 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001287 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001288 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001289 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001290 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1291 }
1292
1293 /// Create a register that is definitely an MSACtrl.
1294 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001295 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001296 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001297 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001298 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1299 }
1300
David Blaikie960ea3f2014-06-08 16:18:35 +00001301 static std::unique_ptr<MipsOperand>
1302 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1303 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001304 Op->Imm.Val = Val;
1305 Op->StartLoc = S;
1306 Op->EndLoc = E;
1307 return Op;
1308 }
1309
David Blaikie960ea3f2014-06-08 16:18:35 +00001310 static std::unique_ptr<MipsOperand>
1311 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1312 SMLoc E, MipsAsmParser &Parser) {
1313 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1314 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001315 Op->Mem.Off = Off;
1316 Op->StartLoc = S;
1317 Op->EndLoc = E;
1318 return Op;
1319 }
1320
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001321 static std::unique_ptr<MipsOperand>
1322 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1323 MipsAsmParser &Parser) {
1324 assert (Regs.size() > 0 && "Empty list not allowed");
1325
1326 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001327 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001328 Op->StartLoc = StartLoc;
1329 Op->EndLoc = EndLoc;
1330 return Op;
1331 }
1332
Daniel Sandersd044e492016-05-09 13:10:57 +00001333 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1334 SMLoc S, SMLoc E,
1335 MipsAsmParser &Parser) {
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001336 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001337 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001338 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1339 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001340 Op->StartLoc = S;
1341 Op->EndLoc = E;
1342 return Op;
1343 }
1344
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001345 bool isGPRAsmReg() const {
1346 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001347 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001348 bool isMM16AsmReg() const {
1349 if (!(isRegIdx() && RegIdx.Kind))
1350 return false;
1351 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1352 || RegIdx.Index == 16 || RegIdx.Index == 17);
1353 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001354 bool isMM16AsmRegZero() const {
1355 if (!(isRegIdx() && RegIdx.Kind))
1356 return false;
1357 return (RegIdx.Index == 0 ||
1358 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1359 RegIdx.Index == 17);
1360 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001361 bool isMM16AsmRegMoveP() const {
1362 if (!(isRegIdx() && RegIdx.Kind))
1363 return false;
1364 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1365 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1366 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001367 bool isFGRAsmReg() const {
1368 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1369 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001370 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001371 bool isHWRegsAsmReg() const {
1372 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001373 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001374 bool isCCRAsmReg() const {
1375 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001376 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001377 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001378 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1379 return false;
1380 if (!AsmParser.hasEightFccRegisters())
1381 return RegIdx.Index == 0;
1382 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001383 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001384 bool isACCAsmReg() const {
1385 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001386 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001387 bool isCOP0AsmReg() const {
1388 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1389 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001390 bool isCOP2AsmReg() const {
1391 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001392 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001393 bool isCOP3AsmReg() const {
1394 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1395 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001396 bool isMSA128AsmReg() const {
1397 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001398 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001399 bool isMSACtrlAsmReg() const {
1400 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001401 }
1402
Jack Carterb4dbc172012-09-05 23:34:03 +00001403 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001404 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001405 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001406 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001407
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001408 virtual ~MipsOperand() {
1409 switch (Kind) {
1410 case k_Immediate:
1411 break;
1412 case k_Memory:
1413 delete Mem.Base;
1414 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001415 case k_RegList:
1416 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001417 case k_PhysRegister:
1418 case k_RegisterIndex:
1419 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001420 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001421 break;
1422 }
1423 }
1424
Craig Topper56c590a2014-04-29 07:58:02 +00001425 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001426 switch (Kind) {
1427 case k_Immediate:
1428 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001429 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001430 OS << ">";
1431 break;
1432 case k_Memory:
1433 OS << "Mem<";
1434 Mem.Base->print(OS);
1435 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001436 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001437 OS << ">";
1438 break;
1439 case k_PhysRegister:
1440 OS << "PhysReg<" << PhysReg.Num << ">";
1441 break;
1442 case k_RegisterIndex:
1443 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1444 break;
1445 case k_Token:
1446 OS << Tok.Data;
1447 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001448 case k_RegList:
1449 OS << "RegList< ";
1450 for (auto Reg : (*RegList.List))
1451 OS << Reg << " ";
1452 OS << ">";
1453 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001454 case k_RegPair:
1455 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1456 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001457 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001458 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001459}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001460} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001461
Jack Carter9e65aa32013-03-22 00:05:30 +00001462namespace llvm {
1463extern const MCInstrDesc MipsInsts[];
1464}
1465static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1466 return MipsInsts[Opcode];
1467}
1468
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001469static bool hasShortDelaySlot(unsigned Opcode) {
1470 switch (Opcode) {
1471 case Mips::JALS_MM:
1472 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001473 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001474 case Mips::BGEZALS_MM:
1475 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001476 return true;
1477 default:
1478 return false;
1479 }
1480}
1481
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001482static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1483 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1484 return &SRExpr->getSymbol();
1485 }
1486
1487 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1488 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1489 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1490
1491 if (LHSSym)
1492 return LHSSym;
1493
1494 if (RHSSym)
1495 return RHSSym;
1496
1497 return nullptr;
1498 }
1499
1500 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1501 return getSingleMCSymbol(UExpr->getSubExpr());
1502
1503 return nullptr;
1504}
1505
1506static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1507 if (isa<MCSymbolRefExpr>(Expr))
1508 return 1;
1509
1510 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1511 return countMCSymbolRefExpr(BExpr->getLHS()) +
1512 countMCSymbolRefExpr(BExpr->getRHS());
1513
1514 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1515 return countMCSymbolRefExpr(UExpr->getSubExpr());
1516
1517 return 0;
1518}
1519
Jack Carter9e65aa32013-03-22 00:05:30 +00001520bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001521 MCStreamer &Out,
1522 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001523 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001524 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001525 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001526
Jack Carter9e65aa32013-03-22 00:05:30 +00001527 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001528
1529 if (MCID.isBranch() || MCID.isCall()) {
1530 const unsigned Opcode = Inst.getOpcode();
1531 MCOperand Offset;
1532
1533 switch (Opcode) {
1534 default:
1535 break;
Kai Nackee0245392015-01-27 19:11:28 +00001536 case Mips::BBIT0:
1537 case Mips::BBIT032:
1538 case Mips::BBIT1:
1539 case Mips::BBIT132:
1540 assert(hasCnMips() && "instruction only valid for octeon cpus");
1541 // Fall through
1542
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001543 case Mips::BEQ:
1544 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001545 case Mips::BEQ_MM:
1546 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001547 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001548 Offset = Inst.getOperand(2);
1549 if (!Offset.isImm())
1550 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001551 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001552 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001553 if (OffsetToAlignment(Offset.getImm(),
1554 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001555 return Error(IDLoc, "branch to misaligned address");
1556 break;
1557 case Mips::BGEZ:
1558 case Mips::BGTZ:
1559 case Mips::BLEZ:
1560 case Mips::BLTZ:
1561 case Mips::BGEZAL:
1562 case Mips::BLTZAL:
1563 case Mips::BC1F:
1564 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001565 case Mips::BGEZ_MM:
1566 case Mips::BGTZ_MM:
1567 case Mips::BLEZ_MM:
1568 case Mips::BLTZ_MM:
1569 case Mips::BGEZAL_MM:
1570 case Mips::BLTZAL_MM:
1571 case Mips::BC1F_MM:
1572 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001573 case Mips::BC1EQZC_MMR6:
1574 case Mips::BC1NEZC_MMR6:
1575 case Mips::BC2EQZC_MMR6:
1576 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001577 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001578 Offset = Inst.getOperand(1);
1579 if (!Offset.isImm())
1580 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001581 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001582 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001583 if (OffsetToAlignment(Offset.getImm(),
1584 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001585 return Error(IDLoc, "branch to misaligned address");
1586 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001587 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001588 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001589 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001590 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001591 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1592 Offset = Inst.getOperand(1);
1593 if (!Offset.isImm())
1594 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001595 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001596 return Error(IDLoc, "branch target out of range");
1597 if (OffsetToAlignment(Offset.getImm(), 2LL))
1598 return Error(IDLoc, "branch to misaligned address");
1599 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001600 }
1601 }
1602
Daniel Sandersa84989a2014-06-16 13:25:35 +00001603 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1604 // We still accept it but it is a normal nop.
1605 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1606 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1607 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1608 "nop instruction");
1609 }
1610
Kai Nackee0245392015-01-27 19:11:28 +00001611 if (hasCnMips()) {
1612 const unsigned Opcode = Inst.getOpcode();
1613 MCOperand Opnd;
1614 int Imm;
1615
1616 switch (Opcode) {
1617 default:
1618 break;
1619
1620 case Mips::BBIT0:
1621 case Mips::BBIT032:
1622 case Mips::BBIT1:
1623 case Mips::BBIT132:
1624 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1625 // The offset is handled above
1626 Opnd = Inst.getOperand(1);
1627 if (!Opnd.isImm())
1628 return Error(IDLoc, "expected immediate operand kind");
1629 Imm = Opnd.getImm();
1630 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1631 Opcode == Mips::BBIT1 ? 63 : 31))
1632 return Error(IDLoc, "immediate operand value out of range");
1633 if (Imm > 31) {
1634 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1635 : Mips::BBIT132);
1636 Inst.getOperand(1).setImm(Imm - 32);
1637 }
1638 break;
1639
Kai Nackee0245392015-01-27 19:11:28 +00001640 case Mips::SEQi:
1641 case Mips::SNEi:
1642 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1643 Opnd = Inst.getOperand(2);
1644 if (!Opnd.isImm())
1645 return Error(IDLoc, "expected immediate operand kind");
1646 Imm = Opnd.getImm();
1647 if (!isInt<10>(Imm))
1648 return Error(IDLoc, "immediate operand value out of range");
1649 break;
1650 }
1651 }
1652
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001653 // This expansion is not in a function called by tryExpandInstruction()
1654 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001655 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1656 inPicMode()) {
1657 warnIfNoMacro(IDLoc);
1658
1659 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1660
1661 // We can do this expansion if there's only 1 symbol in the argument
1662 // expression.
1663 if (countMCSymbolRefExpr(JalExpr) > 1)
1664 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1665
1666 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001667 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001668 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1669
1670 // FIXME: Add support for label+offset operands (currently causes an error).
1671 // FIXME: Add support for forward-declared local symbols.
1672 // FIXME: Add expansion for when the LargeGOT option is enabled.
1673 if (JalSym->isInSection() || JalSym->isTemporary()) {
1674 if (isABI_O32()) {
1675 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001676 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001677 // R_(MICRO)MIPS_GOT16 label
1678 // addiu $25, $25, 0
1679 // R_(MICRO)MIPS_LO16 label
1680 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001681 const MCExpr *Got16RelocExpr =
1682 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1683 const MCExpr *Lo16RelocExpr =
1684 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001685
Daniel Sandersa736b372016-04-29 13:33:12 +00001686 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1687 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1688 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1689 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001690 } else if (isABI_N32() || isABI_N64()) {
1691 // If it's a local symbol and the N32/N64 ABIs are being used,
1692 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001693 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001694 // R_(MICRO)MIPS_GOT_DISP label
1695 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001696 const MCExpr *GotDispRelocExpr =
1697 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001698
Daniel Sandersa736b372016-04-29 13:33:12 +00001699 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1700 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1701 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001702 }
1703 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001704 // If it's an external/weak symbol, we expand to:
1705 // lw/ld $25, 0($gp)
1706 // R_(MICRO)MIPS_CALL16 label
1707 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001708 const MCExpr *Call16RelocExpr =
1709 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001710
Daniel Sandersa736b372016-04-29 13:33:12 +00001711 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1712 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001713 }
1714
1715 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001716 if (IsCpRestoreSet && inMicroMipsMode())
1717 JalrInst.setOpcode(Mips::JALRS_MM);
1718 else
1719 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001720 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1721 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1722
1723 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1724 // This relocation is supposed to be an optimization hint for the linker
1725 // and is not necessary for correctness.
1726
1727 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001728 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001729 }
1730
Jack Carter9e65aa32013-03-22 00:05:30 +00001731 if (MCID.mayLoad() || MCID.mayStore()) {
1732 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001733 // reference or immediate we may have to expand instructions.
1734 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001735 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001736 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1737 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001738 MCOperand &Op = Inst.getOperand(i);
1739 if (Op.isImm()) {
1740 int MemOffset = Op.getImm();
1741 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001742 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001743 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001744 return false;
1745 }
1746 } else if (Op.isExpr()) {
1747 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001748 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001749 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001750 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001751 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001752 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001753 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001754 return false;
1755 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001756 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001757 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001758 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001759 }
1760 }
1761 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001762 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001763 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001764
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001765 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001766 if (MCID.mayLoad()) {
1767 // Try to create 16-bit GP relative load instruction.
1768 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1769 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1770 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1771 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1772 MCOperand &Op = Inst.getOperand(i);
1773 if (Op.isImm()) {
1774 int MemOffset = Op.getImm();
1775 MCOperand &DstReg = Inst.getOperand(0);
1776 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001777 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001778 getContext().getRegisterInfo()->getRegClass(
1779 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001780 (BaseReg.getReg() == Mips::GP ||
1781 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001782
Daniel Sandersa736b372016-04-29 13:33:12 +00001783 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1784 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001785 return false;
1786 }
1787 }
1788 }
1789 } // for
1790 } // if load
1791
1792 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1793
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001794 MCOperand Opnd;
1795 int Imm;
1796
1797 switch (Inst.getOpcode()) {
1798 default:
1799 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001800 case Mips::ADDIUSP_MM:
1801 Opnd = Inst.getOperand(0);
1802 if (!Opnd.isImm())
1803 return Error(IDLoc, "expected immediate operand kind");
1804 Imm = Opnd.getImm();
1805 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1806 Imm % 4 != 0)
1807 return Error(IDLoc, "immediate operand value out of range");
1808 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001809 case Mips::SLL16_MM:
1810 case Mips::SRL16_MM:
1811 Opnd = Inst.getOperand(2);
1812 if (!Opnd.isImm())
1813 return Error(IDLoc, "expected immediate operand kind");
1814 Imm = Opnd.getImm();
1815 if (Imm < 1 || Imm > 8)
1816 return Error(IDLoc, "immediate operand value out of range");
1817 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001818 case Mips::LI16_MM:
1819 Opnd = Inst.getOperand(1);
1820 if (!Opnd.isImm())
1821 return Error(IDLoc, "expected immediate operand kind");
1822 Imm = Opnd.getImm();
1823 if (Imm < -1 || Imm > 126)
1824 return Error(IDLoc, "immediate operand value out of range");
1825 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001826 case Mips::ADDIUR2_MM:
1827 Opnd = Inst.getOperand(2);
1828 if (!Opnd.isImm())
1829 return Error(IDLoc, "expected immediate operand kind");
1830 Imm = Opnd.getImm();
1831 if (!(Imm == 1 || Imm == -1 ||
1832 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1833 return Error(IDLoc, "immediate operand value out of range");
1834 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001835 case Mips::ANDI16_MM:
1836 Opnd = Inst.getOperand(2);
1837 if (!Opnd.isImm())
1838 return Error(IDLoc, "expected immediate operand kind");
1839 Imm = Opnd.getImm();
1840 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1841 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1842 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1843 return Error(IDLoc, "immediate operand value out of range");
1844 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001845 case Mips::LBU16_MM:
1846 Opnd = Inst.getOperand(2);
1847 if (!Opnd.isImm())
1848 return Error(IDLoc, "expected immediate operand kind");
1849 Imm = Opnd.getImm();
1850 if (Imm < -1 || Imm > 14)
1851 return Error(IDLoc, "immediate operand value out of range");
1852 break;
1853 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001854 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001855 Opnd = Inst.getOperand(2);
1856 if (!Opnd.isImm())
1857 return Error(IDLoc, "expected immediate operand kind");
1858 Imm = Opnd.getImm();
1859 if (Imm < 0 || Imm > 15)
1860 return Error(IDLoc, "immediate operand value out of range");
1861 break;
1862 case Mips::LHU16_MM:
1863 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001864 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001865 Opnd = Inst.getOperand(2);
1866 if (!Opnd.isImm())
1867 return Error(IDLoc, "expected immediate operand kind");
1868 Imm = Opnd.getImm();
1869 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1870 return Error(IDLoc, "immediate operand value out of range");
1871 break;
1872 case Mips::LW16_MM:
1873 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001874 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001875 Opnd = Inst.getOperand(2);
1876 if (!Opnd.isImm())
1877 return Error(IDLoc, "expected immediate operand kind");
1878 Imm = Opnd.getImm();
1879 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1880 return Error(IDLoc, "immediate operand value out of range");
1881 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001882 case Mips::ADDIUPC_MM:
1883 MCOperand Opnd = Inst.getOperand(1);
1884 if (!Opnd.isImm())
1885 return Error(IDLoc, "expected immediate operand kind");
1886 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001887 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001888 return Error(IDLoc, "immediate operand value out of range");
1889 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001890 }
1891 }
1892
Daniel Sandersd8c07762016-04-18 12:35:36 +00001893 bool FillDelaySlot =
1894 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
1895 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00001896 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001897
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001898 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001899 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001900 switch (ExpandResult) {
1901 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001902 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001903 break;
1904 case MER_Success:
1905 break;
1906 case MER_Fail:
1907 return true;
1908 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001909
Daniel Sanderscda908a2016-05-16 09:10:13 +00001910 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
1911 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
1912 if (inMicroMipsMode())
1913 TOut.setUsesMicroMips();
1914
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001915 // If this instruction has a delay slot and .set reorder is active,
1916 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00001917 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001918 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
1919 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001920 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001921
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001922 if ((Inst.getOpcode() == Mips::JalOneReg ||
1923 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1924 isPicAndNotNxxAbi()) {
1925 if (IsCpRestoreSet) {
1926 // We need a NOP between the JALR and the LW:
1927 // If .set reorder has been used, we've already emitted a NOP.
1928 // If .set noreorder has been used, we need to emit a NOP at this point.
1929 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00001930 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
1931 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001932
1933 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00001934 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001935 } else
1936 Warning(IDLoc, "no .cprestore used in PIC mode");
1937 }
1938
Jack Carter9e65aa32013-03-22 00:05:30 +00001939 return false;
1940}
1941
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001942MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001943MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
1944 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001945 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001946 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001947 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001948 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001949 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001950 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001951 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001952 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001953 case Mips::LoadAddrImm64:
1954 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1955 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1956 "expected immediate operand kind");
1957
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001958 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1959 Inst.getOperand(1),
1960 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001961 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001962 ? MER_Fail
1963 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001964 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001965 case Mips::LoadAddrReg64:
1966 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1967 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1968 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1969 "expected immediate operand kind");
1970
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001971 return expandLoadAddress(Inst.getOperand(0).getReg(),
1972 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1973 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001974 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001975 ? MER_Fail
1976 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001977 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001978 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001979 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
1980 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001981 case Mips::SWM_MM:
1982 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001983 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
1984 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001985 case Mips::JalOneReg:
1986 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001987 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00001988 case Mips::BneImm:
1989 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001990 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00001991 case Mips::BLT:
1992 case Mips::BLE:
1993 case Mips::BGE:
1994 case Mips::BGT:
1995 case Mips::BLTU:
1996 case Mips::BLEU:
1997 case Mips::BGEU:
1998 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001999 case Mips::BLTL:
2000 case Mips::BLEL:
2001 case Mips::BGEL:
2002 case Mips::BGTL:
2003 case Mips::BLTUL:
2004 case Mips::BLEUL:
2005 case Mips::BGEUL:
2006 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002007 case Mips::BLTImmMacro:
2008 case Mips::BLEImmMacro:
2009 case Mips::BGEImmMacro:
2010 case Mips::BGTImmMacro:
2011 case Mips::BLTUImmMacro:
2012 case Mips::BLEUImmMacro:
2013 case Mips::BGEUImmMacro:
2014 case Mips::BGTUImmMacro:
2015 case Mips::BLTLImmMacro:
2016 case Mips::BLELImmMacro:
2017 case Mips::BGELImmMacro:
2018 case Mips::BGTLImmMacro:
2019 case Mips::BLTULImmMacro:
2020 case Mips::BLEULImmMacro:
2021 case Mips::BGEULImmMacro:
2022 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002023 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002024 case Mips::SDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002025 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2026 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002027 case Mips::DSDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002028 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2029 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002030 case Mips::UDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002031 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2032 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002033 case Mips::DUDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002034 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2035 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002036 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002037 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2038 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002039 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002040 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002041 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002042 case Mips::PseudoTRUNC_W_D:
2043 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2044 : MER_Success;
2045 case Mips::Ulh:
2046 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2047 case Mips::Ulhu:
2048 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2049 case Mips::Ulw:
2050 return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2051 case Mips::NORImm:
2052 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002053 case Mips::ADDi:
2054 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002055 case Mips::SLTi:
2056 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002057 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2058 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2059 int64_t ImmValue = Inst.getOperand(2).getImm();
2060 if (isInt<16>(ImmValue))
2061 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002062 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2063 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002064 }
2065 return MER_NotAMacro;
2066 case Mips::ANDi:
2067 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002068 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002069 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2070 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2071 int64_t ImmValue = Inst.getOperand(2).getImm();
2072 if (isUInt<16>(ImmValue))
2073 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002074 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2075 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002076 }
2077 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002078 case Mips::ROL:
2079 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002080 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002081 case Mips::ROLImm:
2082 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002083 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002084 case Mips::DROL:
2085 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002086 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002087 case Mips::DROLImm:
2088 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002089 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002090 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002091 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002092 }
Jack Carter30a59822012-10-04 04:03:53 +00002093}
Jack Carter92995f12012-10-06 00:53:28 +00002094
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002095bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002096 MCStreamer &Out,
2097 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002098 MipsTargetStreamer &TOut = getTargetStreamer();
2099
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002100 // Create a JALR instruction which is going to replace the pseudo-JAL.
2101 MCInst JalrInst;
2102 JalrInst.setLoc(IDLoc);
2103 const MCOperand FirstRegOp = Inst.getOperand(0);
2104 const unsigned Opcode = Inst.getOpcode();
2105
2106 if (Opcode == Mips::JalOneReg) {
2107 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002108 if (IsCpRestoreSet && inMicroMipsMode()) {
2109 JalrInst.setOpcode(Mips::JALRS16_MM);
2110 JalrInst.addOperand(FirstRegOp);
2111 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002112 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002113 JalrInst.addOperand(FirstRegOp);
2114 } else {
2115 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002116 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002117 JalrInst.addOperand(FirstRegOp);
2118 }
2119 } else if (Opcode == Mips::JalTwoReg) {
2120 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002121 if (IsCpRestoreSet && inMicroMipsMode())
2122 JalrInst.setOpcode(Mips::JALRS_MM);
2123 else
2124 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002125 JalrInst.addOperand(FirstRegOp);
2126 const MCOperand SecondRegOp = Inst.getOperand(1);
2127 JalrInst.addOperand(SecondRegOp);
2128 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002129 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002130
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002131 // If .set reorder is active and branch instruction has a delay slot,
2132 // emit a NOP after it.
2133 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002134 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2135 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2136 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002137
2138 return false;
2139}
2140
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002141/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002142template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002143 unsigned BitNum = findFirstSet(x);
2144
2145 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2146}
2147
2148/// Load (or add) an immediate into a register.
2149///
2150/// @param ImmValue The immediate to load.
2151/// @param DstReg The register that will hold the immediate.
2152/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2153/// for a simple initialization.
2154/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2155/// @param IsAddress True if the immediate represents an address. False if it
2156/// is an integer.
2157/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002158bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002159 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002160 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2161 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002162 MipsTargetStreamer &TOut = getTargetStreamer();
2163
Toma Tabacu00e98672015-05-01 12:19:27 +00002164 if (!Is32BitImm && !isGP64bit()) {
2165 Error(IDLoc, "instruction requires a 64-bit architecture");
2166 return true;
2167 }
2168
Daniel Sanders03f9c012015-07-14 12:24:22 +00002169 if (Is32BitImm) {
2170 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2171 // Sign extend up to 64-bit so that the predicates match the hardware
2172 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2173 // true.
2174 ImmValue = SignExtend64<32>(ImmValue);
2175 } else {
2176 Error(IDLoc, "instruction requires a 32-bit immediate");
2177 return true;
2178 }
2179 }
2180
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002181 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2182 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2183
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002184 bool UseSrcReg = false;
2185 if (SrcReg != Mips::NoRegister)
2186 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002187
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002188 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002189 if (UseSrcReg &&
2190 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002191 // At this point we need AT to perform the expansions and we exit if it is
2192 // not available.
2193 unsigned ATReg = getATReg(IDLoc);
2194 if (!ATReg)
2195 return true;
2196 TmpReg = ATReg;
2197 }
2198
Daniel Sanders03f9c012015-07-14 12:24:22 +00002199 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002200 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002201 SrcReg = ZeroReg;
2202
2203 // This doesn't quite follow the usual ABI expectations for N32 but matches
2204 // traditional assembler behaviour. N32 would normally use addiu for both
2205 // integers and addresses.
2206 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002207 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002208 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002209 }
2210
Daniel Sandersa736b372016-04-29 13:33:12 +00002211 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002212 return false;
2213 }
2214
2215 if (isUInt<16>(ImmValue)) {
2216 unsigned TmpReg = DstReg;
2217 if (SrcReg == DstReg) {
2218 TmpReg = getATReg(IDLoc);
2219 if (!TmpReg)
2220 return true;
2221 }
2222
Daniel Sandersa736b372016-04-29 13:33:12 +00002223 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002224 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002225 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002226 return false;
2227 }
2228
2229 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002230 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002231
Toma Tabacu79588102015-04-29 10:19:56 +00002232 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2233 uint16_t Bits15To0 = ImmValue & 0xffff;
2234
Toma Tabacua3d056f2015-05-15 09:42:11 +00002235 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002236 // Traditional behaviour seems to special case this particular value. It's
2237 // not clear why other masks are handled differently.
2238 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002239 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2240 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002241 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002242 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002243 return false;
2244 }
2245
2246 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002247 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002248 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2249 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002250 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002251 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002252 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002253 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002254 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002255 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002256
Daniel Sandersa736b372016-04-29 13:33:12 +00002257 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002258 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002259 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002260 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002261 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002262 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002263 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002264
2265 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2266 if (Is32BitImm) {
2267 Error(IDLoc, "instruction requires a 32-bit immediate");
2268 return true;
2269 }
2270
2271 // Traditionally, these immediates are shifted as little as possible and as
2272 // such we align the most significant bit to bit 15 of our temporary.
2273 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2274 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2275 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2276 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002277 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2278 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002279
2280 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002281 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002282
2283 return false;
2284 }
2285
2286 warnIfNoMacro(IDLoc);
2287
2288 // The remaining case is packed with a sequence of dsll and ori with zeros
2289 // being omitted and any neighbouring dsll's being coalesced.
2290 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2291
2292 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2293 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002294 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002295 return false;
2296
2297 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2298 // skip it and defer the shift to the next chunk.
2299 unsigned ShiftCarriedForwards = 16;
2300 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2301 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2302
2303 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002304 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2305 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002306 ShiftCarriedForwards = 0;
2307 }
2308
2309 ShiftCarriedForwards += 16;
2310 }
2311 ShiftCarriedForwards -= 16;
2312
2313 // Finish any remaining shifts left by trailing zeros.
2314 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002315 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002316
2317 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002318 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002319
Matheus Almeida3813d572014-06-19 14:39:14 +00002320 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002321}
Jack Carter92995f12012-10-06 00:53:28 +00002322
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002323bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002324 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002325 const MCOperand &ImmOp = Inst.getOperand(1);
2326 assert(ImmOp.isImm() && "expected immediate operand kind");
2327 const MCOperand &DstRegOp = Inst.getOperand(0);
2328 assert(DstRegOp.isReg() && "expected register operand kind");
2329
2330 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002331 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002332 return true;
2333
2334 return false;
2335}
2336
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002337bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2338 const MCOperand &Offset,
2339 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002340 MCStreamer &Out,
2341 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002342 // la can't produce a usable address when addresses are 64-bit.
2343 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2344 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2345 // We currently can't do this because we depend on the equality
2346 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2347 Error(IDLoc, "la used to load 64-bit address");
2348 // Continue as if we had 'dla' instead.
2349 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002350 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002351
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002352 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002353 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002354 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002355 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002356 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002357
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002358 if (!Offset.isImm())
2359 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002360 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002361
Scott Egerton24557012016-01-21 15:11:01 +00002362 if (!ABI.ArePtrs64bit()) {
2363 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2364 Is32BitAddress = true;
2365 }
2366
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002367 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002368 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002369}
2370
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002371bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2372 unsigned DstReg, unsigned SrcReg,
2373 bool Is32BitSym, SMLoc IDLoc,
2374 MCStreamer &Out,
2375 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002376 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacu81496c12015-05-20 08:54:45 +00002377 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002378
Daniel Sandersd5a89412015-10-05 13:19:29 +00002379 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002380 const MipsMCExpr *HiExpr =
2381 MipsMCExpr::create(MipsMCExpr::MEK_HI, Symbol, getContext());
2382 const MipsMCExpr *LoExpr =
2383 MipsMCExpr::create(MipsMCExpr::MEK_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002384
Toma Tabacufb9d1252015-06-22 12:08:39 +00002385 bool UseSrcReg = SrcReg != Mips::NoRegister;
2386
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002387 // This is the 64-bit symbol address expansion.
2388 if (ABI.ArePtrs64bit() && isGP64bit()) {
2389 // We always need AT for the 64-bit expansion.
2390 // If it is not available we exit.
2391 unsigned ATReg = getATReg(IDLoc);
2392 if (!ATReg)
2393 return true;
2394
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002395 const MipsMCExpr *HighestExpr =
2396 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, Symbol, getContext());
2397 const MipsMCExpr *HigherExpr =
2398 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002399
Scott Egerton24557012016-01-21 15:11:01 +00002400 if (UseSrcReg &&
2401 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2402 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002403 // If $rs is the same as $rd:
2404 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2405 // daddiu $at, $at, %higher(sym)
2406 // dsll $at, $at, 16
2407 // daddiu $at, $at, %hi(sym)
2408 // dsll $at, $at, 16
2409 // daddiu $at, $at, %lo(sym)
2410 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002411 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2412 STI);
2413 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2414 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2415 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2416 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2417 IDLoc, STI);
2418 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2419 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2420 IDLoc, STI);
2421 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002422
2423 return false;
2424 }
2425
2426 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2427 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2428 // lui $at, %hi(sym)
2429 // daddiu $rd, $rd, %higher(sym)
2430 // daddiu $at, $at, %lo(sym)
2431 // dsll32 $rd, $rd, 0
2432 // daddu $rd, $rd, $at
2433 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002434 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2435 STI);
2436 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2437 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2438 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2439 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2440 IDLoc, STI);
2441 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2442 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002443 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002444 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002445
2446 return false;
2447 }
2448
2449 // And now, the 32-bit symbol address expansion:
2450 // If $rs is the same as $rd:
2451 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2452 // ori $at, $at, %lo(sym)
2453 // addu $rd, $at, $rd
2454 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2455 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2456 // ori $rd, $rd, %lo(sym)
2457 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002458 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002459 if (UseSrcReg &&
2460 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002461 // If $rs is the same as $rd, we need to use AT.
2462 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002463 unsigned ATReg = getATReg(IDLoc);
2464 if (!ATReg)
2465 return true;
2466 TmpReg = ATReg;
2467 }
2468
Daniel Sandersa736b372016-04-29 13:33:12 +00002469 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2470 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2471 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002472
Toma Tabacufb9d1252015-06-22 12:08:39 +00002473 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002474 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002475 else
Scott Egerton24557012016-01-21 15:11:01 +00002476 assert(
2477 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002478
Toma Tabacu674825c2015-06-16 12:16:24 +00002479 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002480}
2481
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002482bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2483 MCStreamer &Out,
2484 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002485 MipsTargetStreamer &TOut = getTargetStreamer();
2486
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002487 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2488 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002489
2490 MCOperand Offset = Inst.getOperand(0);
2491 if (Offset.isExpr()) {
2492 Inst.clear();
2493 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002494 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2495 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2496 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002497 } else {
2498 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002499 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002500 // If offset fits into 11 bits then this instruction becomes microMIPS
2501 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002502 if (inMicroMipsMode())
2503 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002504 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002505 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002506 Error(IDLoc, "branch target out of range");
2507 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2508 Error(IDLoc, "branch to misaligned address");
2509 Inst.clear();
2510 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002511 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2512 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2513 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002514 }
2515 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002516 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002517
Zoran Jovanovicada70912015-09-07 11:56:37 +00002518 // If .set reorder is active and branch instruction has a delay slot,
2519 // emit a NOP after it.
2520 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2521 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002522 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002523
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002524 return false;
2525}
2526
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002527bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2528 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002529 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002530 const MCOperand &DstRegOp = Inst.getOperand(0);
2531 assert(DstRegOp.isReg() && "expected register operand kind");
2532
2533 const MCOperand &ImmOp = Inst.getOperand(1);
2534 assert(ImmOp.isImm() && "expected immediate operand kind");
2535
2536 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002537 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2538 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002539
2540 unsigned OpCode = 0;
2541 switch(Inst.getOpcode()) {
2542 case Mips::BneImm:
2543 OpCode = Mips::BNE;
2544 break;
2545 case Mips::BeqImm:
2546 OpCode = Mips::BEQ;
2547 break;
2548 default:
2549 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2550 break;
2551 }
2552
2553 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002554 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002555 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2556 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002557 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002558 warnIfNoMacro(IDLoc);
2559
2560 unsigned ATReg = getATReg(IDLoc);
2561 if (!ATReg)
2562 return true;
2563
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002564 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002565 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002566 return true;
2567
Daniel Sandersa736b372016-04-29 13:33:12 +00002568 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002569 }
2570 return false;
2571}
2572
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002573void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002574 const MCSubtargetInfo *STI, bool IsLoad,
2575 bool IsImmOpnd) {
2576 if (IsLoad) {
2577 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2578 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002579 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002580 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2581}
2582
2583void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2584 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2585 MipsTargetStreamer &TOut = getTargetStreamer();
2586
2587 unsigned DstReg = Inst.getOperand(0).getReg();
2588 unsigned BaseReg = Inst.getOperand(1).getReg();
2589
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002590 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002591 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2592 unsigned DstRegClassID =
2593 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2594 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2595 (DstRegClassID == Mips::GPR64RegClassID);
2596
2597 if (IsImmOpnd) {
2598 // Try to use DstReg as the temporary.
2599 if (IsGPR && (BaseReg != DstReg)) {
2600 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2601 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2602 STI);
2603 return;
2604 }
2605
Matheus Almeida7de68e72014-06-18 14:46:05 +00002606 // At this point we need AT to perform the expansions and we exit if it is
2607 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002608 unsigned ATReg = getATReg(IDLoc);
2609 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002610 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002611
2612 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2613 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2614 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002615 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002616
Daniel Sandersfba875f2016-04-29 13:43:45 +00002617 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002618 MCOperand LoOperand = MCOperand::createExpr(
2619 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2620 MCOperand HiOperand = MCOperand::createExpr(
2621 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002622
2623 // Try to use DstReg as the temporary.
2624 if (IsGPR && (BaseReg != DstReg)) {
2625 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2626 LoOperand, DstReg, IDLoc, STI);
2627 return;
2628 }
2629
2630 // At this point we need AT to perform the expansions and we exit if it is
2631 // not available.
2632 unsigned ATReg = getATReg(IDLoc);
2633 if (!ATReg)
2634 return;
2635
2636 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2637 LoOperand, ATReg, IDLoc, STI);
2638}
2639
2640void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2641 const MCSubtargetInfo *STI,
2642 bool IsImmOpnd) {
2643 MipsTargetStreamer &TOut = getTargetStreamer();
2644
2645 unsigned SrcReg = Inst.getOperand(0).getReg();
2646 unsigned BaseReg = Inst.getOperand(1).getReg();
2647
Daniel Sanders241c6792016-05-12 14:01:50 +00002648 if (IsImmOpnd) {
2649 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2650 Inst.getOperand(2).getImm(),
2651 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
2652 return;
2653 }
2654
Daniel Sandersfba875f2016-04-29 13:43:45 +00002655 unsigned ATReg = getATReg(IDLoc);
2656 if (!ATReg)
2657 return;
2658
Daniel Sandersfba875f2016-04-29 13:43:45 +00002659 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002660 MCOperand LoOperand = MCOperand::createExpr(
2661 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2662 MCOperand HiOperand = MCOperand::createExpr(
2663 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002664 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2665 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002666}
2667
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002668bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2669 MCStreamer &Out,
2670 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002671 unsigned OpNum = Inst.getNumOperands();
2672 unsigned Opcode = Inst.getOpcode();
2673 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2674
2675 assert (Inst.getOperand(OpNum - 1).isImm() &&
2676 Inst.getOperand(OpNum - 2).isReg() &&
2677 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2678
2679 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2680 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002681 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2682 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2683 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2684 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002685 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002686 if (inMicroMipsMode() && hasMips32r6())
2687 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2688 else
2689 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2690 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002691
2692 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002693 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002694 return false;
2695}
2696
Toma Tabacu1a108322015-06-17 13:20:24 +00002697bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002698 MCStreamer &Out,
2699 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002700 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002701 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002702 unsigned PseudoOpcode = Inst.getOpcode();
2703 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002704 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002705 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2706
2707 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002708 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002709
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002710 unsigned TrgReg;
2711 if (TrgOp.isReg())
2712 TrgReg = TrgOp.getReg();
2713 else if (TrgOp.isImm()) {
2714 warnIfNoMacro(IDLoc);
2715 EmittedNoMacroWarning = true;
2716
2717 TrgReg = getATReg(IDLoc);
2718 if (!TrgReg)
2719 return true;
2720
2721 switch(PseudoOpcode) {
2722 default:
2723 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2724 case Mips::BLTImmMacro:
2725 PseudoOpcode = Mips::BLT;
2726 break;
2727 case Mips::BLEImmMacro:
2728 PseudoOpcode = Mips::BLE;
2729 break;
2730 case Mips::BGEImmMacro:
2731 PseudoOpcode = Mips::BGE;
2732 break;
2733 case Mips::BGTImmMacro:
2734 PseudoOpcode = Mips::BGT;
2735 break;
2736 case Mips::BLTUImmMacro:
2737 PseudoOpcode = Mips::BLTU;
2738 break;
2739 case Mips::BLEUImmMacro:
2740 PseudoOpcode = Mips::BLEU;
2741 break;
2742 case Mips::BGEUImmMacro:
2743 PseudoOpcode = Mips::BGEU;
2744 break;
2745 case Mips::BGTUImmMacro:
2746 PseudoOpcode = Mips::BGTU;
2747 break;
2748 case Mips::BLTLImmMacro:
2749 PseudoOpcode = Mips::BLTL;
2750 break;
2751 case Mips::BLELImmMacro:
2752 PseudoOpcode = Mips::BLEL;
2753 break;
2754 case Mips::BGELImmMacro:
2755 PseudoOpcode = Mips::BGEL;
2756 break;
2757 case Mips::BGTLImmMacro:
2758 PseudoOpcode = Mips::BGTL;
2759 break;
2760 case Mips::BLTULImmMacro:
2761 PseudoOpcode = Mips::BLTUL;
2762 break;
2763 case Mips::BLEULImmMacro:
2764 PseudoOpcode = Mips::BLEUL;
2765 break;
2766 case Mips::BGEULImmMacro:
2767 PseudoOpcode = Mips::BGEUL;
2768 break;
2769 case Mips::BGTULImmMacro:
2770 PseudoOpcode = Mips::BGTUL;
2771 break;
2772 }
2773
2774 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002775 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002776 return true;
2777 }
2778
Toma Tabacu1a108322015-06-17 13:20:24 +00002779 switch (PseudoOpcode) {
2780 case Mips::BLT:
2781 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002782 case Mips::BLTL:
2783 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002784 AcceptsEquality = false;
2785 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002786 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2787 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002788 ZeroSrcOpcode = Mips::BGTZ;
2789 ZeroTrgOpcode = Mips::BLTZ;
2790 break;
2791 case Mips::BLE:
2792 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002793 case Mips::BLEL:
2794 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002795 AcceptsEquality = true;
2796 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002797 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2798 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002799 ZeroSrcOpcode = Mips::BGEZ;
2800 ZeroTrgOpcode = Mips::BLEZ;
2801 break;
2802 case Mips::BGE:
2803 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002804 case Mips::BGEL:
2805 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002806 AcceptsEquality = true;
2807 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002808 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2809 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002810 ZeroSrcOpcode = Mips::BLEZ;
2811 ZeroTrgOpcode = Mips::BGEZ;
2812 break;
2813 case Mips::BGT:
2814 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002815 case Mips::BGTL:
2816 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002817 AcceptsEquality = false;
2818 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002819 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2820 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002821 ZeroSrcOpcode = Mips::BLTZ;
2822 ZeroTrgOpcode = Mips::BGTZ;
2823 break;
2824 default:
2825 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2826 }
2827
Toma Tabacu1a108322015-06-17 13:20:24 +00002828 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2829 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2830 if (IsSrcRegZero && IsTrgRegZero) {
2831 // FIXME: All of these Opcode-specific if's are needed for compatibility
2832 // with GAS' behaviour. However, they may not generate the most efficient
2833 // code in some circumstances.
2834 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002835 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2836 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002837 return false;
2838 }
2839 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002840 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2841 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002842 Warning(IDLoc, "branch is always taken");
2843 return false;
2844 }
2845 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002846 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2847 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002848 Warning(IDLoc, "branch is always taken");
2849 return false;
2850 }
2851 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002852 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2853 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002854 return false;
2855 }
2856 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002857 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2858 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002859 return false;
2860 }
2861 if (AcceptsEquality) {
2862 // If both registers are $0 and the pseudo-branch accepts equality, it
2863 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00002864 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2865 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002866 Warning(IDLoc, "branch is always taken");
2867 return false;
2868 }
2869 // If both registers are $0 and the pseudo-branch does not accept
2870 // equality, it will never be taken, so we don't have to emit anything.
2871 return false;
2872 }
2873 if (IsSrcRegZero || IsTrgRegZero) {
2874 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2875 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2876 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2877 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2878 // the pseudo-branch will never be taken, so we don't emit anything.
2879 // This only applies to unsigned pseudo-branches.
2880 return false;
2881 }
2882 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2883 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2884 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2885 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2886 // the pseudo-branch will always be taken, so we emit an unconditional
2887 // branch.
2888 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00002889 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2890 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002891 Warning(IDLoc, "branch is always taken");
2892 return false;
2893 }
2894 if (IsUnsigned) {
2895 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2896 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2897 // the pseudo-branch will be taken only when the non-zero register is
2898 // different from 0, so we emit a BNEZ.
2899 //
2900 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2901 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2902 // the pseudo-branch will be taken only when the non-zero register is
2903 // equal to 0, so we emit a BEQZ.
2904 //
2905 // Because only BLEU and BGEU branch on equality, we can use the
2906 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00002907 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2908 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2909 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002910 return false;
2911 }
2912 // If we have a signed pseudo-branch and one of the registers is $0,
2913 // we can use an appropriate compare-to-zero branch. We select which one
2914 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00002915 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2916 IsSrcRegZero ? TrgReg : SrcReg,
2917 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002918 return false;
2919 }
2920
2921 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2922 // expansions. If it is not available, we return.
2923 unsigned ATRegNum = getATReg(IDLoc);
2924 if (!ATRegNum)
2925 return true;
2926
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002927 if (!EmittedNoMacroWarning)
2928 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002929
2930 // SLT fits well with 2 of our 4 pseudo-branches:
2931 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2932 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2933 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2934 // This is accomplished by using a BNEZ with the result of the SLT.
2935 //
2936 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2937 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2938 // Because only BGE and BLE branch on equality, we can use the
2939 // AcceptsEquality variable to decide when to emit the BEQZ.
2940 // Note that the order of the SLT arguments doesn't change between
2941 // opposites.
2942 //
2943 // The same applies to the unsigned variants, except that SLTu is used
2944 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00002945 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2946 ReverseOrderSLT ? TrgReg : SrcReg,
2947 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002948
Daniel Sandersa736b372016-04-29 13:33:12 +00002949 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2950 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2951 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2952 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002953 return false;
2954}
2955
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002956bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2957 const MCSubtargetInfo *STI, const bool IsMips64,
2958 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002959 MipsTargetStreamer &TOut = getTargetStreamer();
2960
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002961 warnIfNoMacro(IDLoc);
2962
Zoran Jovanovic973405b2016-05-16 08:57:59 +00002963 const MCOperand &RdRegOp = Inst.getOperand(0);
2964 assert(RdRegOp.isReg() && "expected register operand kind");
2965 unsigned RdReg = RdRegOp.getReg();
2966
2967 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002968 assert(RsRegOp.isReg() && "expected register operand kind");
2969 unsigned RsReg = RsRegOp.getReg();
2970
Zoran Jovanovic973405b2016-05-16 08:57:59 +00002971 const MCOperand &RtRegOp = Inst.getOperand(2);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002972 assert(RtRegOp.isReg() && "expected register operand kind");
2973 unsigned RtReg = RtRegOp.getReg();
2974 unsigned DivOp;
2975 unsigned ZeroReg;
2976
2977 if (IsMips64) {
2978 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2979 ZeroReg = Mips::ZERO_64;
2980 } else {
2981 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2982 ZeroReg = Mips::ZERO;
2983 }
2984
2985 bool UseTraps = useTraps();
2986
2987 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2988 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2989 Warning(IDLoc, "dividing zero by zero");
2990 if (IsMips64) {
2991 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2992 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002993 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002994 return false;
2995 }
2996
Daniel Sandersa736b372016-04-29 13:33:12 +00002997 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002998 return false;
2999 }
3000 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00003001 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003002 return false;
3003 }
3004 }
3005
3006 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3007 Warning(IDLoc, "division by zero");
3008 if (Signed) {
3009 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003010 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003011 return false;
3012 }
3013
Daniel Sandersa736b372016-04-29 13:33:12 +00003014 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003015 return false;
3016 }
3017 }
3018
3019 // FIXME: The values for these two BranchTarget variables may be different in
3020 // micromips. These magic numbers need to be removed.
3021 unsigned BranchTargetNoTraps;
3022 unsigned BranchTarget;
3023
3024 if (UseTraps) {
3025 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003026 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003027 } else {
3028 BranchTarget = IsMips64 ? 20 : 16;
3029 BranchTargetNoTraps = 8;
3030 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003031 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003032 }
3033
Daniel Sandersa736b372016-04-29 13:33:12 +00003034 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003035
3036 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003037 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003038
3039 if (!Signed) {
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003040 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003041 return false;
3042 }
3043
3044 unsigned ATReg = getATReg(IDLoc);
3045 if (!ATReg)
3046 return true;
3047
Daniel Sandersa736b372016-04-29 13:33:12 +00003048 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003049 if (IsMips64) {
3050 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003051 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3052 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3053 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003054 } else {
3055 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003056 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3057 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003058 }
3059
3060 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003061 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003062 else {
3063 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003064 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3065 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3066 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003067 }
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003068 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003069 return false;
3070}
3071
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003072bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003073 SMLoc IDLoc, MCStreamer &Out,
3074 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003075 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003076
3077 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3078 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3079 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3080
3081 unsigned FirstReg = Inst.getOperand(0).getReg();
3082 unsigned SecondReg = Inst.getOperand(1).getReg();
3083 unsigned ThirdReg = Inst.getOperand(2).getReg();
3084
3085 if (hasMips1() && !hasMips2()) {
3086 unsigned ATReg = getATReg(IDLoc);
3087 if (!ATReg)
3088 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003089 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3090 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3091 TOut.emitNop(IDLoc, STI);
3092 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3093 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3094 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3095 TOut.emitNop(IDLoc, STI);
3096 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3097 : Mips::CVT_W_S,
3098 FirstReg, SecondReg, IDLoc, STI);
3099 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3100 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003101 return false;
3102 }
3103
Daniel Sandersa736b372016-04-29 13:33:12 +00003104 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3105 : Mips::TRUNC_W_S,
3106 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003107
3108 return false;
3109}
3110
Daniel Sanders6394ee52015-10-15 14:52:58 +00003111bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003112 MCStreamer &Out, const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003113 MipsTargetStreamer &TOut = getTargetStreamer();
3114
Toma Tabacud88d79c2015-06-23 14:39:42 +00003115 if (hasMips32r6() || hasMips64r6()) {
3116 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3117 return false;
3118 }
3119
3120 warnIfNoMacro(IDLoc);
3121
3122 const MCOperand &DstRegOp = Inst.getOperand(0);
3123 assert(DstRegOp.isReg() && "expected register operand kind");
3124
3125 const MCOperand &SrcRegOp = Inst.getOperand(1);
3126 assert(SrcRegOp.isReg() && "expected register operand kind");
3127
3128 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3129 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3130
3131 unsigned DstReg = DstRegOp.getReg();
3132 unsigned SrcReg = SrcRegOp.getReg();
3133 int64_t OffsetValue = OffsetImmOp.getImm();
3134
3135 // NOTE: We always need AT for ULHU, as it is always used as the source
3136 // register for one of the LBu's.
3137 unsigned ATReg = getATReg(IDLoc);
3138 if (!ATReg)
3139 return true;
3140
3141 // When the value of offset+1 does not fit in 16 bits, we have to load the
3142 // offset in AT, (D)ADDu the original source register (if there was one), and
3143 // then use AT as the source register for the 2 generated LBu's.
3144 bool LoadedOffsetInAT = false;
3145 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3146 LoadedOffsetInAT = true;
3147
3148 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003149 true, IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003150 return true;
3151
3152 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3153 // because it will make our output more similar to GAS'. For example,
3154 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3155 // instead of just an "ori $1, $9, 32768".
3156 // NOTE: If there is no source register specified in the ULHU, the parser
3157 // will interpret it as $0.
3158 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003159 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003160 }
3161
3162 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3163 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3164 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3165
3166 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3167 if (isLittle()) {
3168 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3169 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3170 } else {
3171 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3172 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3173 }
3174
3175 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3176
Daniel Sandersa736b372016-04-29 13:33:12 +00003177 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3178 FirstLbuOffset, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003179
Daniel Sandersa736b372016-04-29 13:33:12 +00003180 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3181 STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003182
Daniel Sandersa736b372016-04-29 13:33:12 +00003183 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003184
Daniel Sandersa736b372016-04-29 13:33:12 +00003185 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003186
3187 return false;
3188}
3189
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003190bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3191 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003192 MipsTargetStreamer &TOut = getTargetStreamer();
3193
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003194 if (hasMips32r6() || hasMips64r6()) {
3195 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3196 return false;
3197 }
3198
3199 const MCOperand &DstRegOp = Inst.getOperand(0);
3200 assert(DstRegOp.isReg() && "expected register operand kind");
3201
3202 const MCOperand &SrcRegOp = Inst.getOperand(1);
3203 assert(SrcRegOp.isReg() && "expected register operand kind");
3204
3205 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3206 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3207
3208 unsigned SrcReg = SrcRegOp.getReg();
3209 int64_t OffsetValue = OffsetImmOp.getImm();
3210 unsigned ATReg = 0;
3211
3212 // When the value of offset+3 does not fit in 16 bits, we have to load the
3213 // offset in AT, (D)ADDu the original source register (if there was one), and
3214 // then use AT as the source register for the generated LWL and LWR.
3215 bool LoadedOffsetInAT = false;
3216 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3217 ATReg = getATReg(IDLoc);
3218 if (!ATReg)
3219 return true;
3220 LoadedOffsetInAT = true;
3221
3222 warnIfNoMacro(IDLoc);
3223
3224 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003225 true, IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003226 return true;
3227
3228 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3229 // because it will make our output more similar to GAS'. For example,
3230 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3231 // instead of just an "ori $1, $9, 32768".
3232 // NOTE: If there is no source register specified in the ULW, the parser
3233 // will interpret it as $0.
3234 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003235 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003236 }
3237
3238 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3239 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3240 if (isLittle()) {
3241 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3242 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3243 } else {
3244 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3245 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3246 }
3247
Daniel Sandersa736b372016-04-29 13:33:12 +00003248 TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3249 STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003250
Daniel Sandersa736b372016-04-29 13:33:12 +00003251 TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
3252 IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003253
3254 return false;
3255}
3256
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003257bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003258 MCStreamer &Out,
3259 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003260 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003261
3262 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3263 assert (Inst.getOperand(0).isReg() &&
3264 Inst.getOperand(1).isReg() &&
3265 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3266
3267 unsigned ATReg = Mips::NoRegister;
3268 unsigned FinalDstReg = Mips::NoRegister;
3269 unsigned DstReg = Inst.getOperand(0).getReg();
3270 unsigned SrcReg = Inst.getOperand(1).getReg();
3271 int64_t ImmValue = Inst.getOperand(2).getImm();
3272
3273 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3274
3275 unsigned FinalOpcode = Inst.getOpcode();
3276
3277 if (DstReg == SrcReg) {
3278 ATReg = getATReg(Inst.getLoc());
3279 if (!ATReg)
3280 return true;
3281 FinalDstReg = DstReg;
3282 DstReg = ATReg;
3283 }
3284
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003285 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003286 switch (FinalOpcode) {
3287 default:
3288 llvm_unreachable("unimplemented expansion");
3289 case (Mips::ADDi):
3290 FinalOpcode = Mips::ADD;
3291 break;
3292 case (Mips::ADDiu):
3293 FinalOpcode = Mips::ADDu;
3294 break;
3295 case (Mips::ANDi):
3296 FinalOpcode = Mips::AND;
3297 break;
3298 case (Mips::NORImm):
3299 FinalOpcode = Mips::NOR;
3300 break;
3301 case (Mips::ORi):
3302 FinalOpcode = Mips::OR;
3303 break;
3304 case (Mips::SLTi):
3305 FinalOpcode = Mips::SLT;
3306 break;
3307 case (Mips::SLTiu):
3308 FinalOpcode = Mips::SLTu;
3309 break;
3310 case (Mips::XORi):
3311 FinalOpcode = Mips::XOR;
3312 break;
3313 }
3314
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003315 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003316 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003317 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003318 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003319 return false;
3320 }
3321 return true;
3322}
3323
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003324bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3325 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003326 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003327 unsigned ATReg = Mips::NoRegister;
3328 unsigned DReg = Inst.getOperand(0).getReg();
3329 unsigned SReg = Inst.getOperand(1).getReg();
3330 unsigned TReg = Inst.getOperand(2).getReg();
3331 unsigned TmpReg = DReg;
3332
3333 unsigned FirstShift = Mips::NOP;
3334 unsigned SecondShift = Mips::NOP;
3335
3336 if (hasMips32r2()) {
3337
3338 if (DReg == SReg) {
3339 TmpReg = getATReg(Inst.getLoc());
3340 if (!TmpReg)
3341 return true;
3342 }
3343
3344 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003345 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3346 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003347 return false;
3348 }
3349
3350 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003351 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003352 return false;
3353 }
3354
3355 return true;
3356 }
3357
3358 if (hasMips32()) {
3359
3360 switch (Inst.getOpcode()) {
3361 default:
3362 llvm_unreachable("unexpected instruction opcode");
3363 case Mips::ROL:
3364 FirstShift = Mips::SRLV;
3365 SecondShift = Mips::SLLV;
3366 break;
3367 case Mips::ROR:
3368 FirstShift = Mips::SLLV;
3369 SecondShift = Mips::SRLV;
3370 break;
3371 }
3372
3373 ATReg = getATReg(Inst.getLoc());
3374 if (!ATReg)
3375 return true;
3376
Daniel Sandersa736b372016-04-29 13:33:12 +00003377 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3378 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3379 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3380 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003381
3382 return false;
3383 }
3384
3385 return true;
3386}
3387
3388bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003389 MCStreamer &Out,
3390 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003391 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003392 unsigned ATReg = Mips::NoRegister;
3393 unsigned DReg = Inst.getOperand(0).getReg();
3394 unsigned SReg = Inst.getOperand(1).getReg();
3395 int64_t ImmValue = Inst.getOperand(2).getImm();
3396
3397 unsigned FirstShift = Mips::NOP;
3398 unsigned SecondShift = Mips::NOP;
3399
3400 if (hasMips32r2()) {
3401
3402 if (Inst.getOpcode() == Mips::ROLImm) {
3403 uint64_t MaxShift = 32;
3404 uint64_t ShiftValue = ImmValue;
3405 if (ImmValue != 0)
3406 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003407 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003408 return false;
3409 }
3410
3411 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003412 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003413 return false;
3414 }
3415
3416 return true;
3417 }
3418
3419 if (hasMips32()) {
3420
3421 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003422 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003423 return false;
3424 }
3425
3426 switch (Inst.getOpcode()) {
3427 default:
3428 llvm_unreachable("unexpected instruction opcode");
3429 case Mips::ROLImm:
3430 FirstShift = Mips::SLL;
3431 SecondShift = Mips::SRL;
3432 break;
3433 case Mips::RORImm:
3434 FirstShift = Mips::SRL;
3435 SecondShift = Mips::SLL;
3436 break;
3437 }
3438
3439 ATReg = getATReg(Inst.getLoc());
3440 if (!ATReg)
3441 return true;
3442
Daniel Sandersa736b372016-04-29 13:33:12 +00003443 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3444 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3445 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003446
3447 return false;
3448 }
3449
3450 return true;
3451}
3452
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003453bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3454 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003455 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003456 unsigned ATReg = Mips::NoRegister;
3457 unsigned DReg = Inst.getOperand(0).getReg();
3458 unsigned SReg = Inst.getOperand(1).getReg();
3459 unsigned TReg = Inst.getOperand(2).getReg();
3460 unsigned TmpReg = DReg;
3461
3462 unsigned FirstShift = Mips::NOP;
3463 unsigned SecondShift = Mips::NOP;
3464
3465 if (hasMips64r2()) {
3466
3467 if (TmpReg == SReg) {
3468 TmpReg = getATReg(Inst.getLoc());
3469 if (!TmpReg)
3470 return true;
3471 }
3472
3473 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003474 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3475 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003476 return false;
3477 }
3478
3479 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003480 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003481 return false;
3482 }
3483
3484 return true;
3485 }
3486
3487 if (hasMips64()) {
3488
3489 switch (Inst.getOpcode()) {
3490 default:
3491 llvm_unreachable("unexpected instruction opcode");
3492 case Mips::DROL:
3493 FirstShift = Mips::DSRLV;
3494 SecondShift = Mips::DSLLV;
3495 break;
3496 case Mips::DROR:
3497 FirstShift = Mips::DSLLV;
3498 SecondShift = Mips::DSRLV;
3499 break;
3500 }
3501
3502 ATReg = getATReg(Inst.getLoc());
3503 if (!ATReg)
3504 return true;
3505
Daniel Sandersa736b372016-04-29 13:33:12 +00003506 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3507 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3508 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3509 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003510
3511 return false;
3512 }
3513
3514 return true;
3515}
3516
3517bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003518 MCStreamer &Out,
3519 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003520 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003521 unsigned ATReg = Mips::NoRegister;
3522 unsigned DReg = Inst.getOperand(0).getReg();
3523 unsigned SReg = Inst.getOperand(1).getReg();
3524 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3525
3526 unsigned FirstShift = Mips::NOP;
3527 unsigned SecondShift = Mips::NOP;
3528
3529 MCInst TmpInst;
3530
3531 if (hasMips64r2()) {
3532
3533 unsigned FinalOpcode = Mips::NOP;
3534 if (ImmValue == 0)
3535 FinalOpcode = Mips::DROTR;
3536 else if (ImmValue % 32 == 0)
3537 FinalOpcode = Mips::DROTR32;
3538 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3539 if (Inst.getOpcode() == Mips::DROLImm)
3540 FinalOpcode = Mips::DROTR32;
3541 else
3542 FinalOpcode = Mips::DROTR;
3543 } else if (ImmValue >= 33) {
3544 if (Inst.getOpcode() == Mips::DROLImm)
3545 FinalOpcode = Mips::DROTR;
3546 else
3547 FinalOpcode = Mips::DROTR32;
3548 }
3549
3550 uint64_t ShiftValue = ImmValue % 32;
3551 if (Inst.getOpcode() == Mips::DROLImm)
3552 ShiftValue = (32 - ImmValue % 32) % 32;
3553
Daniel Sandersa736b372016-04-29 13:33:12 +00003554 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003555
3556 return false;
3557 }
3558
3559 if (hasMips64()) {
3560
3561 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003562 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003563 return false;
3564 }
3565
3566 switch (Inst.getOpcode()) {
3567 default:
3568 llvm_unreachable("unexpected instruction opcode");
3569 case Mips::DROLImm:
3570 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3571 FirstShift = Mips::DSLL;
3572 SecondShift = Mips::DSRL32;
3573 }
3574 if (ImmValue == 32) {
3575 FirstShift = Mips::DSLL32;
3576 SecondShift = Mips::DSRL32;
3577 }
3578 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3579 FirstShift = Mips::DSLL32;
3580 SecondShift = Mips::DSRL;
3581 }
3582 break;
3583 case Mips::DRORImm:
3584 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3585 FirstShift = Mips::DSRL;
3586 SecondShift = Mips::DSLL32;
3587 }
3588 if (ImmValue == 32) {
3589 FirstShift = Mips::DSRL32;
3590 SecondShift = Mips::DSLL32;
3591 }
3592 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3593 FirstShift = Mips::DSRL32;
3594 SecondShift = Mips::DSLL;
3595 }
3596 break;
3597 }
3598
3599 ATReg = getATReg(Inst.getLoc());
3600 if (!ATReg)
3601 return true;
3602
Daniel Sandersa736b372016-04-29 13:33:12 +00003603 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3604 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3605 Inst.getLoc(), STI);
3606 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003607
3608 return false;
3609 }
3610
3611 return true;
3612}
3613
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003614bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3615 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003616 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003617 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3618 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3619
Daniel Sandersa736b372016-04-29 13:33:12 +00003620 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003621 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003622 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003623 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003624 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3625 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003626
3627 return false;
3628}
3629
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003630void MipsAsmParser::createCpRestoreMemOp(bool IsLoad, int StackOffset,
3631 SMLoc IDLoc, MCStreamer &Out,
3632 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003633 MipsTargetStreamer &TOut = getTargetStreamer();
3634
Daniel Sanders7225cd52016-04-29 16:16:49 +00003635 if (IsLoad) {
3636 TOut.emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, StackOffset,
3637 Mips::GP, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003638 return;
3639 }
3640
Daniel Sanders241c6792016-05-12 14:01:50 +00003641 TOut.emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, StackOffset,
3642 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003643}
3644
Matheus Almeida595fcab2014-06-11 15:05:56 +00003645unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3646 // As described by the Mips32r2 spec, the registers Rd and Rs for
3647 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00003648 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00003649 // and registers Rd and Base for microMIPS lwp instruction
Matheus Almeida595fcab2014-06-11 15:05:56 +00003650 unsigned Opcode = Inst.getOpcode();
3651
Zlatko Buljanae720db2016-04-22 06:44:34 +00003652 if ((Opcode == Mips::JALR_HB || Opcode == Mips::JALRC_HB_MMR6) &&
Matheus Almeida595fcab2014-06-11 15:05:56 +00003653 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3654 return Match_RequiresDifferentSrcAndDst;
Zlatko Buljanba553a62016-05-09 08:07:28 +00003655 else if ((Opcode == Mips::LWP_MM || Opcode == Mips::LWP_MMR6) &&
3656 (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()))
3657 return Match_RequiresDifferentSrcAndDst;
Matheus Almeida595fcab2014-06-11 15:05:56 +00003658
3659 return Match_Success;
3660}
3661
Daniel Sanders52da7af2015-11-06 12:11:03 +00003662static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3663 uint64_t ErrorInfo) {
3664 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3665 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3666 if (ErrorLoc == SMLoc())
3667 return Loc;
3668 return ErrorLoc;
3669 }
3670 return Loc;
3671}
3672
David Blaikie960ea3f2014-06-08 16:18:35 +00003673bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3674 OperandVector &Operands,
3675 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003676 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003677 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003678
Jack Carterb4dbc172012-09-05 23:34:03 +00003679 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00003680 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003681 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003682
3683 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003684 case Match_Success: {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003685 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00003686 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003687 return false;
3688 }
3689 case Match_MissingFeature:
3690 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3691 return true;
3692 case Match_InvalidOperand: {
3693 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003694 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003695 if (ErrorInfo >= Operands.size())
3696 return Error(IDLoc, "too few operands for instruction");
3697
Daniel Sanders52da7af2015-11-06 12:11:03 +00003698 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003699 if (ErrorLoc == SMLoc())
3700 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003701 }
3702
3703 return Error(ErrorLoc, "invalid operand for instruction");
3704 }
3705 case Match_MnemonicFail:
3706 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003707 case Match_RequiresDifferentSrcAndDst:
3708 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003709 case Match_Immz:
3710 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003711 case Match_UImm1_0:
3712 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3713 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003714 case Match_UImm2_0:
3715 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3716 "expected 2-bit unsigned immediate");
3717 case Match_UImm2_1:
3718 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3719 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003720 case Match_UImm3_0:
3721 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3722 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003723 case Match_UImm4_0:
3724 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3725 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003726 case Match_SImm4_0:
3727 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3728 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003729 case Match_UImm5_0:
3730 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3731 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00003732 case Match_SImm5_0:
3733 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3734 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003735 case Match_UImm5_1:
3736 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3737 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003738 case Match_UImm5_32:
3739 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3740 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003741 case Match_UImm5_33:
3742 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3743 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003744 case Match_UImm5_0_Report_UImm6:
3745 // This is used on UImm5 operands that have a corresponding UImm5_32
3746 // operand to avoid confusing the user.
3747 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3748 "expected 6-bit unsigned immediate");
3749 case Match_UImm5_Lsl2:
3750 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3751 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003752 case Match_UImmRange2_64:
3753 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3754 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003755 case Match_UImm6_0:
3756 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3757 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00003758 case Match_UImm6_Lsl2:
3759 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3760 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00003761 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00003762 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3763 "expected 6-bit signed immediate");
3764 case Match_UImm7_0:
3765 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3766 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00003767 case Match_UImm7_N1:
3768 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3769 "expected immediate in range -1 .. 126");
3770 case Match_SImm7_Lsl2:
3771 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3772 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003773 case Match_UImm8_0:
3774 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3775 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003776 case Match_UImm10_0:
3777 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3778 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00003779 case Match_SImm10_0:
3780 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3781 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00003782 case Match_SImm11_0:
3783 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3784 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003785 case Match_UImm16:
3786 case Match_UImm16_Relaxed:
3787 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3788 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003789 case Match_SImm16:
3790 case Match_SImm16_Relaxed:
3791 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3792 "expected 16-bit signed immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003793 case Match_UImm20_0:
3794 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3795 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00003796 case Match_UImm26_0:
3797 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3798 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00003799 case Match_SImm32:
3800 case Match_SImm32_Relaxed:
3801 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3802 "expected 32-bit signed immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00003803 case Match_MemSImm9:
3804 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3805 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00003806 case Match_MemSImm10:
3807 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3808 "expected memory with 10-bit signed offset");
3809 case Match_MemSImm10Lsl1:
3810 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3811 "expected memory with 11-bit signed offset and multiple of 2");
3812 case Match_MemSImm10Lsl2:
3813 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3814 "expected memory with 12-bit signed offset and multiple of 4");
3815 case Match_MemSImm10Lsl3:
3816 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3817 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00003818 case Match_MemSImm11:
3819 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3820 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00003821 case Match_MemSImm12:
3822 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3823 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003824 case Match_MemSImm16:
3825 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3826 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00003827 }
Craig Topper589ceee2015-01-03 08:16:34 +00003828
3829 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003830}
3831
Toma Tabacud9d344b2015-04-27 14:05:04 +00003832void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3833 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3834 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3835 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003836}
3837
Toma Tabacu81496c12015-05-20 08:54:45 +00003838void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3839 if (!AssemblerOptions.back()->isMacro())
3840 Warning(Loc, "macro instruction expanded into multiple instructions");
3841}
3842
Daniel Sandersef638fe2014-10-03 15:37:37 +00003843void
3844MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3845 SMRange Range, bool ShowColors) {
3846 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003847 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003848 ShowColors);
3849}
3850
Jack Carter1ac53222013-02-20 23:11:17 +00003851int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003852 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003853
Vladimir Medic4c299852013-11-06 11:27:05 +00003854 CC = StringSwitch<unsigned>(Name)
3855 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003856 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003857 .Case("a0", 4)
3858 .Case("a1", 5)
3859 .Case("a2", 6)
3860 .Case("a3", 7)
3861 .Case("v0", 2)
3862 .Case("v1", 3)
3863 .Case("s0", 16)
3864 .Case("s1", 17)
3865 .Case("s2", 18)
3866 .Case("s3", 19)
3867 .Case("s4", 20)
3868 .Case("s5", 21)
3869 .Case("s6", 22)
3870 .Case("s7", 23)
3871 .Case("k0", 26)
3872 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003873 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003874 .Case("sp", 29)
3875 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003876 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003877 .Case("ra", 31)
3878 .Case("t0", 8)
3879 .Case("t1", 9)
3880 .Case("t2", 10)
3881 .Case("t3", 11)
3882 .Case("t4", 12)
3883 .Case("t5", 13)
3884 .Case("t6", 14)
3885 .Case("t7", 15)
3886 .Case("t8", 24)
3887 .Case("t9", 25)
3888 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003889
Toma Tabacufda445c2014-09-15 15:33:01 +00003890 if (!(isABI_N32() || isABI_N64()))
3891 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003892
Daniel Sandersef638fe2014-10-03 15:37:37 +00003893 if (12 <= CC && CC <= 15) {
3894 // Name is one of t4-t7
3895 AsmToken RegTok = getLexer().peekTok();
3896 SMRange RegRange = RegTok.getLocRange();
3897
3898 StringRef FixedName = StringSwitch<StringRef>(Name)
3899 .Case("t4", "t0")
3900 .Case("t5", "t1")
3901 .Case("t6", "t2")
3902 .Case("t7", "t3")
3903 .Default("");
3904 assert(FixedName != "" && "Register name is not one of t4-t7.");
3905
3906 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3907 "Did you mean $" + FixedName + "?", RegRange);
3908 }
3909
Toma Tabacufda445c2014-09-15 15:33:01 +00003910 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3911 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3912 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3913 if (8 <= CC && CC <= 11)
3914 CC += 4;
3915
3916 if (CC == -1)
3917 CC = StringSwitch<unsigned>(Name)
3918 .Case("a4", 8)
3919 .Case("a5", 9)
3920 .Case("a6", 10)
3921 .Case("a7", 11)
3922 .Case("kt0", 26)
3923 .Case("kt1", 27)
3924 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003925
3926 return CC;
3927}
Jack Carterd0bd6422013-04-18 00:41:53 +00003928
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003929int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3930 int CC;
3931
3932 CC = StringSwitch<unsigned>(Name)
3933 .Case("hwr_cpunum", 0)
3934 .Case("hwr_synci_step", 1)
3935 .Case("hwr_cc", 2)
3936 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003937 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003938 .Default(-1);
3939
3940 return CC;
3941}
3942
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003943int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003944
Jack Cartera63b16a2012-09-07 00:23:42 +00003945 if (Name[0] == 'f') {
3946 StringRef NumString = Name.substr(1);
3947 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003948 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003949 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003950 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003951 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003952 return IntVal;
3953 }
3954 return -1;
3955}
Jack Cartera63b16a2012-09-07 00:23:42 +00003956
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003957int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3958
3959 if (Name.startswith("fcc")) {
3960 StringRef NumString = Name.substr(3);
3961 unsigned IntVal;
3962 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003963 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003964 if (IntVal > 7) // There are only 8 fcc registers.
3965 return -1;
3966 return IntVal;
3967 }
3968 return -1;
3969}
3970
3971int MipsAsmParser::matchACRegisterName(StringRef Name) {
3972
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003973 if (Name.startswith("ac")) {
3974 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003975 unsigned IntVal;
3976 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003977 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003978 if (IntVal > 3) // There are only 3 acc registers.
3979 return -1;
3980 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003981 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003982 return -1;
3983}
Jack Carterd0bd6422013-04-18 00:41:53 +00003984
Jack Carter5dc8ac92013-09-25 23:50:44 +00003985int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3986 unsigned IntVal;
3987
3988 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3989 return -1;
3990
3991 if (IntVal > 31)
3992 return -1;
3993
3994 return IntVal;
3995}
3996
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003997int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3998 int CC;
3999
4000 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00004001 .Case("msair", 0)
4002 .Case("msacsr", 1)
4003 .Case("msaaccess", 2)
4004 .Case("msasave", 3)
4005 .Case("msamodify", 4)
4006 .Case("msarequest", 5)
4007 .Case("msamap", 6)
4008 .Case("msaunmap", 7)
4009 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004010
4011 return CC;
4012}
4013
Toma Tabacu89a712b2015-04-15 10:48:56 +00004014unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004015 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004016 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004017 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004018 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004019 return 0;
4020 }
4021 unsigned AT = getReg(
4022 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004023 return AT;
4024}
Jack Carter0b744b32012-10-04 02:29:46 +00004025
Jack Carterd0bd6422013-04-18 00:41:53 +00004026unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004027 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004028}
4029
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004030unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004031 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00004032 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004033}
4034
Jack Carter873c7242013-01-12 01:03:14 +00004035int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004036 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00004037 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00004038 return -1;
4039
Jack Carter873c7242013-01-12 01:03:14 +00004040 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00004041}
4042
Toma Tabacu13964452014-09-04 13:23:44 +00004043bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004044 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004045 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004046
Jack Carter30a59822012-10-04 04:03:53 +00004047 // Check if the current operand has a custom associated parser, if so, try to
4048 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004049 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4050 if (ResTy == MatchOperand_Success)
4051 return false;
4052 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4053 // there was a match, but an error occurred, in which case, just return that
4054 // the operand parsing failed.
4055 if (ResTy == MatchOperand_ParseFail)
4056 return true;
4057
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004058 DEBUG(dbgs() << ".. Generic Parser\n");
4059
Jack Carterb4dbc172012-09-05 23:34:03 +00004060 switch (getLexer().getKind()) {
4061 default:
4062 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4063 return true;
4064 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004065 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004066 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004067
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004068 // Almost all registers have been parsed by custom parsers. There is only
4069 // one exception to this. $zero (and it's alias $0) will reach this point
4070 // for div, divu, and similar instructions because it is not an operand
4071 // to the instruction definition but an explicit register. Special case
4072 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004073 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004074 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004075
Jack Carterd0bd6422013-04-18 00:41:53 +00004076 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004077 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004078 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004079 return true;
4080
Jack Carter873c7242013-01-12 01:03:14 +00004081 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004082 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004083 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004084 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004085 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004086
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004087 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004088 return false;
4089 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004090 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004091 case AsmToken::LParen:
4092 case AsmToken::Minus:
4093 case AsmToken::Plus:
4094 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004095 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004096 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004097 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004098 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004099 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004100 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004101 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004102 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004103 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004104 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004105 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004106 return true;
4107
Jack Carter873c7242013-01-12 01:03:14 +00004108 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4109
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004110 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004111 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004112 } // case AsmToken::Percent
4113 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004114 return true;
4115}
4116
Vladimir Medic4c299852013-11-06 11:27:05 +00004117const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004118 StringRef RelocStr) {
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004119 if (RelocStr == "hi(%neg(%gp_rel")
4120 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext());
4121 else if (RelocStr == "lo(%neg(%gp_rel")
4122 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004123
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004124 MipsMCExpr::MipsExprKind Kind =
4125 StringSwitch<MipsMCExpr::MipsExprKind>(RelocStr)
4126 .Case("call16", MipsMCExpr::MEK_GOT_CALL)
4127 .Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
4128 .Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
4129 .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
4130 .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
4131 .Case("got", MipsMCExpr::MEK_GOT)
4132 .Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
4133 .Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
4134 .Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
4135 .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
4136 .Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
4137 .Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
4138 .Case("gp_rel", MipsMCExpr::MEK_GPREL)
4139 .Case("hi", MipsMCExpr::MEK_HI)
4140 .Case("higher", MipsMCExpr::MEK_HIGHER)
4141 .Case("highest", MipsMCExpr::MEK_HIGHEST)
4142 .Case("lo", MipsMCExpr::MEK_LO)
4143 .Case("neg", MipsMCExpr::MEK_NEG)
4144 .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
4145 .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
4146 .Case("tlsgd", MipsMCExpr::MEK_TLSGD)
4147 .Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
4148 .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
4149 .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
4150 .Default(MipsMCExpr::MEK_None);
Jack Carterb5cf5902013-04-17 00:18:04 +00004151
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004152 assert(Kind != MipsMCExpr::MEK_None);
4153 return MipsMCExpr::create(Kind, Expr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004154}
4155
4156bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4157
4158 switch (Expr->getKind()) {
4159 case MCExpr::Constant:
4160 return true;
4161 case MCExpr::SymbolRef:
4162 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4163 case MCExpr::Binary:
4164 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4165 if (!isEvaluated(BE->getLHS()))
4166 return false;
4167 return isEvaluated(BE->getRHS());
4168 }
4169 case MCExpr::Unary:
4170 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004171 case MCExpr::Target:
4172 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004173 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004174 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004175}
Jack Carterd0bd6422013-04-18 00:41:53 +00004176
Jack Carterb5cf5902013-04-17 00:18:04 +00004177bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004178 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004179 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004180 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004181 if (Tok.isNot(AsmToken::Identifier))
4182 return true;
4183
Yaron Keren075759a2015-03-30 15:42:36 +00004184 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004185
Jack Carterd0bd6422013-04-18 00:41:53 +00004186 Parser.Lex(); // Eat the identifier.
4187 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004188 const MCExpr *IdVal;
4189 SMLoc EndLoc;
4190
4191 if (getLexer().getKind() == AsmToken::LParen) {
4192 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004193 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004194 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004195 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004196 const AsmToken &nextTok = Parser.getTok();
4197 if (nextTok.isNot(AsmToken::Identifier))
4198 return true;
4199 Str += "(%";
4200 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004201 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004202 if (getLexer().getKind() != AsmToken::LParen)
4203 return true;
4204 } else
4205 break;
4206 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004207 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004208 return true;
4209
4210 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004211 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004212
4213 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004214 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004215
Jack Carterd0bd6422013-04-18 00:41:53 +00004216 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004217 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004218}
4219
Jack Carterb4dbc172012-09-05 23:34:03 +00004220bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4221 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004222 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004223 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004224 if (ResTy == MatchOperand_Success) {
4225 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004226 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004227 StartLoc = Operand.getStartLoc();
4228 EndLoc = Operand.getEndLoc();
4229
4230 // AFAIK, we only support numeric registers and named GPR's in CFI
4231 // directives.
4232 // Don't worry about eating tokens before failing. Using an unrecognised
4233 // register is a parse error.
4234 if (Operand.isGPRAsmReg()) {
4235 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004236 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004237 }
4238
4239 return (RegNo == (unsigned)-1);
4240 }
4241
4242 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004243 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004244}
4245
Jack Carterb5cf5902013-04-17 00:18:04 +00004246bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004247 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004248 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004249 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004250 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004251
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004252 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004253 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004254 ++NumOfLParen;
4255 }
Jack Carter873c7242013-01-12 01:03:14 +00004256
Jack Carterd0bd6422013-04-18 00:41:53 +00004257 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004258 default:
4259 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004260 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004261 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004262 case AsmToken::Integer:
4263 case AsmToken::Minus:
4264 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004265 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004266 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004267 else
4268 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004269 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004270 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004271 break;
Jack Carter873c7242013-01-12 01:03:14 +00004272 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004273 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004274 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004275 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004276}
4277
David Blaikie960ea3f2014-06-08 16:18:35 +00004278MipsAsmParser::OperandMatchResultTy
4279MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004280 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004281 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004282 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004283 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004284 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004285 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004286 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004287 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004288
Jack Carterb5cf5902013-04-17 00:18:04 +00004289 if (getLexer().getKind() == AsmToken::LParen) {
4290 Parser.Lex();
4291 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004292 }
4293
Jack Carterb5cf5902013-04-17 00:18:04 +00004294 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004295 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004296 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004297
Jack Carterd0bd6422013-04-18 00:41:53 +00004298 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004299 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004300 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004301 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004302 SMLoc E =
4303 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004304 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004305 return MatchOperand_Success;
4306 }
4307 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004308 SMLoc E =
4309 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004310
Jack Carterd0bd6422013-04-18 00:41:53 +00004311 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004312 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004313 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004314 S, E, *this);
4315 Operands.push_back(
4316 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004317 return MatchOperand_Success;
4318 }
4319 Error(Parser.getTok().getLoc(), "'(' expected");
4320 return MatchOperand_ParseFail;
4321 }
4322
Jack Carterd0bd6422013-04-18 00:41:53 +00004323 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004324 }
4325
Toma Tabacu13964452014-09-04 13:23:44 +00004326 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004327 if (Res != MatchOperand_Success)
4328 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004329
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004330 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004331 Error(Parser.getTok().getLoc(), "')' expected");
4332 return MatchOperand_ParseFail;
4333 }
4334
Jack Carter873c7242013-01-12 01:03:14 +00004335 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4336
Jack Carterd0bd6422013-04-18 00:41:53 +00004337 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004338
Craig Topper062a2ba2014-04-25 05:30:21 +00004339 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004340 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004341
Jack Carterd0bd6422013-04-18 00:41:53 +00004342 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004343 std::unique_ptr<MipsOperand> op(
4344 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004345 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004346 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004347 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004348 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004349 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4350 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004351 if (IdVal->evaluateAsAbsolute(Imm))
4352 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004353 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004354 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004355 getContext());
4356 }
4357
David Blaikie960ea3f2014-06-08 16:18:35 +00004358 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004359 return MatchOperand_Success;
4360}
4361
David Blaikie960ea3f2014-06-08 16:18:35 +00004362bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004363 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004364 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004365 if (Sym) {
4366 SMLoc S = Parser.getTok().getLoc();
4367 const MCExpr *Expr;
4368 if (Sym->isVariable())
4369 Expr = Sym->getVariableValue();
4370 else
4371 return false;
4372 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004373 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004374 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004375 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004376 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004377 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004378 if (ResTy == MatchOperand_Success) {
4379 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004380 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004381 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004382 llvm_unreachable("Should never ParseFail");
4383 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004384 }
4385 } else if (Expr->getKind() == MCExpr::Constant) {
4386 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004387 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004388 Operands.push_back(
4389 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004390 return true;
4391 }
4392 }
4393 return false;
4394}
Jack Carterd0bd6422013-04-18 00:41:53 +00004395
Jack Carter873c7242013-01-12 01:03:14 +00004396MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004397MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004398 StringRef Identifier,
4399 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004400 int Index = matchCPURegisterName(Identifier);
4401 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004402 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004403 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4404 return MatchOperand_Success;
4405 }
4406
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004407 Index = matchHWRegsRegisterName(Identifier);
4408 if (Index != -1) {
4409 Operands.push_back(MipsOperand::createHWRegsReg(
4410 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4411 return MatchOperand_Success;
4412 }
4413
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004414 Index = matchFPURegisterName(Identifier);
4415 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004416 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004417 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4418 return MatchOperand_Success;
4419 }
4420
4421 Index = matchFCCRegisterName(Identifier);
4422 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004423 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004424 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4425 return MatchOperand_Success;
4426 }
4427
4428 Index = matchACRegisterName(Identifier);
4429 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004430 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004431 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4432 return MatchOperand_Success;
4433 }
4434
4435 Index = matchMSA128RegisterName(Identifier);
4436 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004437 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004438 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4439 return MatchOperand_Success;
4440 }
4441
4442 Index = matchMSA128CtrlRegisterName(Identifier);
4443 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004444 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004445 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4446 return MatchOperand_Success;
4447 }
4448
4449 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004450}
4451
4452MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004453MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004454 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004455 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004456
4457 if (Token.is(AsmToken::Identifier)) {
4458 DEBUG(dbgs() << ".. identifier\n");
4459 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004460 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004461 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004462 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004463 } else if (Token.is(AsmToken::Integer)) {
4464 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004465 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004466 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4467 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004468 return MatchOperand_Success;
4469 }
4470
4471 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4472
4473 return MatchOperand_NoMatch;
4474}
4475
David Blaikie960ea3f2014-06-08 16:18:35 +00004476MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004477MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004478 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004479 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004480
4481 auto Token = Parser.getTok();
4482
4483 SMLoc S = Token.getLoc();
4484
4485 if (Token.isNot(AsmToken::Dollar)) {
4486 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4487 if (Token.is(AsmToken::Identifier)) {
4488 if (searchSymbolAlias(Operands))
4489 return MatchOperand_Success;
4490 }
4491 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4492 return MatchOperand_NoMatch;
4493 }
4494 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004495
Toma Tabacu13964452014-09-04 13:23:44 +00004496 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004497 if (ResTy == MatchOperand_Success) {
4498 Parser.Lex(); // $
4499 Parser.Lex(); // identifier
4500 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004501 return ResTy;
4502}
4503
4504MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004505MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004506 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004507 switch (getLexer().getKind()) {
4508 default:
4509 return MatchOperand_NoMatch;
4510 case AsmToken::LParen:
4511 case AsmToken::Minus:
4512 case AsmToken::Plus:
4513 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004514 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004515 case AsmToken::String:
4516 break;
4517 }
4518
4519 const MCExpr *IdVal;
4520 SMLoc S = Parser.getTok().getLoc();
4521 if (getParser().parseExpression(IdVal))
4522 return MatchOperand_ParseFail;
4523
4524 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4525 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4526 return MatchOperand_Success;
4527}
4528
David Blaikie960ea3f2014-06-08 16:18:35 +00004529MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004530MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004531 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004532 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004533
4534 SMLoc S = getLexer().getLoc();
4535
4536 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004537 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004538 if (ResTy != MatchOperand_NoMatch)
4539 return ResTy;
4540
Daniel Sanders315386c2014-04-01 10:40:14 +00004541 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004542 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004543 if (ResTy != MatchOperand_NoMatch)
4544 return ResTy;
4545
Daniel Sandersffd84362014-04-01 10:41:48 +00004546 const MCExpr *Expr = nullptr;
4547 if (Parser.parseExpression(Expr)) {
4548 // We have no way of knowing if a symbol was consumed so we must ParseFail
4549 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004550 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004551 Operands.push_back(
4552 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004553 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004554}
4555
Vladimir Medic2b953d02013-10-01 09:48:56 +00004556MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004557MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004558 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004559 const MCExpr *IdVal;
4560 // If the first token is '$' we may have register operand.
4561 if (Parser.getTok().is(AsmToken::Dollar))
4562 return MatchOperand_NoMatch;
4563 SMLoc S = Parser.getTok().getLoc();
4564 if (getParser().parseExpression(IdVal))
4565 return MatchOperand_ParseFail;
4566 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004567 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004568 int64_t Val = MCE->getValue();
4569 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4570 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004571 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004572 return MatchOperand_Success;
4573}
4574
Matheus Almeida779c5932013-11-18 12:32:49 +00004575MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004576MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004577 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004578 switch (getLexer().getKind()) {
4579 default:
4580 return MatchOperand_NoMatch;
4581 case AsmToken::LParen:
4582 case AsmToken::Plus:
4583 case AsmToken::Minus:
4584 case AsmToken::Integer:
4585 break;
4586 }
4587
4588 const MCExpr *Expr;
4589 SMLoc S = Parser.getTok().getLoc();
4590
4591 if (getParser().parseExpression(Expr))
4592 return MatchOperand_ParseFail;
4593
4594 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004595 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004596 Error(S, "expected immediate value");
4597 return MatchOperand_ParseFail;
4598 }
4599
4600 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4601 // and because the CPU always adds one to the immediate field, the allowed
4602 // range becomes 1..4. We'll only check the range here and will deal
4603 // with the addition/subtraction when actually decoding/encoding
4604 // the instruction.
4605 if (Val < 1 || Val > 4) {
4606 Error(S, "immediate not in range (1..4)");
4607 return MatchOperand_ParseFail;
4608 }
4609
Jack Carter3b2c96e2014-01-22 23:31:38 +00004610 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004611 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004612 return MatchOperand_Success;
4613}
4614
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004615MipsAsmParser::OperandMatchResultTy
4616MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4617 MCAsmParser &Parser = getParser();
4618 SmallVector<unsigned, 10> Regs;
4619 unsigned RegNo;
4620 unsigned PrevReg = Mips::NoRegister;
4621 bool RegRange = false;
4622 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4623
4624 if (Parser.getTok().isNot(AsmToken::Dollar))
4625 return MatchOperand_ParseFail;
4626
4627 SMLoc S = Parser.getTok().getLoc();
4628 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4629 SMLoc E = getLexer().getLoc();
4630 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4631 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4632 if (RegRange) {
4633 // Remove last register operand because registers from register range
4634 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004635 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4636 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004637 Regs.push_back(RegNo);
4638 } else {
4639 unsigned TmpReg = PrevReg + 1;
4640 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004641 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4642 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4643 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004644 Error(E, "invalid register operand");
4645 return MatchOperand_ParseFail;
4646 }
4647
4648 PrevReg = TmpReg;
4649 Regs.push_back(TmpReg++);
4650 }
4651 }
4652
4653 RegRange = false;
4654 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004655 if ((PrevReg == Mips::NoRegister) &&
4656 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4657 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004658 Error(E, "$16 or $31 expected");
4659 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004660 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4661 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4662 !isGP64bit()) ||
4663 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4664 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4665 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004666 Error(E, "invalid register operand");
4667 return MatchOperand_ParseFail;
4668 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004669 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4670 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4671 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004672 Error(E, "consecutive register numbers expected");
4673 return MatchOperand_ParseFail;
4674 }
4675
4676 Regs.push_back(RegNo);
4677 }
4678
4679 if (Parser.getTok().is(AsmToken::Minus))
4680 RegRange = true;
4681
4682 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4683 !Parser.getTok().isNot(AsmToken::Comma)) {
4684 Error(E, "',' or '-' expected");
4685 return MatchOperand_ParseFail;
4686 }
4687
4688 Lex(); // Consume comma or minus
4689 if (Parser.getTok().isNot(AsmToken::Dollar))
4690 break;
4691
4692 PrevReg = RegNo;
4693 }
4694
4695 SMLoc E = Parser.getTok().getLoc();
4696 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4697 parseMemOperand(Operands);
4698 return MatchOperand_Success;
4699}
4700
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004701MipsAsmParser::OperandMatchResultTy
4702MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4703 MCAsmParser &Parser = getParser();
4704
4705 SMLoc S = Parser.getTok().getLoc();
4706 if (parseAnyRegister(Operands) != MatchOperand_Success)
4707 return MatchOperand_ParseFail;
4708
4709 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00004710 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00004711
Benjamin Kramer2b68d152016-05-09 10:31:17 +00004712 Operands.pop_back();
4713 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004714 return MatchOperand_Success;
4715}
4716
Zoran Jovanovic41688672015-02-10 16:36:20 +00004717MipsAsmParser::OperandMatchResultTy
4718MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4719 MCAsmParser &Parser = getParser();
4720 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4721 SmallVector<unsigned, 10> Regs;
4722
4723 if (Parser.getTok().isNot(AsmToken::Dollar))
4724 return MatchOperand_ParseFail;
4725
4726 SMLoc S = Parser.getTok().getLoc();
4727
4728 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4729 return MatchOperand_ParseFail;
4730
4731 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4732 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4733 Regs.push_back(RegNo);
4734
4735 SMLoc E = Parser.getTok().getLoc();
4736 if (Parser.getTok().isNot(AsmToken::Comma)) {
4737 Error(E, "',' expected");
4738 return MatchOperand_ParseFail;
4739 }
4740
4741 // Remove comma.
4742 Parser.Lex();
4743
4744 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4745 return MatchOperand_ParseFail;
4746
4747 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4748 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4749 Regs.push_back(RegNo);
4750
4751 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4752
4753 return MatchOperand_Success;
4754}
4755
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004756/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4757/// either this.
4758/// ::= '(', register, ')'
4759/// handle it before we iterate so we don't get tripped up by the lack of
4760/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004761bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004762 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004763 if (getLexer().is(AsmToken::LParen)) {
4764 Operands.push_back(
4765 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4766 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004767 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004768 SMLoc Loc = getLexer().getLoc();
4769 Parser.eatToEndOfStatement();
4770 return Error(Loc, "unexpected token in argument list");
4771 }
4772 if (Parser.getTok().isNot(AsmToken::RParen)) {
4773 SMLoc Loc = getLexer().getLoc();
4774 Parser.eatToEndOfStatement();
4775 return Error(Loc, "unexpected token, expected ')'");
4776 }
4777 Operands.push_back(
4778 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4779 Parser.Lex();
4780 }
4781 return false;
4782}
4783
4784/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4785/// either one of these.
4786/// ::= '[', register, ']'
4787/// ::= '[', integer, ']'
4788/// handle it before we iterate so we don't get tripped up by the lack of
4789/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004790bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004791 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004792 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004793 if (getLexer().is(AsmToken::LBrac)) {
4794 Operands.push_back(
4795 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4796 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004797 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004798 SMLoc Loc = getLexer().getLoc();
4799 Parser.eatToEndOfStatement();
4800 return Error(Loc, "unexpected token in argument list");
4801 }
4802 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4803 SMLoc Loc = getLexer().getLoc();
4804 Parser.eatToEndOfStatement();
4805 return Error(Loc, "unexpected token, expected ']'");
4806 }
4807 Operands.push_back(
4808 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4809 Parser.Lex();
4810 }
4811 return false;
4812}
4813
David Blaikie960ea3f2014-06-08 16:18:35 +00004814bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4815 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004816 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004817 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004818
4819 // We have reached first instruction, module directive are now forbidden.
4820 getTargetStreamer().forbidModuleDirective();
4821
Vladimir Medic74593e62013-07-17 15:00:42 +00004822 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004823 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004824 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004825 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004826 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004827 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004828 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004829
4830 // Read the remaining operands.
4831 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4832 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004833 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004834 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004835 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004836 return Error(Loc, "unexpected token in argument list");
4837 }
Toma Tabacu13964452014-09-04 13:23:44 +00004838 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004839 return true;
4840 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004841
Jack Carterd0bd6422013-04-18 00:41:53 +00004842 while (getLexer().is(AsmToken::Comma)) {
4843 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004844 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004845 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004846 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004847 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004848 return Error(Loc, "unexpected token in argument list");
4849 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004850 // Parse bracket and parenthesis suffixes before we iterate
4851 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004852 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004853 return true;
4854 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004855 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004856 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004857 }
4858 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004859 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4860 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004861 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004862 return Error(Loc, "unexpected token in argument list");
4863 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004864 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004865 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004866}
4867
Nirav Dave996fc132016-05-05 14:15:46 +00004868// FIXME: Given that these have the same name, these should both be
4869// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004870bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004871 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004872 SMLoc Loc = getLexer().getLoc();
4873 Parser.eatToEndOfStatement();
4874 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004875}
4876
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004877bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004878 return Error(Loc, ErrorMsg);
4879}
4880
Jack Carter0b744b32012-10-04 02:29:46 +00004881bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004882 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004883 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004884
4885 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004886 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004887
4888 Parser.Lex(); // Eat "noat".
4889
Jack Carterd0bd6422013-04-18 00:41:53 +00004890 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004891 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004892 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004893 return false;
4894 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004895
4896 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004897 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004898 return false;
4899}
Jack Carterd0bd6422013-04-18 00:41:53 +00004900
Jack Carter0b744b32012-10-04 02:29:46 +00004901bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004902 // Line can be: ".set at", which sets $at to $1
4903 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004904 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004905 Parser.Lex(); // Eat "at".
4906
Jack Carter0b744b32012-10-04 02:29:46 +00004907 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004908 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004909 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004910
4911 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004912 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004913 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004914 }
4915
4916 if (getLexer().isNot(AsmToken::Equal)) {
4917 reportParseError("unexpected token, expected equals sign");
4918 return false;
4919 }
4920 Parser.Lex(); // Eat "=".
4921
4922 if (getLexer().isNot(AsmToken::Dollar)) {
4923 if (getLexer().is(AsmToken::EndOfStatement)) {
4924 reportParseError("no register specified");
4925 return false;
4926 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004927 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004928 return false;
4929 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004930 }
4931 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004932
Toma Tabacu16a74492015-02-13 10:30:57 +00004933 // Find out what "reg" is.
4934 unsigned AtRegNo;
4935 const AsmToken &Reg = Parser.getTok();
4936 if (Reg.is(AsmToken::Identifier)) {
4937 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4938 } else if (Reg.is(AsmToken::Integer)) {
4939 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004940 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004941 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004942 return false;
4943 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004944
4945 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004946 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004947 reportParseError("invalid register");
4948 return false;
4949 }
4950 Parser.Lex(); // Eat "reg".
4951
4952 // If this is not the end of the statement, report an error.
4953 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4954 reportParseError("unexpected token, expected end of statement");
4955 return false;
4956 }
4957
4958 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4959
4960 Parser.Lex(); // Consume the EndOfStatement.
4961 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004962}
4963
4964bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004965 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004966 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004967 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004968 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004969 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004970 return false;
4971 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004972 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004973 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004974 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004975 return false;
4976}
4977
4978bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004979 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004980 Parser.Lex();
4981 // If this is not the end of the statement, report an error.
4982 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004983 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004984 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004985 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004986 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004987 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004988 Parser.Lex(); // Consume the EndOfStatement.
4989 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004990}
4991
4992bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004993 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004994 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004995 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004996 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004997 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004998 return false;
4999 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005000 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005001 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005002 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005003 return false;
5004}
5005
5006bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005007 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005008 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005009 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005010 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005011 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005012 return false;
5013 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005014 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005015 reportParseError("`noreorder' must be set before `nomacro'");
5016 return false;
5017 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005018 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005019 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005020 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005021 return false;
5022}
Jack Carterd76b2372013-03-21 21:44:16 +00005023
Daniel Sanders44934432014-08-07 12:03:36 +00005024bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005025 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005026 Parser.Lex();
5027
5028 // If this is not the end of the statement, report an error.
5029 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005030 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005031
5032 setFeatureBits(Mips::FeatureMSA, "msa");
5033 getTargetStreamer().emitDirectiveSetMsa();
5034 return false;
5035}
5036
5037bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005038 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005039 Parser.Lex();
5040
5041 // If this is not the end of the statement, report an error.
5042 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005043 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005044
5045 clearFeatureBits(Mips::FeatureMSA, "msa");
5046 getTargetStreamer().emitDirectiveSetNoMsa();
5047 return false;
5048}
5049
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005050bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005051 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005052 Parser.Lex(); // Eat "nodsp".
5053
5054 // If this is not the end of the statement, report an error.
5055 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5056 reportParseError("unexpected token, expected end of statement");
5057 return false;
5058 }
5059
5060 clearFeatureBits(Mips::FeatureDSP, "dsp");
5061 getTargetStreamer().emitDirectiveSetNoDsp();
5062 return false;
5063}
5064
Toma Tabacucc2502d2014-11-04 17:18:07 +00005065bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005066 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005067 Parser.Lex(); // Eat "mips16".
5068
Jack Carter39536722014-01-22 23:08:42 +00005069 // If this is not the end of the statement, report an error.
5070 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005071 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005072 return false;
5073 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005074
5075 setFeatureBits(Mips::FeatureMips16, "mips16");
5076 getTargetStreamer().emitDirectiveSetMips16();
5077 Parser.Lex(); // Consume the EndOfStatement.
5078 return false;
5079}
5080
5081bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005082 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005083 Parser.Lex(); // Eat "nomips16".
5084
5085 // If this is not the end of the statement, report an error.
5086 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5087 reportParseError("unexpected token, expected end of statement");
5088 return false;
5089 }
5090
5091 clearFeatureBits(Mips::FeatureMips16, "mips16");
5092 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005093 Parser.Lex(); // Consume the EndOfStatement.
5094 return false;
5095}
5096
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005097bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005098 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005099 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005100 // Line can be: .set fp=32
5101 // .set fp=xx
5102 // .set fp=64
5103 Parser.Lex(); // Eat fp token
5104 AsmToken Tok = Parser.getTok();
5105 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005106 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005107 return false;
5108 }
5109 Parser.Lex(); // Eat '=' token.
5110 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005111
5112 if (!parseFpABIValue(FpAbiVal, ".set"))
5113 return false;
5114
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005115 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005116 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005117 return false;
5118 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005119 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005120 Parser.Lex(); // Consume the EndOfStatement.
5121 return false;
5122}
5123
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005124bool MipsAsmParser::parseSetOddSPRegDirective() {
5125 MCAsmParser &Parser = getParser();
5126
5127 Parser.Lex(); // Eat "oddspreg".
5128 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5129 reportParseError("unexpected token, expected end of statement");
5130 return false;
5131 }
5132
5133 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5134 getTargetStreamer().emitDirectiveSetOddSPReg();
5135 return false;
5136}
5137
5138bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5139 MCAsmParser &Parser = getParser();
5140
5141 Parser.Lex(); // Eat "nooddspreg".
5142 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5143 reportParseError("unexpected token, expected end of statement");
5144 return false;
5145 }
5146
5147 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5148 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5149 return false;
5150}
5151
Toma Tabacu9db22db2014-09-09 10:15:38 +00005152bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005153 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005154 SMLoc Loc = getLexer().getLoc();
5155
5156 Parser.Lex();
5157 if (getLexer().isNot(AsmToken::EndOfStatement))
5158 return reportParseError("unexpected token, expected end of statement");
5159
5160 // Always keep an element on the options "stack" to prevent the user
5161 // from changing the initial options. This is how we remember them.
5162 if (AssemblerOptions.size() == 2)
5163 return reportParseError(Loc, ".set pop with no .set push");
5164
Akira Hatanakab11ef082015-11-14 06:35:56 +00005165 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005166 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005167 setAvailableFeatures(
5168 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5169 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005170
5171 getTargetStreamer().emitDirectiveSetPop();
5172 return false;
5173}
5174
5175bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005176 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005177 Parser.Lex();
5178 if (getLexer().isNot(AsmToken::EndOfStatement))
5179 return reportParseError("unexpected token, expected end of statement");
5180
5181 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005182 AssemblerOptions.push_back(
5183 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005184
5185 getTargetStreamer().emitDirectiveSetPush();
5186 return false;
5187}
5188
Toma Tabacu29696502015-06-02 09:48:04 +00005189bool MipsAsmParser::parseSetSoftFloatDirective() {
5190 MCAsmParser &Parser = getParser();
5191 Parser.Lex();
5192 if (getLexer().isNot(AsmToken::EndOfStatement))
5193 return reportParseError("unexpected token, expected end of statement");
5194
5195 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5196 getTargetStreamer().emitDirectiveSetSoftFloat();
5197 return false;
5198}
5199
5200bool MipsAsmParser::parseSetHardFloatDirective() {
5201 MCAsmParser &Parser = getParser();
5202 Parser.Lex();
5203 if (getLexer().isNot(AsmToken::EndOfStatement))
5204 return reportParseError("unexpected token, expected end of statement");
5205
5206 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5207 getTargetStreamer().emitDirectiveSetHardFloat();
5208 return false;
5209}
5210
Jack Carterd76b2372013-03-21 21:44:16 +00005211bool MipsAsmParser::parseSetAssignment() {
5212 StringRef Name;
5213 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005214 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005215
5216 if (Parser.parseIdentifier(Name))
5217 reportParseError("expected identifier after .set");
5218
5219 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005220 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005221 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005222
Jack Carter3b2c96e2014-01-22 23:31:38 +00005223 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005224 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005225
Jim Grosbach6f482002015-05-18 18:43:14 +00005226 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005227 Sym->setVariableValue(Value);
5228
5229 return false;
5230}
Jack Carterd0bd6422013-04-18 00:41:53 +00005231
Toma Tabacu26647792014-09-09 12:52:14 +00005232bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005233 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005234 Parser.Lex();
5235 if (getLexer().isNot(AsmToken::EndOfStatement))
5236 return reportParseError("unexpected token, expected end of statement");
5237
5238 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005239 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005240 setAvailableFeatures(
5241 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5242 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005243 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5244
5245 getTargetStreamer().emitDirectiveSetMips0();
5246 return false;
5247}
5248
Toma Tabacu85618b32014-08-19 14:22:52 +00005249bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005250 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005251 Parser.Lex();
5252 if (getLexer().isNot(AsmToken::Equal))
5253 return reportParseError("unexpected token, expected equals sign");
5254
5255 Parser.Lex();
5256 StringRef Arch;
5257 if (Parser.parseIdentifier(Arch))
5258 return reportParseError("expected arch identifier");
5259
5260 StringRef ArchFeatureName =
5261 StringSwitch<StringRef>(Arch)
5262 .Case("mips1", "mips1")
5263 .Case("mips2", "mips2")
5264 .Case("mips3", "mips3")
5265 .Case("mips4", "mips4")
5266 .Case("mips5", "mips5")
5267 .Case("mips32", "mips32")
5268 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005269 .Case("mips32r3", "mips32r3")
5270 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005271 .Case("mips32r6", "mips32r6")
5272 .Case("mips64", "mips64")
5273 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005274 .Case("mips64r3", "mips64r3")
5275 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005276 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005277 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005278 .Case("r4000", "mips3") // This is an implementation of Mips3.
5279 .Default("");
5280
5281 if (ArchFeatureName.empty())
5282 return reportParseError("unsupported architecture");
5283
5284 selectArch(ArchFeatureName);
5285 getTargetStreamer().emitDirectiveSetArch(Arch);
5286 return false;
5287}
5288
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005289bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005290 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005291 Parser.Lex();
5292 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005293 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005294
Matheus Almeida2852af82014-04-22 10:15:54 +00005295 switch (Feature) {
5296 default:
5297 llvm_unreachable("Unimplemented feature");
5298 case Mips::FeatureDSP:
5299 setFeatureBits(Mips::FeatureDSP, "dsp");
5300 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005301 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005302 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00005303 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00005304 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005305 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005306 case Mips::FeatureMips1:
5307 selectArch("mips1");
5308 getTargetStreamer().emitDirectiveSetMips1();
5309 break;
5310 case Mips::FeatureMips2:
5311 selectArch("mips2");
5312 getTargetStreamer().emitDirectiveSetMips2();
5313 break;
5314 case Mips::FeatureMips3:
5315 selectArch("mips3");
5316 getTargetStreamer().emitDirectiveSetMips3();
5317 break;
5318 case Mips::FeatureMips4:
5319 selectArch("mips4");
5320 getTargetStreamer().emitDirectiveSetMips4();
5321 break;
5322 case Mips::FeatureMips5:
5323 selectArch("mips5");
5324 getTargetStreamer().emitDirectiveSetMips5();
5325 break;
5326 case Mips::FeatureMips32:
5327 selectArch("mips32");
5328 getTargetStreamer().emitDirectiveSetMips32();
5329 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005330 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005331 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005332 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005333 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005334 case Mips::FeatureMips32r3:
5335 selectArch("mips32r3");
5336 getTargetStreamer().emitDirectiveSetMips32R3();
5337 break;
5338 case Mips::FeatureMips32r5:
5339 selectArch("mips32r5");
5340 getTargetStreamer().emitDirectiveSetMips32R5();
5341 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005342 case Mips::FeatureMips32r6:
5343 selectArch("mips32r6");
5344 getTargetStreamer().emitDirectiveSetMips32R6();
5345 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005346 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005347 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005348 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005349 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005350 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005351 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005352 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005353 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005354 case Mips::FeatureMips64r3:
5355 selectArch("mips64r3");
5356 getTargetStreamer().emitDirectiveSetMips64R3();
5357 break;
5358 case Mips::FeatureMips64r5:
5359 selectArch("mips64r5");
5360 getTargetStreamer().emitDirectiveSetMips64R5();
5361 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005362 case Mips::FeatureMips64r6:
5363 selectArch("mips64r6");
5364 getTargetStreamer().emitDirectiveSetMips64R6();
5365 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005366 }
5367 return false;
5368}
5369
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005370bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005371 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005372 if (getLexer().isNot(AsmToken::Comma)) {
5373 SMLoc Loc = getLexer().getLoc();
5374 Parser.eatToEndOfStatement();
5375 return Error(Loc, ErrorStr);
5376 }
5377
Matheus Almeida2852af82014-04-22 10:15:54 +00005378 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005379 return true;
5380}
5381
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005382// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5383// In this class, it is only used for .cprestore.
5384// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5385// MipsTargetELFStreamer and MipsAsmParser.
5386bool MipsAsmParser::isPicAndNotNxxAbi() {
5387 return inPicMode() && !(isABI_N32() || isABI_N64());
5388}
5389
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005390bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005391 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005392 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005393
Toma Tabacudde4c462014-11-06 10:02:45 +00005394 if (inMips16Mode()) {
5395 reportParseError(".cpload is not supported in Mips16 mode");
5396 return false;
5397 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005398
David Blaikie960ea3f2014-06-08 16:18:35 +00005399 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005400 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005401 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5402 reportParseError("expected register containing function address");
5403 return false;
5404 }
5405
David Blaikie960ea3f2014-06-08 16:18:35 +00005406 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5407 if (!RegOpnd.isGPRAsmReg()) {
5408 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005409 return false;
5410 }
5411
Toma Tabacudde4c462014-11-06 10:02:45 +00005412 // If this is not the end of the statement, report an error.
5413 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5414 reportParseError("unexpected token, expected end of statement");
5415 return false;
5416 }
5417
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005418 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005419 return false;
5420}
5421
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005422bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5423 MCAsmParser &Parser = getParser();
5424
5425 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5426 // is used in non-PIC mode.
5427
5428 if (inMips16Mode()) {
5429 reportParseError(".cprestore is not supported in Mips16 mode");
5430 return false;
5431 }
5432
5433 // Get the stack offset value.
5434 const MCExpr *StackOffset;
5435 int64_t StackOffsetVal;
5436 if (Parser.parseExpression(StackOffset)) {
5437 reportParseError("expected stack offset value");
5438 return false;
5439 }
5440
5441 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5442 reportParseError("stack offset is not an absolute expression");
5443 return false;
5444 }
5445
5446 if (StackOffsetVal < 0) {
5447 Warning(Loc, ".cprestore with negative stack offset has no effect");
5448 IsCpRestoreSet = false;
5449 } else {
5450 IsCpRestoreSet = true;
5451 CpRestoreOffset = StackOffsetVal;
5452 }
5453
5454 // If this is not the end of the statement, report an error.
5455 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5456 reportParseError("unexpected token, expected end of statement");
5457 return false;
5458 }
5459
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005460 if (!getTargetStreamer().emitDirectiveCpRestore(
5461 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005462 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005463 Parser.Lex(); // Consume the EndOfStatement.
5464 return false;
5465}
5466
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005467bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005468 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005469 unsigned FuncReg;
5470 unsigned Save;
5471 bool SaveIsReg = true;
5472
Matheus Almeida7e815762014-06-18 13:08:59 +00005473 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005474 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005475 if (ResTy == MatchOperand_NoMatch) {
5476 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005477 return false;
5478 }
5479
5480 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5481 if (!FuncRegOpnd.isGPRAsmReg()) {
5482 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5483 Parser.eatToEndOfStatement();
5484 return false;
5485 }
5486
5487 FuncReg = FuncRegOpnd.getGPR32Reg();
5488 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005489
Toma Tabacu65f10572014-09-16 15:00:52 +00005490 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005491 return true;
5492
Toma Tabacu13964452014-09-04 13:23:44 +00005493 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005494 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005495 const MCExpr *OffsetExpr;
5496 int64_t OffsetVal;
5497 SMLoc ExprLoc = getLexer().getLoc();
5498
5499 if (Parser.parseExpression(OffsetExpr) ||
5500 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5501 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005502 Parser.eatToEndOfStatement();
5503 return false;
5504 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005505
5506 Save = OffsetVal;
5507 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005508 } else {
5509 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5510 if (!SaveOpnd.isGPRAsmReg()) {
5511 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5512 Parser.eatToEndOfStatement();
5513 return false;
5514 }
5515 Save = SaveOpnd.getGPR32Reg();
5516 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005517
Toma Tabacu65f10572014-09-16 15:00:52 +00005518 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005519 return true;
5520
Toma Tabacu8874eac2015-02-18 13:46:53 +00005521 const MCExpr *Expr;
5522 if (Parser.parseExpression(Expr)) {
5523 reportParseError("expected expression");
5524 return false;
5525 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005526
Toma Tabacu8874eac2015-02-18 13:46:53 +00005527 if (Expr->getKind() != MCExpr::SymbolRef) {
5528 reportParseError("expected symbol");
5529 return false;
5530 }
5531 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5532
Daniel Sandersf173dda2015-09-22 10:50:09 +00005533 CpSaveLocation = Save;
5534 CpSaveLocationIsRegister = SaveIsReg;
5535
Toma Tabacu8874eac2015-02-18 13:46:53 +00005536 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5537 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005538 return false;
5539}
5540
Daniel Sandersf173dda2015-09-22 10:50:09 +00005541bool MipsAsmParser::parseDirectiveCPReturn() {
5542 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5543 CpSaveLocationIsRegister);
5544 return false;
5545}
5546
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005547bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005548 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005549 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5550 const AsmToken &Tok = Parser.getTok();
5551
5552 if (Tok.getString() == "2008") {
5553 Parser.Lex();
5554 getTargetStreamer().emitDirectiveNaN2008();
5555 return false;
5556 } else if (Tok.getString() == "legacy") {
5557 Parser.Lex();
5558 getTargetStreamer().emitDirectiveNaNLegacy();
5559 return false;
5560 }
5561 }
5562 // If we don't recognize the option passed to the .nan
5563 // directive (e.g. no option or unknown option), emit an error.
5564 reportParseError("invalid option in .nan directive");
5565 return false;
5566}
5567
Jack Carter0b744b32012-10-04 02:29:46 +00005568bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005569 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005570 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005571 const AsmToken &Tok = Parser.getTok();
5572
5573 if (Tok.getString() == "noat") {
5574 return parseSetNoAtDirective();
5575 } else if (Tok.getString() == "at") {
5576 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005577 } else if (Tok.getString() == "arch") {
5578 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005579 } else if (Tok.getString() == "fp") {
5580 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005581 } else if (Tok.getString() == "oddspreg") {
5582 return parseSetOddSPRegDirective();
5583 } else if (Tok.getString() == "nooddspreg") {
5584 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005585 } else if (Tok.getString() == "pop") {
5586 return parseSetPopDirective();
5587 } else if (Tok.getString() == "push") {
5588 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005589 } else if (Tok.getString() == "reorder") {
5590 return parseSetReorderDirective();
5591 } else if (Tok.getString() == "noreorder") {
5592 return parseSetNoReorderDirective();
5593 } else if (Tok.getString() == "macro") {
5594 return parseSetMacroDirective();
5595 } else if (Tok.getString() == "nomacro") {
5596 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005597 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005598 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005599 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005600 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005601 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00005602 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005603 getTargetStreamer().emitDirectiveSetNoMicroMips();
5604 Parser.eatToEndOfStatement();
5605 return false;
5606 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005607 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005608 } else if (Tok.getString() == "mips0") {
5609 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005610 } else if (Tok.getString() == "mips1") {
5611 return parseSetFeature(Mips::FeatureMips1);
5612 } else if (Tok.getString() == "mips2") {
5613 return parseSetFeature(Mips::FeatureMips2);
5614 } else if (Tok.getString() == "mips3") {
5615 return parseSetFeature(Mips::FeatureMips3);
5616 } else if (Tok.getString() == "mips4") {
5617 return parseSetFeature(Mips::FeatureMips4);
5618 } else if (Tok.getString() == "mips5") {
5619 return parseSetFeature(Mips::FeatureMips5);
5620 } else if (Tok.getString() == "mips32") {
5621 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005622 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005623 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005624 } else if (Tok.getString() == "mips32r3") {
5625 return parseSetFeature(Mips::FeatureMips32r3);
5626 } else if (Tok.getString() == "mips32r5") {
5627 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005628 } else if (Tok.getString() == "mips32r6") {
5629 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005630 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005631 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005632 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005633 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005634 } else if (Tok.getString() == "mips64r3") {
5635 return parseSetFeature(Mips::FeatureMips64r3);
5636 } else if (Tok.getString() == "mips64r5") {
5637 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005638 } else if (Tok.getString() == "mips64r6") {
5639 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005640 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005641 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005642 } else if (Tok.getString() == "nodsp") {
5643 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005644 } else if (Tok.getString() == "msa") {
5645 return parseSetMsaDirective();
5646 } else if (Tok.getString() == "nomsa") {
5647 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005648 } else if (Tok.getString() == "softfloat") {
5649 return parseSetSoftFloatDirective();
5650 } else if (Tok.getString() == "hardfloat") {
5651 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005652 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005653 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005654 parseSetAssignment();
5655 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005656 }
Jack Carter07c818d2013-01-25 01:31:34 +00005657
Jack Carter0b744b32012-10-04 02:29:46 +00005658 return true;
5659}
5660
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005661/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005662/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005663bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005664 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005665 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5666 for (;;) {
5667 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005668 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005669 return true;
5670
5671 getParser().getStreamer().EmitValue(Value, Size);
5672
5673 if (getLexer().is(AsmToken::EndOfStatement))
5674 break;
5675
Jack Carter07c818d2013-01-25 01:31:34 +00005676 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005677 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005678 Parser.Lex();
5679 }
5680 }
5681
5682 Parser.Lex();
5683 return false;
5684}
5685
Vladimir Medic4c299852013-11-06 11:27:05 +00005686/// parseDirectiveGpWord
5687/// ::= .gpword local_sym
5688bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005689 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005690 const MCExpr *Value;
5691 // EmitGPRel32Value requires an expression, so we are using base class
5692 // method to evaluate the expression.
5693 if (getParser().parseExpression(Value))
5694 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005695 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005696
Vladimir Medice10c1122013-11-13 13:18:04 +00005697 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005698 return Error(getLexer().getLoc(),
5699 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005700 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005701 return false;
5702}
5703
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005704/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005705/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005706bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005707 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005708 const MCExpr *Value;
5709 // EmitGPRel64Value requires an expression, so we are using base class
5710 // method to evaluate the expression.
5711 if (getParser().parseExpression(Value))
5712 return true;
5713 getParser().getStreamer().EmitGPRel64Value(Value);
5714
5715 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005716 return Error(getLexer().getLoc(),
5717 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005718 Parser.Lex(); // Eat EndOfStatement token.
5719 return false;
5720}
5721
Jack Carter0cd3c192014-01-06 23:27:31 +00005722bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005723 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005724 // Get the option token.
5725 AsmToken Tok = Parser.getTok();
5726 // At the moment only identifiers are supported.
5727 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005728 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005729 Parser.eatToEndOfStatement();
5730 return false;
5731 }
5732
5733 StringRef Option = Tok.getIdentifier();
5734
5735 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005736 // MipsAsmParser needs to know if the current PIC mode changes.
5737 IsPicEnabled = false;
5738
Jack Carter0cd3c192014-01-06 23:27:31 +00005739 getTargetStreamer().emitDirectiveOptionPic0();
5740 Parser.Lex();
5741 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5742 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005743 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005744 Parser.eatToEndOfStatement();
5745 }
5746 return false;
5747 }
5748
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005749 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005750 // MipsAsmParser needs to know if the current PIC mode changes.
5751 IsPicEnabled = true;
5752
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005753 getTargetStreamer().emitDirectiveOptionPic2();
5754 Parser.Lex();
5755 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5756 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005757 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005758 Parser.eatToEndOfStatement();
5759 }
5760 return false;
5761 }
5762
Jack Carter0cd3c192014-01-06 23:27:31 +00005763 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005764 Warning(Parser.getTok().getLoc(),
5765 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005766 Parser.eatToEndOfStatement();
5767 return false;
5768}
5769
Toma Tabacu9ca50962015-04-16 09:53:47 +00005770/// parseInsnDirective
5771/// ::= .insn
5772bool MipsAsmParser::parseInsnDirective() {
5773 // If this is not the end of the statement, report an error.
5774 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5775 reportParseError("unexpected token, expected end of statement");
5776 return false;
5777 }
5778
5779 // The actual label marking happens in
5780 // MipsELFStreamer::createPendingLabelRelocs().
5781 getTargetStreamer().emitDirectiveInsn();
5782
5783 getParser().Lex(); // Eat EndOfStatement token.
5784 return false;
5785}
5786
Simon Atanasyanbe186202016-02-11 06:45:54 +00005787/// parseSSectionDirective
5788/// ::= .sbss
5789/// ::= .sdata
5790bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5791 // If this is not the end of the statement, report an error.
5792 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5793 reportParseError("unexpected token, expected end of statement");
5794 return false;
5795 }
5796
5797 MCSection *ELFSection = getContext().getELFSection(
5798 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5799 getParser().getStreamer().SwitchSection(ELFSection);
5800
5801 getParser().Lex(); // Eat EndOfStatement token.
5802 return false;
5803}
5804
Daniel Sanders7e527422014-07-10 13:38:23 +00005805/// parseDirectiveModule
5806/// ::= .module oddspreg
5807/// ::= .module nooddspreg
5808/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005809/// ::= .module softfloat
5810/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005811bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005812 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005813 MCAsmLexer &Lexer = getLexer();
5814 SMLoc L = Lexer.getLoc();
5815
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005816 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005817 // TODO : get a better message.
5818 reportParseError(".module directive must appear before any code");
5819 return false;
5820 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005821
Toma Tabacuc405c822015-01-23 10:40:19 +00005822 StringRef Option;
5823 if (Parser.parseIdentifier(Option)) {
5824 reportParseError("expected .module option identifier");
5825 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005826 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005827
Toma Tabacuc405c822015-01-23 10:40:19 +00005828 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005829 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005830
Toma Tabacu3c499582015-06-25 10:56:57 +00005831 // Synchronize the abiflags information with the FeatureBits information we
5832 // changed above.
5833 getTargetStreamer().updateABIInfo(*this);
5834
5835 // If printing assembly, use the recently updated abiflags information.
5836 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5837 // emitted at the end).
5838 getTargetStreamer().emitDirectiveModuleOddSPReg();
5839
Toma Tabacuc405c822015-01-23 10:40:19 +00005840 // If this is not the end of the statement, report an error.
5841 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5842 reportParseError("unexpected token, expected end of statement");
5843 return false;
5844 }
5845
5846 return false; // parseDirectiveModule has finished successfully.
5847 } else if (Option == "nooddspreg") {
5848 if (!isABI_O32()) {
5849 Error(L, "'.module nooddspreg' requires the O32 ABI");
5850 return false;
5851 }
5852
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005853 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005854
Toma Tabacu3c499582015-06-25 10:56:57 +00005855 // Synchronize the abiflags information with the FeatureBits information we
5856 // changed above.
5857 getTargetStreamer().updateABIInfo(*this);
5858
5859 // If printing assembly, use the recently updated abiflags information.
5860 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5861 // emitted at the end).
5862 getTargetStreamer().emitDirectiveModuleOddSPReg();
5863
Toma Tabacuc405c822015-01-23 10:40:19 +00005864 // If this is not the end of the statement, report an error.
5865 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5866 reportParseError("unexpected token, expected end of statement");
5867 return false;
5868 }
5869
5870 return false; // parseDirectiveModule has finished successfully.
5871 } else if (Option == "fp") {
5872 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005873 } else if (Option == "softfloat") {
5874 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5875
5876 // Synchronize the ABI Flags information with the FeatureBits information we
5877 // updated above.
5878 getTargetStreamer().updateABIInfo(*this);
5879
5880 // If printing assembly, use the recently updated ABI Flags information.
5881 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5882 // emitted later).
5883 getTargetStreamer().emitDirectiveModuleSoftFloat();
5884
5885 // If this is not the end of the statement, report an error.
5886 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5887 reportParseError("unexpected token, expected end of statement");
5888 return false;
5889 }
5890
5891 return false; // parseDirectiveModule has finished successfully.
5892 } else if (Option == "hardfloat") {
5893 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5894
5895 // Synchronize the ABI Flags information with the FeatureBits information we
5896 // updated above.
5897 getTargetStreamer().updateABIInfo(*this);
5898
5899 // If printing assembly, use the recently updated ABI Flags information.
5900 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5901 // emitted later).
5902 getTargetStreamer().emitDirectiveModuleHardFloat();
5903
5904 // If this is not the end of the statement, report an error.
5905 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5906 reportParseError("unexpected token, expected end of statement");
5907 return false;
5908 }
5909
5910 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005911 } else {
5912 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5913 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005914}
5915
5916/// parseDirectiveModuleFP
5917/// ::= =32
5918/// ::= =xx
5919/// ::= =64
5920bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005921 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005922 MCAsmLexer &Lexer = getLexer();
5923
5924 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005925 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005926 return false;
5927 }
5928 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005929
Daniel Sanders7e527422014-07-10 13:38:23 +00005930 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005931 if (!parseFpABIValue(FpABI, ".module"))
5932 return false;
5933
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005934 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005935 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005936 return false;
5937 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005938
Toma Tabacua64e5402015-06-25 12:44:38 +00005939 // Synchronize the abiflags information with the FeatureBits information we
5940 // changed above.
5941 getTargetStreamer().updateABIInfo(*this);
5942
5943 // If printing assembly, use the recently updated abiflags information.
5944 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5945 // emitted at the end).
5946 getTargetStreamer().emitDirectiveModuleFP();
5947
Daniel Sanders7e527422014-07-10 13:38:23 +00005948 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005949 return false;
5950}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005951
Daniel Sanders7e527422014-07-10 13:38:23 +00005952bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005953 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005954 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005955 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005956 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005957
5958 if (Lexer.is(AsmToken::Identifier)) {
5959 StringRef Value = Parser.getTok().getString();
5960 Parser.Lex();
5961
5962 if (Value != "xx") {
5963 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5964 return false;
5965 }
5966
5967 if (!isABI_O32()) {
5968 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5969 return false;
5970 }
5971
Daniel Sanders7e527422014-07-10 13:38:23 +00005972 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005973 if (ModuleLevelOptions) {
5974 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5975 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5976 } else {
5977 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5978 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5979 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005980 return true;
5981 }
5982
5983 if (Lexer.is(AsmToken::Integer)) {
5984 unsigned Value = Parser.getTok().getIntVal();
5985 Parser.Lex();
5986
5987 if (Value != 32 && Value != 64) {
5988 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5989 return false;
5990 }
5991
5992 if (Value == 32) {
5993 if (!isABI_O32()) {
5994 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5995 return false;
5996 }
5997
Daniel Sanders7e527422014-07-10 13:38:23 +00005998 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005999 if (ModuleLevelOptions) {
6000 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6001 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6002 } else {
6003 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6004 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6005 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006006 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006007 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006008 if (ModuleLevelOptions) {
6009 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6010 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6011 } else {
6012 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6013 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6014 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006015 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006016
Daniel Sanders7e527422014-07-10 13:38:23 +00006017 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006018 }
6019
6020 return false;
6021}
6022
Jack Carter0b744b32012-10-04 02:29:46 +00006023bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006024 // This returns false if this function recognizes the directive
6025 // regardless of whether it is successfully handles or reports an
6026 // error. Otherwise it returns true to give the generic parser a
6027 // chance at recognizing it.
6028
Rafael Espindola961d4692014-11-11 05:18:41 +00006029 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006030 StringRef IDVal = DirectiveID.getString();
6031
Nirav Dave996fc132016-05-05 14:15:46 +00006032 if (IDVal == ".cpload") {
6033 parseDirectiveCpLoad(DirectiveID.getLoc());
6034 return false;
6035 }
6036 if (IDVal == ".cprestore") {
6037 parseDirectiveCpRestore(DirectiveID.getLoc());
6038 return false;
6039 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006040 if (IDVal == ".dword") {
6041 parseDataDirective(8, DirectiveID.getLoc());
6042 return false;
6043 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006044 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006045 StringRef SymbolName;
6046
6047 if (Parser.parseIdentifier(SymbolName)) {
6048 reportParseError("expected identifier after .ent");
6049 return false;
6050 }
6051
6052 // There's an undocumented extension that allows an integer to
6053 // follow the name of the procedure which AFAICS is ignored by GAS.
6054 // Example: .ent foo,2
6055 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6056 if (getLexer().isNot(AsmToken::Comma)) {
6057 // Even though we accept this undocumented extension for compatibility
6058 // reasons, the additional integer argument does not actually change
6059 // the behaviour of the '.ent' directive, so we would like to discourage
6060 // its use. We do this by not referring to the extended version in
6061 // error messages which are not directly related to its use.
6062 reportParseError("unexpected token, expected end of statement");
6063 return false;
6064 }
6065 Parser.Lex(); // Eat the comma.
6066 const MCExpr *DummyNumber;
6067 int64_t DummyNumberVal;
6068 // If the user was explicitly trying to use the extended version,
6069 // we still give helpful extension-related error messages.
6070 if (Parser.parseExpression(DummyNumber)) {
6071 reportParseError("expected number after comma");
6072 return false;
6073 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006074 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006075 reportParseError("expected an absolute expression after comma");
6076 return false;
6077 }
6078 }
6079
6080 // If this is not the end of the statement, report an error.
6081 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6082 reportParseError("unexpected token, expected end of statement");
6083 return false;
6084 }
6085
Jim Grosbach6f482002015-05-18 18:43:14 +00006086 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006087
6088 getTargetStreamer().emitDirectiveEnt(*Sym);
6089 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006090 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006091 return false;
6092 }
6093
Jack Carter07c818d2013-01-25 01:31:34 +00006094 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006095 StringRef SymbolName;
6096
6097 if (Parser.parseIdentifier(SymbolName)) {
6098 reportParseError("expected identifier after .end");
6099 return false;
6100 }
6101
6102 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6103 reportParseError("unexpected token, expected end of statement");
6104 return false;
6105 }
6106
6107 if (CurrentFn == nullptr) {
6108 reportParseError(".end used without .ent");
6109 return false;
6110 }
6111
6112 if ((SymbolName != CurrentFn->getName())) {
6113 reportParseError(".end symbol does not match .ent symbol");
6114 return false;
6115 }
6116
6117 getTargetStreamer().emitDirectiveEnd(SymbolName);
6118 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006119 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006120 return false;
6121 }
6122
Jack Carter07c818d2013-01-25 01:31:34 +00006123 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006124 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6125 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006126 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006127 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6128 reportParseError("expected stack register");
6129 return false;
6130 }
6131
6132 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6133 if (!StackRegOpnd.isGPRAsmReg()) {
6134 reportParseError(StackRegOpnd.getStartLoc(),
6135 "expected general purpose register");
6136 return false;
6137 }
6138 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6139
6140 if (Parser.getTok().is(AsmToken::Comma))
6141 Parser.Lex();
6142 else {
6143 reportParseError("unexpected token, expected comma");
6144 return false;
6145 }
6146
6147 // Parse the frame size.
6148 const MCExpr *FrameSize;
6149 int64_t FrameSizeVal;
6150
6151 if (Parser.parseExpression(FrameSize)) {
6152 reportParseError("expected frame size value");
6153 return false;
6154 }
6155
Jim Grosbach13760bd2015-05-30 01:25:56 +00006156 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006157 reportParseError("frame size not an absolute expression");
6158 return false;
6159 }
6160
6161 if (Parser.getTok().is(AsmToken::Comma))
6162 Parser.Lex();
6163 else {
6164 reportParseError("unexpected token, expected comma");
6165 return false;
6166 }
6167
6168 // Parse the return register.
6169 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006170 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006171 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6172 reportParseError("expected return register");
6173 return false;
6174 }
6175
6176 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6177 if (!ReturnRegOpnd.isGPRAsmReg()) {
6178 reportParseError(ReturnRegOpnd.getStartLoc(),
6179 "expected general purpose register");
6180 return false;
6181 }
6182
6183 // If this is not the end of the statement, report an error.
6184 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6185 reportParseError("unexpected token, expected end of statement");
6186 return false;
6187 }
6188
6189 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6190 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006191 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006192 return false;
6193 }
6194
Jack Carter07c818d2013-01-25 01:31:34 +00006195 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006196 parseDirectiveSet();
6197 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006198 }
6199
Daniel Sandersd97a6342014-08-13 10:07:34 +00006200 if (IDVal == ".mask" || IDVal == ".fmask") {
6201 // .mask bitmask, frame_offset
6202 // bitmask: One bit for each register used.
6203 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6204 // first register is expected to be saved.
6205 // Examples:
6206 // .mask 0x80000000, -4
6207 // .fmask 0x80000000, -4
6208 //
Jack Carterbe332172012-09-07 00:48:02 +00006209
Daniel Sandersd97a6342014-08-13 10:07:34 +00006210 // Parse the bitmask
6211 const MCExpr *BitMask;
6212 int64_t BitMaskVal;
6213
6214 if (Parser.parseExpression(BitMask)) {
6215 reportParseError("expected bitmask value");
6216 return false;
6217 }
6218
Jim Grosbach13760bd2015-05-30 01:25:56 +00006219 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006220 reportParseError("bitmask not an absolute expression");
6221 return false;
6222 }
6223
6224 if (Parser.getTok().is(AsmToken::Comma))
6225 Parser.Lex();
6226 else {
6227 reportParseError("unexpected token, expected comma");
6228 return false;
6229 }
6230
6231 // Parse the frame_offset
6232 const MCExpr *FrameOffset;
6233 int64_t FrameOffsetVal;
6234
6235 if (Parser.parseExpression(FrameOffset)) {
6236 reportParseError("expected frame offset value");
6237 return false;
6238 }
6239
Jim Grosbach13760bd2015-05-30 01:25:56 +00006240 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006241 reportParseError("frame offset not an absolute expression");
6242 return false;
6243 }
6244
6245 // If this is not the end of the statement, report an error.
6246 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6247 reportParseError("unexpected token, expected end of statement");
6248 return false;
6249 }
6250
6251 if (IDVal == ".mask")
6252 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6253 else
6254 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006255 return false;
6256 }
6257
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006258 if (IDVal == ".nan")
6259 return parseDirectiveNaN();
6260
Jack Carter07c818d2013-01-25 01:31:34 +00006261 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006262 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006263 return false;
6264 }
6265
Rafael Espindolab59fb732014-03-28 18:50:26 +00006266 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006267 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006268 return false;
6269 }
6270
Jack Carter07c818d2013-01-25 01:31:34 +00006271 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006272 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006273 return false;
6274 }
6275
Scott Egertond1aeb052016-02-15 16:11:51 +00006276 if (IDVal == ".hword") {
6277 parseDataDirective(2, DirectiveID.getLoc());
6278 return false;
6279 }
6280
Nirav Dave996fc132016-05-05 14:15:46 +00006281 if (IDVal == ".option") {
6282 parseDirectiveOption();
6283 return false;
6284 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006285
6286 if (IDVal == ".abicalls") {
6287 getTargetStreamer().emitDirectiveAbiCalls();
6288 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006289 Error(Parser.getTok().getLoc(),
6290 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006291 // Clear line
6292 Parser.eatToEndOfStatement();
6293 }
6294 return false;
6295 }
6296
Nirav Dave996fc132016-05-05 14:15:46 +00006297 if (IDVal == ".cpsetup") {
6298 parseDirectiveCPSetup();
6299 return false;
6300 }
6301 if (IDVal == ".cpreturn") {
6302 parseDirectiveCPReturn();
6303 return false;
6304 }
6305 if (IDVal == ".module") {
6306 parseDirectiveModule();
6307 return false;
6308 }
6309 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6310 parseInternalDirectiveReallowModule();
6311 return false;
6312 }
6313 if (IDVal == ".insn") {
6314 parseInsnDirective();
6315 return false;
6316 }
6317 if (IDVal == ".sbss") {
6318 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6319 return false;
6320 }
6321 if (IDVal == ".sdata") {
6322 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6323 return false;
6324 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006325
Rafael Espindola870c4e92012-01-11 03:56:41 +00006326 return true;
6327}
6328
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006329bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6330 // If this is not the end of the statement, report an error.
6331 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6332 reportParseError("unexpected token, expected end of statement");
6333 return false;
6334 }
6335
6336 getTargetStreamer().reallowModuleDirective();
6337
6338 getParser().Lex(); // Eat EndOfStatement token.
6339 return false;
6340}
6341
Rafael Espindola870c4e92012-01-11 03:56:41 +00006342extern "C" void LLVMInitializeMipsAsmParser() {
6343 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6344 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6345 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6346 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6347}
Jack Carterb4dbc172012-09-05 23:34:03 +00006348
6349#define GET_REGISTER_MATCHER
6350#define GET_MATCHER_IMPLEMENTATION
6351#include "MipsGenAsmMatcher.inc"