blob: 353e679391dbb515d422e56cec48501657447863 [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
Jack Carterdc1e35d2012-09-06 20:00:02 +0000306 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000307
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000308 bool eatComma(StringRef ErrorStr);
309
Jack Carter1ac53222013-02-20 23:11:17 +0000310 int matchCPURegisterName(StringRef Symbol);
311
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000312 int matchHWRegsRegisterName(StringRef Symbol);
313
Jack Carter873c7242013-01-12 01:03:14 +0000314 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000315
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000316 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000317
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000318 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000319
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000320 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000321
Jack Carter5dc8ac92013-09-25 23:50:44 +0000322 int matchMSA128RegisterName(StringRef Name);
323
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000324 int matchMSA128CtrlRegisterName(StringRef Name);
325
Jack Carterd0bd6422013-04-18 00:41:53 +0000326 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000327
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000328 unsigned getGPR(int RegNo);
329
Toma Tabacu89a712b2015-04-15 10:48:56 +0000330 /// Returns the internal register number for the current AT. Also checks if
331 /// the current AT is unavailable (set to $0) and gives an error if it is.
332 /// This should be used in pseudo-instruction expansions which need AT.
333 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000334
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000335 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
336 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000337
338 // Helper function that checks if the value of a vector index is within the
339 // boundaries of accepted values for each RegisterKind
340 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
341 bool validateMSAIndex(int Val, int RegKind);
342
Daniel Sandersf0df2212014-08-04 12:20:00 +0000343 // Selects a new architecture by updating the FeatureBits with the necessary
344 // info including implied dependencies.
345 // Internally, it clears all the feature bits related to *any* architecture
346 // and selects the new one using the ToggleFeature functionality of the
347 // MCSubtargetInfo object that handles implied dependencies. The reason we
348 // clear all the arch related bits manually is because ToggleFeature only
349 // clears the features that imply the feature being cleared and not the
350 // features implied by the feature being cleared. This is easier to see
351 // with an example:
352 // --------------------------------------------------
353 // | Feature | Implies |
354 // | -------------------------------------------------|
355 // | FeatureMips1 | None |
356 // | FeatureMips2 | FeatureMips1 |
357 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
358 // | FeatureMips4 | FeatureMips3 |
359 // | ... | |
360 // --------------------------------------------------
361 //
362 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
363 // FeatureMipsGP64 | FeatureMips1)
364 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
365 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000366 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000367 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000368 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
369 STI.setFeatureBits(FeatureBits);
370 setAvailableFeatures(
371 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000372 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000373 }
374
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000375 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000376 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000377 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000378 setAvailableFeatures(
379 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000380 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000381 }
382 }
383
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000384 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000385 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000386 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000387 setAvailableFeatures(
388 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000389 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000390 }
391 }
392
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000393 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
394 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000395 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000396 }
397
398 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
399 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000400 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000401 }
402
Rafael Espindola870c4e92012-01-11 03:56:41 +0000403public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000404 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000405 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000406#define GET_OPERAND_DIAGNOSTIC_TYPES
407#include "MipsGenAsmMatcher.inc"
408#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000409 };
410
Akira Hatanakab11ef082015-11-14 06:35:56 +0000411 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000412 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000413 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000414 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
415 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000416 MCAsmParserExtension::Initialize(parser);
417
Toma Tabacu11e14a92015-04-21 11:50:52 +0000418 parser.addAliasForDirective(".asciiz", ".asciz");
419
Jack Carterb4dbc172012-09-05 23:34:03 +0000420 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000421 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000422
Toma Tabacu9db22db2014-09-09 10:15:38 +0000423 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000424 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000425 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000426
Toma Tabacu9db22db2014-09-09 10:15:38 +0000427 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000428 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000429 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000430
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000431 getTargetStreamer().updateABIInfo(*this);
432
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000433 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000434 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000435
436 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000437
Daniel Sandersa6994442015-08-18 12:33:54 +0000438 IsPicEnabled =
439 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
440
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000441 IsCpRestoreSet = false;
442 CpRestoreOffset = -1;
443
Daniel Sanders50f17232015-09-15 16:17:27 +0000444 Triple TheTriple(sti.getTargetTriple());
445 if ((TheTriple.getArch() == Triple::mips) ||
446 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000447 IsLittleEndian = false;
448 else
449 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000450 }
451
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000452 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
453 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
454
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000455 bool isGP64bit() const {
456 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
457 }
458 bool isFP64bit() const {
459 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
460 }
Eric Christophera5762812015-01-26 17:33:46 +0000461 const MipsABIInfo &getABI() const { return ABI; }
462 bool isABI_N32() const { return ABI.IsN32(); }
463 bool isABI_N64() const { return ABI.IsN64(); }
464 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000465 bool isABI_FPXX() const {
466 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
467 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000468
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000469 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000470 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000471 }
472
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000473 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000474 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000475 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000476 bool hasMips1() const {
477 return getSTI().getFeatureBits()[Mips::FeatureMips1];
478 }
479 bool hasMips2() const {
480 return getSTI().getFeatureBits()[Mips::FeatureMips2];
481 }
482 bool hasMips3() const {
483 return getSTI().getFeatureBits()[Mips::FeatureMips3];
484 }
485 bool hasMips4() const {
486 return getSTI().getFeatureBits()[Mips::FeatureMips4];
487 }
488 bool hasMips5() const {
489 return getSTI().getFeatureBits()[Mips::FeatureMips5];
490 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000491 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000492 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000493 }
494 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000495 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000496 }
497 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000498 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000499 }
500 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000501 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000502 }
Daniel Sanders17793142015-02-18 16:24:50 +0000503 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000504 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000505 }
506 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000507 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000508 }
509 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000510 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000511 }
512 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000513 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000514 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000515 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000516 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000517 }
518 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000519 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000520 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000521
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000522 bool hasDSP() const {
523 return getSTI().getFeatureBits()[Mips::FeatureDSP];
524 }
525 bool hasDSPR2() const {
526 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
527 }
528 bool hasDSPR3() const {
529 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
530 }
531 bool hasMSA() const {
532 return getSTI().getFeatureBits()[Mips::FeatureMSA];
533 }
Kai Nackee0245392015-01-27 19:11:28 +0000534 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000535 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000536 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000537
Daniel Sandersa6994442015-08-18 12:33:54 +0000538 bool inPicMode() {
539 return IsPicEnabled;
540 }
541
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000542 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000543 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000544 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000545
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000546 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000547 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000548 }
549
Eric Christophere8ae3e32015-05-07 23:10:21 +0000550 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000551 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000552 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000553
Toma Tabacud9d344b2015-04-27 14:05:04 +0000554 /// Warn if RegIndex is the same as the current AT.
555 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000556
557 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000558
559 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000560};
561}
562
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000563namespace {
564
565/// MipsOperand - Instances of this class represent a parsed Mips machine
566/// instruction.
567class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000568public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000569 /// Broad categories of register classes
570 /// The exact class is finalized by the render method.
571 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000572 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000573 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000574 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000575 RegKind_FCC = 4, /// FCC
576 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
577 RegKind_MSACtrl = 16, /// MSA control registers
578 RegKind_COP2 = 32, /// COP2
579 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
580 /// context).
581 RegKind_CCR = 128, /// CCR
582 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000583 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000584 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000585 /// Potentially any (e.g. $1)
586 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
587 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000588 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000589 };
590
591private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000592 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000593 k_Immediate, /// An immediate (possibly involving symbol references)
594 k_Memory, /// Base + Offset Memory Address
595 k_PhysRegister, /// A physical register from the Mips namespace
596 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000597 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000598 k_RegList, /// A physical register list
599 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000600 } Kind;
601
David Blaikie960ea3f2014-06-08 16:18:35 +0000602public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000603 MipsOperand(KindTy K, MipsAsmParser &Parser)
604 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
605
David Blaikie960ea3f2014-06-08 16:18:35 +0000606private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000607 /// For diagnostics, and checking the assembler temporary
608 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000609
Eric Christopher8996c5d2013-03-15 00:42:55 +0000610 struct Token {
611 const char *Data;
612 unsigned Length;
613 };
614
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000615 struct PhysRegOp {
616 unsigned Num; /// Register Number
617 };
618
619 struct RegIdxOp {
620 unsigned Index; /// Index into the register class
621 RegKind Kind; /// Bitfield of the kinds it could possibly be
622 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000623 };
624
625 struct ImmOp {
626 const MCExpr *Val;
627 };
628
629 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000630 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000631 const MCExpr *Off;
632 };
633
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000634 struct RegListOp {
635 SmallVector<unsigned, 10> *List;
636 };
637
Jack Carterb4dbc172012-09-05 23:34:03 +0000638 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000639 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000640 struct PhysRegOp PhysReg;
641 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000642 struct ImmOp Imm;
643 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000644 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000645 };
646
647 SMLoc StartLoc, EndLoc;
648
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000649 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000650 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
651 const MCRegisterInfo *RegInfo,
652 SMLoc S, SMLoc E,
653 MipsAsmParser &Parser) {
654 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000655 Op->RegIdx.Index = Index;
656 Op->RegIdx.RegInfo = RegInfo;
657 Op->RegIdx.Kind = RegKind;
658 Op->StartLoc = S;
659 Op->EndLoc = E;
660 return Op;
661 }
662
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000663public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000664 /// Coerce the register to GPR32 and return the real register for the current
665 /// target.
666 unsigned getGPR32Reg() const {
667 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000668 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000669 unsigned ClassID = Mips::GPR32RegClassID;
670 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000671 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000672
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000673 /// Coerce the register to GPR32 and return the real register for the current
674 /// target.
675 unsigned getGPRMM16Reg() const {
676 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
677 unsigned ClassID = Mips::GPR32RegClassID;
678 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
679 }
680
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000681 /// Coerce the register to GPR64 and return the real register for the current
682 /// target.
683 unsigned getGPR64Reg() const {
684 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
685 unsigned ClassID = Mips::GPR64RegClassID;
686 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000687 }
688
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000689private:
690 /// Coerce the register to AFGR64 and return the real register for the current
691 /// target.
692 unsigned getAFGR64Reg() const {
693 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
694 if (RegIdx.Index % 2 != 0)
695 AsmParser.Warning(StartLoc, "Float register should be even.");
696 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
697 .getRegister(RegIdx.Index / 2);
698 }
699
700 /// Coerce the register to FGR64 and return the real register for the current
701 /// target.
702 unsigned getFGR64Reg() const {
703 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
704 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
705 .getRegister(RegIdx.Index);
706 }
707
708 /// Coerce the register to FGR32 and return the real register for the current
709 /// target.
710 unsigned getFGR32Reg() const {
711 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
712 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
713 .getRegister(RegIdx.Index);
714 }
715
716 /// Coerce the register to FGRH32 and return the real register for the current
717 /// target.
718 unsigned getFGRH32Reg() const {
719 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
720 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
721 .getRegister(RegIdx.Index);
722 }
723
724 /// Coerce the register to FCC and return the real register for the current
725 /// target.
726 unsigned getFCCReg() const {
727 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
728 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
729 .getRegister(RegIdx.Index);
730 }
731
732 /// Coerce the register to MSA128 and return the real register for the current
733 /// target.
734 unsigned getMSA128Reg() const {
735 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
736 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
737 // identical
738 unsigned ClassID = Mips::MSA128BRegClassID;
739 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
740 }
741
742 /// Coerce the register to MSACtrl and return the real register for the
743 /// current target.
744 unsigned getMSACtrlReg() const {
745 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
746 unsigned ClassID = Mips::MSACtrlRegClassID;
747 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
748 }
749
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000750 /// Coerce the register to COP0 and return the real register for the
751 /// current target.
752 unsigned getCOP0Reg() const {
753 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
754 unsigned ClassID = Mips::COP0RegClassID;
755 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
756 }
757
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000758 /// Coerce the register to COP2 and return the real register for the
759 /// current target.
760 unsigned getCOP2Reg() const {
761 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
762 unsigned ClassID = Mips::COP2RegClassID;
763 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
764 }
765
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000766 /// Coerce the register to COP3 and return the real register for the
767 /// current target.
768 unsigned getCOP3Reg() const {
769 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
770 unsigned ClassID = Mips::COP3RegClassID;
771 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
772 }
773
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000774 /// Coerce the register to ACC64DSP and return the real register for the
775 /// current target.
776 unsigned getACC64DSPReg() const {
777 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
778 unsigned ClassID = Mips::ACC64DSPRegClassID;
779 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
780 }
781
782 /// Coerce the register to HI32DSP and return the real register for the
783 /// current target.
784 unsigned getHI32DSPReg() const {
785 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
786 unsigned ClassID = Mips::HI32DSPRegClassID;
787 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
788 }
789
790 /// Coerce the register to LO32DSP and return the real register for the
791 /// current target.
792 unsigned getLO32DSPReg() const {
793 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
794 unsigned ClassID = Mips::LO32DSPRegClassID;
795 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
796 }
797
798 /// Coerce the register to CCR and return the real register for the
799 /// current target.
800 unsigned getCCRReg() const {
801 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
802 unsigned ClassID = Mips::CCRRegClassID;
803 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
804 }
805
806 /// Coerce the register to HWRegs and return the real register for the
807 /// current target.
808 unsigned getHWRegsReg() const {
809 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
810 unsigned ClassID = Mips::HWRegsRegClassID;
811 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
812 }
813
814public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000815 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000816 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000817 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000818 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000819 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000820 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000821 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000822 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000823 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000824
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000825 void addRegOperands(MCInst &Inst, unsigned N) const {
826 llvm_unreachable("Use a custom parser instead");
827 }
828
Daniel Sanders21bce302014-04-01 12:35:23 +0000829 /// Render the operand to an MCInst as a GPR32
830 /// Asserts if the wrong number of operands are requested, or the operand
831 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000832 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
833 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000834 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000835 }
836
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000837 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
838 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000839 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000840 }
841
Jozef Kolek1904fa22014-11-24 14:25:53 +0000842 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
843 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000844 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000845 }
846
Zoran Jovanovic41688672015-02-10 16:36:20 +0000847 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
848 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000849 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000850 }
851
Daniel Sanders21bce302014-04-01 12:35:23 +0000852 /// Render the operand to an MCInst as a GPR64
853 /// Asserts if the wrong number of operands are requested, or the operand
854 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000855 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
856 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000857 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000858 }
859
860 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
861 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000862 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000863 }
864
865 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
866 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000867 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000868 }
869
870 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
871 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000872 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000873 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000874 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000875 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
876 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000877 }
878
879 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
880 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000881 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000882 }
883
884 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
885 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000886 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000887 }
888
889 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
890 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000891 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000892 }
893
894 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
895 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000896 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000897 }
898
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000899 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
900 assert(N == 1 && "Invalid number of operands!");
901 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
902 }
903
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000904 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
905 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000906 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000907 }
908
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000909 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
910 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000911 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000912 }
913
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000914 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
915 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000916 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000917 }
918
919 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
920 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000921 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000922 }
923
924 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
925 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000926 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000927 }
928
929 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
930 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000931 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000932 }
933
934 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
935 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000936 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000937 }
938
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000939 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000940 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
941 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000942 uint64_t Imm = getConstantImm() - Offset;
943 Imm &= (1 << Bits) - 1;
944 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000945 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000946 Inst.addOperand(MCOperand::createImm(Imm));
947 }
948
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000949 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +0000950 void addSImmOperands(MCInst &Inst, unsigned N) const {
951 if (isImm() && !isConstantImm()) {
952 addExpr(Inst, getImm());
953 return;
954 }
955 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
956 }
957
958 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000959 void addUImmOperands(MCInst &Inst, unsigned N) const {
960 if (isImm() && !isConstantImm()) {
961 addExpr(Inst, getImm());
962 return;
963 }
964 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
965 }
966
Daniel Sanders78e89022016-03-11 11:37:50 +0000967 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
968 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
969 assert(N == 1 && "Invalid number of operands!");
970 int64_t Imm = getConstantImm() - Offset;
971 Imm = SignExtend64<Bits>(Imm);
972 Imm += Offset;
973 Imm += AdjustOffset;
974 Inst.addOperand(MCOperand::createImm(Imm));
975 }
976
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000977 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000978 assert(N == 1 && "Invalid number of operands!");
979 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000980 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000981 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000982
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000983 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000984 assert(N == 2 && "Invalid number of operands!");
985
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000986 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
987 ? getMemBase()->getGPR64Reg()
988 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000989
990 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000991 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000992 }
993
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000994 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
995 assert(N == 2 && "Invalid number of operands!");
996
Jim Grosbache9119e42015-05-13 18:37:00 +0000997 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000998
999 const MCExpr *Expr = getMemOff();
1000 addExpr(Inst, Expr);
1001 }
1002
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001003 void addRegListOperands(MCInst &Inst, unsigned N) const {
1004 assert(N == 1 && "Invalid number of operands!");
1005
1006 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001007 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001008 }
1009
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001010 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1011 assert(N == 2 && "Invalid number of operands!");
1012 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +00001013 Inst.addOperand(MCOperand::createReg(RegNo++));
1014 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001015 }
1016
Zoran Jovanovic41688672015-02-10 16:36:20 +00001017 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1018 assert(N == 2 && "Invalid number of operands!");
1019 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001020 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001021 }
1022
Craig Topper56c590a2014-04-29 07:58:02 +00001023 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001024 // As a special case until we sort out the definition of div/divu, pretend
1025 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1026 if (isGPRAsmReg() && RegIdx.Index == 0)
1027 return true;
1028
1029 return Kind == k_PhysRegister;
1030 }
1031 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001032 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001033 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +00001034 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001035 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001036 bool isConstantImmz() const {
1037 return isConstantImm() && getConstantImm() == 0;
1038 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001039 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1040 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1041 }
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001042 template <unsigned Bits> bool isSImm() const {
1043 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1044 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001045 template <unsigned Bits> bool isUImm() const {
1046 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1047 }
1048 template <unsigned Bits> bool isAnyImm() const {
1049 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1050 isUInt<Bits>(getConstantImm()))
1051 : isImm();
1052 }
Daniel Sanders78e89022016-03-11 11:37:50 +00001053 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1054 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001055 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001056 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1057 return isConstantImm() && getConstantImm() >= Bottom &&
1058 getConstantImm() <= Top;
1059 }
Craig Topper56c590a2014-04-29 07:58:02 +00001060 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001061 // Note: It's not possible to pretend that other operand kinds are tokens.
1062 // The matcher emitter checks tokens first.
1063 return Kind == k_Token;
1064 }
Craig Topper56c590a2014-04-29 07:58:02 +00001065 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001066 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001067 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001068 }
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001069 template <unsigned Bits, unsigned ShiftAmount = 0>
1070 bool isMemWithSimmOffset() const {
1071 return isMem() && isConstantMemOff() &&
1072 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff()) &&
1073 getMemBase()->isGPRAsmReg();
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001074 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001075 bool isMemWithGRPMM16Base() const {
1076 return isMem() && getMemBase()->isMM16AsmReg();
1077 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001078 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1079 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1080 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1081 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001082 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1083 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1084 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1085 && (getMemBase()->getGPR32Reg() == Mips::SP);
1086 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001087 template <unsigned Bits, unsigned ShiftLeftAmount>
1088 bool isScaledUImm() const {
1089 return isConstantImm() &&
1090 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001091 }
Daniel Sanders97297772016-03-22 14:40:00 +00001092 template <unsigned Bits, unsigned ShiftLeftAmount>
1093 bool isScaledSImm() const {
1094 return isConstantImm() &&
1095 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
1096 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001097 bool isRegList16() const {
1098 if (!isRegList())
1099 return false;
1100
1101 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001102 if (Size < 2 || Size > 5)
1103 return false;
1104
1105 unsigned R0 = RegList.List->front();
1106 unsigned R1 = RegList.List->back();
1107 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1108 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001109 return false;
1110
1111 int PrevReg = *RegList.List->begin();
1112 for (int i = 1; i < Size - 1; i++) {
1113 int Reg = (*(RegList.List))[i];
1114 if ( Reg != PrevReg + 1)
1115 return false;
1116 PrevReg = Reg;
1117 }
1118
1119 return true;
1120 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001121 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001122 bool isLSAImm() const {
1123 if (!isConstantImm())
1124 return false;
1125 int64_t Val = getConstantImm();
1126 return 1 <= Val && Val <= 4;
1127 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001128 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001129 bool isMovePRegPair() const {
1130 if (Kind != k_RegList || RegList.List->size() != 2)
1131 return false;
1132
1133 unsigned R0 = RegList.List->front();
1134 unsigned R1 = RegList.List->back();
1135
1136 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1137 (R0 == Mips::A1 && R1 == Mips::A3) ||
1138 (R0 == Mips::A2 && R1 == Mips::A3) ||
1139 (R0 == Mips::A0 && R1 == Mips::S5) ||
1140 (R0 == Mips::A0 && R1 == Mips::S6) ||
1141 (R0 == Mips::A0 && R1 == Mips::A1) ||
1142 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljanb43d4bc2016-04-25 15:34:57 +00001143 (R0 == Mips::A0 && R1 == Mips::A3))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001144 return true;
1145
1146 return false;
1147 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001148
1149 StringRef getToken() const {
1150 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001151 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001152 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001153 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001154
Craig Topper56c590a2014-04-29 07:58:02 +00001155 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001156 // As a special case until we sort out the definition of div/divu, pretend
1157 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1158 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1159 RegIdx.Kind & RegKind_GPR)
1160 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001161
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001162 assert(Kind == k_PhysRegister && "Invalid access!");
1163 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001164 }
1165
Jack Carterb4dbc172012-09-05 23:34:03 +00001166 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001167 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001168 return Imm.Val;
1169 }
1170
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001171 int64_t getConstantImm() const {
1172 const MCExpr *Val = getImm();
1173 return static_cast<const MCConstantExpr *>(Val)->getValue();
1174 }
1175
1176 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001177 assert((Kind == k_Memory) && "Invalid access!");
1178 return Mem.Base;
1179 }
1180
1181 const MCExpr *getMemOff() const {
1182 assert((Kind == k_Memory) && "Invalid access!");
1183 return Mem.Off;
1184 }
1185
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001186 int64_t getConstantMemOff() const {
1187 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1188 }
1189
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001190 const SmallVectorImpl<unsigned> &getRegList() const {
1191 assert((Kind == k_RegList) && "Invalid access!");
1192 return *(RegList.List);
1193 }
1194
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001195 unsigned getRegPair() const {
1196 assert((Kind == k_RegPair) && "Invalid access!");
1197 return RegIdx.Index;
1198 }
1199
David Blaikie960ea3f2014-06-08 16:18:35 +00001200 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1201 MipsAsmParser &Parser) {
1202 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001203 Op->Tok.Data = Str.data();
1204 Op->Tok.Length = Str.size();
1205 Op->StartLoc = S;
1206 Op->EndLoc = S;
1207 return Op;
1208 }
1209
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001210 /// Create a numeric register (e.g. $1). The exact register remains
1211 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001212 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001213 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001214 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001215 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001216 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001217 }
1218
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001219 /// Create a register that is definitely a GPR.
1220 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001221 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001222 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001223 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001224 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001225 }
1226
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001227 /// Create a register that is definitely a FGR.
1228 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001229 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001230 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001231 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001232 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1233 }
1234
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001235 /// Create a register that is definitely a HWReg.
1236 /// This is typically only used for named registers such as $hwr_cpunum.
1237 static std::unique_ptr<MipsOperand>
1238 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1239 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1240 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1241 }
1242
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001243 /// Create a register that is definitely an FCC.
1244 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001245 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001246 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001247 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001248 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1249 }
1250
1251 /// Create a register that is definitely an ACC.
1252 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001253 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001254 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001255 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001256 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1257 }
1258
1259 /// Create a register that is definitely an MSA128.
1260 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001261 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001262 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001263 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001264 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1265 }
1266
1267 /// Create a register that is definitely an MSACtrl.
1268 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001269 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001270 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001271 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001272 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1273 }
1274
David Blaikie960ea3f2014-06-08 16:18:35 +00001275 static std::unique_ptr<MipsOperand>
1276 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1277 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001278 Op->Imm.Val = Val;
1279 Op->StartLoc = S;
1280 Op->EndLoc = E;
1281 return Op;
1282 }
1283
David Blaikie960ea3f2014-06-08 16:18:35 +00001284 static std::unique_ptr<MipsOperand>
1285 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1286 SMLoc E, MipsAsmParser &Parser) {
1287 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1288 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001289 Op->Mem.Off = Off;
1290 Op->StartLoc = S;
1291 Op->EndLoc = E;
1292 return Op;
1293 }
1294
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001295 static std::unique_ptr<MipsOperand>
1296 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1297 MipsAsmParser &Parser) {
1298 assert (Regs.size() > 0 && "Empty list not allowed");
1299
1300 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001301 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001302 Op->StartLoc = StartLoc;
1303 Op->EndLoc = EndLoc;
1304 return Op;
1305 }
1306
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001307 static std::unique_ptr<MipsOperand>
1308 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1309 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1310 Op->RegIdx.Index = RegNo;
1311 Op->StartLoc = S;
1312 Op->EndLoc = E;
1313 return Op;
1314 }
1315
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001316 bool isGPRAsmReg() const {
1317 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001318 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001319 bool isMM16AsmReg() const {
1320 if (!(isRegIdx() && RegIdx.Kind))
1321 return false;
1322 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1323 || RegIdx.Index == 16 || RegIdx.Index == 17);
1324 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001325 bool isMM16AsmRegZero() const {
1326 if (!(isRegIdx() && RegIdx.Kind))
1327 return false;
1328 return (RegIdx.Index == 0 ||
1329 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1330 RegIdx.Index == 17);
1331 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001332 bool isMM16AsmRegMoveP() const {
1333 if (!(isRegIdx() && RegIdx.Kind))
1334 return false;
1335 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1336 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1337 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001338 bool isFGRAsmReg() const {
1339 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1340 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001341 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001342 bool isHWRegsAsmReg() const {
1343 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001344 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001345 bool isCCRAsmReg() const {
1346 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001347 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001348 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001349 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1350 return false;
1351 if (!AsmParser.hasEightFccRegisters())
1352 return RegIdx.Index == 0;
1353 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001354 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001355 bool isACCAsmReg() const {
1356 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001357 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001358 bool isCOP0AsmReg() const {
1359 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1360 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001361 bool isCOP2AsmReg() const {
1362 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001363 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001364 bool isCOP3AsmReg() const {
1365 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1366 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001367 bool isMSA128AsmReg() const {
1368 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001369 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001370 bool isMSACtrlAsmReg() const {
1371 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001372 }
1373
Jack Carterb4dbc172012-09-05 23:34:03 +00001374 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001375 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001376 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001377 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001378
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001379 virtual ~MipsOperand() {
1380 switch (Kind) {
1381 case k_Immediate:
1382 break;
1383 case k_Memory:
1384 delete Mem.Base;
1385 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001386 case k_RegList:
1387 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001388 case k_PhysRegister:
1389 case k_RegisterIndex:
1390 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001391 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001392 break;
1393 }
1394 }
1395
Craig Topper56c590a2014-04-29 07:58:02 +00001396 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001397 switch (Kind) {
1398 case k_Immediate:
1399 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001400 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001401 OS << ">";
1402 break;
1403 case k_Memory:
1404 OS << "Mem<";
1405 Mem.Base->print(OS);
1406 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001407 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001408 OS << ">";
1409 break;
1410 case k_PhysRegister:
1411 OS << "PhysReg<" << PhysReg.Num << ">";
1412 break;
1413 case k_RegisterIndex:
1414 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1415 break;
1416 case k_Token:
1417 OS << Tok.Data;
1418 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001419 case k_RegList:
1420 OS << "RegList< ";
1421 for (auto Reg : (*RegList.List))
1422 OS << Reg << " ";
1423 OS << ">";
1424 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001425 case k_RegPair:
1426 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1427 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001428 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001429 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001430}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001431} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001432
Jack Carter9e65aa32013-03-22 00:05:30 +00001433namespace llvm {
1434extern const MCInstrDesc MipsInsts[];
1435}
1436static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1437 return MipsInsts[Opcode];
1438}
1439
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001440static bool hasShortDelaySlot(unsigned Opcode) {
1441 switch (Opcode) {
1442 case Mips::JALS_MM:
1443 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001444 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001445 case Mips::BGEZALS_MM:
1446 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001447 return true;
1448 default:
1449 return false;
1450 }
1451}
1452
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001453static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1454 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1455 return &SRExpr->getSymbol();
1456 }
1457
1458 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1459 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1460 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1461
1462 if (LHSSym)
1463 return LHSSym;
1464
1465 if (RHSSym)
1466 return RHSSym;
1467
1468 return nullptr;
1469 }
1470
1471 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1472 return getSingleMCSymbol(UExpr->getSubExpr());
1473
1474 return nullptr;
1475}
1476
1477static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1478 if (isa<MCSymbolRefExpr>(Expr))
1479 return 1;
1480
1481 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1482 return countMCSymbolRefExpr(BExpr->getLHS()) +
1483 countMCSymbolRefExpr(BExpr->getRHS());
1484
1485 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1486 return countMCSymbolRefExpr(UExpr->getSubExpr());
1487
1488 return 0;
1489}
1490
Jack Carter9e65aa32013-03-22 00:05:30 +00001491bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001492 MCStreamer &Out,
1493 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001494 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001495 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001496 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001497
Jack Carter9e65aa32013-03-22 00:05:30 +00001498 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001499
1500 if (MCID.isBranch() || MCID.isCall()) {
1501 const unsigned Opcode = Inst.getOpcode();
1502 MCOperand Offset;
1503
1504 switch (Opcode) {
1505 default:
1506 break;
Kai Nackee0245392015-01-27 19:11:28 +00001507 case Mips::BBIT0:
1508 case Mips::BBIT032:
1509 case Mips::BBIT1:
1510 case Mips::BBIT132:
1511 assert(hasCnMips() && "instruction only valid for octeon cpus");
1512 // Fall through
1513
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001514 case Mips::BEQ:
1515 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001516 case Mips::BEQ_MM:
1517 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001518 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001519 Offset = Inst.getOperand(2);
1520 if (!Offset.isImm())
1521 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001522 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001523 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001524 if (OffsetToAlignment(Offset.getImm(),
1525 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001526 return Error(IDLoc, "branch to misaligned address");
1527 break;
1528 case Mips::BGEZ:
1529 case Mips::BGTZ:
1530 case Mips::BLEZ:
1531 case Mips::BLTZ:
1532 case Mips::BGEZAL:
1533 case Mips::BLTZAL:
1534 case Mips::BC1F:
1535 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001536 case Mips::BGEZ_MM:
1537 case Mips::BGTZ_MM:
1538 case Mips::BLEZ_MM:
1539 case Mips::BLTZ_MM:
1540 case Mips::BGEZAL_MM:
1541 case Mips::BLTZAL_MM:
1542 case Mips::BC1F_MM:
1543 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001544 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001545 Offset = Inst.getOperand(1);
1546 if (!Offset.isImm())
1547 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001548 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001549 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001550 if (OffsetToAlignment(Offset.getImm(),
1551 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001552 return Error(IDLoc, "branch to misaligned address");
1553 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001554 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001555 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001556 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001557 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001558 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1559 Offset = Inst.getOperand(1);
1560 if (!Offset.isImm())
1561 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001562 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001563 return Error(IDLoc, "branch target out of range");
1564 if (OffsetToAlignment(Offset.getImm(), 2LL))
1565 return Error(IDLoc, "branch to misaligned address");
1566 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001567 }
1568 }
1569
Daniel Sandersa84989a2014-06-16 13:25:35 +00001570 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1571 // We still accept it but it is a normal nop.
1572 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1573 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1574 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1575 "nop instruction");
1576 }
1577
Kai Nackee0245392015-01-27 19:11:28 +00001578 if (hasCnMips()) {
1579 const unsigned Opcode = Inst.getOpcode();
1580 MCOperand Opnd;
1581 int Imm;
1582
1583 switch (Opcode) {
1584 default:
1585 break;
1586
1587 case Mips::BBIT0:
1588 case Mips::BBIT032:
1589 case Mips::BBIT1:
1590 case Mips::BBIT132:
1591 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1592 // The offset is handled above
1593 Opnd = Inst.getOperand(1);
1594 if (!Opnd.isImm())
1595 return Error(IDLoc, "expected immediate operand kind");
1596 Imm = Opnd.getImm();
1597 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1598 Opcode == Mips::BBIT1 ? 63 : 31))
1599 return Error(IDLoc, "immediate operand value out of range");
1600 if (Imm > 31) {
1601 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1602 : Mips::BBIT132);
1603 Inst.getOperand(1).setImm(Imm - 32);
1604 }
1605 break;
1606
Kai Nackee0245392015-01-27 19:11:28 +00001607 case Mips::SEQi:
1608 case Mips::SNEi:
1609 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1610 Opnd = Inst.getOperand(2);
1611 if (!Opnd.isImm())
1612 return Error(IDLoc, "expected immediate operand kind");
1613 Imm = Opnd.getImm();
1614 if (!isInt<10>(Imm))
1615 return Error(IDLoc, "immediate operand value out of range");
1616 break;
1617 }
1618 }
1619
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001620 // This expansion is not in a function called by tryExpandInstruction()
1621 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001622 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1623 inPicMode()) {
1624 warnIfNoMacro(IDLoc);
1625
1626 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1627
1628 // We can do this expansion if there's only 1 symbol in the argument
1629 // expression.
1630 if (countMCSymbolRefExpr(JalExpr) > 1)
1631 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1632
1633 // FIXME: This is checking the expression can be handled by the later stages
1634 // of the assembler. We ought to leave it to those later stages but
1635 // we can't do that until we stop evaluateRelocExpr() rewriting the
1636 // expressions into non-equivalent forms.
1637 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1638
1639 // FIXME: Add support for label+offset operands (currently causes an error).
1640 // FIXME: Add support for forward-declared local symbols.
1641 // FIXME: Add expansion for when the LargeGOT option is enabled.
1642 if (JalSym->isInSection() || JalSym->isTemporary()) {
1643 if (isABI_O32()) {
1644 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001645 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001646 // R_(MICRO)MIPS_GOT16 label
1647 // addiu $25, $25, 0
1648 // R_(MICRO)MIPS_LO16 label
1649 // jalr $25
1650 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1651 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1652
Daniel Sandersa736b372016-04-29 13:33:12 +00001653 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1654 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1655 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1656 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001657 } else if (isABI_N32() || isABI_N64()) {
1658 // If it's a local symbol and the N32/N64 ABIs are being used,
1659 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001660 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001661 // R_(MICRO)MIPS_GOT_DISP label
1662 // jalr $25
1663 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1664
Daniel Sandersa736b372016-04-29 13:33:12 +00001665 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1666 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1667 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001668 }
1669 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001670 // If it's an external/weak symbol, we expand to:
1671 // lw/ld $25, 0($gp)
1672 // R_(MICRO)MIPS_CALL16 label
1673 // jalr $25
1674 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001675
Daniel Sandersa736b372016-04-29 13:33:12 +00001676 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1677 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001678 }
1679
1680 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001681 if (IsCpRestoreSet && inMicroMipsMode())
1682 JalrInst.setOpcode(Mips::JALRS_MM);
1683 else
1684 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001685 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1686 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1687
1688 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1689 // This relocation is supposed to be an optimization hint for the linker
1690 // and is not necessary for correctness.
1691
1692 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001693 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001694 }
1695
Jack Carter9e65aa32013-03-22 00:05:30 +00001696 if (MCID.mayLoad() || MCID.mayStore()) {
1697 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001698 // reference or immediate we may have to expand instructions.
1699 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001700 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001701 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1702 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001703 MCOperand &Op = Inst.getOperand(i);
1704 if (Op.isImm()) {
1705 int MemOffset = Op.getImm();
1706 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001707 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001708 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001709 return false;
1710 }
1711 } else if (Op.isExpr()) {
1712 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001713 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001714 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001715 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001716 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001717 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001718 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001719 return false;
1720 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001721 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001722 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001723 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001724 }
1725 }
1726 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001727 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001728 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001729
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001730 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001731 if (MCID.mayLoad()) {
1732 // Try to create 16-bit GP relative load instruction.
1733 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1734 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1735 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1736 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1737 MCOperand &Op = Inst.getOperand(i);
1738 if (Op.isImm()) {
1739 int MemOffset = Op.getImm();
1740 MCOperand &DstReg = Inst.getOperand(0);
1741 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001742 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001743 getContext().getRegisterInfo()->getRegClass(
1744 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001745 (BaseReg.getReg() == Mips::GP ||
1746 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001747
Daniel Sandersa736b372016-04-29 13:33:12 +00001748 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1749 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001750 return false;
1751 }
1752 }
1753 }
1754 } // for
1755 } // if load
1756
1757 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1758
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001759 MCOperand Opnd;
1760 int Imm;
1761
1762 switch (Inst.getOpcode()) {
1763 default:
1764 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001765 case Mips::ADDIUSP_MM:
1766 Opnd = Inst.getOperand(0);
1767 if (!Opnd.isImm())
1768 return Error(IDLoc, "expected immediate operand kind");
1769 Imm = Opnd.getImm();
1770 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1771 Imm % 4 != 0)
1772 return Error(IDLoc, "immediate operand value out of range");
1773 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001774 case Mips::SLL16_MM:
1775 case Mips::SRL16_MM:
1776 Opnd = Inst.getOperand(2);
1777 if (!Opnd.isImm())
1778 return Error(IDLoc, "expected immediate operand kind");
1779 Imm = Opnd.getImm();
1780 if (Imm < 1 || Imm > 8)
1781 return Error(IDLoc, "immediate operand value out of range");
1782 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001783 case Mips::LI16_MM:
1784 Opnd = Inst.getOperand(1);
1785 if (!Opnd.isImm())
1786 return Error(IDLoc, "expected immediate operand kind");
1787 Imm = Opnd.getImm();
1788 if (Imm < -1 || Imm > 126)
1789 return Error(IDLoc, "immediate operand value out of range");
1790 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001791 case Mips::ADDIUR2_MM:
1792 Opnd = Inst.getOperand(2);
1793 if (!Opnd.isImm())
1794 return Error(IDLoc, "expected immediate operand kind");
1795 Imm = Opnd.getImm();
1796 if (!(Imm == 1 || Imm == -1 ||
1797 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1798 return Error(IDLoc, "immediate operand value out of range");
1799 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001800 case Mips::ANDI16_MM:
1801 Opnd = Inst.getOperand(2);
1802 if (!Opnd.isImm())
1803 return Error(IDLoc, "expected immediate operand kind");
1804 Imm = Opnd.getImm();
1805 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1806 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1807 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1808 return Error(IDLoc, "immediate operand value out of range");
1809 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001810 case Mips::LBU16_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 > 14)
1816 return Error(IDLoc, "immediate operand value out of range");
1817 break;
1818 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001819 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001820 Opnd = Inst.getOperand(2);
1821 if (!Opnd.isImm())
1822 return Error(IDLoc, "expected immediate operand kind");
1823 Imm = Opnd.getImm();
1824 if (Imm < 0 || Imm > 15)
1825 return Error(IDLoc, "immediate operand value out of range");
1826 break;
1827 case Mips::LHU16_MM:
1828 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001829 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001830 Opnd = Inst.getOperand(2);
1831 if (!Opnd.isImm())
1832 return Error(IDLoc, "expected immediate operand kind");
1833 Imm = Opnd.getImm();
1834 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1835 return Error(IDLoc, "immediate operand value out of range");
1836 break;
1837 case Mips::LW16_MM:
1838 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001839 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001840 Opnd = Inst.getOperand(2);
1841 if (!Opnd.isImm())
1842 return Error(IDLoc, "expected immediate operand kind");
1843 Imm = Opnd.getImm();
1844 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1845 return Error(IDLoc, "immediate operand value out of range");
1846 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001847 case Mips::ADDIUPC_MM:
1848 MCOperand Opnd = Inst.getOperand(1);
1849 if (!Opnd.isImm())
1850 return Error(IDLoc, "expected immediate operand kind");
1851 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001852 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001853 return Error(IDLoc, "immediate operand value out of range");
1854 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001855 }
1856 }
1857
Daniel Sandersd8c07762016-04-18 12:35:36 +00001858 bool FillDelaySlot =
1859 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
1860 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00001861 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001862
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001863 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001864 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001865 switch (ExpandResult) {
1866 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001867 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001868 break;
1869 case MER_Success:
1870 break;
1871 case MER_Fail:
1872 return true;
1873 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001874
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001875 // If this instruction has a delay slot and .set reorder is active,
1876 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00001877 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001878 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
1879 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001880 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001881
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001882 if ((Inst.getOpcode() == Mips::JalOneReg ||
1883 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1884 isPicAndNotNxxAbi()) {
1885 if (IsCpRestoreSet) {
1886 // We need a NOP between the JALR and the LW:
1887 // If .set reorder has been used, we've already emitted a NOP.
1888 // If .set noreorder has been used, we need to emit a NOP at this point.
1889 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00001890 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
1891 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001892
1893 // Load the $gp from the stack.
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001894 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001895 IDLoc, Out, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001896 } else
1897 Warning(IDLoc, "no .cprestore used in PIC mode");
1898 }
1899
Jack Carter9e65aa32013-03-22 00:05:30 +00001900 return false;
1901}
1902
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001903MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001904MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
1905 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001906 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001907 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001908 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001909 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001910 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001911 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001912 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001913 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001914 case Mips::LoadAddrImm64:
1915 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1916 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1917 "expected immediate operand kind");
1918
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001919 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1920 Inst.getOperand(1),
1921 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001922 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001923 ? MER_Fail
1924 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001925 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001926 case Mips::LoadAddrReg64:
1927 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1928 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1929 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1930 "expected immediate operand kind");
1931
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001932 return expandLoadAddress(Inst.getOperand(0).getReg(),
1933 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1934 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001935 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001936 ? MER_Fail
1937 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001938 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001939 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001940 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
1941 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001942 case Mips::SWM_MM:
1943 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001944 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
1945 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001946 case Mips::JalOneReg:
1947 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001948 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00001949 case Mips::BneImm:
1950 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001951 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00001952 case Mips::BLT:
1953 case Mips::BLE:
1954 case Mips::BGE:
1955 case Mips::BGT:
1956 case Mips::BLTU:
1957 case Mips::BLEU:
1958 case Mips::BGEU:
1959 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001960 case Mips::BLTL:
1961 case Mips::BLEL:
1962 case Mips::BGEL:
1963 case Mips::BGTL:
1964 case Mips::BLTUL:
1965 case Mips::BLEUL:
1966 case Mips::BGEUL:
1967 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00001968 case Mips::BLTImmMacro:
1969 case Mips::BLEImmMacro:
1970 case Mips::BGEImmMacro:
1971 case Mips::BGTImmMacro:
1972 case Mips::BLTUImmMacro:
1973 case Mips::BLEUImmMacro:
1974 case Mips::BGEUImmMacro:
1975 case Mips::BGTUImmMacro:
1976 case Mips::BLTLImmMacro:
1977 case Mips::BLELImmMacro:
1978 case Mips::BGELImmMacro:
1979 case Mips::BGTLImmMacro:
1980 case Mips::BLTULImmMacro:
1981 case Mips::BLEULImmMacro:
1982 case Mips::BGEULImmMacro:
1983 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001984 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001985 case Mips::SDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001986 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
1987 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001988 case Mips::DSDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001989 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
1990 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001991 case Mips::UDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001992 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
1993 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001994 case Mips::DUDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001995 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
1996 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00001997 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001998 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
1999 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002000 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002001 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002002 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002003 case Mips::PseudoTRUNC_W_D:
2004 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2005 : MER_Success;
2006 case Mips::Ulh:
2007 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2008 case Mips::Ulhu:
2009 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2010 case Mips::Ulw:
2011 return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2012 case Mips::NORImm:
2013 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002014 case Mips::ADDi:
2015 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002016 case Mips::SLTi:
2017 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002018 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2019 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2020 int64_t ImmValue = Inst.getOperand(2).getImm();
2021 if (isInt<16>(ImmValue))
2022 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002023 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2024 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002025 }
2026 return MER_NotAMacro;
2027 case Mips::ANDi:
2028 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002029 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002030 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2031 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2032 int64_t ImmValue = Inst.getOperand(2).getImm();
2033 if (isUInt<16>(ImmValue))
2034 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002035 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2036 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002037 }
2038 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002039 case Mips::ROL:
2040 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002041 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002042 case Mips::ROLImm:
2043 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002044 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002045 case Mips::DROL:
2046 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002047 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002048 case Mips::DROLImm:
2049 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002050 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002051 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002052 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002053 }
Jack Carter30a59822012-10-04 04:03:53 +00002054}
Jack Carter92995f12012-10-06 00:53:28 +00002055
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002056bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002057 MCStreamer &Out,
2058 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002059 MipsTargetStreamer &TOut = getTargetStreamer();
2060
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002061 // Create a JALR instruction which is going to replace the pseudo-JAL.
2062 MCInst JalrInst;
2063 JalrInst.setLoc(IDLoc);
2064 const MCOperand FirstRegOp = Inst.getOperand(0);
2065 const unsigned Opcode = Inst.getOpcode();
2066
2067 if (Opcode == Mips::JalOneReg) {
2068 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002069 if (IsCpRestoreSet && inMicroMipsMode()) {
2070 JalrInst.setOpcode(Mips::JALRS16_MM);
2071 JalrInst.addOperand(FirstRegOp);
2072 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002073 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002074 JalrInst.addOperand(FirstRegOp);
2075 } else {
2076 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002077 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002078 JalrInst.addOperand(FirstRegOp);
2079 }
2080 } else if (Opcode == Mips::JalTwoReg) {
2081 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002082 if (IsCpRestoreSet && inMicroMipsMode())
2083 JalrInst.setOpcode(Mips::JALRS_MM);
2084 else
2085 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002086 JalrInst.addOperand(FirstRegOp);
2087 const MCOperand SecondRegOp = Inst.getOperand(1);
2088 JalrInst.addOperand(SecondRegOp);
2089 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002090 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002091
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002092 // If .set reorder is active and branch instruction has a delay slot,
2093 // emit a NOP after it.
2094 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002095 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2096 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2097 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002098
2099 return false;
2100}
2101
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002102/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002103template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002104 unsigned BitNum = findFirstSet(x);
2105
2106 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2107}
2108
2109/// Load (or add) an immediate into a register.
2110///
2111/// @param ImmValue The immediate to load.
2112/// @param DstReg The register that will hold the immediate.
2113/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2114/// for a simple initialization.
2115/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2116/// @param IsAddress True if the immediate represents an address. False if it
2117/// is an integer.
2118/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002119bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002120 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002121 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2122 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002123 MipsTargetStreamer &TOut = getTargetStreamer();
2124
Toma Tabacu00e98672015-05-01 12:19:27 +00002125 if (!Is32BitImm && !isGP64bit()) {
2126 Error(IDLoc, "instruction requires a 64-bit architecture");
2127 return true;
2128 }
2129
Daniel Sanders03f9c012015-07-14 12:24:22 +00002130 if (Is32BitImm) {
2131 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2132 // Sign extend up to 64-bit so that the predicates match the hardware
2133 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2134 // true.
2135 ImmValue = SignExtend64<32>(ImmValue);
2136 } else {
2137 Error(IDLoc, "instruction requires a 32-bit immediate");
2138 return true;
2139 }
2140 }
2141
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002142 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2143 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2144
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002145 bool UseSrcReg = false;
2146 if (SrcReg != Mips::NoRegister)
2147 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002148
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002149 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002150 if (UseSrcReg &&
2151 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002152 // At this point we need AT to perform the expansions and we exit if it is
2153 // not available.
2154 unsigned ATReg = getATReg(IDLoc);
2155 if (!ATReg)
2156 return true;
2157 TmpReg = ATReg;
2158 }
2159
Daniel Sanders03f9c012015-07-14 12:24:22 +00002160 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002161 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002162 SrcReg = ZeroReg;
2163
2164 // This doesn't quite follow the usual ABI expectations for N32 but matches
2165 // traditional assembler behaviour. N32 would normally use addiu for both
2166 // integers and addresses.
2167 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002168 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002169 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002170 }
2171
Daniel Sandersa736b372016-04-29 13:33:12 +00002172 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002173 return false;
2174 }
2175
2176 if (isUInt<16>(ImmValue)) {
2177 unsigned TmpReg = DstReg;
2178 if (SrcReg == DstReg) {
2179 TmpReg = getATReg(IDLoc);
2180 if (!TmpReg)
2181 return true;
2182 }
2183
Daniel Sandersa736b372016-04-29 13:33:12 +00002184 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002185 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002186 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002187 return false;
2188 }
2189
2190 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002191 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002192
Toma Tabacu79588102015-04-29 10:19:56 +00002193 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2194 uint16_t Bits15To0 = ImmValue & 0xffff;
2195
Toma Tabacua3d056f2015-05-15 09:42:11 +00002196 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002197 // Traditional behaviour seems to special case this particular value. It's
2198 // not clear why other masks are handled differently.
2199 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002200 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2201 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002202 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002203 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002204 return false;
2205 }
2206
2207 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002208 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002209 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2210 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002211 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002212 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002213 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002214 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002215 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002216 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002217
Daniel Sandersa736b372016-04-29 13:33:12 +00002218 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002219 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002220 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002221 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002222 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002223 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002224 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002225
2226 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2227 if (Is32BitImm) {
2228 Error(IDLoc, "instruction requires a 32-bit immediate");
2229 return true;
2230 }
2231
2232 // Traditionally, these immediates are shifted as little as possible and as
2233 // such we align the most significant bit to bit 15 of our temporary.
2234 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2235 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2236 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2237 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002238 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2239 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002240
2241 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
2244 return false;
2245 }
2246
2247 warnIfNoMacro(IDLoc);
2248
2249 // The remaining case is packed with a sequence of dsll and ori with zeros
2250 // being omitted and any neighbouring dsll's being coalesced.
2251 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2252
2253 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2254 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002255 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002256 return false;
2257
2258 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2259 // skip it and defer the shift to the next chunk.
2260 unsigned ShiftCarriedForwards = 16;
2261 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2262 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2263
2264 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002265 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2266 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002267 ShiftCarriedForwards = 0;
2268 }
2269
2270 ShiftCarriedForwards += 16;
2271 }
2272 ShiftCarriedForwards -= 16;
2273
2274 // Finish any remaining shifts left by trailing zeros.
2275 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002276 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002277
2278 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002279 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002280
Matheus Almeida3813d572014-06-19 14:39:14 +00002281 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002282}
Jack Carter92995f12012-10-06 00:53:28 +00002283
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002284bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002285 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002286 const MCOperand &ImmOp = Inst.getOperand(1);
2287 assert(ImmOp.isImm() && "expected immediate operand kind");
2288 const MCOperand &DstRegOp = Inst.getOperand(0);
2289 assert(DstRegOp.isReg() && "expected register operand kind");
2290
2291 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002292 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002293 return true;
2294
2295 return false;
2296}
2297
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002298bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2299 const MCOperand &Offset,
2300 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002301 MCStreamer &Out,
2302 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002303 // la can't produce a usable address when addresses are 64-bit.
2304 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2305 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2306 // We currently can't do this because we depend on the equality
2307 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2308 Error(IDLoc, "la used to load 64-bit address");
2309 // Continue as if we had 'dla' instead.
2310 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002311 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002312
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002313 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002314 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002315 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002316 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002317 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002318
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002319 if (!Offset.isImm())
2320 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002321 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002322
Scott Egerton24557012016-01-21 15:11:01 +00002323 if (!ABI.ArePtrs64bit()) {
2324 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2325 Is32BitAddress = true;
2326 }
2327
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002328 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002329 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002330}
2331
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002332bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2333 unsigned DstReg, unsigned SrcReg,
2334 bool Is32BitSym, SMLoc IDLoc,
2335 MCStreamer &Out,
2336 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002337 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacu81496c12015-05-20 08:54:45 +00002338 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002339
Daniel Sandersd5a89412015-10-05 13:19:29 +00002340 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2341 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2342 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2343 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2344 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002345
Toma Tabacufb9d1252015-06-22 12:08:39 +00002346 bool UseSrcReg = SrcReg != Mips::NoRegister;
2347
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002348 // This is the 64-bit symbol address expansion.
2349 if (ABI.ArePtrs64bit() && isGP64bit()) {
2350 // We always need AT for the 64-bit expansion.
2351 // If it is not available we exit.
2352 unsigned ATReg = getATReg(IDLoc);
2353 if (!ATReg)
2354 return true;
2355
Daniel Sandersd5a89412015-10-05 13:19:29 +00002356 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2357 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2358 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2359 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002360
Scott Egerton24557012016-01-21 15:11:01 +00002361 if (UseSrcReg &&
2362 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2363 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002364 // If $rs is the same as $rd:
2365 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2366 // daddiu $at, $at, %higher(sym)
2367 // dsll $at, $at, 16
2368 // daddiu $at, $at, %hi(sym)
2369 // dsll $at, $at, 16
2370 // daddiu $at, $at, %lo(sym)
2371 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002372 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2373 STI);
2374 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2375 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2376 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2377 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2378 IDLoc, STI);
2379 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2380 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2381 IDLoc, STI);
2382 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002383
2384 return false;
2385 }
2386
2387 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2388 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2389 // lui $at, %hi(sym)
2390 // daddiu $rd, $rd, %higher(sym)
2391 // daddiu $at, $at, %lo(sym)
2392 // dsll32 $rd, $rd, 0
2393 // daddu $rd, $rd, $at
2394 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002395 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2396 STI);
2397 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2398 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2399 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2400 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2401 IDLoc, STI);
2402 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2403 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002404 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002405 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002406
2407 return false;
2408 }
2409
2410 // And now, the 32-bit symbol address expansion:
2411 // If $rs is the same as $rd:
2412 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2413 // ori $at, $at, %lo(sym)
2414 // addu $rd, $at, $rd
2415 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2416 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2417 // ori $rd, $rd, %lo(sym)
2418 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002419 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002420 if (UseSrcReg &&
2421 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002422 // If $rs is the same as $rd, we need to use AT.
2423 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002424 unsigned ATReg = getATReg(IDLoc);
2425 if (!ATReg)
2426 return true;
2427 TmpReg = ATReg;
2428 }
2429
Daniel Sandersa736b372016-04-29 13:33:12 +00002430 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2431 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2432 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002433
Toma Tabacufb9d1252015-06-22 12:08:39 +00002434 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002435 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002436 else
Scott Egerton24557012016-01-21 15:11:01 +00002437 assert(
2438 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002439
Toma Tabacu674825c2015-06-16 12:16:24 +00002440 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002441}
2442
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002443bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2444 MCStreamer &Out,
2445 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002446 MipsTargetStreamer &TOut = getTargetStreamer();
2447
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002448 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2449 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002450
2451 MCOperand Offset = Inst.getOperand(0);
2452 if (Offset.isExpr()) {
2453 Inst.clear();
2454 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002455 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2456 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2457 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002458 } else {
2459 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002460 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002461 // If offset fits into 11 bits then this instruction becomes microMIPS
2462 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002463 if (inMicroMipsMode())
2464 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002465 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002466 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002467 Error(IDLoc, "branch target out of range");
2468 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2469 Error(IDLoc, "branch to misaligned address");
2470 Inst.clear();
2471 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002472 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2473 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2474 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002475 }
2476 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002477 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002478
Zoran Jovanovicada70912015-09-07 11:56:37 +00002479 // If .set reorder is active and branch instruction has a delay slot,
2480 // emit a NOP after it.
2481 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2482 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002483 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002484
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002485 return false;
2486}
2487
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002488bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2489 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002490 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002491 const MCOperand &DstRegOp = Inst.getOperand(0);
2492 assert(DstRegOp.isReg() && "expected register operand kind");
2493
2494 const MCOperand &ImmOp = Inst.getOperand(1);
2495 assert(ImmOp.isImm() && "expected immediate operand kind");
2496
2497 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002498 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2499 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002500
2501 unsigned OpCode = 0;
2502 switch(Inst.getOpcode()) {
2503 case Mips::BneImm:
2504 OpCode = Mips::BNE;
2505 break;
2506 case Mips::BeqImm:
2507 OpCode = Mips::BEQ;
2508 break;
2509 default:
2510 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2511 break;
2512 }
2513
2514 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002515 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002516 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2517 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002518 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002519 warnIfNoMacro(IDLoc);
2520
2521 unsigned ATReg = getATReg(IDLoc);
2522 if (!ATReg)
2523 return true;
2524
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002525 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002526 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002527 return true;
2528
Daniel Sandersa736b372016-04-29 13:33:12 +00002529 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002530 }
2531 return false;
2532}
2533
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002534void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002535 const MCSubtargetInfo *STI, bool IsLoad,
2536 bool IsImmOpnd) {
2537 if (IsLoad) {
2538 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2539 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002540 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002541 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2542}
2543
2544void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2545 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2546 MipsTargetStreamer &TOut = getTargetStreamer();
2547
2548 unsigned DstReg = Inst.getOperand(0).getReg();
2549 unsigned BaseReg = Inst.getOperand(1).getReg();
2550
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002551 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002552 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2553 unsigned DstRegClassID =
2554 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2555 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2556 (DstRegClassID == Mips::GPR64RegClassID);
2557
2558 if (IsImmOpnd) {
2559 // Try to use DstReg as the temporary.
2560 if (IsGPR && (BaseReg != DstReg)) {
2561 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2562 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2563 STI);
2564 return;
2565 }
2566
Matheus Almeida7de68e72014-06-18 14:46:05 +00002567 // At this point we need AT to perform the expansions and we exit if it is
2568 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002569 unsigned ATReg = getATReg(IDLoc);
2570 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002571 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002572
2573 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2574 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2575 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002576 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002577
Daniel Sandersfba875f2016-04-29 13:43:45 +00002578 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
2579 MCOperand LoOperand =
2580 MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo"));
2581 MCOperand HiOperand =
2582 MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi"));
2583
2584 // Try to use DstReg as the temporary.
2585 if (IsGPR && (BaseReg != DstReg)) {
2586 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2587 LoOperand, DstReg, IDLoc, STI);
2588 return;
2589 }
2590
2591 // At this point we need AT to perform the expansions and we exit if it is
2592 // not available.
2593 unsigned ATReg = getATReg(IDLoc);
2594 if (!ATReg)
2595 return;
2596
2597 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2598 LoOperand, ATReg, IDLoc, STI);
2599}
2600
2601void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2602 const MCSubtargetInfo *STI,
2603 bool IsImmOpnd) {
2604 MipsTargetStreamer &TOut = getTargetStreamer();
2605
2606 unsigned SrcReg = Inst.getOperand(0).getReg();
2607 unsigned BaseReg = Inst.getOperand(1).getReg();
2608
2609 unsigned ATReg = getATReg(IDLoc);
2610 if (!ATReg)
2611 return;
2612
2613 if (IsImmOpnd) {
2614 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2615 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2616 return;
2617 }
2618
2619 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
2620 MCOperand LoOperand =
2621 MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo"));
2622 MCOperand HiOperand =
2623 MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi"));
2624 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2625 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002626}
2627
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002628bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2629 MCStreamer &Out,
2630 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002631 unsigned OpNum = Inst.getNumOperands();
2632 unsigned Opcode = Inst.getOpcode();
2633 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2634
2635 assert (Inst.getOperand(OpNum - 1).isImm() &&
2636 Inst.getOperand(OpNum - 2).isReg() &&
2637 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2638
2639 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2640 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002641 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2642 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2643 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2644 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002645 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002646 if (inMicroMipsMode() && hasMips32r6())
2647 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2648 else
2649 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2650 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002651
2652 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002653 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002654 return false;
2655}
2656
Toma Tabacu1a108322015-06-17 13:20:24 +00002657bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002658 MCStreamer &Out,
2659 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002660 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002661 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002662 unsigned PseudoOpcode = Inst.getOpcode();
2663 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002664 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002665 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2666
2667 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002668 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002669
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002670 unsigned TrgReg;
2671 if (TrgOp.isReg())
2672 TrgReg = TrgOp.getReg();
2673 else if (TrgOp.isImm()) {
2674 warnIfNoMacro(IDLoc);
2675 EmittedNoMacroWarning = true;
2676
2677 TrgReg = getATReg(IDLoc);
2678 if (!TrgReg)
2679 return true;
2680
2681 switch(PseudoOpcode) {
2682 default:
2683 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2684 case Mips::BLTImmMacro:
2685 PseudoOpcode = Mips::BLT;
2686 break;
2687 case Mips::BLEImmMacro:
2688 PseudoOpcode = Mips::BLE;
2689 break;
2690 case Mips::BGEImmMacro:
2691 PseudoOpcode = Mips::BGE;
2692 break;
2693 case Mips::BGTImmMacro:
2694 PseudoOpcode = Mips::BGT;
2695 break;
2696 case Mips::BLTUImmMacro:
2697 PseudoOpcode = Mips::BLTU;
2698 break;
2699 case Mips::BLEUImmMacro:
2700 PseudoOpcode = Mips::BLEU;
2701 break;
2702 case Mips::BGEUImmMacro:
2703 PseudoOpcode = Mips::BGEU;
2704 break;
2705 case Mips::BGTUImmMacro:
2706 PseudoOpcode = Mips::BGTU;
2707 break;
2708 case Mips::BLTLImmMacro:
2709 PseudoOpcode = Mips::BLTL;
2710 break;
2711 case Mips::BLELImmMacro:
2712 PseudoOpcode = Mips::BLEL;
2713 break;
2714 case Mips::BGELImmMacro:
2715 PseudoOpcode = Mips::BGEL;
2716 break;
2717 case Mips::BGTLImmMacro:
2718 PseudoOpcode = Mips::BGTL;
2719 break;
2720 case Mips::BLTULImmMacro:
2721 PseudoOpcode = Mips::BLTUL;
2722 break;
2723 case Mips::BLEULImmMacro:
2724 PseudoOpcode = Mips::BLEUL;
2725 break;
2726 case Mips::BGEULImmMacro:
2727 PseudoOpcode = Mips::BGEUL;
2728 break;
2729 case Mips::BGTULImmMacro:
2730 PseudoOpcode = Mips::BGTUL;
2731 break;
2732 }
2733
2734 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002735 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002736 return true;
2737 }
2738
Toma Tabacu1a108322015-06-17 13:20:24 +00002739 switch (PseudoOpcode) {
2740 case Mips::BLT:
2741 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002742 case Mips::BLTL:
2743 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002744 AcceptsEquality = false;
2745 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002746 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2747 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002748 ZeroSrcOpcode = Mips::BGTZ;
2749 ZeroTrgOpcode = Mips::BLTZ;
2750 break;
2751 case Mips::BLE:
2752 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002753 case Mips::BLEL:
2754 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002755 AcceptsEquality = true;
2756 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002757 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2758 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002759 ZeroSrcOpcode = Mips::BGEZ;
2760 ZeroTrgOpcode = Mips::BLEZ;
2761 break;
2762 case Mips::BGE:
2763 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002764 case Mips::BGEL:
2765 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002766 AcceptsEquality = true;
2767 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002768 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2769 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002770 ZeroSrcOpcode = Mips::BLEZ;
2771 ZeroTrgOpcode = Mips::BGEZ;
2772 break;
2773 case Mips::BGT:
2774 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002775 case Mips::BGTL:
2776 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002777 AcceptsEquality = false;
2778 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002779 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2780 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002781 ZeroSrcOpcode = Mips::BLTZ;
2782 ZeroTrgOpcode = Mips::BGTZ;
2783 break;
2784 default:
2785 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2786 }
2787
Toma Tabacu1a108322015-06-17 13:20:24 +00002788 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2789 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2790 if (IsSrcRegZero && IsTrgRegZero) {
2791 // FIXME: All of these Opcode-specific if's are needed for compatibility
2792 // with GAS' behaviour. However, they may not generate the most efficient
2793 // code in some circumstances.
2794 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002795 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2796 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002797 return false;
2798 }
2799 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002800 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2801 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002802 Warning(IDLoc, "branch is always taken");
2803 return false;
2804 }
2805 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002806 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2807 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002808 Warning(IDLoc, "branch is always taken");
2809 return false;
2810 }
2811 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002812 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2813 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002814 return false;
2815 }
2816 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002817 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2818 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002819 return false;
2820 }
2821 if (AcceptsEquality) {
2822 // If both registers are $0 and the pseudo-branch accepts equality, it
2823 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00002824 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2825 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002826 Warning(IDLoc, "branch is always taken");
2827 return false;
2828 }
2829 // If both registers are $0 and the pseudo-branch does not accept
2830 // equality, it will never be taken, so we don't have to emit anything.
2831 return false;
2832 }
2833 if (IsSrcRegZero || IsTrgRegZero) {
2834 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2835 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2836 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2837 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2838 // the pseudo-branch will never be taken, so we don't emit anything.
2839 // This only applies to unsigned pseudo-branches.
2840 return false;
2841 }
2842 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2843 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2844 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2845 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2846 // the pseudo-branch will always be taken, so we emit an unconditional
2847 // branch.
2848 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00002849 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2850 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002851 Warning(IDLoc, "branch is always taken");
2852 return false;
2853 }
2854 if (IsUnsigned) {
2855 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2856 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2857 // the pseudo-branch will be taken only when the non-zero register is
2858 // different from 0, so we emit a BNEZ.
2859 //
2860 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2861 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2862 // the pseudo-branch will be taken only when the non-zero register is
2863 // equal to 0, so we emit a BEQZ.
2864 //
2865 // Because only BLEU and BGEU branch on equality, we can use the
2866 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00002867 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2868 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2869 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002870 return false;
2871 }
2872 // If we have a signed pseudo-branch and one of the registers is $0,
2873 // we can use an appropriate compare-to-zero branch. We select which one
2874 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00002875 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2876 IsSrcRegZero ? TrgReg : SrcReg,
2877 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002878 return false;
2879 }
2880
2881 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2882 // expansions. If it is not available, we return.
2883 unsigned ATRegNum = getATReg(IDLoc);
2884 if (!ATRegNum)
2885 return true;
2886
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002887 if (!EmittedNoMacroWarning)
2888 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002889
2890 // SLT fits well with 2 of our 4 pseudo-branches:
2891 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2892 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2893 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2894 // This is accomplished by using a BNEZ with the result of the SLT.
2895 //
2896 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2897 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2898 // Because only BGE and BLE branch on equality, we can use the
2899 // AcceptsEquality variable to decide when to emit the BEQZ.
2900 // Note that the order of the SLT arguments doesn't change between
2901 // opposites.
2902 //
2903 // The same applies to the unsigned variants, except that SLTu is used
2904 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00002905 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2906 ReverseOrderSLT ? TrgReg : SrcReg,
2907 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002908
Daniel Sandersa736b372016-04-29 13:33:12 +00002909 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2910 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2911 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2912 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002913 return false;
2914}
2915
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002916bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2917 const MCSubtargetInfo *STI, const bool IsMips64,
2918 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002919 MipsTargetStreamer &TOut = getTargetStreamer();
2920
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002921 if (hasMips32r6()) {
2922 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2923 return false;
2924 }
2925
2926 warnIfNoMacro(IDLoc);
2927
2928 const MCOperand &RsRegOp = Inst.getOperand(0);
2929 assert(RsRegOp.isReg() && "expected register operand kind");
2930 unsigned RsReg = RsRegOp.getReg();
2931
2932 const MCOperand &RtRegOp = Inst.getOperand(1);
2933 assert(RtRegOp.isReg() && "expected register operand kind");
2934 unsigned RtReg = RtRegOp.getReg();
2935 unsigned DivOp;
2936 unsigned ZeroReg;
2937
2938 if (IsMips64) {
2939 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2940 ZeroReg = Mips::ZERO_64;
2941 } else {
2942 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2943 ZeroReg = Mips::ZERO;
2944 }
2945
2946 bool UseTraps = useTraps();
2947
2948 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2949 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2950 Warning(IDLoc, "dividing zero by zero");
2951 if (IsMips64) {
2952 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2953 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002954 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002955 return false;
2956 }
2957
Daniel Sandersa736b372016-04-29 13:33:12 +00002958 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002959 return false;
2960 }
2961 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00002962 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002963 return false;
2964 }
2965 }
2966
2967 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2968 Warning(IDLoc, "division by zero");
2969 if (Signed) {
2970 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002971 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002972 return false;
2973 }
2974
Daniel Sandersa736b372016-04-29 13:33:12 +00002975 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002976 return false;
2977 }
2978 }
2979
2980 // FIXME: The values for these two BranchTarget variables may be different in
2981 // micromips. These magic numbers need to be removed.
2982 unsigned BranchTargetNoTraps;
2983 unsigned BranchTarget;
2984
2985 if (UseTraps) {
2986 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00002987 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002988 } else {
2989 BranchTarget = IsMips64 ? 20 : 16;
2990 BranchTargetNoTraps = 8;
2991 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00002992 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002993 }
2994
Daniel Sandersa736b372016-04-29 13:33:12 +00002995 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002996
2997 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00002998 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002999
3000 if (!Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003001 TOut.emitR(Mips::MFLO, RsReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003002 return false;
3003 }
3004
3005 unsigned ATReg = getATReg(IDLoc);
3006 if (!ATReg)
3007 return true;
3008
Daniel Sandersa736b372016-04-29 13:33:12 +00003009 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003010 if (IsMips64) {
3011 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003012 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3013 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3014 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003015 } else {
3016 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003017 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3018 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003019 }
3020
3021 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003022 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003023 else {
3024 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003025 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3026 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3027 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003028 }
Daniel Sandersa736b372016-04-29 13:33:12 +00003029 TOut.emitR(Mips::MFLO, RsReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003030 return false;
3031}
3032
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003033bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003034 SMLoc IDLoc, MCStreamer &Out,
3035 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003036 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003037
3038 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3039 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3040 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3041
3042 unsigned FirstReg = Inst.getOperand(0).getReg();
3043 unsigned SecondReg = Inst.getOperand(1).getReg();
3044 unsigned ThirdReg = Inst.getOperand(2).getReg();
3045
3046 if (hasMips1() && !hasMips2()) {
3047 unsigned ATReg = getATReg(IDLoc);
3048 if (!ATReg)
3049 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003050 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3051 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3052 TOut.emitNop(IDLoc, STI);
3053 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3054 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3055 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3056 TOut.emitNop(IDLoc, STI);
3057 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3058 : Mips::CVT_W_S,
3059 FirstReg, SecondReg, IDLoc, STI);
3060 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3061 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003062 return false;
3063 }
3064
Daniel Sandersa736b372016-04-29 13:33:12 +00003065 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3066 : Mips::TRUNC_W_S,
3067 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003068
3069 return false;
3070}
3071
Daniel Sanders6394ee52015-10-15 14:52:58 +00003072bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003073 MCStreamer &Out, const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003074 MipsTargetStreamer &TOut = getTargetStreamer();
3075
Toma Tabacud88d79c2015-06-23 14:39:42 +00003076 if (hasMips32r6() || hasMips64r6()) {
3077 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3078 return false;
3079 }
3080
3081 warnIfNoMacro(IDLoc);
3082
3083 const MCOperand &DstRegOp = Inst.getOperand(0);
3084 assert(DstRegOp.isReg() && "expected register operand kind");
3085
3086 const MCOperand &SrcRegOp = Inst.getOperand(1);
3087 assert(SrcRegOp.isReg() && "expected register operand kind");
3088
3089 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3090 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3091
3092 unsigned DstReg = DstRegOp.getReg();
3093 unsigned SrcReg = SrcRegOp.getReg();
3094 int64_t OffsetValue = OffsetImmOp.getImm();
3095
3096 // NOTE: We always need AT for ULHU, as it is always used as the source
3097 // register for one of the LBu's.
3098 unsigned ATReg = getATReg(IDLoc);
3099 if (!ATReg)
3100 return true;
3101
3102 // When the value of offset+1 does not fit in 16 bits, we have to load the
3103 // offset in AT, (D)ADDu the original source register (if there was one), and
3104 // then use AT as the source register for the 2 generated LBu's.
3105 bool LoadedOffsetInAT = false;
3106 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3107 LoadedOffsetInAT = true;
3108
3109 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003110 true, IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003111 return true;
3112
3113 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3114 // because it will make our output more similar to GAS'. For example,
3115 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3116 // instead of just an "ori $1, $9, 32768".
3117 // NOTE: If there is no source register specified in the ULHU, the parser
3118 // will interpret it as $0.
3119 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003120 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003121 }
3122
3123 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3124 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3125 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3126
3127 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3128 if (isLittle()) {
3129 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3130 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3131 } else {
3132 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3133 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3134 }
3135
3136 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3137
Daniel Sandersa736b372016-04-29 13:33:12 +00003138 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3139 FirstLbuOffset, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003140
Daniel Sandersa736b372016-04-29 13:33:12 +00003141 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3142 STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003143
Daniel Sandersa736b372016-04-29 13:33:12 +00003144 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003145
Daniel Sandersa736b372016-04-29 13:33:12 +00003146 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003147
3148 return false;
3149}
3150
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003151bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3152 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003153 MipsTargetStreamer &TOut = getTargetStreamer();
3154
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003155 if (hasMips32r6() || hasMips64r6()) {
3156 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3157 return false;
3158 }
3159
3160 const MCOperand &DstRegOp = Inst.getOperand(0);
3161 assert(DstRegOp.isReg() && "expected register operand kind");
3162
3163 const MCOperand &SrcRegOp = Inst.getOperand(1);
3164 assert(SrcRegOp.isReg() && "expected register operand kind");
3165
3166 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3167 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3168
3169 unsigned SrcReg = SrcRegOp.getReg();
3170 int64_t OffsetValue = OffsetImmOp.getImm();
3171 unsigned ATReg = 0;
3172
3173 // When the value of offset+3 does not fit in 16 bits, we have to load the
3174 // offset in AT, (D)ADDu the original source register (if there was one), and
3175 // then use AT as the source register for the generated LWL and LWR.
3176 bool LoadedOffsetInAT = false;
3177 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3178 ATReg = getATReg(IDLoc);
3179 if (!ATReg)
3180 return true;
3181 LoadedOffsetInAT = true;
3182
3183 warnIfNoMacro(IDLoc);
3184
3185 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003186 true, IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003187 return true;
3188
3189 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3190 // because it will make our output more similar to GAS'. For example,
3191 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3192 // instead of just an "ori $1, $9, 32768".
3193 // NOTE: If there is no source register specified in the ULW, the parser
3194 // will interpret it as $0.
3195 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003196 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003197 }
3198
3199 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3200 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3201 if (isLittle()) {
3202 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3203 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3204 } else {
3205 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3206 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3207 }
3208
Daniel Sandersa736b372016-04-29 13:33:12 +00003209 TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3210 STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003211
Daniel Sandersa736b372016-04-29 13:33:12 +00003212 TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
3213 IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003214
3215 return false;
3216}
3217
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003218bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003219 MCStreamer &Out,
3220 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003221 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003222
3223 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3224 assert (Inst.getOperand(0).isReg() &&
3225 Inst.getOperand(1).isReg() &&
3226 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3227
3228 unsigned ATReg = Mips::NoRegister;
3229 unsigned FinalDstReg = Mips::NoRegister;
3230 unsigned DstReg = Inst.getOperand(0).getReg();
3231 unsigned SrcReg = Inst.getOperand(1).getReg();
3232 int64_t ImmValue = Inst.getOperand(2).getImm();
3233
3234 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3235
3236 unsigned FinalOpcode = Inst.getOpcode();
3237
3238 if (DstReg == SrcReg) {
3239 ATReg = getATReg(Inst.getLoc());
3240 if (!ATReg)
3241 return true;
3242 FinalDstReg = DstReg;
3243 DstReg = ATReg;
3244 }
3245
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003246 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003247 switch (FinalOpcode) {
3248 default:
3249 llvm_unreachable("unimplemented expansion");
3250 case (Mips::ADDi):
3251 FinalOpcode = Mips::ADD;
3252 break;
3253 case (Mips::ADDiu):
3254 FinalOpcode = Mips::ADDu;
3255 break;
3256 case (Mips::ANDi):
3257 FinalOpcode = Mips::AND;
3258 break;
3259 case (Mips::NORImm):
3260 FinalOpcode = Mips::NOR;
3261 break;
3262 case (Mips::ORi):
3263 FinalOpcode = Mips::OR;
3264 break;
3265 case (Mips::SLTi):
3266 FinalOpcode = Mips::SLT;
3267 break;
3268 case (Mips::SLTiu):
3269 FinalOpcode = Mips::SLTu;
3270 break;
3271 case (Mips::XORi):
3272 FinalOpcode = Mips::XOR;
3273 break;
3274 }
3275
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003276 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003277 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003278 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003279 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003280 return false;
3281 }
3282 return true;
3283}
3284
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003285bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3286 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003287 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003288 unsigned ATReg = Mips::NoRegister;
3289 unsigned DReg = Inst.getOperand(0).getReg();
3290 unsigned SReg = Inst.getOperand(1).getReg();
3291 unsigned TReg = Inst.getOperand(2).getReg();
3292 unsigned TmpReg = DReg;
3293
3294 unsigned FirstShift = Mips::NOP;
3295 unsigned SecondShift = Mips::NOP;
3296
3297 if (hasMips32r2()) {
3298
3299 if (DReg == SReg) {
3300 TmpReg = getATReg(Inst.getLoc());
3301 if (!TmpReg)
3302 return true;
3303 }
3304
3305 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003306 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3307 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003308 return false;
3309 }
3310
3311 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003312 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003313 return false;
3314 }
3315
3316 return true;
3317 }
3318
3319 if (hasMips32()) {
3320
3321 switch (Inst.getOpcode()) {
3322 default:
3323 llvm_unreachable("unexpected instruction opcode");
3324 case Mips::ROL:
3325 FirstShift = Mips::SRLV;
3326 SecondShift = Mips::SLLV;
3327 break;
3328 case Mips::ROR:
3329 FirstShift = Mips::SLLV;
3330 SecondShift = Mips::SRLV;
3331 break;
3332 }
3333
3334 ATReg = getATReg(Inst.getLoc());
3335 if (!ATReg)
3336 return true;
3337
Daniel Sandersa736b372016-04-29 13:33:12 +00003338 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3339 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3340 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3341 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003342
3343 return false;
3344 }
3345
3346 return true;
3347}
3348
3349bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003350 MCStreamer &Out,
3351 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003352 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003353 unsigned ATReg = Mips::NoRegister;
3354 unsigned DReg = Inst.getOperand(0).getReg();
3355 unsigned SReg = Inst.getOperand(1).getReg();
3356 int64_t ImmValue = Inst.getOperand(2).getImm();
3357
3358 unsigned FirstShift = Mips::NOP;
3359 unsigned SecondShift = Mips::NOP;
3360
3361 if (hasMips32r2()) {
3362
3363 if (Inst.getOpcode() == Mips::ROLImm) {
3364 uint64_t MaxShift = 32;
3365 uint64_t ShiftValue = ImmValue;
3366 if (ImmValue != 0)
3367 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003368 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003369 return false;
3370 }
3371
3372 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003373 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003374 return false;
3375 }
3376
3377 return true;
3378 }
3379
3380 if (hasMips32()) {
3381
3382 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003383 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003384 return false;
3385 }
3386
3387 switch (Inst.getOpcode()) {
3388 default:
3389 llvm_unreachable("unexpected instruction opcode");
3390 case Mips::ROLImm:
3391 FirstShift = Mips::SLL;
3392 SecondShift = Mips::SRL;
3393 break;
3394 case Mips::RORImm:
3395 FirstShift = Mips::SRL;
3396 SecondShift = Mips::SLL;
3397 break;
3398 }
3399
3400 ATReg = getATReg(Inst.getLoc());
3401 if (!ATReg)
3402 return true;
3403
Daniel Sandersa736b372016-04-29 13:33:12 +00003404 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3405 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3406 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003407
3408 return false;
3409 }
3410
3411 return true;
3412}
3413
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003414bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3415 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003416 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003417 unsigned ATReg = Mips::NoRegister;
3418 unsigned DReg = Inst.getOperand(0).getReg();
3419 unsigned SReg = Inst.getOperand(1).getReg();
3420 unsigned TReg = Inst.getOperand(2).getReg();
3421 unsigned TmpReg = DReg;
3422
3423 unsigned FirstShift = Mips::NOP;
3424 unsigned SecondShift = Mips::NOP;
3425
3426 if (hasMips64r2()) {
3427
3428 if (TmpReg == SReg) {
3429 TmpReg = getATReg(Inst.getLoc());
3430 if (!TmpReg)
3431 return true;
3432 }
3433
3434 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003435 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3436 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003437 return false;
3438 }
3439
3440 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003441 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003442 return false;
3443 }
3444
3445 return true;
3446 }
3447
3448 if (hasMips64()) {
3449
3450 switch (Inst.getOpcode()) {
3451 default:
3452 llvm_unreachable("unexpected instruction opcode");
3453 case Mips::DROL:
3454 FirstShift = Mips::DSRLV;
3455 SecondShift = Mips::DSLLV;
3456 break;
3457 case Mips::DROR:
3458 FirstShift = Mips::DSLLV;
3459 SecondShift = Mips::DSRLV;
3460 break;
3461 }
3462
3463 ATReg = getATReg(Inst.getLoc());
3464 if (!ATReg)
3465 return true;
3466
Daniel Sandersa736b372016-04-29 13:33:12 +00003467 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3468 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3469 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3470 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003471
3472 return false;
3473 }
3474
3475 return true;
3476}
3477
3478bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003479 MCStreamer &Out,
3480 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003481 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003482 unsigned ATReg = Mips::NoRegister;
3483 unsigned DReg = Inst.getOperand(0).getReg();
3484 unsigned SReg = Inst.getOperand(1).getReg();
3485 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3486
3487 unsigned FirstShift = Mips::NOP;
3488 unsigned SecondShift = Mips::NOP;
3489
3490 MCInst TmpInst;
3491
3492 if (hasMips64r2()) {
3493
3494 unsigned FinalOpcode = Mips::NOP;
3495 if (ImmValue == 0)
3496 FinalOpcode = Mips::DROTR;
3497 else if (ImmValue % 32 == 0)
3498 FinalOpcode = Mips::DROTR32;
3499 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3500 if (Inst.getOpcode() == Mips::DROLImm)
3501 FinalOpcode = Mips::DROTR32;
3502 else
3503 FinalOpcode = Mips::DROTR;
3504 } else if (ImmValue >= 33) {
3505 if (Inst.getOpcode() == Mips::DROLImm)
3506 FinalOpcode = Mips::DROTR;
3507 else
3508 FinalOpcode = Mips::DROTR32;
3509 }
3510
3511 uint64_t ShiftValue = ImmValue % 32;
3512 if (Inst.getOpcode() == Mips::DROLImm)
3513 ShiftValue = (32 - ImmValue % 32) % 32;
3514
Daniel Sandersa736b372016-04-29 13:33:12 +00003515 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003516
3517 return false;
3518 }
3519
3520 if (hasMips64()) {
3521
3522 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003523 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003524 return false;
3525 }
3526
3527 switch (Inst.getOpcode()) {
3528 default:
3529 llvm_unreachable("unexpected instruction opcode");
3530 case Mips::DROLImm:
3531 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3532 FirstShift = Mips::DSLL;
3533 SecondShift = Mips::DSRL32;
3534 }
3535 if (ImmValue == 32) {
3536 FirstShift = Mips::DSLL32;
3537 SecondShift = Mips::DSRL32;
3538 }
3539 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3540 FirstShift = Mips::DSLL32;
3541 SecondShift = Mips::DSRL;
3542 }
3543 break;
3544 case Mips::DRORImm:
3545 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3546 FirstShift = Mips::DSRL;
3547 SecondShift = Mips::DSLL32;
3548 }
3549 if (ImmValue == 32) {
3550 FirstShift = Mips::DSRL32;
3551 SecondShift = Mips::DSLL32;
3552 }
3553 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3554 FirstShift = Mips::DSRL32;
3555 SecondShift = Mips::DSLL;
3556 }
3557 break;
3558 }
3559
3560 ATReg = getATReg(Inst.getLoc());
3561 if (!ATReg)
3562 return true;
3563
Daniel Sandersa736b372016-04-29 13:33:12 +00003564 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3565 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3566 Inst.getLoc(), STI);
3567 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003568
3569 return false;
3570 }
3571
3572 return true;
3573}
3574
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003575bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3576 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003577 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003578 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3579 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3580
Daniel Sandersa736b372016-04-29 13:33:12 +00003581 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003582 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003583 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003584 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003585 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3586 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003587
3588 return false;
3589}
3590
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003591void MipsAsmParser::createCpRestoreMemOp(bool IsLoad, int StackOffset,
3592 SMLoc IDLoc, MCStreamer &Out,
3593 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003594 MipsTargetStreamer &TOut = getTargetStreamer();
3595
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003596 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003597 if (!isInt<16>(StackOffset)) {
3598 MCInst MemInst;
3599 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3600 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3601 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3602 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003603 expandMemInst(MemInst, IDLoc, Out, STI, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003604 return;
3605 }
3606
Daniel Sandersa736b372016-04-29 13:33:12 +00003607 TOut.emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset,
3608 IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003609}
3610
Matheus Almeida595fcab2014-06-11 15:05:56 +00003611unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3612 // As described by the Mips32r2 spec, the registers Rd and Rs for
3613 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00003614 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Matheus Almeida595fcab2014-06-11 15:05:56 +00003615 unsigned Opcode = Inst.getOpcode();
3616
Zlatko Buljanae720db2016-04-22 06:44:34 +00003617 if ((Opcode == Mips::JALR_HB || Opcode == Mips::JALRC_HB_MMR6) &&
Matheus Almeida595fcab2014-06-11 15:05:56 +00003618 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3619 return Match_RequiresDifferentSrcAndDst;
3620
3621 return Match_Success;
3622}
3623
Daniel Sanders52da7af2015-11-06 12:11:03 +00003624static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3625 uint64_t ErrorInfo) {
3626 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3627 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3628 if (ErrorLoc == SMLoc())
3629 return Loc;
3630 return ErrorLoc;
3631 }
3632 return Loc;
3633}
3634
David Blaikie960ea3f2014-06-08 16:18:35 +00003635bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3636 OperandVector &Operands,
3637 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003638 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003639 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003640
Jack Carterb4dbc172012-09-05 23:34:03 +00003641 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00003642 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003643 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003644
3645 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003646 case Match_Success: {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003647 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00003648 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003649 return false;
3650 }
3651 case Match_MissingFeature:
3652 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3653 return true;
3654 case Match_InvalidOperand: {
3655 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003656 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003657 if (ErrorInfo >= Operands.size())
3658 return Error(IDLoc, "too few operands for instruction");
3659
Daniel Sanders52da7af2015-11-06 12:11:03 +00003660 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003661 if (ErrorLoc == SMLoc())
3662 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003663 }
3664
3665 return Error(ErrorLoc, "invalid operand for instruction");
3666 }
3667 case Match_MnemonicFail:
3668 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003669 case Match_RequiresDifferentSrcAndDst:
3670 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003671 case Match_Immz:
3672 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003673 case Match_UImm1_0:
3674 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3675 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003676 case Match_UImm2_0:
3677 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3678 "expected 2-bit unsigned immediate");
3679 case Match_UImm2_1:
3680 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3681 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003682 case Match_UImm3_0:
3683 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3684 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003685 case Match_UImm4_0:
3686 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3687 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003688 case Match_SImm4_0:
3689 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3690 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003691 case Match_UImm5_0:
3692 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3693 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00003694 case Match_SImm5_0:
3695 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3696 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003697 case Match_UImm5_1:
3698 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3699 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003700 case Match_UImm5_32:
3701 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3702 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003703 case Match_UImm5_33:
3704 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3705 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003706 case Match_UImm5_0_Report_UImm6:
3707 // This is used on UImm5 operands that have a corresponding UImm5_32
3708 // operand to avoid confusing the user.
3709 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3710 "expected 6-bit unsigned immediate");
3711 case Match_UImm5_Lsl2:
3712 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3713 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003714 case Match_UImmRange2_64:
3715 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3716 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003717 case Match_UImm6_0:
3718 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3719 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00003720 case Match_UImm6_Lsl2:
3721 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3722 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00003723 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00003724 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3725 "expected 6-bit signed immediate");
3726 case Match_UImm7_0:
3727 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3728 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00003729 case Match_UImm7_N1:
3730 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3731 "expected immediate in range -1 .. 126");
3732 case Match_SImm7_Lsl2:
3733 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3734 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003735 case Match_UImm8_0:
3736 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3737 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003738 case Match_UImm10_0:
3739 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3740 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00003741 case Match_SImm10_0:
3742 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3743 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00003744 case Match_SImm11_0:
3745 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3746 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003747 case Match_UImm16:
3748 case Match_UImm16_Relaxed:
3749 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3750 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003751 case Match_SImm16:
3752 case Match_SImm16_Relaxed:
3753 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3754 "expected 16-bit signed immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003755 case Match_UImm20_0:
3756 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3757 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00003758 case Match_UImm26_0:
3759 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3760 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00003761 case Match_SImm32:
3762 case Match_SImm32_Relaxed:
3763 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3764 "expected 32-bit signed immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00003765 case Match_MemSImm9:
3766 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3767 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00003768 case Match_MemSImm10:
3769 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3770 "expected memory with 10-bit signed offset");
3771 case Match_MemSImm10Lsl1:
3772 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3773 "expected memory with 11-bit signed offset and multiple of 2");
3774 case Match_MemSImm10Lsl2:
3775 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3776 "expected memory with 12-bit signed offset and multiple of 4");
3777 case Match_MemSImm10Lsl3:
3778 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3779 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00003780 case Match_MemSImm11:
3781 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3782 "expected memory with 11-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003783 case Match_MemSImm16:
3784 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3785 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00003786 }
Craig Topper589ceee2015-01-03 08:16:34 +00003787
3788 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003789}
3790
Toma Tabacud9d344b2015-04-27 14:05:04 +00003791void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3792 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3793 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3794 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003795}
3796
Toma Tabacu81496c12015-05-20 08:54:45 +00003797void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3798 if (!AssemblerOptions.back()->isMacro())
3799 Warning(Loc, "macro instruction expanded into multiple instructions");
3800}
3801
Daniel Sandersef638fe2014-10-03 15:37:37 +00003802void
3803MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3804 SMRange Range, bool ShowColors) {
3805 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003806 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003807 ShowColors);
3808}
3809
Jack Carter1ac53222013-02-20 23:11:17 +00003810int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003811 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003812
Vladimir Medic4c299852013-11-06 11:27:05 +00003813 CC = StringSwitch<unsigned>(Name)
3814 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003815 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003816 .Case("a0", 4)
3817 .Case("a1", 5)
3818 .Case("a2", 6)
3819 .Case("a3", 7)
3820 .Case("v0", 2)
3821 .Case("v1", 3)
3822 .Case("s0", 16)
3823 .Case("s1", 17)
3824 .Case("s2", 18)
3825 .Case("s3", 19)
3826 .Case("s4", 20)
3827 .Case("s5", 21)
3828 .Case("s6", 22)
3829 .Case("s7", 23)
3830 .Case("k0", 26)
3831 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003832 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003833 .Case("sp", 29)
3834 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003835 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003836 .Case("ra", 31)
3837 .Case("t0", 8)
3838 .Case("t1", 9)
3839 .Case("t2", 10)
3840 .Case("t3", 11)
3841 .Case("t4", 12)
3842 .Case("t5", 13)
3843 .Case("t6", 14)
3844 .Case("t7", 15)
3845 .Case("t8", 24)
3846 .Case("t9", 25)
3847 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003848
Toma Tabacufda445c2014-09-15 15:33:01 +00003849 if (!(isABI_N32() || isABI_N64()))
3850 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003851
Daniel Sandersef638fe2014-10-03 15:37:37 +00003852 if (12 <= CC && CC <= 15) {
3853 // Name is one of t4-t7
3854 AsmToken RegTok = getLexer().peekTok();
3855 SMRange RegRange = RegTok.getLocRange();
3856
3857 StringRef FixedName = StringSwitch<StringRef>(Name)
3858 .Case("t4", "t0")
3859 .Case("t5", "t1")
3860 .Case("t6", "t2")
3861 .Case("t7", "t3")
3862 .Default("");
3863 assert(FixedName != "" && "Register name is not one of t4-t7.");
3864
3865 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3866 "Did you mean $" + FixedName + "?", RegRange);
3867 }
3868
Toma Tabacufda445c2014-09-15 15:33:01 +00003869 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3870 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3871 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3872 if (8 <= CC && CC <= 11)
3873 CC += 4;
3874
3875 if (CC == -1)
3876 CC = StringSwitch<unsigned>(Name)
3877 .Case("a4", 8)
3878 .Case("a5", 9)
3879 .Case("a6", 10)
3880 .Case("a7", 11)
3881 .Case("kt0", 26)
3882 .Case("kt1", 27)
3883 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003884
3885 return CC;
3886}
Jack Carterd0bd6422013-04-18 00:41:53 +00003887
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003888int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3889 int CC;
3890
3891 CC = StringSwitch<unsigned>(Name)
3892 .Case("hwr_cpunum", 0)
3893 .Case("hwr_synci_step", 1)
3894 .Case("hwr_cc", 2)
3895 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003896 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003897 .Default(-1);
3898
3899 return CC;
3900}
3901
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003902int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003903
Jack Cartera63b16a2012-09-07 00:23:42 +00003904 if (Name[0] == 'f') {
3905 StringRef NumString = Name.substr(1);
3906 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003907 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003908 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003909 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003910 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003911 return IntVal;
3912 }
3913 return -1;
3914}
Jack Cartera63b16a2012-09-07 00:23:42 +00003915
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003916int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3917
3918 if (Name.startswith("fcc")) {
3919 StringRef NumString = Name.substr(3);
3920 unsigned IntVal;
3921 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003922 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003923 if (IntVal > 7) // There are only 8 fcc registers.
3924 return -1;
3925 return IntVal;
3926 }
3927 return -1;
3928}
3929
3930int MipsAsmParser::matchACRegisterName(StringRef Name) {
3931
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003932 if (Name.startswith("ac")) {
3933 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003934 unsigned IntVal;
3935 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003936 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003937 if (IntVal > 3) // There are only 3 acc registers.
3938 return -1;
3939 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003940 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003941 return -1;
3942}
Jack Carterd0bd6422013-04-18 00:41:53 +00003943
Jack Carter5dc8ac92013-09-25 23:50:44 +00003944int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3945 unsigned IntVal;
3946
3947 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3948 return -1;
3949
3950 if (IntVal > 31)
3951 return -1;
3952
3953 return IntVal;
3954}
3955
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003956int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3957 int CC;
3958
3959 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003960 .Case("msair", 0)
3961 .Case("msacsr", 1)
3962 .Case("msaaccess", 2)
3963 .Case("msasave", 3)
3964 .Case("msamodify", 4)
3965 .Case("msarequest", 5)
3966 .Case("msamap", 6)
3967 .Case("msaunmap", 7)
3968 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003969
3970 return CC;
3971}
3972
Toma Tabacu89a712b2015-04-15 10:48:56 +00003973unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003974 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003975 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003976 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003977 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003978 return 0;
3979 }
3980 unsigned AT = getReg(
3981 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003982 return AT;
3983}
Jack Carter0b744b32012-10-04 02:29:46 +00003984
Jack Carterd0bd6422013-04-18 00:41:53 +00003985unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003986 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003987}
3988
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003989unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003990 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003991 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003992}
3993
Jack Carter873c7242013-01-12 01:03:14 +00003994int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003995 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003996 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003997 return -1;
3998
Jack Carter873c7242013-01-12 01:03:14 +00003999 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00004000}
4001
Toma Tabacu13964452014-09-04 13:23:44 +00004002bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004003 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004004 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004005
Jack Carter30a59822012-10-04 04:03:53 +00004006 // Check if the current operand has a custom associated parser, if so, try to
4007 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004008 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4009 if (ResTy == MatchOperand_Success)
4010 return false;
4011 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4012 // there was a match, but an error occurred, in which case, just return that
4013 // the operand parsing failed.
4014 if (ResTy == MatchOperand_ParseFail)
4015 return true;
4016
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004017 DEBUG(dbgs() << ".. Generic Parser\n");
4018
Jack Carterb4dbc172012-09-05 23:34:03 +00004019 switch (getLexer().getKind()) {
4020 default:
4021 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4022 return true;
4023 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004024 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004025 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004026
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004027 // Almost all registers have been parsed by custom parsers. There is only
4028 // one exception to this. $zero (and it's alias $0) will reach this point
4029 // for div, divu, and similar instructions because it is not an operand
4030 // to the instruction definition but an explicit register. Special case
4031 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004032 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004033 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004034
Jack Carterd0bd6422013-04-18 00:41:53 +00004035 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004036 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004037 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004038 return true;
4039
Jack Carter873c7242013-01-12 01:03:14 +00004040 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004041 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004042 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004043 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004044 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004045
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004046 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004047 return false;
4048 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004049 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004050 case AsmToken::LParen:
4051 case AsmToken::Minus:
4052 case AsmToken::Plus:
4053 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004054 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004055 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004056 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004057 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004058 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004059 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004060 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004061 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004062 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004063 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004064 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004065 return true;
4066
Jack Carter873c7242013-01-12 01:03:14 +00004067 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4068
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004069 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004070 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004071 } // case AsmToken::Percent
4072 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004073 return true;
4074}
4075
Vladimir Medic4c299852013-11-06 11:27:05 +00004076const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004077 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004078 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00004079 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004080 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00004081 // It's a constant, evaluate reloc value.
4082 int16_t Val;
4083 switch (getVariantKind(RelocStr)) {
4084 case MCSymbolRefExpr::VK_Mips_ABS_LO:
4085 // Get the 1st 16-bits.
4086 Val = MCE->getValue() & 0xffff;
4087 break;
4088 case MCSymbolRefExpr::VK_Mips_ABS_HI:
Simon Atanasyan2fc1e3b2016-02-09 22:31:49 +00004089 case MCSymbolRefExpr::VK_Mips_GOT:
Sasa Stankovic06c47802014-04-03 10:37:45 +00004090 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
4091 // 16 bits being negative.
4092 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
4093 break;
4094 case MCSymbolRefExpr::VK_Mips_HIGHER:
4095 // Get the 3rd 16-bits.
4096 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
4097 break;
4098 case MCSymbolRefExpr::VK_Mips_HIGHEST:
4099 // Get the 4th 16-bits.
4100 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
4101 break;
4102 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00004103 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00004104 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004105 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004106 }
4107
Jack Carterb5cf5902013-04-17 00:18:04 +00004108 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004109 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00004110 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00004111 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004112 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004113 return Res;
4114 }
4115
4116 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00004117 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
4118
Sasa Stankovic06c47802014-04-03 10:37:45 +00004119 // Try to create target expression.
4120 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00004121 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004122
Jack Carterd0bd6422013-04-18 00:41:53 +00004123 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
4124 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004125 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004126 return Res;
4127 }
4128
4129 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004130 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004131 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00004132 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00004133 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004134 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004135 return Expr;
4136}
4137
4138bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4139
4140 switch (Expr->getKind()) {
4141 case MCExpr::Constant:
4142 return true;
4143 case MCExpr::SymbolRef:
4144 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4145 case MCExpr::Binary:
4146 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4147 if (!isEvaluated(BE->getLHS()))
4148 return false;
4149 return isEvaluated(BE->getRHS());
4150 }
4151 case MCExpr::Unary:
4152 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004153 case MCExpr::Target:
4154 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004155 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004156 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004157}
Jack Carterd0bd6422013-04-18 00:41:53 +00004158
Jack Carterb5cf5902013-04-17 00:18:04 +00004159bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004160 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004161 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004162 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004163 if (Tok.isNot(AsmToken::Identifier))
4164 return true;
4165
Yaron Keren075759a2015-03-30 15:42:36 +00004166 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004167
Jack Carterd0bd6422013-04-18 00:41:53 +00004168 Parser.Lex(); // Eat the identifier.
4169 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004170 const MCExpr *IdVal;
4171 SMLoc EndLoc;
4172
4173 if (getLexer().getKind() == AsmToken::LParen) {
4174 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004175 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004176 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004177 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004178 const AsmToken &nextTok = Parser.getTok();
4179 if (nextTok.isNot(AsmToken::Identifier))
4180 return true;
4181 Str += "(%";
4182 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004183 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004184 if (getLexer().getKind() != AsmToken::LParen)
4185 return true;
4186 } else
4187 break;
4188 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004189 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004190 return true;
4191
4192 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004193 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004194
4195 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004196 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004197
Jack Carterd0bd6422013-04-18 00:41:53 +00004198 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004199 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004200}
4201
Jack Carterb4dbc172012-09-05 23:34:03 +00004202bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4203 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004204 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004205 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004206 if (ResTy == MatchOperand_Success) {
4207 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004208 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004209 StartLoc = Operand.getStartLoc();
4210 EndLoc = Operand.getEndLoc();
4211
4212 // AFAIK, we only support numeric registers and named GPR's in CFI
4213 // directives.
4214 // Don't worry about eating tokens before failing. Using an unrecognised
4215 // register is a parse error.
4216 if (Operand.isGPRAsmReg()) {
4217 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004218 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004219 }
4220
4221 return (RegNo == (unsigned)-1);
4222 }
4223
4224 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004225 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004226}
4227
Jack Carterb5cf5902013-04-17 00:18:04 +00004228bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004229 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004230 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004231 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004232 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004233
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004234 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004235 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004236 ++NumOfLParen;
4237 }
Jack Carter873c7242013-01-12 01:03:14 +00004238
Jack Carterd0bd6422013-04-18 00:41:53 +00004239 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004240 default:
4241 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004242 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004243 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004244 case AsmToken::Integer:
4245 case AsmToken::Minus:
4246 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004247 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004248 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004249 else
4250 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004251 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004252 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004253 break;
Jack Carter873c7242013-01-12 01:03:14 +00004254 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004255 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004256 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004257 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004258}
4259
David Blaikie960ea3f2014-06-08 16:18:35 +00004260MipsAsmParser::OperandMatchResultTy
4261MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004262 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004263 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004264 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004265 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004266 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004267 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004268 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004269 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004270
Jack Carterb5cf5902013-04-17 00:18:04 +00004271 if (getLexer().getKind() == AsmToken::LParen) {
4272 Parser.Lex();
4273 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004274 }
4275
Jack Carterb5cf5902013-04-17 00:18:04 +00004276 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004277 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004278 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004279
Jack Carterd0bd6422013-04-18 00:41:53 +00004280 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004281 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004282 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004283 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004284 SMLoc E =
4285 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004286 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004287 return MatchOperand_Success;
4288 }
4289 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004290 SMLoc E =
4291 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004292
Jack Carterd0bd6422013-04-18 00:41:53 +00004293 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004294 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004295 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004296 S, E, *this);
4297 Operands.push_back(
4298 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004299 return MatchOperand_Success;
4300 }
4301 Error(Parser.getTok().getLoc(), "'(' expected");
4302 return MatchOperand_ParseFail;
4303 }
4304
Jack Carterd0bd6422013-04-18 00:41:53 +00004305 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004306 }
4307
Toma Tabacu13964452014-09-04 13:23:44 +00004308 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004309 if (Res != MatchOperand_Success)
4310 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004311
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004312 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004313 Error(Parser.getTok().getLoc(), "')' expected");
4314 return MatchOperand_ParseFail;
4315 }
4316
Jack Carter873c7242013-01-12 01:03:14 +00004317 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4318
Jack Carterd0bd6422013-04-18 00:41:53 +00004319 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004320
Craig Topper062a2ba2014-04-25 05:30:21 +00004321 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004322 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004323
Jack Carterd0bd6422013-04-18 00:41:53 +00004324 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004325 std::unique_ptr<MipsOperand> op(
4326 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004327 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004328 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004329 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004330 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004331 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4332 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004333 if (IdVal->evaluateAsAbsolute(Imm))
4334 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004335 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004336 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004337 getContext());
4338 }
4339
David Blaikie960ea3f2014-06-08 16:18:35 +00004340 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004341 return MatchOperand_Success;
4342}
4343
David Blaikie960ea3f2014-06-08 16:18:35 +00004344bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004345 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004346 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004347 if (Sym) {
4348 SMLoc S = Parser.getTok().getLoc();
4349 const MCExpr *Expr;
4350 if (Sym->isVariable())
4351 Expr = Sym->getVariableValue();
4352 else
4353 return false;
4354 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004355 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004356 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004357 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004358 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004359 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004360 if (ResTy == MatchOperand_Success) {
4361 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004362 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004363 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004364 llvm_unreachable("Should never ParseFail");
4365 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004366 }
4367 } else if (Expr->getKind() == MCExpr::Constant) {
4368 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004369 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004370 Operands.push_back(
4371 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004372 return true;
4373 }
4374 }
4375 return false;
4376}
Jack Carterd0bd6422013-04-18 00:41:53 +00004377
Jack Carter873c7242013-01-12 01:03:14 +00004378MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004379MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004380 StringRef Identifier,
4381 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004382 int Index = matchCPURegisterName(Identifier);
4383 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004384 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004385 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4386 return MatchOperand_Success;
4387 }
4388
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004389 Index = matchHWRegsRegisterName(Identifier);
4390 if (Index != -1) {
4391 Operands.push_back(MipsOperand::createHWRegsReg(
4392 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4393 return MatchOperand_Success;
4394 }
4395
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004396 Index = matchFPURegisterName(Identifier);
4397 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004398 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004399 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4400 return MatchOperand_Success;
4401 }
4402
4403 Index = matchFCCRegisterName(Identifier);
4404 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004405 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004406 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4407 return MatchOperand_Success;
4408 }
4409
4410 Index = matchACRegisterName(Identifier);
4411 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004412 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004413 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4414 return MatchOperand_Success;
4415 }
4416
4417 Index = matchMSA128RegisterName(Identifier);
4418 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004419 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004420 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4421 return MatchOperand_Success;
4422 }
4423
4424 Index = matchMSA128CtrlRegisterName(Identifier);
4425 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004426 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004427 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4428 return MatchOperand_Success;
4429 }
4430
4431 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004432}
4433
4434MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004435MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004436 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004437 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004438
4439 if (Token.is(AsmToken::Identifier)) {
4440 DEBUG(dbgs() << ".. identifier\n");
4441 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004442 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004443 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004444 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004445 } else if (Token.is(AsmToken::Integer)) {
4446 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004447 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004448 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4449 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004450 return MatchOperand_Success;
4451 }
4452
4453 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4454
4455 return MatchOperand_NoMatch;
4456}
4457
David Blaikie960ea3f2014-06-08 16:18:35 +00004458MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004459MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004460 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004461 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004462
4463 auto Token = Parser.getTok();
4464
4465 SMLoc S = Token.getLoc();
4466
4467 if (Token.isNot(AsmToken::Dollar)) {
4468 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4469 if (Token.is(AsmToken::Identifier)) {
4470 if (searchSymbolAlias(Operands))
4471 return MatchOperand_Success;
4472 }
4473 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4474 return MatchOperand_NoMatch;
4475 }
4476 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004477
Toma Tabacu13964452014-09-04 13:23:44 +00004478 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004479 if (ResTy == MatchOperand_Success) {
4480 Parser.Lex(); // $
4481 Parser.Lex(); // identifier
4482 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004483 return ResTy;
4484}
4485
4486MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004487MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004488 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004489 switch (getLexer().getKind()) {
4490 default:
4491 return MatchOperand_NoMatch;
4492 case AsmToken::LParen:
4493 case AsmToken::Minus:
4494 case AsmToken::Plus:
4495 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004496 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004497 case AsmToken::String:
4498 break;
4499 }
4500
4501 const MCExpr *IdVal;
4502 SMLoc S = Parser.getTok().getLoc();
4503 if (getParser().parseExpression(IdVal))
4504 return MatchOperand_ParseFail;
4505
4506 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4507 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4508 return MatchOperand_Success;
4509}
4510
David Blaikie960ea3f2014-06-08 16:18:35 +00004511MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004512MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004513 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004514 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004515
4516 SMLoc S = getLexer().getLoc();
4517
4518 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004519 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004520 if (ResTy != MatchOperand_NoMatch)
4521 return ResTy;
4522
Daniel Sanders315386c2014-04-01 10:40:14 +00004523 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004524 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004525 if (ResTy != MatchOperand_NoMatch)
4526 return ResTy;
4527
Daniel Sandersffd84362014-04-01 10:41:48 +00004528 const MCExpr *Expr = nullptr;
4529 if (Parser.parseExpression(Expr)) {
4530 // We have no way of knowing if a symbol was consumed so we must ParseFail
4531 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004532 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004533 Operands.push_back(
4534 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004535 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004536}
4537
Vladimir Medic2b953d02013-10-01 09:48:56 +00004538MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004539MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004540 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004541 const MCExpr *IdVal;
4542 // If the first token is '$' we may have register operand.
4543 if (Parser.getTok().is(AsmToken::Dollar))
4544 return MatchOperand_NoMatch;
4545 SMLoc S = Parser.getTok().getLoc();
4546 if (getParser().parseExpression(IdVal))
4547 return MatchOperand_ParseFail;
4548 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004549 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004550 int64_t Val = MCE->getValue();
4551 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4552 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004553 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004554 return MatchOperand_Success;
4555}
4556
Matheus Almeida779c5932013-11-18 12:32:49 +00004557MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004558MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004559 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004560 switch (getLexer().getKind()) {
4561 default:
4562 return MatchOperand_NoMatch;
4563 case AsmToken::LParen:
4564 case AsmToken::Plus:
4565 case AsmToken::Minus:
4566 case AsmToken::Integer:
4567 break;
4568 }
4569
4570 const MCExpr *Expr;
4571 SMLoc S = Parser.getTok().getLoc();
4572
4573 if (getParser().parseExpression(Expr))
4574 return MatchOperand_ParseFail;
4575
4576 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004577 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004578 Error(S, "expected immediate value");
4579 return MatchOperand_ParseFail;
4580 }
4581
4582 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4583 // and because the CPU always adds one to the immediate field, the allowed
4584 // range becomes 1..4. We'll only check the range here and will deal
4585 // with the addition/subtraction when actually decoding/encoding
4586 // the instruction.
4587 if (Val < 1 || Val > 4) {
4588 Error(S, "immediate not in range (1..4)");
4589 return MatchOperand_ParseFail;
4590 }
4591
Jack Carter3b2c96e2014-01-22 23:31:38 +00004592 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004593 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004594 return MatchOperand_Success;
4595}
4596
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004597MipsAsmParser::OperandMatchResultTy
4598MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4599 MCAsmParser &Parser = getParser();
4600 SmallVector<unsigned, 10> Regs;
4601 unsigned RegNo;
4602 unsigned PrevReg = Mips::NoRegister;
4603 bool RegRange = false;
4604 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4605
4606 if (Parser.getTok().isNot(AsmToken::Dollar))
4607 return MatchOperand_ParseFail;
4608
4609 SMLoc S = Parser.getTok().getLoc();
4610 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4611 SMLoc E = getLexer().getLoc();
4612 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4613 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4614 if (RegRange) {
4615 // Remove last register operand because registers from register range
4616 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004617 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4618 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004619 Regs.push_back(RegNo);
4620 } else {
4621 unsigned TmpReg = PrevReg + 1;
4622 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004623 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4624 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4625 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004626 Error(E, "invalid register operand");
4627 return MatchOperand_ParseFail;
4628 }
4629
4630 PrevReg = TmpReg;
4631 Regs.push_back(TmpReg++);
4632 }
4633 }
4634
4635 RegRange = false;
4636 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004637 if ((PrevReg == Mips::NoRegister) &&
4638 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4639 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004640 Error(E, "$16 or $31 expected");
4641 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004642 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4643 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4644 !isGP64bit()) ||
4645 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4646 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4647 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004648 Error(E, "invalid register operand");
4649 return MatchOperand_ParseFail;
4650 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004651 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4652 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4653 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004654 Error(E, "consecutive register numbers expected");
4655 return MatchOperand_ParseFail;
4656 }
4657
4658 Regs.push_back(RegNo);
4659 }
4660
4661 if (Parser.getTok().is(AsmToken::Minus))
4662 RegRange = true;
4663
4664 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4665 !Parser.getTok().isNot(AsmToken::Comma)) {
4666 Error(E, "',' or '-' expected");
4667 return MatchOperand_ParseFail;
4668 }
4669
4670 Lex(); // Consume comma or minus
4671 if (Parser.getTok().isNot(AsmToken::Dollar))
4672 break;
4673
4674 PrevReg = RegNo;
4675 }
4676
4677 SMLoc E = Parser.getTok().getLoc();
4678 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4679 parseMemOperand(Operands);
4680 return MatchOperand_Success;
4681}
4682
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004683MipsAsmParser::OperandMatchResultTy
4684MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4685 MCAsmParser &Parser = getParser();
4686
4687 SMLoc S = Parser.getTok().getLoc();
4688 if (parseAnyRegister(Operands) != MatchOperand_Success)
4689 return MatchOperand_ParseFail;
4690
4691 SMLoc E = Parser.getTok().getLoc();
4692 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4693 unsigned Reg = Op.getGPR32Reg();
4694 Operands.pop_back();
4695 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4696 return MatchOperand_Success;
4697}
4698
Zoran Jovanovic41688672015-02-10 16:36:20 +00004699MipsAsmParser::OperandMatchResultTy
4700MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4701 MCAsmParser &Parser = getParser();
4702 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4703 SmallVector<unsigned, 10> Regs;
4704
4705 if (Parser.getTok().isNot(AsmToken::Dollar))
4706 return MatchOperand_ParseFail;
4707
4708 SMLoc S = Parser.getTok().getLoc();
4709
4710 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4711 return MatchOperand_ParseFail;
4712
4713 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4714 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4715 Regs.push_back(RegNo);
4716
4717 SMLoc E = Parser.getTok().getLoc();
4718 if (Parser.getTok().isNot(AsmToken::Comma)) {
4719 Error(E, "',' expected");
4720 return MatchOperand_ParseFail;
4721 }
4722
4723 // Remove comma.
4724 Parser.Lex();
4725
4726 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4727 return MatchOperand_ParseFail;
4728
4729 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4730 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4731 Regs.push_back(RegNo);
4732
4733 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4734
4735 return MatchOperand_Success;
4736}
4737
Jack Carterdc1e35d2012-09-06 20:00:02 +00004738MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4739
Vladimir Medic4c299852013-11-06 11:27:05 +00004740 MCSymbolRefExpr::VariantKind VK =
4741 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4742 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4743 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4744 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4745 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4746 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4747 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4748 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4749 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4750 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4751 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4752 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4753 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4754 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4755 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4756 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4757 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4758 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004759 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4760 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4761 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4762 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4763 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4764 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004765 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4766 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004767 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004768
Matheus Almeida2852af82014-04-22 10:15:54 +00004769 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004770
Jack Carterdc1e35d2012-09-06 20:00:02 +00004771 return VK;
4772}
Jack Cartera63b16a2012-09-07 00:23:42 +00004773
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004774/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4775/// either this.
4776/// ::= '(', register, ')'
4777/// handle it before we iterate so we don't get tripped up by the lack of
4778/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004779bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004780 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004781 if (getLexer().is(AsmToken::LParen)) {
4782 Operands.push_back(
4783 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4784 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004785 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004786 SMLoc Loc = getLexer().getLoc();
4787 Parser.eatToEndOfStatement();
4788 return Error(Loc, "unexpected token in argument list");
4789 }
4790 if (Parser.getTok().isNot(AsmToken::RParen)) {
4791 SMLoc Loc = getLexer().getLoc();
4792 Parser.eatToEndOfStatement();
4793 return Error(Loc, "unexpected token, expected ')'");
4794 }
4795 Operands.push_back(
4796 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4797 Parser.Lex();
4798 }
4799 return false;
4800}
4801
4802/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4803/// either one of these.
4804/// ::= '[', register, ']'
4805/// ::= '[', integer, ']'
4806/// handle it before we iterate so we don't get tripped up by the lack of
4807/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004808bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004809 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004810 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004811 if (getLexer().is(AsmToken::LBrac)) {
4812 Operands.push_back(
4813 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4814 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004815 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004816 SMLoc Loc = getLexer().getLoc();
4817 Parser.eatToEndOfStatement();
4818 return Error(Loc, "unexpected token in argument list");
4819 }
4820 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4821 SMLoc Loc = getLexer().getLoc();
4822 Parser.eatToEndOfStatement();
4823 return Error(Loc, "unexpected token, expected ']'");
4824 }
4825 Operands.push_back(
4826 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4827 Parser.Lex();
4828 }
4829 return false;
4830}
4831
David Blaikie960ea3f2014-06-08 16:18:35 +00004832bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4833 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004834 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004835 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004836
4837 // We have reached first instruction, module directive are now forbidden.
4838 getTargetStreamer().forbidModuleDirective();
4839
Vladimir Medic74593e62013-07-17 15:00:42 +00004840 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004841 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004842 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004843 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004844 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004845 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004846 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004847
4848 // Read the remaining operands.
4849 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4850 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004851 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004852 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004853 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004854 return Error(Loc, "unexpected token in argument list");
4855 }
Toma Tabacu13964452014-09-04 13:23:44 +00004856 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004857 return true;
4858 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004859
Jack Carterd0bd6422013-04-18 00:41:53 +00004860 while (getLexer().is(AsmToken::Comma)) {
4861 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004862 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004863 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004864 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004865 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004866 return Error(Loc, "unexpected token in argument list");
4867 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004868 // Parse bracket and parenthesis suffixes before we iterate
4869 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004870 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004871 return true;
4872 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004873 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004874 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004875 }
4876 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004877 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4878 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004879 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004880 return Error(Loc, "unexpected token in argument list");
4881 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004882 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004883 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004884}
4885
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004886bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004887 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004888 SMLoc Loc = getLexer().getLoc();
4889 Parser.eatToEndOfStatement();
4890 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004891}
4892
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004893bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004894 return Error(Loc, ErrorMsg);
4895}
4896
Jack Carter0b744b32012-10-04 02:29:46 +00004897bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004898 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004899 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004900
4901 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004902 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004903
4904 Parser.Lex(); // Eat "noat".
4905
Jack Carterd0bd6422013-04-18 00:41:53 +00004906 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004907 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004908 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004909 return false;
4910 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004911
4912 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004913 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004914 return false;
4915}
Jack Carterd0bd6422013-04-18 00:41:53 +00004916
Jack Carter0b744b32012-10-04 02:29:46 +00004917bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004918 // Line can be: ".set at", which sets $at to $1
4919 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004920 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004921 Parser.Lex(); // Eat "at".
4922
Jack Carter0b744b32012-10-04 02:29:46 +00004923 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004924 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004925 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004926
4927 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004928 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004929 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004930 }
4931
4932 if (getLexer().isNot(AsmToken::Equal)) {
4933 reportParseError("unexpected token, expected equals sign");
4934 return false;
4935 }
4936 Parser.Lex(); // Eat "=".
4937
4938 if (getLexer().isNot(AsmToken::Dollar)) {
4939 if (getLexer().is(AsmToken::EndOfStatement)) {
4940 reportParseError("no register specified");
4941 return false;
4942 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004943 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004944 return false;
4945 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004946 }
4947 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004948
Toma Tabacu16a74492015-02-13 10:30:57 +00004949 // Find out what "reg" is.
4950 unsigned AtRegNo;
4951 const AsmToken &Reg = Parser.getTok();
4952 if (Reg.is(AsmToken::Identifier)) {
4953 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4954 } else if (Reg.is(AsmToken::Integer)) {
4955 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004956 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004957 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004958 return false;
4959 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004960
4961 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004962 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004963 reportParseError("invalid register");
4964 return false;
4965 }
4966 Parser.Lex(); // Eat "reg".
4967
4968 // If this is not the end of the statement, report an error.
4969 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4970 reportParseError("unexpected token, expected end of statement");
4971 return false;
4972 }
4973
4974 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4975
4976 Parser.Lex(); // Consume the EndOfStatement.
4977 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004978}
4979
4980bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004981 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004982 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004983 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004984 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004985 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004986 return false;
4987 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004988 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004989 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004990 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004991 return false;
4992}
4993
4994bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004995 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004996 Parser.Lex();
4997 // If this is not the end of the statement, report an error.
4998 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004999 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005000 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005001 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005002 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005003 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005004 Parser.Lex(); // Consume the EndOfStatement.
5005 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005006}
5007
5008bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005009 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005010 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005011 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005012 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005013 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005014 return false;
5015 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005016 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005017 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005018 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005019 return false;
5020}
5021
5022bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005023 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005024 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005025 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005026 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005027 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005028 return false;
5029 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005030 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005031 reportParseError("`noreorder' must be set before `nomacro'");
5032 return false;
5033 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005034 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005035 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005036 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005037 return false;
5038}
Jack Carterd76b2372013-03-21 21:44:16 +00005039
Daniel Sanders44934432014-08-07 12:03:36 +00005040bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005041 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005042 Parser.Lex();
5043
5044 // If this is not the end of the statement, report an error.
5045 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005046 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005047
5048 setFeatureBits(Mips::FeatureMSA, "msa");
5049 getTargetStreamer().emitDirectiveSetMsa();
5050 return false;
5051}
5052
5053bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005054 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005055 Parser.Lex();
5056
5057 // If this is not the end of the statement, report an error.
5058 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005059 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005060
5061 clearFeatureBits(Mips::FeatureMSA, "msa");
5062 getTargetStreamer().emitDirectiveSetNoMsa();
5063 return false;
5064}
5065
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005066bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005067 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005068 Parser.Lex(); // Eat "nodsp".
5069
5070 // If this is not the end of the statement, report an error.
5071 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5072 reportParseError("unexpected token, expected end of statement");
5073 return false;
5074 }
5075
5076 clearFeatureBits(Mips::FeatureDSP, "dsp");
5077 getTargetStreamer().emitDirectiveSetNoDsp();
5078 return false;
5079}
5080
Toma Tabacucc2502d2014-11-04 17:18:07 +00005081bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005082 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005083 Parser.Lex(); // Eat "mips16".
5084
Jack Carter39536722014-01-22 23:08:42 +00005085 // If this is not the end of the statement, report an error.
5086 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005087 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005088 return false;
5089 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005090
5091 setFeatureBits(Mips::FeatureMips16, "mips16");
5092 getTargetStreamer().emitDirectiveSetMips16();
5093 Parser.Lex(); // Consume the EndOfStatement.
5094 return false;
5095}
5096
5097bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005098 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005099 Parser.Lex(); // Eat "nomips16".
5100
5101 // If this is not the end of the statement, report an error.
5102 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5103 reportParseError("unexpected token, expected end of statement");
5104 return false;
5105 }
5106
5107 clearFeatureBits(Mips::FeatureMips16, "mips16");
5108 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005109 Parser.Lex(); // Consume the EndOfStatement.
5110 return false;
5111}
5112
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005113bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005114 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005115 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005116 // Line can be: .set fp=32
5117 // .set fp=xx
5118 // .set fp=64
5119 Parser.Lex(); // Eat fp token
5120 AsmToken Tok = Parser.getTok();
5121 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005122 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005123 return false;
5124 }
5125 Parser.Lex(); // Eat '=' token.
5126 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005127
5128 if (!parseFpABIValue(FpAbiVal, ".set"))
5129 return false;
5130
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005131 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005132 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005133 return false;
5134 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005135 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005136 Parser.Lex(); // Consume the EndOfStatement.
5137 return false;
5138}
5139
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005140bool MipsAsmParser::parseSetOddSPRegDirective() {
5141 MCAsmParser &Parser = getParser();
5142
5143 Parser.Lex(); // Eat "oddspreg".
5144 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5145 reportParseError("unexpected token, expected end of statement");
5146 return false;
5147 }
5148
5149 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5150 getTargetStreamer().emitDirectiveSetOddSPReg();
5151 return false;
5152}
5153
5154bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5155 MCAsmParser &Parser = getParser();
5156
5157 Parser.Lex(); // Eat "nooddspreg".
5158 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5159 reportParseError("unexpected token, expected end of statement");
5160 return false;
5161 }
5162
5163 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5164 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5165 return false;
5166}
5167
Toma Tabacu9db22db2014-09-09 10:15:38 +00005168bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005169 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005170 SMLoc Loc = getLexer().getLoc();
5171
5172 Parser.Lex();
5173 if (getLexer().isNot(AsmToken::EndOfStatement))
5174 return reportParseError("unexpected token, expected end of statement");
5175
5176 // Always keep an element on the options "stack" to prevent the user
5177 // from changing the initial options. This is how we remember them.
5178 if (AssemblerOptions.size() == 2)
5179 return reportParseError(Loc, ".set pop with no .set push");
5180
Akira Hatanakab11ef082015-11-14 06:35:56 +00005181 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005182 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005183 setAvailableFeatures(
5184 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5185 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005186
5187 getTargetStreamer().emitDirectiveSetPop();
5188 return false;
5189}
5190
5191bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005192 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005193 Parser.Lex();
5194 if (getLexer().isNot(AsmToken::EndOfStatement))
5195 return reportParseError("unexpected token, expected end of statement");
5196
5197 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005198 AssemblerOptions.push_back(
5199 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005200
5201 getTargetStreamer().emitDirectiveSetPush();
5202 return false;
5203}
5204
Toma Tabacu29696502015-06-02 09:48:04 +00005205bool MipsAsmParser::parseSetSoftFloatDirective() {
5206 MCAsmParser &Parser = getParser();
5207 Parser.Lex();
5208 if (getLexer().isNot(AsmToken::EndOfStatement))
5209 return reportParseError("unexpected token, expected end of statement");
5210
5211 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5212 getTargetStreamer().emitDirectiveSetSoftFloat();
5213 return false;
5214}
5215
5216bool MipsAsmParser::parseSetHardFloatDirective() {
5217 MCAsmParser &Parser = getParser();
5218 Parser.Lex();
5219 if (getLexer().isNot(AsmToken::EndOfStatement))
5220 return reportParseError("unexpected token, expected end of statement");
5221
5222 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5223 getTargetStreamer().emitDirectiveSetHardFloat();
5224 return false;
5225}
5226
Jack Carterd76b2372013-03-21 21:44:16 +00005227bool MipsAsmParser::parseSetAssignment() {
5228 StringRef Name;
5229 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005230 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005231
5232 if (Parser.parseIdentifier(Name))
5233 reportParseError("expected identifier after .set");
5234
5235 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005236 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005237 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005238
Jack Carter3b2c96e2014-01-22 23:31:38 +00005239 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005240 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005241
Jim Grosbach6f482002015-05-18 18:43:14 +00005242 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005243 Sym->setVariableValue(Value);
5244
5245 return false;
5246}
Jack Carterd0bd6422013-04-18 00:41:53 +00005247
Toma Tabacu26647792014-09-09 12:52:14 +00005248bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005249 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005250 Parser.Lex();
5251 if (getLexer().isNot(AsmToken::EndOfStatement))
5252 return reportParseError("unexpected token, expected end of statement");
5253
5254 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005255 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005256 setAvailableFeatures(
5257 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5258 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005259 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5260
5261 getTargetStreamer().emitDirectiveSetMips0();
5262 return false;
5263}
5264
Toma Tabacu85618b32014-08-19 14:22:52 +00005265bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005266 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005267 Parser.Lex();
5268 if (getLexer().isNot(AsmToken::Equal))
5269 return reportParseError("unexpected token, expected equals sign");
5270
5271 Parser.Lex();
5272 StringRef Arch;
5273 if (Parser.parseIdentifier(Arch))
5274 return reportParseError("expected arch identifier");
5275
5276 StringRef ArchFeatureName =
5277 StringSwitch<StringRef>(Arch)
5278 .Case("mips1", "mips1")
5279 .Case("mips2", "mips2")
5280 .Case("mips3", "mips3")
5281 .Case("mips4", "mips4")
5282 .Case("mips5", "mips5")
5283 .Case("mips32", "mips32")
5284 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005285 .Case("mips32r3", "mips32r3")
5286 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005287 .Case("mips32r6", "mips32r6")
5288 .Case("mips64", "mips64")
5289 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005290 .Case("mips64r3", "mips64r3")
5291 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005292 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005293 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005294 .Case("r4000", "mips3") // This is an implementation of Mips3.
5295 .Default("");
5296
5297 if (ArchFeatureName.empty())
5298 return reportParseError("unsupported architecture");
5299
5300 selectArch(ArchFeatureName);
5301 getTargetStreamer().emitDirectiveSetArch(Arch);
5302 return false;
5303}
5304
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005305bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005306 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005307 Parser.Lex();
5308 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005309 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005310
Matheus Almeida2852af82014-04-22 10:15:54 +00005311 switch (Feature) {
5312 default:
5313 llvm_unreachable("Unimplemented feature");
5314 case Mips::FeatureDSP:
5315 setFeatureBits(Mips::FeatureDSP, "dsp");
5316 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005317 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005318 case Mips::FeatureMicroMips:
5319 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005320 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005321 case Mips::FeatureMips1:
5322 selectArch("mips1");
5323 getTargetStreamer().emitDirectiveSetMips1();
5324 break;
5325 case Mips::FeatureMips2:
5326 selectArch("mips2");
5327 getTargetStreamer().emitDirectiveSetMips2();
5328 break;
5329 case Mips::FeatureMips3:
5330 selectArch("mips3");
5331 getTargetStreamer().emitDirectiveSetMips3();
5332 break;
5333 case Mips::FeatureMips4:
5334 selectArch("mips4");
5335 getTargetStreamer().emitDirectiveSetMips4();
5336 break;
5337 case Mips::FeatureMips5:
5338 selectArch("mips5");
5339 getTargetStreamer().emitDirectiveSetMips5();
5340 break;
5341 case Mips::FeatureMips32:
5342 selectArch("mips32");
5343 getTargetStreamer().emitDirectiveSetMips32();
5344 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005345 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005346 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005347 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005348 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005349 case Mips::FeatureMips32r3:
5350 selectArch("mips32r3");
5351 getTargetStreamer().emitDirectiveSetMips32R3();
5352 break;
5353 case Mips::FeatureMips32r5:
5354 selectArch("mips32r5");
5355 getTargetStreamer().emitDirectiveSetMips32R5();
5356 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005357 case Mips::FeatureMips32r6:
5358 selectArch("mips32r6");
5359 getTargetStreamer().emitDirectiveSetMips32R6();
5360 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005361 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005362 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005363 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005364 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005365 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005366 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005367 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005368 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005369 case Mips::FeatureMips64r3:
5370 selectArch("mips64r3");
5371 getTargetStreamer().emitDirectiveSetMips64R3();
5372 break;
5373 case Mips::FeatureMips64r5:
5374 selectArch("mips64r5");
5375 getTargetStreamer().emitDirectiveSetMips64R5();
5376 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005377 case Mips::FeatureMips64r6:
5378 selectArch("mips64r6");
5379 getTargetStreamer().emitDirectiveSetMips64R6();
5380 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005381 }
5382 return false;
5383}
5384
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005385bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005386 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005387 if (getLexer().isNot(AsmToken::Comma)) {
5388 SMLoc Loc = getLexer().getLoc();
5389 Parser.eatToEndOfStatement();
5390 return Error(Loc, ErrorStr);
5391 }
5392
Matheus Almeida2852af82014-04-22 10:15:54 +00005393 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005394 return true;
5395}
5396
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005397// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5398// In this class, it is only used for .cprestore.
5399// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5400// MipsTargetELFStreamer and MipsAsmParser.
5401bool MipsAsmParser::isPicAndNotNxxAbi() {
5402 return inPicMode() && !(isABI_N32() || isABI_N64());
5403}
5404
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005405bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005406 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005407 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005408
Toma Tabacudde4c462014-11-06 10:02:45 +00005409 if (inMips16Mode()) {
5410 reportParseError(".cpload is not supported in Mips16 mode");
5411 return false;
5412 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005413
David Blaikie960ea3f2014-06-08 16:18:35 +00005414 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005415 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005416 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5417 reportParseError("expected register containing function address");
5418 return false;
5419 }
5420
David Blaikie960ea3f2014-06-08 16:18:35 +00005421 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5422 if (!RegOpnd.isGPRAsmReg()) {
5423 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005424 return false;
5425 }
5426
Toma Tabacudde4c462014-11-06 10:02:45 +00005427 // If this is not the end of the statement, report an error.
5428 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5429 reportParseError("unexpected token, expected end of statement");
5430 return false;
5431 }
5432
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005433 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005434 return false;
5435}
5436
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005437bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5438 MCAsmParser &Parser = getParser();
5439
5440 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5441 // is used in non-PIC mode.
5442
5443 if (inMips16Mode()) {
5444 reportParseError(".cprestore is not supported in Mips16 mode");
5445 return false;
5446 }
5447
5448 // Get the stack offset value.
5449 const MCExpr *StackOffset;
5450 int64_t StackOffsetVal;
5451 if (Parser.parseExpression(StackOffset)) {
5452 reportParseError("expected stack offset value");
5453 return false;
5454 }
5455
5456 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5457 reportParseError("stack offset is not an absolute expression");
5458 return false;
5459 }
5460
5461 if (StackOffsetVal < 0) {
5462 Warning(Loc, ".cprestore with negative stack offset has no effect");
5463 IsCpRestoreSet = false;
5464 } else {
5465 IsCpRestoreSet = true;
5466 CpRestoreOffset = StackOffsetVal;
5467 }
5468
5469 // If this is not the end of the statement, report an error.
5470 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5471 reportParseError("unexpected token, expected end of statement");
5472 return false;
5473 }
5474
5475 // Store the $gp on the stack.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005476 if (getStreamer().isIntegratedAssemblerRequired()) {
5477 const MCSubtargetInfo &STI = getSTI();
5478 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5479 getStreamer(), &STI);
5480 }
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005481
Daniel Sandersc6924fa2016-04-18 12:06:15 +00005482 getTargetStreamer().emitDirectiveCpRestore(CpRestoreOffset);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005483 Parser.Lex(); // Consume the EndOfStatement.
5484 return false;
5485}
5486
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005487bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005488 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005489 unsigned FuncReg;
5490 unsigned Save;
5491 bool SaveIsReg = true;
5492
Matheus Almeida7e815762014-06-18 13:08:59 +00005493 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005494 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005495 if (ResTy == MatchOperand_NoMatch) {
5496 reportParseError("expected register containing function address");
5497 Parser.eatToEndOfStatement();
5498 return false;
5499 }
5500
5501 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5502 if (!FuncRegOpnd.isGPRAsmReg()) {
5503 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5504 Parser.eatToEndOfStatement();
5505 return false;
5506 }
5507
5508 FuncReg = FuncRegOpnd.getGPR32Reg();
5509 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005510
Toma Tabacu65f10572014-09-16 15:00:52 +00005511 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005512 return true;
5513
Toma Tabacu13964452014-09-04 13:23:44 +00005514 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005515 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005516 const MCExpr *OffsetExpr;
5517 int64_t OffsetVal;
5518 SMLoc ExprLoc = getLexer().getLoc();
5519
5520 if (Parser.parseExpression(OffsetExpr) ||
5521 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5522 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005523 Parser.eatToEndOfStatement();
5524 return false;
5525 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005526
5527 Save = OffsetVal;
5528 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005529 } else {
5530 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5531 if (!SaveOpnd.isGPRAsmReg()) {
5532 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5533 Parser.eatToEndOfStatement();
5534 return false;
5535 }
5536 Save = SaveOpnd.getGPR32Reg();
5537 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005538
Toma Tabacu65f10572014-09-16 15:00:52 +00005539 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005540 return true;
5541
Toma Tabacu8874eac2015-02-18 13:46:53 +00005542 const MCExpr *Expr;
5543 if (Parser.parseExpression(Expr)) {
5544 reportParseError("expected expression");
5545 return false;
5546 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005547
Toma Tabacu8874eac2015-02-18 13:46:53 +00005548 if (Expr->getKind() != MCExpr::SymbolRef) {
5549 reportParseError("expected symbol");
5550 return false;
5551 }
5552 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5553
Daniel Sandersf173dda2015-09-22 10:50:09 +00005554 CpSaveLocation = Save;
5555 CpSaveLocationIsRegister = SaveIsReg;
5556
Toma Tabacu8874eac2015-02-18 13:46:53 +00005557 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5558 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005559 return false;
5560}
5561
Daniel Sandersf173dda2015-09-22 10:50:09 +00005562bool MipsAsmParser::parseDirectiveCPReturn() {
5563 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5564 CpSaveLocationIsRegister);
5565 return false;
5566}
5567
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005568bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005569 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005570 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5571 const AsmToken &Tok = Parser.getTok();
5572
5573 if (Tok.getString() == "2008") {
5574 Parser.Lex();
5575 getTargetStreamer().emitDirectiveNaN2008();
5576 return false;
5577 } else if (Tok.getString() == "legacy") {
5578 Parser.Lex();
5579 getTargetStreamer().emitDirectiveNaNLegacy();
5580 return false;
5581 }
5582 }
5583 // If we don't recognize the option passed to the .nan
5584 // directive (e.g. no option or unknown option), emit an error.
5585 reportParseError("invalid option in .nan directive");
5586 return false;
5587}
5588
Jack Carter0b744b32012-10-04 02:29:46 +00005589bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005590 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005591 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005592 const AsmToken &Tok = Parser.getTok();
5593
5594 if (Tok.getString() == "noat") {
5595 return parseSetNoAtDirective();
5596 } else if (Tok.getString() == "at") {
5597 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005598 } else if (Tok.getString() == "arch") {
5599 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005600 } else if (Tok.getString() == "fp") {
5601 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005602 } else if (Tok.getString() == "oddspreg") {
5603 return parseSetOddSPRegDirective();
5604 } else if (Tok.getString() == "nooddspreg") {
5605 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005606 } else if (Tok.getString() == "pop") {
5607 return parseSetPopDirective();
5608 } else if (Tok.getString() == "push") {
5609 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005610 } else if (Tok.getString() == "reorder") {
5611 return parseSetReorderDirective();
5612 } else if (Tok.getString() == "noreorder") {
5613 return parseSetNoReorderDirective();
5614 } else if (Tok.getString() == "macro") {
5615 return parseSetMacroDirective();
5616 } else if (Tok.getString() == "nomacro") {
5617 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005618 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005619 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005620 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005621 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005622 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005623 getTargetStreamer().emitDirectiveSetNoMicroMips();
5624 Parser.eatToEndOfStatement();
5625 return false;
5626 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005627 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005628 } else if (Tok.getString() == "mips0") {
5629 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005630 } else if (Tok.getString() == "mips1") {
5631 return parseSetFeature(Mips::FeatureMips1);
5632 } else if (Tok.getString() == "mips2") {
5633 return parseSetFeature(Mips::FeatureMips2);
5634 } else if (Tok.getString() == "mips3") {
5635 return parseSetFeature(Mips::FeatureMips3);
5636 } else if (Tok.getString() == "mips4") {
5637 return parseSetFeature(Mips::FeatureMips4);
5638 } else if (Tok.getString() == "mips5") {
5639 return parseSetFeature(Mips::FeatureMips5);
5640 } else if (Tok.getString() == "mips32") {
5641 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005642 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005643 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005644 } else if (Tok.getString() == "mips32r3") {
5645 return parseSetFeature(Mips::FeatureMips32r3);
5646 } else if (Tok.getString() == "mips32r5") {
5647 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005648 } else if (Tok.getString() == "mips32r6") {
5649 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005650 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005651 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005652 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005653 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005654 } else if (Tok.getString() == "mips64r3") {
5655 return parseSetFeature(Mips::FeatureMips64r3);
5656 } else if (Tok.getString() == "mips64r5") {
5657 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005658 } else if (Tok.getString() == "mips64r6") {
5659 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005660 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005661 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005662 } else if (Tok.getString() == "nodsp") {
5663 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005664 } else if (Tok.getString() == "msa") {
5665 return parseSetMsaDirective();
5666 } else if (Tok.getString() == "nomsa") {
5667 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005668 } else if (Tok.getString() == "softfloat") {
5669 return parseSetSoftFloatDirective();
5670 } else if (Tok.getString() == "hardfloat") {
5671 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005672 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005673 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005674 parseSetAssignment();
5675 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005676 }
Jack Carter07c818d2013-01-25 01:31:34 +00005677
Jack Carter0b744b32012-10-04 02:29:46 +00005678 return true;
5679}
5680
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005681/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005682/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005683bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005684 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005685 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5686 for (;;) {
5687 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005688 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005689 return true;
5690
5691 getParser().getStreamer().EmitValue(Value, Size);
5692
5693 if (getLexer().is(AsmToken::EndOfStatement))
5694 break;
5695
Jack Carter07c818d2013-01-25 01:31:34 +00005696 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005697 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005698 Parser.Lex();
5699 }
5700 }
5701
5702 Parser.Lex();
5703 return false;
5704}
5705
Vladimir Medic4c299852013-11-06 11:27:05 +00005706/// parseDirectiveGpWord
5707/// ::= .gpword local_sym
5708bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005709 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005710 const MCExpr *Value;
5711 // EmitGPRel32Value requires an expression, so we are using base class
5712 // method to evaluate the expression.
5713 if (getParser().parseExpression(Value))
5714 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005715 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005716
Vladimir Medice10c1122013-11-13 13:18:04 +00005717 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005718 return Error(getLexer().getLoc(),
5719 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005720 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005721 return false;
5722}
5723
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005724/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005725/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005726bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005727 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005728 const MCExpr *Value;
5729 // EmitGPRel64Value requires an expression, so we are using base class
5730 // method to evaluate the expression.
5731 if (getParser().parseExpression(Value))
5732 return true;
5733 getParser().getStreamer().EmitGPRel64Value(Value);
5734
5735 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005736 return Error(getLexer().getLoc(),
5737 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005738 Parser.Lex(); // Eat EndOfStatement token.
5739 return false;
5740}
5741
Jack Carter0cd3c192014-01-06 23:27:31 +00005742bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005743 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005744 // Get the option token.
5745 AsmToken Tok = Parser.getTok();
5746 // At the moment only identifiers are supported.
5747 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005748 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005749 Parser.eatToEndOfStatement();
5750 return false;
5751 }
5752
5753 StringRef Option = Tok.getIdentifier();
5754
5755 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005756 // MipsAsmParser needs to know if the current PIC mode changes.
5757 IsPicEnabled = false;
5758
Jack Carter0cd3c192014-01-06 23:27:31 +00005759 getTargetStreamer().emitDirectiveOptionPic0();
5760 Parser.Lex();
5761 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5762 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005763 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005764 Parser.eatToEndOfStatement();
5765 }
5766 return false;
5767 }
5768
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005769 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005770 // MipsAsmParser needs to know if the current PIC mode changes.
5771 IsPicEnabled = true;
5772
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005773 getTargetStreamer().emitDirectiveOptionPic2();
5774 Parser.Lex();
5775 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5776 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005777 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005778 Parser.eatToEndOfStatement();
5779 }
5780 return false;
5781 }
5782
Jack Carter0cd3c192014-01-06 23:27:31 +00005783 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005784 Warning(Parser.getTok().getLoc(),
5785 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005786 Parser.eatToEndOfStatement();
5787 return false;
5788}
5789
Toma Tabacu9ca50962015-04-16 09:53:47 +00005790/// parseInsnDirective
5791/// ::= .insn
5792bool MipsAsmParser::parseInsnDirective() {
5793 // If this is not the end of the statement, report an error.
5794 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5795 reportParseError("unexpected token, expected end of statement");
5796 return false;
5797 }
5798
5799 // The actual label marking happens in
5800 // MipsELFStreamer::createPendingLabelRelocs().
5801 getTargetStreamer().emitDirectiveInsn();
5802
5803 getParser().Lex(); // Eat EndOfStatement token.
5804 return false;
5805}
5806
Simon Atanasyanbe186202016-02-11 06:45:54 +00005807/// parseSSectionDirective
5808/// ::= .sbss
5809/// ::= .sdata
5810bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5811 // If this is not the end of the statement, report an error.
5812 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5813 reportParseError("unexpected token, expected end of statement");
5814 return false;
5815 }
5816
5817 MCSection *ELFSection = getContext().getELFSection(
5818 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5819 getParser().getStreamer().SwitchSection(ELFSection);
5820
5821 getParser().Lex(); // Eat EndOfStatement token.
5822 return false;
5823}
5824
Daniel Sanders7e527422014-07-10 13:38:23 +00005825/// parseDirectiveModule
5826/// ::= .module oddspreg
5827/// ::= .module nooddspreg
5828/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005829/// ::= .module softfloat
5830/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005831bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005832 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005833 MCAsmLexer &Lexer = getLexer();
5834 SMLoc L = Lexer.getLoc();
5835
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005836 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005837 // TODO : get a better message.
5838 reportParseError(".module directive must appear before any code");
5839 return false;
5840 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005841
Toma Tabacuc405c822015-01-23 10:40:19 +00005842 StringRef Option;
5843 if (Parser.parseIdentifier(Option)) {
5844 reportParseError("expected .module option identifier");
5845 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005846 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005847
Toma Tabacuc405c822015-01-23 10:40:19 +00005848 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005849 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005850
Toma Tabacu3c499582015-06-25 10:56:57 +00005851 // Synchronize the abiflags information with the FeatureBits information we
5852 // changed above.
5853 getTargetStreamer().updateABIInfo(*this);
5854
5855 // If printing assembly, use the recently updated abiflags information.
5856 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5857 // emitted at the end).
5858 getTargetStreamer().emitDirectiveModuleOddSPReg();
5859
Toma Tabacuc405c822015-01-23 10:40:19 +00005860 // If this is not the end of the statement, report an error.
5861 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5862 reportParseError("unexpected token, expected end of statement");
5863 return false;
5864 }
5865
5866 return false; // parseDirectiveModule has finished successfully.
5867 } else if (Option == "nooddspreg") {
5868 if (!isABI_O32()) {
5869 Error(L, "'.module nooddspreg' requires the O32 ABI");
5870 return false;
5871 }
5872
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005873 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005874
Toma Tabacu3c499582015-06-25 10:56:57 +00005875 // Synchronize the abiflags information with the FeatureBits information we
5876 // changed above.
5877 getTargetStreamer().updateABIInfo(*this);
5878
5879 // If printing assembly, use the recently updated abiflags information.
5880 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5881 // emitted at the end).
5882 getTargetStreamer().emitDirectiveModuleOddSPReg();
5883
Toma Tabacuc405c822015-01-23 10:40:19 +00005884 // If this is not the end of the statement, report an error.
5885 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5886 reportParseError("unexpected token, expected end of statement");
5887 return false;
5888 }
5889
5890 return false; // parseDirectiveModule has finished successfully.
5891 } else if (Option == "fp") {
5892 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005893 } else if (Option == "softfloat") {
5894 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5895
5896 // Synchronize the ABI Flags information with the FeatureBits information we
5897 // updated above.
5898 getTargetStreamer().updateABIInfo(*this);
5899
5900 // If printing assembly, use the recently updated ABI Flags information.
5901 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5902 // emitted later).
5903 getTargetStreamer().emitDirectiveModuleSoftFloat();
5904
5905 // If this is not the end of the statement, report an error.
5906 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5907 reportParseError("unexpected token, expected end of statement");
5908 return false;
5909 }
5910
5911 return false; // parseDirectiveModule has finished successfully.
5912 } else if (Option == "hardfloat") {
5913 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5914
5915 // Synchronize the ABI Flags information with the FeatureBits information we
5916 // updated above.
5917 getTargetStreamer().updateABIInfo(*this);
5918
5919 // If printing assembly, use the recently updated ABI Flags information.
5920 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5921 // emitted later).
5922 getTargetStreamer().emitDirectiveModuleHardFloat();
5923
5924 // If this is not the end of the statement, report an error.
5925 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5926 reportParseError("unexpected token, expected end of statement");
5927 return false;
5928 }
5929
5930 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005931 } else {
5932 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5933 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005934}
5935
5936/// parseDirectiveModuleFP
5937/// ::= =32
5938/// ::= =xx
5939/// ::= =64
5940bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005941 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005942 MCAsmLexer &Lexer = getLexer();
5943
5944 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005945 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005946 return false;
5947 }
5948 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005949
Daniel Sanders7e527422014-07-10 13:38:23 +00005950 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005951 if (!parseFpABIValue(FpABI, ".module"))
5952 return false;
5953
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005954 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005955 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005956 return false;
5957 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005958
Toma Tabacua64e5402015-06-25 12:44:38 +00005959 // Synchronize the abiflags information with the FeatureBits information we
5960 // changed above.
5961 getTargetStreamer().updateABIInfo(*this);
5962
5963 // If printing assembly, use the recently updated abiflags information.
5964 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5965 // emitted at the end).
5966 getTargetStreamer().emitDirectiveModuleFP();
5967
Daniel Sanders7e527422014-07-10 13:38:23 +00005968 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005969 return false;
5970}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005971
Daniel Sanders7e527422014-07-10 13:38:23 +00005972bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005973 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005974 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005975 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005976 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005977
5978 if (Lexer.is(AsmToken::Identifier)) {
5979 StringRef Value = Parser.getTok().getString();
5980 Parser.Lex();
5981
5982 if (Value != "xx") {
5983 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5984 return false;
5985 }
5986
5987 if (!isABI_O32()) {
5988 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5989 return false;
5990 }
5991
Daniel Sanders7e527422014-07-10 13:38:23 +00005992 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005993 if (ModuleLevelOptions) {
5994 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5995 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5996 } else {
5997 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5998 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5999 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006000 return true;
6001 }
6002
6003 if (Lexer.is(AsmToken::Integer)) {
6004 unsigned Value = Parser.getTok().getIntVal();
6005 Parser.Lex();
6006
6007 if (Value != 32 && Value != 64) {
6008 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6009 return false;
6010 }
6011
6012 if (Value == 32) {
6013 if (!isABI_O32()) {
6014 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6015 return false;
6016 }
6017
Daniel Sanders7e527422014-07-10 13:38:23 +00006018 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006019 if (ModuleLevelOptions) {
6020 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6021 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6022 } else {
6023 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6024 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6025 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006026 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006027 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006028 if (ModuleLevelOptions) {
6029 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6030 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6031 } else {
6032 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6033 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6034 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006035 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006036
Daniel Sanders7e527422014-07-10 13:38:23 +00006037 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006038 }
6039
6040 return false;
6041}
6042
Jack Carter0b744b32012-10-04 02:29:46 +00006043bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006044 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006045 StringRef IDVal = DirectiveID.getString();
6046
Matheus Almeida525bc4f2014-04-30 11:28:42 +00006047 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00006048 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006049 if (IDVal == ".cprestore")
6050 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006051 if (IDVal == ".dword") {
6052 parseDataDirective(8, DirectiveID.getLoc());
6053 return false;
6054 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006055 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006056 StringRef SymbolName;
6057
6058 if (Parser.parseIdentifier(SymbolName)) {
6059 reportParseError("expected identifier after .ent");
6060 return false;
6061 }
6062
6063 // There's an undocumented extension that allows an integer to
6064 // follow the name of the procedure which AFAICS is ignored by GAS.
6065 // Example: .ent foo,2
6066 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6067 if (getLexer().isNot(AsmToken::Comma)) {
6068 // Even though we accept this undocumented extension for compatibility
6069 // reasons, the additional integer argument does not actually change
6070 // the behaviour of the '.ent' directive, so we would like to discourage
6071 // its use. We do this by not referring to the extended version in
6072 // error messages which are not directly related to its use.
6073 reportParseError("unexpected token, expected end of statement");
6074 return false;
6075 }
6076 Parser.Lex(); // Eat the comma.
6077 const MCExpr *DummyNumber;
6078 int64_t DummyNumberVal;
6079 // If the user was explicitly trying to use the extended version,
6080 // we still give helpful extension-related error messages.
6081 if (Parser.parseExpression(DummyNumber)) {
6082 reportParseError("expected number after comma");
6083 return false;
6084 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006085 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006086 reportParseError("expected an absolute expression after comma");
6087 return false;
6088 }
6089 }
6090
6091 // If this is not the end of the statement, report an error.
6092 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6093 reportParseError("unexpected token, expected end of statement");
6094 return false;
6095 }
6096
Jim Grosbach6f482002015-05-18 18:43:14 +00006097 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006098
6099 getTargetStreamer().emitDirectiveEnt(*Sym);
6100 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006101 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006102 return false;
6103 }
6104
Jack Carter07c818d2013-01-25 01:31:34 +00006105 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006106 StringRef SymbolName;
6107
6108 if (Parser.parseIdentifier(SymbolName)) {
6109 reportParseError("expected identifier after .end");
6110 return false;
6111 }
6112
6113 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6114 reportParseError("unexpected token, expected end of statement");
6115 return false;
6116 }
6117
6118 if (CurrentFn == nullptr) {
6119 reportParseError(".end used without .ent");
6120 return false;
6121 }
6122
6123 if ((SymbolName != CurrentFn->getName())) {
6124 reportParseError(".end symbol does not match .ent symbol");
6125 return false;
6126 }
6127
6128 getTargetStreamer().emitDirectiveEnd(SymbolName);
6129 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006130 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006131 return false;
6132 }
6133
Jack Carter07c818d2013-01-25 01:31:34 +00006134 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006135 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6136 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006137 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006138 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6139 reportParseError("expected stack register");
6140 return false;
6141 }
6142
6143 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6144 if (!StackRegOpnd.isGPRAsmReg()) {
6145 reportParseError(StackRegOpnd.getStartLoc(),
6146 "expected general purpose register");
6147 return false;
6148 }
6149 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6150
6151 if (Parser.getTok().is(AsmToken::Comma))
6152 Parser.Lex();
6153 else {
6154 reportParseError("unexpected token, expected comma");
6155 return false;
6156 }
6157
6158 // Parse the frame size.
6159 const MCExpr *FrameSize;
6160 int64_t FrameSizeVal;
6161
6162 if (Parser.parseExpression(FrameSize)) {
6163 reportParseError("expected frame size value");
6164 return false;
6165 }
6166
Jim Grosbach13760bd2015-05-30 01:25:56 +00006167 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006168 reportParseError("frame size not an absolute expression");
6169 return false;
6170 }
6171
6172 if (Parser.getTok().is(AsmToken::Comma))
6173 Parser.Lex();
6174 else {
6175 reportParseError("unexpected token, expected comma");
6176 return false;
6177 }
6178
6179 // Parse the return register.
6180 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006181 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006182 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6183 reportParseError("expected return register");
6184 return false;
6185 }
6186
6187 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6188 if (!ReturnRegOpnd.isGPRAsmReg()) {
6189 reportParseError(ReturnRegOpnd.getStartLoc(),
6190 "expected general purpose register");
6191 return false;
6192 }
6193
6194 // If this is not the end of the statement, report an error.
6195 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6196 reportParseError("unexpected token, expected end of statement");
6197 return false;
6198 }
6199
6200 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6201 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006202 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006203 return false;
6204 }
6205
Jack Carter07c818d2013-01-25 01:31:34 +00006206 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00006207 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00006208 }
6209
Daniel Sandersd97a6342014-08-13 10:07:34 +00006210 if (IDVal == ".mask" || IDVal == ".fmask") {
6211 // .mask bitmask, frame_offset
6212 // bitmask: One bit for each register used.
6213 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6214 // first register is expected to be saved.
6215 // Examples:
6216 // .mask 0x80000000, -4
6217 // .fmask 0x80000000, -4
6218 //
Jack Carterbe332172012-09-07 00:48:02 +00006219
Daniel Sandersd97a6342014-08-13 10:07:34 +00006220 // Parse the bitmask
6221 const MCExpr *BitMask;
6222 int64_t BitMaskVal;
6223
6224 if (Parser.parseExpression(BitMask)) {
6225 reportParseError("expected bitmask value");
6226 return false;
6227 }
6228
Jim Grosbach13760bd2015-05-30 01:25:56 +00006229 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006230 reportParseError("bitmask not an absolute expression");
6231 return false;
6232 }
6233
6234 if (Parser.getTok().is(AsmToken::Comma))
6235 Parser.Lex();
6236 else {
6237 reportParseError("unexpected token, expected comma");
6238 return false;
6239 }
6240
6241 // Parse the frame_offset
6242 const MCExpr *FrameOffset;
6243 int64_t FrameOffsetVal;
6244
6245 if (Parser.parseExpression(FrameOffset)) {
6246 reportParseError("expected frame offset value");
6247 return false;
6248 }
6249
Jim Grosbach13760bd2015-05-30 01:25:56 +00006250 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006251 reportParseError("frame offset not an absolute expression");
6252 return false;
6253 }
6254
6255 // If this is not the end of the statement, report an error.
6256 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6257 reportParseError("unexpected token, expected end of statement");
6258 return false;
6259 }
6260
6261 if (IDVal == ".mask")
6262 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6263 else
6264 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006265 return false;
6266 }
6267
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006268 if (IDVal == ".nan")
6269 return parseDirectiveNaN();
6270
Jack Carter07c818d2013-01-25 01:31:34 +00006271 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006272 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006273 return false;
6274 }
6275
Rafael Espindolab59fb732014-03-28 18:50:26 +00006276 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006277 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006278 return false;
6279 }
6280
Jack Carter07c818d2013-01-25 01:31:34 +00006281 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006282 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006283 return false;
6284 }
6285
Scott Egertond1aeb052016-02-15 16:11:51 +00006286 if (IDVal == ".hword") {
6287 parseDataDirective(2, DirectiveID.getLoc());
6288 return false;
6289 }
6290
Jack Carter0cd3c192014-01-06 23:27:31 +00006291 if (IDVal == ".option")
6292 return parseDirectiveOption();
6293
6294 if (IDVal == ".abicalls") {
6295 getTargetStreamer().emitDirectiveAbiCalls();
6296 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006297 Error(Parser.getTok().getLoc(),
6298 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006299 // Clear line
6300 Parser.eatToEndOfStatement();
6301 }
6302 return false;
6303 }
6304
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006305 if (IDVal == ".cpsetup")
6306 return parseDirectiveCPSetup();
6307
Daniel Sandersf173dda2015-09-22 10:50:09 +00006308 if (IDVal == ".cpreturn")
6309 return parseDirectiveCPReturn();
6310
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006311 if (IDVal == ".module")
6312 return parseDirectiveModule();
6313
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006314 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
6315 return parseInternalDirectiveReallowModule();
6316
Toma Tabacu9ca50962015-04-16 09:53:47 +00006317 if (IDVal == ".insn")
6318 return parseInsnDirective();
6319
Simon Atanasyanbe186202016-02-11 06:45:54 +00006320 if (IDVal == ".sbss")
6321 return parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6322 if (IDVal == ".sdata")
6323 return parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6324
Rafael Espindola870c4e92012-01-11 03:56:41 +00006325 return true;
6326}
6327
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006328bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6329 // If this is not the end of the statement, report an error.
6330 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6331 reportParseError("unexpected token, expected end of statement");
6332 return false;
6333 }
6334
6335 getTargetStreamer().reallowModuleDirective();
6336
6337 getParser().Lex(); // Eat EndOfStatement token.
6338 return false;
6339}
6340
Rafael Espindola870c4e92012-01-11 03:56:41 +00006341extern "C" void LLVMInitializeMipsAsmParser() {
6342 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6343 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6344 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6345 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6346}
Jack Carterb4dbc172012-09-05 23:34:03 +00006347
6348#define GET_REGISTER_MATCHER
6349#define GET_MATCHER_IMPLEMENTATION
6350#include "MipsGenAsmMatcher.inc"