blob: bff46886dc71d372792af0fa4a973cb6e2cbd09e [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Christophera5762812015-01-26 17:33:46 +000010#include "MCTargetDesc/MipsABIInfo.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000011#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000012#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "MipsRegisterInfo.h"
Daniel Sandersa6994442015-08-18 12:33:54 +000014#include "MipsTargetObjectFile.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000015#include "MipsTargetStreamer.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000017#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000021#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/MC/MCParser/MCAsmLexer.h"
23#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000024#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000025#include "llvm/MC/MCSectionELF.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000026#include "llvm/MC/MCStreamer.h"
27#include "llvm/MC/MCSubtargetInfo.h"
28#include "llvm/MC/MCSymbol.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000029#include "llvm/Support/Debug.h"
Simon Atanasyanbe186202016-02-11 06:45:54 +000030#include "llvm/Support/ELF.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000031#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000032#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000033#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000034#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000035#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000036
37using namespace llvm;
38
Chandler Carruthe96dd892014-04-21 22:55:11 +000039#define DEBUG_TYPE "mips-asm-parser"
40
Joey Gouly0e76fa72013-09-12 10:28:05 +000041namespace llvm {
42class MCInstrInfo;
43}
44
Rafael Espindola870c4e92012-01-11 03:56:41 +000045namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000046class MipsAssemblerOptions {
47public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000048 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000049 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000050
Toma Tabacu9db22db2014-09-09 10:15:38 +000051 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000052 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000053 Reorder = Opts->isReorder();
54 Macro = Opts->isMacro();
55 Features = Opts->getFeatures();
56 }
57
Toma Tabacub19cf202015-04-27 13:12:59 +000058 unsigned getATRegIndex() const { return ATReg; }
59 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000060 if (Reg > 31)
61 return false;
62
63 ATReg = Reg;
64 return true;
65 }
Jack Carter0b744b32012-10-04 02:29:46 +000066
Toma Tabacu9db22db2014-09-09 10:15:38 +000067 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000068 void setReorder() { Reorder = true; }
69 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000070
Toma Tabacu9db22db2014-09-09 10:15:38 +000071 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000072 void setMacro() { Macro = true; }
73 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000074
Toma Tabacu465acfd2015-06-09 13:33:26 +000075 const FeatureBitset &getFeatures() const { return Features; }
76 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000077
Daniel Sandersf0df2212014-08-04 12:20:00 +000078 // Set of features that are either architecture features or referenced
79 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
80 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
81 // The reason we need this mask is explained in the selectArch function.
82 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000083 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000084
Jack Carter0b744b32012-10-04 02:29:46 +000085private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000086 unsigned ATReg;
87 bool Reorder;
88 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000089 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000090};
91}
92
Michael Kupersteindb0712f2015-05-26 10:47:10 +000093const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
94 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
95 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
96 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
97 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
98 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
99 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
100 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
101 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
102};
103
Jack Carter0b744b32012-10-04 02:29:46 +0000104namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000105class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000106 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000107 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000108 return static_cast<MipsTargetStreamer &>(TS);
109 }
110
Eric Christophera5762812015-01-26 17:33:46 +0000111 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000112 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000113 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
114 // nullptr, which indicates that no function is currently
115 // selected. This usually happens after an '.end func'
116 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000117 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000118 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000119 bool IsCpRestoreSet;
120 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000121 unsigned CpSaveLocation;
122 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
123 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000124
Daniel Sandersef638fe2014-10-03 15:37:37 +0000125 // Print a warning along with its fix-it message at the given range.
126 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
127 SMRange Range, bool ShowColors = true);
128
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000129#define GET_ASSEMBLER_HEADER
130#include "MipsGenAsmMatcher.inc"
131
Matheus Almeida595fcab2014-06-11 15:05:56 +0000132 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
133
Chad Rosier49963552012-10-13 00:26:04 +0000134 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000135 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000136 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000137 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000138
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000139 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000140 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000141
Toma Tabacu13964452014-09-04 13:23:44 +0000142 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000143
Toma Tabacu13964452014-09-04 13:23:44 +0000144 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000145
David Blaikie960ea3f2014-06-08 16:18:35 +0000146 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
147 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000148
Craig Topper56c590a2014-04-29 07:58:02 +0000149 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000150
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000151 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
152 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000153 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000154 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000155 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
156 SMLoc S);
157 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
158 OperandMatchResultTy parseImm(OperandVector &Operands);
159 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
160 OperandMatchResultTy parseInvNum(OperandVector &Operands);
161 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
162 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
163 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
164 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000165
David Blaikie960ea3f2014-06-08 16:18:35 +0000166 bool searchSymbolAlias(OperandVector &Operands);
167
Toma Tabacu13964452014-09-04 13:23:44 +0000168 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000169
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000170 enum MacroExpanderResultTy {
171 MER_NotAMacro,
172 MER_Success,
173 MER_Fail,
174 };
Jack Carter30a59822012-10-04 04:03:53 +0000175
Matheus Almeida3813d572014-06-19 14:39:14 +0000176 // Expands assembly pseudo instructions.
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000177 MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
178 MCStreamer &Out,
179 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000180
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000181 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
182 const MCSubtargetInfo *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000183
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000184 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000185 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000186 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000187
Toma Tabacuf712ede2015-06-17 14:31:51 +0000188 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
189 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000190 MCStreamer &Out, const MCSubtargetInfo *STI);
Toma Tabacu674825c2015-06-16 12:16:24 +0000191
Toma Tabacu00e98672015-05-01 12:19:27 +0000192 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000193 MCStreamer &Out, const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000194
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000195 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
196 const MCOperand &Offset, bool Is32BitAddress,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000197 SMLoc IDLoc, MCStreamer &Out,
198 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000199
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000200 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
201 const MCSubtargetInfo *STI);
Matheus Almeida3813d572014-06-19 14:39:14 +0000202
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000203 void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +0000204 const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
205
206 void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
207 const MCSubtargetInfo *STI, bool IsImmOpnd);
208
209 void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
210 const MCSubtargetInfo *STI, bool IsImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000211
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000212 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
213 const MCSubtargetInfo *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000214
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000215 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
216 const MCSubtargetInfo *STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000217
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000218 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
219 const MCSubtargetInfo *STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +0000220
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000221 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
222 const MCSubtargetInfo *STI);
Toma Tabacu1a108322015-06-17 13:20:24 +0000223
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000224 bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
225 const MCSubtargetInfo *STI, const bool IsMips64,
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000226 const bool Signed);
227
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000228 bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000229 MCStreamer &Out, const MCSubtargetInfo *STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +0000230
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000231 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
232 const MCSubtargetInfo *STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000233
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000234 bool expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
235 const MCSubtargetInfo *STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000236
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000237 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000238 MCStreamer &Out, const MCSubtargetInfo *STI);
239 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
240 const MCSubtargetInfo *STI);
241 bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
242 const MCSubtargetInfo *STI);
243 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
244 const MCSubtargetInfo *STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000245
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000246 bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
247 const MCSubtargetInfo *STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +0000248
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000249 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000250 MCStreamer &Out, const MCSubtargetInfo *STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000251
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000252 bool reportParseError(Twine ErrorMsg);
253 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000254
Jack Carterb5cf5902013-04-17 00:18:04 +0000255 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000256 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000257
Vladimir Medic4c299852013-11-06 11:27:05 +0000258 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000259
260 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000261 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000262 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000263 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000264 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000265 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000266 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000267 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000268 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000269 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000270 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000271 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000272 bool parseInsnDirective();
Simon Atanasyanbe186202016-02-11 06:45:54 +0000273 bool parseSSectionDirective(StringRef Section, unsigned Type);
Jack Carter0b744b32012-10-04 02:29:46 +0000274
275 bool parseSetAtDirective();
276 bool parseSetNoAtDirective();
277 bool parseSetMacroDirective();
278 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000279 bool parseSetMsaDirective();
280 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000281 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000282 bool parseSetReorderDirective();
283 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000284 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000285 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000286 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000287 bool parseSetOddSPRegDirective();
288 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000289 bool parseSetPopDirective();
290 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000291 bool parseSetSoftFloatDirective();
292 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000293
Jack Carterd76b2372013-03-21 21:44:16 +0000294 bool parseSetAssignment();
295
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000296 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000297 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000298 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000299 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000300 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000301 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
302 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000303
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000304 bool parseInternalDirectiveReallowModule();
305
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000306 bool eatComma(StringRef ErrorStr);
307
Jack Carter1ac53222013-02-20 23:11:17 +0000308 int matchCPURegisterName(StringRef Symbol);
309
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000310 int matchHWRegsRegisterName(StringRef Symbol);
311
Jack Carter873c7242013-01-12 01:03:14 +0000312 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000313
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000314 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000315
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000316 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000317
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000318 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000319
Jack Carter5dc8ac92013-09-25 23:50:44 +0000320 int matchMSA128RegisterName(StringRef Name);
321
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000322 int matchMSA128CtrlRegisterName(StringRef Name);
323
Jack Carterd0bd6422013-04-18 00:41:53 +0000324 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000325
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000326 unsigned getGPR(int RegNo);
327
Toma Tabacu89a712b2015-04-15 10:48:56 +0000328 /// Returns the internal register number for the current AT. Also checks if
329 /// the current AT is unavailable (set to $0) and gives an error if it is.
330 /// This should be used in pseudo-instruction expansions which need AT.
331 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000332
Daniel Sandersc6924fa2016-04-18 12:06:15 +0000333 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
334 const MCSubtargetInfo *STI);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000335
336 // Helper function that checks if the value of a vector index is within the
337 // boundaries of accepted values for each RegisterKind
338 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
339 bool validateMSAIndex(int Val, int RegKind);
340
Daniel Sandersf0df2212014-08-04 12:20:00 +0000341 // Selects a new architecture by updating the FeatureBits with the necessary
342 // info including implied dependencies.
343 // Internally, it clears all the feature bits related to *any* architecture
344 // and selects the new one using the ToggleFeature functionality of the
345 // MCSubtargetInfo object that handles implied dependencies. The reason we
346 // clear all the arch related bits manually is because ToggleFeature only
347 // clears the features that imply the feature being cleared and not the
348 // features implied by the feature being cleared. This is easier to see
349 // with an example:
350 // --------------------------------------------------
351 // | Feature | Implies |
352 // | -------------------------------------------------|
353 // | FeatureMips1 | None |
354 // | FeatureMips2 | FeatureMips1 |
355 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
356 // | FeatureMips4 | FeatureMips3 |
357 // | ... | |
358 // --------------------------------------------------
359 //
360 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
361 // FeatureMipsGP64 | FeatureMips1)
362 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
363 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000364 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000365 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000366 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
367 STI.setFeatureBits(FeatureBits);
368 setAvailableFeatures(
369 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000370 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000371 }
372
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000373 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000374 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000375 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000376 setAvailableFeatures(
377 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000378 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000379 }
380 }
381
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000382 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000383 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000384 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000385 setAvailableFeatures(
386 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000387 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000388 }
389 }
390
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000391 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
392 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000393 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000394 }
395
396 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
397 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000398 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000399 }
400
Rafael Espindola870c4e92012-01-11 03:56:41 +0000401public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000402 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000403 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000404#define GET_OPERAND_DIAGNOSTIC_TYPES
405#include "MipsGenAsmMatcher.inc"
406#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000407 };
408
Akira Hatanakab11ef082015-11-14 06:35:56 +0000409 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000410 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000411 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000412 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
413 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000414 MCAsmParserExtension::Initialize(parser);
415
Toma Tabacu11e14a92015-04-21 11:50:52 +0000416 parser.addAliasForDirective(".asciiz", ".asciz");
417
Jack Carterb4dbc172012-09-05 23:34:03 +0000418 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000419 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000420
Toma Tabacu9db22db2014-09-09 10:15:38 +0000421 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000422 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000423 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000424
Toma Tabacu9db22db2014-09-09 10:15:38 +0000425 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000426 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000427 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000428
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000429 getTargetStreamer().updateABIInfo(*this);
430
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000431 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000432 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000433
434 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000435
Daniel Sandersa6994442015-08-18 12:33:54 +0000436 IsPicEnabled =
437 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
438
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000439 IsCpRestoreSet = false;
440 CpRestoreOffset = -1;
441
Daniel Sanders50f17232015-09-15 16:17:27 +0000442 Triple TheTriple(sti.getTargetTriple());
443 if ((TheTriple.getArch() == Triple::mips) ||
444 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000445 IsLittleEndian = false;
446 else
447 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000448 }
449
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000450 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
451 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
452
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000453 bool isGP64bit() const {
454 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
455 }
456 bool isFP64bit() const {
457 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
458 }
Eric Christophera5762812015-01-26 17:33:46 +0000459 const MipsABIInfo &getABI() const { return ABI; }
460 bool isABI_N32() const { return ABI.IsN32(); }
461 bool isABI_N64() const { return ABI.IsN64(); }
462 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000463 bool isABI_FPXX() const {
464 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
465 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000466
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000467 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000468 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000469 }
470
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000471 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000472 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000473 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000474 bool hasMips1() const {
475 return getSTI().getFeatureBits()[Mips::FeatureMips1];
476 }
477 bool hasMips2() const {
478 return getSTI().getFeatureBits()[Mips::FeatureMips2];
479 }
480 bool hasMips3() const {
481 return getSTI().getFeatureBits()[Mips::FeatureMips3];
482 }
483 bool hasMips4() const {
484 return getSTI().getFeatureBits()[Mips::FeatureMips4];
485 }
486 bool hasMips5() const {
487 return getSTI().getFeatureBits()[Mips::FeatureMips5];
488 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000489 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000490 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000491 }
492 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000493 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000494 }
495 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000496 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 }
498 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000500 }
Daniel Sanders17793142015-02-18 16:24:50 +0000501 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000502 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000503 }
504 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000505 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000506 }
507 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000508 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000509 }
510 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000511 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000512 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000513 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000514 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000515 }
516 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000517 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000518 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000519
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000520 bool hasDSP() const {
521 return getSTI().getFeatureBits()[Mips::FeatureDSP];
522 }
523 bool hasDSPR2() const {
524 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
525 }
526 bool hasDSPR3() const {
527 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
528 }
529 bool hasMSA() const {
530 return getSTI().getFeatureBits()[Mips::FeatureMSA];
531 }
Kai Nackee0245392015-01-27 19:11:28 +0000532 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000533 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000534 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000535
Daniel Sandersa6994442015-08-18 12:33:54 +0000536 bool inPicMode() {
537 return IsPicEnabled;
538 }
539
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000540 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000541 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000542 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000543
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000544 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000545 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000546 }
547
Eric Christophere8ae3e32015-05-07 23:10:21 +0000548 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000549 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000550 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000551
Toma Tabacud9d344b2015-04-27 14:05:04 +0000552 /// Warn if RegIndex is the same as the current AT.
553 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000554
555 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000556
557 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000558};
559}
560
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000561namespace {
562
563/// MipsOperand - Instances of this class represent a parsed Mips machine
564/// instruction.
565class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000566public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000567 /// Broad categories of register classes
568 /// The exact class is finalized by the render method.
569 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000570 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000571 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000572 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000573 RegKind_FCC = 4, /// FCC
574 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
575 RegKind_MSACtrl = 16, /// MSA control registers
576 RegKind_COP2 = 32, /// COP2
577 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
578 /// context).
579 RegKind_CCR = 128, /// CCR
580 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000581 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000582 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000583 /// Potentially any (e.g. $1)
584 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
585 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000586 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000587 };
588
589private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000590 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000591 k_Immediate, /// An immediate (possibly involving symbol references)
592 k_Memory, /// Base + Offset Memory Address
593 k_PhysRegister, /// A physical register from the Mips namespace
594 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000595 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000596 k_RegList, /// A physical register list
597 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000598 } Kind;
599
David Blaikie960ea3f2014-06-08 16:18:35 +0000600public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000601 MipsOperand(KindTy K, MipsAsmParser &Parser)
602 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
603
David Blaikie960ea3f2014-06-08 16:18:35 +0000604private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000605 /// For diagnostics, and checking the assembler temporary
606 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000607
Eric Christopher8996c5d2013-03-15 00:42:55 +0000608 struct Token {
609 const char *Data;
610 unsigned Length;
611 };
612
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000613 struct PhysRegOp {
614 unsigned Num; /// Register Number
615 };
616
617 struct RegIdxOp {
618 unsigned Index; /// Index into the register class
619 RegKind Kind; /// Bitfield of the kinds it could possibly be
620 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000621 };
622
623 struct ImmOp {
624 const MCExpr *Val;
625 };
626
627 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000628 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000629 const MCExpr *Off;
630 };
631
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000632 struct RegListOp {
633 SmallVector<unsigned, 10> *List;
634 };
635
Jack Carterb4dbc172012-09-05 23:34:03 +0000636 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000637 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000638 struct PhysRegOp PhysReg;
639 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000640 struct ImmOp Imm;
641 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000642 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000643 };
644
645 SMLoc StartLoc, EndLoc;
646
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000647 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000648 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
649 const MCRegisterInfo *RegInfo,
650 SMLoc S, SMLoc E,
651 MipsAsmParser &Parser) {
652 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000653 Op->RegIdx.Index = Index;
654 Op->RegIdx.RegInfo = RegInfo;
655 Op->RegIdx.Kind = RegKind;
656 Op->StartLoc = S;
657 Op->EndLoc = E;
658 return Op;
659 }
660
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000661public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000662 /// Coerce the register to GPR32 and return the real register for the current
663 /// target.
664 unsigned getGPR32Reg() const {
665 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000666 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000667 unsigned ClassID = Mips::GPR32RegClassID;
668 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000669 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000670
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000671 /// Coerce the register to GPR32 and return the real register for the current
672 /// target.
673 unsigned getGPRMM16Reg() const {
674 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
675 unsigned ClassID = Mips::GPR32RegClassID;
676 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
677 }
678
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000679 /// Coerce the register to GPR64 and return the real register for the current
680 /// target.
681 unsigned getGPR64Reg() const {
682 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
683 unsigned ClassID = Mips::GPR64RegClassID;
684 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000685 }
686
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000687private:
688 /// Coerce the register to AFGR64 and return the real register for the current
689 /// target.
690 unsigned getAFGR64Reg() const {
691 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
692 if (RegIdx.Index % 2 != 0)
693 AsmParser.Warning(StartLoc, "Float register should be even.");
694 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
695 .getRegister(RegIdx.Index / 2);
696 }
697
698 /// Coerce the register to FGR64 and return the real register for the current
699 /// target.
700 unsigned getFGR64Reg() const {
701 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
702 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
703 .getRegister(RegIdx.Index);
704 }
705
706 /// Coerce the register to FGR32 and return the real register for the current
707 /// target.
708 unsigned getFGR32Reg() const {
709 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
710 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
711 .getRegister(RegIdx.Index);
712 }
713
714 /// Coerce the register to FGRH32 and return the real register for the current
715 /// target.
716 unsigned getFGRH32Reg() const {
717 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
718 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
719 .getRegister(RegIdx.Index);
720 }
721
722 /// Coerce the register to FCC and return the real register for the current
723 /// target.
724 unsigned getFCCReg() const {
725 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
726 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
727 .getRegister(RegIdx.Index);
728 }
729
730 /// Coerce the register to MSA128 and return the real register for the current
731 /// target.
732 unsigned getMSA128Reg() const {
733 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
734 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
735 // identical
736 unsigned ClassID = Mips::MSA128BRegClassID;
737 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
738 }
739
740 /// Coerce the register to MSACtrl and return the real register for the
741 /// current target.
742 unsigned getMSACtrlReg() const {
743 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
744 unsigned ClassID = Mips::MSACtrlRegClassID;
745 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
746 }
747
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000748 /// Coerce the register to COP0 and return the real register for the
749 /// current target.
750 unsigned getCOP0Reg() const {
751 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
752 unsigned ClassID = Mips::COP0RegClassID;
753 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
754 }
755
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000756 /// Coerce the register to COP2 and return the real register for the
757 /// current target.
758 unsigned getCOP2Reg() const {
759 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
760 unsigned ClassID = Mips::COP2RegClassID;
761 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
762 }
763
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000764 /// Coerce the register to COP3 and return the real register for the
765 /// current target.
766 unsigned getCOP3Reg() const {
767 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
768 unsigned ClassID = Mips::COP3RegClassID;
769 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
770 }
771
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000772 /// Coerce the register to ACC64DSP and return the real register for the
773 /// current target.
774 unsigned getACC64DSPReg() const {
775 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
776 unsigned ClassID = Mips::ACC64DSPRegClassID;
777 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
778 }
779
780 /// Coerce the register to HI32DSP and return the real register for the
781 /// current target.
782 unsigned getHI32DSPReg() const {
783 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
784 unsigned ClassID = Mips::HI32DSPRegClassID;
785 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
786 }
787
788 /// Coerce the register to LO32DSP and return the real register for the
789 /// current target.
790 unsigned getLO32DSPReg() const {
791 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
792 unsigned ClassID = Mips::LO32DSPRegClassID;
793 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
794 }
795
796 /// Coerce the register to CCR and return the real register for the
797 /// current target.
798 unsigned getCCRReg() const {
799 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
800 unsigned ClassID = Mips::CCRRegClassID;
801 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
802 }
803
804 /// Coerce the register to HWRegs and return the real register for the
805 /// current target.
806 unsigned getHWRegsReg() const {
807 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
808 unsigned ClassID = Mips::HWRegsRegClassID;
809 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
810 }
811
812public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000813 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000814 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000815 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000816 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000817 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000818 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000819 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000820 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000821 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000822
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000823 void addRegOperands(MCInst &Inst, unsigned N) const {
824 llvm_unreachable("Use a custom parser instead");
825 }
826
Daniel Sanders21bce302014-04-01 12:35:23 +0000827 /// Render the operand to an MCInst as a GPR32
828 /// Asserts if the wrong number of operands are requested, or the operand
829 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
831 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000832 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000833 }
834
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000835 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
836 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000837 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000838 }
839
Jozef Kolek1904fa22014-11-24 14:25:53 +0000840 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
841 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000842 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000843 }
844
Zoran Jovanovic41688672015-02-10 16:36:20 +0000845 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
846 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000847 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000848 }
849
Daniel Sanders21bce302014-04-01 12:35:23 +0000850 /// Render the operand to an MCInst as a GPR64
851 /// Asserts if the wrong number of operands are requested, or the operand
852 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000853 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
854 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000855 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000856 }
857
858 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
859 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000860 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000861 }
862
863 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
864 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000865 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000866 }
867
868 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
869 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000870 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000871 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000872 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000873 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
874 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000875 }
876
877 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
878 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000879 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000880 }
881
882 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
883 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000884 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000885 }
886
887 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
888 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000889 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000890 }
891
892 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
893 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000894 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000895 }
896
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000897 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
898 assert(N == 1 && "Invalid number of operands!");
899 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
900 }
901
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000902 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
903 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000904 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000905 }
906
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000907 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
908 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000909 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000910 }
911
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000912 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
913 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000914 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000915 }
916
917 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
918 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000919 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000920 }
921
922 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
923 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000924 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000925 }
926
927 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
928 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000929 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000930 }
931
932 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
933 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000934 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000935 }
936
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000937 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000938 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
939 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000940 uint64_t Imm = getConstantImm() - Offset;
941 Imm &= (1 << Bits) - 1;
942 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000943 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000944 Inst.addOperand(MCOperand::createImm(Imm));
945 }
946
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000947 template <unsigned Bits>
Daniel Sanders85fd10b2016-03-31 14:34:00 +0000948 void addSImmOperands(MCInst &Inst, unsigned N) const {
949 if (isImm() && !isConstantImm()) {
950 addExpr(Inst, getImm());
951 return;
952 }
953 addConstantSImmOperands<Bits, 0, 0>(Inst, N);
954 }
955
956 template <unsigned Bits>
Daniel Sandersf8bb23e2016-02-01 15:13:31 +0000957 void addUImmOperands(MCInst &Inst, unsigned N) const {
958 if (isImm() && !isConstantImm()) {
959 addExpr(Inst, getImm());
960 return;
961 }
962 addConstantUImmOperands<Bits, 0, 0>(Inst, N);
963 }
964
Daniel Sanders78e89022016-03-11 11:37:50 +0000965 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
966 void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
967 assert(N == 1 && "Invalid number of operands!");
968 int64_t Imm = getConstantImm() - Offset;
969 Imm = SignExtend64<Bits>(Imm);
970 Imm += Offset;
971 Imm += AdjustOffset;
972 Inst.addOperand(MCOperand::createImm(Imm));
973 }
974
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000975 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000976 assert(N == 1 && "Invalid number of operands!");
977 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000978 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000979 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000980
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000981 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000982 assert(N == 2 && "Invalid number of operands!");
983
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000984 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
985 ? getMemBase()->getGPR64Reg()
986 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000987
988 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000989 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000990 }
991
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000992 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
993 assert(N == 2 && "Invalid number of operands!");
994
Jim Grosbache9119e42015-05-13 18:37:00 +0000995 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000996
997 const MCExpr *Expr = getMemOff();
998 addExpr(Inst, Expr);
999 }
1000
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001001 void addRegListOperands(MCInst &Inst, unsigned N) const {
1002 assert(N == 1 && "Invalid number of operands!");
1003
1004 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001005 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001006 }
1007
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001008 void addRegPairOperands(MCInst &Inst, unsigned N) const {
1009 assert(N == 2 && "Invalid number of operands!");
Zlatko Buljanba553a62016-05-09 08:07:28 +00001010 assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001011 unsigned RegNo = getRegPair();
Zlatko Buljanba553a62016-05-09 08:07:28 +00001012 AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
1013 Inst.addOperand(MCOperand::createReg(
1014 RegIdx.RegInfo->getRegClass(
1015 AsmParser.getABI().AreGprs64bit()
1016 ? Mips::GPR64RegClassID
1017 : Mips::GPR32RegClassID).getRegister(RegNo++)));
1018 Inst.addOperand(MCOperand::createReg(
1019 RegIdx.RegInfo->getRegClass(
1020 AsmParser.getABI().AreGprs64bit()
1021 ? Mips::GPR64RegClassID
1022 : Mips::GPR32RegClassID).getRegister(RegNo)));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001023 }
1024
Zoran Jovanovic41688672015-02-10 16:36:20 +00001025 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1026 assert(N == 2 && "Invalid number of operands!");
1027 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001028 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001029 }
1030
Craig Topper56c590a2014-04-29 07:58:02 +00001031 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001032 // As a special case until we sort out the definition of div/divu, pretend
1033 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1034 if (isGPRAsmReg() && RegIdx.Index == 0)
1035 return true;
1036
1037 return Kind == k_PhysRegister;
1038 }
1039 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001040 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001041 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +00001042 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001043 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001044 bool isConstantImmz() const {
1045 return isConstantImm() && getConstantImm() == 0;
1046 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001047 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1048 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1049 }
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001050 template <unsigned Bits> bool isSImm() const {
1051 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1052 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001053 template <unsigned Bits> bool isUImm() const {
1054 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1055 }
1056 template <unsigned Bits> bool isAnyImm() const {
1057 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1058 isUInt<Bits>(getConstantImm()))
1059 : isImm();
1060 }
Daniel Sanders78e89022016-03-11 11:37:50 +00001061 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1062 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001063 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001064 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1065 return isConstantImm() && getConstantImm() >= Bottom &&
1066 getConstantImm() <= Top;
1067 }
Craig Topper56c590a2014-04-29 07:58:02 +00001068 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001069 // Note: It's not possible to pretend that other operand kinds are tokens.
1070 // The matcher emitter checks tokens first.
1071 return Kind == k_Token;
1072 }
Craig Topper56c590a2014-04-29 07:58:02 +00001073 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001074 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001075 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001076 }
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001077 template <unsigned Bits, unsigned ShiftAmount = 0>
1078 bool isMemWithSimmOffset() const {
1079 return isMem() && isConstantMemOff() &&
1080 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff()) &&
1081 getMemBase()->isGPRAsmReg();
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001082 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001083 bool isMemWithGRPMM16Base() const {
1084 return isMem() && getMemBase()->isMM16AsmReg();
1085 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001086 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1087 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1088 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1089 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001090 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1091 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1092 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1093 && (getMemBase()->getGPR32Reg() == Mips::SP);
1094 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001095 template <unsigned Bits, unsigned ShiftLeftAmount>
1096 bool isScaledUImm() const {
1097 return isConstantImm() &&
1098 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001099 }
Daniel Sanders97297772016-03-22 14:40:00 +00001100 template <unsigned Bits, unsigned ShiftLeftAmount>
1101 bool isScaledSImm() const {
1102 return isConstantImm() &&
1103 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
1104 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001105 bool isRegList16() const {
1106 if (!isRegList())
1107 return false;
1108
1109 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001110 if (Size < 2 || Size > 5)
1111 return false;
1112
1113 unsigned R0 = RegList.List->front();
1114 unsigned R1 = RegList.List->back();
1115 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1116 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001117 return false;
1118
1119 int PrevReg = *RegList.List->begin();
1120 for (int i = 1; i < Size - 1; i++) {
1121 int Reg = (*(RegList.List))[i];
1122 if ( Reg != PrevReg + 1)
1123 return false;
1124 PrevReg = Reg;
1125 }
1126
1127 return true;
1128 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001129 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001130 bool isLSAImm() const {
1131 if (!isConstantImm())
1132 return false;
1133 int64_t Val = getConstantImm();
1134 return 1 <= Val && Val <= 4;
1135 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001136 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001137 bool isMovePRegPair() const {
1138 if (Kind != k_RegList || RegList.List->size() != 2)
1139 return false;
1140
1141 unsigned R0 = RegList.List->front();
1142 unsigned R1 = RegList.List->back();
1143
1144 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1145 (R0 == Mips::A1 && R1 == Mips::A3) ||
1146 (R0 == Mips::A2 && R1 == Mips::A3) ||
1147 (R0 == Mips::A0 && R1 == Mips::S5) ||
1148 (R0 == Mips::A0 && R1 == Mips::S6) ||
1149 (R0 == Mips::A0 && R1 == Mips::A1) ||
1150 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001151 (R0 == Mips::A0 && R1 == Mips::A3) ||
1152 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1153 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1154 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1155 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1156 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1157 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1158 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1159 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001160 return true;
1161
1162 return false;
1163 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001164
1165 StringRef getToken() const {
1166 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001167 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001168 }
Zlatko Buljanba553a62016-05-09 08:07:28 +00001169 bool isRegPair() const {
1170 return Kind == k_RegPair && RegIdx.Index <= 30;
1171 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001172
Craig Topper56c590a2014-04-29 07:58:02 +00001173 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001174 // As a special case until we sort out the definition of div/divu, pretend
1175 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1176 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1177 RegIdx.Kind & RegKind_GPR)
1178 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001179
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001180 assert(Kind == k_PhysRegister && "Invalid access!");
1181 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001182 }
1183
Jack Carterb4dbc172012-09-05 23:34:03 +00001184 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001185 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001186 return Imm.Val;
1187 }
1188
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001189 int64_t getConstantImm() const {
1190 const MCExpr *Val = getImm();
1191 return static_cast<const MCConstantExpr *>(Val)->getValue();
1192 }
1193
1194 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001195 assert((Kind == k_Memory) && "Invalid access!");
1196 return Mem.Base;
1197 }
1198
1199 const MCExpr *getMemOff() const {
1200 assert((Kind == k_Memory) && "Invalid access!");
1201 return Mem.Off;
1202 }
1203
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001204 int64_t getConstantMemOff() const {
1205 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1206 }
1207
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001208 const SmallVectorImpl<unsigned> &getRegList() const {
1209 assert((Kind == k_RegList) && "Invalid access!");
1210 return *(RegList.List);
1211 }
1212
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001213 unsigned getRegPair() const {
1214 assert((Kind == k_RegPair) && "Invalid access!");
1215 return RegIdx.Index;
1216 }
1217
David Blaikie960ea3f2014-06-08 16:18:35 +00001218 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1219 MipsAsmParser &Parser) {
1220 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001221 Op->Tok.Data = Str.data();
1222 Op->Tok.Length = Str.size();
1223 Op->StartLoc = S;
1224 Op->EndLoc = S;
1225 return Op;
1226 }
1227
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001228 /// Create a numeric register (e.g. $1). The exact register remains
1229 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001230 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001231 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001232 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001233 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001234 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001235 }
1236
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001237 /// Create a register that is definitely a GPR.
1238 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001239 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001240 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001241 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001242 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001243 }
1244
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001245 /// Create a register that is definitely a FGR.
1246 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001247 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001248 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001249 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001250 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1251 }
1252
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001253 /// Create a register that is definitely a HWReg.
1254 /// This is typically only used for named registers such as $hwr_cpunum.
1255 static std::unique_ptr<MipsOperand>
1256 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1257 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1258 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1259 }
1260
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001261 /// Create a register that is definitely an FCC.
1262 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001263 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001264 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001265 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001266 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1267 }
1268
1269 /// Create a register that is definitely an ACC.
1270 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001271 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001272 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001273 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001274 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1275 }
1276
1277 /// Create a register that is definitely an MSA128.
1278 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001279 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001280 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001281 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001282 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1283 }
1284
1285 /// Create a register that is definitely an MSACtrl.
1286 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001287 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001288 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001289 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001290 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1291 }
1292
David Blaikie960ea3f2014-06-08 16:18:35 +00001293 static std::unique_ptr<MipsOperand>
1294 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1295 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001296 Op->Imm.Val = Val;
1297 Op->StartLoc = S;
1298 Op->EndLoc = E;
1299 return Op;
1300 }
1301
David Blaikie960ea3f2014-06-08 16:18:35 +00001302 static std::unique_ptr<MipsOperand>
1303 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1304 SMLoc E, MipsAsmParser &Parser) {
1305 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1306 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001307 Op->Mem.Off = Off;
1308 Op->StartLoc = S;
1309 Op->EndLoc = E;
1310 return Op;
1311 }
1312
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001313 static std::unique_ptr<MipsOperand>
1314 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1315 MipsAsmParser &Parser) {
1316 assert (Regs.size() > 0 && "Empty list not allowed");
1317
1318 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001319 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001320 Op->StartLoc = StartLoc;
1321 Op->EndLoc = EndLoc;
1322 return Op;
1323 }
1324
Daniel Sandersd044e492016-05-09 13:10:57 +00001325 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1326 SMLoc S, SMLoc E,
1327 MipsAsmParser &Parser) {
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001328 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001329 Op->RegIdx.Index = MOP.RegIdx.Index;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001330 Op->StartLoc = S;
1331 Op->EndLoc = E;
1332 return Op;
1333 }
1334
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001335 bool isGPRAsmReg() const {
1336 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001337 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001338 bool isMM16AsmReg() const {
1339 if (!(isRegIdx() && RegIdx.Kind))
1340 return false;
1341 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1342 || RegIdx.Index == 16 || RegIdx.Index == 17);
1343 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001344 bool isMM16AsmRegZero() const {
1345 if (!(isRegIdx() && RegIdx.Kind))
1346 return false;
1347 return (RegIdx.Index == 0 ||
1348 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1349 RegIdx.Index == 17);
1350 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001351 bool isMM16AsmRegMoveP() const {
1352 if (!(isRegIdx() && RegIdx.Kind))
1353 return false;
1354 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1355 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1356 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001357 bool isFGRAsmReg() const {
1358 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1359 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001360 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001361 bool isHWRegsAsmReg() const {
1362 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001363 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001364 bool isCCRAsmReg() const {
1365 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001366 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001367 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001368 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1369 return false;
1370 if (!AsmParser.hasEightFccRegisters())
1371 return RegIdx.Index == 0;
1372 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001373 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001374 bool isACCAsmReg() const {
1375 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001376 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001377 bool isCOP0AsmReg() const {
1378 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1379 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001380 bool isCOP2AsmReg() const {
1381 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001382 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001383 bool isCOP3AsmReg() const {
1384 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1385 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001386 bool isMSA128AsmReg() const {
1387 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001388 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001389 bool isMSACtrlAsmReg() const {
1390 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001391 }
1392
Jack Carterb4dbc172012-09-05 23:34:03 +00001393 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001394 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001395 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001396 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001397
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001398 virtual ~MipsOperand() {
1399 switch (Kind) {
1400 case k_Immediate:
1401 break;
1402 case k_Memory:
1403 delete Mem.Base;
1404 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001405 case k_RegList:
1406 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001407 case k_PhysRegister:
1408 case k_RegisterIndex:
1409 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001410 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001411 break;
1412 }
1413 }
1414
Craig Topper56c590a2014-04-29 07:58:02 +00001415 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001416 switch (Kind) {
1417 case k_Immediate:
1418 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001419 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001420 OS << ">";
1421 break;
1422 case k_Memory:
1423 OS << "Mem<";
1424 Mem.Base->print(OS);
1425 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001426 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001427 OS << ">";
1428 break;
1429 case k_PhysRegister:
1430 OS << "PhysReg<" << PhysReg.Num << ">";
1431 break;
1432 case k_RegisterIndex:
1433 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1434 break;
1435 case k_Token:
1436 OS << Tok.Data;
1437 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001438 case k_RegList:
1439 OS << "RegList< ";
1440 for (auto Reg : (*RegList.List))
1441 OS << Reg << " ";
1442 OS << ">";
1443 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001444 case k_RegPair:
1445 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1446 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001447 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001448 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001449}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001450} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001451
Jack Carter9e65aa32013-03-22 00:05:30 +00001452namespace llvm {
1453extern const MCInstrDesc MipsInsts[];
1454}
1455static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1456 return MipsInsts[Opcode];
1457}
1458
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001459static bool hasShortDelaySlot(unsigned Opcode) {
1460 switch (Opcode) {
1461 case Mips::JALS_MM:
1462 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001463 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001464 case Mips::BGEZALS_MM:
1465 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001466 return true;
1467 default:
1468 return false;
1469 }
1470}
1471
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001472static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1473 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1474 return &SRExpr->getSymbol();
1475 }
1476
1477 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1478 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1479 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1480
1481 if (LHSSym)
1482 return LHSSym;
1483
1484 if (RHSSym)
1485 return RHSSym;
1486
1487 return nullptr;
1488 }
1489
1490 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1491 return getSingleMCSymbol(UExpr->getSubExpr());
1492
1493 return nullptr;
1494}
1495
1496static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1497 if (isa<MCSymbolRefExpr>(Expr))
1498 return 1;
1499
1500 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1501 return countMCSymbolRefExpr(BExpr->getLHS()) +
1502 countMCSymbolRefExpr(BExpr->getRHS());
1503
1504 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1505 return countMCSymbolRefExpr(UExpr->getSubExpr());
1506
1507 return 0;
1508}
1509
Jack Carter9e65aa32013-03-22 00:05:30 +00001510bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001511 MCStreamer &Out,
1512 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001513 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001514 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001515 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001516
Jack Carter9e65aa32013-03-22 00:05:30 +00001517 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001518
1519 if (MCID.isBranch() || MCID.isCall()) {
1520 const unsigned Opcode = Inst.getOpcode();
1521 MCOperand Offset;
1522
1523 switch (Opcode) {
1524 default:
1525 break;
Kai Nackee0245392015-01-27 19:11:28 +00001526 case Mips::BBIT0:
1527 case Mips::BBIT032:
1528 case Mips::BBIT1:
1529 case Mips::BBIT132:
1530 assert(hasCnMips() && "instruction only valid for octeon cpus");
1531 // Fall through
1532
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001533 case Mips::BEQ:
1534 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001535 case Mips::BEQ_MM:
1536 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001537 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001538 Offset = Inst.getOperand(2);
1539 if (!Offset.isImm())
1540 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001541 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001542 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001543 if (OffsetToAlignment(Offset.getImm(),
1544 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001545 return Error(IDLoc, "branch to misaligned address");
1546 break;
1547 case Mips::BGEZ:
1548 case Mips::BGTZ:
1549 case Mips::BLEZ:
1550 case Mips::BLTZ:
1551 case Mips::BGEZAL:
1552 case Mips::BLTZAL:
1553 case Mips::BC1F:
1554 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001555 case Mips::BGEZ_MM:
1556 case Mips::BGTZ_MM:
1557 case Mips::BLEZ_MM:
1558 case Mips::BLTZ_MM:
1559 case Mips::BGEZAL_MM:
1560 case Mips::BLTZAL_MM:
1561 case Mips::BC1F_MM:
1562 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001563 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001564 Offset = Inst.getOperand(1);
1565 if (!Offset.isImm())
1566 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001567 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001568 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001569 if (OffsetToAlignment(Offset.getImm(),
1570 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001571 return Error(IDLoc, "branch to misaligned address");
1572 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001573 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001574 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001575 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001576 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001577 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1578 Offset = Inst.getOperand(1);
1579 if (!Offset.isImm())
1580 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001581 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001582 return Error(IDLoc, "branch target out of range");
1583 if (OffsetToAlignment(Offset.getImm(), 2LL))
1584 return Error(IDLoc, "branch to misaligned address");
1585 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001586 }
1587 }
1588
Daniel Sandersa84989a2014-06-16 13:25:35 +00001589 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1590 // We still accept it but it is a normal nop.
1591 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1592 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1593 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1594 "nop instruction");
1595 }
1596
Kai Nackee0245392015-01-27 19:11:28 +00001597 if (hasCnMips()) {
1598 const unsigned Opcode = Inst.getOpcode();
1599 MCOperand Opnd;
1600 int Imm;
1601
1602 switch (Opcode) {
1603 default:
1604 break;
1605
1606 case Mips::BBIT0:
1607 case Mips::BBIT032:
1608 case Mips::BBIT1:
1609 case Mips::BBIT132:
1610 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1611 // The offset is handled above
1612 Opnd = Inst.getOperand(1);
1613 if (!Opnd.isImm())
1614 return Error(IDLoc, "expected immediate operand kind");
1615 Imm = Opnd.getImm();
1616 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1617 Opcode == Mips::BBIT1 ? 63 : 31))
1618 return Error(IDLoc, "immediate operand value out of range");
1619 if (Imm > 31) {
1620 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1621 : Mips::BBIT132);
1622 Inst.getOperand(1).setImm(Imm - 32);
1623 }
1624 break;
1625
Kai Nackee0245392015-01-27 19:11:28 +00001626 case Mips::SEQi:
1627 case Mips::SNEi:
1628 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1629 Opnd = Inst.getOperand(2);
1630 if (!Opnd.isImm())
1631 return Error(IDLoc, "expected immediate operand kind");
1632 Imm = Opnd.getImm();
1633 if (!isInt<10>(Imm))
1634 return Error(IDLoc, "immediate operand value out of range");
1635 break;
1636 }
1637 }
1638
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001639 // This expansion is not in a function called by tryExpandInstruction()
1640 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001641 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1642 inPicMode()) {
1643 warnIfNoMacro(IDLoc);
1644
1645 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1646
1647 // We can do this expansion if there's only 1 symbol in the argument
1648 // expression.
1649 if (countMCSymbolRefExpr(JalExpr) > 1)
1650 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1651
1652 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001653 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001654 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1655
1656 // FIXME: Add support for label+offset operands (currently causes an error).
1657 // FIXME: Add support for forward-declared local symbols.
1658 // FIXME: Add expansion for when the LargeGOT option is enabled.
1659 if (JalSym->isInSection() || JalSym->isTemporary()) {
1660 if (isABI_O32()) {
1661 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001662 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001663 // R_(MICRO)MIPS_GOT16 label
1664 // addiu $25, $25, 0
1665 // R_(MICRO)MIPS_LO16 label
1666 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001667 const MCExpr *Got16RelocExpr =
1668 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1669 const MCExpr *Lo16RelocExpr =
1670 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001671
Daniel Sandersa736b372016-04-29 13:33:12 +00001672 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1673 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1674 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1675 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001676 } else if (isABI_N32() || isABI_N64()) {
1677 // If it's a local symbol and the N32/N64 ABIs are being used,
1678 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001679 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001680 // R_(MICRO)MIPS_GOT_DISP label
1681 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001682 const MCExpr *GotDispRelocExpr =
1683 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001684
Daniel Sandersa736b372016-04-29 13:33:12 +00001685 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1686 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1687 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001688 }
1689 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001690 // If it's an external/weak symbol, we expand to:
1691 // lw/ld $25, 0($gp)
1692 // R_(MICRO)MIPS_CALL16 label
1693 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001694 const MCExpr *Call16RelocExpr =
1695 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001696
Daniel Sandersa736b372016-04-29 13:33:12 +00001697 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1698 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001699 }
1700
1701 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001702 if (IsCpRestoreSet && inMicroMipsMode())
1703 JalrInst.setOpcode(Mips::JALRS_MM);
1704 else
1705 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001706 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1707 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1708
1709 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1710 // This relocation is supposed to be an optimization hint for the linker
1711 // and is not necessary for correctness.
1712
1713 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001714 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001715 }
1716
Jack Carter9e65aa32013-03-22 00:05:30 +00001717 if (MCID.mayLoad() || MCID.mayStore()) {
1718 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001719 // reference or immediate we may have to expand instructions.
1720 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001721 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001722 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1723 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001724 MCOperand &Op = Inst.getOperand(i);
1725 if (Op.isImm()) {
1726 int MemOffset = Op.getImm();
1727 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001728 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001729 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001730 return false;
1731 }
1732 } else if (Op.isExpr()) {
1733 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001734 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001735 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001736 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001737 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001738 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001739 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001740 return false;
1741 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001742 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001743 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001744 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001745 }
1746 }
1747 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001748 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001749 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001750
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001751 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001752 if (MCID.mayLoad()) {
1753 // Try to create 16-bit GP relative load instruction.
1754 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1755 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1756 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1757 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1758 MCOperand &Op = Inst.getOperand(i);
1759 if (Op.isImm()) {
1760 int MemOffset = Op.getImm();
1761 MCOperand &DstReg = Inst.getOperand(0);
1762 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001763 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001764 getContext().getRegisterInfo()->getRegClass(
1765 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001766 (BaseReg.getReg() == Mips::GP ||
1767 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001768
Daniel Sandersa736b372016-04-29 13:33:12 +00001769 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1770 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001771 return false;
1772 }
1773 }
1774 }
1775 } // for
1776 } // if load
1777
1778 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1779
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001780 MCOperand Opnd;
1781 int Imm;
1782
1783 switch (Inst.getOpcode()) {
1784 default:
1785 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001786 case Mips::ADDIUSP_MM:
1787 Opnd = Inst.getOperand(0);
1788 if (!Opnd.isImm())
1789 return Error(IDLoc, "expected immediate operand kind");
1790 Imm = Opnd.getImm();
1791 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1792 Imm % 4 != 0)
1793 return Error(IDLoc, "immediate operand value out of range");
1794 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001795 case Mips::SLL16_MM:
1796 case Mips::SRL16_MM:
1797 Opnd = Inst.getOperand(2);
1798 if (!Opnd.isImm())
1799 return Error(IDLoc, "expected immediate operand kind");
1800 Imm = Opnd.getImm();
1801 if (Imm < 1 || Imm > 8)
1802 return Error(IDLoc, "immediate operand value out of range");
1803 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001804 case Mips::LI16_MM:
1805 Opnd = Inst.getOperand(1);
1806 if (!Opnd.isImm())
1807 return Error(IDLoc, "expected immediate operand kind");
1808 Imm = Opnd.getImm();
1809 if (Imm < -1 || Imm > 126)
1810 return Error(IDLoc, "immediate operand value out of range");
1811 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001812 case Mips::ADDIUR2_MM:
1813 Opnd = Inst.getOperand(2);
1814 if (!Opnd.isImm())
1815 return Error(IDLoc, "expected immediate operand kind");
1816 Imm = Opnd.getImm();
1817 if (!(Imm == 1 || Imm == -1 ||
1818 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1819 return Error(IDLoc, "immediate operand value out of range");
1820 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001821 case Mips::ANDI16_MM:
1822 Opnd = Inst.getOperand(2);
1823 if (!Opnd.isImm())
1824 return Error(IDLoc, "expected immediate operand kind");
1825 Imm = Opnd.getImm();
1826 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1827 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1828 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1829 return Error(IDLoc, "immediate operand value out of range");
1830 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001831 case Mips::LBU16_MM:
1832 Opnd = Inst.getOperand(2);
1833 if (!Opnd.isImm())
1834 return Error(IDLoc, "expected immediate operand kind");
1835 Imm = Opnd.getImm();
1836 if (Imm < -1 || Imm > 14)
1837 return Error(IDLoc, "immediate operand value out of range");
1838 break;
1839 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001840 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001841 Opnd = Inst.getOperand(2);
1842 if (!Opnd.isImm())
1843 return Error(IDLoc, "expected immediate operand kind");
1844 Imm = Opnd.getImm();
1845 if (Imm < 0 || Imm > 15)
1846 return Error(IDLoc, "immediate operand value out of range");
1847 break;
1848 case Mips::LHU16_MM:
1849 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001850 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001851 Opnd = Inst.getOperand(2);
1852 if (!Opnd.isImm())
1853 return Error(IDLoc, "expected immediate operand kind");
1854 Imm = Opnd.getImm();
1855 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1856 return Error(IDLoc, "immediate operand value out of range");
1857 break;
1858 case Mips::LW16_MM:
1859 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001860 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001861 Opnd = Inst.getOperand(2);
1862 if (!Opnd.isImm())
1863 return Error(IDLoc, "expected immediate operand kind");
1864 Imm = Opnd.getImm();
1865 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1866 return Error(IDLoc, "immediate operand value out of range");
1867 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001868 case Mips::ADDIUPC_MM:
1869 MCOperand Opnd = Inst.getOperand(1);
1870 if (!Opnd.isImm())
1871 return Error(IDLoc, "expected immediate operand kind");
1872 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001873 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001874 return Error(IDLoc, "immediate operand value out of range");
1875 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001876 }
1877 }
1878
Daniel Sandersd8c07762016-04-18 12:35:36 +00001879 bool FillDelaySlot =
1880 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
1881 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00001882 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001883
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001884 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001885 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001886 switch (ExpandResult) {
1887 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001888 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001889 break;
1890 case MER_Success:
1891 break;
1892 case MER_Fail:
1893 return true;
1894 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001895
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001896 // If this instruction has a delay slot and .set reorder is active,
1897 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00001898 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001899 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
1900 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001901 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001902
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001903 if ((Inst.getOpcode() == Mips::JalOneReg ||
1904 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1905 isPicAndNotNxxAbi()) {
1906 if (IsCpRestoreSet) {
1907 // We need a NOP between the JALR and the LW:
1908 // If .set reorder has been used, we've already emitted a NOP.
1909 // If .set noreorder has been used, we need to emit a NOP at this point.
1910 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00001911 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
1912 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001913
1914 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00001915 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001916 } else
1917 Warning(IDLoc, "no .cprestore used in PIC mode");
1918 }
1919
Jack Carter9e65aa32013-03-22 00:05:30 +00001920 return false;
1921}
1922
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001923MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001924MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
1925 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001926 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001927 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001928 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001929 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001930 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001931 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001932 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001933 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001934 case Mips::LoadAddrImm64:
1935 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1936 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1937 "expected immediate operand kind");
1938
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001939 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1940 Inst.getOperand(1),
1941 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001942 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001943 ? MER_Fail
1944 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001945 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001946 case Mips::LoadAddrReg64:
1947 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1948 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1949 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1950 "expected immediate operand kind");
1951
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001952 return expandLoadAddress(Inst.getOperand(0).getReg(),
1953 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1954 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001955 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001956 ? MER_Fail
1957 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001958 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001959 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001960 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
1961 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001962 case Mips::SWM_MM:
1963 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001964 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
1965 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001966 case Mips::JalOneReg:
1967 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001968 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00001969 case Mips::BneImm:
1970 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001971 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00001972 case Mips::BLT:
1973 case Mips::BLE:
1974 case Mips::BGE:
1975 case Mips::BGT:
1976 case Mips::BLTU:
1977 case Mips::BLEU:
1978 case Mips::BGEU:
1979 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001980 case Mips::BLTL:
1981 case Mips::BLEL:
1982 case Mips::BGEL:
1983 case Mips::BGTL:
1984 case Mips::BLTUL:
1985 case Mips::BLEUL:
1986 case Mips::BGEUL:
1987 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00001988 case Mips::BLTImmMacro:
1989 case Mips::BLEImmMacro:
1990 case Mips::BGEImmMacro:
1991 case Mips::BGTImmMacro:
1992 case Mips::BLTUImmMacro:
1993 case Mips::BLEUImmMacro:
1994 case Mips::BGEUImmMacro:
1995 case Mips::BGTUImmMacro:
1996 case Mips::BLTLImmMacro:
1997 case Mips::BLELImmMacro:
1998 case Mips::BGELImmMacro:
1999 case Mips::BGTLImmMacro:
2000 case Mips::BLTULImmMacro:
2001 case Mips::BLEULImmMacro:
2002 case Mips::BGEULImmMacro:
2003 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002004 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002005 case Mips::SDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002006 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2007 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002008 case Mips::DSDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002009 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2010 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002011 case Mips::UDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002012 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2013 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002014 case Mips::DUDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002015 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2016 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002017 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002018 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2019 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002020 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002021 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002022 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002023 case Mips::PseudoTRUNC_W_D:
2024 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2025 : MER_Success;
2026 case Mips::Ulh:
2027 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2028 case Mips::Ulhu:
2029 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2030 case Mips::Ulw:
2031 return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2032 case Mips::NORImm:
2033 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002034 case Mips::ADDi:
2035 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002036 case Mips::SLTi:
2037 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002038 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2039 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2040 int64_t ImmValue = Inst.getOperand(2).getImm();
2041 if (isInt<16>(ImmValue))
2042 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002043 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2044 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002045 }
2046 return MER_NotAMacro;
2047 case Mips::ANDi:
2048 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002049 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002050 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2051 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2052 int64_t ImmValue = Inst.getOperand(2).getImm();
2053 if (isUInt<16>(ImmValue))
2054 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002055 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2056 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002057 }
2058 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002059 case Mips::ROL:
2060 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002061 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002062 case Mips::ROLImm:
2063 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002064 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002065 case Mips::DROL:
2066 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002067 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002068 case Mips::DROLImm:
2069 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002070 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002071 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002072 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002073 }
Jack Carter30a59822012-10-04 04:03:53 +00002074}
Jack Carter92995f12012-10-06 00:53:28 +00002075
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002076bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002077 MCStreamer &Out,
2078 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002079 MipsTargetStreamer &TOut = getTargetStreamer();
2080
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002081 // Create a JALR instruction which is going to replace the pseudo-JAL.
2082 MCInst JalrInst;
2083 JalrInst.setLoc(IDLoc);
2084 const MCOperand FirstRegOp = Inst.getOperand(0);
2085 const unsigned Opcode = Inst.getOpcode();
2086
2087 if (Opcode == Mips::JalOneReg) {
2088 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002089 if (IsCpRestoreSet && inMicroMipsMode()) {
2090 JalrInst.setOpcode(Mips::JALRS16_MM);
2091 JalrInst.addOperand(FirstRegOp);
2092 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002093 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002094 JalrInst.addOperand(FirstRegOp);
2095 } else {
2096 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002097 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002098 JalrInst.addOperand(FirstRegOp);
2099 }
2100 } else if (Opcode == Mips::JalTwoReg) {
2101 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002102 if (IsCpRestoreSet && inMicroMipsMode())
2103 JalrInst.setOpcode(Mips::JALRS_MM);
2104 else
2105 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002106 JalrInst.addOperand(FirstRegOp);
2107 const MCOperand SecondRegOp = Inst.getOperand(1);
2108 JalrInst.addOperand(SecondRegOp);
2109 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002110 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002111
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002112 // If .set reorder is active and branch instruction has a delay slot,
2113 // emit a NOP after it.
2114 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002115 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2116 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2117 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002118
2119 return false;
2120}
2121
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002122/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002123template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002124 unsigned BitNum = findFirstSet(x);
2125
2126 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2127}
2128
2129/// Load (or add) an immediate into a register.
2130///
2131/// @param ImmValue The immediate to load.
2132/// @param DstReg The register that will hold the immediate.
2133/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2134/// for a simple initialization.
2135/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2136/// @param IsAddress True if the immediate represents an address. False if it
2137/// is an integer.
2138/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002139bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002140 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002141 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2142 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002143 MipsTargetStreamer &TOut = getTargetStreamer();
2144
Toma Tabacu00e98672015-05-01 12:19:27 +00002145 if (!Is32BitImm && !isGP64bit()) {
2146 Error(IDLoc, "instruction requires a 64-bit architecture");
2147 return true;
2148 }
2149
Daniel Sanders03f9c012015-07-14 12:24:22 +00002150 if (Is32BitImm) {
2151 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2152 // Sign extend up to 64-bit so that the predicates match the hardware
2153 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2154 // true.
2155 ImmValue = SignExtend64<32>(ImmValue);
2156 } else {
2157 Error(IDLoc, "instruction requires a 32-bit immediate");
2158 return true;
2159 }
2160 }
2161
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002162 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2163 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2164
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002165 bool UseSrcReg = false;
2166 if (SrcReg != Mips::NoRegister)
2167 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002168
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002169 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002170 if (UseSrcReg &&
2171 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002172 // At this point we need AT to perform the expansions and we exit if it is
2173 // not available.
2174 unsigned ATReg = getATReg(IDLoc);
2175 if (!ATReg)
2176 return true;
2177 TmpReg = ATReg;
2178 }
2179
Daniel Sanders03f9c012015-07-14 12:24:22 +00002180 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002181 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002182 SrcReg = ZeroReg;
2183
2184 // This doesn't quite follow the usual ABI expectations for N32 but matches
2185 // traditional assembler behaviour. N32 would normally use addiu for both
2186 // integers and addresses.
2187 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002188 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002189 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002190 }
2191
Daniel Sandersa736b372016-04-29 13:33:12 +00002192 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002193 return false;
2194 }
2195
2196 if (isUInt<16>(ImmValue)) {
2197 unsigned TmpReg = DstReg;
2198 if (SrcReg == DstReg) {
2199 TmpReg = getATReg(IDLoc);
2200 if (!TmpReg)
2201 return true;
2202 }
2203
Daniel Sandersa736b372016-04-29 13:33:12 +00002204 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002205 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002206 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002207 return false;
2208 }
2209
2210 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002211 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002212
Toma Tabacu79588102015-04-29 10:19:56 +00002213 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2214 uint16_t Bits15To0 = ImmValue & 0xffff;
2215
Toma Tabacua3d056f2015-05-15 09:42:11 +00002216 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002217 // Traditional behaviour seems to special case this particular value. It's
2218 // not clear why other masks are handled differently.
2219 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002220 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2221 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002222 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002223 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002224 return false;
2225 }
2226
2227 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002228 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002229 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2230 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002231 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002232 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002233 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002234 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002235 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002236 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002237
Daniel Sandersa736b372016-04-29 13:33:12 +00002238 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002239 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002240 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002241 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002242 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002243 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002244 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002245
2246 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2247 if (Is32BitImm) {
2248 Error(IDLoc, "instruction requires a 32-bit immediate");
2249 return true;
2250 }
2251
2252 // Traditionally, these immediates are shifted as little as possible and as
2253 // such we align the most significant bit to bit 15 of our temporary.
2254 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2255 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2256 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2257 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002258 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2259 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002260
2261 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002262 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002263
2264 return false;
2265 }
2266
2267 warnIfNoMacro(IDLoc);
2268
2269 // The remaining case is packed with a sequence of dsll and ori with zeros
2270 // being omitted and any neighbouring dsll's being coalesced.
2271 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2272
2273 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2274 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002275 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002276 return false;
2277
2278 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2279 // skip it and defer the shift to the next chunk.
2280 unsigned ShiftCarriedForwards = 16;
2281 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2282 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2283
2284 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002285 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2286 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002287 ShiftCarriedForwards = 0;
2288 }
2289
2290 ShiftCarriedForwards += 16;
2291 }
2292 ShiftCarriedForwards -= 16;
2293
2294 // Finish any remaining shifts left by trailing zeros.
2295 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002296 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002297
2298 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002299 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002300
Matheus Almeida3813d572014-06-19 14:39:14 +00002301 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002302}
Jack Carter92995f12012-10-06 00:53:28 +00002303
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002304bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002305 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002306 const MCOperand &ImmOp = Inst.getOperand(1);
2307 assert(ImmOp.isImm() && "expected immediate operand kind");
2308 const MCOperand &DstRegOp = Inst.getOperand(0);
2309 assert(DstRegOp.isReg() && "expected register operand kind");
2310
2311 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002312 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002313 return true;
2314
2315 return false;
2316}
2317
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002318bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2319 const MCOperand &Offset,
2320 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002321 MCStreamer &Out,
2322 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002323 // la can't produce a usable address when addresses are 64-bit.
2324 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2325 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2326 // We currently can't do this because we depend on the equality
2327 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2328 Error(IDLoc, "la used to load 64-bit address");
2329 // Continue as if we had 'dla' instead.
2330 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002331 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002332
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002333 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002334 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002335 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002336 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002337 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002338
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002339 if (!Offset.isImm())
2340 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002341 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002342
Scott Egerton24557012016-01-21 15:11:01 +00002343 if (!ABI.ArePtrs64bit()) {
2344 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2345 Is32BitAddress = true;
2346 }
2347
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002348 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002349 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002350}
2351
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002352bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2353 unsigned DstReg, unsigned SrcReg,
2354 bool Is32BitSym, SMLoc IDLoc,
2355 MCStreamer &Out,
2356 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002357 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacu81496c12015-05-20 08:54:45 +00002358 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002359
Daniel Sandersd5a89412015-10-05 13:19:29 +00002360 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002361 const MipsMCExpr *HiExpr =
2362 MipsMCExpr::create(MipsMCExpr::MEK_HI, Symbol, getContext());
2363 const MipsMCExpr *LoExpr =
2364 MipsMCExpr::create(MipsMCExpr::MEK_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002365
Toma Tabacufb9d1252015-06-22 12:08:39 +00002366 bool UseSrcReg = SrcReg != Mips::NoRegister;
2367
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002368 // This is the 64-bit symbol address expansion.
2369 if (ABI.ArePtrs64bit() && isGP64bit()) {
2370 // We always need AT for the 64-bit expansion.
2371 // If it is not available we exit.
2372 unsigned ATReg = getATReg(IDLoc);
2373 if (!ATReg)
2374 return true;
2375
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002376 const MipsMCExpr *HighestExpr =
2377 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, Symbol, getContext());
2378 const MipsMCExpr *HigherExpr =
2379 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002380
Scott Egerton24557012016-01-21 15:11:01 +00002381 if (UseSrcReg &&
2382 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2383 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002384 // If $rs is the same as $rd:
2385 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2386 // daddiu $at, $at, %higher(sym)
2387 // dsll $at, $at, 16
2388 // daddiu $at, $at, %hi(sym)
2389 // dsll $at, $at, 16
2390 // daddiu $at, $at, %lo(sym)
2391 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002392 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2393 STI);
2394 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2395 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2396 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2397 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2398 IDLoc, STI);
2399 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2400 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2401 IDLoc, STI);
2402 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002403
2404 return false;
2405 }
2406
2407 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2408 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2409 // lui $at, %hi(sym)
2410 // daddiu $rd, $rd, %higher(sym)
2411 // daddiu $at, $at, %lo(sym)
2412 // dsll32 $rd, $rd, 0
2413 // daddu $rd, $rd, $at
2414 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002415 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2416 STI);
2417 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2418 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2419 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2420 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2421 IDLoc, STI);
2422 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2423 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002424 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002425 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002426
2427 return false;
2428 }
2429
2430 // And now, the 32-bit symbol address expansion:
2431 // If $rs is the same as $rd:
2432 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2433 // ori $at, $at, %lo(sym)
2434 // addu $rd, $at, $rd
2435 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2436 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2437 // ori $rd, $rd, %lo(sym)
2438 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002439 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002440 if (UseSrcReg &&
2441 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002442 // If $rs is the same as $rd, we need to use AT.
2443 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002444 unsigned ATReg = getATReg(IDLoc);
2445 if (!ATReg)
2446 return true;
2447 TmpReg = ATReg;
2448 }
2449
Daniel Sandersa736b372016-04-29 13:33:12 +00002450 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2451 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2452 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002453
Toma Tabacufb9d1252015-06-22 12:08:39 +00002454 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002455 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002456 else
Scott Egerton24557012016-01-21 15:11:01 +00002457 assert(
2458 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002459
Toma Tabacu674825c2015-06-16 12:16:24 +00002460 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002461}
2462
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002463bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2464 MCStreamer &Out,
2465 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002466 MipsTargetStreamer &TOut = getTargetStreamer();
2467
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002468 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2469 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002470
2471 MCOperand Offset = Inst.getOperand(0);
2472 if (Offset.isExpr()) {
2473 Inst.clear();
2474 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002475 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2476 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2477 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002478 } else {
2479 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002480 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002481 // If offset fits into 11 bits then this instruction becomes microMIPS
2482 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002483 if (inMicroMipsMode())
2484 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002485 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002486 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002487 Error(IDLoc, "branch target out of range");
2488 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2489 Error(IDLoc, "branch to misaligned address");
2490 Inst.clear();
2491 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002492 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2493 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2494 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002495 }
2496 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002497 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002498
Zoran Jovanovicada70912015-09-07 11:56:37 +00002499 // If .set reorder is active and branch instruction has a delay slot,
2500 // emit a NOP after it.
2501 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2502 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002503 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002504
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002505 return false;
2506}
2507
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002508bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2509 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002510 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002511 const MCOperand &DstRegOp = Inst.getOperand(0);
2512 assert(DstRegOp.isReg() && "expected register operand kind");
2513
2514 const MCOperand &ImmOp = Inst.getOperand(1);
2515 assert(ImmOp.isImm() && "expected immediate operand kind");
2516
2517 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002518 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2519 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002520
2521 unsigned OpCode = 0;
2522 switch(Inst.getOpcode()) {
2523 case Mips::BneImm:
2524 OpCode = Mips::BNE;
2525 break;
2526 case Mips::BeqImm:
2527 OpCode = Mips::BEQ;
2528 break;
2529 default:
2530 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2531 break;
2532 }
2533
2534 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002535 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002536 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2537 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002538 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002539 warnIfNoMacro(IDLoc);
2540
2541 unsigned ATReg = getATReg(IDLoc);
2542 if (!ATReg)
2543 return true;
2544
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002545 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002546 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002547 return true;
2548
Daniel Sandersa736b372016-04-29 13:33:12 +00002549 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002550 }
2551 return false;
2552}
2553
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002554void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002555 const MCSubtargetInfo *STI, bool IsLoad,
2556 bool IsImmOpnd) {
2557 if (IsLoad) {
2558 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2559 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002560 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002561 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2562}
2563
2564void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2565 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2566 MipsTargetStreamer &TOut = getTargetStreamer();
2567
2568 unsigned DstReg = Inst.getOperand(0).getReg();
2569 unsigned BaseReg = Inst.getOperand(1).getReg();
2570
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002571 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002572 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2573 unsigned DstRegClassID =
2574 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2575 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2576 (DstRegClassID == Mips::GPR64RegClassID);
2577
2578 if (IsImmOpnd) {
2579 // Try to use DstReg as the temporary.
2580 if (IsGPR && (BaseReg != DstReg)) {
2581 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2582 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2583 STI);
2584 return;
2585 }
2586
Matheus Almeida7de68e72014-06-18 14:46:05 +00002587 // At this point we need AT to perform the expansions and we exit if it is
2588 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002589 unsigned ATReg = getATReg(IDLoc);
2590 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002591 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002592
2593 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2594 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2595 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002596 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002597
Daniel Sandersfba875f2016-04-29 13:43:45 +00002598 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002599 MCOperand LoOperand = MCOperand::createExpr(
2600 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2601 MCOperand HiOperand = MCOperand::createExpr(
2602 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002603
2604 // Try to use DstReg as the temporary.
2605 if (IsGPR && (BaseReg != DstReg)) {
2606 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2607 LoOperand, DstReg, IDLoc, STI);
2608 return;
2609 }
2610
2611 // At this point we need AT to perform the expansions and we exit if it is
2612 // not available.
2613 unsigned ATReg = getATReg(IDLoc);
2614 if (!ATReg)
2615 return;
2616
2617 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2618 LoOperand, ATReg, IDLoc, STI);
2619}
2620
2621void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2622 const MCSubtargetInfo *STI,
2623 bool IsImmOpnd) {
2624 MipsTargetStreamer &TOut = getTargetStreamer();
2625
2626 unsigned SrcReg = Inst.getOperand(0).getReg();
2627 unsigned BaseReg = Inst.getOperand(1).getReg();
2628
2629 unsigned ATReg = getATReg(IDLoc);
2630 if (!ATReg)
2631 return;
2632
2633 if (IsImmOpnd) {
2634 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2635 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2636 return;
2637 }
2638
2639 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002640 MCOperand LoOperand = MCOperand::createExpr(
2641 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2642 MCOperand HiOperand = MCOperand::createExpr(
2643 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002644 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2645 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002646}
2647
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002648bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2649 MCStreamer &Out,
2650 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002651 unsigned OpNum = Inst.getNumOperands();
2652 unsigned Opcode = Inst.getOpcode();
2653 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2654
2655 assert (Inst.getOperand(OpNum - 1).isImm() &&
2656 Inst.getOperand(OpNum - 2).isReg() &&
2657 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2658
2659 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2660 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002661 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2662 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2663 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2664 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002665 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002666 if (inMicroMipsMode() && hasMips32r6())
2667 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2668 else
2669 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2670 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002671
2672 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002673 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002674 return false;
2675}
2676
Toma Tabacu1a108322015-06-17 13:20:24 +00002677bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002678 MCStreamer &Out,
2679 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002680 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002681 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002682 unsigned PseudoOpcode = Inst.getOpcode();
2683 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002684 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002685 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2686
2687 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002688 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002689
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002690 unsigned TrgReg;
2691 if (TrgOp.isReg())
2692 TrgReg = TrgOp.getReg();
2693 else if (TrgOp.isImm()) {
2694 warnIfNoMacro(IDLoc);
2695 EmittedNoMacroWarning = true;
2696
2697 TrgReg = getATReg(IDLoc);
2698 if (!TrgReg)
2699 return true;
2700
2701 switch(PseudoOpcode) {
2702 default:
2703 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2704 case Mips::BLTImmMacro:
2705 PseudoOpcode = Mips::BLT;
2706 break;
2707 case Mips::BLEImmMacro:
2708 PseudoOpcode = Mips::BLE;
2709 break;
2710 case Mips::BGEImmMacro:
2711 PseudoOpcode = Mips::BGE;
2712 break;
2713 case Mips::BGTImmMacro:
2714 PseudoOpcode = Mips::BGT;
2715 break;
2716 case Mips::BLTUImmMacro:
2717 PseudoOpcode = Mips::BLTU;
2718 break;
2719 case Mips::BLEUImmMacro:
2720 PseudoOpcode = Mips::BLEU;
2721 break;
2722 case Mips::BGEUImmMacro:
2723 PseudoOpcode = Mips::BGEU;
2724 break;
2725 case Mips::BGTUImmMacro:
2726 PseudoOpcode = Mips::BGTU;
2727 break;
2728 case Mips::BLTLImmMacro:
2729 PseudoOpcode = Mips::BLTL;
2730 break;
2731 case Mips::BLELImmMacro:
2732 PseudoOpcode = Mips::BLEL;
2733 break;
2734 case Mips::BGELImmMacro:
2735 PseudoOpcode = Mips::BGEL;
2736 break;
2737 case Mips::BGTLImmMacro:
2738 PseudoOpcode = Mips::BGTL;
2739 break;
2740 case Mips::BLTULImmMacro:
2741 PseudoOpcode = Mips::BLTUL;
2742 break;
2743 case Mips::BLEULImmMacro:
2744 PseudoOpcode = Mips::BLEUL;
2745 break;
2746 case Mips::BGEULImmMacro:
2747 PseudoOpcode = Mips::BGEUL;
2748 break;
2749 case Mips::BGTULImmMacro:
2750 PseudoOpcode = Mips::BGTUL;
2751 break;
2752 }
2753
2754 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002755 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002756 return true;
2757 }
2758
Toma Tabacu1a108322015-06-17 13:20:24 +00002759 switch (PseudoOpcode) {
2760 case Mips::BLT:
2761 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002762 case Mips::BLTL:
2763 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002764 AcceptsEquality = false;
2765 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002766 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2767 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002768 ZeroSrcOpcode = Mips::BGTZ;
2769 ZeroTrgOpcode = Mips::BLTZ;
2770 break;
2771 case Mips::BLE:
2772 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002773 case Mips::BLEL:
2774 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002775 AcceptsEquality = true;
2776 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002777 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2778 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002779 ZeroSrcOpcode = Mips::BGEZ;
2780 ZeroTrgOpcode = Mips::BLEZ;
2781 break;
2782 case Mips::BGE:
2783 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002784 case Mips::BGEL:
2785 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002786 AcceptsEquality = true;
2787 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002788 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2789 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002790 ZeroSrcOpcode = Mips::BLEZ;
2791 ZeroTrgOpcode = Mips::BGEZ;
2792 break;
2793 case Mips::BGT:
2794 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002795 case Mips::BGTL:
2796 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002797 AcceptsEquality = false;
2798 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002799 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2800 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002801 ZeroSrcOpcode = Mips::BLTZ;
2802 ZeroTrgOpcode = Mips::BGTZ;
2803 break;
2804 default:
2805 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2806 }
2807
Toma Tabacu1a108322015-06-17 13:20:24 +00002808 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2809 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2810 if (IsSrcRegZero && IsTrgRegZero) {
2811 // FIXME: All of these Opcode-specific if's are needed for compatibility
2812 // with GAS' behaviour. However, they may not generate the most efficient
2813 // code in some circumstances.
2814 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002815 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2816 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002817 return false;
2818 }
2819 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002820 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2821 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002822 Warning(IDLoc, "branch is always taken");
2823 return false;
2824 }
2825 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002826 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2827 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002828 Warning(IDLoc, "branch is always taken");
2829 return false;
2830 }
2831 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002832 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2833 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002834 return false;
2835 }
2836 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002837 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2838 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002839 return false;
2840 }
2841 if (AcceptsEquality) {
2842 // If both registers are $0 and the pseudo-branch accepts equality, it
2843 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00002844 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2845 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002846 Warning(IDLoc, "branch is always taken");
2847 return false;
2848 }
2849 // If both registers are $0 and the pseudo-branch does not accept
2850 // equality, it will never be taken, so we don't have to emit anything.
2851 return false;
2852 }
2853 if (IsSrcRegZero || IsTrgRegZero) {
2854 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2855 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2856 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2857 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2858 // the pseudo-branch will never be taken, so we don't emit anything.
2859 // This only applies to unsigned pseudo-branches.
2860 return false;
2861 }
2862 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2863 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2864 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2865 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2866 // the pseudo-branch will always be taken, so we emit an unconditional
2867 // branch.
2868 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00002869 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2870 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002871 Warning(IDLoc, "branch is always taken");
2872 return false;
2873 }
2874 if (IsUnsigned) {
2875 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2876 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2877 // the pseudo-branch will be taken only when the non-zero register is
2878 // different from 0, so we emit a BNEZ.
2879 //
2880 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2881 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2882 // the pseudo-branch will be taken only when the non-zero register is
2883 // equal to 0, so we emit a BEQZ.
2884 //
2885 // Because only BLEU and BGEU branch on equality, we can use the
2886 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00002887 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2888 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2889 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002890 return false;
2891 }
2892 // If we have a signed pseudo-branch and one of the registers is $0,
2893 // we can use an appropriate compare-to-zero branch. We select which one
2894 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00002895 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2896 IsSrcRegZero ? TrgReg : SrcReg,
2897 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002898 return false;
2899 }
2900
2901 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2902 // expansions. If it is not available, we return.
2903 unsigned ATRegNum = getATReg(IDLoc);
2904 if (!ATRegNum)
2905 return true;
2906
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002907 if (!EmittedNoMacroWarning)
2908 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002909
2910 // SLT fits well with 2 of our 4 pseudo-branches:
2911 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2912 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2913 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2914 // This is accomplished by using a BNEZ with the result of the SLT.
2915 //
2916 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2917 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2918 // Because only BGE and BLE branch on equality, we can use the
2919 // AcceptsEquality variable to decide when to emit the BEQZ.
2920 // Note that the order of the SLT arguments doesn't change between
2921 // opposites.
2922 //
2923 // The same applies to the unsigned variants, except that SLTu is used
2924 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00002925 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2926 ReverseOrderSLT ? TrgReg : SrcReg,
2927 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002928
Daniel Sandersa736b372016-04-29 13:33:12 +00002929 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2930 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2931 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2932 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002933 return false;
2934}
2935
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002936bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2937 const MCSubtargetInfo *STI, const bool IsMips64,
2938 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002939 MipsTargetStreamer &TOut = getTargetStreamer();
2940
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002941 if (hasMips32r6()) {
2942 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2943 return false;
2944 }
2945
2946 warnIfNoMacro(IDLoc);
2947
2948 const MCOperand &RsRegOp = Inst.getOperand(0);
2949 assert(RsRegOp.isReg() && "expected register operand kind");
2950 unsigned RsReg = RsRegOp.getReg();
2951
2952 const MCOperand &RtRegOp = Inst.getOperand(1);
2953 assert(RtRegOp.isReg() && "expected register operand kind");
2954 unsigned RtReg = RtRegOp.getReg();
2955 unsigned DivOp;
2956 unsigned ZeroReg;
2957
2958 if (IsMips64) {
2959 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2960 ZeroReg = Mips::ZERO_64;
2961 } else {
2962 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2963 ZeroReg = Mips::ZERO;
2964 }
2965
2966 bool UseTraps = useTraps();
2967
2968 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2969 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2970 Warning(IDLoc, "dividing zero by zero");
2971 if (IsMips64) {
2972 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2973 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002974 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002975 return false;
2976 }
2977
Daniel Sandersa736b372016-04-29 13:33:12 +00002978 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002979 return false;
2980 }
2981 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00002982 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002983 return false;
2984 }
2985 }
2986
2987 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2988 Warning(IDLoc, "division by zero");
2989 if (Signed) {
2990 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002991 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002992 return false;
2993 }
2994
Daniel Sandersa736b372016-04-29 13:33:12 +00002995 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002996 return false;
2997 }
2998 }
2999
3000 // FIXME: The values for these two BranchTarget variables may be different in
3001 // micromips. These magic numbers need to be removed.
3002 unsigned BranchTargetNoTraps;
3003 unsigned BranchTarget;
3004
3005 if (UseTraps) {
3006 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003007 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003008 } else {
3009 BranchTarget = IsMips64 ? 20 : 16;
3010 BranchTargetNoTraps = 8;
3011 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003012 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003013 }
3014
Daniel Sandersa736b372016-04-29 13:33:12 +00003015 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003016
3017 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003018 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003019
3020 if (!Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003021 TOut.emitR(Mips::MFLO, RsReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003022 return false;
3023 }
3024
3025 unsigned ATReg = getATReg(IDLoc);
3026 if (!ATReg)
3027 return true;
3028
Daniel Sandersa736b372016-04-29 13:33:12 +00003029 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003030 if (IsMips64) {
3031 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003032 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3033 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3034 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003035 } else {
3036 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003037 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3038 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003039 }
3040
3041 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003042 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003043 else {
3044 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003045 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3046 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3047 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003048 }
Daniel Sandersa736b372016-04-29 13:33:12 +00003049 TOut.emitR(Mips::MFLO, RsReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003050 return false;
3051}
3052
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003053bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003054 SMLoc IDLoc, MCStreamer &Out,
3055 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003056 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003057
3058 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3059 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3060 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3061
3062 unsigned FirstReg = Inst.getOperand(0).getReg();
3063 unsigned SecondReg = Inst.getOperand(1).getReg();
3064 unsigned ThirdReg = Inst.getOperand(2).getReg();
3065
3066 if (hasMips1() && !hasMips2()) {
3067 unsigned ATReg = getATReg(IDLoc);
3068 if (!ATReg)
3069 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003070 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3071 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3072 TOut.emitNop(IDLoc, STI);
3073 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3074 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3075 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3076 TOut.emitNop(IDLoc, STI);
3077 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3078 : Mips::CVT_W_S,
3079 FirstReg, SecondReg, IDLoc, STI);
3080 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3081 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003082 return false;
3083 }
3084
Daniel Sandersa736b372016-04-29 13:33:12 +00003085 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3086 : Mips::TRUNC_W_S,
3087 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003088
3089 return false;
3090}
3091
Daniel Sanders6394ee52015-10-15 14:52:58 +00003092bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003093 MCStreamer &Out, const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003094 MipsTargetStreamer &TOut = getTargetStreamer();
3095
Toma Tabacud88d79c2015-06-23 14:39:42 +00003096 if (hasMips32r6() || hasMips64r6()) {
3097 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3098 return false;
3099 }
3100
3101 warnIfNoMacro(IDLoc);
3102
3103 const MCOperand &DstRegOp = Inst.getOperand(0);
3104 assert(DstRegOp.isReg() && "expected register operand kind");
3105
3106 const MCOperand &SrcRegOp = Inst.getOperand(1);
3107 assert(SrcRegOp.isReg() && "expected register operand kind");
3108
3109 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3110 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3111
3112 unsigned DstReg = DstRegOp.getReg();
3113 unsigned SrcReg = SrcRegOp.getReg();
3114 int64_t OffsetValue = OffsetImmOp.getImm();
3115
3116 // NOTE: We always need AT for ULHU, as it is always used as the source
3117 // register for one of the LBu's.
3118 unsigned ATReg = getATReg(IDLoc);
3119 if (!ATReg)
3120 return true;
3121
3122 // When the value of offset+1 does not fit in 16 bits, we have to load the
3123 // offset in AT, (D)ADDu the original source register (if there was one), and
3124 // then use AT as the source register for the 2 generated LBu's.
3125 bool LoadedOffsetInAT = false;
3126 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3127 LoadedOffsetInAT = true;
3128
3129 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003130 true, IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003131 return true;
3132
3133 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3134 // because it will make our output more similar to GAS'. For example,
3135 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3136 // instead of just an "ori $1, $9, 32768".
3137 // NOTE: If there is no source register specified in the ULHU, the parser
3138 // will interpret it as $0.
3139 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003140 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003141 }
3142
3143 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3144 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3145 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3146
3147 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3148 if (isLittle()) {
3149 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3150 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3151 } else {
3152 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3153 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3154 }
3155
3156 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3157
Daniel Sandersa736b372016-04-29 13:33:12 +00003158 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3159 FirstLbuOffset, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003160
Daniel Sandersa736b372016-04-29 13:33:12 +00003161 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3162 STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003163
Daniel Sandersa736b372016-04-29 13:33:12 +00003164 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003165
Daniel Sandersa736b372016-04-29 13:33:12 +00003166 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003167
3168 return false;
3169}
3170
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003171bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3172 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003173 MipsTargetStreamer &TOut = getTargetStreamer();
3174
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003175 if (hasMips32r6() || hasMips64r6()) {
3176 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3177 return false;
3178 }
3179
3180 const MCOperand &DstRegOp = Inst.getOperand(0);
3181 assert(DstRegOp.isReg() && "expected register operand kind");
3182
3183 const MCOperand &SrcRegOp = Inst.getOperand(1);
3184 assert(SrcRegOp.isReg() && "expected register operand kind");
3185
3186 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3187 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3188
3189 unsigned SrcReg = SrcRegOp.getReg();
3190 int64_t OffsetValue = OffsetImmOp.getImm();
3191 unsigned ATReg = 0;
3192
3193 // When the value of offset+3 does not fit in 16 bits, we have to load the
3194 // offset in AT, (D)ADDu the original source register (if there was one), and
3195 // then use AT as the source register for the generated LWL and LWR.
3196 bool LoadedOffsetInAT = false;
3197 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3198 ATReg = getATReg(IDLoc);
3199 if (!ATReg)
3200 return true;
3201 LoadedOffsetInAT = true;
3202
3203 warnIfNoMacro(IDLoc);
3204
3205 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003206 true, IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003207 return true;
3208
3209 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3210 // because it will make our output more similar to GAS'. For example,
3211 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3212 // instead of just an "ori $1, $9, 32768".
3213 // NOTE: If there is no source register specified in the ULW, the parser
3214 // will interpret it as $0.
3215 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003216 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003217 }
3218
3219 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3220 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3221 if (isLittle()) {
3222 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3223 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3224 } else {
3225 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3226 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3227 }
3228
Daniel Sandersa736b372016-04-29 13:33:12 +00003229 TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3230 STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003231
Daniel Sandersa736b372016-04-29 13:33:12 +00003232 TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
3233 IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003234
3235 return false;
3236}
3237
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003238bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003239 MCStreamer &Out,
3240 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003241 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003242
3243 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3244 assert (Inst.getOperand(0).isReg() &&
3245 Inst.getOperand(1).isReg() &&
3246 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3247
3248 unsigned ATReg = Mips::NoRegister;
3249 unsigned FinalDstReg = Mips::NoRegister;
3250 unsigned DstReg = Inst.getOperand(0).getReg();
3251 unsigned SrcReg = Inst.getOperand(1).getReg();
3252 int64_t ImmValue = Inst.getOperand(2).getImm();
3253
3254 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3255
3256 unsigned FinalOpcode = Inst.getOpcode();
3257
3258 if (DstReg == SrcReg) {
3259 ATReg = getATReg(Inst.getLoc());
3260 if (!ATReg)
3261 return true;
3262 FinalDstReg = DstReg;
3263 DstReg = ATReg;
3264 }
3265
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003266 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003267 switch (FinalOpcode) {
3268 default:
3269 llvm_unreachable("unimplemented expansion");
3270 case (Mips::ADDi):
3271 FinalOpcode = Mips::ADD;
3272 break;
3273 case (Mips::ADDiu):
3274 FinalOpcode = Mips::ADDu;
3275 break;
3276 case (Mips::ANDi):
3277 FinalOpcode = Mips::AND;
3278 break;
3279 case (Mips::NORImm):
3280 FinalOpcode = Mips::NOR;
3281 break;
3282 case (Mips::ORi):
3283 FinalOpcode = Mips::OR;
3284 break;
3285 case (Mips::SLTi):
3286 FinalOpcode = Mips::SLT;
3287 break;
3288 case (Mips::SLTiu):
3289 FinalOpcode = Mips::SLTu;
3290 break;
3291 case (Mips::XORi):
3292 FinalOpcode = Mips::XOR;
3293 break;
3294 }
3295
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003296 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003297 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003298 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003299 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003300 return false;
3301 }
3302 return true;
3303}
3304
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003305bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3306 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003307 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003308 unsigned ATReg = Mips::NoRegister;
3309 unsigned DReg = Inst.getOperand(0).getReg();
3310 unsigned SReg = Inst.getOperand(1).getReg();
3311 unsigned TReg = Inst.getOperand(2).getReg();
3312 unsigned TmpReg = DReg;
3313
3314 unsigned FirstShift = Mips::NOP;
3315 unsigned SecondShift = Mips::NOP;
3316
3317 if (hasMips32r2()) {
3318
3319 if (DReg == SReg) {
3320 TmpReg = getATReg(Inst.getLoc());
3321 if (!TmpReg)
3322 return true;
3323 }
3324
3325 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003326 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3327 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003328 return false;
3329 }
3330
3331 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003332 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003333 return false;
3334 }
3335
3336 return true;
3337 }
3338
3339 if (hasMips32()) {
3340
3341 switch (Inst.getOpcode()) {
3342 default:
3343 llvm_unreachable("unexpected instruction opcode");
3344 case Mips::ROL:
3345 FirstShift = Mips::SRLV;
3346 SecondShift = Mips::SLLV;
3347 break;
3348 case Mips::ROR:
3349 FirstShift = Mips::SLLV;
3350 SecondShift = Mips::SRLV;
3351 break;
3352 }
3353
3354 ATReg = getATReg(Inst.getLoc());
3355 if (!ATReg)
3356 return true;
3357
Daniel Sandersa736b372016-04-29 13:33:12 +00003358 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3359 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3360 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3361 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003362
3363 return false;
3364 }
3365
3366 return true;
3367}
3368
3369bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003370 MCStreamer &Out,
3371 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003372 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003373 unsigned ATReg = Mips::NoRegister;
3374 unsigned DReg = Inst.getOperand(0).getReg();
3375 unsigned SReg = Inst.getOperand(1).getReg();
3376 int64_t ImmValue = Inst.getOperand(2).getImm();
3377
3378 unsigned FirstShift = Mips::NOP;
3379 unsigned SecondShift = Mips::NOP;
3380
3381 if (hasMips32r2()) {
3382
3383 if (Inst.getOpcode() == Mips::ROLImm) {
3384 uint64_t MaxShift = 32;
3385 uint64_t ShiftValue = ImmValue;
3386 if (ImmValue != 0)
3387 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003388 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003389 return false;
3390 }
3391
3392 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003393 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003394 return false;
3395 }
3396
3397 return true;
3398 }
3399
3400 if (hasMips32()) {
3401
3402 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003403 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003404 return false;
3405 }
3406
3407 switch (Inst.getOpcode()) {
3408 default:
3409 llvm_unreachable("unexpected instruction opcode");
3410 case Mips::ROLImm:
3411 FirstShift = Mips::SLL;
3412 SecondShift = Mips::SRL;
3413 break;
3414 case Mips::RORImm:
3415 FirstShift = Mips::SRL;
3416 SecondShift = Mips::SLL;
3417 break;
3418 }
3419
3420 ATReg = getATReg(Inst.getLoc());
3421 if (!ATReg)
3422 return true;
3423
Daniel Sandersa736b372016-04-29 13:33:12 +00003424 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3425 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3426 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003427
3428 return false;
3429 }
3430
3431 return true;
3432}
3433
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003434bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3435 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003436 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003437 unsigned ATReg = Mips::NoRegister;
3438 unsigned DReg = Inst.getOperand(0).getReg();
3439 unsigned SReg = Inst.getOperand(1).getReg();
3440 unsigned TReg = Inst.getOperand(2).getReg();
3441 unsigned TmpReg = DReg;
3442
3443 unsigned FirstShift = Mips::NOP;
3444 unsigned SecondShift = Mips::NOP;
3445
3446 if (hasMips64r2()) {
3447
3448 if (TmpReg == SReg) {
3449 TmpReg = getATReg(Inst.getLoc());
3450 if (!TmpReg)
3451 return true;
3452 }
3453
3454 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003455 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3456 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003457 return false;
3458 }
3459
3460 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003461 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003462 return false;
3463 }
3464
3465 return true;
3466 }
3467
3468 if (hasMips64()) {
3469
3470 switch (Inst.getOpcode()) {
3471 default:
3472 llvm_unreachable("unexpected instruction opcode");
3473 case Mips::DROL:
3474 FirstShift = Mips::DSRLV;
3475 SecondShift = Mips::DSLLV;
3476 break;
3477 case Mips::DROR:
3478 FirstShift = Mips::DSLLV;
3479 SecondShift = Mips::DSRLV;
3480 break;
3481 }
3482
3483 ATReg = getATReg(Inst.getLoc());
3484 if (!ATReg)
3485 return true;
3486
Daniel Sandersa736b372016-04-29 13:33:12 +00003487 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3488 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3489 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3490 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003491
3492 return false;
3493 }
3494
3495 return true;
3496}
3497
3498bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003499 MCStreamer &Out,
3500 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003501 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003502 unsigned ATReg = Mips::NoRegister;
3503 unsigned DReg = Inst.getOperand(0).getReg();
3504 unsigned SReg = Inst.getOperand(1).getReg();
3505 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3506
3507 unsigned FirstShift = Mips::NOP;
3508 unsigned SecondShift = Mips::NOP;
3509
3510 MCInst TmpInst;
3511
3512 if (hasMips64r2()) {
3513
3514 unsigned FinalOpcode = Mips::NOP;
3515 if (ImmValue == 0)
3516 FinalOpcode = Mips::DROTR;
3517 else if (ImmValue % 32 == 0)
3518 FinalOpcode = Mips::DROTR32;
3519 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3520 if (Inst.getOpcode() == Mips::DROLImm)
3521 FinalOpcode = Mips::DROTR32;
3522 else
3523 FinalOpcode = Mips::DROTR;
3524 } else if (ImmValue >= 33) {
3525 if (Inst.getOpcode() == Mips::DROLImm)
3526 FinalOpcode = Mips::DROTR;
3527 else
3528 FinalOpcode = Mips::DROTR32;
3529 }
3530
3531 uint64_t ShiftValue = ImmValue % 32;
3532 if (Inst.getOpcode() == Mips::DROLImm)
3533 ShiftValue = (32 - ImmValue % 32) % 32;
3534
Daniel Sandersa736b372016-04-29 13:33:12 +00003535 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003536
3537 return false;
3538 }
3539
3540 if (hasMips64()) {
3541
3542 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003543 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003544 return false;
3545 }
3546
3547 switch (Inst.getOpcode()) {
3548 default:
3549 llvm_unreachable("unexpected instruction opcode");
3550 case Mips::DROLImm:
3551 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3552 FirstShift = Mips::DSLL;
3553 SecondShift = Mips::DSRL32;
3554 }
3555 if (ImmValue == 32) {
3556 FirstShift = Mips::DSLL32;
3557 SecondShift = Mips::DSRL32;
3558 }
3559 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3560 FirstShift = Mips::DSLL32;
3561 SecondShift = Mips::DSRL;
3562 }
3563 break;
3564 case Mips::DRORImm:
3565 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3566 FirstShift = Mips::DSRL;
3567 SecondShift = Mips::DSLL32;
3568 }
3569 if (ImmValue == 32) {
3570 FirstShift = Mips::DSRL32;
3571 SecondShift = Mips::DSLL32;
3572 }
3573 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3574 FirstShift = Mips::DSRL32;
3575 SecondShift = Mips::DSLL;
3576 }
3577 break;
3578 }
3579
3580 ATReg = getATReg(Inst.getLoc());
3581 if (!ATReg)
3582 return true;
3583
Daniel Sandersa736b372016-04-29 13:33:12 +00003584 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3585 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3586 Inst.getLoc(), STI);
3587 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003588
3589 return false;
3590 }
3591
3592 return true;
3593}
3594
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003595bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3596 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003597 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003598 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3599 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3600
Daniel Sandersa736b372016-04-29 13:33:12 +00003601 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003602 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003603 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003604 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003605 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3606 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003607
3608 return false;
3609}
3610
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003611void MipsAsmParser::createCpRestoreMemOp(bool IsLoad, int StackOffset,
3612 SMLoc IDLoc, MCStreamer &Out,
3613 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003614 MipsTargetStreamer &TOut = getTargetStreamer();
3615
Daniel Sanders7225cd52016-04-29 16:16:49 +00003616 if (IsLoad) {
3617 TOut.emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, StackOffset,
3618 Mips::GP, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003619 return;
3620 }
3621
Daniel Sanders7225cd52016-04-29 16:16:49 +00003622 unsigned ATReg = getATReg(IDLoc);
3623 if (!ATReg)
3624 return;
3625
3626 TOut.emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, StackOffset, ATReg,
3627 IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003628}
3629
Matheus Almeida595fcab2014-06-11 15:05:56 +00003630unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3631 // As described by the Mips32r2 spec, the registers Rd and Rs for
3632 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00003633 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00003634 // and registers Rd and Base for microMIPS lwp instruction
Matheus Almeida595fcab2014-06-11 15:05:56 +00003635 unsigned Opcode = Inst.getOpcode();
3636
Zlatko Buljanae720db2016-04-22 06:44:34 +00003637 if ((Opcode == Mips::JALR_HB || Opcode == Mips::JALRC_HB_MMR6) &&
Matheus Almeida595fcab2014-06-11 15:05:56 +00003638 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3639 return Match_RequiresDifferentSrcAndDst;
Zlatko Buljanba553a62016-05-09 08:07:28 +00003640 else if ((Opcode == Mips::LWP_MM || Opcode == Mips::LWP_MMR6) &&
3641 (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()))
3642 return Match_RequiresDifferentSrcAndDst;
Matheus Almeida595fcab2014-06-11 15:05:56 +00003643
3644 return Match_Success;
3645}
3646
Daniel Sanders52da7af2015-11-06 12:11:03 +00003647static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3648 uint64_t ErrorInfo) {
3649 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3650 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3651 if (ErrorLoc == SMLoc())
3652 return Loc;
3653 return ErrorLoc;
3654 }
3655 return Loc;
3656}
3657
David Blaikie960ea3f2014-06-08 16:18:35 +00003658bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3659 OperandVector &Operands,
3660 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003661 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003662 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003663
Jack Carterb4dbc172012-09-05 23:34:03 +00003664 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00003665 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003666 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003667
3668 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003669 case Match_Success: {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003670 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00003671 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003672 return false;
3673 }
3674 case Match_MissingFeature:
3675 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3676 return true;
3677 case Match_InvalidOperand: {
3678 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003679 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003680 if (ErrorInfo >= Operands.size())
3681 return Error(IDLoc, "too few operands for instruction");
3682
Daniel Sanders52da7af2015-11-06 12:11:03 +00003683 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003684 if (ErrorLoc == SMLoc())
3685 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003686 }
3687
3688 return Error(ErrorLoc, "invalid operand for instruction");
3689 }
3690 case Match_MnemonicFail:
3691 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003692 case Match_RequiresDifferentSrcAndDst:
3693 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003694 case Match_Immz:
3695 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003696 case Match_UImm1_0:
3697 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3698 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003699 case Match_UImm2_0:
3700 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3701 "expected 2-bit unsigned immediate");
3702 case Match_UImm2_1:
3703 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3704 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003705 case Match_UImm3_0:
3706 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3707 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003708 case Match_UImm4_0:
3709 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3710 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003711 case Match_SImm4_0:
3712 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3713 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003714 case Match_UImm5_0:
3715 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3716 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00003717 case Match_SImm5_0:
3718 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3719 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003720 case Match_UImm5_1:
3721 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3722 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003723 case Match_UImm5_32:
3724 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3725 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003726 case Match_UImm5_33:
3727 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3728 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003729 case Match_UImm5_0_Report_UImm6:
3730 // This is used on UImm5 operands that have a corresponding UImm5_32
3731 // operand to avoid confusing the user.
3732 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3733 "expected 6-bit unsigned immediate");
3734 case Match_UImm5_Lsl2:
3735 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3736 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003737 case Match_UImmRange2_64:
3738 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3739 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003740 case Match_UImm6_0:
3741 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3742 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00003743 case Match_UImm6_Lsl2:
3744 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3745 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00003746 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00003747 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3748 "expected 6-bit signed immediate");
3749 case Match_UImm7_0:
3750 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3751 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00003752 case Match_UImm7_N1:
3753 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3754 "expected immediate in range -1 .. 126");
3755 case Match_SImm7_Lsl2:
3756 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3757 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003758 case Match_UImm8_0:
3759 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3760 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003761 case Match_UImm10_0:
3762 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3763 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00003764 case Match_SImm10_0:
3765 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3766 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00003767 case Match_SImm11_0:
3768 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3769 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003770 case Match_UImm16:
3771 case Match_UImm16_Relaxed:
3772 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3773 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003774 case Match_SImm16:
3775 case Match_SImm16_Relaxed:
3776 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3777 "expected 16-bit signed immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003778 case Match_UImm20_0:
3779 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3780 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00003781 case Match_UImm26_0:
3782 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3783 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00003784 case Match_SImm32:
3785 case Match_SImm32_Relaxed:
3786 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3787 "expected 32-bit signed immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00003788 case Match_MemSImm9:
3789 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3790 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00003791 case Match_MemSImm10:
3792 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3793 "expected memory with 10-bit signed offset");
3794 case Match_MemSImm10Lsl1:
3795 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3796 "expected memory with 11-bit signed offset and multiple of 2");
3797 case Match_MemSImm10Lsl2:
3798 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3799 "expected memory with 12-bit signed offset and multiple of 4");
3800 case Match_MemSImm10Lsl3:
3801 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3802 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00003803 case Match_MemSImm11:
3804 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3805 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00003806 case Match_MemSImm12:
3807 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3808 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003809 case Match_MemSImm16:
3810 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3811 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00003812 }
Craig Topper589ceee2015-01-03 08:16:34 +00003813
3814 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003815}
3816
Toma Tabacud9d344b2015-04-27 14:05:04 +00003817void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3818 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3819 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3820 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003821}
3822
Toma Tabacu81496c12015-05-20 08:54:45 +00003823void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3824 if (!AssemblerOptions.back()->isMacro())
3825 Warning(Loc, "macro instruction expanded into multiple instructions");
3826}
3827
Daniel Sandersef638fe2014-10-03 15:37:37 +00003828void
3829MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3830 SMRange Range, bool ShowColors) {
3831 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003832 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003833 ShowColors);
3834}
3835
Jack Carter1ac53222013-02-20 23:11:17 +00003836int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003837 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003838
Vladimir Medic4c299852013-11-06 11:27:05 +00003839 CC = StringSwitch<unsigned>(Name)
3840 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003841 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003842 .Case("a0", 4)
3843 .Case("a1", 5)
3844 .Case("a2", 6)
3845 .Case("a3", 7)
3846 .Case("v0", 2)
3847 .Case("v1", 3)
3848 .Case("s0", 16)
3849 .Case("s1", 17)
3850 .Case("s2", 18)
3851 .Case("s3", 19)
3852 .Case("s4", 20)
3853 .Case("s5", 21)
3854 .Case("s6", 22)
3855 .Case("s7", 23)
3856 .Case("k0", 26)
3857 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003858 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003859 .Case("sp", 29)
3860 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003861 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003862 .Case("ra", 31)
3863 .Case("t0", 8)
3864 .Case("t1", 9)
3865 .Case("t2", 10)
3866 .Case("t3", 11)
3867 .Case("t4", 12)
3868 .Case("t5", 13)
3869 .Case("t6", 14)
3870 .Case("t7", 15)
3871 .Case("t8", 24)
3872 .Case("t9", 25)
3873 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003874
Toma Tabacufda445c2014-09-15 15:33:01 +00003875 if (!(isABI_N32() || isABI_N64()))
3876 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003877
Daniel Sandersef638fe2014-10-03 15:37:37 +00003878 if (12 <= CC && CC <= 15) {
3879 // Name is one of t4-t7
3880 AsmToken RegTok = getLexer().peekTok();
3881 SMRange RegRange = RegTok.getLocRange();
3882
3883 StringRef FixedName = StringSwitch<StringRef>(Name)
3884 .Case("t4", "t0")
3885 .Case("t5", "t1")
3886 .Case("t6", "t2")
3887 .Case("t7", "t3")
3888 .Default("");
3889 assert(FixedName != "" && "Register name is not one of t4-t7.");
3890
3891 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3892 "Did you mean $" + FixedName + "?", RegRange);
3893 }
3894
Toma Tabacufda445c2014-09-15 15:33:01 +00003895 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3896 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3897 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3898 if (8 <= CC && CC <= 11)
3899 CC += 4;
3900
3901 if (CC == -1)
3902 CC = StringSwitch<unsigned>(Name)
3903 .Case("a4", 8)
3904 .Case("a5", 9)
3905 .Case("a6", 10)
3906 .Case("a7", 11)
3907 .Case("kt0", 26)
3908 .Case("kt1", 27)
3909 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003910
3911 return CC;
3912}
Jack Carterd0bd6422013-04-18 00:41:53 +00003913
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003914int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3915 int CC;
3916
3917 CC = StringSwitch<unsigned>(Name)
3918 .Case("hwr_cpunum", 0)
3919 .Case("hwr_synci_step", 1)
3920 .Case("hwr_cc", 2)
3921 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003922 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003923 .Default(-1);
3924
3925 return CC;
3926}
3927
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003928int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003929
Jack Cartera63b16a2012-09-07 00:23:42 +00003930 if (Name[0] == 'f') {
3931 StringRef NumString = Name.substr(1);
3932 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003933 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003934 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003935 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003936 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003937 return IntVal;
3938 }
3939 return -1;
3940}
Jack Cartera63b16a2012-09-07 00:23:42 +00003941
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003942int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3943
3944 if (Name.startswith("fcc")) {
3945 StringRef NumString = Name.substr(3);
3946 unsigned IntVal;
3947 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003948 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003949 if (IntVal > 7) // There are only 8 fcc registers.
3950 return -1;
3951 return IntVal;
3952 }
3953 return -1;
3954}
3955
3956int MipsAsmParser::matchACRegisterName(StringRef Name) {
3957
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003958 if (Name.startswith("ac")) {
3959 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003960 unsigned IntVal;
3961 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003962 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003963 if (IntVal > 3) // There are only 3 acc registers.
3964 return -1;
3965 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003966 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003967 return -1;
3968}
Jack Carterd0bd6422013-04-18 00:41:53 +00003969
Jack Carter5dc8ac92013-09-25 23:50:44 +00003970int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3971 unsigned IntVal;
3972
3973 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3974 return -1;
3975
3976 if (IntVal > 31)
3977 return -1;
3978
3979 return IntVal;
3980}
3981
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003982int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3983 int CC;
3984
3985 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003986 .Case("msair", 0)
3987 .Case("msacsr", 1)
3988 .Case("msaaccess", 2)
3989 .Case("msasave", 3)
3990 .Case("msamodify", 4)
3991 .Case("msarequest", 5)
3992 .Case("msamap", 6)
3993 .Case("msaunmap", 7)
3994 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003995
3996 return CC;
3997}
3998
Toma Tabacu89a712b2015-04-15 10:48:56 +00003999unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004000 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004001 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004002 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004003 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004004 return 0;
4005 }
4006 unsigned AT = getReg(
4007 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004008 return AT;
4009}
Jack Carter0b744b32012-10-04 02:29:46 +00004010
Jack Carterd0bd6422013-04-18 00:41:53 +00004011unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004012 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004013}
4014
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004015unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004016 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00004017 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004018}
4019
Jack Carter873c7242013-01-12 01:03:14 +00004020int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004021 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00004022 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00004023 return -1;
4024
Jack Carter873c7242013-01-12 01:03:14 +00004025 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00004026}
4027
Toma Tabacu13964452014-09-04 13:23:44 +00004028bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004029 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004030 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004031
Jack Carter30a59822012-10-04 04:03:53 +00004032 // Check if the current operand has a custom associated parser, if so, try to
4033 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004034 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4035 if (ResTy == MatchOperand_Success)
4036 return false;
4037 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4038 // there was a match, but an error occurred, in which case, just return that
4039 // the operand parsing failed.
4040 if (ResTy == MatchOperand_ParseFail)
4041 return true;
4042
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004043 DEBUG(dbgs() << ".. Generic Parser\n");
4044
Jack Carterb4dbc172012-09-05 23:34:03 +00004045 switch (getLexer().getKind()) {
4046 default:
4047 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4048 return true;
4049 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004050 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004051 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004052
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004053 // Almost all registers have been parsed by custom parsers. There is only
4054 // one exception to this. $zero (and it's alias $0) will reach this point
4055 // for div, divu, and similar instructions because it is not an operand
4056 // to the instruction definition but an explicit register. Special case
4057 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004058 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004059 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004060
Jack Carterd0bd6422013-04-18 00:41:53 +00004061 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004062 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004063 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004064 return true;
4065
Jack Carter873c7242013-01-12 01:03:14 +00004066 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004067 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004068 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004069 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004070 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004071
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004072 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004073 return false;
4074 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004075 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004076 case AsmToken::LParen:
4077 case AsmToken::Minus:
4078 case AsmToken::Plus:
4079 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004080 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004081 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004082 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004083 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004084 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004085 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004086 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004087 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004088 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004089 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004090 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004091 return true;
4092
Jack Carter873c7242013-01-12 01:03:14 +00004093 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4094
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004095 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004096 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004097 } // case AsmToken::Percent
4098 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004099 return true;
4100}
4101
Vladimir Medic4c299852013-11-06 11:27:05 +00004102const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004103 StringRef RelocStr) {
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004104 if (RelocStr == "hi(%neg(%gp_rel")
4105 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext());
4106 else if (RelocStr == "lo(%neg(%gp_rel")
4107 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004108
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004109 MipsMCExpr::MipsExprKind Kind =
4110 StringSwitch<MipsMCExpr::MipsExprKind>(RelocStr)
4111 .Case("call16", MipsMCExpr::MEK_GOT_CALL)
4112 .Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
4113 .Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
4114 .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
4115 .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
4116 .Case("got", MipsMCExpr::MEK_GOT)
4117 .Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
4118 .Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
4119 .Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
4120 .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
4121 .Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
4122 .Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
4123 .Case("gp_rel", MipsMCExpr::MEK_GPREL)
4124 .Case("hi", MipsMCExpr::MEK_HI)
4125 .Case("higher", MipsMCExpr::MEK_HIGHER)
4126 .Case("highest", MipsMCExpr::MEK_HIGHEST)
4127 .Case("lo", MipsMCExpr::MEK_LO)
4128 .Case("neg", MipsMCExpr::MEK_NEG)
4129 .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
4130 .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
4131 .Case("tlsgd", MipsMCExpr::MEK_TLSGD)
4132 .Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
4133 .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
4134 .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
4135 .Default(MipsMCExpr::MEK_None);
Jack Carterb5cf5902013-04-17 00:18:04 +00004136
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004137 assert(Kind != MipsMCExpr::MEK_None);
4138 return MipsMCExpr::create(Kind, Expr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004139}
4140
4141bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4142
4143 switch (Expr->getKind()) {
4144 case MCExpr::Constant:
4145 return true;
4146 case MCExpr::SymbolRef:
4147 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4148 case MCExpr::Binary:
4149 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4150 if (!isEvaluated(BE->getLHS()))
4151 return false;
4152 return isEvaluated(BE->getRHS());
4153 }
4154 case MCExpr::Unary:
4155 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004156 case MCExpr::Target:
4157 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004158 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004159 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004160}
Jack Carterd0bd6422013-04-18 00:41:53 +00004161
Jack Carterb5cf5902013-04-17 00:18:04 +00004162bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004163 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004164 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004165 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004166 if (Tok.isNot(AsmToken::Identifier))
4167 return true;
4168
Yaron Keren075759a2015-03-30 15:42:36 +00004169 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004170
Jack Carterd0bd6422013-04-18 00:41:53 +00004171 Parser.Lex(); // Eat the identifier.
4172 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004173 const MCExpr *IdVal;
4174 SMLoc EndLoc;
4175
4176 if (getLexer().getKind() == AsmToken::LParen) {
4177 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004178 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004179 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004180 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004181 const AsmToken &nextTok = Parser.getTok();
4182 if (nextTok.isNot(AsmToken::Identifier))
4183 return true;
4184 Str += "(%";
4185 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004186 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004187 if (getLexer().getKind() != AsmToken::LParen)
4188 return true;
4189 } else
4190 break;
4191 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004192 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004193 return true;
4194
4195 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004196 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004197
4198 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004199 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004200
Jack Carterd0bd6422013-04-18 00:41:53 +00004201 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004202 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004203}
4204
Jack Carterb4dbc172012-09-05 23:34:03 +00004205bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4206 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004207 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004208 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004209 if (ResTy == MatchOperand_Success) {
4210 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004211 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004212 StartLoc = Operand.getStartLoc();
4213 EndLoc = Operand.getEndLoc();
4214
4215 // AFAIK, we only support numeric registers and named GPR's in CFI
4216 // directives.
4217 // Don't worry about eating tokens before failing. Using an unrecognised
4218 // register is a parse error.
4219 if (Operand.isGPRAsmReg()) {
4220 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004221 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004222 }
4223
4224 return (RegNo == (unsigned)-1);
4225 }
4226
4227 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004228 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004229}
4230
Jack Carterb5cf5902013-04-17 00:18:04 +00004231bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004232 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004233 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004234 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004235 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004236
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004237 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004238 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004239 ++NumOfLParen;
4240 }
Jack Carter873c7242013-01-12 01:03:14 +00004241
Jack Carterd0bd6422013-04-18 00:41:53 +00004242 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004243 default:
4244 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004245 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004246 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004247 case AsmToken::Integer:
4248 case AsmToken::Minus:
4249 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004250 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004251 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004252 else
4253 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004254 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004255 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004256 break;
Jack Carter873c7242013-01-12 01:03:14 +00004257 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004258 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004259 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004260 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004261}
4262
David Blaikie960ea3f2014-06-08 16:18:35 +00004263MipsAsmParser::OperandMatchResultTy
4264MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004265 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004266 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004267 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004268 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004269 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004270 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004271 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004272 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004273
Jack Carterb5cf5902013-04-17 00:18:04 +00004274 if (getLexer().getKind() == AsmToken::LParen) {
4275 Parser.Lex();
4276 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004277 }
4278
Jack Carterb5cf5902013-04-17 00:18:04 +00004279 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004280 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004281 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004282
Jack Carterd0bd6422013-04-18 00:41:53 +00004283 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004284 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004285 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004286 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004287 SMLoc E =
4288 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004289 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004290 return MatchOperand_Success;
4291 }
4292 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004293 SMLoc E =
4294 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004295
Jack Carterd0bd6422013-04-18 00:41:53 +00004296 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004297 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004298 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004299 S, E, *this);
4300 Operands.push_back(
4301 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004302 return MatchOperand_Success;
4303 }
4304 Error(Parser.getTok().getLoc(), "'(' expected");
4305 return MatchOperand_ParseFail;
4306 }
4307
Jack Carterd0bd6422013-04-18 00:41:53 +00004308 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004309 }
4310
Toma Tabacu13964452014-09-04 13:23:44 +00004311 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004312 if (Res != MatchOperand_Success)
4313 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004314
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004315 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004316 Error(Parser.getTok().getLoc(), "')' expected");
4317 return MatchOperand_ParseFail;
4318 }
4319
Jack Carter873c7242013-01-12 01:03:14 +00004320 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4321
Jack Carterd0bd6422013-04-18 00:41:53 +00004322 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004323
Craig Topper062a2ba2014-04-25 05:30:21 +00004324 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004325 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004326
Jack Carterd0bd6422013-04-18 00:41:53 +00004327 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004328 std::unique_ptr<MipsOperand> op(
4329 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004330 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004331 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004332 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004333 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004334 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4335 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004336 if (IdVal->evaluateAsAbsolute(Imm))
4337 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004338 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004339 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004340 getContext());
4341 }
4342
David Blaikie960ea3f2014-06-08 16:18:35 +00004343 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004344 return MatchOperand_Success;
4345}
4346
David Blaikie960ea3f2014-06-08 16:18:35 +00004347bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004348 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004349 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004350 if (Sym) {
4351 SMLoc S = Parser.getTok().getLoc();
4352 const MCExpr *Expr;
4353 if (Sym->isVariable())
4354 Expr = Sym->getVariableValue();
4355 else
4356 return false;
4357 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004358 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004359 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004360 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004361 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004362 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004363 if (ResTy == MatchOperand_Success) {
4364 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004365 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004366 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004367 llvm_unreachable("Should never ParseFail");
4368 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004369 }
4370 } else if (Expr->getKind() == MCExpr::Constant) {
4371 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004372 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004373 Operands.push_back(
4374 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004375 return true;
4376 }
4377 }
4378 return false;
4379}
Jack Carterd0bd6422013-04-18 00:41:53 +00004380
Jack Carter873c7242013-01-12 01:03:14 +00004381MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004382MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004383 StringRef Identifier,
4384 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004385 int Index = matchCPURegisterName(Identifier);
4386 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004387 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004388 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4389 return MatchOperand_Success;
4390 }
4391
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004392 Index = matchHWRegsRegisterName(Identifier);
4393 if (Index != -1) {
4394 Operands.push_back(MipsOperand::createHWRegsReg(
4395 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4396 return MatchOperand_Success;
4397 }
4398
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004399 Index = matchFPURegisterName(Identifier);
4400 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004401 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004402 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4403 return MatchOperand_Success;
4404 }
4405
4406 Index = matchFCCRegisterName(Identifier);
4407 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004408 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004409 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4410 return MatchOperand_Success;
4411 }
4412
4413 Index = matchACRegisterName(Identifier);
4414 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004415 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004416 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4417 return MatchOperand_Success;
4418 }
4419
4420 Index = matchMSA128RegisterName(Identifier);
4421 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004422 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004423 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4424 return MatchOperand_Success;
4425 }
4426
4427 Index = matchMSA128CtrlRegisterName(Identifier);
4428 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004429 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004430 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4431 return MatchOperand_Success;
4432 }
4433
4434 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004435}
4436
4437MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004438MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004439 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004440 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004441
4442 if (Token.is(AsmToken::Identifier)) {
4443 DEBUG(dbgs() << ".. identifier\n");
4444 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004445 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004446 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004447 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004448 } else if (Token.is(AsmToken::Integer)) {
4449 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004450 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004451 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4452 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004453 return MatchOperand_Success;
4454 }
4455
4456 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4457
4458 return MatchOperand_NoMatch;
4459}
4460
David Blaikie960ea3f2014-06-08 16:18:35 +00004461MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004462MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004463 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004464 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004465
4466 auto Token = Parser.getTok();
4467
4468 SMLoc S = Token.getLoc();
4469
4470 if (Token.isNot(AsmToken::Dollar)) {
4471 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4472 if (Token.is(AsmToken::Identifier)) {
4473 if (searchSymbolAlias(Operands))
4474 return MatchOperand_Success;
4475 }
4476 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4477 return MatchOperand_NoMatch;
4478 }
4479 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004480
Toma Tabacu13964452014-09-04 13:23:44 +00004481 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004482 if (ResTy == MatchOperand_Success) {
4483 Parser.Lex(); // $
4484 Parser.Lex(); // identifier
4485 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004486 return ResTy;
4487}
4488
4489MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004490MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004491 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004492 switch (getLexer().getKind()) {
4493 default:
4494 return MatchOperand_NoMatch;
4495 case AsmToken::LParen:
4496 case AsmToken::Minus:
4497 case AsmToken::Plus:
4498 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004499 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004500 case AsmToken::String:
4501 break;
4502 }
4503
4504 const MCExpr *IdVal;
4505 SMLoc S = Parser.getTok().getLoc();
4506 if (getParser().parseExpression(IdVal))
4507 return MatchOperand_ParseFail;
4508
4509 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4510 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4511 return MatchOperand_Success;
4512}
4513
David Blaikie960ea3f2014-06-08 16:18:35 +00004514MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004515MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004516 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004517 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004518
4519 SMLoc S = getLexer().getLoc();
4520
4521 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004522 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004523 if (ResTy != MatchOperand_NoMatch)
4524 return ResTy;
4525
Daniel Sanders315386c2014-04-01 10:40:14 +00004526 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004527 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004528 if (ResTy != MatchOperand_NoMatch)
4529 return ResTy;
4530
Daniel Sandersffd84362014-04-01 10:41:48 +00004531 const MCExpr *Expr = nullptr;
4532 if (Parser.parseExpression(Expr)) {
4533 // We have no way of knowing if a symbol was consumed so we must ParseFail
4534 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004535 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004536 Operands.push_back(
4537 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004538 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004539}
4540
Vladimir Medic2b953d02013-10-01 09:48:56 +00004541MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004542MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004543 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004544 const MCExpr *IdVal;
4545 // If the first token is '$' we may have register operand.
4546 if (Parser.getTok().is(AsmToken::Dollar))
4547 return MatchOperand_NoMatch;
4548 SMLoc S = Parser.getTok().getLoc();
4549 if (getParser().parseExpression(IdVal))
4550 return MatchOperand_ParseFail;
4551 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004552 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004553 int64_t Val = MCE->getValue();
4554 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4555 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004556 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004557 return MatchOperand_Success;
4558}
4559
Matheus Almeida779c5932013-11-18 12:32:49 +00004560MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004561MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004562 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004563 switch (getLexer().getKind()) {
4564 default:
4565 return MatchOperand_NoMatch;
4566 case AsmToken::LParen:
4567 case AsmToken::Plus:
4568 case AsmToken::Minus:
4569 case AsmToken::Integer:
4570 break;
4571 }
4572
4573 const MCExpr *Expr;
4574 SMLoc S = Parser.getTok().getLoc();
4575
4576 if (getParser().parseExpression(Expr))
4577 return MatchOperand_ParseFail;
4578
4579 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004580 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004581 Error(S, "expected immediate value");
4582 return MatchOperand_ParseFail;
4583 }
4584
4585 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4586 // and because the CPU always adds one to the immediate field, the allowed
4587 // range becomes 1..4. We'll only check the range here and will deal
4588 // with the addition/subtraction when actually decoding/encoding
4589 // the instruction.
4590 if (Val < 1 || Val > 4) {
4591 Error(S, "immediate not in range (1..4)");
4592 return MatchOperand_ParseFail;
4593 }
4594
Jack Carter3b2c96e2014-01-22 23:31:38 +00004595 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004596 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004597 return MatchOperand_Success;
4598}
4599
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004600MipsAsmParser::OperandMatchResultTy
4601MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4602 MCAsmParser &Parser = getParser();
4603 SmallVector<unsigned, 10> Regs;
4604 unsigned RegNo;
4605 unsigned PrevReg = Mips::NoRegister;
4606 bool RegRange = false;
4607 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4608
4609 if (Parser.getTok().isNot(AsmToken::Dollar))
4610 return MatchOperand_ParseFail;
4611
4612 SMLoc S = Parser.getTok().getLoc();
4613 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4614 SMLoc E = getLexer().getLoc();
4615 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4616 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4617 if (RegRange) {
4618 // Remove last register operand because registers from register range
4619 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004620 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4621 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004622 Regs.push_back(RegNo);
4623 } else {
4624 unsigned TmpReg = PrevReg + 1;
4625 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004626 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4627 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4628 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004629 Error(E, "invalid register operand");
4630 return MatchOperand_ParseFail;
4631 }
4632
4633 PrevReg = TmpReg;
4634 Regs.push_back(TmpReg++);
4635 }
4636 }
4637
4638 RegRange = false;
4639 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004640 if ((PrevReg == Mips::NoRegister) &&
4641 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4642 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004643 Error(E, "$16 or $31 expected");
4644 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004645 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4646 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4647 !isGP64bit()) ||
4648 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4649 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4650 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004651 Error(E, "invalid register operand");
4652 return MatchOperand_ParseFail;
4653 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004654 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4655 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4656 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004657 Error(E, "consecutive register numbers expected");
4658 return MatchOperand_ParseFail;
4659 }
4660
4661 Regs.push_back(RegNo);
4662 }
4663
4664 if (Parser.getTok().is(AsmToken::Minus))
4665 RegRange = true;
4666
4667 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4668 !Parser.getTok().isNot(AsmToken::Comma)) {
4669 Error(E, "',' or '-' expected");
4670 return MatchOperand_ParseFail;
4671 }
4672
4673 Lex(); // Consume comma or minus
4674 if (Parser.getTok().isNot(AsmToken::Dollar))
4675 break;
4676
4677 PrevReg = RegNo;
4678 }
4679
4680 SMLoc E = Parser.getTok().getLoc();
4681 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4682 parseMemOperand(Operands);
4683 return MatchOperand_Success;
4684}
4685
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004686MipsAsmParser::OperandMatchResultTy
4687MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4688 MCAsmParser &Parser = getParser();
4689
4690 SMLoc S = Parser.getTok().getLoc();
4691 if (parseAnyRegister(Operands) != MatchOperand_Success)
4692 return MatchOperand_ParseFail;
4693
4694 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00004695 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00004696
Benjamin Kramer2b68d152016-05-09 10:31:17 +00004697 Operands.pop_back();
4698 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004699 return MatchOperand_Success;
4700}
4701
Zoran Jovanovic41688672015-02-10 16:36:20 +00004702MipsAsmParser::OperandMatchResultTy
4703MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4704 MCAsmParser &Parser = getParser();
4705 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4706 SmallVector<unsigned, 10> Regs;
4707
4708 if (Parser.getTok().isNot(AsmToken::Dollar))
4709 return MatchOperand_ParseFail;
4710
4711 SMLoc S = Parser.getTok().getLoc();
4712
4713 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4714 return MatchOperand_ParseFail;
4715
4716 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4717 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4718 Regs.push_back(RegNo);
4719
4720 SMLoc E = Parser.getTok().getLoc();
4721 if (Parser.getTok().isNot(AsmToken::Comma)) {
4722 Error(E, "',' expected");
4723 return MatchOperand_ParseFail;
4724 }
4725
4726 // Remove comma.
4727 Parser.Lex();
4728
4729 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4730 return MatchOperand_ParseFail;
4731
4732 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4733 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4734 Regs.push_back(RegNo);
4735
4736 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4737
4738 return MatchOperand_Success;
4739}
4740
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004741/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4742/// either this.
4743/// ::= '(', register, ')'
4744/// handle it before we iterate so we don't get tripped up by the lack of
4745/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004746bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004747 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004748 if (getLexer().is(AsmToken::LParen)) {
4749 Operands.push_back(
4750 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4751 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004752 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004753 SMLoc Loc = getLexer().getLoc();
4754 Parser.eatToEndOfStatement();
4755 return Error(Loc, "unexpected token in argument list");
4756 }
4757 if (Parser.getTok().isNot(AsmToken::RParen)) {
4758 SMLoc Loc = getLexer().getLoc();
4759 Parser.eatToEndOfStatement();
4760 return Error(Loc, "unexpected token, expected ')'");
4761 }
4762 Operands.push_back(
4763 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4764 Parser.Lex();
4765 }
4766 return false;
4767}
4768
4769/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4770/// either one of these.
4771/// ::= '[', register, ']'
4772/// ::= '[', integer, ']'
4773/// handle it before we iterate so we don't get tripped up by the lack of
4774/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004775bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004776 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004777 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004778 if (getLexer().is(AsmToken::LBrac)) {
4779 Operands.push_back(
4780 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4781 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004782 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004783 SMLoc Loc = getLexer().getLoc();
4784 Parser.eatToEndOfStatement();
4785 return Error(Loc, "unexpected token in argument list");
4786 }
4787 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4788 SMLoc Loc = getLexer().getLoc();
4789 Parser.eatToEndOfStatement();
4790 return Error(Loc, "unexpected token, expected ']'");
4791 }
4792 Operands.push_back(
4793 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4794 Parser.Lex();
4795 }
4796 return false;
4797}
4798
David Blaikie960ea3f2014-06-08 16:18:35 +00004799bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4800 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004801 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004802 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004803
4804 // We have reached first instruction, module directive are now forbidden.
4805 getTargetStreamer().forbidModuleDirective();
4806
Vladimir Medic74593e62013-07-17 15:00:42 +00004807 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004808 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004809 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004810 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004811 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004812 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004813 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004814
4815 // Read the remaining operands.
4816 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4817 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004818 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004819 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004820 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004821 return Error(Loc, "unexpected token in argument list");
4822 }
Toma Tabacu13964452014-09-04 13:23:44 +00004823 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004824 return true;
4825 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004826
Jack Carterd0bd6422013-04-18 00:41:53 +00004827 while (getLexer().is(AsmToken::Comma)) {
4828 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004829 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004830 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004831 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004832 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004833 return Error(Loc, "unexpected token in argument list");
4834 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004835 // Parse bracket and parenthesis suffixes before we iterate
4836 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004837 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004838 return true;
4839 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004840 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004841 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004842 }
4843 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004844 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4845 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004846 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004847 return Error(Loc, "unexpected token in argument list");
4848 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004849 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004850 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004851}
4852
Nirav Dave996fc132016-05-05 14:15:46 +00004853// FIXME: Given that these have the same name, these should both be
4854// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004855bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004856 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004857 SMLoc Loc = getLexer().getLoc();
4858 Parser.eatToEndOfStatement();
4859 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004860}
4861
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004862bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004863 return Error(Loc, ErrorMsg);
4864}
4865
Jack Carter0b744b32012-10-04 02:29:46 +00004866bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004867 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004868 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004869
4870 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004871 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004872
4873 Parser.Lex(); // Eat "noat".
4874
Jack Carterd0bd6422013-04-18 00:41:53 +00004875 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004876 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004877 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004878 return false;
4879 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004880
4881 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004882 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004883 return false;
4884}
Jack Carterd0bd6422013-04-18 00:41:53 +00004885
Jack Carter0b744b32012-10-04 02:29:46 +00004886bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004887 // Line can be: ".set at", which sets $at to $1
4888 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004889 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004890 Parser.Lex(); // Eat "at".
4891
Jack Carter0b744b32012-10-04 02:29:46 +00004892 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004893 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004894 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004895
4896 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004897 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004898 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004899 }
4900
4901 if (getLexer().isNot(AsmToken::Equal)) {
4902 reportParseError("unexpected token, expected equals sign");
4903 return false;
4904 }
4905 Parser.Lex(); // Eat "=".
4906
4907 if (getLexer().isNot(AsmToken::Dollar)) {
4908 if (getLexer().is(AsmToken::EndOfStatement)) {
4909 reportParseError("no register specified");
4910 return false;
4911 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004912 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004913 return false;
4914 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004915 }
4916 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004917
Toma Tabacu16a74492015-02-13 10:30:57 +00004918 // Find out what "reg" is.
4919 unsigned AtRegNo;
4920 const AsmToken &Reg = Parser.getTok();
4921 if (Reg.is(AsmToken::Identifier)) {
4922 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4923 } else if (Reg.is(AsmToken::Integer)) {
4924 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004925 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004926 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004927 return false;
4928 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004929
4930 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004931 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004932 reportParseError("invalid register");
4933 return false;
4934 }
4935 Parser.Lex(); // Eat "reg".
4936
4937 // If this is not the end of the statement, report an error.
4938 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4939 reportParseError("unexpected token, expected end of statement");
4940 return false;
4941 }
4942
4943 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4944
4945 Parser.Lex(); // Consume the EndOfStatement.
4946 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004947}
4948
4949bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004950 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004951 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004952 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004953 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004954 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004955 return false;
4956 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004957 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004958 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004959 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004960 return false;
4961}
4962
4963bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004964 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004965 Parser.Lex();
4966 // If this is not the end of the statement, report an error.
4967 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004968 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004969 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004970 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004971 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004972 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004973 Parser.Lex(); // Consume the EndOfStatement.
4974 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004975}
4976
4977bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004978 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004979 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004980 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004981 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004982 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004983 return false;
4984 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004985 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004986 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004987 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004988 return false;
4989}
4990
4991bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004992 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004993 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004994 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004995 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004996 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004997 return false;
4998 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004999 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005000 reportParseError("`noreorder' must be set before `nomacro'");
5001 return false;
5002 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005003 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005004 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005005 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005006 return false;
5007}
Jack Carterd76b2372013-03-21 21:44:16 +00005008
Daniel Sanders44934432014-08-07 12:03:36 +00005009bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005010 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005011 Parser.Lex();
5012
5013 // If this is not the end of the statement, report an error.
5014 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005015 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005016
5017 setFeatureBits(Mips::FeatureMSA, "msa");
5018 getTargetStreamer().emitDirectiveSetMsa();
5019 return false;
5020}
5021
5022bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005023 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005024 Parser.Lex();
5025
5026 // If this is not the end of the statement, report an error.
5027 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005028 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005029
5030 clearFeatureBits(Mips::FeatureMSA, "msa");
5031 getTargetStreamer().emitDirectiveSetNoMsa();
5032 return false;
5033}
5034
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005035bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005036 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005037 Parser.Lex(); // Eat "nodsp".
5038
5039 // If this is not the end of the statement, report an error.
5040 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5041 reportParseError("unexpected token, expected end of statement");
5042 return false;
5043 }
5044
5045 clearFeatureBits(Mips::FeatureDSP, "dsp");
5046 getTargetStreamer().emitDirectiveSetNoDsp();
5047 return false;
5048}
5049
Toma Tabacucc2502d2014-11-04 17:18:07 +00005050bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005051 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005052 Parser.Lex(); // Eat "mips16".
5053
Jack Carter39536722014-01-22 23:08:42 +00005054 // If this is not the end of the statement, report an error.
5055 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005056 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005057 return false;
5058 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005059
5060 setFeatureBits(Mips::FeatureMips16, "mips16");
5061 getTargetStreamer().emitDirectiveSetMips16();
5062 Parser.Lex(); // Consume the EndOfStatement.
5063 return false;
5064}
5065
5066bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005067 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005068 Parser.Lex(); // Eat "nomips16".
5069
5070 // If this is not the end of the statement, report an error.
5071 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5072 reportParseError("unexpected token, expected end of statement");
5073 return false;
5074 }
5075
5076 clearFeatureBits(Mips::FeatureMips16, "mips16");
5077 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005078 Parser.Lex(); // Consume the EndOfStatement.
5079 return false;
5080}
5081
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005082bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005083 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005084 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005085 // Line can be: .set fp=32
5086 // .set fp=xx
5087 // .set fp=64
5088 Parser.Lex(); // Eat fp token
5089 AsmToken Tok = Parser.getTok();
5090 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005091 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005092 return false;
5093 }
5094 Parser.Lex(); // Eat '=' token.
5095 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005096
5097 if (!parseFpABIValue(FpAbiVal, ".set"))
5098 return false;
5099
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005100 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005101 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005102 return false;
5103 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005104 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005105 Parser.Lex(); // Consume the EndOfStatement.
5106 return false;
5107}
5108
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005109bool MipsAsmParser::parseSetOddSPRegDirective() {
5110 MCAsmParser &Parser = getParser();
5111
5112 Parser.Lex(); // Eat "oddspreg".
5113 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5114 reportParseError("unexpected token, expected end of statement");
5115 return false;
5116 }
5117
5118 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5119 getTargetStreamer().emitDirectiveSetOddSPReg();
5120 return false;
5121}
5122
5123bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5124 MCAsmParser &Parser = getParser();
5125
5126 Parser.Lex(); // Eat "nooddspreg".
5127 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5128 reportParseError("unexpected token, expected end of statement");
5129 return false;
5130 }
5131
5132 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5133 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5134 return false;
5135}
5136
Toma Tabacu9db22db2014-09-09 10:15:38 +00005137bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005138 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005139 SMLoc Loc = getLexer().getLoc();
5140
5141 Parser.Lex();
5142 if (getLexer().isNot(AsmToken::EndOfStatement))
5143 return reportParseError("unexpected token, expected end of statement");
5144
5145 // Always keep an element on the options "stack" to prevent the user
5146 // from changing the initial options. This is how we remember them.
5147 if (AssemblerOptions.size() == 2)
5148 return reportParseError(Loc, ".set pop with no .set push");
5149
Akira Hatanakab11ef082015-11-14 06:35:56 +00005150 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005151 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005152 setAvailableFeatures(
5153 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5154 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005155
5156 getTargetStreamer().emitDirectiveSetPop();
5157 return false;
5158}
5159
5160bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005161 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005162 Parser.Lex();
5163 if (getLexer().isNot(AsmToken::EndOfStatement))
5164 return reportParseError("unexpected token, expected end of statement");
5165
5166 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005167 AssemblerOptions.push_back(
5168 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005169
5170 getTargetStreamer().emitDirectiveSetPush();
5171 return false;
5172}
5173
Toma Tabacu29696502015-06-02 09:48:04 +00005174bool MipsAsmParser::parseSetSoftFloatDirective() {
5175 MCAsmParser &Parser = getParser();
5176 Parser.Lex();
5177 if (getLexer().isNot(AsmToken::EndOfStatement))
5178 return reportParseError("unexpected token, expected end of statement");
5179
5180 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5181 getTargetStreamer().emitDirectiveSetSoftFloat();
5182 return false;
5183}
5184
5185bool MipsAsmParser::parseSetHardFloatDirective() {
5186 MCAsmParser &Parser = getParser();
5187 Parser.Lex();
5188 if (getLexer().isNot(AsmToken::EndOfStatement))
5189 return reportParseError("unexpected token, expected end of statement");
5190
5191 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5192 getTargetStreamer().emitDirectiveSetHardFloat();
5193 return false;
5194}
5195
Jack Carterd76b2372013-03-21 21:44:16 +00005196bool MipsAsmParser::parseSetAssignment() {
5197 StringRef Name;
5198 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005199 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005200
5201 if (Parser.parseIdentifier(Name))
5202 reportParseError("expected identifier after .set");
5203
5204 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005205 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005206 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005207
Jack Carter3b2c96e2014-01-22 23:31:38 +00005208 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005209 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005210
Jim Grosbach6f482002015-05-18 18:43:14 +00005211 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005212 Sym->setVariableValue(Value);
5213
5214 return false;
5215}
Jack Carterd0bd6422013-04-18 00:41:53 +00005216
Toma Tabacu26647792014-09-09 12:52:14 +00005217bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005218 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005219 Parser.Lex();
5220 if (getLexer().isNot(AsmToken::EndOfStatement))
5221 return reportParseError("unexpected token, expected end of statement");
5222
5223 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005224 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005225 setAvailableFeatures(
5226 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5227 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005228 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5229
5230 getTargetStreamer().emitDirectiveSetMips0();
5231 return false;
5232}
5233
Toma Tabacu85618b32014-08-19 14:22:52 +00005234bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005235 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005236 Parser.Lex();
5237 if (getLexer().isNot(AsmToken::Equal))
5238 return reportParseError("unexpected token, expected equals sign");
5239
5240 Parser.Lex();
5241 StringRef Arch;
5242 if (Parser.parseIdentifier(Arch))
5243 return reportParseError("expected arch identifier");
5244
5245 StringRef ArchFeatureName =
5246 StringSwitch<StringRef>(Arch)
5247 .Case("mips1", "mips1")
5248 .Case("mips2", "mips2")
5249 .Case("mips3", "mips3")
5250 .Case("mips4", "mips4")
5251 .Case("mips5", "mips5")
5252 .Case("mips32", "mips32")
5253 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005254 .Case("mips32r3", "mips32r3")
5255 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005256 .Case("mips32r6", "mips32r6")
5257 .Case("mips64", "mips64")
5258 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005259 .Case("mips64r3", "mips64r3")
5260 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005261 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005262 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005263 .Case("r4000", "mips3") // This is an implementation of Mips3.
5264 .Default("");
5265
5266 if (ArchFeatureName.empty())
5267 return reportParseError("unsupported architecture");
5268
5269 selectArch(ArchFeatureName);
5270 getTargetStreamer().emitDirectiveSetArch(Arch);
5271 return false;
5272}
5273
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005274bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005275 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005276 Parser.Lex();
5277 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005278 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005279
Matheus Almeida2852af82014-04-22 10:15:54 +00005280 switch (Feature) {
5281 default:
5282 llvm_unreachable("Unimplemented feature");
5283 case Mips::FeatureDSP:
5284 setFeatureBits(Mips::FeatureDSP, "dsp");
5285 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005286 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005287 case Mips::FeatureMicroMips:
5288 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005289 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005290 case Mips::FeatureMips1:
5291 selectArch("mips1");
5292 getTargetStreamer().emitDirectiveSetMips1();
5293 break;
5294 case Mips::FeatureMips2:
5295 selectArch("mips2");
5296 getTargetStreamer().emitDirectiveSetMips2();
5297 break;
5298 case Mips::FeatureMips3:
5299 selectArch("mips3");
5300 getTargetStreamer().emitDirectiveSetMips3();
5301 break;
5302 case Mips::FeatureMips4:
5303 selectArch("mips4");
5304 getTargetStreamer().emitDirectiveSetMips4();
5305 break;
5306 case Mips::FeatureMips5:
5307 selectArch("mips5");
5308 getTargetStreamer().emitDirectiveSetMips5();
5309 break;
5310 case Mips::FeatureMips32:
5311 selectArch("mips32");
5312 getTargetStreamer().emitDirectiveSetMips32();
5313 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005314 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005315 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005316 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005317 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005318 case Mips::FeatureMips32r3:
5319 selectArch("mips32r3");
5320 getTargetStreamer().emitDirectiveSetMips32R3();
5321 break;
5322 case Mips::FeatureMips32r5:
5323 selectArch("mips32r5");
5324 getTargetStreamer().emitDirectiveSetMips32R5();
5325 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005326 case Mips::FeatureMips32r6:
5327 selectArch("mips32r6");
5328 getTargetStreamer().emitDirectiveSetMips32R6();
5329 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005330 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005331 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005332 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005333 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005334 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005335 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005336 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005337 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005338 case Mips::FeatureMips64r3:
5339 selectArch("mips64r3");
5340 getTargetStreamer().emitDirectiveSetMips64R3();
5341 break;
5342 case Mips::FeatureMips64r5:
5343 selectArch("mips64r5");
5344 getTargetStreamer().emitDirectiveSetMips64R5();
5345 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005346 case Mips::FeatureMips64r6:
5347 selectArch("mips64r6");
5348 getTargetStreamer().emitDirectiveSetMips64R6();
5349 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005350 }
5351 return false;
5352}
5353
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005354bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005355 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005356 if (getLexer().isNot(AsmToken::Comma)) {
5357 SMLoc Loc = getLexer().getLoc();
5358 Parser.eatToEndOfStatement();
5359 return Error(Loc, ErrorStr);
5360 }
5361
Matheus Almeida2852af82014-04-22 10:15:54 +00005362 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005363 return true;
5364}
5365
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005366// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5367// In this class, it is only used for .cprestore.
5368// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5369// MipsTargetELFStreamer and MipsAsmParser.
5370bool MipsAsmParser::isPicAndNotNxxAbi() {
5371 return inPicMode() && !(isABI_N32() || isABI_N64());
5372}
5373
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005374bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005375 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005376 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005377
Toma Tabacudde4c462014-11-06 10:02:45 +00005378 if (inMips16Mode()) {
5379 reportParseError(".cpload is not supported in Mips16 mode");
5380 return false;
5381 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005382
David Blaikie960ea3f2014-06-08 16:18:35 +00005383 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005384 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005385 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5386 reportParseError("expected register containing function address");
5387 return false;
5388 }
5389
David Blaikie960ea3f2014-06-08 16:18:35 +00005390 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5391 if (!RegOpnd.isGPRAsmReg()) {
5392 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005393 return false;
5394 }
5395
Toma Tabacudde4c462014-11-06 10:02:45 +00005396 // If this is not the end of the statement, report an error.
5397 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5398 reportParseError("unexpected token, expected end of statement");
5399 return false;
5400 }
5401
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005402 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005403 return false;
5404}
5405
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005406bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5407 MCAsmParser &Parser = getParser();
5408
5409 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5410 // is used in non-PIC mode.
5411
5412 if (inMips16Mode()) {
5413 reportParseError(".cprestore is not supported in Mips16 mode");
5414 return false;
5415 }
5416
5417 // Get the stack offset value.
5418 const MCExpr *StackOffset;
5419 int64_t StackOffsetVal;
5420 if (Parser.parseExpression(StackOffset)) {
5421 reportParseError("expected stack offset value");
5422 return false;
5423 }
5424
5425 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5426 reportParseError("stack offset is not an absolute expression");
5427 return false;
5428 }
5429
5430 if (StackOffsetVal < 0) {
5431 Warning(Loc, ".cprestore with negative stack offset has no effect");
5432 IsCpRestoreSet = false;
5433 } else {
5434 IsCpRestoreSet = true;
5435 CpRestoreOffset = StackOffsetVal;
5436 }
5437
5438 // If this is not the end of the statement, report an error.
5439 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5440 reportParseError("unexpected token, expected end of statement");
5441 return false;
5442 }
5443
Daniel Sanders7225cd52016-04-29 16:16:49 +00005444 unsigned ATReg = getATReg(Loc);
5445 if (!ATReg)
5446 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005447
Daniel Sanders7225cd52016-04-29 16:16:49 +00005448 getTargetStreamer().emitDirectiveCpRestore(CpRestoreOffset, ATReg, Loc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005449 Parser.Lex(); // Consume the EndOfStatement.
5450 return false;
5451}
5452
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005453bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005454 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005455 unsigned FuncReg;
5456 unsigned Save;
5457 bool SaveIsReg = true;
5458
Matheus Almeida7e815762014-06-18 13:08:59 +00005459 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005460 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005461 if (ResTy == MatchOperand_NoMatch) {
5462 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005463 return false;
5464 }
5465
5466 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5467 if (!FuncRegOpnd.isGPRAsmReg()) {
5468 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5469 Parser.eatToEndOfStatement();
5470 return false;
5471 }
5472
5473 FuncReg = FuncRegOpnd.getGPR32Reg();
5474 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005475
Toma Tabacu65f10572014-09-16 15:00:52 +00005476 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005477 return true;
5478
Toma Tabacu13964452014-09-04 13:23:44 +00005479 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005480 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005481 const MCExpr *OffsetExpr;
5482 int64_t OffsetVal;
5483 SMLoc ExprLoc = getLexer().getLoc();
5484
5485 if (Parser.parseExpression(OffsetExpr) ||
5486 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5487 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005488 Parser.eatToEndOfStatement();
5489 return false;
5490 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005491
5492 Save = OffsetVal;
5493 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005494 } else {
5495 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5496 if (!SaveOpnd.isGPRAsmReg()) {
5497 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5498 Parser.eatToEndOfStatement();
5499 return false;
5500 }
5501 Save = SaveOpnd.getGPR32Reg();
5502 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005503
Toma Tabacu65f10572014-09-16 15:00:52 +00005504 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005505 return true;
5506
Toma Tabacu8874eac2015-02-18 13:46:53 +00005507 const MCExpr *Expr;
5508 if (Parser.parseExpression(Expr)) {
5509 reportParseError("expected expression");
5510 return false;
5511 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005512
Toma Tabacu8874eac2015-02-18 13:46:53 +00005513 if (Expr->getKind() != MCExpr::SymbolRef) {
5514 reportParseError("expected symbol");
5515 return false;
5516 }
5517 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5518
Daniel Sandersf173dda2015-09-22 10:50:09 +00005519 CpSaveLocation = Save;
5520 CpSaveLocationIsRegister = SaveIsReg;
5521
Toma Tabacu8874eac2015-02-18 13:46:53 +00005522 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5523 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005524 return false;
5525}
5526
Daniel Sandersf173dda2015-09-22 10:50:09 +00005527bool MipsAsmParser::parseDirectiveCPReturn() {
5528 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5529 CpSaveLocationIsRegister);
5530 return false;
5531}
5532
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005533bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005534 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005535 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5536 const AsmToken &Tok = Parser.getTok();
5537
5538 if (Tok.getString() == "2008") {
5539 Parser.Lex();
5540 getTargetStreamer().emitDirectiveNaN2008();
5541 return false;
5542 } else if (Tok.getString() == "legacy") {
5543 Parser.Lex();
5544 getTargetStreamer().emitDirectiveNaNLegacy();
5545 return false;
5546 }
5547 }
5548 // If we don't recognize the option passed to the .nan
5549 // directive (e.g. no option or unknown option), emit an error.
5550 reportParseError("invalid option in .nan directive");
5551 return false;
5552}
5553
Jack Carter0b744b32012-10-04 02:29:46 +00005554bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005555 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005556 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005557 const AsmToken &Tok = Parser.getTok();
5558
5559 if (Tok.getString() == "noat") {
5560 return parseSetNoAtDirective();
5561 } else if (Tok.getString() == "at") {
5562 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005563 } else if (Tok.getString() == "arch") {
5564 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005565 } else if (Tok.getString() == "fp") {
5566 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005567 } else if (Tok.getString() == "oddspreg") {
5568 return parseSetOddSPRegDirective();
5569 } else if (Tok.getString() == "nooddspreg") {
5570 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005571 } else if (Tok.getString() == "pop") {
5572 return parseSetPopDirective();
5573 } else if (Tok.getString() == "push") {
5574 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005575 } else if (Tok.getString() == "reorder") {
5576 return parseSetReorderDirective();
5577 } else if (Tok.getString() == "noreorder") {
5578 return parseSetNoReorderDirective();
5579 } else if (Tok.getString() == "macro") {
5580 return parseSetMacroDirective();
5581 } else if (Tok.getString() == "nomacro") {
5582 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005583 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005584 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005585 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005586 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005587 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005588 getTargetStreamer().emitDirectiveSetNoMicroMips();
5589 Parser.eatToEndOfStatement();
5590 return false;
5591 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005592 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005593 } else if (Tok.getString() == "mips0") {
5594 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005595 } else if (Tok.getString() == "mips1") {
5596 return parseSetFeature(Mips::FeatureMips1);
5597 } else if (Tok.getString() == "mips2") {
5598 return parseSetFeature(Mips::FeatureMips2);
5599 } else if (Tok.getString() == "mips3") {
5600 return parseSetFeature(Mips::FeatureMips3);
5601 } else if (Tok.getString() == "mips4") {
5602 return parseSetFeature(Mips::FeatureMips4);
5603 } else if (Tok.getString() == "mips5") {
5604 return parseSetFeature(Mips::FeatureMips5);
5605 } else if (Tok.getString() == "mips32") {
5606 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005607 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005608 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005609 } else if (Tok.getString() == "mips32r3") {
5610 return parseSetFeature(Mips::FeatureMips32r3);
5611 } else if (Tok.getString() == "mips32r5") {
5612 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005613 } else if (Tok.getString() == "mips32r6") {
5614 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005615 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005616 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005617 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005618 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005619 } else if (Tok.getString() == "mips64r3") {
5620 return parseSetFeature(Mips::FeatureMips64r3);
5621 } else if (Tok.getString() == "mips64r5") {
5622 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005623 } else if (Tok.getString() == "mips64r6") {
5624 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005625 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005626 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005627 } else if (Tok.getString() == "nodsp") {
5628 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005629 } else if (Tok.getString() == "msa") {
5630 return parseSetMsaDirective();
5631 } else if (Tok.getString() == "nomsa") {
5632 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005633 } else if (Tok.getString() == "softfloat") {
5634 return parseSetSoftFloatDirective();
5635 } else if (Tok.getString() == "hardfloat") {
5636 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005637 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005638 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005639 parseSetAssignment();
5640 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005641 }
Jack Carter07c818d2013-01-25 01:31:34 +00005642
Jack Carter0b744b32012-10-04 02:29:46 +00005643 return true;
5644}
5645
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005646/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005647/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005648bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005649 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005650 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5651 for (;;) {
5652 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005653 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005654 return true;
5655
5656 getParser().getStreamer().EmitValue(Value, Size);
5657
5658 if (getLexer().is(AsmToken::EndOfStatement))
5659 break;
5660
Jack Carter07c818d2013-01-25 01:31:34 +00005661 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005662 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005663 Parser.Lex();
5664 }
5665 }
5666
5667 Parser.Lex();
5668 return false;
5669}
5670
Vladimir Medic4c299852013-11-06 11:27:05 +00005671/// parseDirectiveGpWord
5672/// ::= .gpword local_sym
5673bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005674 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005675 const MCExpr *Value;
5676 // EmitGPRel32Value requires an expression, so we are using base class
5677 // method to evaluate the expression.
5678 if (getParser().parseExpression(Value))
5679 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005680 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005681
Vladimir Medice10c1122013-11-13 13:18:04 +00005682 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005683 return Error(getLexer().getLoc(),
5684 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005685 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005686 return false;
5687}
5688
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005689/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005690/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005691bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005692 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005693 const MCExpr *Value;
5694 // EmitGPRel64Value requires an expression, so we are using base class
5695 // method to evaluate the expression.
5696 if (getParser().parseExpression(Value))
5697 return true;
5698 getParser().getStreamer().EmitGPRel64Value(Value);
5699
5700 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005701 return Error(getLexer().getLoc(),
5702 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005703 Parser.Lex(); // Eat EndOfStatement token.
5704 return false;
5705}
5706
Jack Carter0cd3c192014-01-06 23:27:31 +00005707bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005708 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005709 // Get the option token.
5710 AsmToken Tok = Parser.getTok();
5711 // At the moment only identifiers are supported.
5712 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005713 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005714 Parser.eatToEndOfStatement();
5715 return false;
5716 }
5717
5718 StringRef Option = Tok.getIdentifier();
5719
5720 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005721 // MipsAsmParser needs to know if the current PIC mode changes.
5722 IsPicEnabled = false;
5723
Jack Carter0cd3c192014-01-06 23:27:31 +00005724 getTargetStreamer().emitDirectiveOptionPic0();
5725 Parser.Lex();
5726 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5727 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005728 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005729 Parser.eatToEndOfStatement();
5730 }
5731 return false;
5732 }
5733
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005734 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005735 // MipsAsmParser needs to know if the current PIC mode changes.
5736 IsPicEnabled = true;
5737
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005738 getTargetStreamer().emitDirectiveOptionPic2();
5739 Parser.Lex();
5740 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5741 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005742 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005743 Parser.eatToEndOfStatement();
5744 }
5745 return false;
5746 }
5747
Jack Carter0cd3c192014-01-06 23:27:31 +00005748 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005749 Warning(Parser.getTok().getLoc(),
5750 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005751 Parser.eatToEndOfStatement();
5752 return false;
5753}
5754
Toma Tabacu9ca50962015-04-16 09:53:47 +00005755/// parseInsnDirective
5756/// ::= .insn
5757bool MipsAsmParser::parseInsnDirective() {
5758 // If this is not the end of the statement, report an error.
5759 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5760 reportParseError("unexpected token, expected end of statement");
5761 return false;
5762 }
5763
5764 // The actual label marking happens in
5765 // MipsELFStreamer::createPendingLabelRelocs().
5766 getTargetStreamer().emitDirectiveInsn();
5767
5768 getParser().Lex(); // Eat EndOfStatement token.
5769 return false;
5770}
5771
Simon Atanasyanbe186202016-02-11 06:45:54 +00005772/// parseSSectionDirective
5773/// ::= .sbss
5774/// ::= .sdata
5775bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5776 // If this is not the end of the statement, report an error.
5777 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5778 reportParseError("unexpected token, expected end of statement");
5779 return false;
5780 }
5781
5782 MCSection *ELFSection = getContext().getELFSection(
5783 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5784 getParser().getStreamer().SwitchSection(ELFSection);
5785
5786 getParser().Lex(); // Eat EndOfStatement token.
5787 return false;
5788}
5789
Daniel Sanders7e527422014-07-10 13:38:23 +00005790/// parseDirectiveModule
5791/// ::= .module oddspreg
5792/// ::= .module nooddspreg
5793/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005794/// ::= .module softfloat
5795/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005796bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005797 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005798 MCAsmLexer &Lexer = getLexer();
5799 SMLoc L = Lexer.getLoc();
5800
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005801 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005802 // TODO : get a better message.
5803 reportParseError(".module directive must appear before any code");
5804 return false;
5805 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005806
Toma Tabacuc405c822015-01-23 10:40:19 +00005807 StringRef Option;
5808 if (Parser.parseIdentifier(Option)) {
5809 reportParseError("expected .module option identifier");
5810 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005811 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005812
Toma Tabacuc405c822015-01-23 10:40:19 +00005813 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005814 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005815
Toma Tabacu3c499582015-06-25 10:56:57 +00005816 // Synchronize the abiflags information with the FeatureBits information we
5817 // changed above.
5818 getTargetStreamer().updateABIInfo(*this);
5819
5820 // If printing assembly, use the recently updated abiflags information.
5821 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5822 // emitted at the end).
5823 getTargetStreamer().emitDirectiveModuleOddSPReg();
5824
Toma Tabacuc405c822015-01-23 10:40:19 +00005825 // If this is not the end of the statement, report an error.
5826 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5827 reportParseError("unexpected token, expected end of statement");
5828 return false;
5829 }
5830
5831 return false; // parseDirectiveModule has finished successfully.
5832 } else if (Option == "nooddspreg") {
5833 if (!isABI_O32()) {
5834 Error(L, "'.module nooddspreg' requires the O32 ABI");
5835 return false;
5836 }
5837
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005838 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005839
Toma Tabacu3c499582015-06-25 10:56:57 +00005840 // Synchronize the abiflags information with the FeatureBits information we
5841 // changed above.
5842 getTargetStreamer().updateABIInfo(*this);
5843
5844 // If printing assembly, use the recently updated abiflags information.
5845 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5846 // emitted at the end).
5847 getTargetStreamer().emitDirectiveModuleOddSPReg();
5848
Toma Tabacuc405c822015-01-23 10:40:19 +00005849 // If this is not the end of the statement, report an error.
5850 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5851 reportParseError("unexpected token, expected end of statement");
5852 return false;
5853 }
5854
5855 return false; // parseDirectiveModule has finished successfully.
5856 } else if (Option == "fp") {
5857 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005858 } else if (Option == "softfloat") {
5859 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5860
5861 // Synchronize the ABI Flags information with the FeatureBits information we
5862 // updated above.
5863 getTargetStreamer().updateABIInfo(*this);
5864
5865 // If printing assembly, use the recently updated ABI Flags information.
5866 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5867 // emitted later).
5868 getTargetStreamer().emitDirectiveModuleSoftFloat();
5869
5870 // If this is not the end of the statement, report an error.
5871 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5872 reportParseError("unexpected token, expected end of statement");
5873 return false;
5874 }
5875
5876 return false; // parseDirectiveModule has finished successfully.
5877 } else if (Option == "hardfloat") {
5878 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5879
5880 // Synchronize the ABI Flags information with the FeatureBits information we
5881 // updated above.
5882 getTargetStreamer().updateABIInfo(*this);
5883
5884 // If printing assembly, use the recently updated ABI Flags information.
5885 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5886 // emitted later).
5887 getTargetStreamer().emitDirectiveModuleHardFloat();
5888
5889 // If this is not the end of the statement, report an error.
5890 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5891 reportParseError("unexpected token, expected end of statement");
5892 return false;
5893 }
5894
5895 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005896 } else {
5897 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5898 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005899}
5900
5901/// parseDirectiveModuleFP
5902/// ::= =32
5903/// ::= =xx
5904/// ::= =64
5905bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005906 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005907 MCAsmLexer &Lexer = getLexer();
5908
5909 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005910 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005911 return false;
5912 }
5913 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005914
Daniel Sanders7e527422014-07-10 13:38:23 +00005915 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005916 if (!parseFpABIValue(FpABI, ".module"))
5917 return false;
5918
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005919 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005920 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005921 return false;
5922 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005923
Toma Tabacua64e5402015-06-25 12:44:38 +00005924 // Synchronize the abiflags information with the FeatureBits information we
5925 // changed above.
5926 getTargetStreamer().updateABIInfo(*this);
5927
5928 // If printing assembly, use the recently updated abiflags information.
5929 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5930 // emitted at the end).
5931 getTargetStreamer().emitDirectiveModuleFP();
5932
Daniel Sanders7e527422014-07-10 13:38:23 +00005933 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005934 return false;
5935}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005936
Daniel Sanders7e527422014-07-10 13:38:23 +00005937bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005938 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005939 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005940 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005941 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005942
5943 if (Lexer.is(AsmToken::Identifier)) {
5944 StringRef Value = Parser.getTok().getString();
5945 Parser.Lex();
5946
5947 if (Value != "xx") {
5948 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5949 return false;
5950 }
5951
5952 if (!isABI_O32()) {
5953 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5954 return false;
5955 }
5956
Daniel Sanders7e527422014-07-10 13:38:23 +00005957 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005958 if (ModuleLevelOptions) {
5959 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5960 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5961 } else {
5962 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5963 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5964 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005965 return true;
5966 }
5967
5968 if (Lexer.is(AsmToken::Integer)) {
5969 unsigned Value = Parser.getTok().getIntVal();
5970 Parser.Lex();
5971
5972 if (Value != 32 && Value != 64) {
5973 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5974 return false;
5975 }
5976
5977 if (Value == 32) {
5978 if (!isABI_O32()) {
5979 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5980 return false;
5981 }
5982
Daniel Sanders7e527422014-07-10 13:38:23 +00005983 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005984 if (ModuleLevelOptions) {
5985 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5986 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5987 } else {
5988 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5989 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5990 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005991 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005992 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005993 if (ModuleLevelOptions) {
5994 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5995 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5996 } else {
5997 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5998 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5999 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006000 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006001
Daniel Sanders7e527422014-07-10 13:38:23 +00006002 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006003 }
6004
6005 return false;
6006}
6007
Jack Carter0b744b32012-10-04 02:29:46 +00006008bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006009 // This returns false if this function recognizes the directive
6010 // regardless of whether it is successfully handles or reports an
6011 // error. Otherwise it returns true to give the generic parser a
6012 // chance at recognizing it.
6013
Rafael Espindola961d4692014-11-11 05:18:41 +00006014 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006015 StringRef IDVal = DirectiveID.getString();
6016
Nirav Dave996fc132016-05-05 14:15:46 +00006017 if (IDVal == ".cpload") {
6018 parseDirectiveCpLoad(DirectiveID.getLoc());
6019 return false;
6020 }
6021 if (IDVal == ".cprestore") {
6022 parseDirectiveCpRestore(DirectiveID.getLoc());
6023 return false;
6024 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006025 if (IDVal == ".dword") {
6026 parseDataDirective(8, DirectiveID.getLoc());
6027 return false;
6028 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006029 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006030 StringRef SymbolName;
6031
6032 if (Parser.parseIdentifier(SymbolName)) {
6033 reportParseError("expected identifier after .ent");
6034 return false;
6035 }
6036
6037 // There's an undocumented extension that allows an integer to
6038 // follow the name of the procedure which AFAICS is ignored by GAS.
6039 // Example: .ent foo,2
6040 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6041 if (getLexer().isNot(AsmToken::Comma)) {
6042 // Even though we accept this undocumented extension for compatibility
6043 // reasons, the additional integer argument does not actually change
6044 // the behaviour of the '.ent' directive, so we would like to discourage
6045 // its use. We do this by not referring to the extended version in
6046 // error messages which are not directly related to its use.
6047 reportParseError("unexpected token, expected end of statement");
6048 return false;
6049 }
6050 Parser.Lex(); // Eat the comma.
6051 const MCExpr *DummyNumber;
6052 int64_t DummyNumberVal;
6053 // If the user was explicitly trying to use the extended version,
6054 // we still give helpful extension-related error messages.
6055 if (Parser.parseExpression(DummyNumber)) {
6056 reportParseError("expected number after comma");
6057 return false;
6058 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006059 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006060 reportParseError("expected an absolute expression after comma");
6061 return false;
6062 }
6063 }
6064
6065 // If this is not the end of the statement, report an error.
6066 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6067 reportParseError("unexpected token, expected end of statement");
6068 return false;
6069 }
6070
Jim Grosbach6f482002015-05-18 18:43:14 +00006071 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006072
6073 getTargetStreamer().emitDirectiveEnt(*Sym);
6074 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006075 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006076 return false;
6077 }
6078
Jack Carter07c818d2013-01-25 01:31:34 +00006079 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006080 StringRef SymbolName;
6081
6082 if (Parser.parseIdentifier(SymbolName)) {
6083 reportParseError("expected identifier after .end");
6084 return false;
6085 }
6086
6087 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6088 reportParseError("unexpected token, expected end of statement");
6089 return false;
6090 }
6091
6092 if (CurrentFn == nullptr) {
6093 reportParseError(".end used without .ent");
6094 return false;
6095 }
6096
6097 if ((SymbolName != CurrentFn->getName())) {
6098 reportParseError(".end symbol does not match .ent symbol");
6099 return false;
6100 }
6101
6102 getTargetStreamer().emitDirectiveEnd(SymbolName);
6103 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006104 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006105 return false;
6106 }
6107
Jack Carter07c818d2013-01-25 01:31:34 +00006108 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006109 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6110 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006111 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006112 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6113 reportParseError("expected stack register");
6114 return false;
6115 }
6116
6117 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6118 if (!StackRegOpnd.isGPRAsmReg()) {
6119 reportParseError(StackRegOpnd.getStartLoc(),
6120 "expected general purpose register");
6121 return false;
6122 }
6123 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6124
6125 if (Parser.getTok().is(AsmToken::Comma))
6126 Parser.Lex();
6127 else {
6128 reportParseError("unexpected token, expected comma");
6129 return false;
6130 }
6131
6132 // Parse the frame size.
6133 const MCExpr *FrameSize;
6134 int64_t FrameSizeVal;
6135
6136 if (Parser.parseExpression(FrameSize)) {
6137 reportParseError("expected frame size value");
6138 return false;
6139 }
6140
Jim Grosbach13760bd2015-05-30 01:25:56 +00006141 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006142 reportParseError("frame size not an absolute expression");
6143 return false;
6144 }
6145
6146 if (Parser.getTok().is(AsmToken::Comma))
6147 Parser.Lex();
6148 else {
6149 reportParseError("unexpected token, expected comma");
6150 return false;
6151 }
6152
6153 // Parse the return register.
6154 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006155 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006156 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6157 reportParseError("expected return register");
6158 return false;
6159 }
6160
6161 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6162 if (!ReturnRegOpnd.isGPRAsmReg()) {
6163 reportParseError(ReturnRegOpnd.getStartLoc(),
6164 "expected general purpose register");
6165 return false;
6166 }
6167
6168 // If this is not the end of the statement, report an error.
6169 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6170 reportParseError("unexpected token, expected end of statement");
6171 return false;
6172 }
6173
6174 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6175 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006176 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006177 return false;
6178 }
6179
Jack Carter07c818d2013-01-25 01:31:34 +00006180 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006181 parseDirectiveSet();
6182 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006183 }
6184
Daniel Sandersd97a6342014-08-13 10:07:34 +00006185 if (IDVal == ".mask" || IDVal == ".fmask") {
6186 // .mask bitmask, frame_offset
6187 // bitmask: One bit for each register used.
6188 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6189 // first register is expected to be saved.
6190 // Examples:
6191 // .mask 0x80000000, -4
6192 // .fmask 0x80000000, -4
6193 //
Jack Carterbe332172012-09-07 00:48:02 +00006194
Daniel Sandersd97a6342014-08-13 10:07:34 +00006195 // Parse the bitmask
6196 const MCExpr *BitMask;
6197 int64_t BitMaskVal;
6198
6199 if (Parser.parseExpression(BitMask)) {
6200 reportParseError("expected bitmask value");
6201 return false;
6202 }
6203
Jim Grosbach13760bd2015-05-30 01:25:56 +00006204 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006205 reportParseError("bitmask not an absolute expression");
6206 return false;
6207 }
6208
6209 if (Parser.getTok().is(AsmToken::Comma))
6210 Parser.Lex();
6211 else {
6212 reportParseError("unexpected token, expected comma");
6213 return false;
6214 }
6215
6216 // Parse the frame_offset
6217 const MCExpr *FrameOffset;
6218 int64_t FrameOffsetVal;
6219
6220 if (Parser.parseExpression(FrameOffset)) {
6221 reportParseError("expected frame offset value");
6222 return false;
6223 }
6224
Jim Grosbach13760bd2015-05-30 01:25:56 +00006225 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006226 reportParseError("frame offset not an absolute expression");
6227 return false;
6228 }
6229
6230 // If this is not the end of the statement, report an error.
6231 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6232 reportParseError("unexpected token, expected end of statement");
6233 return false;
6234 }
6235
6236 if (IDVal == ".mask")
6237 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6238 else
6239 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006240 return false;
6241 }
6242
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006243 if (IDVal == ".nan")
6244 return parseDirectiveNaN();
6245
Jack Carter07c818d2013-01-25 01:31:34 +00006246 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006247 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006248 return false;
6249 }
6250
Rafael Espindolab59fb732014-03-28 18:50:26 +00006251 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006252 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006253 return false;
6254 }
6255
Jack Carter07c818d2013-01-25 01:31:34 +00006256 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006257 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006258 return false;
6259 }
6260
Scott Egertond1aeb052016-02-15 16:11:51 +00006261 if (IDVal == ".hword") {
6262 parseDataDirective(2, DirectiveID.getLoc());
6263 return false;
6264 }
6265
Nirav Dave996fc132016-05-05 14:15:46 +00006266 if (IDVal == ".option") {
6267 parseDirectiveOption();
6268 return false;
6269 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006270
6271 if (IDVal == ".abicalls") {
6272 getTargetStreamer().emitDirectiveAbiCalls();
6273 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006274 Error(Parser.getTok().getLoc(),
6275 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006276 // Clear line
6277 Parser.eatToEndOfStatement();
6278 }
6279 return false;
6280 }
6281
Nirav Dave996fc132016-05-05 14:15:46 +00006282 if (IDVal == ".cpsetup") {
6283 parseDirectiveCPSetup();
6284 return false;
6285 }
6286 if (IDVal == ".cpreturn") {
6287 parseDirectiveCPReturn();
6288 return false;
6289 }
6290 if (IDVal == ".module") {
6291 parseDirectiveModule();
6292 return false;
6293 }
6294 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6295 parseInternalDirectiveReallowModule();
6296 return false;
6297 }
6298 if (IDVal == ".insn") {
6299 parseInsnDirective();
6300 return false;
6301 }
6302 if (IDVal == ".sbss") {
6303 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6304 return false;
6305 }
6306 if (IDVal == ".sdata") {
6307 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6308 return false;
6309 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006310
Rafael Espindola870c4e92012-01-11 03:56:41 +00006311 return true;
6312}
6313
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006314bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6315 // If this is not the end of the statement, report an error.
6316 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6317 reportParseError("unexpected token, expected end of statement");
6318 return false;
6319 }
6320
6321 getTargetStreamer().reallowModuleDirective();
6322
6323 getParser().Lex(); // Eat EndOfStatement token.
6324 return false;
6325}
6326
Rafael Espindola870c4e92012-01-11 03:56:41 +00006327extern "C" void LLVMInitializeMipsAsmParser() {
6328 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6329 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6330 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6331 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6332}
Jack Carterb4dbc172012-09-05 23:34:03 +00006333
6334#define GET_REGISTER_MATCHER
6335#define GET_MATCHER_IMPLEMENTATION
6336#include "MipsGenAsmMatcher.inc"