blob: 8daba92d3541b77cecb0eff5f3988ad19fc34d18 [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
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000237 bool expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
238 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000239
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000240 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000241 MCStreamer &Out, const MCSubtargetInfo *STI);
242 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
243 const MCSubtargetInfo *STI);
244 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
245 const MCSubtargetInfo *STI);
246 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000248
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000249 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
250 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000251
Simon Dardisaff4d142016-10-18 14:28:00 +0000252 bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
253 const MCSubtargetInfo *STI, bool IsLoad);
254
Simon Dardis43115a12016-11-21 20:30:41 +0000255 bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
256 const MCSubtargetInfo *STI);
257
258 bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
259 const MCSubtargetInfo *STI);
260
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000261 bool reportParseError(Twine ErrorMsg);
262 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000263
Jack Carterb5cf5902013-04-17 00:18:04 +0000264 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000265
266 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000267 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000268 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000269 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000270 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000271 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000272 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000273 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000274 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000275 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000276 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000277 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000278 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000279 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000280
281 bool parseSetAtDirective();
282 bool parseSetNoAtDirective();
283 bool parseSetMacroDirective();
284 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000285 bool parseSetMsaDirective();
286 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000287 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000288 bool parseSetReorderDirective();
289 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000290 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000291 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000292 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000293 bool parseSetOddSPRegDirective();
294 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000295 bool parseSetPopDirective();
296 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000297 bool parseSetSoftFloatDirective();
298 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000299
Jack Carterd76b2372013-03-21 21:44:16 +0000300 bool parseSetAssignment();
301
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000302 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000303 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000304 bool parseDirectiveGpDWord();
Simon Atanasyaneb9ed612016-08-22 16:18:42 +0000305 bool parseDirectiveDtpRelWord();
306 bool parseDirectiveDtpRelDWord();
307 bool parseDirectiveTpRelWord();
308 bool parseDirectiveTpRelDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000309 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000310 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000311 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
312 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000313
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000314 bool parseInternalDirectiveReallowModule();
315
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000316 bool eatComma(StringRef ErrorStr);
317
Jack Carter1ac53222013-02-20 23:11:17 +0000318 int matchCPURegisterName(StringRef Symbol);
319
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000320 int matchHWRegsRegisterName(StringRef Symbol);
321
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000322 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000323
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000324 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000325
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000326 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000327
Jack Carter5dc8ac92013-09-25 23:50:44 +0000328 int matchMSA128RegisterName(StringRef Name);
329
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000330 int matchMSA128CtrlRegisterName(StringRef Name);
331
Jack Carterd0bd6422013-04-18 00:41:53 +0000332 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000333
Toma Tabacu89a712b2015-04-15 10:48:56 +0000334 /// Returns the internal register number for the current AT. Also checks if
335 /// the current AT is unavailable (set to $0) and gives an error if it is.
336 /// This should be used in pseudo-instruction expansions which need AT.
337 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000338
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000339 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
340 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000341
342 // Helper function that checks if the value of a vector index is within the
343 // boundaries of accepted values for each RegisterKind
344 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
345 bool validateMSAIndex(int Val, int RegKind);
346
Daniel Sandersf0df2212014-08-04 12:20:00 +0000347 // Selects a new architecture by updating the FeatureBits with the necessary
348 // info including implied dependencies.
349 // Internally, it clears all the feature bits related to *any* architecture
350 // and selects the new one using the ToggleFeature functionality of the
351 // MCSubtargetInfo object that handles implied dependencies. The reason we
352 // clear all the arch related bits manually is because ToggleFeature only
353 // clears the features that imply the feature being cleared and not the
354 // features implied by the feature being cleared. This is easier to see
355 // with an example:
356 // --------------------------------------------------
357 // | Feature | Implies |
358 // | -------------------------------------------------|
359 // | FeatureMips1 | None |
360 // | FeatureMips2 | FeatureMips1 |
361 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
362 // | FeatureMips4 | FeatureMips3 |
363 // | ... | |
364 // --------------------------------------------------
365 //
366 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
367 // FeatureMipsGP64 | FeatureMips1)
368 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
369 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000370 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000371 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000372 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
373 STI.setFeatureBits(FeatureBits);
374 setAvailableFeatures(
375 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000376 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000377 }
378
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000379 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000380 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000381 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000382 setAvailableFeatures(
383 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000384 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000385 }
386 }
387
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000388 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000389 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000390 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000391 setAvailableFeatures(
392 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000393 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000394 }
395 }
396
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000397 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
398 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000399 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000400 }
401
402 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
403 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000404 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000405 }
406
Rafael Espindola870c4e92012-01-11 03:56:41 +0000407public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000408 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000409 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Simon Dardisb60833c2016-05-31 17:34:42 +0000410 Match_RequiresDifferentOperands,
411 Match_RequiresNoZeroRegister,
Daniel Sandersc5537422016-07-27 13:49:44 +0000412 Match_RequiresSameSrcAndDst,
Simon Dardisc4463c92016-10-18 14:42:13 +0000413 Match_NonZeroOperandForSync,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000414#define GET_OPERAND_DIAGNOSTIC_TYPES
415#include "MipsGenAsmMatcher.inc"
416#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000417 };
418
Akira Hatanakab11ef082015-11-14 06:35:56 +0000419 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000420 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000421 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000422 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
423 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000424 MCAsmParserExtension::Initialize(parser);
425
Toma Tabacu11e14a92015-04-21 11:50:52 +0000426 parser.addAliasForDirective(".asciiz", ".asciz");
427
Jack Carterb4dbc172012-09-05 23:34:03 +0000428 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000429 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000430
Toma Tabacu9db22db2014-09-09 10:15:38 +0000431 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000432 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000433 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000434
Toma Tabacu9db22db2014-09-09 10:15:38 +0000435 // Create an assembler options environment for the user to modify.
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 Sanders5a1449d2014-02-20 14:58:19 +0000438
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000439 getTargetStreamer().updateABIInfo(*this);
440
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000441 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000442 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000443
444 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000445
Rafael Espindola699281c2016-05-18 11:58:50 +0000446 IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
Daniel Sandersa6994442015-08-18 12:33:54 +0000447
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000448 IsCpRestoreSet = false;
449 CpRestoreOffset = -1;
450
Benjamin Kramer4fed9282016-05-27 12:30:51 +0000451 const Triple &TheTriple = sti.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000452 if ((TheTriple.getArch() == Triple::mips) ||
453 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000454 IsLittleEndian = false;
455 else
456 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000457 }
458
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000459 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
460 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
461
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000462 bool isGP64bit() const {
463 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
464 }
465 bool isFP64bit() const {
466 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
467 }
Eric Christophera5762812015-01-26 17:33:46 +0000468 const MipsABIInfo &getABI() const { return ABI; }
469 bool isABI_N32() const { return ABI.IsN32(); }
470 bool isABI_N64() const { return ABI.IsN64(); }
471 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000472 bool isABI_FPXX() const {
473 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
474 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000475
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000476 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000477 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000478 }
479
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000480 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000481 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000482 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000483 bool hasMips1() const {
484 return getSTI().getFeatureBits()[Mips::FeatureMips1];
485 }
486 bool hasMips2() const {
487 return getSTI().getFeatureBits()[Mips::FeatureMips2];
488 }
489 bool hasMips3() const {
490 return getSTI().getFeatureBits()[Mips::FeatureMips3];
491 }
492 bool hasMips4() const {
493 return getSTI().getFeatureBits()[Mips::FeatureMips4];
494 }
495 bool hasMips5() const {
496 return getSTI().getFeatureBits()[Mips::FeatureMips5];
497 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000498 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000500 }
501 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000502 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000503 }
504 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000505 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000506 }
507 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000508 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000509 }
Daniel Sanders17793142015-02-18 16:24:50 +0000510 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000511 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000512 }
513 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000514 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000515 }
516 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000517 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000518 }
519 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000520 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000521 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000522 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000523 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000524 }
525 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000526 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000527 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000528
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000529 bool hasDSP() const {
530 return getSTI().getFeatureBits()[Mips::FeatureDSP];
531 }
532 bool hasDSPR2() const {
533 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
534 }
535 bool hasDSPR3() const {
536 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
537 }
538 bool hasMSA() const {
539 return getSTI().getFeatureBits()[Mips::FeatureMSA];
540 }
Kai Nackee0245392015-01-27 19:11:28 +0000541 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000542 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000543 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000544
Daniel Sandersa6994442015-08-18 12:33:54 +0000545 bool inPicMode() {
546 return IsPicEnabled;
547 }
548
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000549 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000550 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000551 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000552
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000553 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000554 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000555 }
556
Eric Christophere8ae3e32015-05-07 23:10:21 +0000557 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000558 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000559 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000560
Toma Tabacud9d344b2015-04-27 14:05:04 +0000561 /// Warn if RegIndex is the same as the current AT.
562 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000563
564 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000565
566 bool isLittle() const { return IsLittleEndian; }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +0000567
568 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
569 AsmToken::TokenKind OperatorToken,
570 MCContext &Ctx) override {
571 switch(OperatorToken) {
572 default:
573 llvm_unreachable("Unknown token");
574 return nullptr;
575 case AsmToken::PercentCall16:
576 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
577 case AsmToken::PercentCall_Hi:
578 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
579 case AsmToken::PercentCall_Lo:
580 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
581 case AsmToken::PercentDtprel_Hi:
582 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
583 case AsmToken::PercentDtprel_Lo:
584 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
585 case AsmToken::PercentGot:
586 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
587 case AsmToken::PercentGot_Disp:
588 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
589 case AsmToken::PercentGot_Hi:
590 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
591 case AsmToken::PercentGot_Lo:
592 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
593 case AsmToken::PercentGot_Ofst:
594 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
595 case AsmToken::PercentGot_Page:
596 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
597 case AsmToken::PercentGottprel:
598 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
599 case AsmToken::PercentGp_Rel:
600 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
601 case AsmToken::PercentHi:
602 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
603 case AsmToken::PercentHigher:
604 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
605 case AsmToken::PercentHighest:
606 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
607 case AsmToken::PercentLo:
608 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
609 case AsmToken::PercentNeg:
610 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
611 case AsmToken::PercentPcrel_Hi:
612 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
613 case AsmToken::PercentPcrel_Lo:
614 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
615 case AsmToken::PercentTlsgd:
616 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
617 case AsmToken::PercentTlsldm:
618 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
619 case AsmToken::PercentTprel_Hi:
620 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
621 case AsmToken::PercentTprel_Lo:
622 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
623 }
624 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000625};
626}
627
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000628namespace {
629
630/// MipsOperand - Instances of this class represent a parsed Mips machine
631/// instruction.
632class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000633public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000634 /// Broad categories of register classes
635 /// The exact class is finalized by the render method.
636 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000637 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000638 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000639 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000640 RegKind_FCC = 4, /// FCC
641 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
642 RegKind_MSACtrl = 16, /// MSA control registers
643 RegKind_COP2 = 32, /// COP2
644 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
645 /// context).
646 RegKind_CCR = 128, /// CCR
647 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000648 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000649 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000650 /// Potentially any (e.g. $1)
651 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
652 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000653 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000654 };
655
656private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000657 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000658 k_Immediate, /// An immediate (possibly involving symbol references)
659 k_Memory, /// Base + Offset Memory Address
Daniel Sanders21bce302014-04-01 12:35:23 +0000660 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000661 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000662 k_RegList, /// A physical register list
663 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000664 } Kind;
665
David Blaikie960ea3f2014-06-08 16:18:35 +0000666public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000667 MipsOperand(KindTy K, MipsAsmParser &Parser)
668 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
669
David Blaikie960ea3f2014-06-08 16:18:35 +0000670private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000671 /// For diagnostics, and checking the assembler temporary
672 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000673
Eric Christopher8996c5d2013-03-15 00:42:55 +0000674 struct Token {
Daniel Sanders7b361a22016-07-05 10:44:24 +0000675 const char *Data;
676 unsigned Length;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000677 };
678
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000679 struct RegIdxOp {
680 unsigned Index; /// Index into the register class
681 RegKind Kind; /// Bitfield of the kinds it could possibly be
Daniel Sandersc5537422016-07-27 13:49:44 +0000682 struct Token Tok; /// The input token this operand originated from.
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000683 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000684 };
685
686 struct ImmOp {
687 const MCExpr *Val;
688 };
689
690 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000691 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000692 const MCExpr *Off;
693 };
694
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000695 struct RegListOp {
696 SmallVector<unsigned, 10> *List;
697 };
698
Jack Carterb4dbc172012-09-05 23:34:03 +0000699 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000700 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000701 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000702 struct ImmOp Imm;
703 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000704 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000705 };
706
707 SMLoc StartLoc, EndLoc;
708
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000709 /// Internal constructor for register kinds
Daniel Sandersc5537422016-07-27 13:49:44 +0000710 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str,
711 RegKind RegKind,
David Blaikie960ea3f2014-06-08 16:18:35 +0000712 const MCRegisterInfo *RegInfo,
713 SMLoc S, SMLoc E,
714 MipsAsmParser &Parser) {
715 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000716 Op->RegIdx.Index = Index;
717 Op->RegIdx.RegInfo = RegInfo;
718 Op->RegIdx.Kind = RegKind;
Daniel Sandersc5537422016-07-27 13:49:44 +0000719 Op->RegIdx.Tok.Data = Str.data();
720 Op->RegIdx.Tok.Length = Str.size();
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000721 Op->StartLoc = S;
722 Op->EndLoc = E;
723 return Op;
724 }
725
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000726public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000727 /// Coerce the register to GPR32 and return the real register for the current
728 /// target.
729 unsigned getGPR32Reg() const {
730 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000731 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000732 unsigned ClassID = Mips::GPR32RegClassID;
733 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000734 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000735
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000736 /// Coerce the register to GPR32 and return the real register for the current
737 /// target.
738 unsigned getGPRMM16Reg() const {
739 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
740 unsigned ClassID = Mips::GPR32RegClassID;
741 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
742 }
743
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000744 /// Coerce the register to GPR64 and return the real register for the current
745 /// target.
746 unsigned getGPR64Reg() const {
747 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
748 unsigned ClassID = Mips::GPR64RegClassID;
749 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000750 }
751
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000752private:
753 /// Coerce the register to AFGR64 and return the real register for the current
754 /// target.
755 unsigned getAFGR64Reg() const {
756 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
757 if (RegIdx.Index % 2 != 0)
758 AsmParser.Warning(StartLoc, "Float register should be even.");
759 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
760 .getRegister(RegIdx.Index / 2);
761 }
762
763 /// Coerce the register to FGR64 and return the real register for the current
764 /// target.
765 unsigned getFGR64Reg() const {
766 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
767 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
768 .getRegister(RegIdx.Index);
769 }
770
771 /// Coerce the register to FGR32 and return the real register for the current
772 /// target.
773 unsigned getFGR32Reg() const {
774 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
775 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
776 .getRegister(RegIdx.Index);
777 }
778
779 /// Coerce the register to FGRH32 and return the real register for the current
780 /// target.
781 unsigned getFGRH32Reg() const {
782 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
783 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
784 .getRegister(RegIdx.Index);
785 }
786
787 /// Coerce the register to FCC and return the real register for the current
788 /// target.
789 unsigned getFCCReg() const {
790 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
791 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
792 .getRegister(RegIdx.Index);
793 }
794
795 /// Coerce the register to MSA128 and return the real register for the current
796 /// target.
797 unsigned getMSA128Reg() const {
798 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
799 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
800 // identical
801 unsigned ClassID = Mips::MSA128BRegClassID;
802 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
803 }
804
805 /// Coerce the register to MSACtrl and return the real register for the
806 /// current target.
807 unsigned getMSACtrlReg() const {
808 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
809 unsigned ClassID = Mips::MSACtrlRegClassID;
810 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
811 }
812
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000813 /// Coerce the register to COP0 and return the real register for the
814 /// current target.
815 unsigned getCOP0Reg() const {
816 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
817 unsigned ClassID = Mips::COP0RegClassID;
818 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
819 }
820
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000821 /// Coerce the register to COP2 and return the real register for the
822 /// current target.
823 unsigned getCOP2Reg() const {
824 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
825 unsigned ClassID = Mips::COP2RegClassID;
826 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
827 }
828
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000829 /// Coerce the register to COP3 and return the real register for the
830 /// current target.
831 unsigned getCOP3Reg() const {
832 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
833 unsigned ClassID = Mips::COP3RegClassID;
834 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
835 }
836
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000837 /// Coerce the register to ACC64DSP and return the real register for the
838 /// current target.
839 unsigned getACC64DSPReg() const {
840 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
841 unsigned ClassID = Mips::ACC64DSPRegClassID;
842 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
843 }
844
845 /// Coerce the register to HI32DSP and return the real register for the
846 /// current target.
847 unsigned getHI32DSPReg() const {
848 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
849 unsigned ClassID = Mips::HI32DSPRegClassID;
850 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
851 }
852
853 /// Coerce the register to LO32DSP and return the real register for the
854 /// current target.
855 unsigned getLO32DSPReg() const {
856 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
857 unsigned ClassID = Mips::LO32DSPRegClassID;
858 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
859 }
860
861 /// Coerce the register to CCR and return the real register for the
862 /// current target.
863 unsigned getCCRReg() const {
864 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
865 unsigned ClassID = Mips::CCRRegClassID;
866 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
867 }
868
869 /// Coerce the register to HWRegs and return the real register for the
870 /// current target.
871 unsigned getHWRegsReg() const {
872 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
873 unsigned ClassID = Mips::HWRegsRegClassID;
874 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
875 }
876
877public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000878 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000879 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000880 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000881 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000882 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000883 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000884 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000885 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000886 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000887
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000888 void addRegOperands(MCInst &Inst, unsigned N) const {
889 llvm_unreachable("Use a custom parser instead");
890 }
891
Daniel Sanders21bce302014-04-01 12:35:23 +0000892 /// Render the operand to an MCInst as a GPR32
893 /// Asserts if the wrong number of operands are requested, or the operand
894 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000895 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
896 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000897 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000898 }
899
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000900 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
901 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000902 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000903 }
904
Jozef Kolek1904fa22014-11-24 14:25:53 +0000905 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
906 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000907 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000908 }
909
Zoran Jovanovic41688672015-02-10 16:36:20 +0000910 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
911 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000912 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000913 }
914
Daniel Sanders21bce302014-04-01 12:35:23 +0000915 /// Render the operand to an MCInst as a GPR64
916 /// Asserts if the wrong number of operands are requested, or the operand
917 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000918 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
919 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000920 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000921 }
922
923 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
924 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000925 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000926 }
927
928 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
929 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000930 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000931 }
932
933 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
934 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000935 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000936 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Nirav Dave2364748a2016-09-16 18:30:20 +0000937 // FIXME: This should propagate failure up to parseStatement.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000938 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Nirav Dave2364748a2016-09-16 18:30:20 +0000939 AsmParser.getParser().printError(
940 StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
941 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000942 }
943
944 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
945 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000946 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000947 }
948
949 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
950 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000951 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000952 }
953
954 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
955 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000956 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000957 }
958
959 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
960 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000961 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000962 }
963
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000964 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
965 assert(N == 1 && "Invalid number of operands!");
966 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
967 }
968
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000969 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
970 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000971 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000972 }
973
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000974 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
975 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000976 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000977 }
978
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000979 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
980 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000981 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000982 }
983
984 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
985 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000986 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000987 }
988
989 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
990 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000991 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000992 }
993
994 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
995 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000996 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000997 }
998
999 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
1000 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001001 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001002 }
1003
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001004 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +00001005 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
1006 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +00001007 uint64_t Imm = getConstantImm() - Offset;
Simon Dardis299dbd62016-10-05 18:26:19 +00001008 Imm &= (1ULL << Bits) - 1;
Daniel Sandersea4f6532015-11-06 12:22:31 +00001009 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001010 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +00001011 Inst.addOperand(MCOperand::createImm(Imm));
1012 }
1013
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001014 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001015 void addSImmOperands(MCInst &Inst, unsigned N) const {
1016 if (isImm() && !isConstantImm()) {
1017 addExpr(Inst, getImm());
1018 return;
1019 }
1020 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
1021 }
1022
1023 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001024 void addUImmOperands(MCInst &Inst, unsigned N) const {
1025 if (isImm() && !isConstantImm()) {
1026 addExpr(Inst, getImm());
1027 return;
1028 }
1029 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
1030 }
1031
Daniel Sanders78e89022016-03-11 11:37:50 +00001032 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
1033 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
1034 assert(N == 1 && "Invalid number of operands!");
1035 int64_t Imm = getConstantImm() - Offset;
1036 Imm = SignExtend64<Bits>(Imm);
1037 Imm += Offset;
1038 Imm += AdjustOffset;
1039 Inst.addOperand(MCOperand::createImm(Imm));
1040 }
1041
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001042 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +00001043 assert(N == 1 && "Invalid number of operands!");
1044 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001045 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001046 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001047
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001048 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001049 assert(N == 2 && "Invalid number of operands!");
1050
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001051 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
1052 ? getMemBase()->getGPR64Reg()
1053 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001054
1055 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +00001056 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001057 }
1058
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001059 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
1060 assert(N == 2 && "Invalid number of operands!");
1061
Jim Grosbache9119e42015-05-13 18:37:00 +00001062 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001063
1064 const MCExpr *Expr = getMemOff();
1065 addExpr(Inst, Expr);
1066 }
1067
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001068 void addRegListOperands(MCInst &Inst, unsigned N) const {
1069 assert(N == 1 && "Invalid number of operands!");
1070
1071 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001072 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001073 }
1074
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001075 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1076 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001077 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001078 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001079 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1080 Inst.addOperand(MCOperand::createReg(
1081 RegIdx.RegInfo->getRegClass(
1082 AsmParser.getABI().AreGprs64bit()
1083 ? Mips::GPR64RegClassID
1084 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1085 Inst.addOperand(MCOperand::createReg(
1086 RegIdx.RegInfo->getRegClass(
1087 AsmParser.getABI().AreGprs64bit()
1088 ? Mips::GPR64RegClassID
1089 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001090 }
1091
Zoran Jovanovic41688672015-02-10 16:36:20 +00001092 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1093 assert(N == 2 && "Invalid number of operands!");
1094 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001095 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001096 }
1097
Craig Topper56c590a2014-04-29 07:58:02 +00001098 bool isReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001099 // As a special case until we sort out the definition of div/divu, accept
1100 // $0/$zero here so that MCK_ZERO works correctly.
1101 return isGPRAsmReg() && RegIdx.Index == 0;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001102 }
1103 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001104 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001105 bool isConstantImm() const {
Simon Dardis299dbd62016-10-05 18:26:19 +00001106 int64_t Res;
1107 return isImm() && getImm()->evaluateAsAbsolute(Res);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001109 bool isConstantImmz() const {
1110 return isConstantImm() && getConstantImm() == 0;
1111 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001112 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1113 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1114 }
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001115 template <unsigned Bits> bool isSImm() const {
1116 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1117 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001118 template <unsigned Bits> bool isUImm() const {
1119 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1120 }
1121 template <unsigned Bits> bool isAnyImm() const {
1122 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1123 isUInt<Bits>(getConstantImm()))
1124 : isImm();
1125 }
Daniel Sanders78e89022016-03-11 11:37:50 +00001126 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1127 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001128 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001129 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1130 return isConstantImm() && getConstantImm() >= Bottom &&
1131 getConstantImm() <= Top;
1132 }
Craig Topper56c590a2014-04-29 07:58:02 +00001133 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001134 // Note: It's not possible to pretend that other operand kinds are tokens.
1135 // The matcher emitter checks tokens first.
1136 return Kind == k_Token;
1137 }
Craig Topper56c590a2014-04-29 07:58:02 +00001138 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001139 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001140 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001141 }
Simon Dardis4ccda502016-05-27 13:56:36 +00001142 // Allow relocation operators.
1143 // FIXME: This predicate and others need to look through binary expressions
1144 // and determine whether a Value is a constant or not.
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001145 template <unsigned Bits, unsigned ShiftAmount = 0>
1146 bool isMemWithSimmOffset() const {
Zlatko Buljancba9f802016-07-11 07:41:56 +00001147 if (!isMem())
1148 return false;
1149 if (!getMemBase()->isGPRAsmReg())
1150 return false;
1151 if (isa<MCTargetExpr>(getMemOff()) ||
1152 (isConstantMemOff() &&
1153 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
1154 return true;
1155 MCValue Res;
1156 bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
1157 return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001158 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001159 bool isMemWithGRPMM16Base() const {
1160 return isMem() && getMemBase()->isMM16AsmReg();
1161 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001162 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1163 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1164 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1165 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001166 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1167 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1168 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1169 && (getMemBase()->getGPR32Reg() == Mips::SP);
1170 }
Daniel Sanderse473dc92016-05-09 13:38:25 +00001171 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1172 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1173 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1174 && (getMemBase()->getGPR32Reg() == Mips::GP);
1175 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001176 template <unsigned Bits, unsigned ShiftLeftAmount>
1177 bool isScaledUImm() const {
1178 return isConstantImm() &&
1179 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001180 }
Daniel Sanders97297772016-03-22 14:40:00 +00001181 template <unsigned Bits, unsigned ShiftLeftAmount>
1182 bool isScaledSImm() const {
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001183 if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()))
1184 return true;
1185 // Operand can also be a symbol or symbol plus offset in case of relocations.
1186 if (Kind != k_Immediate)
1187 return false;
1188 MCValue Res;
1189 bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr);
1190 return Success && isShiftedInt<Bits, ShiftLeftAmount>(Res.getConstant());
Daniel Sanders97297772016-03-22 14:40:00 +00001191 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001192 bool isRegList16() const {
1193 if (!isRegList())
1194 return false;
1195
1196 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001197 if (Size < 2 || Size > 5)
1198 return false;
1199
1200 unsigned R0 = RegList.List->front();
1201 unsigned R1 = RegList.List->back();
1202 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1203 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001204 return false;
1205
1206 int PrevReg = *RegList.List->begin();
1207 for (int i = 1; i < Size - 1; i++) {
1208 int Reg = (*(RegList.List))[i];
1209 if ( Reg != PrevReg + 1)
1210 return false;
1211 PrevReg = Reg;
1212 }
1213
1214 return true;
1215 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001216 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001217 bool isLSAImm() const {
1218 if (!isConstantImm())
1219 return false;
1220 int64_t Val = getConstantImm();
1221 return 1 <= Val && Val <= 4;
1222 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001223 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001224 bool isMovePRegPair() const {
1225 if (Kind != k_RegList || RegList.List->size() != 2)
1226 return false;
1227
1228 unsigned R0 = RegList.List->front();
1229 unsigned R1 = RegList.List->back();
1230
1231 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1232 (R0 == Mips::A1 && R1 == Mips::A3) ||
1233 (R0 == Mips::A2 && R1 == Mips::A3) ||
1234 (R0 == Mips::A0 && R1 == Mips::S5) ||
1235 (R0 == Mips::A0 && R1 == Mips::S6) ||
1236 (R0 == Mips::A0 && R1 == Mips::A1) ||
1237 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001238 (R0 == Mips::A0 && R1 == Mips::A3) ||
1239 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1240 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1241 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1242 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1243 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1244 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1245 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1246 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001247 return true;
1248
1249 return false;
1250 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001251
1252 StringRef getToken() const {
1253 assert(Kind == k_Token && "Invalid access!");
Daniel Sanders7b361a22016-07-05 10:44:24 +00001254 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001255 }
Zlatko Buljanba553a62016-05-09 08:07:28 +00001256 bool isRegPair() const {
1257 return Kind == k_RegPair && RegIdx.Index <= 30;
1258 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001259
Craig Topper56c590a2014-04-29 07:58:02 +00001260 unsigned getReg() const override {
Daniel Sanders976d9382016-07-05 13:38:40 +00001261 // As a special case until we sort out the definition of div/divu, accept
1262 // $0/$zero here so that MCK_ZERO works correctly.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001263 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1264 RegIdx.Kind & RegKind_GPR)
1265 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001266
Daniel Sanders976d9382016-07-05 13:38:40 +00001267 llvm_unreachable("Invalid access!");
1268 return 0;
Jack Carter873c7242013-01-12 01:03:14 +00001269 }
1270
Jack Carterb4dbc172012-09-05 23:34:03 +00001271 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001272 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001273 return Imm.Val;
1274 }
1275
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001276 int64_t getConstantImm() const {
1277 const MCExpr *Val = getImm();
Simon Dardis299dbd62016-10-05 18:26:19 +00001278 int64_t Value = 0;
1279 (void)Val->evaluateAsAbsolute(Value);
1280 return Value;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001281 }
1282
1283 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001284 assert((Kind == k_Memory) && "Invalid access!");
1285 return Mem.Base;
1286 }
1287
1288 const MCExpr *getMemOff() const {
1289 assert((Kind == k_Memory) && "Invalid access!");
1290 return Mem.Off;
1291 }
1292
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001293 int64_t getConstantMemOff() const {
1294 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1295 }
1296
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001297 const SmallVectorImpl<unsigned> &getRegList() const {
1298 assert((Kind == k_RegList) && "Invalid access!");
1299 return *(RegList.List);
1300 }
1301
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001302 unsigned getRegPair() const {
1303 assert((Kind == k_RegPair) && "Invalid access!");
1304 return RegIdx.Index;
1305 }
1306
David Blaikie960ea3f2014-06-08 16:18:35 +00001307 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1308 MipsAsmParser &Parser) {
1309 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Daniel Sanders7b361a22016-07-05 10:44:24 +00001310 Op->Tok.Data = Str.data();
1311 Op->Tok.Length = Str.size();
Jack Carterb4dbc172012-09-05 23:34:03 +00001312 Op->StartLoc = S;
1313 Op->EndLoc = S;
1314 return Op;
1315 }
1316
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001317 /// Create a numeric register (e.g. $1). The exact register remains
1318 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001319 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001320 createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1321 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001322 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersc5537422016-07-27 13:49:44 +00001323 return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001324 }
1325
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001326 /// Create a register that is definitely a GPR.
1327 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001328 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001329 createGPRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1330 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1331 return CreateReg(Index, Str, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001332 }
1333
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001334 /// Create a register that is definitely a FGR.
1335 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001336 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001337 createFGRReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1338 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1339 return CreateReg(Index, Str, RegKind_FGR, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001340 }
1341
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001342 /// Create a register that is definitely a HWReg.
1343 /// This is typically only used for named registers such as $hwr_cpunum.
1344 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001345 createHWRegsReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001346 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersc5537422016-07-27 13:49:44 +00001347 return CreateReg(Index, Str, RegKind_HWRegs, RegInfo, S, E, Parser);
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001348 }
1349
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001350 /// Create a register that is definitely an FCC.
1351 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001352 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001353 createFCCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1354 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1355 return CreateReg(Index, Str, RegKind_FCC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001356 }
1357
1358 /// Create a register that is definitely an ACC.
1359 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001360 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001361 createACCReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1362 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1363 return CreateReg(Index, Str, RegKind_ACC, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001364 }
1365
1366 /// Create a register that is definitely an MSA128.
1367 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001368 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001369 createMSA128Reg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1370 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1371 return CreateReg(Index, Str, RegKind_MSA128, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001372 }
1373
1374 /// Create a register that is definitely an MSACtrl.
1375 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001376 static std::unique_ptr<MipsOperand>
Daniel Sandersc5537422016-07-27 13:49:44 +00001377 createMSACtrlReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo,
1378 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1379 return CreateReg(Index, Str, RegKind_MSACtrl, RegInfo, S, E, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001380 }
1381
David Blaikie960ea3f2014-06-08 16:18:35 +00001382 static std::unique_ptr<MipsOperand>
1383 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1384 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001385 Op->Imm.Val = Val;
1386 Op->StartLoc = S;
1387 Op->EndLoc = E;
1388 return Op;
1389 }
1390
David Blaikie960ea3f2014-06-08 16:18:35 +00001391 static std::unique_ptr<MipsOperand>
1392 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1393 SMLoc E, MipsAsmParser &Parser) {
1394 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1395 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001396 Op->Mem.Off = Off;
1397 Op->StartLoc = S;
1398 Op->EndLoc = E;
1399 return Op;
1400 }
1401
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001402 static std::unique_ptr<MipsOperand>
1403 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1404 MipsAsmParser &Parser) {
1405 assert (Regs.size() > 0 && "Empty list not allowed");
1406
1407 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001408 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001409 Op->StartLoc = StartLoc;
1410 Op->EndLoc = EndLoc;
1411 return Op;
1412 }
1413
Daniel Sandersd044e492016-05-09 13:10:57 +00001414 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1415 SMLoc S, SMLoc E,
1416 MipsAsmParser &Parser) {
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001417 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001418 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001419 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1420 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001421 Op->StartLoc = S;
1422 Op->EndLoc = E;
1423 return Op;
1424 }
1425
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001426 bool isGPRAsmReg() const {
1427 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001428 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001429 bool isMM16AsmReg() const {
1430 if (!(isRegIdx() && RegIdx.Kind))
1431 return false;
1432 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1433 || RegIdx.Index == 16 || RegIdx.Index == 17);
1434 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001435 bool isMM16AsmRegZero() const {
1436 if (!(isRegIdx() && RegIdx.Kind))
1437 return false;
1438 return (RegIdx.Index == 0 ||
1439 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1440 RegIdx.Index == 17);
1441 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001442 bool isMM16AsmRegMoveP() const {
1443 if (!(isRegIdx() && RegIdx.Kind))
1444 return false;
1445 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1446 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1447 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001448 bool isFGRAsmReg() const {
1449 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1450 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001451 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001452 bool isHWRegsAsmReg() const {
1453 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001454 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001455 bool isCCRAsmReg() const {
1456 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001457 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001458 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001459 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1460 return false;
1461 if (!AsmParser.hasEightFccRegisters())
1462 return RegIdx.Index == 0;
1463 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001464 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001465 bool isACCAsmReg() const {
1466 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001467 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001468 bool isCOP0AsmReg() const {
1469 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1470 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001471 bool isCOP2AsmReg() const {
1472 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001473 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001474 bool isCOP3AsmReg() const {
1475 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1476 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001477 bool isMSA128AsmReg() const {
1478 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001479 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001480 bool isMSACtrlAsmReg() const {
1481 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001482 }
1483
Jack Carterb4dbc172012-09-05 23:34:03 +00001484 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001485 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001486 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +00001487 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001488
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001489 virtual ~MipsOperand() {
1490 switch (Kind) {
1491 case k_Immediate:
1492 break;
1493 case k_Memory:
1494 delete Mem.Base;
1495 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001496 case k_RegList:
1497 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001498 case k_RegisterIndex:
1499 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001500 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001501 break;
1502 }
1503 }
1504
Craig Topper56c590a2014-04-29 07:58:02 +00001505 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001506 switch (Kind) {
1507 case k_Immediate:
1508 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001509 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001510 OS << ">";
1511 break;
1512 case k_Memory:
1513 OS << "Mem<";
1514 Mem.Base->print(OS);
1515 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001516 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001517 OS << ">";
1518 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001519 case k_RegisterIndex:
Daniel Sandersc5537422016-07-27 13:49:44 +00001520 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", "
1521 << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">";
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001522 break;
1523 case k_Token:
Daniel Sandersc5537422016-07-27 13:49:44 +00001524 OS << getToken();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001525 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001526 case k_RegList:
1527 OS << "RegList< ";
1528 for (auto Reg : (*RegList.List))
1529 OS << Reg << " ";
1530 OS << ">";
1531 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001532 case k_RegPair:
1533 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1534 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001535 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001536 }
Daniel Sandersc5537422016-07-27 13:49:44 +00001537
1538 bool isValidForTie(const MipsOperand &Other) const {
1539 if (Kind != Other.Kind)
1540 return false;
1541
1542 switch (Kind) {
1543 default:
1544 llvm_unreachable("Unexpected kind");
1545 return false;
1546 case k_RegisterIndex: {
1547 StringRef Token(RegIdx.Tok.Data, RegIdx.Tok.Length);
1548 StringRef OtherToken(Other.RegIdx.Tok.Data, Other.RegIdx.Tok.Length);
1549 return Token == OtherToken;
1550 }
1551 }
1552 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001553}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001554} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001555
Jack Carter9e65aa32013-03-22 00:05:30 +00001556namespace llvm {
1557extern const MCInstrDesc MipsInsts[];
1558}
1559static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1560 return MipsInsts[Opcode];
1561}
1562
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001563static bool hasShortDelaySlot(unsigned Opcode) {
1564 switch (Opcode) {
1565 case Mips::JALS_MM:
1566 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001567 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001568 case Mips::BGEZALS_MM:
1569 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001570 return true;
1571 default:
1572 return false;
1573 }
1574}
1575
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001576static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1577 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1578 return &SRExpr->getSymbol();
1579 }
1580
1581 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1582 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1583 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1584
1585 if (LHSSym)
1586 return LHSSym;
1587
1588 if (RHSSym)
1589 return RHSSym;
1590
1591 return nullptr;
1592 }
1593
1594 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1595 return getSingleMCSymbol(UExpr->getSubExpr());
1596
1597 return nullptr;
1598}
1599
1600static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1601 if (isa<MCSymbolRefExpr>(Expr))
1602 return 1;
1603
1604 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1605 return countMCSymbolRefExpr(BExpr->getLHS()) +
1606 countMCSymbolRefExpr(BExpr->getRHS());
1607
1608 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1609 return countMCSymbolRefExpr(UExpr->getSubExpr());
1610
1611 return 0;
1612}
1613
Jack Carter9e65aa32013-03-22 00:05:30 +00001614bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001615 MCStreamer &Out,
1616 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001617 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001618 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001619 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001620
Jack Carter9e65aa32013-03-22 00:05:30 +00001621 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001622
1623 if (MCID.isBranch() || MCID.isCall()) {
1624 const unsigned Opcode = Inst.getOpcode();
1625 MCOperand Offset;
1626
1627 switch (Opcode) {
1628 default:
1629 break;
Kai Nackee0245392015-01-27 19:11:28 +00001630 case Mips::BBIT0:
1631 case Mips::BBIT032:
1632 case Mips::BBIT1:
1633 case Mips::BBIT132:
1634 assert(hasCnMips() && "instruction only valid for octeon cpus");
Justin Bognercd1d5aa2016-08-17 20:30:52 +00001635 LLVM_FALLTHROUGH;
Kai Nackee0245392015-01-27 19:11:28 +00001636
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001637 case Mips::BEQ:
1638 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001639 case Mips::BEQ_MM:
1640 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001641 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001642 Offset = Inst.getOperand(2);
1643 if (!Offset.isImm())
1644 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001645 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001646 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001647 if (OffsetToAlignment(Offset.getImm(),
1648 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001649 return Error(IDLoc, "branch to misaligned address");
1650 break;
1651 case Mips::BGEZ:
1652 case Mips::BGTZ:
1653 case Mips::BLEZ:
1654 case Mips::BLTZ:
1655 case Mips::BGEZAL:
1656 case Mips::BLTZAL:
1657 case Mips::BC1F:
1658 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001659 case Mips::BGEZ_MM:
1660 case Mips::BGTZ_MM:
1661 case Mips::BLEZ_MM:
1662 case Mips::BLTZ_MM:
1663 case Mips::BGEZAL_MM:
1664 case Mips::BLTZAL_MM:
1665 case Mips::BC1F_MM:
1666 case Mips::BC1T_MM:
Zlatko Buljane663e342016-05-19 07:31:28 +00001667 case Mips::BC1EQZC_MMR6:
1668 case Mips::BC1NEZC_MMR6:
1669 case Mips::BC2EQZC_MMR6:
1670 case Mips::BC2NEZC_MMR6:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001671 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001672 Offset = Inst.getOperand(1);
1673 if (!Offset.isImm())
1674 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001675 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001676 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001677 if (OffsetToAlignment(Offset.getImm(),
1678 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001679 return Error(IDLoc, "branch to misaligned address");
1680 break;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00001681 case Mips::BGEC: case Mips::BGEC_MMR6:
1682 case Mips::BLTC: case Mips::BLTC_MMR6:
1683 case Mips::BGEUC: case Mips::BGEUC_MMR6:
1684 case Mips::BLTUC: case Mips::BLTUC_MMR6:
1685 case Mips::BEQC: case Mips::BEQC_MMR6:
1686 case Mips::BNEC: case Mips::BNEC_MMR6:
1687 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1688 Offset = Inst.getOperand(2);
1689 if (!Offset.isImm())
1690 break; // We'll deal with this situation later on when applying fixups.
1691 if (!isIntN(18, Offset.getImm()))
1692 return Error(IDLoc, "branch target out of range");
1693 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1694 return Error(IDLoc, "branch to misaligned address");
1695 break;
1696 case Mips::BLEZC: case Mips::BLEZC_MMR6:
1697 case Mips::BGEZC: case Mips::BGEZC_MMR6:
1698 case Mips::BGTZC: case Mips::BGTZC_MMR6:
1699 case Mips::BLTZC: case Mips::BLTZC_MMR6:
1700 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1701 Offset = Inst.getOperand(1);
1702 if (!Offset.isImm())
1703 break; // We'll deal with this situation later on when applying fixups.
1704 if (!isIntN(18, Offset.getImm()))
1705 return Error(IDLoc, "branch target out of range");
1706 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1707 return Error(IDLoc, "branch to misaligned address");
1708 break;
1709 case Mips::BEQZC: case Mips::BEQZC_MMR6:
1710 case Mips::BNEZC: case Mips::BNEZC_MMR6:
1711 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1712 Offset = Inst.getOperand(1);
1713 if (!Offset.isImm())
1714 break; // We'll deal with this situation later on when applying fixups.
1715 if (!isIntN(23, Offset.getImm()))
1716 return Error(IDLoc, "branch target out of range");
1717 if (OffsetToAlignment(Offset.getImm(), 1LL << 2))
1718 return Error(IDLoc, "branch to misaligned address");
1719 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001720 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001721 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001722 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001723 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001724 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1725 Offset = Inst.getOperand(1);
1726 if (!Offset.isImm())
1727 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001728 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001729 return Error(IDLoc, "branch target out of range");
1730 if (OffsetToAlignment(Offset.getImm(), 2LL))
1731 return Error(IDLoc, "branch to misaligned address");
1732 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001733 }
1734 }
1735
Daniel Sandersa84989a2014-06-16 13:25:35 +00001736 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1737 // We still accept it but it is a normal nop.
1738 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1739 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1740 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1741 "nop instruction");
1742 }
1743
Kai Nackee0245392015-01-27 19:11:28 +00001744 if (hasCnMips()) {
1745 const unsigned Opcode = Inst.getOpcode();
1746 MCOperand Opnd;
1747 int Imm;
1748
1749 switch (Opcode) {
1750 default:
1751 break;
1752
1753 case Mips::BBIT0:
1754 case Mips::BBIT032:
1755 case Mips::BBIT1:
1756 case Mips::BBIT132:
1757 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1758 // The offset is handled above
1759 Opnd = Inst.getOperand(1);
1760 if (!Opnd.isImm())
1761 return Error(IDLoc, "expected immediate operand kind");
1762 Imm = Opnd.getImm();
1763 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1764 Opcode == Mips::BBIT1 ? 63 : 31))
1765 return Error(IDLoc, "immediate operand value out of range");
1766 if (Imm > 31) {
1767 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1768 : Mips::BBIT132);
1769 Inst.getOperand(1).setImm(Imm - 32);
1770 }
1771 break;
1772
Kai Nackee0245392015-01-27 19:11:28 +00001773 case Mips::SEQi:
1774 case Mips::SNEi:
1775 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1776 Opnd = Inst.getOperand(2);
1777 if (!Opnd.isImm())
1778 return Error(IDLoc, "expected immediate operand kind");
1779 Imm = Opnd.getImm();
1780 if (!isInt<10>(Imm))
1781 return Error(IDLoc, "immediate operand value out of range");
1782 break;
1783 }
1784 }
1785
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001786 // This expansion is not in a function called by tryExpandInstruction()
1787 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001788 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1789 inPicMode()) {
1790 warnIfNoMacro(IDLoc);
1791
1792 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1793
1794 // We can do this expansion if there's only 1 symbol in the argument
1795 // expression.
1796 if (countMCSymbolRefExpr(JalExpr) > 1)
1797 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1798
1799 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001800 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001801 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1802
1803 // FIXME: Add support for label+offset operands (currently causes an error).
1804 // FIXME: Add support for forward-declared local symbols.
1805 // FIXME: Add expansion for when the LargeGOT option is enabled.
1806 if (JalSym->isInSection() || JalSym->isTemporary()) {
1807 if (isABI_O32()) {
1808 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001809 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001810 // R_(MICRO)MIPS_GOT16 label
1811 // addiu $25, $25, 0
1812 // R_(MICRO)MIPS_LO16 label
1813 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001814 const MCExpr *Got16RelocExpr =
1815 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1816 const MCExpr *Lo16RelocExpr =
1817 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001818
Daniel Sandersa736b372016-04-29 13:33:12 +00001819 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1820 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1821 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1822 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001823 } else if (isABI_N32() || isABI_N64()) {
1824 // If it's a local symbol and the N32/N64 ABIs are being used,
1825 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001826 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001827 // R_(MICRO)MIPS_GOT_DISP label
1828 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001829 const MCExpr *GotDispRelocExpr =
1830 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001831
Daniel Sandersa736b372016-04-29 13:33:12 +00001832 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1833 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1834 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001835 }
1836 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001837 // If it's an external/weak symbol, we expand to:
1838 // lw/ld $25, 0($gp)
1839 // R_(MICRO)MIPS_CALL16 label
1840 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001841 const MCExpr *Call16RelocExpr =
1842 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001843
Daniel Sandersa736b372016-04-29 13:33:12 +00001844 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1845 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001846 }
1847
1848 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001849 if (IsCpRestoreSet && inMicroMipsMode())
1850 JalrInst.setOpcode(Mips::JALRS_MM);
1851 else
1852 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001853 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1854 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1855
1856 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1857 // This relocation is supposed to be an optimization hint for the linker
1858 // and is not necessary for correctness.
1859
1860 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001861 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001862 }
1863
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00001864 bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0;
1865 if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001866 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001867 // reference or immediate we may have to expand instructions.
1868 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001869 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001870 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1871 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001872 MCOperand &Op = Inst.getOperand(i);
1873 if (Op.isImm()) {
1874 int MemOffset = Op.getImm();
1875 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001876 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001877 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Nirav Dave2364748a2016-09-16 18:30:20 +00001878 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001879 }
1880 } else if (Op.isExpr()) {
1881 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001882 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001883 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001884 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001885 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001886 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001887 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00001888 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001889 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001890 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001891 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Nirav Dave2364748a2016-09-16 18:30:20 +00001892 return getParser().hasPendingError();
Jack Carter9e65aa32013-03-22 00:05:30 +00001893 }
1894 }
1895 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001896 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001897 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001898
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001899 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001900 if (MCID.mayLoad()) {
1901 // Try to create 16-bit GP relative load instruction.
1902 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1903 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1904 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1905 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1906 MCOperand &Op = Inst.getOperand(i);
1907 if (Op.isImm()) {
1908 int MemOffset = Op.getImm();
1909 MCOperand &DstReg = Inst.getOperand(0);
1910 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001911 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001912 getContext().getRegisterInfo()->getRegClass(
1913 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001914 (BaseReg.getReg() == Mips::GP ||
1915 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001916
Daniel Sandersa736b372016-04-29 13:33:12 +00001917 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1918 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001919 return false;
1920 }
1921 }
1922 }
1923 } // for
1924 } // if load
1925
1926 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1927
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001928 MCOperand Opnd;
1929 int Imm;
1930
1931 switch (Inst.getOpcode()) {
1932 default:
1933 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001934 case Mips::ADDIUSP_MM:
1935 Opnd = Inst.getOperand(0);
1936 if (!Opnd.isImm())
1937 return Error(IDLoc, "expected immediate operand kind");
1938 Imm = Opnd.getImm();
1939 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1940 Imm % 4 != 0)
1941 return Error(IDLoc, "immediate operand value out of range");
1942 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001943 case Mips::SLL16_MM:
1944 case Mips::SRL16_MM:
1945 Opnd = Inst.getOperand(2);
1946 if (!Opnd.isImm())
1947 return Error(IDLoc, "expected immediate operand kind");
1948 Imm = Opnd.getImm();
1949 if (Imm < 1 || Imm > 8)
1950 return Error(IDLoc, "immediate operand value out of range");
1951 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001952 case Mips::LI16_MM:
1953 Opnd = Inst.getOperand(1);
1954 if (!Opnd.isImm())
1955 return Error(IDLoc, "expected immediate operand kind");
1956 Imm = Opnd.getImm();
1957 if (Imm < -1 || Imm > 126)
1958 return Error(IDLoc, "immediate operand value out of range");
1959 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001960 case Mips::ADDIUR2_MM:
1961 Opnd = Inst.getOperand(2);
1962 if (!Opnd.isImm())
1963 return Error(IDLoc, "expected immediate operand kind");
1964 Imm = Opnd.getImm();
1965 if (!(Imm == 1 || Imm == -1 ||
1966 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1967 return Error(IDLoc, "immediate operand value out of range");
1968 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001969 case Mips::ANDI16_MM:
1970 Opnd = Inst.getOperand(2);
1971 if (!Opnd.isImm())
1972 return Error(IDLoc, "expected immediate operand kind");
1973 Imm = Opnd.getImm();
1974 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1975 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1976 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1977 return Error(IDLoc, "immediate operand value out of range");
1978 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001979 case Mips::LBU16_MM:
1980 Opnd = Inst.getOperand(2);
1981 if (!Opnd.isImm())
1982 return Error(IDLoc, "expected immediate operand kind");
1983 Imm = Opnd.getImm();
1984 if (Imm < -1 || Imm > 14)
1985 return Error(IDLoc, "immediate operand value out of range");
1986 break;
1987 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001988 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001989 Opnd = Inst.getOperand(2);
1990 if (!Opnd.isImm())
1991 return Error(IDLoc, "expected immediate operand kind");
1992 Imm = Opnd.getImm();
1993 if (Imm < 0 || Imm > 15)
1994 return Error(IDLoc, "immediate operand value out of range");
1995 break;
1996 case Mips::LHU16_MM:
1997 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001998 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001999 Opnd = Inst.getOperand(2);
2000 if (!Opnd.isImm())
2001 return Error(IDLoc, "expected immediate operand kind");
2002 Imm = Opnd.getImm();
2003 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
2004 return Error(IDLoc, "immediate operand value out of range");
2005 break;
2006 case Mips::LW16_MM:
2007 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002008 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00002009 Opnd = Inst.getOperand(2);
2010 if (!Opnd.isImm())
2011 return Error(IDLoc, "expected immediate operand kind");
2012 Imm = Opnd.getImm();
2013 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
2014 return Error(IDLoc, "immediate operand value out of range");
2015 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002016 case Mips::ADDIUPC_MM:
2017 MCOperand Opnd = Inst.getOperand(1);
2018 if (!Opnd.isImm())
2019 return Error(IDLoc, "expected immediate operand kind");
2020 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00002021 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00002022 return Error(IDLoc, "immediate operand value out of range");
2023 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00002024 }
2025 }
2026
Daniel Sandersd8c07762016-04-18 12:35:36 +00002027 bool FillDelaySlot =
2028 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2029 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00002030 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002031
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002032 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002033 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002034 switch (ExpandResult) {
2035 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002036 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002037 break;
2038 case MER_Success:
2039 break;
2040 case MER_Fail:
2041 return true;
2042 }
Jack Carter9e65aa32013-03-22 00:05:30 +00002043
Daniel Sanderscda908a2016-05-16 09:10:13 +00002044 // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
2045 // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
2046 if (inMicroMipsMode())
2047 TOut.setUsesMicroMips();
2048
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002049 // If this instruction has a delay slot and .set reorder is active,
2050 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00002051 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002052 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
2053 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00002054 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00002055
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002056 if ((Inst.getOpcode() == Mips::JalOneReg ||
2057 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
2058 isPicAndNotNxxAbi()) {
2059 if (IsCpRestoreSet) {
2060 // We need a NOP between the JALR and the LW:
2061 // If .set reorder has been used, we've already emitted a NOP.
2062 // If .set noreorder has been used, we need to emit a NOP at this point.
2063 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002064 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
2065 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002066
2067 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00002068 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002069 } else
2070 Warning(IDLoc, "no .cprestore used in PIC mode");
2071 }
2072
Jack Carter9e65aa32013-03-22 00:05:30 +00002073 return false;
2074}
2075
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002076MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002077MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2078 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002079 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002080 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002081 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002082 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002083 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002084 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002085 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002086 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002087 case Mips::LoadAddrImm64:
2088 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2089 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
2090 "expected immediate operand kind");
2091
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002092 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
2093 Inst.getOperand(1),
2094 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002095 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002096 ? MER_Fail
2097 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00002098 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002099 case Mips::LoadAddrReg64:
2100 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2101 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2102 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
2103 "expected immediate operand kind");
2104
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002105 return expandLoadAddress(Inst.getOperand(0).getReg(),
2106 Inst.getOperand(1).getReg(), Inst.getOperand(2),
2107 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002108 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002109 ? MER_Fail
2110 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002111 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00002112 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002113 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
2114 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002115 case Mips::SWM_MM:
2116 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002117 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
2118 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002119 case Mips::JalOneReg:
2120 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002121 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00002122 case Mips::BneImm:
2123 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002124 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00002125 case Mips::BLT:
2126 case Mips::BLE:
2127 case Mips::BGE:
2128 case Mips::BGT:
2129 case Mips::BLTU:
2130 case Mips::BLEU:
2131 case Mips::BGEU:
2132 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002133 case Mips::BLTL:
2134 case Mips::BLEL:
2135 case Mips::BGEL:
2136 case Mips::BGTL:
2137 case Mips::BLTUL:
2138 case Mips::BLEUL:
2139 case Mips::BGEUL:
2140 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002141 case Mips::BLTImmMacro:
2142 case Mips::BLEImmMacro:
2143 case Mips::BGEImmMacro:
2144 case Mips::BGTImmMacro:
2145 case Mips::BLTUImmMacro:
2146 case Mips::BLEUImmMacro:
2147 case Mips::BGEUImmMacro:
2148 case Mips::BGTUImmMacro:
2149 case Mips::BLTLImmMacro:
2150 case Mips::BLELImmMacro:
2151 case Mips::BGELImmMacro:
2152 case Mips::BGTLImmMacro:
2153 case Mips::BLTULImmMacro:
2154 case Mips::BLEULImmMacro:
2155 case Mips::BGEULImmMacro:
2156 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002157 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002158 case Mips::SDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002159 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2160 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002161 case Mips::DSDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002162 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2163 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002164 case Mips::UDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002165 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2166 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002167 case Mips::DUDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002168 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2169 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002170 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002171 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2172 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002173 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002174 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002175 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002176 case Mips::PseudoTRUNC_W_D:
2177 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2178 : MER_Success;
2179 case Mips::Ulh:
2180 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2181 case Mips::Ulhu:
2182 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2183 case Mips::Ulw:
2184 return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2185 case Mips::NORImm:
2186 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002187 case Mips::ADDi:
2188 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002189 case Mips::SLTi:
2190 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002191 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2192 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2193 int64_t ImmValue = Inst.getOperand(2).getImm();
2194 if (isInt<16>(ImmValue))
2195 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002196 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2197 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002198 }
2199 return MER_NotAMacro;
2200 case Mips::ANDi:
2201 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002202 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002203 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2204 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2205 int64_t ImmValue = Inst.getOperand(2).getImm();
2206 if (isUInt<16>(ImmValue))
2207 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002208 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2209 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002210 }
2211 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002212 case Mips::ROL:
2213 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002214 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002215 case Mips::ROLImm:
2216 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002217 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002218 case Mips::DROL:
2219 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002220 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002221 case Mips::DROLImm:
2222 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002223 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002224 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002225 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Simon Dardisaff4d142016-10-18 14:28:00 +00002226 case Mips::LDMacro:
2227 case Mips::SDMacro:
2228 return expandLoadStoreDMacro(Inst, IDLoc, Out, STI,
2229 Inst.getOpcode() == Mips::LDMacro)
2230 ? MER_Fail
2231 : MER_Success;
Simon Dardis43115a12016-11-21 20:30:41 +00002232 case Mips::SEQMacro:
2233 return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2234 case Mips::SEQIMacro:
2235 return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002236 }
Jack Carter30a59822012-10-04 04:03:53 +00002237}
Jack Carter92995f12012-10-06 00:53:28 +00002238
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002239bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002240 MCStreamer &Out,
2241 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002242 MipsTargetStreamer &TOut = getTargetStreamer();
2243
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002244 // Create a JALR instruction which is going to replace the pseudo-JAL.
2245 MCInst JalrInst;
2246 JalrInst.setLoc(IDLoc);
2247 const MCOperand FirstRegOp = Inst.getOperand(0);
2248 const unsigned Opcode = Inst.getOpcode();
2249
2250 if (Opcode == Mips::JalOneReg) {
2251 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002252 if (IsCpRestoreSet && inMicroMipsMode()) {
2253 JalrInst.setOpcode(Mips::JALRS16_MM);
2254 JalrInst.addOperand(FirstRegOp);
2255 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002256 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002257 JalrInst.addOperand(FirstRegOp);
2258 } else {
2259 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002260 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002261 JalrInst.addOperand(FirstRegOp);
2262 }
2263 } else if (Opcode == Mips::JalTwoReg) {
2264 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002265 if (IsCpRestoreSet && inMicroMipsMode())
2266 JalrInst.setOpcode(Mips::JALRS_MM);
2267 else
2268 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002269 JalrInst.addOperand(FirstRegOp);
2270 const MCOperand SecondRegOp = Inst.getOperand(1);
2271 JalrInst.addOperand(SecondRegOp);
2272 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002273 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002274
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002275 // If .set reorder is active and branch instruction has a delay slot,
2276 // emit a NOP after it.
2277 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002278 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2279 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2280 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002281
2282 return false;
2283}
2284
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002285/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002286template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002287 unsigned BitNum = findFirstSet(x);
2288
2289 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2290}
2291
2292/// Load (or add) an immediate into a register.
2293///
2294/// @param ImmValue The immediate to load.
2295/// @param DstReg The register that will hold the immediate.
2296/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2297/// for a simple initialization.
2298/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2299/// @param IsAddress True if the immediate represents an address. False if it
2300/// is an integer.
2301/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002302bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002303 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002304 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2305 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002306 MipsTargetStreamer &TOut = getTargetStreamer();
2307
Toma Tabacu00e98672015-05-01 12:19:27 +00002308 if (!Is32BitImm && !isGP64bit()) {
2309 Error(IDLoc, "instruction requires a 64-bit architecture");
2310 return true;
2311 }
2312
Daniel Sanders03f9c012015-07-14 12:24:22 +00002313 if (Is32BitImm) {
2314 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2315 // Sign extend up to 64-bit so that the predicates match the hardware
2316 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2317 // true.
2318 ImmValue = SignExtend64<32>(ImmValue);
2319 } else {
2320 Error(IDLoc, "instruction requires a 32-bit immediate");
2321 return true;
2322 }
2323 }
2324
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002325 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2326 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2327
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002328 bool UseSrcReg = false;
2329 if (SrcReg != Mips::NoRegister)
2330 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002331
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002332 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002333 if (UseSrcReg &&
2334 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002335 // At this point we need AT to perform the expansions and we exit if it is
2336 // not available.
2337 unsigned ATReg = getATReg(IDLoc);
2338 if (!ATReg)
2339 return true;
2340 TmpReg = ATReg;
2341 }
2342
Daniel Sanders03f9c012015-07-14 12:24:22 +00002343 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002344 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002345 SrcReg = ZeroReg;
2346
2347 // This doesn't quite follow the usual ABI expectations for N32 but matches
2348 // traditional assembler behaviour. N32 would normally use addiu for both
2349 // integers and addresses.
2350 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002351 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002352 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002353 }
2354
Daniel Sandersa736b372016-04-29 13:33:12 +00002355 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002356 return false;
2357 }
2358
2359 if (isUInt<16>(ImmValue)) {
2360 unsigned TmpReg = DstReg;
2361 if (SrcReg == DstReg) {
2362 TmpReg = getATReg(IDLoc);
2363 if (!TmpReg)
2364 return true;
2365 }
2366
Daniel Sandersa736b372016-04-29 13:33:12 +00002367 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002368 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002369 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002370 return false;
2371 }
2372
2373 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002374 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002375
Toma Tabacu79588102015-04-29 10:19:56 +00002376 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2377 uint16_t Bits15To0 = ImmValue & 0xffff;
2378
Toma Tabacua3d056f2015-05-15 09:42:11 +00002379 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002380 // Traditional behaviour seems to special case this particular value. It's
2381 // not clear why other masks are handled differently.
2382 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002383 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2384 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002385 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002386 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002387 return false;
2388 }
2389
2390 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002391 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002392 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2393 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002394 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002395 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002396 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002397 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002398 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002399 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002400
Daniel Sandersa736b372016-04-29 13:33:12 +00002401 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002402 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002403 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002404 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002405 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002406 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002407 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002408
2409 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2410 if (Is32BitImm) {
2411 Error(IDLoc, "instruction requires a 32-bit immediate");
2412 return true;
2413 }
2414
2415 // Traditionally, these immediates are shifted as little as possible and as
2416 // such we align the most significant bit to bit 15 of our temporary.
2417 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2418 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2419 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2420 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002421 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2422 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002423
2424 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002425 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002426
2427 return false;
2428 }
2429
2430 warnIfNoMacro(IDLoc);
2431
2432 // The remaining case is packed with a sequence of dsll and ori with zeros
2433 // being omitted and any neighbouring dsll's being coalesced.
2434 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2435
2436 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2437 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002438 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002439 return false;
2440
2441 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2442 // skip it and defer the shift to the next chunk.
2443 unsigned ShiftCarriedForwards = 16;
2444 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2445 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2446
2447 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002448 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2449 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002450 ShiftCarriedForwards = 0;
2451 }
2452
2453 ShiftCarriedForwards += 16;
2454 }
2455 ShiftCarriedForwards -= 16;
2456
2457 // Finish any remaining shifts left by trailing zeros.
2458 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002459 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002460
2461 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002462 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002463
Matheus Almeida3813d572014-06-19 14:39:14 +00002464 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002465}
Jack Carter92995f12012-10-06 00:53:28 +00002466
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002467bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002468 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002469 const MCOperand &ImmOp = Inst.getOperand(1);
2470 assert(ImmOp.isImm() && "expected immediate operand kind");
2471 const MCOperand &DstRegOp = Inst.getOperand(0);
2472 assert(DstRegOp.isReg() && "expected register operand kind");
2473
2474 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002475 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002476 return true;
2477
2478 return false;
2479}
2480
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002481bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2482 const MCOperand &Offset,
2483 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002484 MCStreamer &Out,
2485 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002486 // la can't produce a usable address when addresses are 64-bit.
2487 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2488 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2489 // We currently can't do this because we depend on the equality
2490 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2491 Error(IDLoc, "la used to load 64-bit address");
2492 // Continue as if we had 'dla' instead.
2493 Is32BitAddress = false;
Nirav Dave2364748a2016-09-16 18:30:20 +00002494 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002495 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002496
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002497 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002498 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002499 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002500 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002501 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002502
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002503 if (!Offset.isImm())
2504 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002505 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002506
Scott Egerton24557012016-01-21 15:11:01 +00002507 if (!ABI.ArePtrs64bit()) {
2508 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2509 Is32BitAddress = true;
2510 }
2511
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002512 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002513 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002514}
2515
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002516bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2517 unsigned DstReg, unsigned SrcReg,
2518 bool Is32BitSym, SMLoc IDLoc,
2519 MCStreamer &Out,
2520 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002521 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002522 bool UseSrcReg = SrcReg != Mips::NoRegister;
Toma Tabacu81496c12015-05-20 08:54:45 +00002523 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002524
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002525 if (inPicMode() && ABI.IsO32()) {
2526 MCValue Res;
2527 if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
2528 Error(IDLoc, "expected relocatable expression");
2529 return true;
2530 }
2531 if (Res.getSymB() != nullptr) {
2532 Error(IDLoc, "expected relocatable expression with only one symbol");
2533 return true;
2534 }
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002535
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002536 // The case where the result register is $25 is somewhat special. If the
2537 // symbol in the final relocation is external and not modified with a
2538 // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2539 if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2540 Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
2541 !Res.getSymA()->getSymbol().isTemporary()) {
2542 const MCExpr *CallExpr =
2543 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
2544 TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
2545 MCOperand::createExpr(CallExpr), IDLoc, STI);
2546 return false;
2547 }
2548
2549 // The remaining cases are:
2550 // External GOT: lw $tmp, %got(symbol+offset)($gp)
2551 // >addiu $tmp, $tmp, %lo(offset)
2552 // >addiu $rd, $tmp, $rs
2553 // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2554 // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2555 // >addiu $rd, $tmp, $rs
2556 // The addiu's marked with a '>' may be omitted if they are redundant. If
2557 // this happens then the last instruction must use $rd as the result
2558 // register.
2559 const MipsMCExpr *GotExpr =
2560 MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
2561 const MCExpr *LoExpr = nullptr;
2562 if (Res.getSymA()->getSymbol().isInSection() ||
2563 Res.getSymA()->getSymbol().isTemporary())
2564 LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
2565 else if (Res.getConstant() != 0) {
2566 // External symbols fully resolve the symbol with just the %got(symbol)
2567 // but we must still account for any offset to the symbol for expressions
2568 // like symbol+8.
2569 LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
2570 }
2571
2572 unsigned TmpReg = DstReg;
2573 if (UseSrcReg &&
2574 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2575 SrcReg)) {
2576 // If $rs is the same as $rd, we need to use AT.
2577 // If it is not available we exit.
2578 unsigned ATReg = getATReg(IDLoc);
2579 if (!ATReg)
2580 return true;
2581 TmpReg = ATReg;
2582 }
2583
2584 TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
2585 MCOperand::createExpr(GotExpr), IDLoc, STI);
2586
2587 if (LoExpr)
2588 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2589 IDLoc, STI);
2590
2591 if (UseSrcReg)
2592 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2593
2594 return false;
2595 }
2596
2597 const MipsMCExpr *HiExpr =
2598 MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
2599 const MipsMCExpr *LoExpr =
2600 MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
Toma Tabacufb9d1252015-06-22 12:08:39 +00002601
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002602 // This is the 64-bit symbol address expansion.
2603 if (ABI.ArePtrs64bit() && isGP64bit()) {
2604 // We always need AT for the 64-bit expansion.
2605 // If it is not available we exit.
2606 unsigned ATReg = getATReg(IDLoc);
2607 if (!ATReg)
2608 return true;
2609
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002610 const MipsMCExpr *HighestExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002611 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002612 const MipsMCExpr *HigherExpr =
Daniel Sanders6ba3dd62016-06-03 09:53:06 +00002613 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002614
Scott Egerton24557012016-01-21 15:11:01 +00002615 if (UseSrcReg &&
2616 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2617 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002618 // If $rs is the same as $rd:
2619 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2620 // daddiu $at, $at, %higher(sym)
2621 // dsll $at, $at, 16
2622 // daddiu $at, $at, %hi(sym)
2623 // dsll $at, $at, 16
2624 // daddiu $at, $at, %lo(sym)
2625 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002626 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2627 STI);
2628 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2629 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2630 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2631 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2632 IDLoc, STI);
2633 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2634 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2635 IDLoc, STI);
2636 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002637
2638 return false;
2639 }
2640
2641 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2642 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2643 // lui $at, %hi(sym)
2644 // daddiu $rd, $rd, %higher(sym)
2645 // daddiu $at, $at, %lo(sym)
2646 // dsll32 $rd, $rd, 0
2647 // daddu $rd, $rd, $at
2648 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002649 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2650 STI);
2651 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2652 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2653 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2654 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2655 IDLoc, STI);
2656 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2657 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002658 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002659 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002660
2661 return false;
2662 }
2663
2664 // And now, the 32-bit symbol address expansion:
2665 // If $rs is the same as $rd:
2666 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2667 // ori $at, $at, %lo(sym)
2668 // addu $rd, $at, $rd
2669 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2670 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2671 // ori $rd, $rd, %lo(sym)
2672 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002673 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002674 if (UseSrcReg &&
2675 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002676 // If $rs is the same as $rd, we need to use AT.
2677 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002678 unsigned ATReg = getATReg(IDLoc);
2679 if (!ATReg)
2680 return true;
2681 TmpReg = ATReg;
2682 }
2683
Daniel Sandersa736b372016-04-29 13:33:12 +00002684 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2685 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2686 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002687
Toma Tabacufb9d1252015-06-22 12:08:39 +00002688 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002689 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002690 else
Scott Egerton24557012016-01-21 15:11:01 +00002691 assert(
2692 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002693
Toma Tabacu674825c2015-06-16 12:16:24 +00002694 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002695}
2696
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002697bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2698 MCStreamer &Out,
2699 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002700 MipsTargetStreamer &TOut = getTargetStreamer();
2701
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002702 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2703 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002704
2705 MCOperand Offset = Inst.getOperand(0);
2706 if (Offset.isExpr()) {
2707 Inst.clear();
2708 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002709 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2710 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2711 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002712 } else {
2713 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002714 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002715 // If offset fits into 11 bits then this instruction becomes microMIPS
2716 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002717 if (inMicroMipsMode())
2718 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002719 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002720 if (!isInt<17>(Offset.getImm()))
Nirav Dave2364748a2016-09-16 18:30:20 +00002721 return Error(IDLoc, "branch target out of range");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002722 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
Nirav Dave2364748a2016-09-16 18:30:20 +00002723 return Error(IDLoc, "branch to misaligned address");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002724 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::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002729 }
2730 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002731 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002732
Zoran Jovanovicada70912015-09-07 11:56:37 +00002733 // If .set reorder is active and branch instruction has a delay slot,
2734 // emit a NOP after it.
2735 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2736 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002737 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002738
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002739 return false;
2740}
2741
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002742bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2743 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002744 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002745 const MCOperand &DstRegOp = Inst.getOperand(0);
2746 assert(DstRegOp.isReg() && "expected register operand kind");
2747
2748 const MCOperand &ImmOp = Inst.getOperand(1);
2749 assert(ImmOp.isImm() && "expected immediate operand kind");
2750
2751 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002752 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2753 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002754
2755 unsigned OpCode = 0;
2756 switch(Inst.getOpcode()) {
2757 case Mips::BneImm:
2758 OpCode = Mips::BNE;
2759 break;
2760 case Mips::BeqImm:
2761 OpCode = Mips::BEQ;
2762 break;
2763 default:
2764 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2765 break;
2766 }
2767
2768 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002769 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002770 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2771 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002772 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002773 warnIfNoMacro(IDLoc);
2774
2775 unsigned ATReg = getATReg(IDLoc);
2776 if (!ATReg)
2777 return true;
2778
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002779 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002780 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002781 return true;
2782
Daniel Sandersa736b372016-04-29 13:33:12 +00002783 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002784 }
2785 return false;
2786}
2787
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002788void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002789 const MCSubtargetInfo *STI, bool IsLoad,
2790 bool IsImmOpnd) {
2791 if (IsLoad) {
2792 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2793 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002794 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002795 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2796}
2797
2798void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2799 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2800 MipsTargetStreamer &TOut = getTargetStreamer();
2801
2802 unsigned DstReg = Inst.getOperand(0).getReg();
2803 unsigned BaseReg = Inst.getOperand(1).getReg();
2804
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002805 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002806 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2807 unsigned DstRegClassID =
2808 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2809 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2810 (DstRegClassID == Mips::GPR64RegClassID);
2811
2812 if (IsImmOpnd) {
2813 // Try to use DstReg as the temporary.
2814 if (IsGPR && (BaseReg != DstReg)) {
2815 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2816 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2817 STI);
2818 return;
2819 }
2820
Matheus Almeida7de68e72014-06-18 14:46:05 +00002821 // At this point we need AT to perform the expansions and we exit if it is
2822 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002823 unsigned ATReg = getATReg(IDLoc);
2824 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002825 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002826
2827 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2828 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2829 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002830 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002831
Daniel Sandersfba875f2016-04-29 13:43:45 +00002832 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002833 MCOperand LoOperand = MCOperand::createExpr(
2834 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2835 MCOperand HiOperand = MCOperand::createExpr(
2836 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002837
2838 // Try to use DstReg as the temporary.
2839 if (IsGPR && (BaseReg != DstReg)) {
2840 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2841 LoOperand, DstReg, IDLoc, STI);
2842 return;
2843 }
2844
2845 // At this point we need AT to perform the expansions and we exit if it is
2846 // not available.
2847 unsigned ATReg = getATReg(IDLoc);
2848 if (!ATReg)
2849 return;
2850
2851 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2852 LoOperand, ATReg, IDLoc, STI);
2853}
2854
2855void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2856 const MCSubtargetInfo *STI,
2857 bool IsImmOpnd) {
2858 MipsTargetStreamer &TOut = getTargetStreamer();
2859
2860 unsigned SrcReg = Inst.getOperand(0).getReg();
2861 unsigned BaseReg = Inst.getOperand(1).getReg();
2862
Daniel Sanders241c6792016-05-12 14:01:50 +00002863 if (IsImmOpnd) {
2864 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2865 Inst.getOperand(2).getImm(),
2866 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
2867 return;
2868 }
2869
Daniel Sandersfba875f2016-04-29 13:43:45 +00002870 unsigned ATReg = getATReg(IDLoc);
2871 if (!ATReg)
2872 return;
2873
Daniel Sandersfba875f2016-04-29 13:43:45 +00002874 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002875 MCOperand LoOperand = MCOperand::createExpr(
2876 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2877 MCOperand HiOperand = MCOperand::createExpr(
2878 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002879 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2880 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002881}
2882
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002883bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2884 MCStreamer &Out,
2885 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002886 unsigned OpNum = Inst.getNumOperands();
2887 unsigned Opcode = Inst.getOpcode();
2888 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2889
2890 assert (Inst.getOperand(OpNum - 1).isImm() &&
2891 Inst.getOperand(OpNum - 2).isReg() &&
2892 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2893
2894 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2895 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002896 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2897 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2898 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2899 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002900 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002901 if (inMicroMipsMode() && hasMips32r6())
2902 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2903 else
2904 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2905 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002906
2907 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002908 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002909 return false;
2910}
2911
Toma Tabacu1a108322015-06-17 13:20:24 +00002912bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002913 MCStreamer &Out,
2914 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002915 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002916 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002917 unsigned PseudoOpcode = Inst.getOpcode();
2918 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002919 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002920 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2921
2922 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002923 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002924
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002925 unsigned TrgReg;
2926 if (TrgOp.isReg())
2927 TrgReg = TrgOp.getReg();
2928 else if (TrgOp.isImm()) {
2929 warnIfNoMacro(IDLoc);
2930 EmittedNoMacroWarning = true;
2931
2932 TrgReg = getATReg(IDLoc);
2933 if (!TrgReg)
2934 return true;
2935
2936 switch(PseudoOpcode) {
2937 default:
2938 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2939 case Mips::BLTImmMacro:
2940 PseudoOpcode = Mips::BLT;
2941 break;
2942 case Mips::BLEImmMacro:
2943 PseudoOpcode = Mips::BLE;
2944 break;
2945 case Mips::BGEImmMacro:
2946 PseudoOpcode = Mips::BGE;
2947 break;
2948 case Mips::BGTImmMacro:
2949 PseudoOpcode = Mips::BGT;
2950 break;
2951 case Mips::BLTUImmMacro:
2952 PseudoOpcode = Mips::BLTU;
2953 break;
2954 case Mips::BLEUImmMacro:
2955 PseudoOpcode = Mips::BLEU;
2956 break;
2957 case Mips::BGEUImmMacro:
2958 PseudoOpcode = Mips::BGEU;
2959 break;
2960 case Mips::BGTUImmMacro:
2961 PseudoOpcode = Mips::BGTU;
2962 break;
2963 case Mips::BLTLImmMacro:
2964 PseudoOpcode = Mips::BLTL;
2965 break;
2966 case Mips::BLELImmMacro:
2967 PseudoOpcode = Mips::BLEL;
2968 break;
2969 case Mips::BGELImmMacro:
2970 PseudoOpcode = Mips::BGEL;
2971 break;
2972 case Mips::BGTLImmMacro:
2973 PseudoOpcode = Mips::BGTL;
2974 break;
2975 case Mips::BLTULImmMacro:
2976 PseudoOpcode = Mips::BLTUL;
2977 break;
2978 case Mips::BLEULImmMacro:
2979 PseudoOpcode = Mips::BLEUL;
2980 break;
2981 case Mips::BGEULImmMacro:
2982 PseudoOpcode = Mips::BGEUL;
2983 break;
2984 case Mips::BGTULImmMacro:
2985 PseudoOpcode = Mips::BGTUL;
2986 break;
2987 }
2988
2989 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002990 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002991 return true;
2992 }
2993
Toma Tabacu1a108322015-06-17 13:20:24 +00002994 switch (PseudoOpcode) {
2995 case Mips::BLT:
2996 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002997 case Mips::BLTL:
2998 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002999 AcceptsEquality = false;
3000 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003001 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
3002 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003003 ZeroSrcOpcode = Mips::BGTZ;
3004 ZeroTrgOpcode = Mips::BLTZ;
3005 break;
3006 case Mips::BLE:
3007 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003008 case Mips::BLEL:
3009 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003010 AcceptsEquality = true;
3011 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003012 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
3013 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003014 ZeroSrcOpcode = Mips::BGEZ;
3015 ZeroTrgOpcode = Mips::BLEZ;
3016 break;
3017 case Mips::BGE:
3018 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003019 case Mips::BGEL:
3020 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003021 AcceptsEquality = true;
3022 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003023 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
3024 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003025 ZeroSrcOpcode = Mips::BLEZ;
3026 ZeroTrgOpcode = Mips::BGEZ;
3027 break;
3028 case Mips::BGT:
3029 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003030 case Mips::BGTL:
3031 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00003032 AcceptsEquality = false;
3033 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00003034 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
3035 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00003036 ZeroSrcOpcode = Mips::BLTZ;
3037 ZeroTrgOpcode = Mips::BGTZ;
3038 break;
3039 default:
3040 llvm_unreachable("unknown opcode for branch pseudo-instruction");
3041 }
3042
Toma Tabacu1a108322015-06-17 13:20:24 +00003043 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
3044 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
3045 if (IsSrcRegZero && IsTrgRegZero) {
3046 // FIXME: All of these Opcode-specific if's are needed for compatibility
3047 // with GAS' behaviour. However, they may not generate the most efficient
3048 // code in some circumstances.
3049 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003050 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3051 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003052 return false;
3053 }
3054 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003055 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3056 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003057 Warning(IDLoc, "branch is always taken");
3058 return false;
3059 }
3060 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003061 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3062 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003063 Warning(IDLoc, "branch is always taken");
3064 return false;
3065 }
3066 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003067 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
3068 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003069 return false;
3070 }
3071 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003072 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
3073 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003074 return false;
3075 }
3076 if (AcceptsEquality) {
3077 // If both registers are $0 and the pseudo-branch accepts equality, it
3078 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00003079 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3080 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003081 Warning(IDLoc, "branch is always taken");
3082 return false;
3083 }
3084 // If both registers are $0 and the pseudo-branch does not accept
3085 // equality, it will never be taken, so we don't have to emit anything.
3086 return false;
3087 }
3088 if (IsSrcRegZero || IsTrgRegZero) {
3089 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
3090 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
3091 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
3092 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
3093 // the pseudo-branch will never be taken, so we don't emit anything.
3094 // This only applies to unsigned pseudo-branches.
3095 return false;
3096 }
3097 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
3098 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
3099 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
3100 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
3101 // the pseudo-branch will always be taken, so we emit an unconditional
3102 // branch.
3103 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00003104 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
3105 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003106 Warning(IDLoc, "branch is always taken");
3107 return false;
3108 }
3109 if (IsUnsigned) {
3110 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
3111 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
3112 // the pseudo-branch will be taken only when the non-zero register is
3113 // different from 0, so we emit a BNEZ.
3114 //
3115 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
3116 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
3117 // the pseudo-branch will be taken only when the non-zero register is
3118 // equal to 0, so we emit a BEQZ.
3119 //
3120 // Because only BLEU and BGEU branch on equality, we can use the
3121 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00003122 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
3123 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
3124 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003125 return false;
3126 }
3127 // If we have a signed pseudo-branch and one of the registers is $0,
3128 // we can use an appropriate compare-to-zero branch. We select which one
3129 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00003130 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
3131 IsSrcRegZero ? TrgReg : SrcReg,
3132 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003133 return false;
3134 }
3135
3136 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
3137 // expansions. If it is not available, we return.
3138 unsigned ATRegNum = getATReg(IDLoc);
3139 if (!ATRegNum)
3140 return true;
3141
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00003142 if (!EmittedNoMacroWarning)
3143 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00003144
3145 // SLT fits well with 2 of our 4 pseudo-branches:
3146 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
3147 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
3148 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
3149 // This is accomplished by using a BNEZ with the result of the SLT.
3150 //
3151 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
3152 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
3153 // Because only BGE and BLE branch on equality, we can use the
3154 // AcceptsEquality variable to decide when to emit the BEQZ.
3155 // Note that the order of the SLT arguments doesn't change between
3156 // opposites.
3157 //
3158 // The same applies to the unsigned variants, except that SLTu is used
3159 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00003160 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
3161 ReverseOrderSLT ? TrgReg : SrcReg,
3162 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003163
Daniel Sandersa736b372016-04-29 13:33:12 +00003164 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
3165 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
3166 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
3167 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00003168 return false;
3169}
3170
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003171bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3172 const MCSubtargetInfo *STI, const bool IsMips64,
3173 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003174 MipsTargetStreamer &TOut = getTargetStreamer();
3175
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003176 warnIfNoMacro(IDLoc);
3177
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003178 const MCOperand &RdRegOp = Inst.getOperand(0);
3179 assert(RdRegOp.isReg() && "expected register operand kind");
3180 unsigned RdReg = RdRegOp.getReg();
3181
3182 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003183 assert(RsRegOp.isReg() && "expected register operand kind");
3184 unsigned RsReg = RsRegOp.getReg();
3185
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003186 const MCOperand &RtRegOp = Inst.getOperand(2);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003187 assert(RtRegOp.isReg() && "expected register operand kind");
3188 unsigned RtReg = RtRegOp.getReg();
3189 unsigned DivOp;
3190 unsigned ZeroReg;
3191
3192 if (IsMips64) {
3193 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
3194 ZeroReg = Mips::ZERO_64;
3195 } else {
3196 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
3197 ZeroReg = Mips::ZERO;
3198 }
3199
3200 bool UseTraps = useTraps();
3201
3202 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
3203 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
3204 Warning(IDLoc, "dividing zero by zero");
3205 if (IsMips64) {
3206 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
3207 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003208 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003209 return false;
3210 }
3211
Daniel Sandersa736b372016-04-29 13:33:12 +00003212 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003213 return false;
3214 }
3215 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00003216 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003217 return false;
3218 }
3219 }
3220
3221 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
3222 Warning(IDLoc, "division by zero");
3223 if (Signed) {
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 }
3233
3234 // FIXME: The values for these two BranchTarget variables may be different in
3235 // micromips. These magic numbers need to be removed.
3236 unsigned BranchTargetNoTraps;
3237 unsigned BranchTarget;
3238
3239 if (UseTraps) {
3240 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003241 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003242 } else {
3243 BranchTarget = IsMips64 ? 20 : 16;
3244 BranchTargetNoTraps = 8;
3245 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003246 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003247 }
3248
Daniel Sandersa736b372016-04-29 13:33:12 +00003249 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003250
3251 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003252 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003253
3254 if (!Signed) {
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003255 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003256 return false;
3257 }
3258
3259 unsigned ATReg = getATReg(IDLoc);
3260 if (!ATReg)
3261 return true;
3262
Daniel Sandersa736b372016-04-29 13:33:12 +00003263 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003264 if (IsMips64) {
3265 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003266 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3267 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3268 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003269 } else {
3270 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003271 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3272 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003273 }
3274
3275 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003276 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003277 else {
3278 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003279 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3280 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3281 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003282 }
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003283 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003284 return false;
3285}
3286
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003287bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003288 SMLoc IDLoc, MCStreamer &Out,
3289 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003290 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003291
3292 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3293 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3294 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3295
3296 unsigned FirstReg = Inst.getOperand(0).getReg();
3297 unsigned SecondReg = Inst.getOperand(1).getReg();
3298 unsigned ThirdReg = Inst.getOperand(2).getReg();
3299
3300 if (hasMips1() && !hasMips2()) {
3301 unsigned ATReg = getATReg(IDLoc);
3302 if (!ATReg)
3303 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003304 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3305 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3306 TOut.emitNop(IDLoc, STI);
3307 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3308 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3309 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3310 TOut.emitNop(IDLoc, STI);
3311 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3312 : Mips::CVT_W_S,
3313 FirstReg, SecondReg, IDLoc, STI);
3314 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3315 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003316 return false;
3317 }
3318
Daniel Sandersa736b372016-04-29 13:33:12 +00003319 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3320 : Mips::TRUNC_W_S,
3321 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003322
3323 return false;
3324}
3325
Daniel Sanders6394ee52015-10-15 14:52:58 +00003326bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003327 MCStreamer &Out, const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003328 MipsTargetStreamer &TOut = getTargetStreamer();
3329
Toma Tabacud88d79c2015-06-23 14:39:42 +00003330 if (hasMips32r6() || hasMips64r6()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00003331 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacud88d79c2015-06-23 14:39:42 +00003332 }
3333
3334 warnIfNoMacro(IDLoc);
3335
3336 const MCOperand &DstRegOp = Inst.getOperand(0);
3337 assert(DstRegOp.isReg() && "expected register operand kind");
3338
3339 const MCOperand &SrcRegOp = Inst.getOperand(1);
3340 assert(SrcRegOp.isReg() && "expected register operand kind");
3341
3342 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3343 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3344
3345 unsigned DstReg = DstRegOp.getReg();
3346 unsigned SrcReg = SrcRegOp.getReg();
3347 int64_t OffsetValue = OffsetImmOp.getImm();
3348
3349 // NOTE: We always need AT for ULHU, as it is always used as the source
3350 // register for one of the LBu's.
3351 unsigned ATReg = getATReg(IDLoc);
3352 if (!ATReg)
3353 return true;
3354
3355 // When the value of offset+1 does not fit in 16 bits, we have to load the
3356 // offset in AT, (D)ADDu the original source register (if there was one), and
3357 // then use AT as the source register for the 2 generated LBu's.
3358 bool LoadedOffsetInAT = false;
3359 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3360 LoadedOffsetInAT = true;
3361
3362 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003363 true, IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003364 return true;
3365
3366 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3367 // because it will make our output more similar to GAS'. For example,
3368 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3369 // instead of just an "ori $1, $9, 32768".
3370 // NOTE: If there is no source register specified in the ULHU, the parser
3371 // will interpret it as $0.
3372 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003373 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003374 }
3375
3376 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3377 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3378 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3379
3380 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3381 if (isLittle()) {
3382 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3383 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3384 } else {
3385 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3386 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3387 }
3388
3389 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3390
Daniel Sandersa736b372016-04-29 13:33:12 +00003391 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3392 FirstLbuOffset, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003393
Daniel Sandersa736b372016-04-29 13:33:12 +00003394 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3395 STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003396
Daniel Sandersa736b372016-04-29 13:33:12 +00003397 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003398
Daniel Sandersa736b372016-04-29 13:33:12 +00003399 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003400
3401 return false;
3402}
3403
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003404bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3405 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003406 MipsTargetStreamer &TOut = getTargetStreamer();
3407
Nirav Dave2364748a2016-09-16 18:30:20 +00003408 if (hasMips32r6() || hasMips64r6())
3409 return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003410
3411 const MCOperand &DstRegOp = Inst.getOperand(0);
3412 assert(DstRegOp.isReg() && "expected register operand kind");
3413
3414 const MCOperand &SrcRegOp = Inst.getOperand(1);
3415 assert(SrcRegOp.isReg() && "expected register operand kind");
3416
3417 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3418 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3419
3420 unsigned SrcReg = SrcRegOp.getReg();
3421 int64_t OffsetValue = OffsetImmOp.getImm();
3422 unsigned ATReg = 0;
3423
3424 // When the value of offset+3 does not fit in 16 bits, we have to load the
3425 // offset in AT, (D)ADDu the original source register (if there was one), and
3426 // then use AT as the source register for the generated LWL and LWR.
3427 bool LoadedOffsetInAT = false;
3428 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3429 ATReg = getATReg(IDLoc);
3430 if (!ATReg)
3431 return true;
3432 LoadedOffsetInAT = true;
3433
3434 warnIfNoMacro(IDLoc);
3435
3436 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003437 true, IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003438 return true;
3439
3440 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3441 // because it will make our output more similar to GAS'. For example,
3442 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3443 // instead of just an "ori $1, $9, 32768".
3444 // NOTE: If there is no source register specified in the ULW, the parser
3445 // will interpret it as $0.
3446 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003447 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003448 }
3449
3450 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3451 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3452 if (isLittle()) {
3453 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3454 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3455 } else {
3456 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3457 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3458 }
3459
Daniel Sandersa736b372016-04-29 13:33:12 +00003460 TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3461 STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003462
Daniel Sandersa736b372016-04-29 13:33:12 +00003463 TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
3464 IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003465
3466 return false;
3467}
3468
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003469bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003470 MCStreamer &Out,
3471 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003472 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003473
3474 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3475 assert (Inst.getOperand(0).isReg() &&
3476 Inst.getOperand(1).isReg() &&
3477 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3478
3479 unsigned ATReg = Mips::NoRegister;
3480 unsigned FinalDstReg = Mips::NoRegister;
3481 unsigned DstReg = Inst.getOperand(0).getReg();
3482 unsigned SrcReg = Inst.getOperand(1).getReg();
3483 int64_t ImmValue = Inst.getOperand(2).getImm();
3484
3485 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3486
3487 unsigned FinalOpcode = Inst.getOpcode();
3488
3489 if (DstReg == SrcReg) {
3490 ATReg = getATReg(Inst.getLoc());
3491 if (!ATReg)
3492 return true;
3493 FinalDstReg = DstReg;
3494 DstReg = ATReg;
3495 }
3496
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003497 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003498 switch (FinalOpcode) {
3499 default:
3500 llvm_unreachable("unimplemented expansion");
3501 case (Mips::ADDi):
3502 FinalOpcode = Mips::ADD;
3503 break;
3504 case (Mips::ADDiu):
3505 FinalOpcode = Mips::ADDu;
3506 break;
3507 case (Mips::ANDi):
3508 FinalOpcode = Mips::AND;
3509 break;
3510 case (Mips::NORImm):
3511 FinalOpcode = Mips::NOR;
3512 break;
3513 case (Mips::ORi):
3514 FinalOpcode = Mips::OR;
3515 break;
3516 case (Mips::SLTi):
3517 FinalOpcode = Mips::SLT;
3518 break;
3519 case (Mips::SLTiu):
3520 FinalOpcode = Mips::SLTu;
3521 break;
3522 case (Mips::XORi):
3523 FinalOpcode = Mips::XOR;
3524 break;
3525 }
3526
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003527 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003528 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003529 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003530 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003531 return false;
3532 }
3533 return true;
3534}
3535
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003536bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3537 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003538 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003539 unsigned ATReg = Mips::NoRegister;
3540 unsigned DReg = Inst.getOperand(0).getReg();
3541 unsigned SReg = Inst.getOperand(1).getReg();
3542 unsigned TReg = Inst.getOperand(2).getReg();
3543 unsigned TmpReg = DReg;
3544
3545 unsigned FirstShift = Mips::NOP;
3546 unsigned SecondShift = Mips::NOP;
3547
3548 if (hasMips32r2()) {
3549
3550 if (DReg == SReg) {
3551 TmpReg = getATReg(Inst.getLoc());
3552 if (!TmpReg)
3553 return true;
3554 }
3555
3556 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003557 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3558 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003559 return false;
3560 }
3561
3562 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003563 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003564 return false;
3565 }
3566
3567 return true;
3568 }
3569
3570 if (hasMips32()) {
3571
3572 switch (Inst.getOpcode()) {
3573 default:
3574 llvm_unreachable("unexpected instruction opcode");
3575 case Mips::ROL:
3576 FirstShift = Mips::SRLV;
3577 SecondShift = Mips::SLLV;
3578 break;
3579 case Mips::ROR:
3580 FirstShift = Mips::SLLV;
3581 SecondShift = Mips::SRLV;
3582 break;
3583 }
3584
3585 ATReg = getATReg(Inst.getLoc());
3586 if (!ATReg)
3587 return true;
3588
Daniel Sandersa736b372016-04-29 13:33:12 +00003589 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3590 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3591 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3592 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003593
3594 return false;
3595 }
3596
3597 return true;
3598}
3599
3600bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003601 MCStreamer &Out,
3602 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003603 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003604 unsigned ATReg = Mips::NoRegister;
3605 unsigned DReg = Inst.getOperand(0).getReg();
3606 unsigned SReg = Inst.getOperand(1).getReg();
3607 int64_t ImmValue = Inst.getOperand(2).getImm();
3608
3609 unsigned FirstShift = Mips::NOP;
3610 unsigned SecondShift = Mips::NOP;
3611
3612 if (hasMips32r2()) {
3613
3614 if (Inst.getOpcode() == Mips::ROLImm) {
3615 uint64_t MaxShift = 32;
3616 uint64_t ShiftValue = ImmValue;
3617 if (ImmValue != 0)
3618 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003619 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003620 return false;
3621 }
3622
3623 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003624 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003625 return false;
3626 }
3627
3628 return true;
3629 }
3630
3631 if (hasMips32()) {
3632
3633 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003634 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003635 return false;
3636 }
3637
3638 switch (Inst.getOpcode()) {
3639 default:
3640 llvm_unreachable("unexpected instruction opcode");
3641 case Mips::ROLImm:
3642 FirstShift = Mips::SLL;
3643 SecondShift = Mips::SRL;
3644 break;
3645 case Mips::RORImm:
3646 FirstShift = Mips::SRL;
3647 SecondShift = Mips::SLL;
3648 break;
3649 }
3650
3651 ATReg = getATReg(Inst.getLoc());
3652 if (!ATReg)
3653 return true;
3654
Daniel Sandersa736b372016-04-29 13:33:12 +00003655 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3656 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3657 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003658
3659 return false;
3660 }
3661
3662 return true;
3663}
3664
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003665bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3666 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003667 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003668 unsigned ATReg = Mips::NoRegister;
3669 unsigned DReg = Inst.getOperand(0).getReg();
3670 unsigned SReg = Inst.getOperand(1).getReg();
3671 unsigned TReg = Inst.getOperand(2).getReg();
3672 unsigned TmpReg = DReg;
3673
3674 unsigned FirstShift = Mips::NOP;
3675 unsigned SecondShift = Mips::NOP;
3676
3677 if (hasMips64r2()) {
3678
3679 if (TmpReg == SReg) {
3680 TmpReg = getATReg(Inst.getLoc());
3681 if (!TmpReg)
3682 return true;
3683 }
3684
3685 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003686 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3687 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003688 return false;
3689 }
3690
3691 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003692 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003693 return false;
3694 }
3695
3696 return true;
3697 }
3698
3699 if (hasMips64()) {
3700
3701 switch (Inst.getOpcode()) {
3702 default:
3703 llvm_unreachable("unexpected instruction opcode");
3704 case Mips::DROL:
3705 FirstShift = Mips::DSRLV;
3706 SecondShift = Mips::DSLLV;
3707 break;
3708 case Mips::DROR:
3709 FirstShift = Mips::DSLLV;
3710 SecondShift = Mips::DSRLV;
3711 break;
3712 }
3713
3714 ATReg = getATReg(Inst.getLoc());
3715 if (!ATReg)
3716 return true;
3717
Daniel Sandersa736b372016-04-29 13:33:12 +00003718 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3719 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3720 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3721 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003722
3723 return false;
3724 }
3725
3726 return true;
3727}
3728
3729bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003730 MCStreamer &Out,
3731 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003732 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003733 unsigned ATReg = Mips::NoRegister;
3734 unsigned DReg = Inst.getOperand(0).getReg();
3735 unsigned SReg = Inst.getOperand(1).getReg();
3736 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3737
3738 unsigned FirstShift = Mips::NOP;
3739 unsigned SecondShift = Mips::NOP;
3740
3741 MCInst TmpInst;
3742
3743 if (hasMips64r2()) {
3744
3745 unsigned FinalOpcode = Mips::NOP;
3746 if (ImmValue == 0)
3747 FinalOpcode = Mips::DROTR;
3748 else if (ImmValue % 32 == 0)
3749 FinalOpcode = Mips::DROTR32;
3750 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3751 if (Inst.getOpcode() == Mips::DROLImm)
3752 FinalOpcode = Mips::DROTR32;
3753 else
3754 FinalOpcode = Mips::DROTR;
3755 } else if (ImmValue >= 33) {
3756 if (Inst.getOpcode() == Mips::DROLImm)
3757 FinalOpcode = Mips::DROTR;
3758 else
3759 FinalOpcode = Mips::DROTR32;
3760 }
3761
3762 uint64_t ShiftValue = ImmValue % 32;
3763 if (Inst.getOpcode() == Mips::DROLImm)
3764 ShiftValue = (32 - ImmValue % 32) % 32;
3765
Daniel Sandersa736b372016-04-29 13:33:12 +00003766 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003767
3768 return false;
3769 }
3770
3771 if (hasMips64()) {
3772
3773 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003774 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003775 return false;
3776 }
3777
3778 switch (Inst.getOpcode()) {
3779 default:
3780 llvm_unreachable("unexpected instruction opcode");
3781 case Mips::DROLImm:
3782 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3783 FirstShift = Mips::DSLL;
3784 SecondShift = Mips::DSRL32;
3785 }
3786 if (ImmValue == 32) {
3787 FirstShift = Mips::DSLL32;
3788 SecondShift = Mips::DSRL32;
3789 }
3790 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3791 FirstShift = Mips::DSLL32;
3792 SecondShift = Mips::DSRL;
3793 }
3794 break;
3795 case Mips::DRORImm:
3796 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3797 FirstShift = Mips::DSRL;
3798 SecondShift = Mips::DSLL32;
3799 }
3800 if (ImmValue == 32) {
3801 FirstShift = Mips::DSRL32;
3802 SecondShift = Mips::DSLL32;
3803 }
3804 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3805 FirstShift = Mips::DSRL32;
3806 SecondShift = Mips::DSLL;
3807 }
3808 break;
3809 }
3810
3811 ATReg = getATReg(Inst.getLoc());
3812 if (!ATReg)
3813 return true;
3814
Daniel Sandersa736b372016-04-29 13:33:12 +00003815 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3816 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3817 Inst.getLoc(), STI);
3818 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003819
3820 return false;
3821 }
3822
3823 return true;
3824}
3825
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003826bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3827 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003828 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003829 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3830 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3831
Daniel Sandersa736b372016-04-29 13:33:12 +00003832 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003833 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003834 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003835 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003836 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3837 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003838
3839 return false;
3840}
3841
Simon Dardisaff4d142016-10-18 14:28:00 +00003842static unsigned nextReg(unsigned Reg) {
3843 switch (Reg) {
3844 case Mips::ZERO: return Mips::AT;
3845 case Mips::AT: return Mips::V0;
3846 case Mips::V0: return Mips::V1;
3847 case Mips::V1: return Mips::A0;
3848 case Mips::A0: return Mips::A1;
3849 case Mips::A1: return Mips::A2;
3850 case Mips::A2: return Mips::A3;
3851 case Mips::A3: return Mips::T0;
3852 case Mips::T0: return Mips::T1;
3853 case Mips::T1: return Mips::T2;
3854 case Mips::T2: return Mips::T3;
3855 case Mips::T3: return Mips::T4;
3856 case Mips::T4: return Mips::T5;
3857 case Mips::T5: return Mips::T6;
3858 case Mips::T6: return Mips::T7;
3859 case Mips::T7: return Mips::S0;
3860 case Mips::S0: return Mips::S1;
3861 case Mips::S1: return Mips::S2;
3862 case Mips::S2: return Mips::S3;
3863 case Mips::S3: return Mips::S4;
3864 case Mips::S4: return Mips::S5;
3865 case Mips::S5: return Mips::S6;
3866 case Mips::S6: return Mips::S7;
3867 case Mips::S7: return Mips::T8;
3868 case Mips::T8: return Mips::T9;
3869 case Mips::T9: return Mips::K0;
3870 case Mips::K0: return Mips::K1;
3871 case Mips::K1: return Mips::GP;
3872 case Mips::GP: return Mips::SP;
3873 case Mips::SP: return Mips::FP;
3874 case Mips::FP: return Mips::RA;
3875 case Mips::RA: return Mips::ZERO;
3876 default: return 0;
3877 }
3878
3879}
3880
3881// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
3882// lw $<reg+1>>, offset+4($reg2)'
3883// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
3884// sw $<reg+1>>, offset+4($reg2)'
3885// for O32.
3886bool MipsAsmParser::expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc,
3887 MCStreamer &Out,
3888 const MCSubtargetInfo *STI,
3889 bool IsLoad) {
3890 if (!isABI_O32())
3891 return true;
3892
3893 warnIfNoMacro(IDLoc);
3894
3895 MipsTargetStreamer &TOut = getTargetStreamer();
3896 unsigned Opcode = IsLoad ? Mips::LW : Mips::SW;
3897 unsigned FirstReg = Inst.getOperand(0).getReg();
3898 unsigned SecondReg = nextReg(FirstReg);
3899 unsigned BaseReg = Inst.getOperand(1).getReg();
3900 if (!SecondReg)
3901 return true;
3902
3903 warnIfRegIndexIsAT(FirstReg, IDLoc);
3904
3905 assert(Inst.getOperand(2).isImm() &&
3906 "Offset for load macro is not immediate!");
3907
3908 MCOperand &FirstOffset = Inst.getOperand(2);
3909 signed NextOffset = FirstOffset.getImm() + 4;
3910 MCOperand SecondOffset = MCOperand::createImm(NextOffset);
3911
3912 if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset))
3913 return true;
3914
3915 // For loads, clobber the base register with the second load instead of the
3916 // first if the BaseReg == FirstReg.
3917 if (FirstReg != BaseReg || !IsLoad) {
3918 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
3919 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
3920 } else {
3921 TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI);
3922 TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI);
3923 }
3924
3925 return false;
3926}
3927
Simon Dardis43115a12016-11-21 20:30:41 +00003928bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3929 const MCSubtargetInfo *STI) {
3930
3931 warnIfNoMacro(IDLoc);
3932 MipsTargetStreamer &TOut = getTargetStreamer();
3933
3934 if (Inst.getOperand(1).getReg() != Mips::ZERO &&
3935 Inst.getOperand(2).getReg() != Mips::ZERO) {
3936 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
3937 Inst.getOperand(1).getReg(), Inst.getOperand(2).getReg(),
3938 IDLoc, STI);
3939 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
3940 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
3941 return false;
3942 }
3943
3944 unsigned Reg = 0;
3945 if (Inst.getOperand(1).getReg() == Mips::ZERO) {
3946 Reg = Inst.getOperand(2).getReg();
3947 } else {
3948 Reg = Inst.getOperand(1).getReg();
3949 }
3950 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(), Reg, 1, IDLoc, STI);
3951 return false;
3952}
3953
3954bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3955 const MCSubtargetInfo *STI) {
3956
3957 warnIfNoMacro(IDLoc);
3958 MipsTargetStreamer &TOut = getTargetStreamer();
3959
3960 unsigned Opc;
3961 int64_t Imm = Inst.getOperand(2).getImm();
3962 unsigned Reg = Inst.getOperand(1).getReg();
3963
3964 if (Imm == 0) {
3965 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
3966 Inst.getOperand(1).getReg(), 1, IDLoc, STI);
3967 return false;
3968 } else {
3969
3970 if (Reg == Mips::ZERO) {
3971 Warning(IDLoc, "comparison is always false");
3972 TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu,
3973 Inst.getOperand(0).getReg(), Reg, Reg, IDLoc, STI);
3974 return false;
3975 }
3976
3977 if (Imm > -0x8000 && Imm < 0) {
3978 Imm = -Imm;
3979 Opc = isGP64bit() ? Mips::DADDiu : Mips::ADDiu;
3980 } else {
3981 Opc = Mips::XORi;
3982 }
3983 }
3984 if (!isUInt<16>(Imm)) {
3985 unsigned ATReg = getATReg(IDLoc);
3986 if (!ATReg)
3987 return true;
3988
3989 if (loadImmediate(Imm, ATReg, Mips::NoRegister, true, isGP64bit(), IDLoc,
3990 Out, STI))
3991 return true;
3992
3993 TOut.emitRRR(Mips::XOR, Inst.getOperand(0).getReg(),
3994 Inst.getOperand(1).getReg(), ATReg, IDLoc, STI);
3995 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
3996 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
3997 return false;
3998 }
3999
4000 TOut.emitRRI(Opc, Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(),
4001 Imm, IDLoc, STI);
4002 TOut.emitRRI(Mips::SLTiu, Inst.getOperand(0).getReg(),
4003 Inst.getOperand(0).getReg(), 1, IDLoc, STI);
4004 return false;
4005}
4006
Daniel Sandersc5537422016-07-27 13:49:44 +00004007unsigned
4008MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
4009 const OperandVector &Operands) {
4010 switch (Inst.getOpcode()) {
4011 default:
4012 return Match_Success;
4013 case Mips::DATI:
4014 case Mips::DAHI:
Simon Dardisb3fd1892016-10-14 09:31:42 +00004015 case Mips::DATI_MM64R6:
4016 case Mips::DAHI_MM64R6:
Daniel Sandersb23005e2016-07-28 15:59:06 +00004017 if (static_cast<MipsOperand &>(*Operands[1])
4018 .isValidForTie(static_cast<MipsOperand &>(*Operands[2])))
4019 return Match_Success;
4020 return Match_RequiresSameSrcAndDst;
Daniel Sandersc5537422016-07-27 13:49:44 +00004021 }
4022}
Matheus Almeida595fcab2014-06-11 15:05:56 +00004023unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
Simon Dardisb60833c2016-05-31 17:34:42 +00004024 switch (Inst.getOpcode()) {
Simon Dardisb3fd1892016-10-14 09:31:42 +00004025 // As described by the MIPSR6 spec, daui must not use the zero operand for
4026 // its source operand.
4027 case Mips::DAUI:
4028 case Mips::DAUI_MM64R6:
4029 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4030 Inst.getOperand(1).getReg() == Mips::ZERO_64)
4031 return Match_RequiresNoZeroRegister;
4032 return Match_Success;
Matheus Almeida595fcab2014-06-11 15:05:56 +00004033 // As described by the Mips32r2 spec, the registers Rd and Rs for
4034 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00004035 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00004036 // and registers Rd and Base for microMIPS lwp instruction
Simon Dardisb60833c2016-05-31 17:34:42 +00004037 case Mips::JALR_HB:
4038 case Mips::JALRC_HB_MMR6:
Hrvoje Vargac962c492016-06-09 12:57:23 +00004039 case Mips::JALRC_MMR6:
Simon Dardisb60833c2016-05-31 17:34:42 +00004040 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4041 return Match_RequiresDifferentSrcAndDst;
4042 return Match_Success;
4043 case Mips::LWP_MM:
4044 case Mips::LWP_MMR6:
4045 if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
4046 return Match_RequiresDifferentSrcAndDst;
4047 return Match_Success;
Simon Dardisc4463c92016-10-18 14:42:13 +00004048 case Mips::SYNC:
4049 if (Inst.getOperand(0).getImm() != 0 && !hasMips32())
4050 return Match_NonZeroOperandForSync;
4051 return Match_Success;
Simon Dardisb60833c2016-05-31 17:34:42 +00004052 // As described the MIPSR6 spec, the compact branches that compare registers
4053 // must:
4054 // a) Not use the zero register.
4055 // b) Not use the same register twice.
4056 // c) rs < rt for bnec, beqc.
4057 // NB: For this case, the encoding will swap the operands as their
4058 // ordering doesn't matter. GAS performs this transformation too.
4059 // Hence, that constraint does not have to be enforced.
4060 //
4061 // The compact branches that branch iff the signed addition of two registers
4062 // would overflow must have rs >= rt. That can be handled like beqc/bnec with
4063 // operand swapping. They do not have restriction of using the zero register.
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004064 case Mips::BLEZC: case Mips::BLEZC_MMR6:
4065 case Mips::BGEZC: case Mips::BGEZC_MMR6:
4066 case Mips::BGTZC: case Mips::BGTZC_MMR6:
4067 case Mips::BLTZC: case Mips::BLTZC_MMR6:
4068 case Mips::BEQZC: case Mips::BEQZC_MMR6:
4069 case Mips::BNEZC: case Mips::BNEZC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004070 case Mips::BLEZC64:
4071 case Mips::BGEZC64:
4072 case Mips::BGTZC64:
4073 case Mips::BLTZC64:
4074 case Mips::BEQZC64:
4075 case Mips::BNEZC64:
4076 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4077 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004078 return Match_RequiresNoZeroRegister;
4079 return Match_Success;
Hrvoje Vargaf0ed16e2016-08-22 12:17:59 +00004080 case Mips::BGEC: case Mips::BGEC_MMR6:
4081 case Mips::BLTC: case Mips::BLTC_MMR6:
4082 case Mips::BGEUC: case Mips::BGEUC_MMR6:
4083 case Mips::BLTUC: case Mips::BLTUC_MMR6:
4084 case Mips::BEQC: case Mips::BEQC_MMR6:
4085 case Mips::BNEC: case Mips::BNEC_MMR6:
Simon Dardis68a204d2016-07-26 10:25:07 +00004086 case Mips::BGEC64:
4087 case Mips::BLTC64:
4088 case Mips::BGEUC64:
4089 case Mips::BLTUC64:
4090 case Mips::BEQC64:
4091 case Mips::BNEC64:
4092 if (Inst.getOperand(0).getReg() == Mips::ZERO ||
4093 Inst.getOperand(0).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004094 return Match_RequiresNoZeroRegister;
Simon Dardis68a204d2016-07-26 10:25:07 +00004095 if (Inst.getOperand(1).getReg() == Mips::ZERO ||
4096 Inst.getOperand(1).getReg() == Mips::ZERO_64)
Simon Dardisb60833c2016-05-31 17:34:42 +00004097 return Match_RequiresNoZeroRegister;
4098 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
4099 return Match_RequiresDifferentOperands;
4100 return Match_Success;
4101 default:
4102 return Match_Success;
4103 }
Matheus Almeida595fcab2014-06-11 15:05:56 +00004104}
4105
Daniel Sanders52da7af2015-11-06 12:11:03 +00004106static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
4107 uint64_t ErrorInfo) {
4108 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
4109 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
4110 if (ErrorLoc == SMLoc())
4111 return Loc;
4112 return ErrorLoc;
4113 }
4114 return Loc;
4115}
4116
David Blaikie960ea3f2014-06-08 16:18:35 +00004117bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4118 OperandVector &Operands,
4119 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004120 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00004121 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00004122
Jack Carterb4dbc172012-09-05 23:34:03 +00004123 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00004124 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004125 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00004126
4127 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004128 case Match_Success: {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00004129 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00004130 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004131 return false;
4132 }
4133 case Match_MissingFeature:
4134 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4135 return true;
4136 case Match_InvalidOperand: {
4137 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00004138 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004139 if (ErrorInfo >= Operands.size())
4140 return Error(IDLoc, "too few operands for instruction");
4141
Daniel Sanders52da7af2015-11-06 12:11:03 +00004142 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00004143 if (ErrorLoc == SMLoc())
4144 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00004145 }
4146
4147 return Error(ErrorLoc, "invalid operand for instruction");
4148 }
Simon Dardisc4463c92016-10-18 14:42:13 +00004149 case Match_NonZeroOperandForSync:
4150 return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs");
Jack Carterb4dbc172012-09-05 23:34:03 +00004151 case Match_MnemonicFail:
4152 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00004153 case Match_RequiresDifferentSrcAndDst:
4154 return Error(IDLoc, "source and destination must be different");
Simon Dardisb60833c2016-05-31 17:34:42 +00004155 case Match_RequiresDifferentOperands:
4156 return Error(IDLoc, "registers must be different");
4157 case Match_RequiresNoZeroRegister:
4158 return Error(IDLoc, "invalid operand ($zero) for instruction");
Daniel Sandersc5537422016-07-27 13:49:44 +00004159 case Match_RequiresSameSrcAndDst:
4160 return Error(IDLoc, "source and destination must match");
Daniel Sanders52da7af2015-11-06 12:11:03 +00004161 case Match_Immz:
4162 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004163 case Match_UImm1_0:
4164 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4165 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00004166 case Match_UImm2_0:
4167 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4168 "expected 2-bit unsigned immediate");
4169 case Match_UImm2_1:
4170 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4171 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00004172 case Match_UImm3_0:
4173 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4174 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00004175 case Match_UImm4_0:
4176 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4177 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00004178 case Match_SImm4_0:
4179 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4180 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004181 case Match_UImm5_0:
4182 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4183 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00004184 case Match_SImm5_0:
4185 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4186 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004187 case Match_UImm5_1:
4188 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4189 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004190 case Match_UImm5_32:
4191 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4192 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00004193 case Match_UImm5_33:
4194 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4195 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00004196 case Match_UImm5_0_Report_UImm6:
4197 // This is used on UImm5 operands that have a corresponding UImm5_32
4198 // operand to avoid confusing the user.
4199 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4200 "expected 6-bit unsigned immediate");
4201 case Match_UImm5_Lsl2:
4202 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4203 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00004204 case Match_UImmRange2_64:
4205 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4206 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00004207 case Match_UImm6_0:
4208 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4209 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00004210 case Match_UImm6_Lsl2:
4211 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4212 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00004213 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00004214 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4215 "expected 6-bit signed immediate");
4216 case Match_UImm7_0:
4217 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4218 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00004219 case Match_UImm7_N1:
4220 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4221 "expected immediate in range -1 .. 126");
4222 case Match_SImm7_Lsl2:
4223 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4224 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00004225 case Match_UImm8_0:
4226 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4227 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00004228 case Match_UImm10_0:
4229 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4230 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00004231 case Match_SImm10_0:
4232 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4233 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00004234 case Match_SImm11_0:
4235 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4236 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00004237 case Match_UImm16:
4238 case Match_UImm16_Relaxed:
4239 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4240 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004241 case Match_SImm16:
4242 case Match_SImm16_Relaxed:
4243 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4244 "expected 16-bit signed immediate");
Hrvoje Vargadbe4d962016-09-08 07:41:43 +00004245 case Match_SImm19_Lsl2:
4246 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4247 "expected both 19-bit signed immediate and multiple of 4");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00004248 case Match_UImm20_0:
4249 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4250 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00004251 case Match_UImm26_0:
4252 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4253 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00004254 case Match_SImm32:
4255 case Match_SImm32_Relaxed:
4256 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4257 "expected 32-bit signed immediate");
Simon Dardis299dbd62016-10-05 18:26:19 +00004258 case Match_UImm32_Coerced:
4259 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4260 "expected 32-bit immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00004261 case Match_MemSImm9:
4262 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4263 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00004264 case Match_MemSImm10:
4265 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4266 "expected memory with 10-bit signed offset");
4267 case Match_MemSImm10Lsl1:
4268 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4269 "expected memory with 11-bit signed offset and multiple of 2");
4270 case Match_MemSImm10Lsl2:
4271 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4272 "expected memory with 12-bit signed offset and multiple of 4");
4273 case Match_MemSImm10Lsl3:
4274 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4275 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00004276 case Match_MemSImm11:
4277 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4278 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00004279 case Match_MemSImm12:
4280 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4281 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00004282 case Match_MemSImm16:
4283 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
4284 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00004285 }
Craig Topper589ceee2015-01-03 08:16:34 +00004286
4287 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00004288}
4289
Toma Tabacud9d344b2015-04-27 14:05:04 +00004290void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
4291 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
4292 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
4293 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004294}
4295
Toma Tabacu81496c12015-05-20 08:54:45 +00004296void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
4297 if (!AssemblerOptions.back()->isMacro())
4298 Warning(Loc, "macro instruction expanded into multiple instructions");
4299}
4300
Daniel Sandersef638fe2014-10-03 15:37:37 +00004301void
4302MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
4303 SMRange Range, bool ShowColors) {
4304 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00004305 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00004306 ShowColors);
4307}
4308
Jack Carter1ac53222013-02-20 23:11:17 +00004309int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004310 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004311
Vladimir Medic4c299852013-11-06 11:27:05 +00004312 CC = StringSwitch<unsigned>(Name)
4313 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00004314 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00004315 .Case("a0", 4)
4316 .Case("a1", 5)
4317 .Case("a2", 6)
4318 .Case("a3", 7)
4319 .Case("v0", 2)
4320 .Case("v1", 3)
4321 .Case("s0", 16)
4322 .Case("s1", 17)
4323 .Case("s2", 18)
4324 .Case("s3", 19)
4325 .Case("s4", 20)
4326 .Case("s5", 21)
4327 .Case("s6", 22)
4328 .Case("s7", 23)
4329 .Case("k0", 26)
4330 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004331 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00004332 .Case("sp", 29)
4333 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00004334 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00004335 .Case("ra", 31)
4336 .Case("t0", 8)
4337 .Case("t1", 9)
4338 .Case("t2", 10)
4339 .Case("t3", 11)
4340 .Case("t4", 12)
4341 .Case("t5", 13)
4342 .Case("t6", 14)
4343 .Case("t7", 15)
4344 .Case("t8", 24)
4345 .Case("t9", 25)
4346 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004347
Toma Tabacufda445c2014-09-15 15:33:01 +00004348 if (!(isABI_N32() || isABI_N64()))
4349 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00004350
Daniel Sandersef638fe2014-10-03 15:37:37 +00004351 if (12 <= CC && CC <= 15) {
4352 // Name is one of t4-t7
4353 AsmToken RegTok = getLexer().peekTok();
4354 SMRange RegRange = RegTok.getLocRange();
4355
4356 StringRef FixedName = StringSwitch<StringRef>(Name)
4357 .Case("t4", "t0")
4358 .Case("t5", "t1")
4359 .Case("t6", "t2")
4360 .Case("t7", "t3")
4361 .Default("");
4362 assert(FixedName != "" && "Register name is not one of t4-t7.");
4363
4364 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
4365 "Did you mean $" + FixedName + "?", RegRange);
4366 }
4367
Toma Tabacufda445c2014-09-15 15:33:01 +00004368 // Although SGI documentation just cuts out t0-t3 for n32/n64,
4369 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
4370 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
4371 if (8 <= CC && CC <= 11)
4372 CC += 4;
4373
4374 if (CC == -1)
4375 CC = StringSwitch<unsigned>(Name)
4376 .Case("a4", 8)
4377 .Case("a5", 9)
4378 .Case("a6", 10)
4379 .Case("a7", 11)
4380 .Case("kt0", 26)
4381 .Case("kt1", 27)
4382 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00004383
4384 return CC;
4385}
Jack Carterd0bd6422013-04-18 00:41:53 +00004386
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004387int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
4388 int CC;
4389
4390 CC = StringSwitch<unsigned>(Name)
4391 .Case("hwr_cpunum", 0)
4392 .Case("hwr_synci_step", 1)
4393 .Case("hwr_cc", 2)
4394 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00004395 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004396 .Default(-1);
4397
4398 return CC;
4399}
4400
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004401int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004402
Jack Cartera63b16a2012-09-07 00:23:42 +00004403 if (Name[0] == 'f') {
4404 StringRef NumString = Name.substr(1);
4405 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004406 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004407 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004408 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00004409 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004410 return IntVal;
4411 }
4412 return -1;
4413}
Jack Cartera63b16a2012-09-07 00:23:42 +00004414
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004415int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
4416
4417 if (Name.startswith("fcc")) {
4418 StringRef NumString = Name.substr(3);
4419 unsigned IntVal;
4420 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004421 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004422 if (IntVal > 7) // There are only 8 fcc registers.
4423 return -1;
4424 return IntVal;
4425 }
4426 return -1;
4427}
4428
4429int MipsAsmParser::matchACRegisterName(StringRef Name) {
4430
Akira Hatanaka274d24c2013-08-14 01:15:52 +00004431 if (Name.startswith("ac")) {
4432 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004433 unsigned IntVal;
4434 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00004435 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004436 if (IntVal > 3) // There are only 3 acc registers.
4437 return -1;
4438 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00004439 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004440 return -1;
4441}
Jack Carterd0bd6422013-04-18 00:41:53 +00004442
Jack Carter5dc8ac92013-09-25 23:50:44 +00004443int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
4444 unsigned IntVal;
4445
4446 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
4447 return -1;
4448
4449 if (IntVal > 31)
4450 return -1;
4451
4452 return IntVal;
4453}
4454
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004455int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
4456 int CC;
4457
4458 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00004459 .Case("msair", 0)
4460 .Case("msacsr", 1)
4461 .Case("msaaccess", 2)
4462 .Case("msasave", 3)
4463 .Case("msamodify", 4)
4464 .Case("msarequest", 5)
4465 .Case("msamap", 6)
4466 .Case("msaunmap", 7)
4467 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00004468
4469 return CC;
4470}
4471
Toma Tabacu89a712b2015-04-15 10:48:56 +00004472unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004473 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004474 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004475 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004476 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004477 return 0;
4478 }
4479 unsigned AT = getReg(
4480 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004481 return AT;
4482}
Jack Carter0b744b32012-10-04 02:29:46 +00004483
Jack Carterd0bd6422013-04-18 00:41:53 +00004484unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004485 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004486}
4487
Toma Tabacu13964452014-09-04 13:23:44 +00004488bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004489 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004490 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004491
Jack Carter30a59822012-10-04 04:03:53 +00004492 // Check if the current operand has a custom associated parser, if so, try to
4493 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004494 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4495 if (ResTy == MatchOperand_Success)
4496 return false;
4497 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4498 // there was a match, but an error occurred, in which case, just return that
4499 // the operand parsing failed.
4500 if (ResTy == MatchOperand_ParseFail)
4501 return true;
4502
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004503 DEBUG(dbgs() << ".. Generic Parser\n");
4504
Jack Carterb4dbc172012-09-05 23:34:03 +00004505 switch (getLexer().getKind()) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004506 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004507 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004508 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004509
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004510 // Almost all registers have been parsed by custom parsers. There is only
4511 // one exception to this. $zero (and it's alias $0) will reach this point
4512 // for div, divu, and similar instructions because it is not an operand
4513 // to the instruction definition but an explicit register. Special case
4514 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004515 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004516 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004517
Jack Carterd0bd6422013-04-18 00:41:53 +00004518 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004519 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004520 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004521 return true;
4522
Jack Carter873c7242013-01-12 01:03:14 +00004523 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004524 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004525 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004526 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004527 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004528
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004529 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004530 return false;
4531 }
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004532 default: {
4533 DEBUG(dbgs() << ".. generic integer expression\n");
4534
4535 const MCExpr *Expr;
Jack Carterd0bd6422013-04-18 00:41:53 +00004536 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004537 if (getParser().parseExpression(Expr))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004538 return true;
4539
Jack Carter873c7242013-01-12 01:03:14 +00004540 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4541
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004542 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004543 return false;
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004544 }
Jack Carter0b744b32012-10-04 02:29:46 +00004545 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004546 return true;
4547}
4548
Jack Carterb5cf5902013-04-17 00:18:04 +00004549bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4550
4551 switch (Expr->getKind()) {
4552 case MCExpr::Constant:
4553 return true;
4554 case MCExpr::SymbolRef:
4555 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4556 case MCExpr::Binary:
4557 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4558 if (!isEvaluated(BE->getLHS()))
4559 return false;
4560 return isEvaluated(BE->getRHS());
4561 }
4562 case MCExpr::Unary:
4563 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004564 case MCExpr::Target:
4565 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004566 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004567 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004568}
Jack Carterd0bd6422013-04-18 00:41:53 +00004569
Jack Carterb4dbc172012-09-05 23:34:03 +00004570bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4571 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004572 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004573 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004574 if (ResTy == MatchOperand_Success) {
4575 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004576 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004577 StartLoc = Operand.getStartLoc();
4578 EndLoc = Operand.getEndLoc();
4579
4580 // AFAIK, we only support numeric registers and named GPR's in CFI
4581 // directives.
4582 // Don't worry about eating tokens before failing. Using an unrecognised
4583 // register is a parse error.
4584 if (Operand.isGPRAsmReg()) {
4585 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004586 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004587 }
4588
4589 return (RegNo == (unsigned)-1);
4590 }
4591
4592 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004593 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004594}
4595
Jack Carterb5cf5902013-04-17 00:18:04 +00004596bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00004597 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004598
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004599 if (isParenExpr)
4600 return getParser().parseParenExprOfDepth(0, Res, S);
4601 return getParser().parseExpression(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004602}
4603
Alex Bradbury58eba092016-11-01 16:32:05 +00004604OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004605MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004606 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004607 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004608 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004609 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004610 bool isParenExpr = false;
Alex Bradbury58eba092016-11-01 16:32:05 +00004611 OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004612 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004613 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004614
Jack Carterb5cf5902013-04-17 00:18:04 +00004615 if (getLexer().getKind() == AsmToken::LParen) {
4616 Parser.Lex();
4617 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004618 }
4619
Jack Carterb5cf5902013-04-17 00:18:04 +00004620 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004621 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004622 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004623
Jack Carterd0bd6422013-04-18 00:41:53 +00004624 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004625 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004626 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004627 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004628 SMLoc E =
4629 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004630 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004631 return MatchOperand_Success;
4632 }
4633 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004634 SMLoc E =
4635 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004636
Jack Carterd0bd6422013-04-18 00:41:53 +00004637 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004638 // "Base" will be managed by k_Memory.
Daniel Sandersc5537422016-07-27 13:49:44 +00004639 auto Base = MipsOperand::createGPRReg(
4640 0, "0", getContext().getRegisterInfo(), S, E, *this);
David Blaikie960ea3f2014-06-08 16:18:35 +00004641 Operands.push_back(
4642 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004643 return MatchOperand_Success;
4644 }
Simon Dardis858915f2016-10-18 15:17:17 +00004645 MCBinaryExpr::Opcode Opcode;
4646 // GAS and LLVM treat comparison operators different. GAS will generate -1
4647 // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is
4648 // highly unlikely to be found in a memory offset expression, we don't
4649 // handle them.
4650 switch (Tok.getKind()) {
4651 case AsmToken::Plus:
4652 Opcode = MCBinaryExpr::Add;
4653 Parser.Lex();
4654 break;
4655 case AsmToken::Minus:
4656 Opcode = MCBinaryExpr::Sub;
4657 Parser.Lex();
4658 break;
4659 case AsmToken::Star:
4660 Opcode = MCBinaryExpr::Mul;
4661 Parser.Lex();
4662 break;
4663 case AsmToken::Pipe:
4664 Opcode = MCBinaryExpr::Or;
4665 Parser.Lex();
4666 break;
4667 case AsmToken::Amp:
4668 Opcode = MCBinaryExpr::And;
4669 Parser.Lex();
4670 break;
4671 case AsmToken::LessLess:
4672 Opcode = MCBinaryExpr::Shl;
4673 Parser.Lex();
4674 break;
4675 case AsmToken::GreaterGreater:
4676 Opcode = MCBinaryExpr::LShr;
4677 Parser.Lex();
4678 break;
4679 case AsmToken::Caret:
4680 Opcode = MCBinaryExpr::Xor;
4681 Parser.Lex();
4682 break;
4683 case AsmToken::Slash:
4684 Opcode = MCBinaryExpr::Div;
4685 Parser.Lex();
4686 break;
4687 case AsmToken::Percent:
4688 Opcode = MCBinaryExpr::Mod;
4689 Parser.Lex();
4690 break;
4691 default:
4692 Error(Parser.getTok().getLoc(), "'(' or expression expected");
4693 return MatchOperand_ParseFail;
4694 }
4695 const MCExpr * NextExpr;
4696 if (getParser().parseExpression(NextExpr))
4697 return MatchOperand_ParseFail;
4698 IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004699 }
4700
Jack Carterd0bd6422013-04-18 00:41:53 +00004701 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004702 }
4703
Toma Tabacu13964452014-09-04 13:23:44 +00004704 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004705 if (Res != MatchOperand_Success)
4706 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004707
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004708 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004709 Error(Parser.getTok().getLoc(), "')' expected");
4710 return MatchOperand_ParseFail;
4711 }
4712
Jack Carter873c7242013-01-12 01:03:14 +00004713 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4714
Jack Carterd0bd6422013-04-18 00:41:53 +00004715 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004716
Craig Topper062a2ba2014-04-25 05:30:21 +00004717 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004718 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004719
Jack Carterd0bd6422013-04-18 00:41:53 +00004720 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004721 std::unique_ptr<MipsOperand> op(
4722 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004723 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004724 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004725 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004726 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004727 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4728 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004729 if (IdVal->evaluateAsAbsolute(Imm))
4730 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004731 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004732 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004733 getContext());
4734 }
4735
David Blaikie960ea3f2014-06-08 16:18:35 +00004736 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004737 return MatchOperand_Success;
4738}
4739
David Blaikie960ea3f2014-06-08 16:18:35 +00004740bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004741 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004742 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004743 if (Sym) {
4744 SMLoc S = Parser.getTok().getLoc();
4745 const MCExpr *Expr;
4746 if (Sym->isVariable())
4747 Expr = Sym->getVariableValue();
4748 else
4749 return false;
4750 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004751 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004752 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004753 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004754 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004755 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004756 if (ResTy == MatchOperand_Success) {
4757 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004758 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004759 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004760 llvm_unreachable("Should never ParseFail");
4761 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004762 }
Jack Carterd76b2372013-03-21 21:44:16 +00004763 }
4764 }
4765 return false;
4766}
Jack Carterd0bd6422013-04-18 00:41:53 +00004767
Alex Bradbury58eba092016-11-01 16:32:05 +00004768OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004769MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004770 StringRef Identifier,
4771 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004772 int Index = matchCPURegisterName(Identifier);
4773 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004774 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004775 Index, Identifier, getContext().getRegisterInfo(), S,
4776 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004777 return MatchOperand_Success;
4778 }
4779
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004780 Index = matchHWRegsRegisterName(Identifier);
4781 if (Index != -1) {
4782 Operands.push_back(MipsOperand::createHWRegsReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004783 Index, Identifier, getContext().getRegisterInfo(), S,
4784 getLexer().getLoc(), *this));
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004785 return MatchOperand_Success;
4786 }
4787
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004788 Index = matchFPURegisterName(Identifier);
4789 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004790 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004791 Index, Identifier, getContext().getRegisterInfo(), S,
4792 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004793 return MatchOperand_Success;
4794 }
4795
4796 Index = matchFCCRegisterName(Identifier);
4797 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004798 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004799 Index, Identifier, getContext().getRegisterInfo(), S,
4800 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004801 return MatchOperand_Success;
4802 }
4803
4804 Index = matchACRegisterName(Identifier);
4805 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004806 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004807 Index, Identifier, getContext().getRegisterInfo(), S,
4808 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004809 return MatchOperand_Success;
4810 }
4811
4812 Index = matchMSA128RegisterName(Identifier);
4813 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004814 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004815 Index, Identifier, getContext().getRegisterInfo(), S,
4816 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004817 return MatchOperand_Success;
4818 }
4819
4820 Index = matchMSA128CtrlRegisterName(Identifier);
4821 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004822 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004823 Index, Identifier, getContext().getRegisterInfo(), S,
4824 getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004825 return MatchOperand_Success;
4826 }
4827
4828 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004829}
4830
Alex Bradbury58eba092016-11-01 16:32:05 +00004831OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004832MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004833 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004834 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004835
4836 if (Token.is(AsmToken::Identifier)) {
4837 DEBUG(dbgs() << ".. identifier\n");
4838 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004839 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004840 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004841 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004842 } else if (Token.is(AsmToken::Integer)) {
4843 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004844 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersc5537422016-07-27 13:49:44 +00004845 Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S,
4846 Token.getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004847 return MatchOperand_Success;
4848 }
4849
4850 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4851
4852 return MatchOperand_NoMatch;
4853}
4854
Alex Bradbury58eba092016-11-01 16:32:05 +00004855OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004856MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004857 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004858 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004859
4860 auto Token = Parser.getTok();
4861
4862 SMLoc S = Token.getLoc();
4863
4864 if (Token.isNot(AsmToken::Dollar)) {
4865 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4866 if (Token.is(AsmToken::Identifier)) {
4867 if (searchSymbolAlias(Operands))
4868 return MatchOperand_Success;
4869 }
4870 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4871 return MatchOperand_NoMatch;
4872 }
4873 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004874
Toma Tabacu13964452014-09-04 13:23:44 +00004875 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004876 if (ResTy == MatchOperand_Success) {
4877 Parser.Lex(); // $
4878 Parser.Lex(); // identifier
4879 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004880 return ResTy;
4881}
4882
Alex Bradbury58eba092016-11-01 16:32:05 +00004883OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004884MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004885 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004886 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004887
4888 SMLoc S = getLexer().getLoc();
4889
Daniel Sanderscae9aee2016-08-08 09:33:14 +00004890 // Registers are a valid target and have priority over symbols.
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004891 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sanderscae9aee2016-08-08 09:33:14 +00004892 if (ResTy != MatchOperand_NoMatch)
4893 return ResTy;
4894
Daniel Sanders3feeb9c2016-08-08 11:50:25 +00004895 // Integers and expressions are acceptable
Daniel Sandersffd84362014-04-01 10:41:48 +00004896 const MCExpr *Expr = nullptr;
4897 if (Parser.parseExpression(Expr)) {
4898 // We have no way of knowing if a symbol was consumed so we must ParseFail
4899 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004900 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004901 Operands.push_back(
4902 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004903 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004904}
4905
Alex Bradbury58eba092016-11-01 16:32:05 +00004906OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004907MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004908 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004909 const MCExpr *IdVal;
4910 // If the first token is '$' we may have register operand.
4911 if (Parser.getTok().is(AsmToken::Dollar))
4912 return MatchOperand_NoMatch;
4913 SMLoc S = Parser.getTok().getLoc();
4914 if (getParser().parseExpression(IdVal))
4915 return MatchOperand_ParseFail;
4916 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004917 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004918 int64_t Val = MCE->getValue();
4919 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4920 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004921 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004922 return MatchOperand_Success;
4923}
4924
Alex Bradbury58eba092016-11-01 16:32:05 +00004925OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004926MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4927 MCAsmParser &Parser = getParser();
4928 SmallVector<unsigned, 10> Regs;
4929 unsigned RegNo;
4930 unsigned PrevReg = Mips::NoRegister;
4931 bool RegRange = false;
4932 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4933
4934 if (Parser.getTok().isNot(AsmToken::Dollar))
4935 return MatchOperand_ParseFail;
4936
4937 SMLoc S = Parser.getTok().getLoc();
4938 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4939 SMLoc E = getLexer().getLoc();
4940 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4941 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4942 if (RegRange) {
4943 // Remove last register operand because registers from register range
4944 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004945 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4946 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004947 Regs.push_back(RegNo);
4948 } else {
4949 unsigned TmpReg = PrevReg + 1;
4950 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004951 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4952 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4953 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004954 Error(E, "invalid register operand");
4955 return MatchOperand_ParseFail;
4956 }
4957
4958 PrevReg = TmpReg;
4959 Regs.push_back(TmpReg++);
4960 }
4961 }
4962
4963 RegRange = false;
4964 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004965 if ((PrevReg == Mips::NoRegister) &&
4966 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4967 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004968 Error(E, "$16 or $31 expected");
4969 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004970 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4971 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4972 !isGP64bit()) ||
4973 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4974 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4975 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004976 Error(E, "invalid register operand");
4977 return MatchOperand_ParseFail;
4978 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004979 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4980 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4981 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004982 Error(E, "consecutive register numbers expected");
4983 return MatchOperand_ParseFail;
4984 }
4985
4986 Regs.push_back(RegNo);
4987 }
4988
4989 if (Parser.getTok().is(AsmToken::Minus))
4990 RegRange = true;
4991
4992 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4993 !Parser.getTok().isNot(AsmToken::Comma)) {
4994 Error(E, "',' or '-' expected");
4995 return MatchOperand_ParseFail;
4996 }
4997
4998 Lex(); // Consume comma or minus
4999 if (Parser.getTok().isNot(AsmToken::Dollar))
5000 break;
5001
5002 PrevReg = RegNo;
5003 }
5004
5005 SMLoc E = Parser.getTok().getLoc();
5006 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5007 parseMemOperand(Operands);
5008 return MatchOperand_Success;
5009}
5010
Alex Bradbury58eba092016-11-01 16:32:05 +00005011OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005012MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
5013 MCAsmParser &Parser = getParser();
5014
5015 SMLoc S = Parser.getTok().getLoc();
5016 if (parseAnyRegister(Operands) != MatchOperand_Success)
5017 return MatchOperand_ParseFail;
5018
5019 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00005020 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00005021
Benjamin Kramer2b68d152016-05-09 10:31:17 +00005022 Operands.pop_back();
5023 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00005024 return MatchOperand_Success;
5025}
5026
Alex Bradbury58eba092016-11-01 16:32:05 +00005027OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +00005028MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
5029 MCAsmParser &Parser = getParser();
5030 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
5031 SmallVector<unsigned, 10> Regs;
5032
5033 if (Parser.getTok().isNot(AsmToken::Dollar))
5034 return MatchOperand_ParseFail;
5035
5036 SMLoc S = Parser.getTok().getLoc();
5037
5038 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5039 return MatchOperand_ParseFail;
5040
5041 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5042 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5043 Regs.push_back(RegNo);
5044
5045 SMLoc E = Parser.getTok().getLoc();
5046 if (Parser.getTok().isNot(AsmToken::Comma)) {
5047 Error(E, "',' expected");
5048 return MatchOperand_ParseFail;
5049 }
5050
5051 // Remove comma.
5052 Parser.Lex();
5053
5054 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
5055 return MatchOperand_ParseFail;
5056
5057 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
5058 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
5059 Regs.push_back(RegNo);
5060
5061 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
5062
5063 return MatchOperand_Success;
5064}
5065
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005066/// Sometimes (i.e. load/stores) the operand may be followed immediately by
5067/// either this.
5068/// ::= '(', register, ')'
5069/// handle it before we iterate so we don't get tripped up by the lack of
5070/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005071bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005072 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005073 if (getLexer().is(AsmToken::LParen)) {
5074 Operands.push_back(
5075 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
5076 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005077 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005078 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005079 return Error(Loc, "unexpected token in argument list");
5080 }
5081 if (Parser.getTok().isNot(AsmToken::RParen)) {
5082 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005083 return Error(Loc, "unexpected token, expected ')'");
5084 }
5085 Operands.push_back(
5086 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
5087 Parser.Lex();
5088 }
5089 return false;
5090}
5091
5092/// Sometimes (i.e. in MSA) the operand may be followed immediately by
5093/// either one of these.
5094/// ::= '[', register, ']'
5095/// ::= '[', integer, ']'
5096/// handle it before we iterate so we don't get tripped up by the lack of
5097/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00005098bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00005099 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005100 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005101 if (getLexer().is(AsmToken::LBrac)) {
5102 Operands.push_back(
5103 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
5104 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00005105 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005106 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005107 return Error(Loc, "unexpected token in argument list");
5108 }
5109 if (Parser.getTok().isNot(AsmToken::RBrac)) {
5110 SMLoc Loc = getLexer().getLoc();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005111 return Error(Loc, "unexpected token, expected ']'");
5112 }
5113 Operands.push_back(
5114 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
5115 Parser.Lex();
5116 }
5117 return false;
5118}
5119
David Blaikie960ea3f2014-06-08 16:18:35 +00005120bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
5121 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005122 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005123 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005124
5125 // We have reached first instruction, module directive are now forbidden.
5126 getTargetStreamer().forbidModuleDirective();
5127
Vladimir Medic74593e62013-07-17 15:00:42 +00005128 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00005129 if (!mnemonicIsValid(Name, 0)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005130 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00005131 }
Vladimir Medic64828a12013-07-16 10:07:14 +00005132 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005133 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00005134
5135 // Read the remaining operands.
5136 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5137 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005138 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005139 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005140 return Error(Loc, "unexpected token in argument list");
5141 }
Toma Tabacu13964452014-09-04 13:23:44 +00005142 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005143 return true;
5144 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00005145
Jack Carterd0bd6422013-04-18 00:41:53 +00005146 while (getLexer().is(AsmToken::Comma)) {
5147 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00005148 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00005149 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00005150 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005151 return Error(Loc, "unexpected token in argument list");
5152 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005153 // Parse bracket and parenthesis suffixes before we iterate
5154 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00005155 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005156 return true;
5157 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00005158 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00005159 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00005160 }
5161 }
Jack Carterb4dbc172012-09-05 23:34:03 +00005162 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5163 SMLoc Loc = getLexer().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00005164 return Error(Loc, "unexpected token in argument list");
5165 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005166 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00005167 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00005168}
5169
Nirav Dave996fc132016-05-05 14:15:46 +00005170// FIXME: Given that these have the same name, these should both be
5171// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005172bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00005173 SMLoc Loc = getLexer().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00005174 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00005175}
5176
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005177bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005178 return Error(Loc, ErrorMsg);
5179}
5180
Jack Carter0b744b32012-10-04 02:29:46 +00005181bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005182 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005183 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00005184
5185 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00005186 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00005187
5188 Parser.Lex(); // Eat "noat".
5189
Jack Carterd0bd6422013-04-18 00:41:53 +00005190 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005191 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005192 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005193 return false;
5194 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005195
5196 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005197 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005198 return false;
5199}
Jack Carterd0bd6422013-04-18 00:41:53 +00005200
Jack Carter0b744b32012-10-04 02:29:46 +00005201bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00005202 // Line can be: ".set at", which sets $at to $1
5203 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00005204 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00005205 Parser.Lex(); // Eat "at".
5206
Jack Carter0b744b32012-10-04 02:29:46 +00005207 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005208 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00005209 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00005210
5211 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00005212 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005213 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00005214 }
5215
5216 if (getLexer().isNot(AsmToken::Equal)) {
5217 reportParseError("unexpected token, expected equals sign");
5218 return false;
5219 }
5220 Parser.Lex(); // Eat "=".
5221
5222 if (getLexer().isNot(AsmToken::Dollar)) {
5223 if (getLexer().is(AsmToken::EndOfStatement)) {
5224 reportParseError("no register specified");
5225 return false;
5226 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00005227 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00005228 return false;
5229 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005230 }
5231 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00005232
Toma Tabacu16a74492015-02-13 10:30:57 +00005233 // Find out what "reg" is.
5234 unsigned AtRegNo;
5235 const AsmToken &Reg = Parser.getTok();
5236 if (Reg.is(AsmToken::Identifier)) {
5237 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
5238 } else if (Reg.is(AsmToken::Integer)) {
5239 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00005240 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00005241 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00005242 return false;
5243 }
Toma Tabacu16a74492015-02-13 10:30:57 +00005244
5245 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00005246 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00005247 reportParseError("invalid register");
5248 return false;
5249 }
5250 Parser.Lex(); // Eat "reg".
5251
5252 // If this is not the end of the statement, report an error.
5253 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5254 reportParseError("unexpected token, expected end of statement");
5255 return false;
5256 }
5257
5258 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
5259
5260 Parser.Lex(); // Consume the EndOfStatement.
5261 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005262}
5263
5264bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005265 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005266 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005267 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005268 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005269 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005270 return false;
5271 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005272 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00005273 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005274 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005275 return false;
5276}
5277
5278bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005279 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005280 Parser.Lex();
5281 // If this is not the end of the statement, report an error.
5282 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005283 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005284 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00005285 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005286 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00005287 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00005288 Parser.Lex(); // Consume the EndOfStatement.
5289 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005290}
5291
5292bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005293 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00005294 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00005295 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00005296 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005297 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005298 return false;
5299 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005300 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005301 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005302 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005303 return false;
5304}
5305
5306bool MipsAsmParser::parseSetNoMacroDirective() {
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 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005315 reportParseError("`noreorder' must be set before `nomacro'");
5316 return false;
5317 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005318 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005319 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005320 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005321 return false;
5322}
Jack Carterd76b2372013-03-21 21:44:16 +00005323
Daniel Sanders44934432014-08-07 12:03:36 +00005324bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005325 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005326 Parser.Lex();
5327
5328 // If this is not the end of the statement, report an error.
5329 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005330 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005331
5332 setFeatureBits(Mips::FeatureMSA, "msa");
5333 getTargetStreamer().emitDirectiveSetMsa();
5334 return false;
5335}
5336
5337bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005338 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005339 Parser.Lex();
5340
5341 // If this is not the end of the statement, report an error.
5342 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005343 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005344
5345 clearFeatureBits(Mips::FeatureMSA, "msa");
5346 getTargetStreamer().emitDirectiveSetNoMsa();
5347 return false;
5348}
5349
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005350bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005351 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005352 Parser.Lex(); // Eat "nodsp".
5353
5354 // If this is not the end of the statement, report an error.
5355 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5356 reportParseError("unexpected token, expected end of statement");
5357 return false;
5358 }
5359
5360 clearFeatureBits(Mips::FeatureDSP, "dsp");
5361 getTargetStreamer().emitDirectiveSetNoDsp();
5362 return false;
5363}
5364
Toma Tabacucc2502d2014-11-04 17:18:07 +00005365bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005366 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005367 Parser.Lex(); // Eat "mips16".
5368
Jack Carter39536722014-01-22 23:08:42 +00005369 // If this is not the end of the statement, report an error.
5370 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005371 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005372 return false;
5373 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005374
5375 setFeatureBits(Mips::FeatureMips16, "mips16");
5376 getTargetStreamer().emitDirectiveSetMips16();
5377 Parser.Lex(); // Consume the EndOfStatement.
5378 return false;
5379}
5380
5381bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005382 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005383 Parser.Lex(); // Eat "nomips16".
5384
5385 // If this is not the end of the statement, report an error.
5386 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5387 reportParseError("unexpected token, expected end of statement");
5388 return false;
5389 }
5390
5391 clearFeatureBits(Mips::FeatureMips16, "mips16");
5392 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005393 Parser.Lex(); // Consume the EndOfStatement.
5394 return false;
5395}
5396
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005397bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005398 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005399 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005400 // Line can be: .set fp=32
5401 // .set fp=xx
5402 // .set fp=64
5403 Parser.Lex(); // Eat fp token
5404 AsmToken Tok = Parser.getTok();
5405 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005406 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005407 return false;
5408 }
5409 Parser.Lex(); // Eat '=' token.
5410 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005411
5412 if (!parseFpABIValue(FpAbiVal, ".set"))
5413 return false;
5414
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005415 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005416 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005417 return false;
5418 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005419 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005420 Parser.Lex(); // Consume the EndOfStatement.
5421 return false;
5422}
5423
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005424bool MipsAsmParser::parseSetOddSPRegDirective() {
5425 MCAsmParser &Parser = getParser();
5426
5427 Parser.Lex(); // Eat "oddspreg".
5428 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5429 reportParseError("unexpected token, expected end of statement");
5430 return false;
5431 }
5432
5433 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5434 getTargetStreamer().emitDirectiveSetOddSPReg();
5435 return false;
5436}
5437
5438bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5439 MCAsmParser &Parser = getParser();
5440
5441 Parser.Lex(); // Eat "nooddspreg".
5442 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5443 reportParseError("unexpected token, expected end of statement");
5444 return false;
5445 }
5446
5447 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5448 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5449 return false;
5450}
5451
Toma Tabacu9db22db2014-09-09 10:15:38 +00005452bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005453 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005454 SMLoc Loc = getLexer().getLoc();
5455
5456 Parser.Lex();
5457 if (getLexer().isNot(AsmToken::EndOfStatement))
5458 return reportParseError("unexpected token, expected end of statement");
5459
5460 // Always keep an element on the options "stack" to prevent the user
5461 // from changing the initial options. This is how we remember them.
5462 if (AssemblerOptions.size() == 2)
5463 return reportParseError(Loc, ".set pop with no .set push");
5464
Akira Hatanakab11ef082015-11-14 06:35:56 +00005465 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005466 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005467 setAvailableFeatures(
5468 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5469 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005470
5471 getTargetStreamer().emitDirectiveSetPop();
5472 return false;
5473}
5474
5475bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005476 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005477 Parser.Lex();
5478 if (getLexer().isNot(AsmToken::EndOfStatement))
5479 return reportParseError("unexpected token, expected end of statement");
5480
5481 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005482 AssemblerOptions.push_back(
5483 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005484
5485 getTargetStreamer().emitDirectiveSetPush();
5486 return false;
5487}
5488
Toma Tabacu29696502015-06-02 09:48:04 +00005489bool MipsAsmParser::parseSetSoftFloatDirective() {
5490 MCAsmParser &Parser = getParser();
5491 Parser.Lex();
5492 if (getLexer().isNot(AsmToken::EndOfStatement))
5493 return reportParseError("unexpected token, expected end of statement");
5494
5495 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5496 getTargetStreamer().emitDirectiveSetSoftFloat();
5497 return false;
5498}
5499
5500bool MipsAsmParser::parseSetHardFloatDirective() {
5501 MCAsmParser &Parser = getParser();
5502 Parser.Lex();
5503 if (getLexer().isNot(AsmToken::EndOfStatement))
5504 return reportParseError("unexpected token, expected end of statement");
5505
5506 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5507 getTargetStreamer().emitDirectiveSetHardFloat();
5508 return false;
5509}
5510
Jack Carterd76b2372013-03-21 21:44:16 +00005511bool MipsAsmParser::parseSetAssignment() {
5512 StringRef Name;
5513 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005514 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005515
5516 if (Parser.parseIdentifier(Name))
5517 reportParseError("expected identifier after .set");
5518
5519 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005520 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005521 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005522
Jack Carter3b2c96e2014-01-22 23:31:38 +00005523 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005524 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005525
Jim Grosbach6f482002015-05-18 18:43:14 +00005526 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005527 Sym->setVariableValue(Value);
5528
5529 return false;
5530}
Jack Carterd0bd6422013-04-18 00:41:53 +00005531
Toma Tabacu26647792014-09-09 12:52:14 +00005532bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005533 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005534 Parser.Lex();
5535 if (getLexer().isNot(AsmToken::EndOfStatement))
5536 return reportParseError("unexpected token, expected end of statement");
5537
5538 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005539 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005540 setAvailableFeatures(
5541 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5542 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005543 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5544
5545 getTargetStreamer().emitDirectiveSetMips0();
5546 return false;
5547}
5548
Toma Tabacu85618b32014-08-19 14:22:52 +00005549bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005550 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005551 Parser.Lex();
5552 if (getLexer().isNot(AsmToken::Equal))
5553 return reportParseError("unexpected token, expected equals sign");
5554
5555 Parser.Lex();
5556 StringRef Arch;
5557 if (Parser.parseIdentifier(Arch))
5558 return reportParseError("expected arch identifier");
5559
5560 StringRef ArchFeatureName =
5561 StringSwitch<StringRef>(Arch)
5562 .Case("mips1", "mips1")
5563 .Case("mips2", "mips2")
5564 .Case("mips3", "mips3")
5565 .Case("mips4", "mips4")
5566 .Case("mips5", "mips5")
5567 .Case("mips32", "mips32")
5568 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005569 .Case("mips32r3", "mips32r3")
5570 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005571 .Case("mips32r6", "mips32r6")
5572 .Case("mips64", "mips64")
5573 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005574 .Case("mips64r3", "mips64r3")
5575 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005576 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005577 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005578 .Case("r4000", "mips3") // This is an implementation of Mips3.
5579 .Default("");
5580
5581 if (ArchFeatureName.empty())
5582 return reportParseError("unsupported architecture");
5583
5584 selectArch(ArchFeatureName);
5585 getTargetStreamer().emitDirectiveSetArch(Arch);
5586 return false;
5587}
5588
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005589bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005590 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005591 Parser.Lex();
5592 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005593 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005594
Matheus Almeida2852af82014-04-22 10:15:54 +00005595 switch (Feature) {
5596 default:
5597 llvm_unreachable("Unimplemented feature");
5598 case Mips::FeatureDSP:
5599 setFeatureBits(Mips::FeatureDSP, "dsp");
5600 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005601 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005602 case Mips::FeatureMicroMips:
Daniel Sanderscda908a2016-05-16 09:10:13 +00005603 setFeatureBits(Mips::FeatureMicroMips, "micromips");
Matheus Almeida2852af82014-04-22 10:15:54 +00005604 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005605 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005606 case Mips::FeatureMips1:
5607 selectArch("mips1");
5608 getTargetStreamer().emitDirectiveSetMips1();
5609 break;
5610 case Mips::FeatureMips2:
5611 selectArch("mips2");
5612 getTargetStreamer().emitDirectiveSetMips2();
5613 break;
5614 case Mips::FeatureMips3:
5615 selectArch("mips3");
5616 getTargetStreamer().emitDirectiveSetMips3();
5617 break;
5618 case Mips::FeatureMips4:
5619 selectArch("mips4");
5620 getTargetStreamer().emitDirectiveSetMips4();
5621 break;
5622 case Mips::FeatureMips5:
5623 selectArch("mips5");
5624 getTargetStreamer().emitDirectiveSetMips5();
5625 break;
5626 case Mips::FeatureMips32:
5627 selectArch("mips32");
5628 getTargetStreamer().emitDirectiveSetMips32();
5629 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005630 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005631 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005632 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005633 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005634 case Mips::FeatureMips32r3:
5635 selectArch("mips32r3");
5636 getTargetStreamer().emitDirectiveSetMips32R3();
5637 break;
5638 case Mips::FeatureMips32r5:
5639 selectArch("mips32r5");
5640 getTargetStreamer().emitDirectiveSetMips32R5();
5641 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005642 case Mips::FeatureMips32r6:
5643 selectArch("mips32r6");
5644 getTargetStreamer().emitDirectiveSetMips32R6();
5645 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005646 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005647 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005648 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005649 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005650 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005651 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005652 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005653 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005654 case Mips::FeatureMips64r3:
5655 selectArch("mips64r3");
5656 getTargetStreamer().emitDirectiveSetMips64R3();
5657 break;
5658 case Mips::FeatureMips64r5:
5659 selectArch("mips64r5");
5660 getTargetStreamer().emitDirectiveSetMips64R5();
5661 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005662 case Mips::FeatureMips64r6:
5663 selectArch("mips64r6");
5664 getTargetStreamer().emitDirectiveSetMips64R6();
5665 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005666 }
5667 return false;
5668}
5669
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005670bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005671 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005672 if (getLexer().isNot(AsmToken::Comma)) {
5673 SMLoc Loc = getLexer().getLoc();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005674 return Error(Loc, ErrorStr);
5675 }
5676
Matheus Almeida2852af82014-04-22 10:15:54 +00005677 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005678 return true;
5679}
5680
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005681// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5682// In this class, it is only used for .cprestore.
5683// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5684// MipsTargetELFStreamer and MipsAsmParser.
5685bool MipsAsmParser::isPicAndNotNxxAbi() {
5686 return inPicMode() && !(isABI_N32() || isABI_N64());
5687}
5688
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005689bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005690 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005691 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005692
Toma Tabacudde4c462014-11-06 10:02:45 +00005693 if (inMips16Mode()) {
5694 reportParseError(".cpload is not supported in Mips16 mode");
5695 return false;
5696 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005697
David Blaikie960ea3f2014-06-08 16:18:35 +00005698 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005699 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005700 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5701 reportParseError("expected register containing function address");
5702 return false;
5703 }
5704
David Blaikie960ea3f2014-06-08 16:18:35 +00005705 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5706 if (!RegOpnd.isGPRAsmReg()) {
5707 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005708 return false;
5709 }
5710
Toma Tabacudde4c462014-11-06 10:02:45 +00005711 // If this is not the end of the statement, report an error.
5712 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5713 reportParseError("unexpected token, expected end of statement");
5714 return false;
5715 }
5716
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005717 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005718 return false;
5719}
5720
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005721bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5722 MCAsmParser &Parser = getParser();
5723
5724 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5725 // is used in non-PIC mode.
5726
5727 if (inMips16Mode()) {
5728 reportParseError(".cprestore is not supported in Mips16 mode");
5729 return false;
5730 }
5731
5732 // Get the stack offset value.
5733 const MCExpr *StackOffset;
5734 int64_t StackOffsetVal;
5735 if (Parser.parseExpression(StackOffset)) {
5736 reportParseError("expected stack offset value");
5737 return false;
5738 }
5739
5740 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5741 reportParseError("stack offset is not an absolute expression");
5742 return false;
5743 }
5744
5745 if (StackOffsetVal < 0) {
5746 Warning(Loc, ".cprestore with negative stack offset has no effect");
5747 IsCpRestoreSet = false;
5748 } else {
5749 IsCpRestoreSet = true;
5750 CpRestoreOffset = StackOffsetVal;
5751 }
5752
5753 // 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
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005759 if (!getTargetStreamer().emitDirectiveCpRestore(
5760 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005761 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005762 Parser.Lex(); // Consume the EndOfStatement.
5763 return false;
5764}
5765
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005766bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005767 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005768 unsigned FuncReg;
5769 unsigned Save;
5770 bool SaveIsReg = true;
5771
Matheus Almeida7e815762014-06-18 13:08:59 +00005772 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005773 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005774 if (ResTy == MatchOperand_NoMatch) {
5775 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005776 return false;
5777 }
5778
5779 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5780 if (!FuncRegOpnd.isGPRAsmReg()) {
5781 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005782 return false;
5783 }
5784
5785 FuncReg = FuncRegOpnd.getGPR32Reg();
5786 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005787
Toma Tabacu65f10572014-09-16 15:00:52 +00005788 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005789 return true;
5790
Toma Tabacu13964452014-09-04 13:23:44 +00005791 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005792 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005793 const MCExpr *OffsetExpr;
5794 int64_t OffsetVal;
5795 SMLoc ExprLoc = getLexer().getLoc();
5796
5797 if (Parser.parseExpression(OffsetExpr) ||
5798 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5799 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005800 return false;
5801 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005802
5803 Save = OffsetVal;
5804 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005805 } else {
5806 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5807 if (!SaveOpnd.isGPRAsmReg()) {
5808 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
Matheus Almeida7e815762014-06-18 13:08:59 +00005809 return false;
5810 }
5811 Save = SaveOpnd.getGPR32Reg();
5812 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005813
Toma Tabacu65f10572014-09-16 15:00:52 +00005814 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005815 return true;
5816
Toma Tabacu8874eac2015-02-18 13:46:53 +00005817 const MCExpr *Expr;
5818 if (Parser.parseExpression(Expr)) {
5819 reportParseError("expected expression");
5820 return false;
5821 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005822
Toma Tabacu8874eac2015-02-18 13:46:53 +00005823 if (Expr->getKind() != MCExpr::SymbolRef) {
5824 reportParseError("expected symbol");
5825 return false;
5826 }
5827 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5828
Daniel Sandersf173dda2015-09-22 10:50:09 +00005829 CpSaveLocation = Save;
5830 CpSaveLocationIsRegister = SaveIsReg;
5831
Toma Tabacu8874eac2015-02-18 13:46:53 +00005832 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5833 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005834 return false;
5835}
5836
Daniel Sandersf173dda2015-09-22 10:50:09 +00005837bool MipsAsmParser::parseDirectiveCPReturn() {
5838 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5839 CpSaveLocationIsRegister);
5840 return false;
5841}
5842
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005843bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005844 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005845 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5846 const AsmToken &Tok = Parser.getTok();
5847
5848 if (Tok.getString() == "2008") {
5849 Parser.Lex();
5850 getTargetStreamer().emitDirectiveNaN2008();
5851 return false;
5852 } else if (Tok.getString() == "legacy") {
5853 Parser.Lex();
5854 getTargetStreamer().emitDirectiveNaNLegacy();
5855 return false;
5856 }
5857 }
5858 // If we don't recognize the option passed to the .nan
5859 // directive (e.g. no option or unknown option), emit an error.
5860 reportParseError("invalid option in .nan directive");
5861 return false;
5862}
5863
Jack Carter0b744b32012-10-04 02:29:46 +00005864bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005865 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005866 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005867 const AsmToken &Tok = Parser.getTok();
5868
5869 if (Tok.getString() == "noat") {
5870 return parseSetNoAtDirective();
5871 } else if (Tok.getString() == "at") {
5872 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005873 } else if (Tok.getString() == "arch") {
5874 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005875 } else if (Tok.getString() == "fp") {
5876 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005877 } else if (Tok.getString() == "oddspreg") {
5878 return parseSetOddSPRegDirective();
5879 } else if (Tok.getString() == "nooddspreg") {
5880 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005881 } else if (Tok.getString() == "pop") {
5882 return parseSetPopDirective();
5883 } else if (Tok.getString() == "push") {
5884 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005885 } else if (Tok.getString() == "reorder") {
5886 return parseSetReorderDirective();
5887 } else if (Tok.getString() == "noreorder") {
5888 return parseSetNoReorderDirective();
5889 } else if (Tok.getString() == "macro") {
5890 return parseSetMacroDirective();
5891 } else if (Tok.getString() == "nomacro") {
5892 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005893 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005894 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005895 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005896 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005897 } else if (Tok.getString() == "nomicromips") {
Daniel Sanderscda908a2016-05-16 09:10:13 +00005898 clearFeatureBits(Mips::FeatureMicroMips, "micromips");
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005899 getTargetStreamer().emitDirectiveSetNoMicroMips();
5900 Parser.eatToEndOfStatement();
5901 return false;
5902 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005903 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005904 } else if (Tok.getString() == "mips0") {
5905 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005906 } else if (Tok.getString() == "mips1") {
5907 return parseSetFeature(Mips::FeatureMips1);
5908 } else if (Tok.getString() == "mips2") {
5909 return parseSetFeature(Mips::FeatureMips2);
5910 } else if (Tok.getString() == "mips3") {
5911 return parseSetFeature(Mips::FeatureMips3);
5912 } else if (Tok.getString() == "mips4") {
5913 return parseSetFeature(Mips::FeatureMips4);
5914 } else if (Tok.getString() == "mips5") {
5915 return parseSetFeature(Mips::FeatureMips5);
5916 } else if (Tok.getString() == "mips32") {
5917 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005918 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005919 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005920 } else if (Tok.getString() == "mips32r3") {
5921 return parseSetFeature(Mips::FeatureMips32r3);
5922 } else if (Tok.getString() == "mips32r5") {
5923 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005924 } else if (Tok.getString() == "mips32r6") {
5925 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005926 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005927 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005928 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005929 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005930 } else if (Tok.getString() == "mips64r3") {
5931 return parseSetFeature(Mips::FeatureMips64r3);
5932 } else if (Tok.getString() == "mips64r5") {
5933 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005934 } else if (Tok.getString() == "mips64r6") {
5935 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005936 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005937 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005938 } else if (Tok.getString() == "nodsp") {
5939 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005940 } else if (Tok.getString() == "msa") {
5941 return parseSetMsaDirective();
5942 } else if (Tok.getString() == "nomsa") {
5943 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005944 } else if (Tok.getString() == "softfloat") {
5945 return parseSetSoftFloatDirective();
5946 } else if (Tok.getString() == "hardfloat") {
5947 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005948 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005949 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005950 parseSetAssignment();
5951 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005952 }
Jack Carter07c818d2013-01-25 01:31:34 +00005953
Jack Carter0b744b32012-10-04 02:29:46 +00005954 return true;
5955}
5956
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005957/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005958/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005959bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005960 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005961 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5962 for (;;) {
5963 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005964 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005965 return true;
5966
5967 getParser().getStreamer().EmitValue(Value, Size);
5968
5969 if (getLexer().is(AsmToken::EndOfStatement))
5970 break;
5971
Jack Carter07c818d2013-01-25 01:31:34 +00005972 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005973 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005974 Parser.Lex();
5975 }
5976 }
5977
5978 Parser.Lex();
5979 return false;
5980}
5981
Vladimir Medic4c299852013-11-06 11:27:05 +00005982/// parseDirectiveGpWord
5983/// ::= .gpword local_sym
5984bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005985 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005986 const MCExpr *Value;
5987 // EmitGPRel32Value requires an expression, so we are using base class
5988 // method to evaluate the expression.
5989 if (getParser().parseExpression(Value))
5990 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005991 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005992
Vladimir Medice10c1122013-11-13 13:18:04 +00005993 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005994 return Error(getLexer().getLoc(),
5995 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005996 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005997 return false;
5998}
5999
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006000/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00006001/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006002bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006003 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006004 const MCExpr *Value;
6005 // EmitGPRel64Value requires an expression, so we are using base class
6006 // method to evaluate the expression.
6007 if (getParser().parseExpression(Value))
6008 return true;
6009 getParser().getStreamer().EmitGPRel64Value(Value);
6010
6011 if (getLexer().isNot(AsmToken::EndOfStatement))
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006012 return Error(getLexer().getLoc(),
6013 "unexpected token, expected end of statement");
6014 Parser.Lex(); // Eat EndOfStatement token.
6015 return false;
6016}
6017
6018/// parseDirectiveDtpRelWord
6019/// ::= .dtprelword tls_sym
6020bool MipsAsmParser::parseDirectiveDtpRelWord() {
6021 MCAsmParser &Parser = getParser();
6022 const MCExpr *Value;
6023 // EmitDTPRel32Value requires an expression, so we are using base class
6024 // method to evaluate the expression.
6025 if (getParser().parseExpression(Value))
6026 return true;
6027 getParser().getStreamer().EmitDTPRel32Value(Value);
6028
6029 if (getLexer().isNot(AsmToken::EndOfStatement))
6030 return Error(getLexer().getLoc(),
6031 "unexpected token, expected end of statement");
6032 Parser.Lex(); // Eat EndOfStatement token.
6033 return false;
6034}
6035
6036/// parseDirectiveDtpRelDWord
6037/// ::= .dtpreldword tls_sym
6038bool MipsAsmParser::parseDirectiveDtpRelDWord() {
6039 MCAsmParser &Parser = getParser();
6040 const MCExpr *Value;
6041 // EmitDTPRel64Value requires an expression, so we are using base class
6042 // method to evaluate the expression.
6043 if (getParser().parseExpression(Value))
6044 return true;
6045 getParser().getStreamer().EmitDTPRel64Value(Value);
6046
6047 if (getLexer().isNot(AsmToken::EndOfStatement))
6048 return Error(getLexer().getLoc(),
6049 "unexpected token, expected end of statement");
6050 Parser.Lex(); // Eat EndOfStatement token.
6051 return false;
6052}
6053
6054/// parseDirectiveTpRelWord
6055/// ::= .tprelword tls_sym
6056bool MipsAsmParser::parseDirectiveTpRelWord() {
6057 MCAsmParser &Parser = getParser();
6058 const MCExpr *Value;
6059 // EmitTPRel32Value requires an expression, so we are using base class
6060 // method to evaluate the expression.
6061 if (getParser().parseExpression(Value))
6062 return true;
6063 getParser().getStreamer().EmitTPRel32Value(Value);
6064
6065 if (getLexer().isNot(AsmToken::EndOfStatement))
6066 return Error(getLexer().getLoc(),
6067 "unexpected token, expected end of statement");
6068 Parser.Lex(); // Eat EndOfStatement token.
6069 return false;
6070}
6071
6072/// parseDirectiveTpRelDWord
6073/// ::= .tpreldword tls_sym
6074bool MipsAsmParser::parseDirectiveTpRelDWord() {
6075 MCAsmParser &Parser = getParser();
6076 const MCExpr *Value;
6077 // EmitTPRel64Value requires an expression, so we are using base class
6078 // method to evaluate the expression.
6079 if (getParser().parseExpression(Value))
6080 return true;
6081 getParser().getStreamer().EmitTPRel64Value(Value);
6082
6083 if (getLexer().isNot(AsmToken::EndOfStatement))
6084 return Error(getLexer().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00006085 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00006086 Parser.Lex(); // Eat EndOfStatement token.
6087 return false;
6088}
6089
Jack Carter0cd3c192014-01-06 23:27:31 +00006090bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006091 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00006092 // Get the option token.
6093 AsmToken Tok = Parser.getTok();
6094 // At the moment only identifiers are supported.
6095 if (Tok.isNot(AsmToken::Identifier)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006096 return Error(Parser.getTok().getLoc(),
6097 "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00006098 }
6099
6100 StringRef Option = Tok.getIdentifier();
6101
6102 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006103 // MipsAsmParser needs to know if the current PIC mode changes.
6104 IsPicEnabled = false;
6105
Jack Carter0cd3c192014-01-06 23:27:31 +00006106 getTargetStreamer().emitDirectiveOptionPic0();
6107 Parser.Lex();
6108 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006109 return Error(Parser.getTok().getLoc(),
6110 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006111 }
6112 return false;
6113 }
6114
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006115 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00006116 // MipsAsmParser needs to know if the current PIC mode changes.
6117 IsPicEnabled = true;
6118
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006119 getTargetStreamer().emitDirectiveOptionPic2();
6120 Parser.Lex();
6121 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006122 return Error(Parser.getTok().getLoc(),
6123 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00006124 }
6125 return false;
6126 }
6127
Jack Carter0cd3c192014-01-06 23:27:31 +00006128 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00006129 Warning(Parser.getTok().getLoc(),
6130 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00006131 Parser.eatToEndOfStatement();
6132 return false;
6133}
6134
Toma Tabacu9ca50962015-04-16 09:53:47 +00006135/// parseInsnDirective
6136/// ::= .insn
6137bool MipsAsmParser::parseInsnDirective() {
6138 // If this is not the end of the statement, report an error.
6139 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6140 reportParseError("unexpected token, expected end of statement");
6141 return false;
6142 }
6143
6144 // The actual label marking happens in
6145 // MipsELFStreamer::createPendingLabelRelocs().
6146 getTargetStreamer().emitDirectiveInsn();
6147
6148 getParser().Lex(); // Eat EndOfStatement token.
6149 return false;
6150}
6151
Simon Atanasyanbe186202016-02-11 06:45:54 +00006152/// parseSSectionDirective
6153/// ::= .sbss
6154/// ::= .sdata
6155bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
6156 // If this is not the end of the statement, report an error.
6157 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6158 reportParseError("unexpected token, expected end of statement");
6159 return false;
6160 }
6161
6162 MCSection *ELFSection = getContext().getELFSection(
6163 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
6164 getParser().getStreamer().SwitchSection(ELFSection);
6165
6166 getParser().Lex(); // Eat EndOfStatement token.
6167 return false;
6168}
6169
Daniel Sanders7e527422014-07-10 13:38:23 +00006170/// parseDirectiveModule
6171/// ::= .module oddspreg
6172/// ::= .module nooddspreg
6173/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00006174/// ::= .module softfloat
6175/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006176bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006177 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006178 MCAsmLexer &Lexer = getLexer();
6179 SMLoc L = Lexer.getLoc();
6180
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00006181 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006182 // TODO : get a better message.
6183 reportParseError(".module directive must appear before any code");
6184 return false;
6185 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006186
Toma Tabacuc405c822015-01-23 10:40:19 +00006187 StringRef Option;
6188 if (Parser.parseIdentifier(Option)) {
6189 reportParseError("expected .module option identifier");
6190 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006191 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006192
Toma Tabacuc405c822015-01-23 10:40:19 +00006193 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006194 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006195
Toma Tabacu3c499582015-06-25 10:56:57 +00006196 // Synchronize the abiflags information with the FeatureBits information we
6197 // changed above.
6198 getTargetStreamer().updateABIInfo(*this);
6199
6200 // If printing assembly, use the recently updated abiflags information.
6201 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6202 // emitted at the end).
6203 getTargetStreamer().emitDirectiveModuleOddSPReg();
6204
Toma Tabacuc405c822015-01-23 10:40:19 +00006205 // If this is not the end of the statement, report an error.
6206 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6207 reportParseError("unexpected token, expected end of statement");
6208 return false;
6209 }
6210
6211 return false; // parseDirectiveModule has finished successfully.
6212 } else if (Option == "nooddspreg") {
6213 if (!isABI_O32()) {
Nirav Dave2364748a2016-09-16 18:30:20 +00006214 return Error(L, "'.module nooddspreg' requires the O32 ABI");
Toma Tabacuc405c822015-01-23 10:40:19 +00006215 }
6216
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006217 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00006218
Toma Tabacu3c499582015-06-25 10:56:57 +00006219 // Synchronize the abiflags information with the FeatureBits information we
6220 // changed above.
6221 getTargetStreamer().updateABIInfo(*this);
6222
6223 // If printing assembly, use the recently updated abiflags information.
6224 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6225 // emitted at the end).
6226 getTargetStreamer().emitDirectiveModuleOddSPReg();
6227
Toma Tabacuc405c822015-01-23 10:40:19 +00006228 // If this is not the end of the statement, report an error.
6229 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6230 reportParseError("unexpected token, expected end of statement");
6231 return false;
6232 }
6233
6234 return false; // parseDirectiveModule has finished successfully.
6235 } else if (Option == "fp") {
6236 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00006237 } else if (Option == "softfloat") {
6238 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6239
6240 // Synchronize the ABI Flags information with the FeatureBits information we
6241 // updated above.
6242 getTargetStreamer().updateABIInfo(*this);
6243
6244 // If printing assembly, use the recently updated ABI Flags information.
6245 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6246 // emitted later).
6247 getTargetStreamer().emitDirectiveModuleSoftFloat();
6248
6249 // If this is not the end of the statement, report an error.
6250 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6251 reportParseError("unexpected token, expected end of statement");
6252 return false;
6253 }
6254
6255 return false; // parseDirectiveModule has finished successfully.
6256 } else if (Option == "hardfloat") {
6257 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
6258
6259 // Synchronize the ABI Flags information with the FeatureBits information we
6260 // updated above.
6261 getTargetStreamer().updateABIInfo(*this);
6262
6263 // If printing assembly, use the recently updated ABI Flags information.
6264 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6265 // emitted later).
6266 getTargetStreamer().emitDirectiveModuleHardFloat();
6267
6268 // If this is not the end of the statement, report an error.
6269 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6270 reportParseError("unexpected token, expected end of statement");
6271 return false;
6272 }
6273
6274 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00006275 } else {
6276 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
6277 }
Daniel Sanders7e527422014-07-10 13:38:23 +00006278}
6279
6280/// parseDirectiveModuleFP
6281/// ::= =32
6282/// ::= =xx
6283/// ::= =64
6284bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00006285 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00006286 MCAsmLexer &Lexer = getLexer();
6287
6288 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006289 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006290 return false;
6291 }
6292 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006293
Daniel Sanders7e527422014-07-10 13:38:23 +00006294 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006295 if (!parseFpABIValue(FpABI, ".module"))
6296 return false;
6297
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006298 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006299 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006300 return false;
6301 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006302
Toma Tabacua64e5402015-06-25 12:44:38 +00006303 // Synchronize the abiflags information with the FeatureBits information we
6304 // changed above.
6305 getTargetStreamer().updateABIInfo(*this);
6306
6307 // If printing assembly, use the recently updated abiflags information.
6308 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
6309 // emitted at the end).
6310 getTargetStreamer().emitDirectiveModuleFP();
6311
Daniel Sanders7e527422014-07-10 13:38:23 +00006312 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006313 return false;
6314}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006315
Daniel Sanders7e527422014-07-10 13:38:23 +00006316bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006317 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00006318 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006319 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006320 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006321
6322 if (Lexer.is(AsmToken::Identifier)) {
6323 StringRef Value = Parser.getTok().getString();
6324 Parser.Lex();
6325
6326 if (Value != "xx") {
6327 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6328 return false;
6329 }
6330
6331 if (!isABI_O32()) {
6332 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
6333 return false;
6334 }
6335
Daniel Sanders7e527422014-07-10 13:38:23 +00006336 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006337 if (ModuleLevelOptions) {
6338 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6339 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6340 } else {
6341 setFeatureBits(Mips::FeatureFPXX, "fpxx");
6342 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6343 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006344 return true;
6345 }
6346
6347 if (Lexer.is(AsmToken::Integer)) {
6348 unsigned Value = Parser.getTok().getIntVal();
6349 Parser.Lex();
6350
6351 if (Value != 32 && Value != 64) {
6352 reportParseError("unsupported value, expected 'xx', '32' or '64'");
6353 return false;
6354 }
6355
6356 if (Value == 32) {
6357 if (!isABI_O32()) {
6358 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
6359 return false;
6360 }
6361
Daniel Sanders7e527422014-07-10 13:38:23 +00006362 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006363 if (ModuleLevelOptions) {
6364 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6365 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6366 } else {
6367 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6368 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
6369 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006370 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00006371 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00006372 if (ModuleLevelOptions) {
6373 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
6374 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
6375 } else {
6376 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6377 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6378 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006379 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006380
Daniel Sanders7e527422014-07-10 13:38:23 +00006381 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006382 }
6383
6384 return false;
6385}
6386
Jack Carter0b744b32012-10-04 02:29:46 +00006387bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006388 // This returns false if this function recognizes the directive
6389 // regardless of whether it is successfully handles or reports an
6390 // error. Otherwise it returns true to give the generic parser a
6391 // chance at recognizing it.
6392
Rafael Espindola961d4692014-11-11 05:18:41 +00006393 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006394 StringRef IDVal = DirectiveID.getString();
6395
Nirav Dave996fc132016-05-05 14:15:46 +00006396 if (IDVal == ".cpload") {
6397 parseDirectiveCpLoad(DirectiveID.getLoc());
6398 return false;
6399 }
6400 if (IDVal == ".cprestore") {
6401 parseDirectiveCpRestore(DirectiveID.getLoc());
6402 return false;
6403 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006404 if (IDVal == ".dword") {
6405 parseDataDirective(8, DirectiveID.getLoc());
6406 return false;
6407 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006408 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006409 StringRef SymbolName;
6410
6411 if (Parser.parseIdentifier(SymbolName)) {
6412 reportParseError("expected identifier after .ent");
6413 return false;
6414 }
6415
6416 // There's an undocumented extension that allows an integer to
6417 // follow the name of the procedure which AFAICS is ignored by GAS.
6418 // Example: .ent foo,2
6419 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6420 if (getLexer().isNot(AsmToken::Comma)) {
6421 // Even though we accept this undocumented extension for compatibility
6422 // reasons, the additional integer argument does not actually change
6423 // the behaviour of the '.ent' directive, so we would like to discourage
6424 // its use. We do this by not referring to the extended version in
6425 // error messages which are not directly related to its use.
6426 reportParseError("unexpected token, expected end of statement");
6427 return false;
6428 }
6429 Parser.Lex(); // Eat the comma.
6430 const MCExpr *DummyNumber;
6431 int64_t DummyNumberVal;
6432 // If the user was explicitly trying to use the extended version,
6433 // we still give helpful extension-related error messages.
6434 if (Parser.parseExpression(DummyNumber)) {
6435 reportParseError("expected number after comma");
6436 return false;
6437 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006438 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006439 reportParseError("expected an absolute expression after comma");
6440 return false;
6441 }
6442 }
6443
6444 // If this is not the end of the statement, report an error.
6445 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6446 reportParseError("unexpected token, expected end of statement");
6447 return false;
6448 }
6449
Jim Grosbach6f482002015-05-18 18:43:14 +00006450 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006451
6452 getTargetStreamer().emitDirectiveEnt(*Sym);
6453 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006454 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006455 return false;
6456 }
6457
Jack Carter07c818d2013-01-25 01:31:34 +00006458 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006459 StringRef SymbolName;
6460
6461 if (Parser.parseIdentifier(SymbolName)) {
6462 reportParseError("expected identifier after .end");
6463 return false;
6464 }
6465
6466 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6467 reportParseError("unexpected token, expected end of statement");
6468 return false;
6469 }
6470
6471 if (CurrentFn == nullptr) {
6472 reportParseError(".end used without .ent");
6473 return false;
6474 }
6475
6476 if ((SymbolName != CurrentFn->getName())) {
6477 reportParseError(".end symbol does not match .ent symbol");
6478 return false;
6479 }
6480
6481 getTargetStreamer().emitDirectiveEnd(SymbolName);
6482 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006483 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006484 return false;
6485 }
6486
Jack Carter07c818d2013-01-25 01:31:34 +00006487 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006488 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6489 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006490 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006491 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6492 reportParseError("expected stack register");
6493 return false;
6494 }
6495
6496 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6497 if (!StackRegOpnd.isGPRAsmReg()) {
6498 reportParseError(StackRegOpnd.getStartLoc(),
6499 "expected general purpose register");
6500 return false;
6501 }
6502 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6503
6504 if (Parser.getTok().is(AsmToken::Comma))
6505 Parser.Lex();
6506 else {
6507 reportParseError("unexpected token, expected comma");
6508 return false;
6509 }
6510
6511 // Parse the frame size.
6512 const MCExpr *FrameSize;
6513 int64_t FrameSizeVal;
6514
6515 if (Parser.parseExpression(FrameSize)) {
6516 reportParseError("expected frame size value");
6517 return false;
6518 }
6519
Jim Grosbach13760bd2015-05-30 01:25:56 +00006520 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006521 reportParseError("frame size not an absolute expression");
6522 return false;
6523 }
6524
6525 if (Parser.getTok().is(AsmToken::Comma))
6526 Parser.Lex();
6527 else {
6528 reportParseError("unexpected token, expected comma");
6529 return false;
6530 }
6531
6532 // Parse the return register.
6533 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006534 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006535 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6536 reportParseError("expected return register");
6537 return false;
6538 }
6539
6540 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6541 if (!ReturnRegOpnd.isGPRAsmReg()) {
6542 reportParseError(ReturnRegOpnd.getStartLoc(),
6543 "expected general purpose register");
6544 return false;
6545 }
6546
6547 // If this is not the end of the statement, report an error.
6548 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6549 reportParseError("unexpected token, expected end of statement");
6550 return false;
6551 }
6552
6553 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6554 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006555 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006556 return false;
6557 }
6558
Jack Carter07c818d2013-01-25 01:31:34 +00006559 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006560 parseDirectiveSet();
6561 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006562 }
6563
Daniel Sandersd97a6342014-08-13 10:07:34 +00006564 if (IDVal == ".mask" || IDVal == ".fmask") {
6565 // .mask bitmask, frame_offset
6566 // bitmask: One bit for each register used.
6567 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6568 // first register is expected to be saved.
6569 // Examples:
6570 // .mask 0x80000000, -4
6571 // .fmask 0x80000000, -4
6572 //
Jack Carterbe332172012-09-07 00:48:02 +00006573
Daniel Sandersd97a6342014-08-13 10:07:34 +00006574 // Parse the bitmask
6575 const MCExpr *BitMask;
6576 int64_t BitMaskVal;
6577
6578 if (Parser.parseExpression(BitMask)) {
6579 reportParseError("expected bitmask value");
6580 return false;
6581 }
6582
Jim Grosbach13760bd2015-05-30 01:25:56 +00006583 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006584 reportParseError("bitmask not an absolute expression");
6585 return false;
6586 }
6587
6588 if (Parser.getTok().is(AsmToken::Comma))
6589 Parser.Lex();
6590 else {
6591 reportParseError("unexpected token, expected comma");
6592 return false;
6593 }
6594
6595 // Parse the frame_offset
6596 const MCExpr *FrameOffset;
6597 int64_t FrameOffsetVal;
6598
6599 if (Parser.parseExpression(FrameOffset)) {
6600 reportParseError("expected frame offset value");
6601 return false;
6602 }
6603
Jim Grosbach13760bd2015-05-30 01:25:56 +00006604 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006605 reportParseError("frame offset not an absolute expression");
6606 return false;
6607 }
6608
6609 // If this is not the end of the statement, report an error.
6610 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6611 reportParseError("unexpected token, expected end of statement");
6612 return false;
6613 }
6614
6615 if (IDVal == ".mask")
6616 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6617 else
6618 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006619 return false;
6620 }
6621
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006622 if (IDVal == ".nan")
6623 return parseDirectiveNaN();
6624
Jack Carter07c818d2013-01-25 01:31:34 +00006625 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006626 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006627 return false;
6628 }
6629
Rafael Espindolab59fb732014-03-28 18:50:26 +00006630 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006631 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006632 return false;
6633 }
6634
Simon Atanasyaneb9ed612016-08-22 16:18:42 +00006635 if (IDVal == ".dtprelword") {
6636 parseDirectiveDtpRelWord();
6637 return false;
6638 }
6639
6640 if (IDVal == ".dtpreldword") {
6641 parseDirectiveDtpRelDWord();
6642 return false;
6643 }
6644
6645 if (IDVal == ".tprelword") {
6646 parseDirectiveTpRelWord();
6647 return false;
6648 }
6649
6650 if (IDVal == ".tpreldword") {
6651 parseDirectiveTpRelDWord();
6652 return false;
6653 }
6654
Jack Carter07c818d2013-01-25 01:31:34 +00006655 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006656 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006657 return false;
6658 }
6659
Scott Egertond1aeb052016-02-15 16:11:51 +00006660 if (IDVal == ".hword") {
6661 parseDataDirective(2, DirectiveID.getLoc());
6662 return false;
6663 }
6664
Nirav Dave996fc132016-05-05 14:15:46 +00006665 if (IDVal == ".option") {
6666 parseDirectiveOption();
6667 return false;
6668 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006669
6670 if (IDVal == ".abicalls") {
6671 getTargetStreamer().emitDirectiveAbiCalls();
6672 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006673 Error(Parser.getTok().getLoc(),
6674 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006675 }
6676 return false;
6677 }
6678
Nirav Dave996fc132016-05-05 14:15:46 +00006679 if (IDVal == ".cpsetup") {
6680 parseDirectiveCPSetup();
6681 return false;
6682 }
6683 if (IDVal == ".cpreturn") {
6684 parseDirectiveCPReturn();
6685 return false;
6686 }
6687 if (IDVal == ".module") {
6688 parseDirectiveModule();
6689 return false;
6690 }
6691 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6692 parseInternalDirectiveReallowModule();
6693 return false;
6694 }
6695 if (IDVal == ".insn") {
6696 parseInsnDirective();
6697 return false;
6698 }
6699 if (IDVal == ".sbss") {
6700 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6701 return false;
6702 }
6703 if (IDVal == ".sdata") {
6704 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6705 return false;
6706 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006707
Rafael Espindola870c4e92012-01-11 03:56:41 +00006708 return true;
6709}
6710
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006711bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6712 // If this is not the end of the statement, report an error.
6713 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6714 reportParseError("unexpected token, expected end of statement");
6715 return false;
6716 }
6717
6718 getTargetStreamer().reallowModuleDirective();
6719
6720 getParser().Lex(); // Eat EndOfStatement token.
6721 return false;
6722}
6723
Rafael Espindola870c4e92012-01-11 03:56:41 +00006724extern "C" void LLVMInitializeMipsAsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00006725 RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget());
6726 RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget());
6727 RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target());
6728 RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget());
Rafael Espindola870c4e92012-01-11 03:56:41 +00006729}
Jack Carterb4dbc172012-09-05 23:34:03 +00006730
6731#define GET_REGISTER_MATCHER
6732#define GET_MATCHER_IMPLEMENTATION
6733#include "MipsGenAsmMatcher.inc"