blob: d054578deb6722221678c2fcd30d47e6f8093f5d [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Daniel Sandersa6994442015-08-18 12:33:54 +000014#include "MipsTargetObjectFile.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Hrvoje Vargadbe4d962016-09-08 07:41:43 +000016#include "MCTargetDesc/MipsBaseInfo.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000017#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000022#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000023#include "llvm/MC/MCParser/MCAsmLexer.h"
24#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000025#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000026#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000027#include "llvm/MC/MCStreamer.h"
28#include "llvm/MC/MCSubtargetInfo.h"
29#include "llvm/MC/MCSymbol.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000030#include "llvm/Support/Debug.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000031#include "llvm/Support/ELF.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000032#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000033#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000034#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000035#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000036#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000037
38using namespace llvm;
39
Chandler Carruthe96dd892014-04-21 22:55:11 +000040#define DEBUG_TYPE "mips-asm-parser"
41
Joey Gouly0e76fa72013-09-12 10:28:05 +000042namespace llvm {
43class MCInstrInfo;
44}
45
Rafael Espindola870c4e92012-01-11 03:56:41 +000046namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000047class MipsAssemblerOptions {
48public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000049 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000050 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000051
Toma Tabacu9db22db2014-09-09 10:15:38 +000052 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000053 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000054 Reorder = Opts->isReorder();
55 Macro = Opts->isMacro();
56 Features = Opts->getFeatures();
57 }
58
Toma Tabacub19cf202015-04-27 13:12:59 +000059 unsigned getATRegIndex() const { return ATReg; }
60 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000061 if (Reg > 31)
62 return false;
63
64 ATReg = Reg;
65 return true;
66 }
Jack Carter0b744b32012-10-04 02:29:46 +000067
Toma Tabacu9db22db2014-09-09 10:15:38 +000068 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000069 void setReorder() { Reorder = true; }
70 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000071
Toma Tabacu9db22db2014-09-09 10:15:38 +000072 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000073 void setMacro() { Macro = true; }
74 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000075
Toma Tabacu465acfd2015-06-09 13:33:26 +000076 const FeatureBitset &getFeatures() const { return Features; }
77 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000078
Daniel Sandersf0df2212014-08-04 12:20:00 +000079 // Set of features that are either architecture features or referenced
80 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
81 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
82 // The reason we need this mask is explained in the selectArch function.
83 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000084 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000085
Jack Carter0b744b32012-10-04 02:29:46 +000086private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000087 unsigned ATReg;
88 bool Reorder;
89 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000090 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000091};
92}
93
Michael Kupersteindb0712f2015-05-26 10:47:10 +000094const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
95 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
96 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
97 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
98 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
99 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
100 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
101 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
102 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
103};
104
Jack Carter0b744b32012-10-04 02:29:46 +0000105namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000106class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000107 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000108 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000109 return static_cast<MipsTargetStreamer &>(TS);
110 }
111
Eric Christophera5762812015-01-26 17:33:46 +0000112 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000113 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000114 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
115 // nullptr, which indicates that no function is currently
116 // selected. This usually happens after an '.end func'
117 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000118 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000119 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000120 bool IsCpRestoreSet;
121 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000122 unsigned CpSaveLocation;
123 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
124 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000125
Daniel Sandersef638fe2014-10-03 15:37:37 +0000126 // Print a warning along with its fix-it message at the given range.
127 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
128 SMRange Range, bool ShowColors = true);
129
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000130#define GET_ASSEMBLER_HEADER
131#include "MipsGenAsmMatcher.inc"
132
Daniel Sandersc5537422016-07-27 13:49:44 +0000133 unsigned
134 checkEarlyTargetMatchPredicate(MCInst &Inst,
135 const OperandVector &Operands) override;
Matheus Almeida595fcab2014-06-11 15:05:56 +0000136 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
137
Chad Rosier49963552012-10-13 00:26:04 +0000138 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000139 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000140 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000141 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000142
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000143 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000144 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000145
Toma Tabacu13964452014-09-04 13:23:44 +0000146 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000147
Toma Tabacu13964452014-09-04 13:23:44 +0000148 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000149
David Blaikie960ea3f2014-06-08 16:18:35 +0000150 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
151 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000152
Craig Topper56c590a2014-04-29 07:58:02 +0000153 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000154
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000155 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
156 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000157 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000158 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000159 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
160 SMLoc S);
161 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
162 OperandMatchResultTy parseImm(OperandVector &Operands);
163 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
164 OperandMatchResultTy parseInvNum(OperandVector &Operands);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000165 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
166 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
167 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000168
David Blaikie960ea3f2014-06-08 16:18:35 +0000169 bool searchSymbolAlias(OperandVector &Operands);
170
Toma Tabacu13964452014-09-04 13:23:44 +0000171 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000172
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000173 enum MacroExpanderResultTy {
174 MER_NotAMacro,
175 MER_Success,
176 MER_Fail,
177 };
Jack Carter30a59822012-10-04 04:03:53 +0000178
Matheus Almeida3813d572014-06-19 14:39:14 +0000179 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000180 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
181 MCStreamer &Out,
182 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000183
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000184 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
185 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000186
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000187 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000188 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000189 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000190
Toma Tabacuf712ede2015-06-17 14:31:51 +0000191 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
192 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000193 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000194
Toma Tabacu00e98672015-05-01 12:19:27 +0000195 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000196 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000197
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000198 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
199 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000200 SMLoc IDLoc, MCStreamer &Out,
201 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000202
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000203 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
204 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000205
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000206 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000207 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
208
209 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
210 const MCSubtargetInfo *STI, bool IsImmOpnd);
211
212 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
213 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000214
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000215 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
216 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000217
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
219 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000220
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000221 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
222 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000223
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000224 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
225 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000226
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000227 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
228 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000229 const bool Signed);
230
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000231 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000232 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000233
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000234 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000236
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +0000237 bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
238 const MCSubtargetInfo *STI);
239
240 bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000241 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000242
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000243 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000244 MCStreamer &Out, const MCSubtargetInfo *STI);
245 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
246 const MCSubtargetInfo *STI);
247 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
248 const MCSubtargetInfo *STI);
249 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
250 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000251
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000252 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
253 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000254
Simon Dardisaff4d142016-10-18 14:28:00 +0000255 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
256 const MCSubtargetInfo *STI, bool IsLoad);
257
Simon Dardis43115a12016-11-21 20:30:41 +0000258 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
259 const MCSubtargetInfo *STI);
260
261 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
262 const MCSubtargetInfo *STI);
263
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000264 bool reportParseError(Twine ErrorMsg);
265 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000266
Jack Carterb5cf5902013-04-17 00:18:04 +0000267 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000268
269 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000270 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000271 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000272 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000273 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000274 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000275 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000276 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000277 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000278 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000279 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000280 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000281 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000282 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000283
284 bool parseSetAtDirective();
285 bool parseSetNoAtDirective();
286 bool parseSetMacroDirective();
287 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000288 bool parseSetMsaDirective();
289 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000290 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000291 bool parseSetReorderDirective();
292 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000293 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000294 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000295 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000296 bool parseSetOddSPRegDirective();
297 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000298 bool parseSetPopDirective();
299 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000300 bool parseSetSoftFloatDirective();
301 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000302
Jack Carterd76b2372013-03-21 21:44:16 +0000303 bool parseSetAssignment();
304
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000305 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000306 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000307 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000308 bool parseDirectiveDtpRelWord();
309 bool parseDirectiveDtpRelDWord();
310 bool parseDirectiveTpRelWord();
311 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000312 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000313 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000314 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
315 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000316
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000317 bool parseInternalDirectiveReallowModule();
318
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000319 bool eatComma(StringRef ErrorStr);
320
Jack Carter1ac53222013-02-20 23:11:17 +0000321 int matchCPURegisterName(StringRef Symbol);
322
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000323 int matchHWRegsRegisterName(StringRef Symbol);
324
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000325 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000326
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000327 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000328
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000329 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000330
Jack Carter5dc8ac92013-09-25 23:50:44 +0000331 int matchMSA128RegisterName(StringRef Name);
332
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000333 int matchMSA128CtrlRegisterName(StringRef Name);
334
Jack Carterd0bd6422013-04-18 00:41:53 +0000335 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000336
Toma Tabacu89a712b2015-04-15 10:48:56 +0000337 /// Returns the internal register number for the current AT. Also checks if
338 /// the current AT is unavailable (set to $0) and gives an error if it is.
339 /// This should be used in pseudo-instruction expansions which need AT.
340 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000341
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000342 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
343 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000344
345 // Helper function that checks if the value of a vector index is within the
346 // boundaries of accepted values for each RegisterKind
347 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
348 bool validateMSAIndex(int Val, int RegKind);
349
Daniel Sandersf0df2212014-08-04 12:20:00 +0000350 // Selects a new architecture by updating the FeatureBits with the necessary
351 // info including implied dependencies.
352 // Internally, it clears all the feature bits related to *any* architecture
353 // and selects the new one using the ToggleFeature functionality of the
354 // MCSubtargetInfo object that handles implied dependencies. The reason we
355 // clear all the arch related bits manually is because ToggleFeature only
356 // clears the features that imply the feature being cleared and not the
357 // features implied by the feature being cleared. This is easier to see
358 // with an example:
359 // --------------------------------------------------
360 // | Feature | Implies |
361 // | -------------------------------------------------|
362 // | FeatureMips1 | None |
363 // | FeatureMips2 | FeatureMips1 |
364 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
365 // | FeatureMips4 | FeatureMips3 |
366 // | ... | |
367 // --------------------------------------------------
368 //
369 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
370 // FeatureMipsGP64 | FeatureMips1)
371 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
372 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000373 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000374 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000375 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
376 STI.setFeatureBits(FeatureBits);
377 setAvailableFeatures(
378 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000379 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000380 }
381
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000382 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000383 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000384 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000385 setAvailableFeatures(
386 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000387 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000388 }
389 }
390
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000391 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000392 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000393 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000394 setAvailableFeatures(
395 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000396 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000397 }
398 }
399
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000400 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
401 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000402 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000403 }
404
405 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
406 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000407 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000408 }
409
Rafael Espindola870c4e92012-01-11 03:56:41 +0000410public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000411 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000412 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000413 Match_RequiresDifferentOperands,
414 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000415 Match_RequiresSameSrcAndDst,
Simon Dardis730fdb72017-01-16 13:55:58 +0000416 Match_NoFCCRegisterForCurrentISA,
Simon Dardisc4463c92016-10-18 14:42:13 +0000417 Match_NonZeroOperandForSync,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000418#define GET_OPERAND_DIAGNOSTIC_TYPES
419#include "MipsGenAsmMatcher.inc"
420#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000421 };
422
Akira Hatanakab11ef082015-11-14 06:35:56 +0000423 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000424 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000425 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000426 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
427 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000428 MCAsmParserExtension::Initialize(parser);
429
Toma Tabacu11e14a92015-04-21 11:50:52 +0000430 parser.addAliasForDirective(".asciiz", ".asciz");
431
Jack Carterb4dbc172012-09-05 23:34:03 +0000432 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000433 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000434
Toma Tabacu9db22db2014-09-09 10:15:38 +0000435 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000436 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000437 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000438
Toma Tabacu9db22db2014-09-09 10:15:38 +0000439 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000440 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000441 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000442
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000443 getTargetStreamer().updateABIInfo(*this);
444
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000445 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000446 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000447
448 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000449
Rafael Espindola699281c2016-05-18 11:58:50 +0000450 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000451
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000452 IsCpRestoreSet = false;
453 CpRestoreOffset = -1;
454
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000455 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000456 if ((TheTriple.getArch() == Triple::mips) ||
457 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000458 IsLittleEndian = false;
459 else
460 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000461 }
462
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000463 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
464 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
465
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000466 bool isGP64bit() const {
467 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
468 }
469 bool isFP64bit() const {
470 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
471 }
Eric Christophera5762812015-01-26 17:33:46 +0000472 const MipsABIInfo &getABI() const { return ABI; }
473 bool isABI_N32() const { return ABI.IsN32(); }
474 bool isABI_N64() const { return ABI.IsN64(); }
475 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000476 bool isABI_FPXX() const {
477 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
478 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000479
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000480 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000481 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000482 }
483
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000484 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000485 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000486 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000487 bool hasMips1() const {
488 return getSTI().getFeatureBits()[Mips::FeatureMips1];
489 }
490 bool hasMips2() const {
491 return getSTI().getFeatureBits()[Mips::FeatureMips2];
492 }
493 bool hasMips3() const {
494 return getSTI().getFeatureBits()[Mips::FeatureMips3];
495 }
496 bool hasMips4() const {
497 return getSTI().getFeatureBits()[Mips::FeatureMips4];
498 }
499 bool hasMips5() const {
500 return getSTI().getFeatureBits()[Mips::FeatureMips5];
501 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000502 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000503 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000504 }
505 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000506 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000507 }
508 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000509 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000510 }
511 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000512 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000513 }
Daniel Sanders17793142015-02-18 16:24:50 +0000514 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000515 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000516 }
517 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000518 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000519 }
520 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000521 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000522 }
523 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000524 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000525 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000526 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000527 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000528 }
529 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000530 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000531 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000532
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000533 bool hasDSP() const {
534 return getSTI().getFeatureBits()[Mips::FeatureDSP];
535 }
536 bool hasDSPR2() const {
537 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
538 }
539 bool hasDSPR3() const {
540 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
541 }
542 bool hasMSA() const {
543 return getSTI().getFeatureBits()[Mips::FeatureMSA];
544 }
Kai Nackee0245392015-01-27 19:11:28 +0000545 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000546 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000547 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000548
Daniel Sandersa6994442015-08-18 12:33:54 +0000549 bool inPicMode() {
550 return IsPicEnabled;
551 }
552
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000553 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000554 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000555 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000556
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000557 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000558 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000559 }
560
Eric Christophere8ae3e32015-05-07 23:10:21 +0000561 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000562 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000563 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000564
Toma Tabacud9d344b2015-04-27 14:05:04 +0000565 /// Warn if RegIndex is the same as the current AT.
566 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000567
568 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000569
570 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000571
572 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
573 AsmToken::TokenKind OperatorToken,
574 MCContext &Ctx) override {
575 switch(OperatorToken) {
576 default:
577 llvm_unreachable("Unknown token");
578 return nullptr;
579 case AsmToken::PercentCall16:
580 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
581 case AsmToken::PercentCall_Hi:
582 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
583 case AsmToken::PercentCall_Lo:
584 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
585 case AsmToken::PercentDtprel_Hi:
586 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
587 case AsmToken::PercentDtprel_Lo:
588 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
589 case AsmToken::PercentGot:
590 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
591 case AsmToken::PercentGot_Disp:
592 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
593 case AsmToken::PercentGot_Hi:
594 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
595 case AsmToken::PercentGot_Lo:
596 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
597 case AsmToken::PercentGot_Ofst:
598 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
599 case AsmToken::PercentGot_Page:
600 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
601 case AsmToken::PercentGottprel:
602 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
603 case AsmToken::PercentGp_Rel:
604 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
605 case AsmToken::PercentHi:
606 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
607 case AsmToken::PercentHigher:
608 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
609 case AsmToken::PercentHighest:
610 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
611 case AsmToken::PercentLo:
612 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
613 case AsmToken::PercentNeg:
614 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
615 case AsmToken::PercentPcrel_Hi:
616 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
617 case AsmToken::PercentPcrel_Lo:
618 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
619 case AsmToken::PercentTlsgd:
620 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
621 case AsmToken::PercentTlsldm:
622 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
623 case AsmToken::PercentTprel_Hi:
624 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
625 case AsmToken::PercentTprel_Lo:
626 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
627 }
628 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000629};
630}
631
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000632namespace {
633
634/// MipsOperand - Instances of this class represent a parsed Mips machine
635/// instruction.
636class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000637public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000638 /// Broad categories of register classes
639 /// The exact class is finalized by the render method.
640 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000641 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000642 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000643 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000644 RegKind_FCC = 4, /// FCC
645 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
646 RegKind_MSACtrl = 16, /// MSA control registers
647 RegKind_COP2 = 32, /// COP2
648 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
649 /// context).
650 RegKind_CCR = 128, /// CCR
651 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000652 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000653 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000654 /// Potentially any (e.g. $1)
655 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
656 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000657 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000658 };
659
660private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000661 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000662 k_Immediate, /// An immediate (possibly involving symbol references)
663 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000664 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000665 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000666 k_RegList, /// A physical register list
667 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000668 } Kind;
669
David Blaikie960ea3f2014-06-08 16:18:35 +0000670public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000671 MipsOperand(KindTy K, MipsAsmParser &Parser)
672 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
673
David Blaikie960ea3f2014-06-08 16:18:35 +0000674private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000675 /// For diagnostics, and checking the assembler temporary
676 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000677
Eric Christopher8996c5d2013-03-15 00:42:55 +0000678 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000679 const char *Data;
680 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000681 };
682
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000683 struct RegIdxOp {
684 unsigned Index; /// Index into the register class
685 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000686 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000687 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000688 };
689
690 struct ImmOp {
691 const MCExpr *Val;
692 };
693
694 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000695 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000696 const MCExpr *Off;
697 };
698
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000699 struct RegListOp {
700 SmallVector<unsigned, 10> *List;
701 };
702
Jack Carterb4dbc172012-09-05 23:34:03 +0000703 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000704 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000705 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000706 struct ImmOp Imm;
707 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000708 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000709 };
710
711 SMLoc StartLoc, EndLoc;
712
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000713 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000714 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
715 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000716 const MCRegisterInfo *RegInfo,
717 SMLoc S, SMLoc E,
718 MipsAsmParser &Parser) {
719 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000720 Op->RegIdx.Index = Index;
721 Op->RegIdx.RegInfo = RegInfo;
722 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000723 Op->RegIdx.Tok.Data = Str.data();
724 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000725 Op->StartLoc = S;
726 Op->EndLoc = E;
727 return Op;
728 }
729
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000730public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000731 /// Coerce the register to GPR32 and return the real register for the current
732 /// target.
733 unsigned getGPR32Reg() const {
734 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000735 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000736 unsigned ClassID = Mips::GPR32RegClassID;
737 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000738 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000739
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000740 /// Coerce the register to GPR32 and return the real register for the current
741 /// target.
742 unsigned getGPRMM16Reg() const {
743 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
744 unsigned ClassID = Mips::GPR32RegClassID;
745 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
746 }
747
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000748 /// Coerce the register to GPR64 and return the real register for the current
749 /// target.
750 unsigned getGPR64Reg() const {
751 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
752 unsigned ClassID = Mips::GPR64RegClassID;
753 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000754 }
755
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000756private:
757 /// Coerce the register to AFGR64 and return the real register for the current
758 /// target.
759 unsigned getAFGR64Reg() const {
760 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
761 if (RegIdx.Index % 2 != 0)
762 AsmParser.Warning(StartLoc, "Float register should be even.");
763 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
764 .getRegister(RegIdx.Index / 2);
765 }
766
767 /// Coerce the register to FGR64 and return the real register for the current
768 /// target.
769 unsigned getFGR64Reg() const {
770 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
771 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
772 .getRegister(RegIdx.Index);
773 }
774
775 /// Coerce the register to FGR32 and return the real register for the current
776 /// target.
777 unsigned getFGR32Reg() const {
778 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
779 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
780 .getRegister(RegIdx.Index);
781 }
782
783 /// Coerce the register to FGRH32 and return the real register for the current
784 /// target.
785 unsigned getFGRH32Reg() const {
786 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
787 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
788 .getRegister(RegIdx.Index);
789 }
790
791 /// Coerce the register to FCC and return the real register for the current
792 /// target.
793 unsigned getFCCReg() const {
794 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
795 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
796 .getRegister(RegIdx.Index);
797 }
798
799 /// Coerce the register to MSA128 and return the real register for the current
800 /// target.
801 unsigned getMSA128Reg() const {
802 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
803 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
804 // identical
805 unsigned ClassID = Mips::MSA128BRegClassID;
806 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
807 }
808
809 /// Coerce the register to MSACtrl and return the real register for the
810 /// current target.
811 unsigned getMSACtrlReg() const {
812 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
813 unsigned ClassID = Mips::MSACtrlRegClassID;
814 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
815 }
816
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000817 /// Coerce the register to COP0 and return the real register for the
818 /// current target.
819 unsigned getCOP0Reg() const {
820 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
821 unsigned ClassID = Mips::COP0RegClassID;
822 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
823 }
824
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000825 /// Coerce the register to COP2 and return the real register for the
826 /// current target.
827 unsigned getCOP2Reg() const {
828 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
829 unsigned ClassID = Mips::COP2RegClassID;
830 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
831 }
832
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000833 /// Coerce the register to COP3 and return the real register for the
834 /// current target.
835 unsigned getCOP3Reg() const {
836 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
837 unsigned ClassID = Mips::COP3RegClassID;
838 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
839 }
840
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000841 /// Coerce the register to ACC64DSP and return the real register for the
842 /// current target.
843 unsigned getACC64DSPReg() const {
844 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
845 unsigned ClassID = Mips::ACC64DSPRegClassID;
846 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
847 }
848
849 /// Coerce the register to HI32DSP and return the real register for the
850 /// current target.
851 unsigned getHI32DSPReg() const {
852 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
853 unsigned ClassID = Mips::HI32DSPRegClassID;
854 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
855 }
856
857 /// Coerce the register to LO32DSP and return the real register for the
858 /// current target.
859 unsigned getLO32DSPReg() const {
860 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
861 unsigned ClassID = Mips::LO32DSPRegClassID;
862 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
863 }
864
865 /// Coerce the register to CCR and return the real register for the
866 /// current target.
867 unsigned getCCRReg() const {
868 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
869 unsigned ClassID = Mips::CCRRegClassID;
870 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
871 }
872
873 /// Coerce the register to HWRegs and return the real register for the
874 /// current target.
875 unsigned getHWRegsReg() const {
876 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
877 unsigned ClassID = Mips::HWRegsRegClassID;
878 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
879 }
880
881public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000882 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000883 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000884 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000885 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000886 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000887 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000888 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000889 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000890 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000891
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000892 void addRegOperands(MCInst &Inst, unsigned N) const {
893 llvm_unreachable("Use a custom parser instead");
894 }
895
Daniel Sanders21bce302014-04-01 12:35:23 +0000896 /// Render the operand to an MCInst as a GPR32
897 /// Asserts if the wrong number of operands are requested, or the operand
898 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000899 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
900 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000901 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000902 }
903
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000904 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
905 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000906 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000907 }
908
Jozef Kolek1904fa22014-11-24 14:25:53 +0000909 void addGPRMM16AsmRegZeroOperands(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(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000912 }
913
Zoran Jovanovic41688672015-02-10 16:36:20 +0000914 void addGPRMM16AsmRegMovePOperands(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(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000917 }
918
Daniel Sanders21bce302014-04-01 12:35:23 +0000919 /// Render the operand to an MCInst as a GPR64
920 /// Asserts if the wrong number of operands are requested, or the operand
921 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000922 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
923 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000924 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000925 }
926
927 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
928 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000929 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000930 }
931
932 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
933 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000934 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000935 }
936
937 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
938 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000939 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000940 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +0000941 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000942 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +0000943 AsmParser.getParser().printError(
944 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
945 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000946 }
947
948 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
949 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000950 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000951 }
952
953 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
954 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000955 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000956 }
957
958 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
959 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000960 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000961 }
962
963 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
964 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000965 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000966 }
967
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000968 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
969 assert(N == 1 && "Invalid number of operands!");
970 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
971 }
972
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000973 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
974 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000975 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000976 }
977
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000978 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
979 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000980 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000981 }
982
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000983 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
984 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000985 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000986 }
987
988 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
989 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000990 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000991 }
992
993 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
994 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000995 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000996 }
997
998 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
999 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001000 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001001 }
1002
1003 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1004 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001005 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001006 }
1007
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001008 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001009 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1010 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001011 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001012 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001013 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001014 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001015 Inst.addOperand(MCOperand::createImm(Imm));
1016 }
1017
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001018 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001019 void addSImmOperands(MCInst &Inst, unsigned N) const {
1020 if (isImm() && !isConstantImm()) {
1021 addExpr(Inst, getImm());
1022 return;
1023 }
1024 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1025 }
1026
1027 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001028 void addUImmOperands(MCInst &Inst, unsigned N) const {
1029 if (isImm() && !isConstantImm()) {
1030 addExpr(Inst, getImm());
1031 return;
1032 }
1033 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1034 }
1035
Daniel Sanders78e89022016-03-11 11:37:50 +00001036 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1037 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1038 assert(N == 1 && "Invalid number of operands!");
1039 int64_t Imm = getConstantImm() - Offset;
1040 Imm = SignExtend64<Bits>(Imm);
1041 Imm += Offset;
1042 Imm += AdjustOffset;
1043 Inst.addOperand(MCOperand::createImm(Imm));
1044 }
1045
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001046 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001047 assert(N == 1 && "Invalid number of operands!");
1048 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001049 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001050 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001051
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001052 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001053 assert(N == 2 && "Invalid number of operands!");
1054
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001055 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1056 ? getMemBase()->getGPR64Reg()
1057 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001058
1059 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001060 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001061 }
1062
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001063 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1064 assert(N == 2 && "Invalid number of operands!");
1065
Jim Grosbache9119e42015-05-13 18:37:00 +00001066 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001067
1068 const MCExpr *Expr = getMemOff();
1069 addExpr(Inst, Expr);
1070 }
1071
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001072 void addRegListOperands(MCInst &Inst, unsigned N) const {
1073 assert(N == 1 && "Invalid number of operands!");
1074
1075 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001076 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001077 }
1078
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001079 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1080 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001081 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001082 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001083 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1084 Inst.addOperand(MCOperand::createReg(
1085 RegIdx.RegInfo->getRegClass(
1086 AsmParser.getABI().AreGprs64bit()
1087 ? Mips::GPR64RegClassID
1088 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1089 Inst.addOperand(MCOperand::createReg(
1090 RegIdx.RegInfo->getRegClass(
1091 AsmParser.getABI().AreGprs64bit()
1092 ? Mips::GPR64RegClassID
1093 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001094 }
1095
Zoran Jovanovic41688672015-02-10 16:36:20 +00001096 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1097 assert(N == 2 && "Invalid number of operands!");
1098 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001099 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001100 }
1101
Craig Topper56c590a2014-04-29 07:58:02 +00001102 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001103 // As a special case until we sort out the definition of div/divu, accept
1104 // $0/$zero here so that MCK_ZERO works correctly.
1105 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001106 }
1107 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001108 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001109 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001110 int64_t Res;
1111 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001112 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001113 bool isConstantImmz() const {
1114 return isConstantImm() && getConstantImm() == 0;
1115 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001116 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1117 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1118 }
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001119 template <unsigned Bits> bool isSImm() const {
1120 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1121 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001122 template <unsigned Bits> bool isUImm() const {
1123 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1124 }
1125 template <unsigned Bits> bool isAnyImm() const {
1126 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1127 isUInt<Bits>(getConstantImm()))
1128 : isImm();
1129 }
Daniel Sanders78e89022016-03-11 11:37:50 +00001130 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1131 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001132 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001133 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1134 return isConstantImm() && getConstantImm() >= Bottom &&
1135 getConstantImm() <= Top;
1136 }
Craig Topper56c590a2014-04-29 07:58:02 +00001137 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001138 // Note: It's not possible to pretend that other operand kinds are tokens.
1139 // The matcher emitter checks tokens first.
1140 return Kind == k_Token;
1141 }
Craig Topper56c590a2014-04-29 07:58:02 +00001142 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001143 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001144 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001145 }
Simon Dardis4ccda502016-05-27 13:56:36 +00001146 // Allow relocation operators.
1147 // FIXME: This predicate and others need to look through binary expressions
1148 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001149 template <unsigned Bits, unsigned ShiftAmount = 0>
1150 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001151 if (!isMem())
1152 return false;
1153 if (!getMemBase()->isGPRAsmReg())
1154 return false;
1155 if (isa<MCTargetExpr>(getMemOff()) ||
1156 (isConstantMemOff() &&
1157 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1158 return true;
1159 MCValue Res;
1160 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1161 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001162 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001163 bool isMemWithGRPMM16Base() const {
1164 return isMem() && getMemBase()->isMM16AsmReg();
1165 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001166 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1167 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1168 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1169 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001170 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1171 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1172 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1173 && (getMemBase()->getGPR32Reg() == Mips::SP);
1174 }
Daniel Sanderse473dc92016-05-09 13:38:25 +00001175 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1176 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1177 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1178 && (getMemBase()->getGPR32Reg() == Mips::GP);
1179 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001180 template <unsigned Bits, unsigned ShiftLeftAmount>
1181 bool isScaledUImm() const {
1182 return isConstantImm() &&
1183 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001184 }
Daniel Sanders97297772016-03-22 14:40:00 +00001185 template <unsigned Bits, unsigned ShiftLeftAmount>
1186 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001187 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1188 return true;
1189 // Operand can also be a symbol or symbol plus offset in case of relocations.
1190 if (Kind != k_Immediate)
1191 return false;
1192 MCValue Res;
1193 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1194 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001195 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001196 bool isRegList16() const {
1197 if (!isRegList())
1198 return false;
1199
1200 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001201 if (Size < 2 || Size > 5)
1202 return false;
1203
1204 unsigned R0 = RegList.List->front();
1205 unsigned R1 = RegList.List->back();
1206 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1207 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001208 return false;
1209
1210 int PrevReg = *RegList.List->begin();
1211 for (int i = 1; i < Size - 1; i++) {
1212 int Reg = (*(RegList.List))[i];
1213 if ( Reg != PrevReg + 1)
1214 return false;
1215 PrevReg = Reg;
1216 }
1217
1218 return true;
1219 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001220 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001221 bool isLSAImm() const {
1222 if (!isConstantImm())
1223 return false;
1224 int64_t Val = getConstantImm();
1225 return 1 <= Val && Val <= 4;
1226 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001227 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001228 bool isMovePRegPair() const {
1229 if (Kind != k_RegList || RegList.List->size() != 2)
1230 return false;
1231
1232 unsigned R0 = RegList.List->front();
1233 unsigned R1 = RegList.List->back();
1234
1235 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1236 (R0 == Mips::A1 && R1 == Mips::A3) ||
1237 (R0 == Mips::A2 && R1 == Mips::A3) ||
1238 (R0 == Mips::A0 && R1 == Mips::S5) ||
1239 (R0 == Mips::A0 && R1 == Mips::S6) ||
1240 (R0 == Mips::A0 && R1 == Mips::A1) ||
1241 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001242 (R0 == Mips::A0 && R1 == Mips::A3) ||
1243 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1244 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1245 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1246 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1247 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1248 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1249 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1250 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001251 return true;
1252
1253 return false;
1254 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001255
1256 StringRef getToken() const {
1257 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001258 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001259 }
Zlatko Buljanba553a62016-05-09 08:07:28 +00001260 bool isRegPair() const {
1261 return Kind == k_RegPair && RegIdx.Index <= 30;
1262 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001263
Craig Topper56c590a2014-04-29 07:58:02 +00001264 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001265 // As a special case until we sort out the definition of div/divu, accept
1266 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001267 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1268 RegIdx.Kind & RegKind_GPR)
1269 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001270
Daniel Sanders976d9382016-07-05 13:38:40 +00001271 llvm_unreachable("Invalid access!");
1272 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001273 }
1274
Jack Carterb4dbc172012-09-05 23:34:03 +00001275 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001276 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001277 return Imm.Val;
1278 }
1279
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001280 int64_t getConstantImm() const {
1281 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001282 int64_t Value = 0;
1283 (void)Val->evaluateAsAbsolute(Value);
1284 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001285 }
1286
1287 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001288 assert((Kind == k_Memory) && "Invalid access!");
1289 return Mem.Base;
1290 }
1291
1292 const MCExpr *getMemOff() const {
1293 assert((Kind == k_Memory) && "Invalid access!");
1294 return Mem.Off;
1295 }
1296
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001297 int64_t getConstantMemOff() const {
1298 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1299 }
1300
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001301 const SmallVectorImpl<unsigned> &getRegList() const {
1302 assert((Kind == k_RegList) && "Invalid access!");
1303 return *(RegList.List);
1304 }
1305
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001306 unsigned getRegPair() const {
1307 assert((Kind == k_RegPair) && "Invalid access!");
1308 return RegIdx.Index;
1309 }
1310
David Blaikie960ea3f2014-06-08 16:18:35 +00001311 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1312 MipsAsmParser &Parser) {
1313 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001314 Op->Tok.Data = Str.data();
1315 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001316 Op->StartLoc = S;
1317 Op->EndLoc = S;
1318 return Op;
1319 }
1320
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001321 /// Create a numeric register (e.g. $1). The exact register remains
1322 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001323 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001324 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1325 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001326 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001327 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001328 }
1329
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001330 /// Create a register that is definitely a GPR.
1331 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001332 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001333 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1334 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1335 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001336 }
1337
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001338 /// Create a register that is definitely a FGR.
1339 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001340 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001341 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1342 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1343 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001344 }
1345
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001346 /// Create a register that is definitely a HWReg.
1347 /// This is typically only used for named registers such as $hwr_cpunum.
1348 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001349 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001350 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001351 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001352 }
1353
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001354 /// Create a register that is definitely an FCC.
1355 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001356 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001357 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1358 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1359 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001360 }
1361
1362 /// Create a register that is definitely an ACC.
1363 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001364 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001365 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1366 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1367 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001368 }
1369
1370 /// Create a register that is definitely an MSA128.
1371 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001372 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001373 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1374 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1375 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001376 }
1377
1378 /// Create a register that is definitely an MSACtrl.
1379 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001380 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001381 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1382 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1383 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001384 }
1385
David Blaikie960ea3f2014-06-08 16:18:35 +00001386 static std::unique_ptr<MipsOperand>
1387 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1388 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001389 Op->Imm.Val = Val;
1390 Op->StartLoc = S;
1391 Op->EndLoc = E;
1392 return Op;
1393 }
1394
David Blaikie960ea3f2014-06-08 16:18:35 +00001395 static std::unique_ptr<MipsOperand>
1396 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1397 SMLoc E, MipsAsmParser &Parser) {
1398 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1399 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001400 Op->Mem.Off = Off;
1401 Op->StartLoc = S;
1402 Op->EndLoc = E;
1403 return Op;
1404 }
1405
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001406 static std::unique_ptr<MipsOperand>
1407 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1408 MipsAsmParser &Parser) {
1409 assert (Regs.size() > 0 && "Empty list not allowed");
1410
1411 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001412 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001413 Op->StartLoc = StartLoc;
1414 Op->EndLoc = EndLoc;
1415 return Op;
1416 }
1417
Daniel Sandersd044e492016-05-09 13:10:57 +00001418 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1419 SMLoc S, SMLoc E,
1420 MipsAsmParser &Parser) {
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001421 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001422 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001423 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1424 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001425 Op->StartLoc = S;
1426 Op->EndLoc = E;
1427 return Op;
1428 }
1429
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001430 bool isGPRAsmReg() const {
1431 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001432 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001433 bool isMM16AsmReg() const {
1434 if (!(isRegIdx() && RegIdx.Kind))
1435 return false;
1436 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1437 || RegIdx.Index == 16 || RegIdx.Index == 17);
1438 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001439 bool isMM16AsmRegZero() const {
1440 if (!(isRegIdx() && RegIdx.Kind))
1441 return false;
1442 return (RegIdx.Index == 0 ||
1443 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1444 RegIdx.Index == 17);
1445 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001446 bool isMM16AsmRegMoveP() const {
1447 if (!(isRegIdx() && RegIdx.Kind))
1448 return false;
1449 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1450 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1451 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001452 bool isFGRAsmReg() const {
1453 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1454 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001455 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001456 bool isHWRegsAsmReg() const {
1457 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001458 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001459 bool isCCRAsmReg() const {
1460 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001461 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001462 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001463 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1464 return false;
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001465 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001466 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001467 bool isACCAsmReg() const {
1468 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001469 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001470 bool isCOP0AsmReg() const {
1471 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1472 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001473 bool isCOP2AsmReg() const {
1474 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001475 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001476 bool isCOP3AsmReg() const {
1477 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1478 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001479 bool isMSA128AsmReg() const {
1480 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001481 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001482 bool isMSACtrlAsmReg() const {
1483 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001484 }
1485
Jack Carterb4dbc172012-09-05 23:34:03 +00001486 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001487 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001488 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001489 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001490
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001491 virtual ~MipsOperand() {
1492 switch (Kind) {
1493 case k_Immediate:
1494 break;
1495 case k_Memory:
1496 delete Mem.Base;
1497 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001498 case k_RegList:
1499 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001500 case k_RegisterIndex:
1501 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001502 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001503 break;
1504 }
1505 }
1506
Craig Topper56c590a2014-04-29 07:58:02 +00001507 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001508 switch (Kind) {
1509 case k_Immediate:
1510 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001511 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001512 OS << ">";
1513 break;
1514 case k_Memory:
1515 OS << "Mem<";
1516 Mem.Base->print(OS);
1517 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001518 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001519 OS << ">";
1520 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001521 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001522 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1523 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001524 break;
1525 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001526 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001527 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001528 case k_RegList:
1529 OS << "RegList< ";
1530 for (auto Reg : (*RegList.List))
1531 OS << Reg << " ";
1532 OS << ">";
1533 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001534 case k_RegPair:
1535 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1536 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001537 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001538 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001539
1540 bool isValidForTie(const MipsOperand &Other) const {
1541 if (Kind != Other.Kind)
1542 return false;
1543
1544 switch (Kind) {
1545 default:
1546 llvm_unreachable("Unexpected kind");
1547 return false;
1548 case k_RegisterIndex: {
1549 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1550 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1551 return Token == OtherToken;
1552 }
1553 }
1554 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001555}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001556} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001557
Jack Carter9e65aa32013-03-22 00:05:30 +00001558namespace llvm {
1559extern const MCInstrDesc MipsInsts[];
1560}
1561static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1562 return MipsInsts[Opcode];
1563}
1564
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001565static bool hasShortDelaySlot(unsigned Opcode) {
1566 switch (Opcode) {
1567 case Mips::JALS_MM:
1568 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001569 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001570 case Mips::BGEZALS_MM:
1571 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001572 return true;
1573 default:
1574 return false;
1575 }
1576}
1577
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001578static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1579 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1580 return &SRExpr->getSymbol();
1581 }
1582
1583 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1584 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1585 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1586
1587 if (LHSSym)
1588 return LHSSym;
1589
1590 if (RHSSym)
1591 return RHSSym;
1592
1593 return nullptr;
1594 }
1595
1596 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1597 return getSingleMCSymbol(UExpr->getSubExpr());
1598
1599 return nullptr;
1600}
1601
1602static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1603 if (isa<MCSymbolRefExpr>(Expr))
1604 return 1;
1605
1606 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1607 return countMCSymbolRefExpr(BExpr->getLHS()) +
1608 countMCSymbolRefExpr(BExpr->getRHS());
1609
1610 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1611 return countMCSymbolRefExpr(UExpr->getSubExpr());
1612
1613 return 0;
1614}
1615
Jack Carter9e65aa32013-03-22 00:05:30 +00001616bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001617 MCStreamer &Out,
1618 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001619 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001620 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001621 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001622
Jack Carter9e65aa32013-03-22 00:05:30 +00001623 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001624
1625 if (MCID.isBranch() || MCID.isCall()) {
1626 const unsigned Opcode = Inst.getOpcode();
1627 MCOperand Offset;
1628
1629 switch (Opcode) {
1630 default:
1631 break;
Kai Nackee0245392015-01-27 19:11:28 +00001632 case Mips::BBIT0:
1633 case Mips::BBIT032:
1634 case Mips::BBIT1:
1635 case Mips::BBIT132:
1636 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001637 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001638
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001639 case Mips::BEQ:
1640 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001641 case Mips::BEQ_MM:
1642 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001643 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001644 Offset = Inst.getOperand(2);
1645 if (!Offset.isImm())
1646 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001647 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001648 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001649 if (OffsetToAlignment(Offset.getImm(),
1650 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001651 return Error(IDLoc, "branch to misaligned address");
1652 break;
1653 case Mips::BGEZ:
1654 case Mips::BGTZ:
1655 case Mips::BLEZ:
1656 case Mips::BLTZ:
1657 case Mips::BGEZAL:
1658 case Mips::BLTZAL:
1659 case Mips::BC1F:
1660 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001661 case Mips::BGEZ_MM:
1662 case Mips::BGTZ_MM:
1663 case Mips::BLEZ_MM:
1664 case Mips::BLTZ_MM:
1665 case Mips::BGEZAL_MM:
1666 case Mips::BLTZAL_MM:
1667 case Mips::BC1F_MM:
1668 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001669 case Mips::BC1EQZC_MMR6:
1670 case Mips::BC1NEZC_MMR6:
1671 case Mips::BC2EQZC_MMR6:
1672 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001673 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001674 Offset = Inst.getOperand(1);
1675 if (!Offset.isImm())
1676 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001677 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001678 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001679 if (OffsetToAlignment(Offset.getImm(),
1680 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001681 return Error(IDLoc, "branch to misaligned address");
1682 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001683 case Mips::BGEC: case Mips::BGEC_MMR6:
1684 case Mips::BLTC: case Mips::BLTC_MMR6:
1685 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1686 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1687 case Mips::BEQC: case Mips::BEQC_MMR6:
1688 case Mips::BNEC: case Mips::BNEC_MMR6:
1689 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1690 Offset = Inst.getOperand(2);
1691 if (!Offset.isImm())
1692 break; // We'll deal with this situation later on when applying fixups.
1693 if (!isIntN(18, Offset.getImm()))
1694 return Error(IDLoc, "branch target out of range");
1695 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1696 return Error(IDLoc, "branch to misaligned address");
1697 break;
1698 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1699 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1700 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1701 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1702 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1703 Offset = Inst.getOperand(1);
1704 if (!Offset.isImm())
1705 break; // We'll deal with this situation later on when applying fixups.
1706 if (!isIntN(18, Offset.getImm()))
1707 return Error(IDLoc, "branch target out of range");
1708 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1709 return Error(IDLoc, "branch to misaligned address");
1710 break;
1711 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1712 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1713 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1714 Offset = Inst.getOperand(1);
1715 if (!Offset.isImm())
1716 break; // We'll deal with this situation later on when applying fixups.
1717 if (!isIntN(23, Offset.getImm()))
1718 return Error(IDLoc, "branch target out of range");
1719 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1720 return Error(IDLoc, "branch to misaligned address");
1721 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001722 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001723 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001724 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001725 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001726 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1727 Offset = Inst.getOperand(1);
1728 if (!Offset.isImm())
1729 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001730 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001731 return Error(IDLoc, "branch target out of range");
1732 if (OffsetToAlignment(Offset.getImm(), 2LL))
1733 return Error(IDLoc, "branch to misaligned address");
1734 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001735 }
1736 }
1737
Daniel Sandersa84989a2014-06-16 13:25:35 +00001738 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1739 // We still accept it but it is a normal nop.
1740 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1741 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1742 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1743 "nop instruction");
1744 }
1745
Kai Nackee0245392015-01-27 19:11:28 +00001746 if (hasCnMips()) {
1747 const unsigned Opcode = Inst.getOpcode();
1748 MCOperand Opnd;
1749 int Imm;
1750
1751 switch (Opcode) {
1752 default:
1753 break;
1754
1755 case Mips::BBIT0:
1756 case Mips::BBIT032:
1757 case Mips::BBIT1:
1758 case Mips::BBIT132:
1759 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1760 // The offset is handled above
1761 Opnd = Inst.getOperand(1);
1762 if (!Opnd.isImm())
1763 return Error(IDLoc, "expected immediate operand kind");
1764 Imm = Opnd.getImm();
1765 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1766 Opcode == Mips::BBIT1 ? 63 : 31))
1767 return Error(IDLoc, "immediate operand value out of range");
1768 if (Imm > 31) {
1769 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1770 : Mips::BBIT132);
1771 Inst.getOperand(1).setImm(Imm - 32);
1772 }
1773 break;
1774
Kai Nackee0245392015-01-27 19:11:28 +00001775 case Mips::SEQi:
1776 case Mips::SNEi:
1777 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1778 Opnd = Inst.getOperand(2);
1779 if (!Opnd.isImm())
1780 return Error(IDLoc, "expected immediate operand kind");
1781 Imm = Opnd.getImm();
1782 if (!isInt<10>(Imm))
1783 return Error(IDLoc, "immediate operand value out of range");
1784 break;
1785 }
1786 }
1787
Simon Atanasyan50485142016-12-12 17:40:26 +00001788 // For PIC code convert unconditional jump to unconditional branch.
1789 if ((Inst.getOpcode() == Mips::J || Inst.getOpcode() == Mips::J_MM) &&
1790 inPicMode()) {
1791 MCInst BInst;
1792 BInst.setOpcode(inMicroMipsMode() ? Mips::BEQ_MM : Mips::BEQ);
1793 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1794 BInst.addOperand(MCOperand::createReg(Mips::ZERO));
1795 BInst.addOperand(Inst.getOperand(0));
1796 Inst = BInst;
1797 }
1798
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001799 // This expansion is not in a function called by tryExpandInstruction()
1800 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001801 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1802 inPicMode()) {
1803 warnIfNoMacro(IDLoc);
1804
1805 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1806
1807 // We can do this expansion if there's only 1 symbol in the argument
1808 // expression.
1809 if (countMCSymbolRefExpr(JalExpr) > 1)
1810 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1811
1812 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001813 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001814 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1815
1816 // FIXME: Add support for label+offset operands (currently causes an error).
1817 // FIXME: Add support for forward-declared local symbols.
1818 // FIXME: Add expansion for when the LargeGOT option is enabled.
Simon Dardisc08af6d2016-11-25 11:06:43 +00001819 if (JalSym->isInSection() || JalSym->isTemporary() ||
1820 (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) {
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001821 if (isABI_O32()) {
1822 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001823 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001824 // R_(MICRO)MIPS_GOT16 label
1825 // addiu $25, $25, 0
1826 // R_(MICRO)MIPS_LO16 label
1827 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001828 const MCExpr *Got16RelocExpr =
1829 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1830 const MCExpr *Lo16RelocExpr =
1831 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001832
Daniel Sandersa736b372016-04-29 13:33:12 +00001833 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1834 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1835 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1836 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001837 } else if (isABI_N32() || isABI_N64()) {
1838 // If it's a local symbol and the N32/N64 ABIs are being used,
1839 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001840 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001841 // R_(MICRO)MIPS_GOT_DISP label
1842 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001843 const MCExpr *GotDispRelocExpr =
1844 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001845
Daniel Sandersa736b372016-04-29 13:33:12 +00001846 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1847 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1848 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001849 }
1850 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001851 // If it's an external/weak symbol, we expand to:
1852 // lw/ld $25, 0($gp)
1853 // R_(MICRO)MIPS_CALL16 label
1854 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001855 const MCExpr *Call16RelocExpr =
1856 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001857
Daniel Sandersa736b372016-04-29 13:33:12 +00001858 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1859 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001860 }
1861
1862 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001863 if (IsCpRestoreSet && inMicroMipsMode())
1864 JalrInst.setOpcode(Mips::JALRS_MM);
1865 else
1866 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001867 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1868 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1869
1870 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1871 // This relocation is supposed to be an optimization hint for the linker
1872 // and is not necessary for correctness.
1873
1874 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001875 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001876 }
1877
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001878 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
1879 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001880 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001881 // reference or immediate we may have to expand instructions.
1882 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001883 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001884 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1885 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001886 MCOperand &Op = Inst.getOperand(i);
1887 if (Op.isImm()) {
1888 int MemOffset = Op.getImm();
1889 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001890 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001891 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00001892 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001893 }
1894 } else if (Op.isExpr()) {
1895 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001896 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001897 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001898 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001899 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001900 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001901 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00001902 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001903 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001904 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001905 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00001906 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001907 }
1908 }
1909 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001910 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001911 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001912
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001913 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001914 if (MCID.mayLoad()) {
1915 // Try to create 16-bit GP relative load instruction.
1916 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1917 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1918 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1919 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1920 MCOperand &Op = Inst.getOperand(i);
1921 if (Op.isImm()) {
1922 int MemOffset = Op.getImm();
1923 MCOperand &DstReg = Inst.getOperand(0);
1924 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001925 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001926 getContext().getRegisterInfo()->getRegClass(
1927 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001928 (BaseReg.getReg() == Mips::GP ||
1929 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001930
Daniel Sandersa736b372016-04-29 13:33:12 +00001931 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1932 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001933 return false;
1934 }
1935 }
1936 }
1937 } // for
1938 } // if load
1939
1940 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1941
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001942 MCOperand Opnd;
1943 int Imm;
1944
1945 switch (Inst.getOpcode()) {
1946 default:
1947 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001948 case Mips::ADDIUSP_MM:
1949 Opnd = Inst.getOperand(0);
1950 if (!Opnd.isImm())
1951 return Error(IDLoc, "expected immediate operand kind");
1952 Imm = Opnd.getImm();
1953 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1954 Imm % 4 != 0)
1955 return Error(IDLoc, "immediate operand value out of range");
1956 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001957 case Mips::SLL16_MM:
1958 case Mips::SRL16_MM:
1959 Opnd = Inst.getOperand(2);
1960 if (!Opnd.isImm())
1961 return Error(IDLoc, "expected immediate operand kind");
1962 Imm = Opnd.getImm();
1963 if (Imm < 1 || Imm > 8)
1964 return Error(IDLoc, "immediate operand value out of range");
1965 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001966 case Mips::LI16_MM:
1967 Opnd = Inst.getOperand(1);
1968 if (!Opnd.isImm())
1969 return Error(IDLoc, "expected immediate operand kind");
1970 Imm = Opnd.getImm();
1971 if (Imm < -1 || Imm > 126)
1972 return Error(IDLoc, "immediate operand value out of range");
1973 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001974 case Mips::ADDIUR2_MM:
1975 Opnd = Inst.getOperand(2);
1976 if (!Opnd.isImm())
1977 return Error(IDLoc, "expected immediate operand kind");
1978 Imm = Opnd.getImm();
1979 if (!(Imm == 1 || Imm == -1 ||
1980 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1981 return Error(IDLoc, "immediate operand value out of range");
1982 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001983 case Mips::ANDI16_MM:
1984 Opnd = Inst.getOperand(2);
1985 if (!Opnd.isImm())
1986 return Error(IDLoc, "expected immediate operand kind");
1987 Imm = Opnd.getImm();
1988 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1989 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1990 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1991 return Error(IDLoc, "immediate operand value out of range");
1992 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001993 case Mips::LBU16_MM:
1994 Opnd = Inst.getOperand(2);
1995 if (!Opnd.isImm())
1996 return Error(IDLoc, "expected immediate operand kind");
1997 Imm = Opnd.getImm();
1998 if (Imm < -1 || Imm > 14)
1999 return Error(IDLoc, "immediate operand value out of range");
2000 break;
2001 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002002 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002003 Opnd = Inst.getOperand(2);
2004 if (!Opnd.isImm())
2005 return Error(IDLoc, "expected immediate operand kind");
2006 Imm = Opnd.getImm();
2007 if (Imm < 0 || Imm > 15)
2008 return Error(IDLoc, "immediate operand value out of range");
2009 break;
2010 case Mips::LHU16_MM:
2011 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002012 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002013 Opnd = Inst.getOperand(2);
2014 if (!Opnd.isImm())
2015 return Error(IDLoc, "expected immediate operand kind");
2016 Imm = Opnd.getImm();
2017 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2018 return Error(IDLoc, "immediate operand value out of range");
2019 break;
2020 case Mips::LW16_MM:
2021 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002022 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002023 Opnd = Inst.getOperand(2);
2024 if (!Opnd.isImm())
2025 return Error(IDLoc, "expected immediate operand kind");
2026 Imm = Opnd.getImm();
2027 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2028 return Error(IDLoc, "immediate operand value out of range");
2029 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002030 case Mips::ADDIUPC_MM:
2031 MCOperand Opnd = Inst.getOperand(1);
2032 if (!Opnd.isImm())
2033 return Error(IDLoc, "expected immediate operand kind");
2034 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002035 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002036 return Error(IDLoc, "immediate operand value out of range");
2037 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002038 }
2039 }
2040
Daniel Sandersd8c07762016-04-18 12:35:36 +00002041 bool FillDelaySlot =
2042 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2043 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002044 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002045
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002046 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002047 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002048 switch (ExpandResult) {
2049 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002050 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002051 break;
2052 case MER_Success:
2053 break;
2054 case MER_Fail:
2055 return true;
2056 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002057
Daniel Sanderscda908a2016-05-16 09:10:13 +00002058 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2059 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2060 if (inMicroMipsMode())
2061 TOut.setUsesMicroMips();
2062
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002063 // If this instruction has a delay slot and .set reorder is active,
2064 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002065 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002066 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2067 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002068 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002069
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002070 if ((Inst.getOpcode() == Mips::JalOneReg ||
2071 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2072 isPicAndNotNxxAbi()) {
2073 if (IsCpRestoreSet) {
2074 // We need a NOP between the JALR and the LW:
2075 // If .set reorder has been used, we've already emitted a NOP.
2076 // If .set noreorder has been used, we need to emit a NOP at this point.
2077 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002078 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2079 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002080
2081 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002082 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002083 } else
2084 Warning(IDLoc, "no .cprestore used in PIC mode");
2085 }
2086
Jack Carter9e65aa32013-03-22 00:05:30 +00002087 return false;
2088}
2089
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002090MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002091MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2092 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002093 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002094 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002095 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002096 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002097 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002098 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002099 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002100 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002101 case Mips::LoadAddrImm64:
2102 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2103 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2104 "expected immediate operand kind");
2105
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002106 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2107 Inst.getOperand(1),
2108 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002109 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002110 ? MER_Fail
2111 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002112 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002113 case Mips::LoadAddrReg64:
2114 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2115 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2116 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2117 "expected immediate operand kind");
2118
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002119 return expandLoadAddress(Inst.getOperand(0).getReg(),
2120 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2121 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002122 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002123 ? MER_Fail
2124 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002125 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002126 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002127 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2128 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002129 case Mips::SWM_MM:
2130 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002131 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2132 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002133 case Mips::JalOneReg:
2134 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002135 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002136 case Mips::BneImm:
2137 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002138 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002139 case Mips::BLT:
2140 case Mips::BLE:
2141 case Mips::BGE:
2142 case Mips::BGT:
2143 case Mips::BLTU:
2144 case Mips::BLEU:
2145 case Mips::BGEU:
2146 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002147 case Mips::BLTL:
2148 case Mips::BLEL:
2149 case Mips::BGEL:
2150 case Mips::BGTL:
2151 case Mips::BLTUL:
2152 case Mips::BLEUL:
2153 case Mips::BGEUL:
2154 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002155 case Mips::BLTImmMacro:
2156 case Mips::BLEImmMacro:
2157 case Mips::BGEImmMacro:
2158 case Mips::BGTImmMacro:
2159 case Mips::BLTUImmMacro:
2160 case Mips::BLEUImmMacro:
2161 case Mips::BGEUImmMacro:
2162 case Mips::BGTUImmMacro:
2163 case Mips::BLTLImmMacro:
2164 case Mips::BLELImmMacro:
2165 case Mips::BGELImmMacro:
2166 case Mips::BGTLImmMacro:
2167 case Mips::BLTULImmMacro:
2168 case Mips::BLEULImmMacro:
2169 case Mips::BGEULImmMacro:
2170 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002171 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002172 case Mips::SDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002173 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2174 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002175 case Mips::DSDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002176 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2177 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002178 case Mips::UDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002179 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2180 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002181 case Mips::DUDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002182 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2183 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002184 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002185 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2186 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002187 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002188 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002189 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002190 case Mips::PseudoTRUNC_W_D:
2191 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2192 : MER_Success;
2193 case Mips::Ulh:
2194 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2195 case Mips::Ulhu:
2196 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002197 case Mips::Ush:
2198 return expandUsh(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002199 case Mips::Ulw:
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00002200 case Mips::Usw:
2201 return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002202 case Mips::NORImm:
2203 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002204 case Mips::ADDi:
2205 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002206 case Mips::SLTi:
2207 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002208 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2209 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2210 int64_t ImmValue = Inst.getOperand(2).getImm();
2211 if (isInt<16>(ImmValue))
2212 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002213 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2214 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002215 }
2216 return MER_NotAMacro;
2217 case Mips::ANDi:
2218 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002219 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002220 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2221 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2222 int64_t ImmValue = Inst.getOperand(2).getImm();
2223 if (isUInt<16>(ImmValue))
2224 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002225 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2226 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002227 }
2228 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002229 case Mips::ROL:
2230 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002231 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002232 case Mips::ROLImm:
2233 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002234 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002235 case Mips::DROL:
2236 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002237 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002238 case Mips::DROLImm:
2239 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002240 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002241 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002242 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002243 case Mips::LDMacro:
2244 case Mips::SDMacro:
2245 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2246 Inst.getOpcode() == Mips::LDMacro)
2247 ? MER_Fail
2248 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002249 case Mips::SEQMacro:
2250 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2251 case Mips::SEQIMacro:
2252 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002253 }
Jack Carter30a59822012-10-04 04:03:53 +00002254}
Jack Carter92995f12012-10-06 00:53:28 +00002255
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002256bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002257 MCStreamer &Out,
2258 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002259 MipsTargetStreamer &TOut = getTargetStreamer();
2260
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002261 // Create a JALR instruction which is going to replace the pseudo-JAL.
2262 MCInst JalrInst;
2263 JalrInst.setLoc(IDLoc);
2264 const MCOperand FirstRegOp = Inst.getOperand(0);
2265 const unsigned Opcode = Inst.getOpcode();
2266
2267 if (Opcode == Mips::JalOneReg) {
2268 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002269 if (IsCpRestoreSet && inMicroMipsMode()) {
2270 JalrInst.setOpcode(Mips::JALRS16_MM);
2271 JalrInst.addOperand(FirstRegOp);
2272 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002273 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002274 JalrInst.addOperand(FirstRegOp);
2275 } else {
2276 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002277 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002278 JalrInst.addOperand(FirstRegOp);
2279 }
2280 } else if (Opcode == Mips::JalTwoReg) {
2281 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002282 if (IsCpRestoreSet && inMicroMipsMode())
2283 JalrInst.setOpcode(Mips::JALRS_MM);
2284 else
2285 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002286 JalrInst.addOperand(FirstRegOp);
2287 const MCOperand SecondRegOp = Inst.getOperand(1);
2288 JalrInst.addOperand(SecondRegOp);
2289 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002290 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002291
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002292 // If .set reorder is active and branch instruction has a delay slot,
2293 // emit a NOP after it.
2294 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002295 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2296 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2297 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002298
2299 return false;
2300}
2301
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002302/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002303template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002304 unsigned BitNum = findFirstSet(x);
2305
2306 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2307}
2308
2309/// Load (or add) an immediate into a register.
2310///
2311/// @param ImmValue The immediate to load.
2312/// @param DstReg The register that will hold the immediate.
2313/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2314/// for a simple initialization.
2315/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2316/// @param IsAddress True if the immediate represents an address. False if it
2317/// is an integer.
2318/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002319bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002320 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002321 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2322 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002323 MipsTargetStreamer &TOut = getTargetStreamer();
2324
Toma Tabacu00e98672015-05-01 12:19:27 +00002325 if (!Is32BitImm && !isGP64bit()) {
2326 Error(IDLoc, "instruction requires a 64-bit architecture");
2327 return true;
2328 }
2329
Daniel Sanders03f9c012015-07-14 12:24:22 +00002330 if (Is32BitImm) {
2331 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2332 // Sign extend up to 64-bit so that the predicates match the hardware
2333 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2334 // true.
2335 ImmValue = SignExtend64<32>(ImmValue);
2336 } else {
2337 Error(IDLoc, "instruction requires a 32-bit immediate");
2338 return true;
2339 }
2340 }
2341
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002342 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2343 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2344
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002345 bool UseSrcReg = false;
2346 if (SrcReg != Mips::NoRegister)
2347 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002348
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002349 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002350 if (UseSrcReg &&
2351 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002352 // At this point we need AT to perform the expansions and we exit if it is
2353 // not available.
2354 unsigned ATReg = getATReg(IDLoc);
2355 if (!ATReg)
2356 return true;
2357 TmpReg = ATReg;
2358 }
2359
Daniel Sanders03f9c012015-07-14 12:24:22 +00002360 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002361 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002362 SrcReg = ZeroReg;
2363
2364 // This doesn't quite follow the usual ABI expectations for N32 but matches
2365 // traditional assembler behaviour. N32 would normally use addiu for both
2366 // integers and addresses.
2367 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002368 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002369 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002370 }
2371
Daniel Sandersa736b372016-04-29 13:33:12 +00002372 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002373 return false;
2374 }
2375
2376 if (isUInt<16>(ImmValue)) {
2377 unsigned TmpReg = DstReg;
2378 if (SrcReg == DstReg) {
2379 TmpReg = getATReg(IDLoc);
2380 if (!TmpReg)
2381 return true;
2382 }
2383
Daniel Sandersa736b372016-04-29 13:33:12 +00002384 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002385 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002386 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002387 return false;
2388 }
2389
2390 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002391 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002392
Toma Tabacu79588102015-04-29 10:19:56 +00002393 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2394 uint16_t Bits15To0 = ImmValue & 0xffff;
2395
Toma Tabacua3d056f2015-05-15 09:42:11 +00002396 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002397 // Traditional behaviour seems to special case this particular value. It's
2398 // not clear why other masks are handled differently.
2399 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002400 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2401 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002402 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002403 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002404 return false;
2405 }
2406
2407 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002408 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002409 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2410 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002411 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002412 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002413 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002414 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002415 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002416 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002417
Daniel Sandersa736b372016-04-29 13:33:12 +00002418 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002419 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002420 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002421 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002422 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002423 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002424 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002425
2426 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2427 if (Is32BitImm) {
2428 Error(IDLoc, "instruction requires a 32-bit immediate");
2429 return true;
2430 }
2431
2432 // Traditionally, these immediates are shifted as little as possible and as
2433 // such we align the most significant bit to bit 15 of our temporary.
2434 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2435 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2436 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2437 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002438 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2439 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002440
2441 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002442 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002443
2444 return false;
2445 }
2446
2447 warnIfNoMacro(IDLoc);
2448
2449 // The remaining case is packed with a sequence of dsll and ori with zeros
2450 // being omitted and any neighbouring dsll's being coalesced.
2451 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2452
2453 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2454 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002455 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002456 return false;
2457
2458 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2459 // skip it and defer the shift to the next chunk.
2460 unsigned ShiftCarriedForwards = 16;
2461 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2462 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2463
2464 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002465 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2466 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002467 ShiftCarriedForwards = 0;
2468 }
2469
2470 ShiftCarriedForwards += 16;
2471 }
2472 ShiftCarriedForwards -= 16;
2473
2474 // Finish any remaining shifts left by trailing zeros.
2475 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002476 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002477
2478 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002479 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002480
Matheus Almeida3813d572014-06-19 14:39:14 +00002481 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002482}
Jack Carter92995f12012-10-06 00:53:28 +00002483
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002484bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002485 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002486 const MCOperand &ImmOp = Inst.getOperand(1);
2487 assert(ImmOp.isImm() && "expected immediate operand kind");
2488 const MCOperand &DstRegOp = Inst.getOperand(0);
2489 assert(DstRegOp.isReg() && "expected register operand kind");
2490
2491 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002492 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002493 return true;
2494
2495 return false;
2496}
2497
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002498bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2499 const MCOperand &Offset,
2500 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002501 MCStreamer &Out,
2502 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002503 // la can't produce a usable address when addresses are 64-bit.
2504 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2505 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2506 // We currently can't do this because we depend on the equality
2507 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2508 Error(IDLoc, "la used to load 64-bit address");
2509 // Continue as if we had 'dla' instead.
2510 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002511 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002512 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002513
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002514 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002515 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002516 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002517 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002518 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002519
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002520 if (!Offset.isImm())
2521 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002522 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002523
Scott Egerton24557012016-01-21 15:11:01 +00002524 if (!ABI.ArePtrs64bit()) {
2525 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2526 Is32BitAddress = true;
2527 }
2528
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002529 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002530 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002531}
2532
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002533bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2534 unsigned DstReg, unsigned SrcReg,
2535 bool Is32BitSym, SMLoc IDLoc,
2536 MCStreamer &Out,
2537 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002538 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002539 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002540 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002541
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002542 if (inPicMode() && ABI.IsO32()) {
2543 MCValue Res;
2544 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2545 Error(IDLoc, "expected relocatable expression");
2546 return true;
2547 }
2548 if (Res.getSymB() != nullptr) {
2549 Error(IDLoc, "expected relocatable expression with only one symbol");
2550 return true;
2551 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002552
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002553 // The case where the result register is $25 is somewhat special. If the
2554 // symbol in the final relocation is external and not modified with a
2555 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2556 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2557 Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
2558 !Res.getSymA()->getSymbol().isTemporary()) {
2559 const MCExpr *CallExpr =
2560 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2561 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2562 MCOperand::createExpr(CallExpr), IDLoc, STI);
2563 return false;
2564 }
2565
2566 // The remaining cases are:
2567 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2568 // >addiu $tmp, $tmp, %lo(offset)
2569 // >addiu $rd, $tmp, $rs
2570 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2571 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2572 // >addiu $rd, $tmp, $rs
2573 // The addiu's marked with a '>' may be omitted if they are redundant. If
2574 // this happens then the last instruction must use $rd as the result
2575 // register.
2576 const MipsMCExpr *GotExpr =
2577 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2578 const MCExpr *LoExpr = nullptr;
2579 if (Res.getSymA()->getSymbol().isInSection() ||
2580 Res.getSymA()->getSymbol().isTemporary())
2581 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2582 else if (Res.getConstant() != 0) {
2583 // External symbols fully resolve the symbol with just the %got(symbol)
2584 // but we must still account for any offset to the symbol for expressions
2585 // like symbol+8.
2586 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2587 }
2588
2589 unsigned TmpReg = DstReg;
2590 if (UseSrcReg &&
2591 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2592 SrcReg)) {
2593 // If $rs is the same as $rd, we need to use AT.
2594 // If it is not available we exit.
2595 unsigned ATReg = getATReg(IDLoc);
2596 if (!ATReg)
2597 return true;
2598 TmpReg = ATReg;
2599 }
2600
2601 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2602 MCOperand::createExpr(GotExpr), IDLoc, STI);
2603
2604 if (LoExpr)
2605 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2606 IDLoc, STI);
2607
2608 if (UseSrcReg)
2609 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2610
2611 return false;
2612 }
2613
2614 const MipsMCExpr *HiExpr =
2615 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2616 const MipsMCExpr *LoExpr =
2617 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002618
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002619 // This is the 64-bit symbol address expansion.
2620 if (ABI.ArePtrs64bit() && isGP64bit()) {
2621 // We always need AT for the 64-bit expansion.
2622 // If it is not available we exit.
2623 unsigned ATReg = getATReg(IDLoc);
2624 if (!ATReg)
2625 return true;
2626
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002627 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002628 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002629 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002630 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002631
Scott Egerton24557012016-01-21 15:11:01 +00002632 if (UseSrcReg &&
2633 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2634 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002635 // If $rs is the same as $rd:
2636 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2637 // daddiu $at, $at, %higher(sym)
2638 // dsll $at, $at, 16
2639 // daddiu $at, $at, %hi(sym)
2640 // dsll $at, $at, 16
2641 // daddiu $at, $at, %lo(sym)
2642 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002643 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2644 STI);
2645 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2646 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2647 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2648 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2649 IDLoc, STI);
2650 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2651 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2652 IDLoc, STI);
2653 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002654
2655 return false;
2656 }
2657
2658 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2659 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2660 // lui $at, %hi(sym)
2661 // daddiu $rd, $rd, %higher(sym)
2662 // daddiu $at, $at, %lo(sym)
2663 // dsll32 $rd, $rd, 0
2664 // daddu $rd, $rd, $at
2665 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002666 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2667 STI);
2668 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2669 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2670 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2671 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2672 IDLoc, STI);
2673 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2674 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002675 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002676 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002677
2678 return false;
2679 }
2680
2681 // And now, the 32-bit symbol address expansion:
2682 // If $rs is the same as $rd:
2683 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2684 // ori $at, $at, %lo(sym)
2685 // addu $rd, $at, $rd
2686 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2687 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2688 // ori $rd, $rd, %lo(sym)
2689 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002690 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002691 if (UseSrcReg &&
2692 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002693 // If $rs is the same as $rd, we need to use AT.
2694 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002695 unsigned ATReg = getATReg(IDLoc);
2696 if (!ATReg)
2697 return true;
2698 TmpReg = ATReg;
2699 }
2700
Daniel Sandersa736b372016-04-29 13:33:12 +00002701 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2702 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2703 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002704
Toma Tabacufb9d1252015-06-22 12:08:39 +00002705 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002706 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002707 else
Scott Egerton24557012016-01-21 15:11:01 +00002708 assert(
2709 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002710
Toma Tabacu674825c2015-06-16 12:16:24 +00002711 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002712}
2713
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002714bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2715 MCStreamer &Out,
2716 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002717 MipsTargetStreamer &TOut = getTargetStreamer();
2718
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002719 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2720 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002721
2722 MCOperand Offset = Inst.getOperand(0);
2723 if (Offset.isExpr()) {
2724 Inst.clear();
2725 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002726 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2727 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2728 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002729 } else {
2730 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002731 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002732 // If offset fits into 11 bits then this instruction becomes microMIPS
2733 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002734 if (inMicroMipsMode())
2735 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002736 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002737 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00002738 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002739 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00002740 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002741 Inst.clear();
2742 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002743 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2744 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2745 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002746 }
2747 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002748 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002749
Zoran Jovanovicada70912015-09-07 11:56:37 +00002750 // If .set reorder is active and branch instruction has a delay slot,
2751 // emit a NOP after it.
2752 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2753 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002754 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002755
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002756 return false;
2757}
2758
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002759bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2760 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002761 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002762 const MCOperand &DstRegOp = Inst.getOperand(0);
2763 assert(DstRegOp.isReg() && "expected register operand kind");
2764
2765 const MCOperand &ImmOp = Inst.getOperand(1);
2766 assert(ImmOp.isImm() && "expected immediate operand kind");
2767
2768 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002769 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2770 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002771
2772 unsigned OpCode = 0;
2773 switch(Inst.getOpcode()) {
2774 case Mips::BneImm:
2775 OpCode = Mips::BNE;
2776 break;
2777 case Mips::BeqImm:
2778 OpCode = Mips::BEQ;
2779 break;
2780 default:
2781 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2782 break;
2783 }
2784
2785 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002786 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002787 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2788 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002789 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002790 warnIfNoMacro(IDLoc);
2791
2792 unsigned ATReg = getATReg(IDLoc);
2793 if (!ATReg)
2794 return true;
2795
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002796 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002797 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002798 return true;
2799
Daniel Sandersa736b372016-04-29 13:33:12 +00002800 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002801 }
2802 return false;
2803}
2804
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002805void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002806 const MCSubtargetInfo *STI, bool IsLoad,
2807 bool IsImmOpnd) {
2808 if (IsLoad) {
2809 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2810 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002811 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002812 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2813}
2814
2815void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2816 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2817 MipsTargetStreamer &TOut = getTargetStreamer();
2818
2819 unsigned DstReg = Inst.getOperand(0).getReg();
2820 unsigned BaseReg = Inst.getOperand(1).getReg();
2821
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002822 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002823 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2824 unsigned DstRegClassID =
2825 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2826 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2827 (DstRegClassID == Mips::GPR64RegClassID);
2828
2829 if (IsImmOpnd) {
2830 // Try to use DstReg as the temporary.
2831 if (IsGPR && (BaseReg != DstReg)) {
2832 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2833 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2834 STI);
2835 return;
2836 }
2837
Matheus Almeida7de68e72014-06-18 14:46:05 +00002838 // At this point we need AT to perform the expansions and we exit if it is
2839 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002840 unsigned ATReg = getATReg(IDLoc);
2841 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002842 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002843
2844 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2845 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2846 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002847 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002848
Daniel Sandersfba875f2016-04-29 13:43:45 +00002849 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002850 MCOperand LoOperand = MCOperand::createExpr(
2851 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2852 MCOperand HiOperand = MCOperand::createExpr(
2853 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002854
2855 // Try to use DstReg as the temporary.
2856 if (IsGPR && (BaseReg != DstReg)) {
2857 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2858 LoOperand, DstReg, IDLoc, STI);
2859 return;
2860 }
2861
2862 // At this point we need AT to perform the expansions and we exit if it is
2863 // not available.
2864 unsigned ATReg = getATReg(IDLoc);
2865 if (!ATReg)
2866 return;
2867
2868 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2869 LoOperand, ATReg, IDLoc, STI);
2870}
2871
2872void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2873 const MCSubtargetInfo *STI,
2874 bool IsImmOpnd) {
2875 MipsTargetStreamer &TOut = getTargetStreamer();
2876
2877 unsigned SrcReg = Inst.getOperand(0).getReg();
2878 unsigned BaseReg = Inst.getOperand(1).getReg();
2879
Daniel Sanders241c6792016-05-12 14:01:50 +00002880 if (IsImmOpnd) {
2881 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2882 Inst.getOperand(2).getImm(),
2883 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
2884 return;
2885 }
2886
Daniel Sandersfba875f2016-04-29 13:43:45 +00002887 unsigned ATReg = getATReg(IDLoc);
2888 if (!ATReg)
2889 return;
2890
Daniel Sandersfba875f2016-04-29 13:43:45 +00002891 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002892 MCOperand LoOperand = MCOperand::createExpr(
2893 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2894 MCOperand HiOperand = MCOperand::createExpr(
2895 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002896 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2897 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002898}
2899
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002900bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2901 MCStreamer &Out,
2902 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002903 unsigned OpNum = Inst.getNumOperands();
2904 unsigned Opcode = Inst.getOpcode();
2905 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2906
2907 assert (Inst.getOperand(OpNum - 1).isImm() &&
2908 Inst.getOperand(OpNum - 2).isReg() &&
2909 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2910
2911 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2912 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002913 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2914 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2915 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2916 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002917 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002918 if (inMicroMipsMode() && hasMips32r6())
2919 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2920 else
2921 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2922 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002923
2924 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002925 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002926 return false;
2927}
2928
Toma Tabacu1a108322015-06-17 13:20:24 +00002929bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002930 MCStreamer &Out,
2931 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002932 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002933 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002934 unsigned PseudoOpcode = Inst.getOpcode();
2935 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002936 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002937 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2938
2939 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002940 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002941
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002942 unsigned TrgReg;
2943 if (TrgOp.isReg())
2944 TrgReg = TrgOp.getReg();
2945 else if (TrgOp.isImm()) {
2946 warnIfNoMacro(IDLoc);
2947 EmittedNoMacroWarning = true;
2948
2949 TrgReg = getATReg(IDLoc);
2950 if (!TrgReg)
2951 return true;
2952
2953 switch(PseudoOpcode) {
2954 default:
2955 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2956 case Mips::BLTImmMacro:
2957 PseudoOpcode = Mips::BLT;
2958 break;
2959 case Mips::BLEImmMacro:
2960 PseudoOpcode = Mips::BLE;
2961 break;
2962 case Mips::BGEImmMacro:
2963 PseudoOpcode = Mips::BGE;
2964 break;
2965 case Mips::BGTImmMacro:
2966 PseudoOpcode = Mips::BGT;
2967 break;
2968 case Mips::BLTUImmMacro:
2969 PseudoOpcode = Mips::BLTU;
2970 break;
2971 case Mips::BLEUImmMacro:
2972 PseudoOpcode = Mips::BLEU;
2973 break;
2974 case Mips::BGEUImmMacro:
2975 PseudoOpcode = Mips::BGEU;
2976 break;
2977 case Mips::BGTUImmMacro:
2978 PseudoOpcode = Mips::BGTU;
2979 break;
2980 case Mips::BLTLImmMacro:
2981 PseudoOpcode = Mips::BLTL;
2982 break;
2983 case Mips::BLELImmMacro:
2984 PseudoOpcode = Mips::BLEL;
2985 break;
2986 case Mips::BGELImmMacro:
2987 PseudoOpcode = Mips::BGEL;
2988 break;
2989 case Mips::BGTLImmMacro:
2990 PseudoOpcode = Mips::BGTL;
2991 break;
2992 case Mips::BLTULImmMacro:
2993 PseudoOpcode = Mips::BLTUL;
2994 break;
2995 case Mips::BLEULImmMacro:
2996 PseudoOpcode = Mips::BLEUL;
2997 break;
2998 case Mips::BGEULImmMacro:
2999 PseudoOpcode = Mips::BGEUL;
3000 break;
3001 case Mips::BGTULImmMacro:
3002 PseudoOpcode = Mips::BGTUL;
3003 break;
3004 }
3005
3006 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003007 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003008 return true;
3009 }
3010
Toma Tabacu1a108322015-06-17 13:20:24 +00003011 switch (PseudoOpcode) {
3012 case Mips::BLT:
3013 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003014 case Mips::BLTL:
3015 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003016 AcceptsEquality = false;
3017 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003018 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3019 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003020 ZeroSrcOpcode = Mips::BGTZ;
3021 ZeroTrgOpcode = Mips::BLTZ;
3022 break;
3023 case Mips::BLE:
3024 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003025 case Mips::BLEL:
3026 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003027 AcceptsEquality = true;
3028 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003029 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3030 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003031 ZeroSrcOpcode = Mips::BGEZ;
3032 ZeroTrgOpcode = Mips::BLEZ;
3033 break;
3034 case Mips::BGE:
3035 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003036 case Mips::BGEL:
3037 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003038 AcceptsEquality = true;
3039 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003040 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3041 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003042 ZeroSrcOpcode = Mips::BLEZ;
3043 ZeroTrgOpcode = Mips::BGEZ;
3044 break;
3045 case Mips::BGT:
3046 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003047 case Mips::BGTL:
3048 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003049 AcceptsEquality = false;
3050 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003051 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3052 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003053 ZeroSrcOpcode = Mips::BLTZ;
3054 ZeroTrgOpcode = Mips::BGTZ;
3055 break;
3056 default:
3057 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3058 }
3059
Toma Tabacu1a108322015-06-17 13:20:24 +00003060 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3061 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3062 if (IsSrcRegZero && IsTrgRegZero) {
3063 // FIXME: All of these Opcode-specific if's are needed for compatibility
3064 // with GAS' behaviour. However, they may not generate the most efficient
3065 // code in some circumstances.
3066 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003067 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3068 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003069 return false;
3070 }
3071 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003072 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3073 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003074 Warning(IDLoc, "branch is always taken");
3075 return false;
3076 }
3077 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003078 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3079 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003080 Warning(IDLoc, "branch is always taken");
3081 return false;
3082 }
3083 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003084 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3085 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003086 return false;
3087 }
3088 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003089 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3090 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003091 return false;
3092 }
3093 if (AcceptsEquality) {
3094 // If both registers are $0 and the pseudo-branch accepts equality, it
3095 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003096 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3097 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003098 Warning(IDLoc, "branch is always taken");
3099 return false;
3100 }
3101 // If both registers are $0 and the pseudo-branch does not accept
3102 // equality, it will never be taken, so we don't have to emit anything.
3103 return false;
3104 }
3105 if (IsSrcRegZero || IsTrgRegZero) {
3106 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3107 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3108 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3109 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3110 // the pseudo-branch will never be taken, so we don't emit anything.
3111 // This only applies to unsigned pseudo-branches.
3112 return false;
3113 }
3114 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3115 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3116 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3117 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3118 // the pseudo-branch will always be taken, so we emit an unconditional
3119 // branch.
3120 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003121 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3122 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003123 Warning(IDLoc, "branch is always taken");
3124 return false;
3125 }
3126 if (IsUnsigned) {
3127 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3128 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3129 // the pseudo-branch will be taken only when the non-zero register is
3130 // different from 0, so we emit a BNEZ.
3131 //
3132 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3133 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3134 // the pseudo-branch will be taken only when the non-zero register is
3135 // equal to 0, so we emit a BEQZ.
3136 //
3137 // Because only BLEU and BGEU branch on equality, we can use the
3138 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003139 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3140 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3141 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003142 return false;
3143 }
3144 // If we have a signed pseudo-branch and one of the registers is $0,
3145 // we can use an appropriate compare-to-zero branch. We select which one
3146 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003147 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3148 IsSrcRegZero ? TrgReg : SrcReg,
3149 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003150 return false;
3151 }
3152
3153 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3154 // expansions. If it is not available, we return.
3155 unsigned ATRegNum = getATReg(IDLoc);
3156 if (!ATRegNum)
3157 return true;
3158
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003159 if (!EmittedNoMacroWarning)
3160 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003161
3162 // SLT fits well with 2 of our 4 pseudo-branches:
3163 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3164 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3165 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3166 // This is accomplished by using a BNEZ with the result of the SLT.
3167 //
3168 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3169 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3170 // Because only BGE and BLE branch on equality, we can use the
3171 // AcceptsEquality variable to decide when to emit the BEQZ.
3172 // Note that the order of the SLT arguments doesn't change between
3173 // opposites.
3174 //
3175 // The same applies to the unsigned variants, except that SLTu is used
3176 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003177 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3178 ReverseOrderSLT ? TrgReg : SrcReg,
3179 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003180
Daniel Sandersa736b372016-04-29 13:33:12 +00003181 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3182 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3183 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3184 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003185 return false;
3186}
3187
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003188bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3189 const MCSubtargetInfo *STI, const bool IsMips64,
3190 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003191 MipsTargetStreamer &TOut = getTargetStreamer();
3192
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003193 warnIfNoMacro(IDLoc);
3194
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003195 const MCOperand &RdRegOp = Inst.getOperand(0);
3196 assert(RdRegOp.isReg() && "expected register operand kind");
3197 unsigned RdReg = RdRegOp.getReg();
3198
3199 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003200 assert(RsRegOp.isReg() && "expected register operand kind");
3201 unsigned RsReg = RsRegOp.getReg();
3202
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003203 const MCOperand &RtRegOp = Inst.getOperand(2);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003204 assert(RtRegOp.isReg() && "expected register operand kind");
3205 unsigned RtReg = RtRegOp.getReg();
3206 unsigned DivOp;
3207 unsigned ZeroReg;
3208
3209 if (IsMips64) {
3210 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3211 ZeroReg = Mips::ZERO_64;
3212 } else {
3213 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3214 ZeroReg = Mips::ZERO;
3215 }
3216
3217 bool UseTraps = useTraps();
3218
3219 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
3220 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
3221 Warning(IDLoc, "dividing zero by zero");
3222 if (IsMips64) {
3223 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
3224 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003225 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003226 return false;
3227 }
3228
Daniel Sandersa736b372016-04-29 13:33:12 +00003229 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003230 return false;
3231 }
3232 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00003233 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003234 return false;
3235 }
3236 }
3237
3238 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3239 Warning(IDLoc, "division by zero");
3240 if (Signed) {
3241 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003242 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003243 return false;
3244 }
3245
Daniel Sandersa736b372016-04-29 13:33:12 +00003246 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003247 return false;
3248 }
3249 }
3250
3251 // FIXME: The values for these two BranchTarget variables may be different in
3252 // micromips. These magic numbers need to be removed.
3253 unsigned BranchTargetNoTraps;
3254 unsigned BranchTarget;
3255
3256 if (UseTraps) {
3257 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003258 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003259 } else {
3260 BranchTarget = IsMips64 ? 20 : 16;
3261 BranchTargetNoTraps = 8;
3262 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003263 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003264 }
3265
Daniel Sandersa736b372016-04-29 13:33:12 +00003266 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003267
3268 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003269 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003270
3271 if (!Signed) {
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003272 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003273 return false;
3274 }
3275
3276 unsigned ATReg = getATReg(IDLoc);
3277 if (!ATReg)
3278 return true;
3279
Daniel Sandersa736b372016-04-29 13:33:12 +00003280 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003281 if (IsMips64) {
3282 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003283 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3284 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3285 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003286 } else {
3287 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003288 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3289 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003290 }
3291
3292 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003293 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003294 else {
3295 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003296 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3297 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3298 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003299 }
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003300 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003301 return false;
3302}
3303
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003304bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003305 SMLoc IDLoc, MCStreamer &Out,
3306 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003307 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003308
3309 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3310 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3311 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3312
3313 unsigned FirstReg = Inst.getOperand(0).getReg();
3314 unsigned SecondReg = Inst.getOperand(1).getReg();
3315 unsigned ThirdReg = Inst.getOperand(2).getReg();
3316
3317 if (hasMips1() && !hasMips2()) {
3318 unsigned ATReg = getATReg(IDLoc);
3319 if (!ATReg)
3320 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003321 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3322 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3323 TOut.emitNop(IDLoc, STI);
3324 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3325 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3326 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3327 TOut.emitNop(IDLoc, STI);
3328 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3329 : Mips::CVT_W_S,
3330 FirstReg, SecondReg, IDLoc, STI);
3331 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3332 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003333 return false;
3334 }
3335
Daniel Sandersa736b372016-04-29 13:33:12 +00003336 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3337 : Mips::TRUNC_W_S,
3338 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003339
3340 return false;
3341}
3342
Daniel Sanders6394ee52015-10-15 14:52:58 +00003343bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003344 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003345 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003346 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003347 }
3348
Toma Tabacud88d79c2015-06-23 14:39:42 +00003349 const MCOperand &DstRegOp = Inst.getOperand(0);
3350 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003351 const MCOperand &SrcRegOp = Inst.getOperand(1);
3352 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003353 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3354 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3355
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003356 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacud88d79c2015-06-23 14:39:42 +00003357 unsigned DstReg = DstRegOp.getReg();
3358 unsigned SrcReg = SrcRegOp.getReg();
3359 int64_t OffsetValue = OffsetImmOp.getImm();
3360
3361 // NOTE: We always need AT for ULHU, as it is always used as the source
3362 // register for one of the LBu's.
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003363 warnIfNoMacro(IDLoc);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003364 unsigned ATReg = getATReg(IDLoc);
3365 if (!ATReg)
3366 return true;
3367
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003368 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
3369 if (IsLargeOffset) {
3370 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
3371 IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003372 return true;
Toma Tabacud88d79c2015-06-23 14:39:42 +00003373 }
3374
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003375 int64_t FirstOffset = IsLargeOffset ? 0 : OffsetValue;
3376 int64_t SecondOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
3377 if (isLittle())
3378 std::swap(FirstOffset, SecondOffset);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003379
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003380 unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg;
3381 unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00003382
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003383 unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg;
3384 unsigned SllReg = IsLargeOffset ? DstReg : ATReg;
Toma Tabacud88d79c2015-06-23 14:39:42 +00003385
Daniel Sandersa736b372016-04-29 13:33:12 +00003386 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003387 FirstOffset, IDLoc, STI);
3388 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondOffset, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00003389 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Daniel Sandersa736b372016-04-29 13:33:12 +00003390 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003391
3392 return false;
3393}
3394
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003395bool MipsAsmParser::expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003396 const MCSubtargetInfo *STI) {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003397 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003398 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003399 }
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003400
3401 const MCOperand &DstRegOp = Inst.getOperand(0);
3402 assert(DstRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003403 const MCOperand &SrcRegOp = Inst.getOperand(1);
3404 assert(SrcRegOp.isReg() && "expected register operand kind");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003405 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3406 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3407
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003408 MipsTargetStreamer &TOut = getTargetStreamer();
3409 unsigned DstReg = DstRegOp.getReg();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003410 unsigned SrcReg = SrcRegOp.getReg();
3411 int64_t OffsetValue = OffsetImmOp.getImm();
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003412
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003413 warnIfNoMacro(IDLoc);
3414 unsigned ATReg = getATReg(IDLoc);
3415 if (!ATReg)
3416 return true;
3417
3418 bool IsLargeOffset = !(isInt<16>(OffsetValue + 1) && isInt<16>(OffsetValue));
3419 if (IsLargeOffset) {
3420 if (loadImmediate(OffsetValue, ATReg, SrcReg, !ABI.ArePtrs64bit(), true,
3421 IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003422 return true;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003423 }
3424
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003425 int64_t FirstOffset = IsLargeOffset ? 1 : (OffsetValue + 1);
3426 int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue;
3427 if (isLittle())
3428 std::swap(FirstOffset, SecondOffset);
3429
3430 if (IsLargeOffset) {
3431 TOut.emitRRI(Mips::SB, DstReg, ATReg, FirstOffset, IDLoc, STI);
3432 TOut.emitRRI(Mips::SRL, DstReg, DstReg, 8, IDLoc, STI);
3433 TOut.emitRRI(Mips::SB, DstReg, ATReg, SecondOffset, IDLoc, STI);
3434 TOut.emitRRI(Mips::LBu, ATReg, ATReg, 0, IDLoc, STI);
3435 TOut.emitRRI(Mips::SLL, DstReg, DstReg, 8, IDLoc, STI);
3436 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003437 } else {
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003438 TOut.emitRRI(Mips::SB, DstReg, SrcReg, FirstOffset, IDLoc, STI);
3439 TOut.emitRRI(Mips::SRL, ATReg, DstReg, 8, IDLoc, STI);
3440 TOut.emitRRI(Mips::SB, ATReg, SrcReg, SecondOffset, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003441 }
3442
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003443 return false;
3444}
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003445
Vasileios Kalintiris04dc2112016-11-22 16:43:49 +00003446bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3447 const MCSubtargetInfo *STI) {
3448 if (hasMips32r6() || hasMips64r6()) {
3449 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3450 }
3451
3452 const MCOperand &DstRegOp = Inst.getOperand(0);
3453 assert(DstRegOp.isReg() && "expected register operand kind");
3454 const MCOperand &SrcRegOp = Inst.getOperand(1);
3455 assert(SrcRegOp.isReg() && "expected register operand kind");
3456 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3457 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3458
3459 MipsTargetStreamer &TOut = getTargetStreamer();
3460 unsigned DstReg = DstRegOp.getReg();
3461 unsigned SrcReg = SrcRegOp.getReg();
3462 int64_t OffsetValue = OffsetImmOp.getImm();
3463
3464 // Compute left/right load/store offsets.
3465 bool IsLargeOffset = !(isInt<16>(OffsetValue + 3) && isInt<16>(OffsetValue));
3466 int64_t LxlOffset = IsLargeOffset ? 0 : OffsetValue;
3467 int64_t LxrOffset = IsLargeOffset ? 3 : (OffsetValue + 3);
3468 if (isLittle())
3469 std::swap(LxlOffset, LxrOffset);
3470
3471 bool IsLoadInst = (Inst.getOpcode() == Mips::Ulw);
3472 bool DoMove = IsLoadInst && (SrcReg == DstReg) && !IsLargeOffset;
3473 unsigned TmpReg = SrcReg;
3474 if (IsLargeOffset || DoMove) {
3475 warnIfNoMacro(IDLoc);
3476 TmpReg = getATReg(IDLoc);
3477 if (!TmpReg)
3478 return true;
3479 }
3480
3481 if (IsLargeOffset) {
3482 if (loadImmediate(OffsetValue, TmpReg, SrcReg, !ABI.ArePtrs64bit(), true,
3483 IDLoc, Out, STI))
3484 return true;
3485 }
3486
3487 if (DoMove)
3488 std::swap(DstReg, TmpReg);
3489
3490 unsigned XWL = IsLoadInst ? Mips::LWL : Mips::SWL;
3491 unsigned XWR = IsLoadInst ? Mips::LWR : Mips::SWR;
3492 TOut.emitRRI(XWL, DstReg, TmpReg, LxlOffset, IDLoc, STI);
3493 TOut.emitRRI(XWR, DstReg, TmpReg, LxrOffset, IDLoc, STI);
3494
3495 if (DoMove)
3496 TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003497
3498 return false;
3499}
3500
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003501bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003502 MCStreamer &Out,
3503 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003504 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003505
3506 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3507 assert (Inst.getOperand(0).isReg() &&
3508 Inst.getOperand(1).isReg() &&
3509 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3510
3511 unsigned ATReg = Mips::NoRegister;
3512 unsigned FinalDstReg = Mips::NoRegister;
3513 unsigned DstReg = Inst.getOperand(0).getReg();
3514 unsigned SrcReg = Inst.getOperand(1).getReg();
3515 int64_t ImmValue = Inst.getOperand(2).getImm();
3516
3517 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3518
3519 unsigned FinalOpcode = Inst.getOpcode();
3520
3521 if (DstReg == SrcReg) {
3522 ATReg = getATReg(Inst.getLoc());
3523 if (!ATReg)
3524 return true;
3525 FinalDstReg = DstReg;
3526 DstReg = ATReg;
3527 }
3528
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003529 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003530 switch (FinalOpcode) {
3531 default:
3532 llvm_unreachable("unimplemented expansion");
3533 case (Mips::ADDi):
3534 FinalOpcode = Mips::ADD;
3535 break;
3536 case (Mips::ADDiu):
3537 FinalOpcode = Mips::ADDu;
3538 break;
3539 case (Mips::ANDi):
3540 FinalOpcode = Mips::AND;
3541 break;
3542 case (Mips::NORImm):
3543 FinalOpcode = Mips::NOR;
3544 break;
3545 case (Mips::ORi):
3546 FinalOpcode = Mips::OR;
3547 break;
3548 case (Mips::SLTi):
3549 FinalOpcode = Mips::SLT;
3550 break;
3551 case (Mips::SLTiu):
3552 FinalOpcode = Mips::SLTu;
3553 break;
3554 case (Mips::XORi):
3555 FinalOpcode = Mips::XOR;
3556 break;
3557 }
3558
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003559 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003560 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003561 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003562 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003563 return false;
3564 }
3565 return true;
3566}
3567
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003568bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3569 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003570 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003571 unsigned ATReg = Mips::NoRegister;
3572 unsigned DReg = Inst.getOperand(0).getReg();
3573 unsigned SReg = Inst.getOperand(1).getReg();
3574 unsigned TReg = Inst.getOperand(2).getReg();
3575 unsigned TmpReg = DReg;
3576
3577 unsigned FirstShift = Mips::NOP;
3578 unsigned SecondShift = Mips::NOP;
3579
3580 if (hasMips32r2()) {
3581
3582 if (DReg == SReg) {
3583 TmpReg = getATReg(Inst.getLoc());
3584 if (!TmpReg)
3585 return true;
3586 }
3587
3588 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003589 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3590 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003591 return false;
3592 }
3593
3594 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003595 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003596 return false;
3597 }
3598
3599 return true;
3600 }
3601
3602 if (hasMips32()) {
3603
3604 switch (Inst.getOpcode()) {
3605 default:
3606 llvm_unreachable("unexpected instruction opcode");
3607 case Mips::ROL:
3608 FirstShift = Mips::SRLV;
3609 SecondShift = Mips::SLLV;
3610 break;
3611 case Mips::ROR:
3612 FirstShift = Mips::SLLV;
3613 SecondShift = Mips::SRLV;
3614 break;
3615 }
3616
3617 ATReg = getATReg(Inst.getLoc());
3618 if (!ATReg)
3619 return true;
3620
Daniel Sandersa736b372016-04-29 13:33:12 +00003621 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3622 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3623 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3624 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003625
3626 return false;
3627 }
3628
3629 return true;
3630}
3631
3632bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003633 MCStreamer &Out,
3634 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003635 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003636 unsigned ATReg = Mips::NoRegister;
3637 unsigned DReg = Inst.getOperand(0).getReg();
3638 unsigned SReg = Inst.getOperand(1).getReg();
3639 int64_t ImmValue = Inst.getOperand(2).getImm();
3640
3641 unsigned FirstShift = Mips::NOP;
3642 unsigned SecondShift = Mips::NOP;
3643
3644 if (hasMips32r2()) {
3645
3646 if (Inst.getOpcode() == Mips::ROLImm) {
3647 uint64_t MaxShift = 32;
3648 uint64_t ShiftValue = ImmValue;
3649 if (ImmValue != 0)
3650 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003651 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003652 return false;
3653 }
3654
3655 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003656 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003657 return false;
3658 }
3659
3660 return true;
3661 }
3662
3663 if (hasMips32()) {
3664
3665 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003666 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003667 return false;
3668 }
3669
3670 switch (Inst.getOpcode()) {
3671 default:
3672 llvm_unreachable("unexpected instruction opcode");
3673 case Mips::ROLImm:
3674 FirstShift = Mips::SLL;
3675 SecondShift = Mips::SRL;
3676 break;
3677 case Mips::RORImm:
3678 FirstShift = Mips::SRL;
3679 SecondShift = Mips::SLL;
3680 break;
3681 }
3682
3683 ATReg = getATReg(Inst.getLoc());
3684 if (!ATReg)
3685 return true;
3686
Daniel Sandersa736b372016-04-29 13:33:12 +00003687 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3688 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3689 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003690
3691 return false;
3692 }
3693
3694 return true;
3695}
3696
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003697bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3698 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003699 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003700 unsigned ATReg = Mips::NoRegister;
3701 unsigned DReg = Inst.getOperand(0).getReg();
3702 unsigned SReg = Inst.getOperand(1).getReg();
3703 unsigned TReg = Inst.getOperand(2).getReg();
3704 unsigned TmpReg = DReg;
3705
3706 unsigned FirstShift = Mips::NOP;
3707 unsigned SecondShift = Mips::NOP;
3708
3709 if (hasMips64r2()) {
3710
3711 if (TmpReg == SReg) {
3712 TmpReg = getATReg(Inst.getLoc());
3713 if (!TmpReg)
3714 return true;
3715 }
3716
3717 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003718 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3719 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003720 return false;
3721 }
3722
3723 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003724 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003725 return false;
3726 }
3727
3728 return true;
3729 }
3730
3731 if (hasMips64()) {
3732
3733 switch (Inst.getOpcode()) {
3734 default:
3735 llvm_unreachable("unexpected instruction opcode");
3736 case Mips::DROL:
3737 FirstShift = Mips::DSRLV;
3738 SecondShift = Mips::DSLLV;
3739 break;
3740 case Mips::DROR:
3741 FirstShift = Mips::DSLLV;
3742 SecondShift = Mips::DSRLV;
3743 break;
3744 }
3745
3746 ATReg = getATReg(Inst.getLoc());
3747 if (!ATReg)
3748 return true;
3749
Daniel Sandersa736b372016-04-29 13:33:12 +00003750 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3751 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3752 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3753 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003754
3755 return false;
3756 }
3757
3758 return true;
3759}
3760
3761bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003762 MCStreamer &Out,
3763 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003764 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003765 unsigned ATReg = Mips::NoRegister;
3766 unsigned DReg = Inst.getOperand(0).getReg();
3767 unsigned SReg = Inst.getOperand(1).getReg();
3768 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3769
3770 unsigned FirstShift = Mips::NOP;
3771 unsigned SecondShift = Mips::NOP;
3772
3773 MCInst TmpInst;
3774
3775 if (hasMips64r2()) {
3776
3777 unsigned FinalOpcode = Mips::NOP;
3778 if (ImmValue == 0)
3779 FinalOpcode = Mips::DROTR;
3780 else if (ImmValue % 32 == 0)
3781 FinalOpcode = Mips::DROTR32;
3782 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3783 if (Inst.getOpcode() == Mips::DROLImm)
3784 FinalOpcode = Mips::DROTR32;
3785 else
3786 FinalOpcode = Mips::DROTR;
3787 } else if (ImmValue >= 33) {
3788 if (Inst.getOpcode() == Mips::DROLImm)
3789 FinalOpcode = Mips::DROTR;
3790 else
3791 FinalOpcode = Mips::DROTR32;
3792 }
3793
3794 uint64_t ShiftValue = ImmValue % 32;
3795 if (Inst.getOpcode() == Mips::DROLImm)
3796 ShiftValue = (32 - ImmValue % 32) % 32;
3797
Daniel Sandersa736b372016-04-29 13:33:12 +00003798 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003799
3800 return false;
3801 }
3802
3803 if (hasMips64()) {
3804
3805 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003806 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003807 return false;
3808 }
3809
3810 switch (Inst.getOpcode()) {
3811 default:
3812 llvm_unreachable("unexpected instruction opcode");
3813 case Mips::DROLImm:
3814 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3815 FirstShift = Mips::DSLL;
3816 SecondShift = Mips::DSRL32;
3817 }
3818 if (ImmValue == 32) {
3819 FirstShift = Mips::DSLL32;
3820 SecondShift = Mips::DSRL32;
3821 }
3822 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3823 FirstShift = Mips::DSLL32;
3824 SecondShift = Mips::DSRL;
3825 }
3826 break;
3827 case Mips::DRORImm:
3828 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3829 FirstShift = Mips::DSRL;
3830 SecondShift = Mips::DSLL32;
3831 }
3832 if (ImmValue == 32) {
3833 FirstShift = Mips::DSRL32;
3834 SecondShift = Mips::DSLL32;
3835 }
3836 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3837 FirstShift = Mips::DSRL32;
3838 SecondShift = Mips::DSLL;
3839 }
3840 break;
3841 }
3842
3843 ATReg = getATReg(Inst.getLoc());
3844 if (!ATReg)
3845 return true;
3846
Daniel Sandersa736b372016-04-29 13:33:12 +00003847 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3848 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3849 Inst.getLoc(), STI);
3850 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003851
3852 return false;
3853 }
3854
3855 return true;
3856}
3857
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003858bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3859 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003860 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003861 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3862 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3863
Daniel Sandersa736b372016-04-29 13:33:12 +00003864 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003865 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003866 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003867 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003868 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3869 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003870
3871 return false;
3872}
3873
Simon Dardisaff4d142016-10-18 14:28:00 +00003874static unsigned nextReg(unsigned Reg) {
3875 switch (Reg) {
3876 case Mips::ZERO: return Mips::AT;
3877 case Mips::AT: return Mips::V0;
3878 case Mips::V0: return Mips::V1;
3879 case Mips::V1: return Mips::A0;
3880 case Mips::A0: return Mips::A1;
3881 case Mips::A1: return Mips::A2;
3882 case Mips::A2: return Mips::A3;
3883 case Mips::A3: return Mips::T0;
3884 case Mips::T0: return Mips::T1;
3885 case Mips::T1: return Mips::T2;
3886 case Mips::T2: return Mips::T3;
3887 case Mips::T3: return Mips::T4;
3888 case Mips::T4: return Mips::T5;
3889 case Mips::T5: return Mips::T6;
3890 case Mips::T6: return Mips::T7;
3891 case Mips::T7: return Mips::S0;
3892 case Mips::S0: return Mips::S1;
3893 case Mips::S1: return Mips::S2;
3894 case Mips::S2: return Mips::S3;
3895 case Mips::S3: return Mips::S4;
3896 case Mips::S4: return Mips::S5;
3897 case Mips::S5: return Mips::S6;
3898 case Mips::S6: return Mips::S7;
3899 case Mips::S7: return Mips::T8;
3900 case Mips::T8: return Mips::T9;
3901 case Mips::T9: return Mips::K0;
3902 case Mips::K0: return Mips::K1;
3903 case Mips::K1: return Mips::GP;
3904 case Mips::GP: return Mips::SP;
3905 case Mips::SP: return Mips::FP;
3906 case Mips::FP: return Mips::RA;
3907 case Mips::RA: return Mips::ZERO;
3908 default: return 0;
3909 }
3910
3911}
3912
3913// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
3914// lw $<reg+1>>, offset+4($reg2)'
3915// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
3916// sw $<reg+1>>, offset+4($reg2)'
3917// for O32.
3918bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
3919 MCStreamer &Out,
3920 const MCSubtargetInfo *STI,
3921 bool IsLoad) {
3922 if (!isABI_O32())
3923 return true;
3924
3925 warnIfNoMacro(IDLoc);
3926
3927 MipsTargetStreamer &TOut = getTargetStreamer();
3928 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
3929 unsigned FirstReg = Inst.getOperand(0).getReg();
3930 unsigned SecondReg = nextReg(FirstReg);
3931 unsigned BaseReg = Inst.getOperand(1).getReg();
3932 if (!SecondReg)
3933 return true;
3934
3935 warnIfRegIndexIsAT(FirstReg, IDLoc);
3936
3937 assert(Inst.getOperand(2).isImm() &&
3938 "Offset for load macro is not immediate!");
3939
3940 MCOperand &FirstOffset = Inst.getOperand(2);
3941 signed NextOffset = FirstOffset.getImm() + 4;
3942 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
3943
3944 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
3945 return true;
3946
3947 // For loads, clobber the base register with the second load instead of the
3948 // first if the BaseReg == FirstReg.
3949 if (FirstReg != BaseReg || !IsLoad) {
3950 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
3951 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
3952 } else {
3953 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
3954 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
3955 }
3956
3957 return false;
3958}
3959
Simon Dardis43115a12016-11-21 20:30:41 +00003960bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3961 const MCSubtargetInfo *STI) {
3962
3963 warnIfNoMacro(IDLoc);
3964 MipsTargetStreamer &TOut = getTargetStreamer();
3965
3966 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
3967 Inst.getOperand(2).getReg() != Mips::ZERO) {
3968 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
3969 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
3970 IDLoc, STI);
3971 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
3972 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
3973 return false;
3974 }
3975
3976 unsigned Reg = 0;
3977 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
3978 Reg = Inst.getOperand(2).getReg();
3979 } else {
3980 Reg = Inst.getOperand(1).getReg();
3981 }
3982 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
3983 return false;
3984}
3985
3986bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3987 const MCSubtargetInfo *STI) {
3988
3989 warnIfNoMacro(IDLoc);
3990 MipsTargetStreamer &TOut = getTargetStreamer();
3991
3992 unsigned Opc;
3993 int64_t Imm = Inst.getOperand(2).getImm();
3994 unsigned Reg = Inst.getOperand(1).getReg();
3995
3996 if (Imm == 0) {
3997 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
3998 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
3999 return false;
4000 } else {
4001
4002 if (Reg == Mips::ZERO) {
4003 Warning(IDLoc, "comparison is always false");
4004 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
4005 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
4006 return false;
4007 }
4008
4009 if (Imm > -0x8000 && Imm < 0) {
4010 Imm = -Imm;
4011 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
4012 } else {
4013 Opc = Mips::XORi;
4014 }
4015 }
4016 if (!isUInt<16>(Imm)) {
4017 unsigned ATReg = getATReg(IDLoc);
4018 if (!ATReg)
4019 return true;
4020
4021 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
4022 Out, STI))
4023 return true;
4024
4025 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
4026 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
4027 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4028 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4029 return false;
4030 }
4031
4032 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4033 Imm, IDLoc, STI);
4034 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4035 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4036 return false;
4037}
4038
Daniel Sandersc5537422016-07-27 13:49:44 +00004039unsigned
4040MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
4041 const OperandVector &Operands) {
4042 switch (Inst.getOpcode()) {
4043 default:
4044 return Match_Success;
4045 case Mips::DATI:
4046 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00004047 case Mips::DATI_MM64R6:
4048 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00004049 if (static_cast<MipsOperand &>(*Operands[1])
4050 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
4051 return Match_Success;
4052 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00004053 }
4054}
Simon Dardis730fdb72017-01-16 13:55:58 +00004055
Matheus Almeida595fcab2014-06-11 15:05:56 +00004056unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00004057 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00004058 // As described by the MIPSR6 spec, daui must not use the zero operand for
4059 // its source operand.
4060 case Mips::DAUI:
4061 case Mips::DAUI_MM64R6:
4062 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4063 Inst.getOperand(1).getReg() == Mips::ZERO_64)
4064 return Match_RequiresNoZeroRegister;
4065 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00004066 // As described by the Mips32r2 spec, the registers Rd and Rs for
4067 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00004068 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00004069 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00004070 case Mips::JALR_HB:
4071 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00004072 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00004073 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4074 return Match_RequiresDifferentSrcAndDst;
4075 return Match_Success;
4076 case Mips::LWP_MM:
4077 case Mips::LWP_MMR6:
4078 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
4079 return Match_RequiresDifferentSrcAndDst;
4080 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00004081 case Mips::SYNC:
4082 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
4083 return Match_NonZeroOperandForSync;
4084 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004085 // As described the MIPSR6 spec, the compact branches that compare registers
4086 // must:
4087 // a) Not use the zero register.
4088 // b) Not use the same register twice.
4089 // c) rs < rt for bnec, beqc.
4090 // NB: For this case, the encoding will swap the operands as their
4091 // ordering doesn't matter. GAS performs this transformation too.
4092 // Hence, that constraint does not have to be enforced.
4093 //
4094 // The compact branches that branch iff the signed addition of two registers
4095 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
4096 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004097 case Mips::BLEZC: case Mips::BLEZC_MMR6:
4098 case Mips::BGEZC: case Mips::BGEZC_MMR6:
4099 case Mips::BGTZC: case Mips::BGTZC_MMR6:
4100 case Mips::BLTZC: case Mips::BLTZC_MMR6:
4101 case Mips::BEQZC: case Mips::BEQZC_MMR6:
4102 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004103 case Mips::BLEZC64:
4104 case Mips::BGEZC64:
4105 case Mips::BGTZC64:
4106 case Mips::BLTZC64:
4107 case Mips::BEQZC64:
4108 case Mips::BNEZC64:
4109 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4110 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004111 return Match_RequiresNoZeroRegister;
4112 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004113 case Mips::BGEC: case Mips::BGEC_MMR6:
4114 case Mips::BLTC: case Mips::BLTC_MMR6:
4115 case Mips::BGEUC: case Mips::BGEUC_MMR6:
4116 case Mips::BLTUC: case Mips::BLTUC_MMR6:
4117 case Mips::BEQC: case Mips::BEQC_MMR6:
4118 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004119 case Mips::BGEC64:
4120 case Mips::BLTC64:
4121 case Mips::BGEUC64:
4122 case Mips::BLTUC64:
4123 case Mips::BEQC64:
4124 case Mips::BNEC64:
4125 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4126 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004127 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00004128 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4129 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004130 return Match_RequiresNoZeroRegister;
4131 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4132 return Match_RequiresDifferentOperands;
4133 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004134 }
Simon Dardis730fdb72017-01-16 13:55:58 +00004135
4136 uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
4137 if ((TSFlags & MipsII::HasFCCRegOperand) &&
4138 (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
4139 return Match_NoFCCRegisterForCurrentISA;
4140
4141 return Match_Success;
4142
Matheus Almeida595fcab2014-06-11 15:05:56 +00004143}
4144
Daniel Sanders52da7af2015-11-06 12:11:03 +00004145static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
4146 uint64_t ErrorInfo) {
4147 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
4148 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
4149 if (ErrorLoc == SMLoc())
4150 return Loc;
4151 return ErrorLoc;
4152 }
4153 return Loc;
4154}
4155
David Blaikie960ea3f2014-06-08 16:18:35 +00004156bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4157 OperandVector &Operands,
4158 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004159 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00004160 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00004161
Jack Carterb4dbc172012-09-05 23:34:03 +00004162 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00004163 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004164 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00004165
4166 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004167 case Match_Success: {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004168 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00004169 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004170 return false;
4171 }
4172 case Match_MissingFeature:
4173 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4174 return true;
4175 case Match_InvalidOperand: {
4176 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00004177 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004178 if (ErrorInfo >= Operands.size())
4179 return Error(IDLoc, "too few operands for instruction");
4180
Daniel Sanders52da7af2015-11-06 12:11:03 +00004181 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00004182 if (ErrorLoc == SMLoc())
4183 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00004184 }
4185
4186 return Error(ErrorLoc, "invalid operand for instruction");
4187 }
Simon Dardisc4463c92016-10-18 14:42:13 +00004188 case Match_NonZeroOperandForSync:
4189 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00004190 case Match_MnemonicFail:
4191 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00004192 case Match_RequiresDifferentSrcAndDst:
4193 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00004194 case Match_RequiresDifferentOperands:
4195 return Error(IDLoc, "registers must be different");
4196 case Match_RequiresNoZeroRegister:
4197 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00004198 case Match_RequiresSameSrcAndDst:
4199 return Error(IDLoc, "source and destination must match");
Simon Dardis730fdb72017-01-16 13:55:58 +00004200 case Match_NoFCCRegisterForCurrentISA:
4201 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4202 "non-zero fcc register doesn't exist in current ISA level");
Daniel Sanders52da7af2015-11-06 12:11:03 +00004203 case Match_Immz:
4204 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004205 case Match_UImm1_0:
4206 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4207 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00004208 case Match_UImm2_0:
4209 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4210 "expected 2-bit unsigned immediate");
4211 case Match_UImm2_1:
4212 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4213 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00004214 case Match_UImm3_0:
4215 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4216 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004217 case Match_UImm4_0:
4218 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4219 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00004220 case Match_SImm4_0:
4221 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4222 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004223 case Match_UImm5_0:
4224 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4225 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00004226 case Match_SImm5_0:
4227 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4228 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004229 case Match_UImm5_1:
4230 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4231 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004232 case Match_UImm5_32:
4233 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4234 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004235 case Match_UImm5_33:
4236 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4237 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004238 case Match_UImm5_0_Report_UImm6:
4239 // This is used on UImm5 operands that have a corresponding UImm5_32
4240 // operand to avoid confusing the user.
4241 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4242 "expected 6-bit unsigned immediate");
4243 case Match_UImm5_Lsl2:
4244 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4245 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00004246 case Match_UImmRange2_64:
4247 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4248 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00004249 case Match_UImm6_0:
4250 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4251 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00004252 case Match_UImm6_Lsl2:
4253 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4254 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00004255 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00004256 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4257 "expected 6-bit signed immediate");
4258 case Match_UImm7_0:
4259 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4260 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00004261 case Match_UImm7_N1:
4262 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4263 "expected immediate in range -1 .. 126");
4264 case Match_SImm7_Lsl2:
4265 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4266 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00004267 case Match_UImm8_0:
4268 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4269 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00004270 case Match_UImm10_0:
4271 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4272 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00004273 case Match_SImm10_0:
4274 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4275 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00004276 case Match_SImm11_0:
4277 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4278 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00004279 case Match_UImm16:
4280 case Match_UImm16_Relaxed:
4281 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4282 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004283 case Match_SImm16:
4284 case Match_SImm16_Relaxed:
4285 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4286 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00004287 case Match_SImm19_Lsl2:
4288 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4289 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00004290 case Match_UImm20_0:
4291 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4292 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00004293 case Match_UImm26_0:
4294 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4295 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00004296 case Match_SImm32:
4297 case Match_SImm32_Relaxed:
4298 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4299 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00004300 case Match_UImm32_Coerced:
4301 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4302 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00004303 case Match_MemSImm9:
4304 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4305 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00004306 case Match_MemSImm10:
4307 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4308 "expected memory with 10-bit signed offset");
4309 case Match_MemSImm10Lsl1:
4310 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4311 "expected memory with 11-bit signed offset and multiple of 2");
4312 case Match_MemSImm10Lsl2:
4313 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4314 "expected memory with 12-bit signed offset and multiple of 4");
4315 case Match_MemSImm10Lsl3:
4316 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4317 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00004318 case Match_MemSImm11:
4319 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4320 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00004321 case Match_MemSImm12:
4322 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4323 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004324 case Match_MemSImm16:
4325 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4326 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00004327 }
Craig Topper589ceee2015-01-03 08:16:34 +00004328
4329 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00004330}
4331
Toma Tabacud9d344b2015-04-27 14:05:04 +00004332void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
4333 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
4334 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
4335 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004336}
4337
Toma Tabacu81496c12015-05-20 08:54:45 +00004338void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
4339 if (!AssemblerOptions.back()->isMacro())
4340 Warning(Loc, "macro instruction expanded into multiple instructions");
4341}
4342
Daniel Sandersef638fe2014-10-03 15:37:37 +00004343void
4344MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
4345 SMRange Range, bool ShowColors) {
4346 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00004347 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00004348 ShowColors);
4349}
4350
Jack Carter1ac53222013-02-20 23:11:17 +00004351int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004352 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004353
Vladimir Medic4c299852013-11-06 11:27:05 +00004354 CC = StringSwitch<unsigned>(Name)
4355 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004356 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00004357 .Case("a0", 4)
4358 .Case("a1", 5)
4359 .Case("a2", 6)
4360 .Case("a3", 7)
4361 .Case("v0", 2)
4362 .Case("v1", 3)
4363 .Case("s0", 16)
4364 .Case("s1", 17)
4365 .Case("s2", 18)
4366 .Case("s3", 19)
4367 .Case("s4", 20)
4368 .Case("s5", 21)
4369 .Case("s6", 22)
4370 .Case("s7", 23)
4371 .Case("k0", 26)
4372 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004373 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00004374 .Case("sp", 29)
4375 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004376 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00004377 .Case("ra", 31)
4378 .Case("t0", 8)
4379 .Case("t1", 9)
4380 .Case("t2", 10)
4381 .Case("t3", 11)
4382 .Case("t4", 12)
4383 .Case("t5", 13)
4384 .Case("t6", 14)
4385 .Case("t7", 15)
4386 .Case("t8", 24)
4387 .Case("t9", 25)
4388 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004389
Toma Tabacufda445c2014-09-15 15:33:01 +00004390 if (!(isABI_N32() || isABI_N64()))
4391 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004392
Daniel Sandersef638fe2014-10-03 15:37:37 +00004393 if (12 <= CC && CC <= 15) {
4394 // Name is one of t4-t7
4395 AsmToken RegTok = getLexer().peekTok();
4396 SMRange RegRange = RegTok.getLocRange();
4397
4398 StringRef FixedName = StringSwitch<StringRef>(Name)
4399 .Case("t4", "t0")
4400 .Case("t5", "t1")
4401 .Case("t6", "t2")
4402 .Case("t7", "t3")
4403 .Default("");
4404 assert(FixedName != "" && "Register name is not one of t4-t7.");
4405
4406 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
4407 "Did you mean $" + FixedName + "?", RegRange);
4408 }
4409
Toma Tabacufda445c2014-09-15 15:33:01 +00004410 // Although SGI documentation just cuts out t0-t3 for n32/n64,
4411 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
4412 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
4413 if (8 <= CC && CC <= 11)
4414 CC += 4;
4415
4416 if (CC == -1)
4417 CC = StringSwitch<unsigned>(Name)
4418 .Case("a4", 8)
4419 .Case("a5", 9)
4420 .Case("a6", 10)
4421 .Case("a7", 11)
4422 .Case("kt0", 26)
4423 .Case("kt1", 27)
4424 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004425
4426 return CC;
4427}
Jack Carterd0bd6422013-04-18 00:41:53 +00004428
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004429int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
4430 int CC;
4431
4432 CC = StringSwitch<unsigned>(Name)
4433 .Case("hwr_cpunum", 0)
4434 .Case("hwr_synci_step", 1)
4435 .Case("hwr_cc", 2)
4436 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00004437 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004438 .Default(-1);
4439
4440 return CC;
4441}
4442
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004443int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004444
Jack Cartera63b16a2012-09-07 00:23:42 +00004445 if (Name[0] == 'f') {
4446 StringRef NumString = Name.substr(1);
4447 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004448 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004449 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004450 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00004451 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004452 return IntVal;
4453 }
4454 return -1;
4455}
Jack Cartera63b16a2012-09-07 00:23:42 +00004456
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004457int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
4458
4459 if (Name.startswith("fcc")) {
4460 StringRef NumString = Name.substr(3);
4461 unsigned IntVal;
4462 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004463 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004464 if (IntVal > 7) // There are only 8 fcc registers.
4465 return -1;
4466 return IntVal;
4467 }
4468 return -1;
4469}
4470
4471int MipsAsmParser::matchACRegisterName(StringRef Name) {
4472
Akira Hatanaka274d24c2013-08-14 01:15:52 +00004473 if (Name.startswith("ac")) {
4474 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004475 unsigned IntVal;
4476 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004477 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004478 if (IntVal > 3) // There are only 3 acc registers.
4479 return -1;
4480 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00004481 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004482 return -1;
4483}
Jack Carterd0bd6422013-04-18 00:41:53 +00004484
Jack Carter5dc8ac92013-09-25 23:50:44 +00004485int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
4486 unsigned IntVal;
4487
4488 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
4489 return -1;
4490
4491 if (IntVal > 31)
4492 return -1;
4493
4494 return IntVal;
4495}
4496
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004497int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
4498 int CC;
4499
4500 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00004501 .Case("msair", 0)
4502 .Case("msacsr", 1)
4503 .Case("msaaccess", 2)
4504 .Case("msasave", 3)
4505 .Case("msamodify", 4)
4506 .Case("msarequest", 5)
4507 .Case("msamap", 6)
4508 .Case("msaunmap", 7)
4509 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004510
4511 return CC;
4512}
4513
Toma Tabacu89a712b2015-04-15 10:48:56 +00004514unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004515 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004516 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004517 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004518 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004519 return 0;
4520 }
4521 unsigned AT = getReg(
4522 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004523 return AT;
4524}
Jack Carter0b744b32012-10-04 02:29:46 +00004525
Jack Carterd0bd6422013-04-18 00:41:53 +00004526unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004527 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004528}
4529
Toma Tabacu13964452014-09-04 13:23:44 +00004530bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004531 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004532 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004533
Jack Carter30a59822012-10-04 04:03:53 +00004534 // Check if the current operand has a custom associated parser, if so, try to
4535 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004536 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4537 if (ResTy == MatchOperand_Success)
4538 return false;
4539 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4540 // there was a match, but an error occurred, in which case, just return that
4541 // the operand parsing failed.
4542 if (ResTy == MatchOperand_ParseFail)
4543 return true;
4544
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004545 DEBUG(dbgs() << ".. Generic Parser\n");
4546
Jack Carterb4dbc172012-09-05 23:34:03 +00004547 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004548 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004549 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004550 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004551
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004552 // Almost all registers have been parsed by custom parsers. There is only
4553 // one exception to this. $zero (and it's alias $0) will reach this point
4554 // for div, divu, and similar instructions because it is not an operand
4555 // to the instruction definition but an explicit register. Special case
4556 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004557 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004558 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004559
Jack Carterd0bd6422013-04-18 00:41:53 +00004560 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004561 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004562 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004563 return true;
4564
Jack Carter873c7242013-01-12 01:03:14 +00004565 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004566 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004567 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004568 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004569 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004570
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004571 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004572 return false;
4573 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004574 default: {
4575 DEBUG(dbgs() << ".. generic integer expression\n");
4576
4577 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00004578 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004579 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004580 return true;
4581
Jack Carter873c7242013-01-12 01:03:14 +00004582 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4583
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004584 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004585 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004586 }
Jack Carter0b744b32012-10-04 02:29:46 +00004587 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004588 return true;
4589}
4590
Jack Carterb5cf5902013-04-17 00:18:04 +00004591bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4592
4593 switch (Expr->getKind()) {
4594 case MCExpr::Constant:
4595 return true;
4596 case MCExpr::SymbolRef:
4597 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4598 case MCExpr::Binary:
4599 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4600 if (!isEvaluated(BE->getLHS()))
4601 return false;
4602 return isEvaluated(BE->getRHS());
4603 }
4604 case MCExpr::Unary:
4605 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004606 case MCExpr::Target:
4607 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004608 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004609 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004610}
Jack Carterd0bd6422013-04-18 00:41:53 +00004611
Jack Carterb4dbc172012-09-05 23:34:03 +00004612bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4613 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004614 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004615 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004616 if (ResTy == MatchOperand_Success) {
4617 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004618 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004619 StartLoc = Operand.getStartLoc();
4620 EndLoc = Operand.getEndLoc();
4621
4622 // AFAIK, we only support numeric registers and named GPR's in CFI
4623 // directives.
4624 // Don't worry about eating tokens before failing. Using an unrecognised
4625 // register is a parse error.
4626 if (Operand.isGPRAsmReg()) {
4627 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004628 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004629 }
4630
4631 return (RegNo == (unsigned)-1);
4632 }
4633
4634 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004635 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004636}
4637
Jack Carterb5cf5902013-04-17 00:18:04 +00004638bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00004639 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004640
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004641 if (isParenExpr)
4642 return getParser().parseParenExprOfDepth(0, Res, S);
4643 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004644}
4645
Alex Bradbury58eba092016-11-01 16:32:05 +00004646OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004647MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004648 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004649 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004650 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004651 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004652 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00004653 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004654 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004655 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004656
Jack Carterb5cf5902013-04-17 00:18:04 +00004657 if (getLexer().getKind() == AsmToken::LParen) {
4658 Parser.Lex();
4659 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004660 }
4661
Jack Carterb5cf5902013-04-17 00:18:04 +00004662 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004663 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004664 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004665
Jack Carterd0bd6422013-04-18 00:41:53 +00004666 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004667 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004668 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004669 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004670 SMLoc E =
4671 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004672 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004673 return MatchOperand_Success;
4674 }
4675 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004676 SMLoc E =
4677 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004678
Jack Carterd0bd6422013-04-18 00:41:53 +00004679 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004680 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00004681 auto Base = MipsOperand::createGPRReg(
4682 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00004683 Operands.push_back(
4684 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004685 return MatchOperand_Success;
4686 }
Simon Dardis858915f2016-10-18 15:17:17 +00004687 MCBinaryExpr::Opcode Opcode;
4688 // GAS and LLVM treat comparison operators different. GAS will generate -1
4689 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
4690 // highly unlikely to be found in a memory offset expression, we don't
4691 // handle them.
4692 switch (Tok.getKind()) {
4693 case AsmToken::Plus:
4694 Opcode = MCBinaryExpr::Add;
4695 Parser.Lex();
4696 break;
4697 case AsmToken::Minus:
4698 Opcode = MCBinaryExpr::Sub;
4699 Parser.Lex();
4700 break;
4701 case AsmToken::Star:
4702 Opcode = MCBinaryExpr::Mul;
4703 Parser.Lex();
4704 break;
4705 case AsmToken::Pipe:
4706 Opcode = MCBinaryExpr::Or;
4707 Parser.Lex();
4708 break;
4709 case AsmToken::Amp:
4710 Opcode = MCBinaryExpr::And;
4711 Parser.Lex();
4712 break;
4713 case AsmToken::LessLess:
4714 Opcode = MCBinaryExpr::Shl;
4715 Parser.Lex();
4716 break;
4717 case AsmToken::GreaterGreater:
4718 Opcode = MCBinaryExpr::LShr;
4719 Parser.Lex();
4720 break;
4721 case AsmToken::Caret:
4722 Opcode = MCBinaryExpr::Xor;
4723 Parser.Lex();
4724 break;
4725 case AsmToken::Slash:
4726 Opcode = MCBinaryExpr::Div;
4727 Parser.Lex();
4728 break;
4729 case AsmToken::Percent:
4730 Opcode = MCBinaryExpr::Mod;
4731 Parser.Lex();
4732 break;
4733 default:
4734 Error(Parser.getTok().getLoc(), "'(' or expression expected");
4735 return MatchOperand_ParseFail;
4736 }
4737 const MCExpr * NextExpr;
4738 if (getParser().parseExpression(NextExpr))
4739 return MatchOperand_ParseFail;
4740 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004741 }
4742
Jack Carterd0bd6422013-04-18 00:41:53 +00004743 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004744 }
4745
Toma Tabacu13964452014-09-04 13:23:44 +00004746 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004747 if (Res != MatchOperand_Success)
4748 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004749
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004750 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004751 Error(Parser.getTok().getLoc(), "')' expected");
4752 return MatchOperand_ParseFail;
4753 }
4754
Jack Carter873c7242013-01-12 01:03:14 +00004755 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4756
Jack Carterd0bd6422013-04-18 00:41:53 +00004757 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004758
Craig Topper062a2ba2014-04-25 05:30:21 +00004759 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004760 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004761
Jack Carterd0bd6422013-04-18 00:41:53 +00004762 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004763 std::unique_ptr<MipsOperand> op(
4764 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004765 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004766 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004767 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004768 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004769 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4770 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004771 if (IdVal->evaluateAsAbsolute(Imm))
4772 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004773 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004774 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004775 getContext());
4776 }
4777
David Blaikie960ea3f2014-06-08 16:18:35 +00004778 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004779 return MatchOperand_Success;
4780}
4781
David Blaikie960ea3f2014-06-08 16:18:35 +00004782bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004783 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004784 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004785 if (Sym) {
4786 SMLoc S = Parser.getTok().getLoc();
4787 const MCExpr *Expr;
4788 if (Sym->isVariable())
4789 Expr = Sym->getVariableValue();
4790 else
4791 return false;
4792 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004793 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004794 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004795 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004796 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004797 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004798 if (ResTy == MatchOperand_Success) {
4799 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004800 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004801 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004802 llvm_unreachable("Should never ParseFail");
4803 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004804 }
Jack Carterd76b2372013-03-21 21:44:16 +00004805 }
4806 }
4807 return false;
4808}
Jack Carterd0bd6422013-04-18 00:41:53 +00004809
Alex Bradbury58eba092016-11-01 16:32:05 +00004810OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004811MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004812 StringRef Identifier,
4813 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004814 int Index = matchCPURegisterName(Identifier);
4815 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004816 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004817 Index, Identifier, getContext().getRegisterInfo(), S,
4818 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004819 return MatchOperand_Success;
4820 }
4821
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004822 Index = matchHWRegsRegisterName(Identifier);
4823 if (Index != -1) {
4824 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004825 Index, Identifier, getContext().getRegisterInfo(), S,
4826 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004827 return MatchOperand_Success;
4828 }
4829
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004830 Index = matchFPURegisterName(Identifier);
4831 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004832 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004833 Index, Identifier, getContext().getRegisterInfo(), S,
4834 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004835 return MatchOperand_Success;
4836 }
4837
4838 Index = matchFCCRegisterName(Identifier);
4839 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004840 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004841 Index, Identifier, getContext().getRegisterInfo(), S,
4842 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004843 return MatchOperand_Success;
4844 }
4845
4846 Index = matchACRegisterName(Identifier);
4847 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004848 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004849 Index, Identifier, getContext().getRegisterInfo(), S,
4850 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004851 return MatchOperand_Success;
4852 }
4853
4854 Index = matchMSA128RegisterName(Identifier);
4855 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004856 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004857 Index, Identifier, getContext().getRegisterInfo(), S,
4858 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004859 return MatchOperand_Success;
4860 }
4861
4862 Index = matchMSA128CtrlRegisterName(Identifier);
4863 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004864 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004865 Index, Identifier, getContext().getRegisterInfo(), S,
4866 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004867 return MatchOperand_Success;
4868 }
4869
4870 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004871}
4872
Alex Bradbury58eba092016-11-01 16:32:05 +00004873OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004874MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004875 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004876 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004877
4878 if (Token.is(AsmToken::Identifier)) {
4879 DEBUG(dbgs() << ".. identifier\n");
4880 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004881 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004882 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004883 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004884 } else if (Token.is(AsmToken::Integer)) {
4885 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004886 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004887 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
4888 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004889 return MatchOperand_Success;
4890 }
4891
4892 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4893
4894 return MatchOperand_NoMatch;
4895}
4896
Alex Bradbury58eba092016-11-01 16:32:05 +00004897OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004898MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004899 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004900 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004901
4902 auto Token = Parser.getTok();
4903
4904 SMLoc S = Token.getLoc();
4905
4906 if (Token.isNot(AsmToken::Dollar)) {
4907 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4908 if (Token.is(AsmToken::Identifier)) {
4909 if (searchSymbolAlias(Operands))
4910 return MatchOperand_Success;
4911 }
4912 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4913 return MatchOperand_NoMatch;
4914 }
4915 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004916
Toma Tabacu13964452014-09-04 13:23:44 +00004917 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004918 if (ResTy == MatchOperand_Success) {
4919 Parser.Lex(); // $
4920 Parser.Lex(); // identifier
4921 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004922 return ResTy;
4923}
4924
Alex Bradbury58eba092016-11-01 16:32:05 +00004925OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004926MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004927 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004928 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004929
4930 SMLoc S = getLexer().getLoc();
4931
Daniel Sanderscae9aee2016-08-08 09:33:14 +00004932 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004933 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00004934 if (ResTy != MatchOperand_NoMatch)
4935 return ResTy;
4936
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004937 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00004938 const MCExpr *Expr = nullptr;
4939 if (Parser.parseExpression(Expr)) {
4940 // We have no way of knowing if a symbol was consumed so we must ParseFail
4941 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004942 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004943 Operands.push_back(
4944 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004945 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004946}
4947
Alex Bradbury58eba092016-11-01 16:32:05 +00004948OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004949MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004950 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004951 const MCExpr *IdVal;
4952 // If the first token is '$' we may have register operand.
4953 if (Parser.getTok().is(AsmToken::Dollar))
4954 return MatchOperand_NoMatch;
4955 SMLoc S = Parser.getTok().getLoc();
4956 if (getParser().parseExpression(IdVal))
4957 return MatchOperand_ParseFail;
4958 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004959 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004960 int64_t Val = MCE->getValue();
4961 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4962 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004963 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004964 return MatchOperand_Success;
4965}
4966
Alex Bradbury58eba092016-11-01 16:32:05 +00004967OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004968MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4969 MCAsmParser &Parser = getParser();
4970 SmallVector<unsigned, 10> Regs;
4971 unsigned RegNo;
4972 unsigned PrevReg = Mips::NoRegister;
4973 bool RegRange = false;
4974 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4975
4976 if (Parser.getTok().isNot(AsmToken::Dollar))
4977 return MatchOperand_ParseFail;
4978
4979 SMLoc S = Parser.getTok().getLoc();
4980 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4981 SMLoc E = getLexer().getLoc();
4982 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4983 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4984 if (RegRange) {
4985 // Remove last register operand because registers from register range
4986 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004987 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4988 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004989 Regs.push_back(RegNo);
4990 } else {
4991 unsigned TmpReg = PrevReg + 1;
4992 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004993 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4994 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4995 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004996 Error(E, "invalid register operand");
4997 return MatchOperand_ParseFail;
4998 }
4999
5000 PrevReg = TmpReg;
5001 Regs.push_back(TmpReg++);
5002 }
5003 }
5004
5005 RegRange = false;
5006 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005007 if ((PrevReg == Mips::NoRegister) &&
5008 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
5009 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005010 Error(E, "$16 or $31 expected");
5011 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005012 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
5013 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
5014 !isGP64bit()) ||
5015 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
5016 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
5017 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005018 Error(E, "invalid register operand");
5019 return MatchOperand_ParseFail;
5020 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00005021 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
5022 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
5023 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00005024 Error(E, "consecutive register numbers expected");
5025 return MatchOperand_ParseFail;
5026 }
5027
5028 Regs.push_back(RegNo);
5029 }
5030
5031 if (Parser.getTok().is(AsmToken::Minus))
5032 RegRange = true;
5033
5034 if (!Parser.getTok().isNot(AsmToken::Minus) &&
5035 !Parser.getTok().isNot(AsmToken::Comma)) {
5036 Error(E, "',' or '-' expected");
5037 return MatchOperand_ParseFail;
5038 }
5039
5040 Lex(); // Consume comma or minus
5041 if (Parser.getTok().isNot(AsmToken::Dollar))
5042 break;
5043
5044 PrevReg = RegNo;
5045 }
5046
5047 SMLoc E = Parser.getTok().getLoc();
5048 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5049 parseMemOperand(Operands);
5050 return MatchOperand_Success;
5051}
5052
Alex Bradbury58eba092016-11-01 16:32:05 +00005053OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005054MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
5055 MCAsmParser &Parser = getParser();
5056
5057 SMLoc S = Parser.getTok().getLoc();
5058 if (parseAnyRegister(Operands) != MatchOperand_Success)
5059 return MatchOperand_ParseFail;
5060
5061 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00005062 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00005063
Benjamin Kramer2b68d152016-05-09 10:31:17 +00005064 Operands.pop_back();
5065 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005066 return MatchOperand_Success;
5067}
5068
Alex Bradbury58eba092016-11-01 16:32:05 +00005069OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00005070MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
5071 MCAsmParser &Parser = getParser();
5072 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5073 SmallVector<unsigned, 10> Regs;
5074
5075 if (Parser.getTok().isNot(AsmToken::Dollar))
5076 return MatchOperand_ParseFail;
5077
5078 SMLoc S = Parser.getTok().getLoc();
5079
5080 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5081 return MatchOperand_ParseFail;
5082
5083 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5084 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5085 Regs.push_back(RegNo);
5086
5087 SMLoc E = Parser.getTok().getLoc();
5088 if (Parser.getTok().isNot(AsmToken::Comma)) {
5089 Error(E, "',' expected");
5090 return MatchOperand_ParseFail;
5091 }
5092
5093 // Remove comma.
5094 Parser.Lex();
5095
5096 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5097 return MatchOperand_ParseFail;
5098
5099 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5100 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5101 Regs.push_back(RegNo);
5102
5103 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5104
5105 return MatchOperand_Success;
5106}
5107
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005108/// Sometimes (i.e. load/stores) the operand may be followed immediately by
5109/// either this.
5110/// ::= '(', register, ')'
5111/// handle it before we iterate so we don't get tripped up by the lack of
5112/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005113bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005114 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005115 if (getLexer().is(AsmToken::LParen)) {
5116 Operands.push_back(
5117 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
5118 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005119 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005120 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005121 return Error(Loc, "unexpected token in argument list");
5122 }
5123 if (Parser.getTok().isNot(AsmToken::RParen)) {
5124 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005125 return Error(Loc, "unexpected token, expected ')'");
5126 }
5127 Operands.push_back(
5128 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
5129 Parser.Lex();
5130 }
5131 return false;
5132}
5133
5134/// Sometimes (i.e. in MSA) the operand may be followed immediately by
5135/// either one of these.
5136/// ::= '[', register, ']'
5137/// ::= '[', integer, ']'
5138/// handle it before we iterate so we don't get tripped up by the lack of
5139/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005140bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00005141 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005142 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005143 if (getLexer().is(AsmToken::LBrac)) {
5144 Operands.push_back(
5145 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
5146 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005147 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005148 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005149 return Error(Loc, "unexpected token in argument list");
5150 }
5151 if (Parser.getTok().isNot(AsmToken::RBrac)) {
5152 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005153 return Error(Loc, "unexpected token, expected ']'");
5154 }
5155 Operands.push_back(
5156 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
5157 Parser.Lex();
5158 }
5159 return false;
5160}
5161
David Blaikie960ea3f2014-06-08 16:18:35 +00005162bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
5163 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005164 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005165 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005166
5167 // We have reached first instruction, module directive are now forbidden.
5168 getTargetStreamer().forbidModuleDirective();
5169
Vladimir Medic74593e62013-07-17 15:00:42 +00005170 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00005171 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005172 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00005173 }
Vladimir Medic64828a12013-07-16 10:07:14 +00005174 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005175 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005176
5177 // Read the remaining operands.
5178 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5179 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005180 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005181 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005182 return Error(Loc, "unexpected token in argument list");
5183 }
Toma Tabacu13964452014-09-04 13:23:44 +00005184 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005185 return true;
5186 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00005187
Jack Carterd0bd6422013-04-18 00:41:53 +00005188 while (getLexer().is(AsmToken::Comma)) {
5189 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00005190 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005191 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005192 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005193 return Error(Loc, "unexpected token in argument list");
5194 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005195 // Parse bracket and parenthesis suffixes before we iterate
5196 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00005197 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005198 return true;
5199 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00005200 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005201 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005202 }
5203 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005204 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5205 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005206 return Error(Loc, "unexpected token in argument list");
5207 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005208 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00005209 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00005210}
5211
Nirav Dave996fc132016-05-05 14:15:46 +00005212// FIXME: Given that these have the same name, these should both be
5213// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005214bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005215 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005216 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00005217}
5218
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005219bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005220 return Error(Loc, ErrorMsg);
5221}
5222
Jack Carter0b744b32012-10-04 02:29:46 +00005223bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005224 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005225 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00005226
5227 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00005228 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00005229
5230 Parser.Lex(); // Eat "noat".
5231
Jack Carterd0bd6422013-04-18 00:41:53 +00005232 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005233 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005234 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005235 return false;
5236 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005237
5238 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005239 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005240 return false;
5241}
Jack Carterd0bd6422013-04-18 00:41:53 +00005242
Jack Carter0b744b32012-10-04 02:29:46 +00005243bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00005244 // Line can be: ".set at", which sets $at to $1
5245 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00005246 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00005247 Parser.Lex(); // Eat "at".
5248
Jack Carter0b744b32012-10-04 02:29:46 +00005249 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005250 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00005251 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00005252
5253 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005254 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005255 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00005256 }
5257
5258 if (getLexer().isNot(AsmToken::Equal)) {
5259 reportParseError("unexpected token, expected equals sign");
5260 return false;
5261 }
5262 Parser.Lex(); // Eat "=".
5263
5264 if (getLexer().isNot(AsmToken::Dollar)) {
5265 if (getLexer().is(AsmToken::EndOfStatement)) {
5266 reportParseError("no register specified");
5267 return false;
5268 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00005269 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00005270 return false;
5271 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005272 }
5273 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00005274
Toma Tabacu16a74492015-02-13 10:30:57 +00005275 // Find out what "reg" is.
5276 unsigned AtRegNo;
5277 const AsmToken &Reg = Parser.getTok();
5278 if (Reg.is(AsmToken::Identifier)) {
5279 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
5280 } else if (Reg.is(AsmToken::Integer)) {
5281 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00005282 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00005283 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00005284 return false;
5285 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005286
5287 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00005288 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005289 reportParseError("invalid register");
5290 return false;
5291 }
5292 Parser.Lex(); // Eat "reg".
5293
5294 // If this is not the end of the statement, report an error.
5295 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5296 reportParseError("unexpected token, expected end of statement");
5297 return false;
5298 }
5299
5300 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
5301
5302 Parser.Lex(); // Consume the EndOfStatement.
5303 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005304}
5305
5306bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005307 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005308 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005309 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005310 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005311 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005312 return false;
5313 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005314 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00005315 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005316 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005317 return false;
5318}
5319
5320bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005321 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005322 Parser.Lex();
5323 // If this is not the end of the statement, report an error.
5324 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005325 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005326 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005327 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005328 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005329 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005330 Parser.Lex(); // Consume the EndOfStatement.
5331 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005332}
5333
5334bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005335 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005336 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005337 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005338 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005339 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005340 return false;
5341 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005342 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005343 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005344 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005345 return false;
5346}
5347
5348bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005349 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005350 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005351 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005352 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005353 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005354 return false;
5355 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005356 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005357 reportParseError("`noreorder' must be set before `nomacro'");
5358 return false;
5359 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005360 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005361 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005362 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005363 return false;
5364}
Jack Carterd76b2372013-03-21 21:44:16 +00005365
Daniel Sanders44934432014-08-07 12:03:36 +00005366bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005367 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005368 Parser.Lex();
5369
5370 // If this is not the end of the statement, report an error.
5371 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005372 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005373
5374 setFeatureBits(Mips::FeatureMSA, "msa");
5375 getTargetStreamer().emitDirectiveSetMsa();
5376 return false;
5377}
5378
5379bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005380 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005381 Parser.Lex();
5382
5383 // If this is not the end of the statement, report an error.
5384 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005385 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005386
5387 clearFeatureBits(Mips::FeatureMSA, "msa");
5388 getTargetStreamer().emitDirectiveSetNoMsa();
5389 return false;
5390}
5391
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005392bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005393 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005394 Parser.Lex(); // Eat "nodsp".
5395
5396 // If this is not the end of the statement, report an error.
5397 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5398 reportParseError("unexpected token, expected end of statement");
5399 return false;
5400 }
5401
5402 clearFeatureBits(Mips::FeatureDSP, "dsp");
5403 getTargetStreamer().emitDirectiveSetNoDsp();
5404 return false;
5405}
5406
Toma Tabacucc2502d2014-11-04 17:18:07 +00005407bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005408 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005409 Parser.Lex(); // Eat "mips16".
5410
Jack Carter39536722014-01-22 23:08:42 +00005411 // If this is not the end of the statement, report an error.
5412 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005413 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005414 return false;
5415 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005416
5417 setFeatureBits(Mips::FeatureMips16, "mips16");
5418 getTargetStreamer().emitDirectiveSetMips16();
5419 Parser.Lex(); // Consume the EndOfStatement.
5420 return false;
5421}
5422
5423bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005424 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005425 Parser.Lex(); // Eat "nomips16".
5426
5427 // 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
5433 clearFeatureBits(Mips::FeatureMips16, "mips16");
5434 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005435 Parser.Lex(); // Consume the EndOfStatement.
5436 return false;
5437}
5438
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005439bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005440 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005441 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005442 // Line can be: .set fp=32
5443 // .set fp=xx
5444 // .set fp=64
5445 Parser.Lex(); // Eat fp token
5446 AsmToken Tok = Parser.getTok();
5447 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005448 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005449 return false;
5450 }
5451 Parser.Lex(); // Eat '=' token.
5452 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005453
5454 if (!parseFpABIValue(FpAbiVal, ".set"))
5455 return false;
5456
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005457 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005458 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005459 return false;
5460 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005461 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005462 Parser.Lex(); // Consume the EndOfStatement.
5463 return false;
5464}
5465
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005466bool MipsAsmParser::parseSetOddSPRegDirective() {
5467 MCAsmParser &Parser = getParser();
5468
5469 Parser.Lex(); // Eat "oddspreg".
5470 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5471 reportParseError("unexpected token, expected end of statement");
5472 return false;
5473 }
5474
5475 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5476 getTargetStreamer().emitDirectiveSetOddSPReg();
5477 return false;
5478}
5479
5480bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5481 MCAsmParser &Parser = getParser();
5482
5483 Parser.Lex(); // Eat "nooddspreg".
5484 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5485 reportParseError("unexpected token, expected end of statement");
5486 return false;
5487 }
5488
5489 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5490 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5491 return false;
5492}
5493
Toma Tabacu9db22db2014-09-09 10:15:38 +00005494bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005495 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005496 SMLoc Loc = getLexer().getLoc();
5497
5498 Parser.Lex();
5499 if (getLexer().isNot(AsmToken::EndOfStatement))
5500 return reportParseError("unexpected token, expected end of statement");
5501
5502 // Always keep an element on the options "stack" to prevent the user
5503 // from changing the initial options. This is how we remember them.
5504 if (AssemblerOptions.size() == 2)
5505 return reportParseError(Loc, ".set pop with no .set push");
5506
Akira Hatanakab11ef082015-11-14 06:35:56 +00005507 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005508 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005509 setAvailableFeatures(
5510 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5511 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005512
5513 getTargetStreamer().emitDirectiveSetPop();
5514 return false;
5515}
5516
5517bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005518 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005519 Parser.Lex();
5520 if (getLexer().isNot(AsmToken::EndOfStatement))
5521 return reportParseError("unexpected token, expected end of statement");
5522
5523 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005524 AssemblerOptions.push_back(
5525 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005526
5527 getTargetStreamer().emitDirectiveSetPush();
5528 return false;
5529}
5530
Toma Tabacu29696502015-06-02 09:48:04 +00005531bool MipsAsmParser::parseSetSoftFloatDirective() {
5532 MCAsmParser &Parser = getParser();
5533 Parser.Lex();
5534 if (getLexer().isNot(AsmToken::EndOfStatement))
5535 return reportParseError("unexpected token, expected end of statement");
5536
5537 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5538 getTargetStreamer().emitDirectiveSetSoftFloat();
5539 return false;
5540}
5541
5542bool MipsAsmParser::parseSetHardFloatDirective() {
5543 MCAsmParser &Parser = getParser();
5544 Parser.Lex();
5545 if (getLexer().isNot(AsmToken::EndOfStatement))
5546 return reportParseError("unexpected token, expected end of statement");
5547
5548 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5549 getTargetStreamer().emitDirectiveSetHardFloat();
5550 return false;
5551}
5552
Jack Carterd76b2372013-03-21 21:44:16 +00005553bool MipsAsmParser::parseSetAssignment() {
5554 StringRef Name;
5555 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005556 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005557
5558 if (Parser.parseIdentifier(Name))
5559 reportParseError("expected identifier after .set");
5560
5561 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005562 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005563 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005564
Jack Carter3b2c96e2014-01-22 23:31:38 +00005565 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005566 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005567
Jim Grosbach6f482002015-05-18 18:43:14 +00005568 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005569 Sym->setVariableValue(Value);
5570
5571 return false;
5572}
Jack Carterd0bd6422013-04-18 00:41:53 +00005573
Toma Tabacu26647792014-09-09 12:52:14 +00005574bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005575 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005576 Parser.Lex();
5577 if (getLexer().isNot(AsmToken::EndOfStatement))
5578 return reportParseError("unexpected token, expected end of statement");
5579
5580 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005581 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005582 setAvailableFeatures(
5583 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5584 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005585 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5586
5587 getTargetStreamer().emitDirectiveSetMips0();
5588 return false;
5589}
5590
Toma Tabacu85618b32014-08-19 14:22:52 +00005591bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005592 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005593 Parser.Lex();
5594 if (getLexer().isNot(AsmToken::Equal))
5595 return reportParseError("unexpected token, expected equals sign");
5596
5597 Parser.Lex();
5598 StringRef Arch;
5599 if (Parser.parseIdentifier(Arch))
5600 return reportParseError("expected arch identifier");
5601
5602 StringRef ArchFeatureName =
5603 StringSwitch<StringRef>(Arch)
5604 .Case("mips1", "mips1")
5605 .Case("mips2", "mips2")
5606 .Case("mips3", "mips3")
5607 .Case("mips4", "mips4")
5608 .Case("mips5", "mips5")
5609 .Case("mips32", "mips32")
5610 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005611 .Case("mips32r3", "mips32r3")
5612 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005613 .Case("mips32r6", "mips32r6")
5614 .Case("mips64", "mips64")
5615 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005616 .Case("mips64r3", "mips64r3")
5617 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005618 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005619 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005620 .Case("r4000", "mips3") // This is an implementation of Mips3.
5621 .Default("");
5622
5623 if (ArchFeatureName.empty())
5624 return reportParseError("unsupported architecture");
5625
5626 selectArch(ArchFeatureName);
5627 getTargetStreamer().emitDirectiveSetArch(Arch);
5628 return false;
5629}
5630
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005631bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005632 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005633 Parser.Lex();
5634 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005635 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005636
Matheus Almeida2852af82014-04-22 10:15:54 +00005637 switch (Feature) {
5638 default:
5639 llvm_unreachable("Unimplemented feature");
5640 case Mips::FeatureDSP:
5641 setFeatureBits(Mips::FeatureDSP, "dsp");
5642 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005643 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005644 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00005645 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00005646 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005647 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005648 case Mips::FeatureMips1:
5649 selectArch("mips1");
5650 getTargetStreamer().emitDirectiveSetMips1();
5651 break;
5652 case Mips::FeatureMips2:
5653 selectArch("mips2");
5654 getTargetStreamer().emitDirectiveSetMips2();
5655 break;
5656 case Mips::FeatureMips3:
5657 selectArch("mips3");
5658 getTargetStreamer().emitDirectiveSetMips3();
5659 break;
5660 case Mips::FeatureMips4:
5661 selectArch("mips4");
5662 getTargetStreamer().emitDirectiveSetMips4();
5663 break;
5664 case Mips::FeatureMips5:
5665 selectArch("mips5");
5666 getTargetStreamer().emitDirectiveSetMips5();
5667 break;
5668 case Mips::FeatureMips32:
5669 selectArch("mips32");
5670 getTargetStreamer().emitDirectiveSetMips32();
5671 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005672 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005673 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005674 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005675 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005676 case Mips::FeatureMips32r3:
5677 selectArch("mips32r3");
5678 getTargetStreamer().emitDirectiveSetMips32R3();
5679 break;
5680 case Mips::FeatureMips32r5:
5681 selectArch("mips32r5");
5682 getTargetStreamer().emitDirectiveSetMips32R5();
5683 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005684 case Mips::FeatureMips32r6:
5685 selectArch("mips32r6");
5686 getTargetStreamer().emitDirectiveSetMips32R6();
5687 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005688 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005689 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005690 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005691 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005692 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005693 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005694 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005695 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005696 case Mips::FeatureMips64r3:
5697 selectArch("mips64r3");
5698 getTargetStreamer().emitDirectiveSetMips64R3();
5699 break;
5700 case Mips::FeatureMips64r5:
5701 selectArch("mips64r5");
5702 getTargetStreamer().emitDirectiveSetMips64R5();
5703 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005704 case Mips::FeatureMips64r6:
5705 selectArch("mips64r6");
5706 getTargetStreamer().emitDirectiveSetMips64R6();
5707 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005708 }
5709 return false;
5710}
5711
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005712bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005713 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005714 if (getLexer().isNot(AsmToken::Comma)) {
5715 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005716 return Error(Loc, ErrorStr);
5717 }
5718
Matheus Almeida2852af82014-04-22 10:15:54 +00005719 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005720 return true;
5721}
5722
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005723// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5724// In this class, it is only used for .cprestore.
5725// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5726// MipsTargetELFStreamer and MipsAsmParser.
5727bool MipsAsmParser::isPicAndNotNxxAbi() {
5728 return inPicMode() && !(isABI_N32() || isABI_N64());
5729}
5730
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005731bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005732 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005733 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005734
Toma Tabacudde4c462014-11-06 10:02:45 +00005735 if (inMips16Mode()) {
5736 reportParseError(".cpload is not supported in Mips16 mode");
5737 return false;
5738 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005739
David Blaikie960ea3f2014-06-08 16:18:35 +00005740 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005741 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005742 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5743 reportParseError("expected register containing function address");
5744 return false;
5745 }
5746
David Blaikie960ea3f2014-06-08 16:18:35 +00005747 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5748 if (!RegOpnd.isGPRAsmReg()) {
5749 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005750 return false;
5751 }
5752
Toma Tabacudde4c462014-11-06 10:02:45 +00005753 // If this is not the end of the statement, report an error.
5754 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5755 reportParseError("unexpected token, expected end of statement");
5756 return false;
5757 }
5758
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005759 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005760 return false;
5761}
5762
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005763bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5764 MCAsmParser &Parser = getParser();
5765
5766 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5767 // is used in non-PIC mode.
5768
5769 if (inMips16Mode()) {
5770 reportParseError(".cprestore is not supported in Mips16 mode");
5771 return false;
5772 }
5773
5774 // Get the stack offset value.
5775 const MCExpr *StackOffset;
5776 int64_t StackOffsetVal;
5777 if (Parser.parseExpression(StackOffset)) {
5778 reportParseError("expected stack offset value");
5779 return false;
5780 }
5781
5782 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5783 reportParseError("stack offset is not an absolute expression");
5784 return false;
5785 }
5786
5787 if (StackOffsetVal < 0) {
5788 Warning(Loc, ".cprestore with negative stack offset has no effect");
5789 IsCpRestoreSet = false;
5790 } else {
5791 IsCpRestoreSet = true;
5792 CpRestoreOffset = StackOffsetVal;
5793 }
5794
5795 // If this is not the end of the statement, report an error.
5796 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5797 reportParseError("unexpected token, expected end of statement");
5798 return false;
5799 }
5800
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005801 if (!getTargetStreamer().emitDirectiveCpRestore(
5802 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005803 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005804 Parser.Lex(); // Consume the EndOfStatement.
5805 return false;
5806}
5807
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005808bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005809 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005810 unsigned FuncReg;
5811 unsigned Save;
5812 bool SaveIsReg = true;
5813
Matheus Almeida7e815762014-06-18 13:08:59 +00005814 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005815 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005816 if (ResTy == MatchOperand_NoMatch) {
5817 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005818 return false;
5819 }
5820
5821 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5822 if (!FuncRegOpnd.isGPRAsmReg()) {
5823 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005824 return false;
5825 }
5826
5827 FuncReg = FuncRegOpnd.getGPR32Reg();
5828 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005829
Toma Tabacu65f10572014-09-16 15:00:52 +00005830 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005831 return true;
5832
Toma Tabacu13964452014-09-04 13:23:44 +00005833 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005834 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005835 const MCExpr *OffsetExpr;
5836 int64_t OffsetVal;
5837 SMLoc ExprLoc = getLexer().getLoc();
5838
5839 if (Parser.parseExpression(OffsetExpr) ||
5840 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5841 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005842 return false;
5843 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005844
5845 Save = OffsetVal;
5846 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005847 } else {
5848 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5849 if (!SaveOpnd.isGPRAsmReg()) {
5850 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005851 return false;
5852 }
5853 Save = SaveOpnd.getGPR32Reg();
5854 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005855
Toma Tabacu65f10572014-09-16 15:00:52 +00005856 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005857 return true;
5858
Toma Tabacu8874eac2015-02-18 13:46:53 +00005859 const MCExpr *Expr;
5860 if (Parser.parseExpression(Expr)) {
5861 reportParseError("expected expression");
5862 return false;
5863 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005864
Toma Tabacu8874eac2015-02-18 13:46:53 +00005865 if (Expr->getKind() != MCExpr::SymbolRef) {
5866 reportParseError("expected symbol");
5867 return false;
5868 }
5869 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5870
Daniel Sandersf173dda2015-09-22 10:50:09 +00005871 CpSaveLocation = Save;
5872 CpSaveLocationIsRegister = SaveIsReg;
5873
Toma Tabacu8874eac2015-02-18 13:46:53 +00005874 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5875 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005876 return false;
5877}
5878
Daniel Sandersf173dda2015-09-22 10:50:09 +00005879bool MipsAsmParser::parseDirectiveCPReturn() {
5880 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5881 CpSaveLocationIsRegister);
5882 return false;
5883}
5884
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005885bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005886 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005887 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5888 const AsmToken &Tok = Parser.getTok();
5889
5890 if (Tok.getString() == "2008") {
5891 Parser.Lex();
5892 getTargetStreamer().emitDirectiveNaN2008();
5893 return false;
5894 } else if (Tok.getString() == "legacy") {
5895 Parser.Lex();
5896 getTargetStreamer().emitDirectiveNaNLegacy();
5897 return false;
5898 }
5899 }
5900 // If we don't recognize the option passed to the .nan
5901 // directive (e.g. no option or unknown option), emit an error.
5902 reportParseError("invalid option in .nan directive");
5903 return false;
5904}
5905
Jack Carter0b744b32012-10-04 02:29:46 +00005906bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005907 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005908 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005909 const AsmToken &Tok = Parser.getTok();
5910
5911 if (Tok.getString() == "noat") {
5912 return parseSetNoAtDirective();
5913 } else if (Tok.getString() == "at") {
5914 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005915 } else if (Tok.getString() == "arch") {
5916 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005917 } else if (Tok.getString() == "fp") {
5918 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005919 } else if (Tok.getString() == "oddspreg") {
5920 return parseSetOddSPRegDirective();
5921 } else if (Tok.getString() == "nooddspreg") {
5922 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005923 } else if (Tok.getString() == "pop") {
5924 return parseSetPopDirective();
5925 } else if (Tok.getString() == "push") {
5926 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005927 } else if (Tok.getString() == "reorder") {
5928 return parseSetReorderDirective();
5929 } else if (Tok.getString() == "noreorder") {
5930 return parseSetNoReorderDirective();
5931 } else if (Tok.getString() == "macro") {
5932 return parseSetMacroDirective();
5933 } else if (Tok.getString() == "nomacro") {
5934 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005935 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005936 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005937 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005938 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005939 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00005940 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005941 getTargetStreamer().emitDirectiveSetNoMicroMips();
5942 Parser.eatToEndOfStatement();
5943 return false;
5944 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005945 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005946 } else if (Tok.getString() == "mips0") {
5947 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005948 } else if (Tok.getString() == "mips1") {
5949 return parseSetFeature(Mips::FeatureMips1);
5950 } else if (Tok.getString() == "mips2") {
5951 return parseSetFeature(Mips::FeatureMips2);
5952 } else if (Tok.getString() == "mips3") {
5953 return parseSetFeature(Mips::FeatureMips3);
5954 } else if (Tok.getString() == "mips4") {
5955 return parseSetFeature(Mips::FeatureMips4);
5956 } else if (Tok.getString() == "mips5") {
5957 return parseSetFeature(Mips::FeatureMips5);
5958 } else if (Tok.getString() == "mips32") {
5959 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005960 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005961 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005962 } else if (Tok.getString() == "mips32r3") {
5963 return parseSetFeature(Mips::FeatureMips32r3);
5964 } else if (Tok.getString() == "mips32r5") {
5965 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005966 } else if (Tok.getString() == "mips32r6") {
5967 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005968 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005969 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005970 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005971 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005972 } else if (Tok.getString() == "mips64r3") {
5973 return parseSetFeature(Mips::FeatureMips64r3);
5974 } else if (Tok.getString() == "mips64r5") {
5975 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005976 } else if (Tok.getString() == "mips64r6") {
5977 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005978 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005979 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005980 } else if (Tok.getString() == "nodsp") {
5981 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005982 } else if (Tok.getString() == "msa") {
5983 return parseSetMsaDirective();
5984 } else if (Tok.getString() == "nomsa") {
5985 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005986 } else if (Tok.getString() == "softfloat") {
5987 return parseSetSoftFloatDirective();
5988 } else if (Tok.getString() == "hardfloat") {
5989 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005990 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005991 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005992 parseSetAssignment();
5993 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005994 }
Jack Carter07c818d2013-01-25 01:31:34 +00005995
Jack Carter0b744b32012-10-04 02:29:46 +00005996 return true;
5997}
5998
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005999/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00006000/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006001bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006002 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006003 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6004 for (;;) {
6005 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00006006 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00006007 return true;
6008
6009 getParser().getStreamer().EmitValue(Value, Size);
6010
6011 if (getLexer().is(AsmToken::EndOfStatement))
6012 break;
6013
Jack Carter07c818d2013-01-25 01:31:34 +00006014 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00006015 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00006016 Parser.Lex();
6017 }
6018 }
6019
6020 Parser.Lex();
6021 return false;
6022}
6023
Vladimir Medic4c299852013-11-06 11:27:05 +00006024/// parseDirectiveGpWord
6025/// ::= .gpword local_sym
6026bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006027 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00006028 const MCExpr *Value;
6029 // EmitGPRel32Value requires an expression, so we are using base class
6030 // method to evaluate the expression.
6031 if (getParser().parseExpression(Value))
6032 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00006033 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00006034
Vladimir Medice10c1122013-11-13 13:18:04 +00006035 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00006036 return Error(getLexer().getLoc(),
6037 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00006038 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00006039 return false;
6040}
6041
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006042/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00006043/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006044bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006045 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006046 const MCExpr *Value;
6047 // EmitGPRel64Value requires an expression, so we are using base class
6048 // method to evaluate the expression.
6049 if (getParser().parseExpression(Value))
6050 return true;
6051 getParser().getStreamer().EmitGPRel64Value(Value);
6052
6053 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006054 return Error(getLexer().getLoc(),
6055 "unexpected token, expected end of statement");
6056 Parser.Lex(); // Eat EndOfStatement token.
6057 return false;
6058}
6059
6060/// parseDirectiveDtpRelWord
6061/// ::= .dtprelword tls_sym
6062bool MipsAsmParser::parseDirectiveDtpRelWord() {
6063 MCAsmParser &Parser = getParser();
6064 const MCExpr *Value;
6065 // EmitDTPRel32Value requires an expression, so we are using base class
6066 // method to evaluate the expression.
6067 if (getParser().parseExpression(Value))
6068 return true;
6069 getParser().getStreamer().EmitDTPRel32Value(Value);
6070
6071 if (getLexer().isNot(AsmToken::EndOfStatement))
6072 return Error(getLexer().getLoc(),
6073 "unexpected token, expected end of statement");
6074 Parser.Lex(); // Eat EndOfStatement token.
6075 return false;
6076}
6077
6078/// parseDirectiveDtpRelDWord
6079/// ::= .dtpreldword tls_sym
6080bool MipsAsmParser::parseDirectiveDtpRelDWord() {
6081 MCAsmParser &Parser = getParser();
6082 const MCExpr *Value;
6083 // EmitDTPRel64Value requires an expression, so we are using base class
6084 // method to evaluate the expression.
6085 if (getParser().parseExpression(Value))
6086 return true;
6087 getParser().getStreamer().EmitDTPRel64Value(Value);
6088
6089 if (getLexer().isNot(AsmToken::EndOfStatement))
6090 return Error(getLexer().getLoc(),
6091 "unexpected token, expected end of statement");
6092 Parser.Lex(); // Eat EndOfStatement token.
6093 return false;
6094}
6095
6096/// parseDirectiveTpRelWord
6097/// ::= .tprelword tls_sym
6098bool MipsAsmParser::parseDirectiveTpRelWord() {
6099 MCAsmParser &Parser = getParser();
6100 const MCExpr *Value;
6101 // EmitTPRel32Value requires an expression, so we are using base class
6102 // method to evaluate the expression.
6103 if (getParser().parseExpression(Value))
6104 return true;
6105 getParser().getStreamer().EmitTPRel32Value(Value);
6106
6107 if (getLexer().isNot(AsmToken::EndOfStatement))
6108 return Error(getLexer().getLoc(),
6109 "unexpected token, expected end of statement");
6110 Parser.Lex(); // Eat EndOfStatement token.
6111 return false;
6112}
6113
6114/// parseDirectiveTpRelDWord
6115/// ::= .tpreldword tls_sym
6116bool MipsAsmParser::parseDirectiveTpRelDWord() {
6117 MCAsmParser &Parser = getParser();
6118 const MCExpr *Value;
6119 // EmitTPRel64Value requires an expression, so we are using base class
6120 // method to evaluate the expression.
6121 if (getParser().parseExpression(Value))
6122 return true;
6123 getParser().getStreamer().EmitTPRel64Value(Value);
6124
6125 if (getLexer().isNot(AsmToken::EndOfStatement))
6126 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00006127 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00006128 Parser.Lex(); // Eat EndOfStatement token.
6129 return false;
6130}
6131
Jack Carter0cd3c192014-01-06 23:27:31 +00006132bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006133 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00006134 // Get the option token.
6135 AsmToken Tok = Parser.getTok();
6136 // At the moment only identifiers are supported.
6137 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006138 return Error(Parser.getTok().getLoc(),
6139 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00006140 }
6141
6142 StringRef Option = Tok.getIdentifier();
6143
6144 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006145 // MipsAsmParser needs to know if the current PIC mode changes.
6146 IsPicEnabled = false;
6147
Jack Carter0cd3c192014-01-06 23:27:31 +00006148 getTargetStreamer().emitDirectiveOptionPic0();
6149 Parser.Lex();
6150 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006151 return Error(Parser.getTok().getLoc(),
6152 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006153 }
6154 return false;
6155 }
6156
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006157 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006158 // MipsAsmParser needs to know if the current PIC mode changes.
6159 IsPicEnabled = true;
6160
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006161 getTargetStreamer().emitDirectiveOptionPic2();
6162 Parser.Lex();
6163 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006164 return Error(Parser.getTok().getLoc(),
6165 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006166 }
6167 return false;
6168 }
6169
Jack Carter0cd3c192014-01-06 23:27:31 +00006170 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00006171 Warning(Parser.getTok().getLoc(),
6172 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00006173 Parser.eatToEndOfStatement();
6174 return false;
6175}
6176
Toma Tabacu9ca50962015-04-16 09:53:47 +00006177/// parseInsnDirective
6178/// ::= .insn
6179bool MipsAsmParser::parseInsnDirective() {
6180 // If this is not the end of the statement, report an error.
6181 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6182 reportParseError("unexpected token, expected end of statement");
6183 return false;
6184 }
6185
6186 // The actual label marking happens in
6187 // MipsELFStreamer::createPendingLabelRelocs().
6188 getTargetStreamer().emitDirectiveInsn();
6189
6190 getParser().Lex(); // Eat EndOfStatement token.
6191 return false;
6192}
6193
Simon Atanasyanbe186202016-02-11 06:45:54 +00006194/// parseSSectionDirective
6195/// ::= .sbss
6196/// ::= .sdata
6197bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
6198 // If this is not the end of the statement, report an error.
6199 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6200 reportParseError("unexpected token, expected end of statement");
6201 return false;
6202 }
6203
6204 MCSection *ELFSection = getContext().getELFSection(
6205 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
6206 getParser().getStreamer().SwitchSection(ELFSection);
6207
6208 getParser().Lex(); // Eat EndOfStatement token.
6209 return false;
6210}
6211
Daniel Sanders7e527422014-07-10 13:38:23 +00006212/// parseDirectiveModule
6213/// ::= .module oddspreg
6214/// ::= .module nooddspreg
6215/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00006216/// ::= .module softfloat
6217/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006218bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006219 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006220 MCAsmLexer &Lexer = getLexer();
6221 SMLoc L = Lexer.getLoc();
6222
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006223 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006224 // TODO : get a better message.
6225 reportParseError(".module directive must appear before any code");
6226 return false;
6227 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006228
Toma Tabacuc405c822015-01-23 10:40:19 +00006229 StringRef Option;
6230 if (Parser.parseIdentifier(Option)) {
6231 reportParseError("expected .module option identifier");
6232 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006233 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006234
Toma Tabacuc405c822015-01-23 10:40:19 +00006235 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006236 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006237
Toma Tabacu3c499582015-06-25 10:56:57 +00006238 // Synchronize the abiflags information with the FeatureBits information we
6239 // changed above.
6240 getTargetStreamer().updateABIInfo(*this);
6241
6242 // If printing assembly, use the recently updated abiflags information.
6243 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6244 // emitted at the end).
6245 getTargetStreamer().emitDirectiveModuleOddSPReg();
6246
Toma Tabacuc405c822015-01-23 10:40:19 +00006247 // If this is not the end of the statement, report an error.
6248 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6249 reportParseError("unexpected token, expected end of statement");
6250 return false;
6251 }
6252
6253 return false; // parseDirectiveModule has finished successfully.
6254 } else if (Option == "nooddspreg") {
6255 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006256 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00006257 }
6258
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006259 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006260
Toma Tabacu3c499582015-06-25 10:56:57 +00006261 // Synchronize the abiflags information with the FeatureBits information we
6262 // changed above.
6263 getTargetStreamer().updateABIInfo(*this);
6264
6265 // If printing assembly, use the recently updated abiflags information.
6266 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6267 // emitted at the end).
6268 getTargetStreamer().emitDirectiveModuleOddSPReg();
6269
Toma Tabacuc405c822015-01-23 10:40:19 +00006270 // If this is not the end of the statement, report an error.
6271 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6272 reportParseError("unexpected token, expected end of statement");
6273 return false;
6274 }
6275
6276 return false; // parseDirectiveModule has finished successfully.
6277 } else if (Option == "fp") {
6278 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00006279 } else if (Option == "softfloat") {
6280 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6281
6282 // Synchronize the ABI Flags information with the FeatureBits information we
6283 // updated above.
6284 getTargetStreamer().updateABIInfo(*this);
6285
6286 // If printing assembly, use the recently updated ABI Flags information.
6287 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6288 // emitted later).
6289 getTargetStreamer().emitDirectiveModuleSoftFloat();
6290
6291 // If this is not the end of the statement, report an error.
6292 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6293 reportParseError("unexpected token, expected end of statement");
6294 return false;
6295 }
6296
6297 return false; // parseDirectiveModule has finished successfully.
6298 } else if (Option == "hardfloat") {
6299 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6300
6301 // Synchronize the ABI Flags information with the FeatureBits information we
6302 // updated above.
6303 getTargetStreamer().updateABIInfo(*this);
6304
6305 // If printing assembly, use the recently updated ABI Flags information.
6306 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6307 // emitted later).
6308 getTargetStreamer().emitDirectiveModuleHardFloat();
6309
6310 // If this is not the end of the statement, report an error.
6311 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6312 reportParseError("unexpected token, expected end of statement");
6313 return false;
6314 }
6315
6316 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00006317 } else {
6318 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
6319 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006320}
6321
6322/// parseDirectiveModuleFP
6323/// ::= =32
6324/// ::= =xx
6325/// ::= =64
6326bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006327 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006328 MCAsmLexer &Lexer = getLexer();
6329
6330 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006331 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006332 return false;
6333 }
6334 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006335
Daniel Sanders7e527422014-07-10 13:38:23 +00006336 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006337 if (!parseFpABIValue(FpABI, ".module"))
6338 return false;
6339
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006340 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006341 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006342 return false;
6343 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006344
Toma Tabacua64e5402015-06-25 12:44:38 +00006345 // Synchronize the abiflags information with the FeatureBits information we
6346 // changed above.
6347 getTargetStreamer().updateABIInfo(*this);
6348
6349 // If printing assembly, use the recently updated abiflags information.
6350 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6351 // emitted at the end).
6352 getTargetStreamer().emitDirectiveModuleFP();
6353
Daniel Sanders7e527422014-07-10 13:38:23 +00006354 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006355 return false;
6356}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006357
Daniel Sanders7e527422014-07-10 13:38:23 +00006358bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006359 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006360 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006361 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006362 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006363
6364 if (Lexer.is(AsmToken::Identifier)) {
6365 StringRef Value = Parser.getTok().getString();
6366 Parser.Lex();
6367
6368 if (Value != "xx") {
6369 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6370 return false;
6371 }
6372
6373 if (!isABI_O32()) {
6374 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
6375 return false;
6376 }
6377
Daniel Sanders7e527422014-07-10 13:38:23 +00006378 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006379 if (ModuleLevelOptions) {
6380 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6381 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6382 } else {
6383 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6384 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6385 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006386 return true;
6387 }
6388
6389 if (Lexer.is(AsmToken::Integer)) {
6390 unsigned Value = Parser.getTok().getIntVal();
6391 Parser.Lex();
6392
6393 if (Value != 32 && Value != 64) {
6394 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6395 return false;
6396 }
6397
6398 if (Value == 32) {
6399 if (!isABI_O32()) {
6400 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6401 return false;
6402 }
6403
Daniel Sanders7e527422014-07-10 13:38:23 +00006404 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006405 if (ModuleLevelOptions) {
6406 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6407 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6408 } else {
6409 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6410 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6411 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006412 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006413 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006414 if (ModuleLevelOptions) {
6415 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6416 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6417 } else {
6418 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6419 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6420 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006421 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006422
Daniel Sanders7e527422014-07-10 13:38:23 +00006423 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006424 }
6425
6426 return false;
6427}
6428
Jack Carter0b744b32012-10-04 02:29:46 +00006429bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006430 // This returns false if this function recognizes the directive
6431 // regardless of whether it is successfully handles or reports an
6432 // error. Otherwise it returns true to give the generic parser a
6433 // chance at recognizing it.
6434
Rafael Espindola961d4692014-11-11 05:18:41 +00006435 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006436 StringRef IDVal = DirectiveID.getString();
6437
Nirav Dave996fc132016-05-05 14:15:46 +00006438 if (IDVal == ".cpload") {
6439 parseDirectiveCpLoad(DirectiveID.getLoc());
6440 return false;
6441 }
6442 if (IDVal == ".cprestore") {
6443 parseDirectiveCpRestore(DirectiveID.getLoc());
6444 return false;
6445 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006446 if (IDVal == ".dword") {
6447 parseDataDirective(8, DirectiveID.getLoc());
6448 return false;
6449 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006450 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006451 StringRef SymbolName;
6452
6453 if (Parser.parseIdentifier(SymbolName)) {
6454 reportParseError("expected identifier after .ent");
6455 return false;
6456 }
6457
6458 // There's an undocumented extension that allows an integer to
6459 // follow the name of the procedure which AFAICS is ignored by GAS.
6460 // Example: .ent foo,2
6461 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6462 if (getLexer().isNot(AsmToken::Comma)) {
6463 // Even though we accept this undocumented extension for compatibility
6464 // reasons, the additional integer argument does not actually change
6465 // the behaviour of the '.ent' directive, so we would like to discourage
6466 // its use. We do this by not referring to the extended version in
6467 // error messages which are not directly related to its use.
6468 reportParseError("unexpected token, expected end of statement");
6469 return false;
6470 }
6471 Parser.Lex(); // Eat the comma.
6472 const MCExpr *DummyNumber;
6473 int64_t DummyNumberVal;
6474 // If the user was explicitly trying to use the extended version,
6475 // we still give helpful extension-related error messages.
6476 if (Parser.parseExpression(DummyNumber)) {
6477 reportParseError("expected number after comma");
6478 return false;
6479 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006480 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006481 reportParseError("expected an absolute expression after comma");
6482 return false;
6483 }
6484 }
6485
6486 // If this is not the end of the statement, report an error.
6487 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6488 reportParseError("unexpected token, expected end of statement");
6489 return false;
6490 }
6491
Jim Grosbach6f482002015-05-18 18:43:14 +00006492 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006493
6494 getTargetStreamer().emitDirectiveEnt(*Sym);
6495 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006496 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006497 return false;
6498 }
6499
Jack Carter07c818d2013-01-25 01:31:34 +00006500 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006501 StringRef SymbolName;
6502
6503 if (Parser.parseIdentifier(SymbolName)) {
6504 reportParseError("expected identifier after .end");
6505 return false;
6506 }
6507
6508 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6509 reportParseError("unexpected token, expected end of statement");
6510 return false;
6511 }
6512
6513 if (CurrentFn == nullptr) {
6514 reportParseError(".end used without .ent");
6515 return false;
6516 }
6517
6518 if ((SymbolName != CurrentFn->getName())) {
6519 reportParseError(".end symbol does not match .ent symbol");
6520 return false;
6521 }
6522
6523 getTargetStreamer().emitDirectiveEnd(SymbolName);
6524 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006525 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006526 return false;
6527 }
6528
Jack Carter07c818d2013-01-25 01:31:34 +00006529 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006530 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6531 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006532 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006533 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6534 reportParseError("expected stack register");
6535 return false;
6536 }
6537
6538 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6539 if (!StackRegOpnd.isGPRAsmReg()) {
6540 reportParseError(StackRegOpnd.getStartLoc(),
6541 "expected general purpose register");
6542 return false;
6543 }
6544 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6545
6546 if (Parser.getTok().is(AsmToken::Comma))
6547 Parser.Lex();
6548 else {
6549 reportParseError("unexpected token, expected comma");
6550 return false;
6551 }
6552
6553 // Parse the frame size.
6554 const MCExpr *FrameSize;
6555 int64_t FrameSizeVal;
6556
6557 if (Parser.parseExpression(FrameSize)) {
6558 reportParseError("expected frame size value");
6559 return false;
6560 }
6561
Jim Grosbach13760bd2015-05-30 01:25:56 +00006562 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006563 reportParseError("frame size not an absolute expression");
6564 return false;
6565 }
6566
6567 if (Parser.getTok().is(AsmToken::Comma))
6568 Parser.Lex();
6569 else {
6570 reportParseError("unexpected token, expected comma");
6571 return false;
6572 }
6573
6574 // Parse the return register.
6575 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006576 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006577 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6578 reportParseError("expected return register");
6579 return false;
6580 }
6581
6582 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6583 if (!ReturnRegOpnd.isGPRAsmReg()) {
6584 reportParseError(ReturnRegOpnd.getStartLoc(),
6585 "expected general purpose register");
6586 return false;
6587 }
6588
6589 // If this is not the end of the statement, report an error.
6590 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6591 reportParseError("unexpected token, expected end of statement");
6592 return false;
6593 }
6594
6595 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6596 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006597 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006598 return false;
6599 }
6600
Jack Carter07c818d2013-01-25 01:31:34 +00006601 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006602 parseDirectiveSet();
6603 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006604 }
6605
Daniel Sandersd97a6342014-08-13 10:07:34 +00006606 if (IDVal == ".mask" || IDVal == ".fmask") {
6607 // .mask bitmask, frame_offset
6608 // bitmask: One bit for each register used.
6609 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6610 // first register is expected to be saved.
6611 // Examples:
6612 // .mask 0x80000000, -4
6613 // .fmask 0x80000000, -4
6614 //
Jack Carterbe332172012-09-07 00:48:02 +00006615
Daniel Sandersd97a6342014-08-13 10:07:34 +00006616 // Parse the bitmask
6617 const MCExpr *BitMask;
6618 int64_t BitMaskVal;
6619
6620 if (Parser.parseExpression(BitMask)) {
6621 reportParseError("expected bitmask value");
6622 return false;
6623 }
6624
Jim Grosbach13760bd2015-05-30 01:25:56 +00006625 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006626 reportParseError("bitmask not an absolute expression");
6627 return false;
6628 }
6629
6630 if (Parser.getTok().is(AsmToken::Comma))
6631 Parser.Lex();
6632 else {
6633 reportParseError("unexpected token, expected comma");
6634 return false;
6635 }
6636
6637 // Parse the frame_offset
6638 const MCExpr *FrameOffset;
6639 int64_t FrameOffsetVal;
6640
6641 if (Parser.parseExpression(FrameOffset)) {
6642 reportParseError("expected frame offset value");
6643 return false;
6644 }
6645
Jim Grosbach13760bd2015-05-30 01:25:56 +00006646 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006647 reportParseError("frame offset not an absolute expression");
6648 return false;
6649 }
6650
6651 // If this is not the end of the statement, report an error.
6652 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6653 reportParseError("unexpected token, expected end of statement");
6654 return false;
6655 }
6656
6657 if (IDVal == ".mask")
6658 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6659 else
6660 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006661 return false;
6662 }
6663
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006664 if (IDVal == ".nan")
6665 return parseDirectiveNaN();
6666
Jack Carter07c818d2013-01-25 01:31:34 +00006667 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006668 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006669 return false;
6670 }
6671
Rafael Espindolab59fb732014-03-28 18:50:26 +00006672 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006673 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006674 return false;
6675 }
6676
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006677 if (IDVal == ".dtprelword") {
6678 parseDirectiveDtpRelWord();
6679 return false;
6680 }
6681
6682 if (IDVal == ".dtpreldword") {
6683 parseDirectiveDtpRelDWord();
6684 return false;
6685 }
6686
6687 if (IDVal == ".tprelword") {
6688 parseDirectiveTpRelWord();
6689 return false;
6690 }
6691
6692 if (IDVal == ".tpreldword") {
6693 parseDirectiveTpRelDWord();
6694 return false;
6695 }
6696
Jack Carter07c818d2013-01-25 01:31:34 +00006697 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006698 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006699 return false;
6700 }
6701
Scott Egertond1aeb052016-02-15 16:11:51 +00006702 if (IDVal == ".hword") {
6703 parseDataDirective(2, DirectiveID.getLoc());
6704 return false;
6705 }
6706
Nirav Dave996fc132016-05-05 14:15:46 +00006707 if (IDVal == ".option") {
6708 parseDirectiveOption();
6709 return false;
6710 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006711
6712 if (IDVal == ".abicalls") {
6713 getTargetStreamer().emitDirectiveAbiCalls();
6714 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006715 Error(Parser.getTok().getLoc(),
6716 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006717 }
6718 return false;
6719 }
6720
Nirav Dave996fc132016-05-05 14:15:46 +00006721 if (IDVal == ".cpsetup") {
6722 parseDirectiveCPSetup();
6723 return false;
6724 }
6725 if (IDVal == ".cpreturn") {
6726 parseDirectiveCPReturn();
6727 return false;
6728 }
6729 if (IDVal == ".module") {
6730 parseDirectiveModule();
6731 return false;
6732 }
6733 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6734 parseInternalDirectiveReallowModule();
6735 return false;
6736 }
6737 if (IDVal == ".insn") {
6738 parseInsnDirective();
6739 return false;
6740 }
6741 if (IDVal == ".sbss") {
6742 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6743 return false;
6744 }
6745 if (IDVal == ".sdata") {
6746 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6747 return false;
6748 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006749
Rafael Espindola870c4e92012-01-11 03:56:41 +00006750 return true;
6751}
6752
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006753bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6754 // If this is not the end of the statement, report an error.
6755 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6756 reportParseError("unexpected token, expected end of statement");
6757 return false;
6758 }
6759
6760 getTargetStreamer().reallowModuleDirective();
6761
6762 getParser().Lex(); // Eat EndOfStatement token.
6763 return false;
6764}
6765
Rafael Espindola870c4e92012-01-11 03:56:41 +00006766extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00006767 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
6768 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
6769 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
6770 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00006771}
Jack Carterb4dbc172012-09-05 23:34:03 +00006772
6773#define GET_REGISTER_MATCHER
6774#define GET_MATCHER_IMPLEMENTATION
6775#include "MipsGenAsmMatcher.inc"