blob: 128cef7bc8deceb06b855abc81a01ff8fa416bdc [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 Sanderse473dc92016-05-09 13:38:25 +00001095 template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
1096 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1097 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1098 && (getMemBase()->getGPR32Reg() == Mips::GP);
1099 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001100 template <unsigned Bits, unsigned ShiftLeftAmount>
1101 bool isScaledUImm() const {
1102 return isConstantImm() &&
1103 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001104 }
Daniel Sanders97297772016-03-22 14:40:00 +00001105 template <unsigned Bits, unsigned ShiftLeftAmount>
1106 bool isScaledSImm() const {
1107 return isConstantImm() &&
1108 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
1109 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001110 bool isRegList16() const {
1111 if (!isRegList())
1112 return false;
1113
1114 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001115 if (Size < 2 || Size > 5)
1116 return false;
1117
1118 unsigned R0 = RegList.List->front();
1119 unsigned R1 = RegList.List->back();
1120 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1121 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001122 return false;
1123
1124 int PrevReg = *RegList.List->begin();
1125 for (int i = 1; i < Size - 1; i++) {
1126 int Reg = (*(RegList.List))[i];
1127 if ( Reg != PrevReg + 1)
1128 return false;
1129 PrevReg = Reg;
1130 }
1131
1132 return true;
1133 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001134 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001135 bool isLSAImm() const {
1136 if (!isConstantImm())
1137 return false;
1138 int64_t Val = getConstantImm();
1139 return 1 <= Val && Val <= 4;
1140 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001141 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001142 bool isMovePRegPair() const {
1143 if (Kind != k_RegList || RegList.List->size() != 2)
1144 return false;
1145
1146 unsigned R0 = RegList.List->front();
1147 unsigned R1 = RegList.List->back();
1148
1149 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1150 (R0 == Mips::A1 && R1 == Mips::A3) ||
1151 (R0 == Mips::A2 && R1 == Mips::A3) ||
1152 (R0 == Mips::A0 && R1 == Mips::S5) ||
1153 (R0 == Mips::A0 && R1 == Mips::S6) ||
1154 (R0 == Mips::A0 && R1 == Mips::A1) ||
1155 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001156 (R0 == Mips::A0 && R1 == Mips::A3) ||
1157 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1158 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1159 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1160 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1161 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1162 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1163 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1164 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001165 return true;
1166
1167 return false;
1168 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001169
1170 StringRef getToken() const {
1171 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001172 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001173 }
Zlatko Buljanba553a62016-05-09 08:07:28 +00001174 bool isRegPair() const {
1175 return Kind == k_RegPair && RegIdx.Index <= 30;
1176 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001177
Craig Topper56c590a2014-04-29 07:58:02 +00001178 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001179 // As a special case until we sort out the definition of div/divu, pretend
1180 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1181 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1182 RegIdx.Kind & RegKind_GPR)
1183 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001184
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001185 assert(Kind == k_PhysRegister && "Invalid access!");
1186 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001187 }
1188
Jack Carterb4dbc172012-09-05 23:34:03 +00001189 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001190 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001191 return Imm.Val;
1192 }
1193
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001194 int64_t getConstantImm() const {
1195 const MCExpr *Val = getImm();
1196 return static_cast<const MCConstantExpr *>(Val)->getValue();
1197 }
1198
1199 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001200 assert((Kind == k_Memory) && "Invalid access!");
1201 return Mem.Base;
1202 }
1203
1204 const MCExpr *getMemOff() const {
1205 assert((Kind == k_Memory) && "Invalid access!");
1206 return Mem.Off;
1207 }
1208
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001209 int64_t getConstantMemOff() const {
1210 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1211 }
1212
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001213 const SmallVectorImpl<unsigned> &getRegList() const {
1214 assert((Kind == k_RegList) && "Invalid access!");
1215 return *(RegList.List);
1216 }
1217
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001218 unsigned getRegPair() const {
1219 assert((Kind == k_RegPair) && "Invalid access!");
1220 return RegIdx.Index;
1221 }
1222
David Blaikie960ea3f2014-06-08 16:18:35 +00001223 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1224 MipsAsmParser &Parser) {
1225 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001226 Op->Tok.Data = Str.data();
1227 Op->Tok.Length = Str.size();
1228 Op->StartLoc = S;
1229 Op->EndLoc = S;
1230 return Op;
1231 }
1232
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001233 /// Create a numeric register (e.g. $1). The exact register remains
1234 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001235 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001236 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001237 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001238 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001239 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001240 }
1241
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001242 /// Create a register that is definitely a GPR.
1243 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001244 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001245 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001246 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001247 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001248 }
1249
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001250 /// Create a register that is definitely a FGR.
1251 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001252 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001253 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001254 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001255 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1256 }
1257
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001258 /// Create a register that is definitely a HWReg.
1259 /// This is typically only used for named registers such as $hwr_cpunum.
1260 static std::unique_ptr<MipsOperand>
1261 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1262 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1263 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1264 }
1265
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001266 /// Create a register that is definitely an FCC.
1267 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001268 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001269 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001270 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001271 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1272 }
1273
1274 /// Create a register that is definitely an ACC.
1275 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001276 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001277 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001278 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001279 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1280 }
1281
1282 /// Create a register that is definitely an MSA128.
1283 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001284 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001285 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001286 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001287 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1288 }
1289
1290 /// Create a register that is definitely an MSACtrl.
1291 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001292 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001293 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001294 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001295 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1296 }
1297
David Blaikie960ea3f2014-06-08 16:18:35 +00001298 static std::unique_ptr<MipsOperand>
1299 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1300 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001301 Op->Imm.Val = Val;
1302 Op->StartLoc = S;
1303 Op->EndLoc = E;
1304 return Op;
1305 }
1306
David Blaikie960ea3f2014-06-08 16:18:35 +00001307 static std::unique_ptr<MipsOperand>
1308 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1309 SMLoc E, MipsAsmParser &Parser) {
1310 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1311 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001312 Op->Mem.Off = Off;
1313 Op->StartLoc = S;
1314 Op->EndLoc = E;
1315 return Op;
1316 }
1317
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001318 static std::unique_ptr<MipsOperand>
1319 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1320 MipsAsmParser &Parser) {
1321 assert (Regs.size() > 0 && "Empty list not allowed");
1322
1323 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001324 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001325 Op->StartLoc = StartLoc;
1326 Op->EndLoc = EndLoc;
1327 return Op;
1328 }
1329
Daniel Sandersd044e492016-05-09 13:10:57 +00001330 static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
1331 SMLoc S, SMLoc E,
1332 MipsAsmParser &Parser) {
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001333 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
Zlatko Buljanba553a62016-05-09 08:07:28 +00001334 Op->RegIdx.Index = MOP.RegIdx.Index;
Daniel Sandersda43f0e2016-05-09 17:42:04 +00001335 Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
1336 Op->RegIdx.Kind = MOP.RegIdx.Kind;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001337 Op->StartLoc = S;
1338 Op->EndLoc = E;
1339 return Op;
1340 }
1341
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001342 bool isGPRAsmReg() const {
1343 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001344 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001345 bool isMM16AsmReg() const {
1346 if (!(isRegIdx() && RegIdx.Kind))
1347 return false;
1348 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1349 || RegIdx.Index == 16 || RegIdx.Index == 17);
1350 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001351 bool isMM16AsmRegZero() const {
1352 if (!(isRegIdx() && RegIdx.Kind))
1353 return false;
1354 return (RegIdx.Index == 0 ||
1355 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1356 RegIdx.Index == 17);
1357 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001358 bool isMM16AsmRegMoveP() const {
1359 if (!(isRegIdx() && RegIdx.Kind))
1360 return false;
1361 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1362 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1363 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001364 bool isFGRAsmReg() const {
1365 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1366 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001367 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001368 bool isHWRegsAsmReg() const {
1369 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001370 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001371 bool isCCRAsmReg() const {
1372 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001373 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001374 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001375 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1376 return false;
1377 if (!AsmParser.hasEightFccRegisters())
1378 return RegIdx.Index == 0;
1379 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001380 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001381 bool isACCAsmReg() const {
1382 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001383 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001384 bool isCOP0AsmReg() const {
1385 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1386 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001387 bool isCOP2AsmReg() const {
1388 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001389 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001390 bool isCOP3AsmReg() const {
1391 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1392 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001393 bool isMSA128AsmReg() const {
1394 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001395 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001396 bool isMSACtrlAsmReg() const {
1397 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001398 }
1399
Jack Carterb4dbc172012-09-05 23:34:03 +00001400 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001401 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001402 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001403 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001404
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001405 virtual ~MipsOperand() {
1406 switch (Kind) {
1407 case k_Immediate:
1408 break;
1409 case k_Memory:
1410 delete Mem.Base;
1411 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001412 case k_RegList:
1413 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001414 case k_PhysRegister:
1415 case k_RegisterIndex:
1416 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001417 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001418 break;
1419 }
1420 }
1421
Craig Topper56c590a2014-04-29 07:58:02 +00001422 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001423 switch (Kind) {
1424 case k_Immediate:
1425 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001426 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001427 OS << ">";
1428 break;
1429 case k_Memory:
1430 OS << "Mem<";
1431 Mem.Base->print(OS);
1432 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001433 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001434 OS << ">";
1435 break;
1436 case k_PhysRegister:
1437 OS << "PhysReg<" << PhysReg.Num << ">";
1438 break;
1439 case k_RegisterIndex:
1440 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1441 break;
1442 case k_Token:
1443 OS << Tok.Data;
1444 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001445 case k_RegList:
1446 OS << "RegList< ";
1447 for (auto Reg : (*RegList.List))
1448 OS << Reg << " ";
1449 OS << ">";
1450 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001451 case k_RegPair:
1452 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1453 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001454 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001455 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001456}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001457} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001458
Jack Carter9e65aa32013-03-22 00:05:30 +00001459namespace llvm {
1460extern const MCInstrDesc MipsInsts[];
1461}
1462static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1463 return MipsInsts[Opcode];
1464}
1465
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001466static bool hasShortDelaySlot(unsigned Opcode) {
1467 switch (Opcode) {
1468 case Mips::JALS_MM:
1469 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001470 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001471 case Mips::BGEZALS_MM:
1472 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001473 return true;
1474 default:
1475 return false;
1476 }
1477}
1478
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001479static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1480 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1481 return &SRExpr->getSymbol();
1482 }
1483
1484 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1485 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1486 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1487
1488 if (LHSSym)
1489 return LHSSym;
1490
1491 if (RHSSym)
1492 return RHSSym;
1493
1494 return nullptr;
1495 }
1496
1497 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1498 return getSingleMCSymbol(UExpr->getSubExpr());
1499
1500 return nullptr;
1501}
1502
1503static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1504 if (isa<MCSymbolRefExpr>(Expr))
1505 return 1;
1506
1507 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1508 return countMCSymbolRefExpr(BExpr->getLHS()) +
1509 countMCSymbolRefExpr(BExpr->getRHS());
1510
1511 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1512 return countMCSymbolRefExpr(UExpr->getSubExpr());
1513
1514 return 0;
1515}
1516
Jack Carter9e65aa32013-03-22 00:05:30 +00001517bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001518 MCStreamer &Out,
1519 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001520 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001521 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001522 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001523
Jack Carter9e65aa32013-03-22 00:05:30 +00001524 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001525
1526 if (MCID.isBranch() || MCID.isCall()) {
1527 const unsigned Opcode = Inst.getOpcode();
1528 MCOperand Offset;
1529
1530 switch (Opcode) {
1531 default:
1532 break;
Kai Nackee0245392015-01-27 19:11:28 +00001533 case Mips::BBIT0:
1534 case Mips::BBIT032:
1535 case Mips::BBIT1:
1536 case Mips::BBIT132:
1537 assert(hasCnMips() && "instruction only valid for octeon cpus");
1538 // Fall through
1539
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001540 case Mips::BEQ:
1541 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001542 case Mips::BEQ_MM:
1543 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001544 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001545 Offset = Inst.getOperand(2);
1546 if (!Offset.isImm())
1547 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001548 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001549 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001550 if (OffsetToAlignment(Offset.getImm(),
1551 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001552 return Error(IDLoc, "branch to misaligned address");
1553 break;
1554 case Mips::BGEZ:
1555 case Mips::BGTZ:
1556 case Mips::BLEZ:
1557 case Mips::BLTZ:
1558 case Mips::BGEZAL:
1559 case Mips::BLTZAL:
1560 case Mips::BC1F:
1561 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001562 case Mips::BGEZ_MM:
1563 case Mips::BGTZ_MM:
1564 case Mips::BLEZ_MM:
1565 case Mips::BLTZ_MM:
1566 case Mips::BGEZAL_MM:
1567 case Mips::BLTZAL_MM:
1568 case Mips::BC1F_MM:
1569 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001570 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001571 Offset = Inst.getOperand(1);
1572 if (!Offset.isImm())
1573 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001574 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001575 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001576 if (OffsetToAlignment(Offset.getImm(),
1577 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001578 return Error(IDLoc, "branch to misaligned address");
1579 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001580 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001581 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001582 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001583 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001584 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1585 Offset = Inst.getOperand(1);
1586 if (!Offset.isImm())
1587 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001588 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001589 return Error(IDLoc, "branch target out of range");
1590 if (OffsetToAlignment(Offset.getImm(), 2LL))
1591 return Error(IDLoc, "branch to misaligned address");
1592 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001593 }
1594 }
1595
Daniel Sandersa84989a2014-06-16 13:25:35 +00001596 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1597 // We still accept it but it is a normal nop.
1598 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1599 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1600 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1601 "nop instruction");
1602 }
1603
Kai Nackee0245392015-01-27 19:11:28 +00001604 if (hasCnMips()) {
1605 const unsigned Opcode = Inst.getOpcode();
1606 MCOperand Opnd;
1607 int Imm;
1608
1609 switch (Opcode) {
1610 default:
1611 break;
1612
1613 case Mips::BBIT0:
1614 case Mips::BBIT032:
1615 case Mips::BBIT1:
1616 case Mips::BBIT132:
1617 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1618 // The offset is handled above
1619 Opnd = Inst.getOperand(1);
1620 if (!Opnd.isImm())
1621 return Error(IDLoc, "expected immediate operand kind");
1622 Imm = Opnd.getImm();
1623 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1624 Opcode == Mips::BBIT1 ? 63 : 31))
1625 return Error(IDLoc, "immediate operand value out of range");
1626 if (Imm > 31) {
1627 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1628 : Mips::BBIT132);
1629 Inst.getOperand(1).setImm(Imm - 32);
1630 }
1631 break;
1632
Kai Nackee0245392015-01-27 19:11:28 +00001633 case Mips::SEQi:
1634 case Mips::SNEi:
1635 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1636 Opnd = Inst.getOperand(2);
1637 if (!Opnd.isImm())
1638 return Error(IDLoc, "expected immediate operand kind");
1639 Imm = Opnd.getImm();
1640 if (!isInt<10>(Imm))
1641 return Error(IDLoc, "immediate operand value out of range");
1642 break;
1643 }
1644 }
1645
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001646 // This expansion is not in a function called by tryExpandInstruction()
1647 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001648 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1649 inPicMode()) {
1650 warnIfNoMacro(IDLoc);
1651
1652 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1653
1654 // We can do this expansion if there's only 1 symbol in the argument
1655 // expression.
1656 if (countMCSymbolRefExpr(JalExpr) > 1)
1657 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1658
1659 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001660 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001661 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1662
1663 // FIXME: Add support for label+offset operands (currently causes an error).
1664 // FIXME: Add support for forward-declared local symbols.
1665 // FIXME: Add expansion for when the LargeGOT option is enabled.
1666 if (JalSym->isInSection() || JalSym->isTemporary()) {
1667 if (isABI_O32()) {
1668 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001669 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001670 // R_(MICRO)MIPS_GOT16 label
1671 // addiu $25, $25, 0
1672 // R_(MICRO)MIPS_LO16 label
1673 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001674 const MCExpr *Got16RelocExpr =
1675 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1676 const MCExpr *Lo16RelocExpr =
1677 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001678
Daniel Sandersa736b372016-04-29 13:33:12 +00001679 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1680 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1681 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1682 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001683 } else if (isABI_N32() || isABI_N64()) {
1684 // If it's a local symbol and the N32/N64 ABIs are being used,
1685 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001686 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001687 // R_(MICRO)MIPS_GOT_DISP label
1688 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001689 const MCExpr *GotDispRelocExpr =
1690 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001691
Daniel Sandersa736b372016-04-29 13:33:12 +00001692 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1693 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1694 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001695 }
1696 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001697 // If it's an external/weak symbol, we expand to:
1698 // lw/ld $25, 0($gp)
1699 // R_(MICRO)MIPS_CALL16 label
1700 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001701 const MCExpr *Call16RelocExpr =
1702 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001703
Daniel Sandersa736b372016-04-29 13:33:12 +00001704 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1705 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001706 }
1707
1708 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001709 if (IsCpRestoreSet && inMicroMipsMode())
1710 JalrInst.setOpcode(Mips::JALRS_MM);
1711 else
1712 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001713 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1714 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1715
1716 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1717 // This relocation is supposed to be an optimization hint for the linker
1718 // and is not necessary for correctness.
1719
1720 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001721 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001722 }
1723
Jack Carter9e65aa32013-03-22 00:05:30 +00001724 if (MCID.mayLoad() || MCID.mayStore()) {
1725 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001726 // reference or immediate we may have to expand instructions.
1727 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001728 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001729 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1730 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001731 MCOperand &Op = Inst.getOperand(i);
1732 if (Op.isImm()) {
1733 int MemOffset = Op.getImm();
1734 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001735 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001736 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001737 return false;
1738 }
1739 } else if (Op.isExpr()) {
1740 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001741 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001742 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001743 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001744 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001745 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001746 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001747 return false;
1748 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001749 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001750 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001751 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001752 }
1753 }
1754 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001755 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001756 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001757
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001758 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001759 if (MCID.mayLoad()) {
1760 // Try to create 16-bit GP relative load instruction.
1761 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1762 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1763 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1764 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1765 MCOperand &Op = Inst.getOperand(i);
1766 if (Op.isImm()) {
1767 int MemOffset = Op.getImm();
1768 MCOperand &DstReg = Inst.getOperand(0);
1769 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001770 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001771 getContext().getRegisterInfo()->getRegClass(
1772 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001773 (BaseReg.getReg() == Mips::GP ||
1774 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001775
Daniel Sandersa736b372016-04-29 13:33:12 +00001776 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1777 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001778 return false;
1779 }
1780 }
1781 }
1782 } // for
1783 } // if load
1784
1785 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1786
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001787 MCOperand Opnd;
1788 int Imm;
1789
1790 switch (Inst.getOpcode()) {
1791 default:
1792 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001793 case Mips::ADDIUSP_MM:
1794 Opnd = Inst.getOperand(0);
1795 if (!Opnd.isImm())
1796 return Error(IDLoc, "expected immediate operand kind");
1797 Imm = Opnd.getImm();
1798 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1799 Imm % 4 != 0)
1800 return Error(IDLoc, "immediate operand value out of range");
1801 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001802 case Mips::SLL16_MM:
1803 case Mips::SRL16_MM:
1804 Opnd = Inst.getOperand(2);
1805 if (!Opnd.isImm())
1806 return Error(IDLoc, "expected immediate operand kind");
1807 Imm = Opnd.getImm();
1808 if (Imm < 1 || Imm > 8)
1809 return Error(IDLoc, "immediate operand value out of range");
1810 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001811 case Mips::LI16_MM:
1812 Opnd = Inst.getOperand(1);
1813 if (!Opnd.isImm())
1814 return Error(IDLoc, "expected immediate operand kind");
1815 Imm = Opnd.getImm();
1816 if (Imm < -1 || Imm > 126)
1817 return Error(IDLoc, "immediate operand value out of range");
1818 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001819 case Mips::ADDIUR2_MM:
1820 Opnd = Inst.getOperand(2);
1821 if (!Opnd.isImm())
1822 return Error(IDLoc, "expected immediate operand kind");
1823 Imm = Opnd.getImm();
1824 if (!(Imm == 1 || Imm == -1 ||
1825 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1826 return Error(IDLoc, "immediate operand value out of range");
1827 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001828 case Mips::ANDI16_MM:
1829 Opnd = Inst.getOperand(2);
1830 if (!Opnd.isImm())
1831 return Error(IDLoc, "expected immediate operand kind");
1832 Imm = Opnd.getImm();
1833 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1834 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1835 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1836 return Error(IDLoc, "immediate operand value out of range");
1837 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001838 case Mips::LBU16_MM:
1839 Opnd = Inst.getOperand(2);
1840 if (!Opnd.isImm())
1841 return Error(IDLoc, "expected immediate operand kind");
1842 Imm = Opnd.getImm();
1843 if (Imm < -1 || Imm > 14)
1844 return Error(IDLoc, "immediate operand value out of range");
1845 break;
1846 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001847 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001848 Opnd = Inst.getOperand(2);
1849 if (!Opnd.isImm())
1850 return Error(IDLoc, "expected immediate operand kind");
1851 Imm = Opnd.getImm();
1852 if (Imm < 0 || Imm > 15)
1853 return Error(IDLoc, "immediate operand value out of range");
1854 break;
1855 case Mips::LHU16_MM:
1856 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001857 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001858 Opnd = Inst.getOperand(2);
1859 if (!Opnd.isImm())
1860 return Error(IDLoc, "expected immediate operand kind");
1861 Imm = Opnd.getImm();
1862 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1863 return Error(IDLoc, "immediate operand value out of range");
1864 break;
1865 case Mips::LW16_MM:
1866 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001867 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001868 Opnd = Inst.getOperand(2);
1869 if (!Opnd.isImm())
1870 return Error(IDLoc, "expected immediate operand kind");
1871 Imm = Opnd.getImm();
1872 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1873 return Error(IDLoc, "immediate operand value out of range");
1874 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001875 case Mips::ADDIUPC_MM:
1876 MCOperand Opnd = Inst.getOperand(1);
1877 if (!Opnd.isImm())
1878 return Error(IDLoc, "expected immediate operand kind");
1879 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001880 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001881 return Error(IDLoc, "immediate operand value out of range");
1882 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001883 }
1884 }
1885
Daniel Sandersd8c07762016-04-18 12:35:36 +00001886 bool FillDelaySlot =
1887 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
1888 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00001889 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001890
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001891 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001892 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001893 switch (ExpandResult) {
1894 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001895 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001896 break;
1897 case MER_Success:
1898 break;
1899 case MER_Fail:
1900 return true;
1901 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001902
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001903 // If this instruction has a delay slot and .set reorder is active,
1904 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00001905 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001906 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
1907 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001908 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001909
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001910 if ((Inst.getOpcode() == Mips::JalOneReg ||
1911 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1912 isPicAndNotNxxAbi()) {
1913 if (IsCpRestoreSet) {
1914 // We need a NOP between the JALR and the LW:
1915 // If .set reorder has been used, we've already emitted a NOP.
1916 // If .set noreorder has been used, we need to emit a NOP at this point.
1917 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00001918 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
1919 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001920
1921 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00001922 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001923 } else
1924 Warning(IDLoc, "no .cprestore used in PIC mode");
1925 }
1926
Jack Carter9e65aa32013-03-22 00:05:30 +00001927 return false;
1928}
1929
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001930MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001931MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
1932 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001933 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001934 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001935 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001936 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001937 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001938 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001939 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001940 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001941 case Mips::LoadAddrImm64:
1942 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1943 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1944 "expected immediate operand kind");
1945
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001946 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1947 Inst.getOperand(1),
1948 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001949 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001950 ? MER_Fail
1951 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001952 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001953 case Mips::LoadAddrReg64:
1954 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1955 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1956 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1957 "expected immediate operand kind");
1958
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001959 return expandLoadAddress(Inst.getOperand(0).getReg(),
1960 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1961 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001962 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001963 ? MER_Fail
1964 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001965 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001966 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001967 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
1968 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001969 case Mips::SWM_MM:
1970 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001971 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
1972 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001973 case Mips::JalOneReg:
1974 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001975 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00001976 case Mips::BneImm:
1977 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001978 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00001979 case Mips::BLT:
1980 case Mips::BLE:
1981 case Mips::BGE:
1982 case Mips::BGT:
1983 case Mips::BLTU:
1984 case Mips::BLEU:
1985 case Mips::BGEU:
1986 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001987 case Mips::BLTL:
1988 case Mips::BLEL:
1989 case Mips::BGEL:
1990 case Mips::BGTL:
1991 case Mips::BLTUL:
1992 case Mips::BLEUL:
1993 case Mips::BGEUL:
1994 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00001995 case Mips::BLTImmMacro:
1996 case Mips::BLEImmMacro:
1997 case Mips::BGEImmMacro:
1998 case Mips::BGTImmMacro:
1999 case Mips::BLTUImmMacro:
2000 case Mips::BLEUImmMacro:
2001 case Mips::BGEUImmMacro:
2002 case Mips::BGTUImmMacro:
2003 case Mips::BLTLImmMacro:
2004 case Mips::BLELImmMacro:
2005 case Mips::BGELImmMacro:
2006 case Mips::BGTLImmMacro:
2007 case Mips::BLTULImmMacro:
2008 case Mips::BLEULImmMacro:
2009 case Mips::BGEULImmMacro:
2010 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002011 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002012 case Mips::SDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002013 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
2014 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002015 case Mips::DSDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002016 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
2017 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002018 case Mips::UDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002019 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2020 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002021 case Mips::DUDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002022 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2023 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002024 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002025 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2026 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002027 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002028 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002029 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002030 case Mips::PseudoTRUNC_W_D:
2031 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2032 : MER_Success;
2033 case Mips::Ulh:
2034 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2035 case Mips::Ulhu:
2036 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2037 case Mips::Ulw:
2038 return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2039 case Mips::NORImm:
2040 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002041 case Mips::ADDi:
2042 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002043 case Mips::SLTi:
2044 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002045 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2046 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2047 int64_t ImmValue = Inst.getOperand(2).getImm();
2048 if (isInt<16>(ImmValue))
2049 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002050 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2051 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002052 }
2053 return MER_NotAMacro;
2054 case Mips::ANDi:
2055 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002056 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002057 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2058 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2059 int64_t ImmValue = Inst.getOperand(2).getImm();
2060 if (isUInt<16>(ImmValue))
2061 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002062 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2063 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002064 }
2065 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002066 case Mips::ROL:
2067 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002068 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002069 case Mips::ROLImm:
2070 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002071 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002072 case Mips::DROL:
2073 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002074 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002075 case Mips::DROLImm:
2076 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002077 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002078 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002079 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002080 }
Jack Carter30a59822012-10-04 04:03:53 +00002081}
Jack Carter92995f12012-10-06 00:53:28 +00002082
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002083bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002084 MCStreamer &Out,
2085 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002086 MipsTargetStreamer &TOut = getTargetStreamer();
2087
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002088 // Create a JALR instruction which is going to replace the pseudo-JAL.
2089 MCInst JalrInst;
2090 JalrInst.setLoc(IDLoc);
2091 const MCOperand FirstRegOp = Inst.getOperand(0);
2092 const unsigned Opcode = Inst.getOpcode();
2093
2094 if (Opcode == Mips::JalOneReg) {
2095 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002096 if (IsCpRestoreSet && inMicroMipsMode()) {
2097 JalrInst.setOpcode(Mips::JALRS16_MM);
2098 JalrInst.addOperand(FirstRegOp);
2099 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002100 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002101 JalrInst.addOperand(FirstRegOp);
2102 } else {
2103 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002104 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002105 JalrInst.addOperand(FirstRegOp);
2106 }
2107 } else if (Opcode == Mips::JalTwoReg) {
2108 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002109 if (IsCpRestoreSet && inMicroMipsMode())
2110 JalrInst.setOpcode(Mips::JALRS_MM);
2111 else
2112 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002113 JalrInst.addOperand(FirstRegOp);
2114 const MCOperand SecondRegOp = Inst.getOperand(1);
2115 JalrInst.addOperand(SecondRegOp);
2116 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002117 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002118
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002119 // If .set reorder is active and branch instruction has a delay slot,
2120 // emit a NOP after it.
2121 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002122 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2123 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2124 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002125
2126 return false;
2127}
2128
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002129/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002130template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002131 unsigned BitNum = findFirstSet(x);
2132
2133 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2134}
2135
2136/// Load (or add) an immediate into a register.
2137///
2138/// @param ImmValue The immediate to load.
2139/// @param DstReg The register that will hold the immediate.
2140/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2141/// for a simple initialization.
2142/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2143/// @param IsAddress True if the immediate represents an address. False if it
2144/// is an integer.
2145/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002146bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002147 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002148 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2149 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002150 MipsTargetStreamer &TOut = getTargetStreamer();
2151
Toma Tabacu00e98672015-05-01 12:19:27 +00002152 if (!Is32BitImm && !isGP64bit()) {
2153 Error(IDLoc, "instruction requires a 64-bit architecture");
2154 return true;
2155 }
2156
Daniel Sanders03f9c012015-07-14 12:24:22 +00002157 if (Is32BitImm) {
2158 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2159 // Sign extend up to 64-bit so that the predicates match the hardware
2160 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2161 // true.
2162 ImmValue = SignExtend64<32>(ImmValue);
2163 } else {
2164 Error(IDLoc, "instruction requires a 32-bit immediate");
2165 return true;
2166 }
2167 }
2168
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002169 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2170 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2171
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002172 bool UseSrcReg = false;
2173 if (SrcReg != Mips::NoRegister)
2174 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002175
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002176 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002177 if (UseSrcReg &&
2178 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002179 // At this point we need AT to perform the expansions and we exit if it is
2180 // not available.
2181 unsigned ATReg = getATReg(IDLoc);
2182 if (!ATReg)
2183 return true;
2184 TmpReg = ATReg;
2185 }
2186
Daniel Sanders03f9c012015-07-14 12:24:22 +00002187 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002188 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002189 SrcReg = ZeroReg;
2190
2191 // This doesn't quite follow the usual ABI expectations for N32 but matches
2192 // traditional assembler behaviour. N32 would normally use addiu for both
2193 // integers and addresses.
2194 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002195 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002196 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002197 }
2198
Daniel Sandersa736b372016-04-29 13:33:12 +00002199 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002200 return false;
2201 }
2202
2203 if (isUInt<16>(ImmValue)) {
2204 unsigned TmpReg = DstReg;
2205 if (SrcReg == DstReg) {
2206 TmpReg = getATReg(IDLoc);
2207 if (!TmpReg)
2208 return true;
2209 }
2210
Daniel Sandersa736b372016-04-29 13:33:12 +00002211 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002212 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002213 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002214 return false;
2215 }
2216
2217 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002218 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002219
Toma Tabacu79588102015-04-29 10:19:56 +00002220 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2221 uint16_t Bits15To0 = ImmValue & 0xffff;
2222
Toma Tabacua3d056f2015-05-15 09:42:11 +00002223 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002224 // Traditional behaviour seems to special case this particular value. It's
2225 // not clear why other masks are handled differently.
2226 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002227 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2228 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002229 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002230 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002231 return false;
2232 }
2233
2234 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002235 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002236 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2237 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002238 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002239 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002240 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002241 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002242 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002243 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002244
Daniel Sandersa736b372016-04-29 13:33:12 +00002245 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002246 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002247 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002248 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002249 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002250 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002251 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002252
2253 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2254 if (Is32BitImm) {
2255 Error(IDLoc, "instruction requires a 32-bit immediate");
2256 return true;
2257 }
2258
2259 // Traditionally, these immediates are shifted as little as possible and as
2260 // such we align the most significant bit to bit 15 of our temporary.
2261 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2262 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2263 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2264 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002265 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2266 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002267
2268 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002269 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002270
2271 return false;
2272 }
2273
2274 warnIfNoMacro(IDLoc);
2275
2276 // The remaining case is packed with a sequence of dsll and ori with zeros
2277 // being omitted and any neighbouring dsll's being coalesced.
2278 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2279
2280 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2281 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002282 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002283 return false;
2284
2285 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2286 // skip it and defer the shift to the next chunk.
2287 unsigned ShiftCarriedForwards = 16;
2288 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2289 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2290
2291 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002292 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2293 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002294 ShiftCarriedForwards = 0;
2295 }
2296
2297 ShiftCarriedForwards += 16;
2298 }
2299 ShiftCarriedForwards -= 16;
2300
2301 // Finish any remaining shifts left by trailing zeros.
2302 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002303 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002304
2305 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002306 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002307
Matheus Almeida3813d572014-06-19 14:39:14 +00002308 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002309}
Jack Carter92995f12012-10-06 00:53:28 +00002310
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002311bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002312 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002313 const MCOperand &ImmOp = Inst.getOperand(1);
2314 assert(ImmOp.isImm() && "expected immediate operand kind");
2315 const MCOperand &DstRegOp = Inst.getOperand(0);
2316 assert(DstRegOp.isReg() && "expected register operand kind");
2317
2318 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002319 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002320 return true;
2321
2322 return false;
2323}
2324
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002325bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2326 const MCOperand &Offset,
2327 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002328 MCStreamer &Out,
2329 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002330 // la can't produce a usable address when addresses are 64-bit.
2331 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2332 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2333 // We currently can't do this because we depend on the equality
2334 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2335 Error(IDLoc, "la used to load 64-bit address");
2336 // Continue as if we had 'dla' instead.
2337 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002338 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002339
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002340 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002341 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002342 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002343 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002344 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002345
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002346 if (!Offset.isImm())
2347 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002348 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002349
Scott Egerton24557012016-01-21 15:11:01 +00002350 if (!ABI.ArePtrs64bit()) {
2351 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2352 Is32BitAddress = true;
2353 }
2354
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002355 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002356 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002357}
2358
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002359bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2360 unsigned DstReg, unsigned SrcReg,
2361 bool Is32BitSym, SMLoc IDLoc,
2362 MCStreamer &Out,
2363 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002364 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacu81496c12015-05-20 08:54:45 +00002365 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002366
Daniel Sandersd5a89412015-10-05 13:19:29 +00002367 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002368 const MipsMCExpr *HiExpr =
2369 MipsMCExpr::create(MipsMCExpr::MEK_HI, Symbol, getContext());
2370 const MipsMCExpr *LoExpr =
2371 MipsMCExpr::create(MipsMCExpr::MEK_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002372
Toma Tabacufb9d1252015-06-22 12:08:39 +00002373 bool UseSrcReg = SrcReg != Mips::NoRegister;
2374
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002375 // This is the 64-bit symbol address expansion.
2376 if (ABI.ArePtrs64bit() && isGP64bit()) {
2377 // We always need AT for the 64-bit expansion.
2378 // If it is not available we exit.
2379 unsigned ATReg = getATReg(IDLoc);
2380 if (!ATReg)
2381 return true;
2382
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002383 const MipsMCExpr *HighestExpr =
2384 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, Symbol, getContext());
2385 const MipsMCExpr *HigherExpr =
2386 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002387
Scott Egerton24557012016-01-21 15:11:01 +00002388 if (UseSrcReg &&
2389 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2390 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002391 // If $rs is the same as $rd:
2392 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2393 // daddiu $at, $at, %higher(sym)
2394 // dsll $at, $at, 16
2395 // daddiu $at, $at, %hi(sym)
2396 // dsll $at, $at, 16
2397 // daddiu $at, $at, %lo(sym)
2398 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002399 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2400 STI);
2401 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2402 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2403 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2404 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2405 IDLoc, STI);
2406 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2407 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2408 IDLoc, STI);
2409 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002410
2411 return false;
2412 }
2413
2414 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2415 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2416 // lui $at, %hi(sym)
2417 // daddiu $rd, $rd, %higher(sym)
2418 // daddiu $at, $at, %lo(sym)
2419 // dsll32 $rd, $rd, 0
2420 // daddu $rd, $rd, $at
2421 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002422 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2423 STI);
2424 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2425 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2426 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2427 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2428 IDLoc, STI);
2429 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2430 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002431 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002432 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002433
2434 return false;
2435 }
2436
2437 // And now, the 32-bit symbol address expansion:
2438 // If $rs is the same as $rd:
2439 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2440 // ori $at, $at, %lo(sym)
2441 // addu $rd, $at, $rd
2442 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2443 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2444 // ori $rd, $rd, %lo(sym)
2445 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002446 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002447 if (UseSrcReg &&
2448 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002449 // If $rs is the same as $rd, we need to use AT.
2450 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002451 unsigned ATReg = getATReg(IDLoc);
2452 if (!ATReg)
2453 return true;
2454 TmpReg = ATReg;
2455 }
2456
Daniel Sandersa736b372016-04-29 13:33:12 +00002457 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2458 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2459 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002460
Toma Tabacufb9d1252015-06-22 12:08:39 +00002461 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002462 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002463 else
Scott Egerton24557012016-01-21 15:11:01 +00002464 assert(
2465 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002466
Toma Tabacu674825c2015-06-16 12:16:24 +00002467 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002468}
2469
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002470bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2471 MCStreamer &Out,
2472 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002473 MipsTargetStreamer &TOut = getTargetStreamer();
2474
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002475 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2476 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002477
2478 MCOperand Offset = Inst.getOperand(0);
2479 if (Offset.isExpr()) {
2480 Inst.clear();
2481 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002482 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2483 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2484 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002485 } else {
2486 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002487 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002488 // If offset fits into 11 bits then this instruction becomes microMIPS
2489 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002490 if (inMicroMipsMode())
2491 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002492 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002493 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002494 Error(IDLoc, "branch target out of range");
2495 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2496 Error(IDLoc, "branch to misaligned address");
2497 Inst.clear();
2498 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002499 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2500 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2501 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002502 }
2503 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002504 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002505
Zoran Jovanovicada70912015-09-07 11:56:37 +00002506 // If .set reorder is active and branch instruction has a delay slot,
2507 // emit a NOP after it.
2508 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2509 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002510 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002511
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002512 return false;
2513}
2514
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002515bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2516 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002517 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002518 const MCOperand &DstRegOp = Inst.getOperand(0);
2519 assert(DstRegOp.isReg() && "expected register operand kind");
2520
2521 const MCOperand &ImmOp = Inst.getOperand(1);
2522 assert(ImmOp.isImm() && "expected immediate operand kind");
2523
2524 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002525 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2526 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002527
2528 unsigned OpCode = 0;
2529 switch(Inst.getOpcode()) {
2530 case Mips::BneImm:
2531 OpCode = Mips::BNE;
2532 break;
2533 case Mips::BeqImm:
2534 OpCode = Mips::BEQ;
2535 break;
2536 default:
2537 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2538 break;
2539 }
2540
2541 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002542 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002543 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2544 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002545 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002546 warnIfNoMacro(IDLoc);
2547
2548 unsigned ATReg = getATReg(IDLoc);
2549 if (!ATReg)
2550 return true;
2551
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002552 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002553 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002554 return true;
2555
Daniel Sandersa736b372016-04-29 13:33:12 +00002556 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002557 }
2558 return false;
2559}
2560
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002561void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002562 const MCSubtargetInfo *STI, bool IsLoad,
2563 bool IsImmOpnd) {
2564 if (IsLoad) {
2565 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2566 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002567 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002568 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2569}
2570
2571void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2572 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2573 MipsTargetStreamer &TOut = getTargetStreamer();
2574
2575 unsigned DstReg = Inst.getOperand(0).getReg();
2576 unsigned BaseReg = Inst.getOperand(1).getReg();
2577
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002578 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002579 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2580 unsigned DstRegClassID =
2581 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2582 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2583 (DstRegClassID == Mips::GPR64RegClassID);
2584
2585 if (IsImmOpnd) {
2586 // Try to use DstReg as the temporary.
2587 if (IsGPR && (BaseReg != DstReg)) {
2588 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2589 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2590 STI);
2591 return;
2592 }
2593
Matheus Almeida7de68e72014-06-18 14:46:05 +00002594 // At this point we need AT to perform the expansions and we exit if it is
2595 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002596 unsigned ATReg = getATReg(IDLoc);
2597 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002598 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002599
2600 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2601 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2602 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002603 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002604
Daniel Sandersfba875f2016-04-29 13:43:45 +00002605 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002606 MCOperand LoOperand = MCOperand::createExpr(
2607 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2608 MCOperand HiOperand = MCOperand::createExpr(
2609 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002610
2611 // Try to use DstReg as the temporary.
2612 if (IsGPR && (BaseReg != DstReg)) {
2613 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2614 LoOperand, DstReg, IDLoc, STI);
2615 return;
2616 }
2617
2618 // At this point we need AT to perform the expansions and we exit if it is
2619 // not available.
2620 unsigned ATReg = getATReg(IDLoc);
2621 if (!ATReg)
2622 return;
2623
2624 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2625 LoOperand, ATReg, IDLoc, STI);
2626}
2627
2628void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2629 const MCSubtargetInfo *STI,
2630 bool IsImmOpnd) {
2631 MipsTargetStreamer &TOut = getTargetStreamer();
2632
2633 unsigned SrcReg = Inst.getOperand(0).getReg();
2634 unsigned BaseReg = Inst.getOperand(1).getReg();
2635
Daniel Sanders241c6792016-05-12 14:01:50 +00002636 if (IsImmOpnd) {
2637 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2638 Inst.getOperand(2).getImm(),
2639 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
2640 return;
2641 }
2642
Daniel Sandersfba875f2016-04-29 13:43:45 +00002643 unsigned ATReg = getATReg(IDLoc);
2644 if (!ATReg)
2645 return;
2646
Daniel Sandersfba875f2016-04-29 13:43:45 +00002647 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002648 MCOperand LoOperand = MCOperand::createExpr(
2649 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2650 MCOperand HiOperand = MCOperand::createExpr(
2651 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002652 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2653 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002654}
2655
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002656bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2657 MCStreamer &Out,
2658 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002659 unsigned OpNum = Inst.getNumOperands();
2660 unsigned Opcode = Inst.getOpcode();
2661 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2662
2663 assert (Inst.getOperand(OpNum - 1).isImm() &&
2664 Inst.getOperand(OpNum - 2).isReg() &&
2665 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2666
2667 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2668 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002669 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2670 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2671 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2672 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002673 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002674 if (inMicroMipsMode() && hasMips32r6())
2675 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2676 else
2677 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2678 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002679
2680 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002681 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002682 return false;
2683}
2684
Toma Tabacu1a108322015-06-17 13:20:24 +00002685bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002686 MCStreamer &Out,
2687 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002688 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002689 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002690 unsigned PseudoOpcode = Inst.getOpcode();
2691 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002692 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002693 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2694
2695 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002696 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002697
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002698 unsigned TrgReg;
2699 if (TrgOp.isReg())
2700 TrgReg = TrgOp.getReg();
2701 else if (TrgOp.isImm()) {
2702 warnIfNoMacro(IDLoc);
2703 EmittedNoMacroWarning = true;
2704
2705 TrgReg = getATReg(IDLoc);
2706 if (!TrgReg)
2707 return true;
2708
2709 switch(PseudoOpcode) {
2710 default:
2711 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2712 case Mips::BLTImmMacro:
2713 PseudoOpcode = Mips::BLT;
2714 break;
2715 case Mips::BLEImmMacro:
2716 PseudoOpcode = Mips::BLE;
2717 break;
2718 case Mips::BGEImmMacro:
2719 PseudoOpcode = Mips::BGE;
2720 break;
2721 case Mips::BGTImmMacro:
2722 PseudoOpcode = Mips::BGT;
2723 break;
2724 case Mips::BLTUImmMacro:
2725 PseudoOpcode = Mips::BLTU;
2726 break;
2727 case Mips::BLEUImmMacro:
2728 PseudoOpcode = Mips::BLEU;
2729 break;
2730 case Mips::BGEUImmMacro:
2731 PseudoOpcode = Mips::BGEU;
2732 break;
2733 case Mips::BGTUImmMacro:
2734 PseudoOpcode = Mips::BGTU;
2735 break;
2736 case Mips::BLTLImmMacro:
2737 PseudoOpcode = Mips::BLTL;
2738 break;
2739 case Mips::BLELImmMacro:
2740 PseudoOpcode = Mips::BLEL;
2741 break;
2742 case Mips::BGELImmMacro:
2743 PseudoOpcode = Mips::BGEL;
2744 break;
2745 case Mips::BGTLImmMacro:
2746 PseudoOpcode = Mips::BGTL;
2747 break;
2748 case Mips::BLTULImmMacro:
2749 PseudoOpcode = Mips::BLTUL;
2750 break;
2751 case Mips::BLEULImmMacro:
2752 PseudoOpcode = Mips::BLEUL;
2753 break;
2754 case Mips::BGEULImmMacro:
2755 PseudoOpcode = Mips::BGEUL;
2756 break;
2757 case Mips::BGTULImmMacro:
2758 PseudoOpcode = Mips::BGTUL;
2759 break;
2760 }
2761
2762 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002763 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002764 return true;
2765 }
2766
Toma Tabacu1a108322015-06-17 13:20:24 +00002767 switch (PseudoOpcode) {
2768 case Mips::BLT:
2769 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002770 case Mips::BLTL:
2771 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002772 AcceptsEquality = false;
2773 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002774 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2775 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002776 ZeroSrcOpcode = Mips::BGTZ;
2777 ZeroTrgOpcode = Mips::BLTZ;
2778 break;
2779 case Mips::BLE:
2780 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002781 case Mips::BLEL:
2782 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002783 AcceptsEquality = true;
2784 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002785 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2786 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002787 ZeroSrcOpcode = Mips::BGEZ;
2788 ZeroTrgOpcode = Mips::BLEZ;
2789 break;
2790 case Mips::BGE:
2791 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002792 case Mips::BGEL:
2793 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002794 AcceptsEquality = true;
2795 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002796 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2797 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002798 ZeroSrcOpcode = Mips::BLEZ;
2799 ZeroTrgOpcode = Mips::BGEZ;
2800 break;
2801 case Mips::BGT:
2802 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002803 case Mips::BGTL:
2804 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002805 AcceptsEquality = false;
2806 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002807 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2808 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002809 ZeroSrcOpcode = Mips::BLTZ;
2810 ZeroTrgOpcode = Mips::BGTZ;
2811 break;
2812 default:
2813 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2814 }
2815
Toma Tabacu1a108322015-06-17 13:20:24 +00002816 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2817 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2818 if (IsSrcRegZero && IsTrgRegZero) {
2819 // FIXME: All of these Opcode-specific if's are needed for compatibility
2820 // with GAS' behaviour. However, they may not generate the most efficient
2821 // code in some circumstances.
2822 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002823 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2824 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002825 return false;
2826 }
2827 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002828 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2829 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002830 Warning(IDLoc, "branch is always taken");
2831 return false;
2832 }
2833 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002834 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2835 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002836 Warning(IDLoc, "branch is always taken");
2837 return false;
2838 }
2839 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002840 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2841 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002842 return false;
2843 }
2844 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002845 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2846 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002847 return false;
2848 }
2849 if (AcceptsEquality) {
2850 // If both registers are $0 and the pseudo-branch accepts equality, it
2851 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00002852 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2853 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002854 Warning(IDLoc, "branch is always taken");
2855 return false;
2856 }
2857 // If both registers are $0 and the pseudo-branch does not accept
2858 // equality, it will never be taken, so we don't have to emit anything.
2859 return false;
2860 }
2861 if (IsSrcRegZero || IsTrgRegZero) {
2862 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2863 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2864 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2865 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2866 // the pseudo-branch will never be taken, so we don't emit anything.
2867 // This only applies to unsigned pseudo-branches.
2868 return false;
2869 }
2870 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2871 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2872 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2873 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2874 // the pseudo-branch will always be taken, so we emit an unconditional
2875 // branch.
2876 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00002877 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2878 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002879 Warning(IDLoc, "branch is always taken");
2880 return false;
2881 }
2882 if (IsUnsigned) {
2883 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2884 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2885 // the pseudo-branch will be taken only when the non-zero register is
2886 // different from 0, so we emit a BNEZ.
2887 //
2888 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2889 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2890 // the pseudo-branch will be taken only when the non-zero register is
2891 // equal to 0, so we emit a BEQZ.
2892 //
2893 // Because only BLEU and BGEU branch on equality, we can use the
2894 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00002895 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2896 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2897 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002898 return false;
2899 }
2900 // If we have a signed pseudo-branch and one of the registers is $0,
2901 // we can use an appropriate compare-to-zero branch. We select which one
2902 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00002903 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2904 IsSrcRegZero ? TrgReg : SrcReg,
2905 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002906 return false;
2907 }
2908
2909 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2910 // expansions. If it is not available, we return.
2911 unsigned ATRegNum = getATReg(IDLoc);
2912 if (!ATRegNum)
2913 return true;
2914
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002915 if (!EmittedNoMacroWarning)
2916 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002917
2918 // SLT fits well with 2 of our 4 pseudo-branches:
2919 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2920 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2921 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2922 // This is accomplished by using a BNEZ with the result of the SLT.
2923 //
2924 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2925 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2926 // Because only BGE and BLE branch on equality, we can use the
2927 // AcceptsEquality variable to decide when to emit the BEQZ.
2928 // Note that the order of the SLT arguments doesn't change between
2929 // opposites.
2930 //
2931 // The same applies to the unsigned variants, except that SLTu is used
2932 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00002933 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2934 ReverseOrderSLT ? TrgReg : SrcReg,
2935 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002936
Daniel Sandersa736b372016-04-29 13:33:12 +00002937 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2938 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2939 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2940 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002941 return false;
2942}
2943
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002944bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2945 const MCSubtargetInfo *STI, const bool IsMips64,
2946 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002947 MipsTargetStreamer &TOut = getTargetStreamer();
2948
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002949 if (hasMips32r6()) {
2950 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2951 return false;
2952 }
2953
2954 warnIfNoMacro(IDLoc);
2955
2956 const MCOperand &RsRegOp = Inst.getOperand(0);
2957 assert(RsRegOp.isReg() && "expected register operand kind");
2958 unsigned RsReg = RsRegOp.getReg();
2959
2960 const MCOperand &RtRegOp = Inst.getOperand(1);
2961 assert(RtRegOp.isReg() && "expected register operand kind");
2962 unsigned RtReg = RtRegOp.getReg();
2963 unsigned DivOp;
2964 unsigned ZeroReg;
2965
2966 if (IsMips64) {
2967 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2968 ZeroReg = Mips::ZERO_64;
2969 } else {
2970 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2971 ZeroReg = Mips::ZERO;
2972 }
2973
2974 bool UseTraps = useTraps();
2975
2976 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2977 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2978 Warning(IDLoc, "dividing zero by zero");
2979 if (IsMips64) {
2980 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2981 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002982 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002983 return false;
2984 }
2985
Daniel Sandersa736b372016-04-29 13:33:12 +00002986 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002987 return false;
2988 }
2989 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00002990 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002991 return false;
2992 }
2993 }
2994
2995 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2996 Warning(IDLoc, "division by zero");
2997 if (Signed) {
2998 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002999 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003000 return false;
3001 }
3002
Daniel Sandersa736b372016-04-29 13:33:12 +00003003 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003004 return false;
3005 }
3006 }
3007
3008 // FIXME: The values for these two BranchTarget variables may be different in
3009 // micromips. These magic numbers need to be removed.
3010 unsigned BranchTargetNoTraps;
3011 unsigned BranchTarget;
3012
3013 if (UseTraps) {
3014 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003015 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003016 } else {
3017 BranchTarget = IsMips64 ? 20 : 16;
3018 BranchTargetNoTraps = 8;
3019 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003020 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003021 }
3022
Daniel Sandersa736b372016-04-29 13:33:12 +00003023 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003024
3025 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003026 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003027
3028 if (!Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003029 TOut.emitR(Mips::MFLO, RsReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003030 return false;
3031 }
3032
3033 unsigned ATReg = getATReg(IDLoc);
3034 if (!ATReg)
3035 return true;
3036
Daniel Sandersa736b372016-04-29 13:33:12 +00003037 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003038 if (IsMips64) {
3039 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003040 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3041 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3042 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, 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, RtReg, ATReg, BranchTarget, IDLoc, STI);
3046 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003047 }
3048
3049 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003050 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003051 else {
3052 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003053 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3054 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3055 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003056 }
Daniel Sandersa736b372016-04-29 13:33:12 +00003057 TOut.emitR(Mips::MFLO, RsReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003058 return false;
3059}
3060
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003061bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003062 SMLoc IDLoc, MCStreamer &Out,
3063 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003064 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003065
3066 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3067 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3068 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3069
3070 unsigned FirstReg = Inst.getOperand(0).getReg();
3071 unsigned SecondReg = Inst.getOperand(1).getReg();
3072 unsigned ThirdReg = Inst.getOperand(2).getReg();
3073
3074 if (hasMips1() && !hasMips2()) {
3075 unsigned ATReg = getATReg(IDLoc);
3076 if (!ATReg)
3077 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003078 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3079 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3080 TOut.emitNop(IDLoc, STI);
3081 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3082 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3083 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3084 TOut.emitNop(IDLoc, STI);
3085 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3086 : Mips::CVT_W_S,
3087 FirstReg, SecondReg, IDLoc, STI);
3088 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3089 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003090 return false;
3091 }
3092
Daniel Sandersa736b372016-04-29 13:33:12 +00003093 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3094 : Mips::TRUNC_W_S,
3095 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003096
3097 return false;
3098}
3099
Daniel Sanders6394ee52015-10-15 14:52:58 +00003100bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003101 MCStreamer &Out, const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003102 MipsTargetStreamer &TOut = getTargetStreamer();
3103
Toma Tabacud88d79c2015-06-23 14:39:42 +00003104 if (hasMips32r6() || hasMips64r6()) {
3105 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3106 return false;
3107 }
3108
3109 warnIfNoMacro(IDLoc);
3110
3111 const MCOperand &DstRegOp = Inst.getOperand(0);
3112 assert(DstRegOp.isReg() && "expected register operand kind");
3113
3114 const MCOperand &SrcRegOp = Inst.getOperand(1);
3115 assert(SrcRegOp.isReg() && "expected register operand kind");
3116
3117 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3118 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3119
3120 unsigned DstReg = DstRegOp.getReg();
3121 unsigned SrcReg = SrcRegOp.getReg();
3122 int64_t OffsetValue = OffsetImmOp.getImm();
3123
3124 // NOTE: We always need AT for ULHU, as it is always used as the source
3125 // register for one of the LBu's.
3126 unsigned ATReg = getATReg(IDLoc);
3127 if (!ATReg)
3128 return true;
3129
3130 // When the value of offset+1 does not fit in 16 bits, we have to load the
3131 // offset in AT, (D)ADDu the original source register (if there was one), and
3132 // then use AT as the source register for the 2 generated LBu's.
3133 bool LoadedOffsetInAT = false;
3134 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3135 LoadedOffsetInAT = true;
3136
3137 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003138 true, IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003139 return true;
3140
3141 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3142 // because it will make our output more similar to GAS'. For example,
3143 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3144 // instead of just an "ori $1, $9, 32768".
3145 // NOTE: If there is no source register specified in the ULHU, the parser
3146 // will interpret it as $0.
3147 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003148 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003149 }
3150
3151 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3152 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3153 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3154
3155 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3156 if (isLittle()) {
3157 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3158 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3159 } else {
3160 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3161 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3162 }
3163
3164 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3165
Daniel Sandersa736b372016-04-29 13:33:12 +00003166 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3167 FirstLbuOffset, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003168
Daniel Sandersa736b372016-04-29 13:33:12 +00003169 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3170 STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003171
Daniel Sandersa736b372016-04-29 13:33:12 +00003172 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003173
Daniel Sandersa736b372016-04-29 13:33:12 +00003174 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003175
3176 return false;
3177}
3178
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003179bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3180 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003181 MipsTargetStreamer &TOut = getTargetStreamer();
3182
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003183 if (hasMips32r6() || hasMips64r6()) {
3184 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3185 return false;
3186 }
3187
3188 const MCOperand &DstRegOp = Inst.getOperand(0);
3189 assert(DstRegOp.isReg() && "expected register operand kind");
3190
3191 const MCOperand &SrcRegOp = Inst.getOperand(1);
3192 assert(SrcRegOp.isReg() && "expected register operand kind");
3193
3194 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3195 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3196
3197 unsigned SrcReg = SrcRegOp.getReg();
3198 int64_t OffsetValue = OffsetImmOp.getImm();
3199 unsigned ATReg = 0;
3200
3201 // When the value of offset+3 does not fit in 16 bits, we have to load the
3202 // offset in AT, (D)ADDu the original source register (if there was one), and
3203 // then use AT as the source register for the generated LWL and LWR.
3204 bool LoadedOffsetInAT = false;
3205 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3206 ATReg = getATReg(IDLoc);
3207 if (!ATReg)
3208 return true;
3209 LoadedOffsetInAT = true;
3210
3211 warnIfNoMacro(IDLoc);
3212
3213 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003214 true, IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003215 return true;
3216
3217 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3218 // because it will make our output more similar to GAS'. For example,
3219 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3220 // instead of just an "ori $1, $9, 32768".
3221 // NOTE: If there is no source register specified in the ULW, the parser
3222 // will interpret it as $0.
3223 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003224 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003225 }
3226
3227 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3228 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3229 if (isLittle()) {
3230 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3231 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3232 } else {
3233 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3234 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3235 }
3236
Daniel Sandersa736b372016-04-29 13:33:12 +00003237 TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3238 STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003239
Daniel Sandersa736b372016-04-29 13:33:12 +00003240 TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
3241 IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003242
3243 return false;
3244}
3245
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003246bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003247 MCStreamer &Out,
3248 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003249 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003250
3251 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3252 assert (Inst.getOperand(0).isReg() &&
3253 Inst.getOperand(1).isReg() &&
3254 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3255
3256 unsigned ATReg = Mips::NoRegister;
3257 unsigned FinalDstReg = Mips::NoRegister;
3258 unsigned DstReg = Inst.getOperand(0).getReg();
3259 unsigned SrcReg = Inst.getOperand(1).getReg();
3260 int64_t ImmValue = Inst.getOperand(2).getImm();
3261
3262 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3263
3264 unsigned FinalOpcode = Inst.getOpcode();
3265
3266 if (DstReg == SrcReg) {
3267 ATReg = getATReg(Inst.getLoc());
3268 if (!ATReg)
3269 return true;
3270 FinalDstReg = DstReg;
3271 DstReg = ATReg;
3272 }
3273
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003274 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003275 switch (FinalOpcode) {
3276 default:
3277 llvm_unreachable("unimplemented expansion");
3278 case (Mips::ADDi):
3279 FinalOpcode = Mips::ADD;
3280 break;
3281 case (Mips::ADDiu):
3282 FinalOpcode = Mips::ADDu;
3283 break;
3284 case (Mips::ANDi):
3285 FinalOpcode = Mips::AND;
3286 break;
3287 case (Mips::NORImm):
3288 FinalOpcode = Mips::NOR;
3289 break;
3290 case (Mips::ORi):
3291 FinalOpcode = Mips::OR;
3292 break;
3293 case (Mips::SLTi):
3294 FinalOpcode = Mips::SLT;
3295 break;
3296 case (Mips::SLTiu):
3297 FinalOpcode = Mips::SLTu;
3298 break;
3299 case (Mips::XORi):
3300 FinalOpcode = Mips::XOR;
3301 break;
3302 }
3303
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003304 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003305 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003306 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003307 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003308 return false;
3309 }
3310 return true;
3311}
3312
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003313bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3314 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003315 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003316 unsigned ATReg = Mips::NoRegister;
3317 unsigned DReg = Inst.getOperand(0).getReg();
3318 unsigned SReg = Inst.getOperand(1).getReg();
3319 unsigned TReg = Inst.getOperand(2).getReg();
3320 unsigned TmpReg = DReg;
3321
3322 unsigned FirstShift = Mips::NOP;
3323 unsigned SecondShift = Mips::NOP;
3324
3325 if (hasMips32r2()) {
3326
3327 if (DReg == SReg) {
3328 TmpReg = getATReg(Inst.getLoc());
3329 if (!TmpReg)
3330 return true;
3331 }
3332
3333 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003334 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3335 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003336 return false;
3337 }
3338
3339 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003340 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003341 return false;
3342 }
3343
3344 return true;
3345 }
3346
3347 if (hasMips32()) {
3348
3349 switch (Inst.getOpcode()) {
3350 default:
3351 llvm_unreachable("unexpected instruction opcode");
3352 case Mips::ROL:
3353 FirstShift = Mips::SRLV;
3354 SecondShift = Mips::SLLV;
3355 break;
3356 case Mips::ROR:
3357 FirstShift = Mips::SLLV;
3358 SecondShift = Mips::SRLV;
3359 break;
3360 }
3361
3362 ATReg = getATReg(Inst.getLoc());
3363 if (!ATReg)
3364 return true;
3365
Daniel Sandersa736b372016-04-29 13:33:12 +00003366 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3367 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3368 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3369 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003370
3371 return false;
3372 }
3373
3374 return true;
3375}
3376
3377bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003378 MCStreamer &Out,
3379 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003380 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003381 unsigned ATReg = Mips::NoRegister;
3382 unsigned DReg = Inst.getOperand(0).getReg();
3383 unsigned SReg = Inst.getOperand(1).getReg();
3384 int64_t ImmValue = Inst.getOperand(2).getImm();
3385
3386 unsigned FirstShift = Mips::NOP;
3387 unsigned SecondShift = Mips::NOP;
3388
3389 if (hasMips32r2()) {
3390
3391 if (Inst.getOpcode() == Mips::ROLImm) {
3392 uint64_t MaxShift = 32;
3393 uint64_t ShiftValue = ImmValue;
3394 if (ImmValue != 0)
3395 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003396 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003397 return false;
3398 }
3399
3400 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003401 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003402 return false;
3403 }
3404
3405 return true;
3406 }
3407
3408 if (hasMips32()) {
3409
3410 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003411 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003412 return false;
3413 }
3414
3415 switch (Inst.getOpcode()) {
3416 default:
3417 llvm_unreachable("unexpected instruction opcode");
3418 case Mips::ROLImm:
3419 FirstShift = Mips::SLL;
3420 SecondShift = Mips::SRL;
3421 break;
3422 case Mips::RORImm:
3423 FirstShift = Mips::SRL;
3424 SecondShift = Mips::SLL;
3425 break;
3426 }
3427
3428 ATReg = getATReg(Inst.getLoc());
3429 if (!ATReg)
3430 return true;
3431
Daniel Sandersa736b372016-04-29 13:33:12 +00003432 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3433 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3434 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003435
3436 return false;
3437 }
3438
3439 return true;
3440}
3441
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003442bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3443 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003444 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003445 unsigned ATReg = Mips::NoRegister;
3446 unsigned DReg = Inst.getOperand(0).getReg();
3447 unsigned SReg = Inst.getOperand(1).getReg();
3448 unsigned TReg = Inst.getOperand(2).getReg();
3449 unsigned TmpReg = DReg;
3450
3451 unsigned FirstShift = Mips::NOP;
3452 unsigned SecondShift = Mips::NOP;
3453
3454 if (hasMips64r2()) {
3455
3456 if (TmpReg == SReg) {
3457 TmpReg = getATReg(Inst.getLoc());
3458 if (!TmpReg)
3459 return true;
3460 }
3461
3462 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003463 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3464 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003465 return false;
3466 }
3467
3468 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003469 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003470 return false;
3471 }
3472
3473 return true;
3474 }
3475
3476 if (hasMips64()) {
3477
3478 switch (Inst.getOpcode()) {
3479 default:
3480 llvm_unreachable("unexpected instruction opcode");
3481 case Mips::DROL:
3482 FirstShift = Mips::DSRLV;
3483 SecondShift = Mips::DSLLV;
3484 break;
3485 case Mips::DROR:
3486 FirstShift = Mips::DSLLV;
3487 SecondShift = Mips::DSRLV;
3488 break;
3489 }
3490
3491 ATReg = getATReg(Inst.getLoc());
3492 if (!ATReg)
3493 return true;
3494
Daniel Sandersa736b372016-04-29 13:33:12 +00003495 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3496 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3497 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3498 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003499
3500 return false;
3501 }
3502
3503 return true;
3504}
3505
3506bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003507 MCStreamer &Out,
3508 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003509 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003510 unsigned ATReg = Mips::NoRegister;
3511 unsigned DReg = Inst.getOperand(0).getReg();
3512 unsigned SReg = Inst.getOperand(1).getReg();
3513 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3514
3515 unsigned FirstShift = Mips::NOP;
3516 unsigned SecondShift = Mips::NOP;
3517
3518 MCInst TmpInst;
3519
3520 if (hasMips64r2()) {
3521
3522 unsigned FinalOpcode = Mips::NOP;
3523 if (ImmValue == 0)
3524 FinalOpcode = Mips::DROTR;
3525 else if (ImmValue % 32 == 0)
3526 FinalOpcode = Mips::DROTR32;
3527 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3528 if (Inst.getOpcode() == Mips::DROLImm)
3529 FinalOpcode = Mips::DROTR32;
3530 else
3531 FinalOpcode = Mips::DROTR;
3532 } else if (ImmValue >= 33) {
3533 if (Inst.getOpcode() == Mips::DROLImm)
3534 FinalOpcode = Mips::DROTR;
3535 else
3536 FinalOpcode = Mips::DROTR32;
3537 }
3538
3539 uint64_t ShiftValue = ImmValue % 32;
3540 if (Inst.getOpcode() == Mips::DROLImm)
3541 ShiftValue = (32 - ImmValue % 32) % 32;
3542
Daniel Sandersa736b372016-04-29 13:33:12 +00003543 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003544
3545 return false;
3546 }
3547
3548 if (hasMips64()) {
3549
3550 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003551 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003552 return false;
3553 }
3554
3555 switch (Inst.getOpcode()) {
3556 default:
3557 llvm_unreachable("unexpected instruction opcode");
3558 case Mips::DROLImm:
3559 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3560 FirstShift = Mips::DSLL;
3561 SecondShift = Mips::DSRL32;
3562 }
3563 if (ImmValue == 32) {
3564 FirstShift = Mips::DSLL32;
3565 SecondShift = Mips::DSRL32;
3566 }
3567 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3568 FirstShift = Mips::DSLL32;
3569 SecondShift = Mips::DSRL;
3570 }
3571 break;
3572 case Mips::DRORImm:
3573 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3574 FirstShift = Mips::DSRL;
3575 SecondShift = Mips::DSLL32;
3576 }
3577 if (ImmValue == 32) {
3578 FirstShift = Mips::DSRL32;
3579 SecondShift = Mips::DSLL32;
3580 }
3581 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3582 FirstShift = Mips::DSRL32;
3583 SecondShift = Mips::DSLL;
3584 }
3585 break;
3586 }
3587
3588 ATReg = getATReg(Inst.getLoc());
3589 if (!ATReg)
3590 return true;
3591
Daniel Sandersa736b372016-04-29 13:33:12 +00003592 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3593 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3594 Inst.getLoc(), STI);
3595 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003596
3597 return false;
3598 }
3599
3600 return true;
3601}
3602
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003603bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3604 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003605 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003606 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3607 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3608
Daniel Sandersa736b372016-04-29 13:33:12 +00003609 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003610 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003611 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003612 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003613 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3614 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003615
3616 return false;
3617}
3618
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003619void MipsAsmParser::createCpRestoreMemOp(bool IsLoad, int StackOffset,
3620 SMLoc IDLoc, MCStreamer &Out,
3621 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003622 MipsTargetStreamer &TOut = getTargetStreamer();
3623
Daniel Sanders7225cd52016-04-29 16:16:49 +00003624 if (IsLoad) {
3625 TOut.emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, StackOffset,
3626 Mips::GP, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003627 return;
3628 }
3629
Daniel Sanders241c6792016-05-12 14:01:50 +00003630 TOut.emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, StackOffset,
3631 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003632}
3633
Matheus Almeida595fcab2014-06-11 15:05:56 +00003634unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3635 // As described by the Mips32r2 spec, the registers Rd and Rs for
3636 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00003637 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00003638 // and registers Rd and Base for microMIPS lwp instruction
Matheus Almeida595fcab2014-06-11 15:05:56 +00003639 unsigned Opcode = Inst.getOpcode();
3640
Zlatko Buljanae720db2016-04-22 06:44:34 +00003641 if ((Opcode == Mips::JALR_HB || Opcode == Mips::JALRC_HB_MMR6) &&
Matheus Almeida595fcab2014-06-11 15:05:56 +00003642 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3643 return Match_RequiresDifferentSrcAndDst;
Zlatko Buljanba553a62016-05-09 08:07:28 +00003644 else if ((Opcode == Mips::LWP_MM || Opcode == Mips::LWP_MMR6) &&
3645 (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()))
3646 return Match_RequiresDifferentSrcAndDst;
Matheus Almeida595fcab2014-06-11 15:05:56 +00003647
3648 return Match_Success;
3649}
3650
Daniel Sanders52da7af2015-11-06 12:11:03 +00003651static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3652 uint64_t ErrorInfo) {
3653 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3654 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3655 if (ErrorLoc == SMLoc())
3656 return Loc;
3657 return ErrorLoc;
3658 }
3659 return Loc;
3660}
3661
David Blaikie960ea3f2014-06-08 16:18:35 +00003662bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3663 OperandVector &Operands,
3664 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003665 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003666 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003667
Jack Carterb4dbc172012-09-05 23:34:03 +00003668 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00003669 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003670 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003671
3672 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003673 case Match_Success: {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003674 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00003675 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003676 return false;
3677 }
3678 case Match_MissingFeature:
3679 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3680 return true;
3681 case Match_InvalidOperand: {
3682 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003683 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003684 if (ErrorInfo >= Operands.size())
3685 return Error(IDLoc, "too few operands for instruction");
3686
Daniel Sanders52da7af2015-11-06 12:11:03 +00003687 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003688 if (ErrorLoc == SMLoc())
3689 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003690 }
3691
3692 return Error(ErrorLoc, "invalid operand for instruction");
3693 }
3694 case Match_MnemonicFail:
3695 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003696 case Match_RequiresDifferentSrcAndDst:
3697 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003698 case Match_Immz:
3699 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003700 case Match_UImm1_0:
3701 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3702 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003703 case Match_UImm2_0:
3704 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3705 "expected 2-bit unsigned immediate");
3706 case Match_UImm2_1:
3707 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3708 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003709 case Match_UImm3_0:
3710 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3711 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003712 case Match_UImm4_0:
3713 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3714 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003715 case Match_SImm4_0:
3716 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3717 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003718 case Match_UImm5_0:
3719 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3720 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00003721 case Match_SImm5_0:
3722 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3723 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003724 case Match_UImm5_1:
3725 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3726 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003727 case Match_UImm5_32:
3728 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3729 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003730 case Match_UImm5_33:
3731 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3732 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003733 case Match_UImm5_0_Report_UImm6:
3734 // This is used on UImm5 operands that have a corresponding UImm5_32
3735 // operand to avoid confusing the user.
3736 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3737 "expected 6-bit unsigned immediate");
3738 case Match_UImm5_Lsl2:
3739 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3740 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003741 case Match_UImmRange2_64:
3742 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3743 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003744 case Match_UImm6_0:
3745 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3746 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00003747 case Match_UImm6_Lsl2:
3748 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3749 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00003750 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00003751 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3752 "expected 6-bit signed immediate");
3753 case Match_UImm7_0:
3754 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3755 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00003756 case Match_UImm7_N1:
3757 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3758 "expected immediate in range -1 .. 126");
3759 case Match_SImm7_Lsl2:
3760 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3761 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003762 case Match_UImm8_0:
3763 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3764 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003765 case Match_UImm10_0:
3766 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3767 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00003768 case Match_SImm10_0:
3769 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3770 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00003771 case Match_SImm11_0:
3772 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3773 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003774 case Match_UImm16:
3775 case Match_UImm16_Relaxed:
3776 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3777 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003778 case Match_SImm16:
3779 case Match_SImm16_Relaxed:
3780 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3781 "expected 16-bit signed immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003782 case Match_UImm20_0:
3783 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3784 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00003785 case Match_UImm26_0:
3786 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3787 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00003788 case Match_SImm32:
3789 case Match_SImm32_Relaxed:
3790 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3791 "expected 32-bit signed immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00003792 case Match_MemSImm9:
3793 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3794 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00003795 case Match_MemSImm10:
3796 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3797 "expected memory with 10-bit signed offset");
3798 case Match_MemSImm10Lsl1:
3799 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3800 "expected memory with 11-bit signed offset and multiple of 2");
3801 case Match_MemSImm10Lsl2:
3802 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3803 "expected memory with 12-bit signed offset and multiple of 4");
3804 case Match_MemSImm10Lsl3:
3805 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3806 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00003807 case Match_MemSImm11:
3808 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3809 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00003810 case Match_MemSImm12:
3811 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3812 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003813 case Match_MemSImm16:
3814 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3815 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00003816 }
Craig Topper589ceee2015-01-03 08:16:34 +00003817
3818 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003819}
3820
Toma Tabacud9d344b2015-04-27 14:05:04 +00003821void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3822 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3823 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3824 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003825}
3826
Toma Tabacu81496c12015-05-20 08:54:45 +00003827void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3828 if (!AssemblerOptions.back()->isMacro())
3829 Warning(Loc, "macro instruction expanded into multiple instructions");
3830}
3831
Daniel Sandersef638fe2014-10-03 15:37:37 +00003832void
3833MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3834 SMRange Range, bool ShowColors) {
3835 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003836 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003837 ShowColors);
3838}
3839
Jack Carter1ac53222013-02-20 23:11:17 +00003840int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003841 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003842
Vladimir Medic4c299852013-11-06 11:27:05 +00003843 CC = StringSwitch<unsigned>(Name)
3844 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003845 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003846 .Case("a0", 4)
3847 .Case("a1", 5)
3848 .Case("a2", 6)
3849 .Case("a3", 7)
3850 .Case("v0", 2)
3851 .Case("v1", 3)
3852 .Case("s0", 16)
3853 .Case("s1", 17)
3854 .Case("s2", 18)
3855 .Case("s3", 19)
3856 .Case("s4", 20)
3857 .Case("s5", 21)
3858 .Case("s6", 22)
3859 .Case("s7", 23)
3860 .Case("k0", 26)
3861 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003862 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003863 .Case("sp", 29)
3864 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003865 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003866 .Case("ra", 31)
3867 .Case("t0", 8)
3868 .Case("t1", 9)
3869 .Case("t2", 10)
3870 .Case("t3", 11)
3871 .Case("t4", 12)
3872 .Case("t5", 13)
3873 .Case("t6", 14)
3874 .Case("t7", 15)
3875 .Case("t8", 24)
3876 .Case("t9", 25)
3877 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003878
Toma Tabacufda445c2014-09-15 15:33:01 +00003879 if (!(isABI_N32() || isABI_N64()))
3880 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003881
Daniel Sandersef638fe2014-10-03 15:37:37 +00003882 if (12 <= CC && CC <= 15) {
3883 // Name is one of t4-t7
3884 AsmToken RegTok = getLexer().peekTok();
3885 SMRange RegRange = RegTok.getLocRange();
3886
3887 StringRef FixedName = StringSwitch<StringRef>(Name)
3888 .Case("t4", "t0")
3889 .Case("t5", "t1")
3890 .Case("t6", "t2")
3891 .Case("t7", "t3")
3892 .Default("");
3893 assert(FixedName != "" && "Register name is not one of t4-t7.");
3894
3895 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3896 "Did you mean $" + FixedName + "?", RegRange);
3897 }
3898
Toma Tabacufda445c2014-09-15 15:33:01 +00003899 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3900 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3901 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3902 if (8 <= CC && CC <= 11)
3903 CC += 4;
3904
3905 if (CC == -1)
3906 CC = StringSwitch<unsigned>(Name)
3907 .Case("a4", 8)
3908 .Case("a5", 9)
3909 .Case("a6", 10)
3910 .Case("a7", 11)
3911 .Case("kt0", 26)
3912 .Case("kt1", 27)
3913 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003914
3915 return CC;
3916}
Jack Carterd0bd6422013-04-18 00:41:53 +00003917
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003918int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3919 int CC;
3920
3921 CC = StringSwitch<unsigned>(Name)
3922 .Case("hwr_cpunum", 0)
3923 .Case("hwr_synci_step", 1)
3924 .Case("hwr_cc", 2)
3925 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003926 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003927 .Default(-1);
3928
3929 return CC;
3930}
3931
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003932int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003933
Jack Cartera63b16a2012-09-07 00:23:42 +00003934 if (Name[0] == 'f') {
3935 StringRef NumString = Name.substr(1);
3936 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003937 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003938 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003939 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003940 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003941 return IntVal;
3942 }
3943 return -1;
3944}
Jack Cartera63b16a2012-09-07 00:23:42 +00003945
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003946int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3947
3948 if (Name.startswith("fcc")) {
3949 StringRef NumString = Name.substr(3);
3950 unsigned IntVal;
3951 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003952 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003953 if (IntVal > 7) // There are only 8 fcc registers.
3954 return -1;
3955 return IntVal;
3956 }
3957 return -1;
3958}
3959
3960int MipsAsmParser::matchACRegisterName(StringRef Name) {
3961
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003962 if (Name.startswith("ac")) {
3963 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003964 unsigned IntVal;
3965 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003966 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003967 if (IntVal > 3) // There are only 3 acc registers.
3968 return -1;
3969 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003970 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003971 return -1;
3972}
Jack Carterd0bd6422013-04-18 00:41:53 +00003973
Jack Carter5dc8ac92013-09-25 23:50:44 +00003974int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3975 unsigned IntVal;
3976
3977 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3978 return -1;
3979
3980 if (IntVal > 31)
3981 return -1;
3982
3983 return IntVal;
3984}
3985
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003986int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3987 int CC;
3988
3989 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003990 .Case("msair", 0)
3991 .Case("msacsr", 1)
3992 .Case("msaaccess", 2)
3993 .Case("msasave", 3)
3994 .Case("msamodify", 4)
3995 .Case("msarequest", 5)
3996 .Case("msamap", 6)
3997 .Case("msaunmap", 7)
3998 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003999
4000 return CC;
4001}
4002
Toma Tabacu89a712b2015-04-15 10:48:56 +00004003unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004004 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004005 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004006 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004007 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004008 return 0;
4009 }
4010 unsigned AT = getReg(
4011 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004012 return AT;
4013}
Jack Carter0b744b32012-10-04 02:29:46 +00004014
Jack Carterd0bd6422013-04-18 00:41:53 +00004015unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004016 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004017}
4018
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004019unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004020 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00004021 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004022}
4023
Jack Carter873c7242013-01-12 01:03:14 +00004024int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004025 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00004026 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00004027 return -1;
4028
Jack Carter873c7242013-01-12 01:03:14 +00004029 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00004030}
4031
Toma Tabacu13964452014-09-04 13:23:44 +00004032bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004033 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004034 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004035
Jack Carter30a59822012-10-04 04:03:53 +00004036 // Check if the current operand has a custom associated parser, if so, try to
4037 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004038 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4039 if (ResTy == MatchOperand_Success)
4040 return false;
4041 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4042 // there was a match, but an error occurred, in which case, just return that
4043 // the operand parsing failed.
4044 if (ResTy == MatchOperand_ParseFail)
4045 return true;
4046
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004047 DEBUG(dbgs() << ".. Generic Parser\n");
4048
Jack Carterb4dbc172012-09-05 23:34:03 +00004049 switch (getLexer().getKind()) {
4050 default:
4051 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4052 return true;
4053 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004054 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004055 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004056
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004057 // Almost all registers have been parsed by custom parsers. There is only
4058 // one exception to this. $zero (and it's alias $0) will reach this point
4059 // for div, divu, and similar instructions because it is not an operand
4060 // to the instruction definition but an explicit register. Special case
4061 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004062 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004063 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004064
Jack Carterd0bd6422013-04-18 00:41:53 +00004065 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004066 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004067 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004068 return true;
4069
Jack Carter873c7242013-01-12 01:03:14 +00004070 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004071 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004072 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004073 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004074 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004075
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004076 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004077 return false;
4078 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004079 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004080 case AsmToken::LParen:
4081 case AsmToken::Minus:
4082 case AsmToken::Plus:
4083 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004084 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004085 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004086 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004087 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004088 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004089 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004090 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004091 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004092 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004093 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004094 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004095 return true;
4096
Jack Carter873c7242013-01-12 01:03:14 +00004097 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4098
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004099 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004100 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004101 } // case AsmToken::Percent
4102 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004103 return true;
4104}
4105
Vladimir Medic4c299852013-11-06 11:27:05 +00004106const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004107 StringRef RelocStr) {
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004108 if (RelocStr == "hi(%neg(%gp_rel")
4109 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext());
4110 else if (RelocStr == "lo(%neg(%gp_rel")
4111 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004112
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004113 MipsMCExpr::MipsExprKind Kind =
4114 StringSwitch<MipsMCExpr::MipsExprKind>(RelocStr)
4115 .Case("call16", MipsMCExpr::MEK_GOT_CALL)
4116 .Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
4117 .Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
4118 .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
4119 .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
4120 .Case("got", MipsMCExpr::MEK_GOT)
4121 .Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
4122 .Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
4123 .Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
4124 .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
4125 .Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
4126 .Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
4127 .Case("gp_rel", MipsMCExpr::MEK_GPREL)
4128 .Case("hi", MipsMCExpr::MEK_HI)
4129 .Case("higher", MipsMCExpr::MEK_HIGHER)
4130 .Case("highest", MipsMCExpr::MEK_HIGHEST)
4131 .Case("lo", MipsMCExpr::MEK_LO)
4132 .Case("neg", MipsMCExpr::MEK_NEG)
4133 .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
4134 .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
4135 .Case("tlsgd", MipsMCExpr::MEK_TLSGD)
4136 .Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
4137 .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
4138 .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
4139 .Default(MipsMCExpr::MEK_None);
Jack Carterb5cf5902013-04-17 00:18:04 +00004140
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004141 assert(Kind != MipsMCExpr::MEK_None);
4142 return MipsMCExpr::create(Kind, Expr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004143}
4144
4145bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4146
4147 switch (Expr->getKind()) {
4148 case MCExpr::Constant:
4149 return true;
4150 case MCExpr::SymbolRef:
4151 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4152 case MCExpr::Binary:
4153 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4154 if (!isEvaluated(BE->getLHS()))
4155 return false;
4156 return isEvaluated(BE->getRHS());
4157 }
4158 case MCExpr::Unary:
4159 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004160 case MCExpr::Target:
4161 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004162 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004163 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004164}
Jack Carterd0bd6422013-04-18 00:41:53 +00004165
Jack Carterb5cf5902013-04-17 00:18:04 +00004166bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004167 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004168 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004169 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004170 if (Tok.isNot(AsmToken::Identifier))
4171 return true;
4172
Yaron Keren075759a2015-03-30 15:42:36 +00004173 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004174
Jack Carterd0bd6422013-04-18 00:41:53 +00004175 Parser.Lex(); // Eat the identifier.
4176 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004177 const MCExpr *IdVal;
4178 SMLoc EndLoc;
4179
4180 if (getLexer().getKind() == AsmToken::LParen) {
4181 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004182 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004183 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004184 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004185 const AsmToken &nextTok = Parser.getTok();
4186 if (nextTok.isNot(AsmToken::Identifier))
4187 return true;
4188 Str += "(%";
4189 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004190 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004191 if (getLexer().getKind() != AsmToken::LParen)
4192 return true;
4193 } else
4194 break;
4195 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004196 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004197 return true;
4198
4199 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004200 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004201
4202 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004203 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004204
Jack Carterd0bd6422013-04-18 00:41:53 +00004205 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004206 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004207}
4208
Jack Carterb4dbc172012-09-05 23:34:03 +00004209bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4210 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004211 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004212 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004213 if (ResTy == MatchOperand_Success) {
4214 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004215 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004216 StartLoc = Operand.getStartLoc();
4217 EndLoc = Operand.getEndLoc();
4218
4219 // AFAIK, we only support numeric registers and named GPR's in CFI
4220 // directives.
4221 // Don't worry about eating tokens before failing. Using an unrecognised
4222 // register is a parse error.
4223 if (Operand.isGPRAsmReg()) {
4224 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004225 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004226 }
4227
4228 return (RegNo == (unsigned)-1);
4229 }
4230
4231 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004232 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004233}
4234
Jack Carterb5cf5902013-04-17 00:18:04 +00004235bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004236 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004237 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004238 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004239 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004240
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004241 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004242 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004243 ++NumOfLParen;
4244 }
Jack Carter873c7242013-01-12 01:03:14 +00004245
Jack Carterd0bd6422013-04-18 00:41:53 +00004246 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004247 default:
4248 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004249 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004250 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004251 case AsmToken::Integer:
4252 case AsmToken::Minus:
4253 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004254 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004255 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004256 else
4257 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004258 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004259 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004260 break;
Jack Carter873c7242013-01-12 01:03:14 +00004261 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004262 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004263 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004264 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004265}
4266
David Blaikie960ea3f2014-06-08 16:18:35 +00004267MipsAsmParser::OperandMatchResultTy
4268MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004269 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004270 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004271 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004272 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004273 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004274 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004275 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004276 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004277
Jack Carterb5cf5902013-04-17 00:18:04 +00004278 if (getLexer().getKind() == AsmToken::LParen) {
4279 Parser.Lex();
4280 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004281 }
4282
Jack Carterb5cf5902013-04-17 00:18:04 +00004283 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004284 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004285 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004286
Jack Carterd0bd6422013-04-18 00:41:53 +00004287 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004288 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004289 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004290 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004291 SMLoc E =
4292 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004293 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004294 return MatchOperand_Success;
4295 }
4296 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004297 SMLoc E =
4298 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004299
Jack Carterd0bd6422013-04-18 00:41:53 +00004300 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004301 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004302 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004303 S, E, *this);
4304 Operands.push_back(
4305 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004306 return MatchOperand_Success;
4307 }
4308 Error(Parser.getTok().getLoc(), "'(' expected");
4309 return MatchOperand_ParseFail;
4310 }
4311
Jack Carterd0bd6422013-04-18 00:41:53 +00004312 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004313 }
4314
Toma Tabacu13964452014-09-04 13:23:44 +00004315 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004316 if (Res != MatchOperand_Success)
4317 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004318
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004319 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004320 Error(Parser.getTok().getLoc(), "')' expected");
4321 return MatchOperand_ParseFail;
4322 }
4323
Jack Carter873c7242013-01-12 01:03:14 +00004324 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4325
Jack Carterd0bd6422013-04-18 00:41:53 +00004326 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004327
Craig Topper062a2ba2014-04-25 05:30:21 +00004328 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004329 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004330
Jack Carterd0bd6422013-04-18 00:41:53 +00004331 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004332 std::unique_ptr<MipsOperand> op(
4333 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004334 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004335 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004336 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004337 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004338 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4339 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004340 if (IdVal->evaluateAsAbsolute(Imm))
4341 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004342 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004343 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004344 getContext());
4345 }
4346
David Blaikie960ea3f2014-06-08 16:18:35 +00004347 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004348 return MatchOperand_Success;
4349}
4350
David Blaikie960ea3f2014-06-08 16:18:35 +00004351bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004352 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004353 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004354 if (Sym) {
4355 SMLoc S = Parser.getTok().getLoc();
4356 const MCExpr *Expr;
4357 if (Sym->isVariable())
4358 Expr = Sym->getVariableValue();
4359 else
4360 return false;
4361 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004362 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004363 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004364 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004365 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004366 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004367 if (ResTy == MatchOperand_Success) {
4368 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004369 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004370 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004371 llvm_unreachable("Should never ParseFail");
4372 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004373 }
4374 } else if (Expr->getKind() == MCExpr::Constant) {
4375 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004376 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004377 Operands.push_back(
4378 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004379 return true;
4380 }
4381 }
4382 return false;
4383}
Jack Carterd0bd6422013-04-18 00:41:53 +00004384
Jack Carter873c7242013-01-12 01:03:14 +00004385MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004386MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004387 StringRef Identifier,
4388 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004389 int Index = matchCPURegisterName(Identifier);
4390 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004391 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004392 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4393 return MatchOperand_Success;
4394 }
4395
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004396 Index = matchHWRegsRegisterName(Identifier);
4397 if (Index != -1) {
4398 Operands.push_back(MipsOperand::createHWRegsReg(
4399 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4400 return MatchOperand_Success;
4401 }
4402
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004403 Index = matchFPURegisterName(Identifier);
4404 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004405 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004406 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4407 return MatchOperand_Success;
4408 }
4409
4410 Index = matchFCCRegisterName(Identifier);
4411 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004412 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004413 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4414 return MatchOperand_Success;
4415 }
4416
4417 Index = matchACRegisterName(Identifier);
4418 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004419 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004420 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4421 return MatchOperand_Success;
4422 }
4423
4424 Index = matchMSA128RegisterName(Identifier);
4425 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004426 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004427 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4428 return MatchOperand_Success;
4429 }
4430
4431 Index = matchMSA128CtrlRegisterName(Identifier);
4432 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004433 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004434 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4435 return MatchOperand_Success;
4436 }
4437
4438 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004439}
4440
4441MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004442MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004443 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004444 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004445
4446 if (Token.is(AsmToken::Identifier)) {
4447 DEBUG(dbgs() << ".. identifier\n");
4448 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004449 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004450 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004451 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004452 } else if (Token.is(AsmToken::Integer)) {
4453 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004454 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004455 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4456 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004457 return MatchOperand_Success;
4458 }
4459
4460 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4461
4462 return MatchOperand_NoMatch;
4463}
4464
David Blaikie960ea3f2014-06-08 16:18:35 +00004465MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004466MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004467 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004468 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004469
4470 auto Token = Parser.getTok();
4471
4472 SMLoc S = Token.getLoc();
4473
4474 if (Token.isNot(AsmToken::Dollar)) {
4475 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4476 if (Token.is(AsmToken::Identifier)) {
4477 if (searchSymbolAlias(Operands))
4478 return MatchOperand_Success;
4479 }
4480 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4481 return MatchOperand_NoMatch;
4482 }
4483 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004484
Toma Tabacu13964452014-09-04 13:23:44 +00004485 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004486 if (ResTy == MatchOperand_Success) {
4487 Parser.Lex(); // $
4488 Parser.Lex(); // identifier
4489 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004490 return ResTy;
4491}
4492
4493MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004494MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004495 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004496 switch (getLexer().getKind()) {
4497 default:
4498 return MatchOperand_NoMatch;
4499 case AsmToken::LParen:
4500 case AsmToken::Minus:
4501 case AsmToken::Plus:
4502 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004503 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004504 case AsmToken::String:
4505 break;
4506 }
4507
4508 const MCExpr *IdVal;
4509 SMLoc S = Parser.getTok().getLoc();
4510 if (getParser().parseExpression(IdVal))
4511 return MatchOperand_ParseFail;
4512
4513 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4514 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4515 return MatchOperand_Success;
4516}
4517
David Blaikie960ea3f2014-06-08 16:18:35 +00004518MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004519MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004520 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004521 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004522
4523 SMLoc S = getLexer().getLoc();
4524
4525 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004526 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004527 if (ResTy != MatchOperand_NoMatch)
4528 return ResTy;
4529
Daniel Sanders315386c2014-04-01 10:40:14 +00004530 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004531 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004532 if (ResTy != MatchOperand_NoMatch)
4533 return ResTy;
4534
Daniel Sandersffd84362014-04-01 10:41:48 +00004535 const MCExpr *Expr = nullptr;
4536 if (Parser.parseExpression(Expr)) {
4537 // We have no way of knowing if a symbol was consumed so we must ParseFail
4538 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004539 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004540 Operands.push_back(
4541 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004542 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004543}
4544
Vladimir Medic2b953d02013-10-01 09:48:56 +00004545MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004546MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004547 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004548 const MCExpr *IdVal;
4549 // If the first token is '$' we may have register operand.
4550 if (Parser.getTok().is(AsmToken::Dollar))
4551 return MatchOperand_NoMatch;
4552 SMLoc S = Parser.getTok().getLoc();
4553 if (getParser().parseExpression(IdVal))
4554 return MatchOperand_ParseFail;
4555 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004556 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004557 int64_t Val = MCE->getValue();
4558 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4559 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004560 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004561 return MatchOperand_Success;
4562}
4563
Matheus Almeida779c5932013-11-18 12:32:49 +00004564MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004565MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004566 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004567 switch (getLexer().getKind()) {
4568 default:
4569 return MatchOperand_NoMatch;
4570 case AsmToken::LParen:
4571 case AsmToken::Plus:
4572 case AsmToken::Minus:
4573 case AsmToken::Integer:
4574 break;
4575 }
4576
4577 const MCExpr *Expr;
4578 SMLoc S = Parser.getTok().getLoc();
4579
4580 if (getParser().parseExpression(Expr))
4581 return MatchOperand_ParseFail;
4582
4583 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004584 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004585 Error(S, "expected immediate value");
4586 return MatchOperand_ParseFail;
4587 }
4588
4589 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4590 // and because the CPU always adds one to the immediate field, the allowed
4591 // range becomes 1..4. We'll only check the range here and will deal
4592 // with the addition/subtraction when actually decoding/encoding
4593 // the instruction.
4594 if (Val < 1 || Val > 4) {
4595 Error(S, "immediate not in range (1..4)");
4596 return MatchOperand_ParseFail;
4597 }
4598
Jack Carter3b2c96e2014-01-22 23:31:38 +00004599 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004600 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004601 return MatchOperand_Success;
4602}
4603
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004604MipsAsmParser::OperandMatchResultTy
4605MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4606 MCAsmParser &Parser = getParser();
4607 SmallVector<unsigned, 10> Regs;
4608 unsigned RegNo;
4609 unsigned PrevReg = Mips::NoRegister;
4610 bool RegRange = false;
4611 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4612
4613 if (Parser.getTok().isNot(AsmToken::Dollar))
4614 return MatchOperand_ParseFail;
4615
4616 SMLoc S = Parser.getTok().getLoc();
4617 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4618 SMLoc E = getLexer().getLoc();
4619 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4620 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4621 if (RegRange) {
4622 // Remove last register operand because registers from register range
4623 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004624 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4625 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004626 Regs.push_back(RegNo);
4627 } else {
4628 unsigned TmpReg = PrevReg + 1;
4629 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004630 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4631 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4632 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004633 Error(E, "invalid register operand");
4634 return MatchOperand_ParseFail;
4635 }
4636
4637 PrevReg = TmpReg;
4638 Regs.push_back(TmpReg++);
4639 }
4640 }
4641
4642 RegRange = false;
4643 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004644 if ((PrevReg == Mips::NoRegister) &&
4645 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4646 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004647 Error(E, "$16 or $31 expected");
4648 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004649 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4650 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4651 !isGP64bit()) ||
4652 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4653 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4654 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004655 Error(E, "invalid register operand");
4656 return MatchOperand_ParseFail;
4657 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004658 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4659 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4660 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004661 Error(E, "consecutive register numbers expected");
4662 return MatchOperand_ParseFail;
4663 }
4664
4665 Regs.push_back(RegNo);
4666 }
4667
4668 if (Parser.getTok().is(AsmToken::Minus))
4669 RegRange = true;
4670
4671 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4672 !Parser.getTok().isNot(AsmToken::Comma)) {
4673 Error(E, "',' or '-' expected");
4674 return MatchOperand_ParseFail;
4675 }
4676
4677 Lex(); // Consume comma or minus
4678 if (Parser.getTok().isNot(AsmToken::Dollar))
4679 break;
4680
4681 PrevReg = RegNo;
4682 }
4683
4684 SMLoc E = Parser.getTok().getLoc();
4685 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4686 parseMemOperand(Operands);
4687 return MatchOperand_Success;
4688}
4689
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004690MipsAsmParser::OperandMatchResultTy
4691MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4692 MCAsmParser &Parser = getParser();
4693
4694 SMLoc S = Parser.getTok().getLoc();
4695 if (parseAnyRegister(Operands) != MatchOperand_Success)
4696 return MatchOperand_ParseFail;
4697
4698 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00004699 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00004700
Benjamin Kramer2b68d152016-05-09 10:31:17 +00004701 Operands.pop_back();
4702 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004703 return MatchOperand_Success;
4704}
4705
Zoran Jovanovic41688672015-02-10 16:36:20 +00004706MipsAsmParser::OperandMatchResultTy
4707MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4708 MCAsmParser &Parser = getParser();
4709 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4710 SmallVector<unsigned, 10> Regs;
4711
4712 if (Parser.getTok().isNot(AsmToken::Dollar))
4713 return MatchOperand_ParseFail;
4714
4715 SMLoc S = Parser.getTok().getLoc();
4716
4717 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4718 return MatchOperand_ParseFail;
4719
4720 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4721 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4722 Regs.push_back(RegNo);
4723
4724 SMLoc E = Parser.getTok().getLoc();
4725 if (Parser.getTok().isNot(AsmToken::Comma)) {
4726 Error(E, "',' expected");
4727 return MatchOperand_ParseFail;
4728 }
4729
4730 // Remove comma.
4731 Parser.Lex();
4732
4733 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4734 return MatchOperand_ParseFail;
4735
4736 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4737 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4738 Regs.push_back(RegNo);
4739
4740 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4741
4742 return MatchOperand_Success;
4743}
4744
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004745/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4746/// either this.
4747/// ::= '(', register, ')'
4748/// handle it before we iterate so we don't get tripped up by the lack of
4749/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004750bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004751 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004752 if (getLexer().is(AsmToken::LParen)) {
4753 Operands.push_back(
4754 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4755 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004756 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004757 SMLoc Loc = getLexer().getLoc();
4758 Parser.eatToEndOfStatement();
4759 return Error(Loc, "unexpected token in argument list");
4760 }
4761 if (Parser.getTok().isNot(AsmToken::RParen)) {
4762 SMLoc Loc = getLexer().getLoc();
4763 Parser.eatToEndOfStatement();
4764 return Error(Loc, "unexpected token, expected ')'");
4765 }
4766 Operands.push_back(
4767 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4768 Parser.Lex();
4769 }
4770 return false;
4771}
4772
4773/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4774/// either one of these.
4775/// ::= '[', register, ']'
4776/// ::= '[', integer, ']'
4777/// handle it before we iterate so we don't get tripped up by the lack of
4778/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004779bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004780 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004781 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004782 if (getLexer().is(AsmToken::LBrac)) {
4783 Operands.push_back(
4784 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4785 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004786 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004787 SMLoc Loc = getLexer().getLoc();
4788 Parser.eatToEndOfStatement();
4789 return Error(Loc, "unexpected token in argument list");
4790 }
4791 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4792 SMLoc Loc = getLexer().getLoc();
4793 Parser.eatToEndOfStatement();
4794 return Error(Loc, "unexpected token, expected ']'");
4795 }
4796 Operands.push_back(
4797 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4798 Parser.Lex();
4799 }
4800 return false;
4801}
4802
David Blaikie960ea3f2014-06-08 16:18:35 +00004803bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4804 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004805 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004806 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004807
4808 // We have reached first instruction, module directive are now forbidden.
4809 getTargetStreamer().forbidModuleDirective();
4810
Vladimir Medic74593e62013-07-17 15:00:42 +00004811 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004812 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004813 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004814 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004815 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004816 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004817 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004818
4819 // Read the remaining operands.
4820 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4821 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004822 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004823 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004824 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004825 return Error(Loc, "unexpected token in argument list");
4826 }
Toma Tabacu13964452014-09-04 13:23:44 +00004827 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004828 return true;
4829 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004830
Jack Carterd0bd6422013-04-18 00:41:53 +00004831 while (getLexer().is(AsmToken::Comma)) {
4832 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004833 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004834 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004835 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004836 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004837 return Error(Loc, "unexpected token in argument list");
4838 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004839 // Parse bracket and parenthesis suffixes before we iterate
4840 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004841 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004842 return true;
4843 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004844 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004845 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004846 }
4847 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004848 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4849 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004850 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004851 return Error(Loc, "unexpected token in argument list");
4852 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004853 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004854 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004855}
4856
Nirav Dave996fc132016-05-05 14:15:46 +00004857// FIXME: Given that these have the same name, these should both be
4858// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004859bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004860 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004861 SMLoc Loc = getLexer().getLoc();
4862 Parser.eatToEndOfStatement();
4863 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004864}
4865
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004866bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004867 return Error(Loc, ErrorMsg);
4868}
4869
Jack Carter0b744b32012-10-04 02:29:46 +00004870bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004871 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004872 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004873
4874 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004875 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004876
4877 Parser.Lex(); // Eat "noat".
4878
Jack Carterd0bd6422013-04-18 00:41:53 +00004879 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004880 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004881 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004882 return false;
4883 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004884
4885 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004886 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004887 return false;
4888}
Jack Carterd0bd6422013-04-18 00:41:53 +00004889
Jack Carter0b744b32012-10-04 02:29:46 +00004890bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004891 // Line can be: ".set at", which sets $at to $1
4892 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004893 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004894 Parser.Lex(); // Eat "at".
4895
Jack Carter0b744b32012-10-04 02:29:46 +00004896 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004897 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004898 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004899
4900 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004901 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004902 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004903 }
4904
4905 if (getLexer().isNot(AsmToken::Equal)) {
4906 reportParseError("unexpected token, expected equals sign");
4907 return false;
4908 }
4909 Parser.Lex(); // Eat "=".
4910
4911 if (getLexer().isNot(AsmToken::Dollar)) {
4912 if (getLexer().is(AsmToken::EndOfStatement)) {
4913 reportParseError("no register specified");
4914 return false;
4915 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004916 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004917 return false;
4918 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004919 }
4920 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004921
Toma Tabacu16a74492015-02-13 10:30:57 +00004922 // Find out what "reg" is.
4923 unsigned AtRegNo;
4924 const AsmToken &Reg = Parser.getTok();
4925 if (Reg.is(AsmToken::Identifier)) {
4926 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4927 } else if (Reg.is(AsmToken::Integer)) {
4928 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004929 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004930 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004931 return false;
4932 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004933
4934 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004935 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004936 reportParseError("invalid register");
4937 return false;
4938 }
4939 Parser.Lex(); // Eat "reg".
4940
4941 // If this is not the end of the statement, report an error.
4942 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4943 reportParseError("unexpected token, expected end of statement");
4944 return false;
4945 }
4946
4947 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4948
4949 Parser.Lex(); // Consume the EndOfStatement.
4950 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004951}
4952
4953bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004954 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004955 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004956 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004957 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004958 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004959 return false;
4960 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004961 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004962 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004963 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004964 return false;
4965}
4966
4967bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004968 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004969 Parser.Lex();
4970 // If this is not the end of the statement, report an error.
4971 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004972 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004973 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004974 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004975 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004976 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004977 Parser.Lex(); // Consume the EndOfStatement.
4978 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004979}
4980
4981bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004982 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004983 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004984 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004985 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004986 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004987 return false;
4988 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004989 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004990 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004991 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004992 return false;
4993}
4994
4995bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004996 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004997 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004998 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004999 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005000 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005001 return false;
5002 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005003 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005004 reportParseError("`noreorder' must be set before `nomacro'");
5005 return false;
5006 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005007 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005008 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005009 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005010 return false;
5011}
Jack Carterd76b2372013-03-21 21:44:16 +00005012
Daniel Sanders44934432014-08-07 12:03:36 +00005013bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005014 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005015 Parser.Lex();
5016
5017 // If this is not the end of the statement, report an error.
5018 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005019 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005020
5021 setFeatureBits(Mips::FeatureMSA, "msa");
5022 getTargetStreamer().emitDirectiveSetMsa();
5023 return false;
5024}
5025
5026bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005027 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005028 Parser.Lex();
5029
5030 // If this is not the end of the statement, report an error.
5031 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005032 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005033
5034 clearFeatureBits(Mips::FeatureMSA, "msa");
5035 getTargetStreamer().emitDirectiveSetNoMsa();
5036 return false;
5037}
5038
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005039bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005040 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005041 Parser.Lex(); // Eat "nodsp".
5042
5043 // If this is not the end of the statement, report an error.
5044 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5045 reportParseError("unexpected token, expected end of statement");
5046 return false;
5047 }
5048
5049 clearFeatureBits(Mips::FeatureDSP, "dsp");
5050 getTargetStreamer().emitDirectiveSetNoDsp();
5051 return false;
5052}
5053
Toma Tabacucc2502d2014-11-04 17:18:07 +00005054bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005055 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005056 Parser.Lex(); // Eat "mips16".
5057
Jack Carter39536722014-01-22 23:08:42 +00005058 // If this is not the end of the statement, report an error.
5059 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005060 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005061 return false;
5062 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005063
5064 setFeatureBits(Mips::FeatureMips16, "mips16");
5065 getTargetStreamer().emitDirectiveSetMips16();
5066 Parser.Lex(); // Consume the EndOfStatement.
5067 return false;
5068}
5069
5070bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005071 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005072 Parser.Lex(); // Eat "nomips16".
5073
5074 // If this is not the end of the statement, report an error.
5075 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5076 reportParseError("unexpected token, expected end of statement");
5077 return false;
5078 }
5079
5080 clearFeatureBits(Mips::FeatureMips16, "mips16");
5081 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005082 Parser.Lex(); // Consume the EndOfStatement.
5083 return false;
5084}
5085
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005086bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005087 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005088 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005089 // Line can be: .set fp=32
5090 // .set fp=xx
5091 // .set fp=64
5092 Parser.Lex(); // Eat fp token
5093 AsmToken Tok = Parser.getTok();
5094 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005095 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005096 return false;
5097 }
5098 Parser.Lex(); // Eat '=' token.
5099 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005100
5101 if (!parseFpABIValue(FpAbiVal, ".set"))
5102 return false;
5103
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005104 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005105 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005106 return false;
5107 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005108 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005109 Parser.Lex(); // Consume the EndOfStatement.
5110 return false;
5111}
5112
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005113bool MipsAsmParser::parseSetOddSPRegDirective() {
5114 MCAsmParser &Parser = getParser();
5115
5116 Parser.Lex(); // Eat "oddspreg".
5117 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5118 reportParseError("unexpected token, expected end of statement");
5119 return false;
5120 }
5121
5122 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5123 getTargetStreamer().emitDirectiveSetOddSPReg();
5124 return false;
5125}
5126
5127bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5128 MCAsmParser &Parser = getParser();
5129
5130 Parser.Lex(); // Eat "nooddspreg".
5131 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5132 reportParseError("unexpected token, expected end of statement");
5133 return false;
5134 }
5135
5136 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5137 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5138 return false;
5139}
5140
Toma Tabacu9db22db2014-09-09 10:15:38 +00005141bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005142 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005143 SMLoc Loc = getLexer().getLoc();
5144
5145 Parser.Lex();
5146 if (getLexer().isNot(AsmToken::EndOfStatement))
5147 return reportParseError("unexpected token, expected end of statement");
5148
5149 // Always keep an element on the options "stack" to prevent the user
5150 // from changing the initial options. This is how we remember them.
5151 if (AssemblerOptions.size() == 2)
5152 return reportParseError(Loc, ".set pop with no .set push");
5153
Akira Hatanakab11ef082015-11-14 06:35:56 +00005154 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005155 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005156 setAvailableFeatures(
5157 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5158 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005159
5160 getTargetStreamer().emitDirectiveSetPop();
5161 return false;
5162}
5163
5164bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005165 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005166 Parser.Lex();
5167 if (getLexer().isNot(AsmToken::EndOfStatement))
5168 return reportParseError("unexpected token, expected end of statement");
5169
5170 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005171 AssemblerOptions.push_back(
5172 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005173
5174 getTargetStreamer().emitDirectiveSetPush();
5175 return false;
5176}
5177
Toma Tabacu29696502015-06-02 09:48:04 +00005178bool MipsAsmParser::parseSetSoftFloatDirective() {
5179 MCAsmParser &Parser = getParser();
5180 Parser.Lex();
5181 if (getLexer().isNot(AsmToken::EndOfStatement))
5182 return reportParseError("unexpected token, expected end of statement");
5183
5184 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5185 getTargetStreamer().emitDirectiveSetSoftFloat();
5186 return false;
5187}
5188
5189bool MipsAsmParser::parseSetHardFloatDirective() {
5190 MCAsmParser &Parser = getParser();
5191 Parser.Lex();
5192 if (getLexer().isNot(AsmToken::EndOfStatement))
5193 return reportParseError("unexpected token, expected end of statement");
5194
5195 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5196 getTargetStreamer().emitDirectiveSetHardFloat();
5197 return false;
5198}
5199
Jack Carterd76b2372013-03-21 21:44:16 +00005200bool MipsAsmParser::parseSetAssignment() {
5201 StringRef Name;
5202 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005203 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005204
5205 if (Parser.parseIdentifier(Name))
5206 reportParseError("expected identifier after .set");
5207
5208 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005209 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005210 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005211
Jack Carter3b2c96e2014-01-22 23:31:38 +00005212 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005213 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005214
Jim Grosbach6f482002015-05-18 18:43:14 +00005215 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005216 Sym->setVariableValue(Value);
5217
5218 return false;
5219}
Jack Carterd0bd6422013-04-18 00:41:53 +00005220
Toma Tabacu26647792014-09-09 12:52:14 +00005221bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005222 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005223 Parser.Lex();
5224 if (getLexer().isNot(AsmToken::EndOfStatement))
5225 return reportParseError("unexpected token, expected end of statement");
5226
5227 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005228 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005229 setAvailableFeatures(
5230 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5231 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005232 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5233
5234 getTargetStreamer().emitDirectiveSetMips0();
5235 return false;
5236}
5237
Toma Tabacu85618b32014-08-19 14:22:52 +00005238bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005239 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005240 Parser.Lex();
5241 if (getLexer().isNot(AsmToken::Equal))
5242 return reportParseError("unexpected token, expected equals sign");
5243
5244 Parser.Lex();
5245 StringRef Arch;
5246 if (Parser.parseIdentifier(Arch))
5247 return reportParseError("expected arch identifier");
5248
5249 StringRef ArchFeatureName =
5250 StringSwitch<StringRef>(Arch)
5251 .Case("mips1", "mips1")
5252 .Case("mips2", "mips2")
5253 .Case("mips3", "mips3")
5254 .Case("mips4", "mips4")
5255 .Case("mips5", "mips5")
5256 .Case("mips32", "mips32")
5257 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005258 .Case("mips32r3", "mips32r3")
5259 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005260 .Case("mips32r6", "mips32r6")
5261 .Case("mips64", "mips64")
5262 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005263 .Case("mips64r3", "mips64r3")
5264 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005265 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005266 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005267 .Case("r4000", "mips3") // This is an implementation of Mips3.
5268 .Default("");
5269
5270 if (ArchFeatureName.empty())
5271 return reportParseError("unsupported architecture");
5272
5273 selectArch(ArchFeatureName);
5274 getTargetStreamer().emitDirectiveSetArch(Arch);
5275 return false;
5276}
5277
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005278bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005279 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005280 Parser.Lex();
5281 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005282 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005283
Matheus Almeida2852af82014-04-22 10:15:54 +00005284 switch (Feature) {
5285 default:
5286 llvm_unreachable("Unimplemented feature");
5287 case Mips::FeatureDSP:
5288 setFeatureBits(Mips::FeatureDSP, "dsp");
5289 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005290 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005291 case Mips::FeatureMicroMips:
5292 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005293 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005294 case Mips::FeatureMips1:
5295 selectArch("mips1");
5296 getTargetStreamer().emitDirectiveSetMips1();
5297 break;
5298 case Mips::FeatureMips2:
5299 selectArch("mips2");
5300 getTargetStreamer().emitDirectiveSetMips2();
5301 break;
5302 case Mips::FeatureMips3:
5303 selectArch("mips3");
5304 getTargetStreamer().emitDirectiveSetMips3();
5305 break;
5306 case Mips::FeatureMips4:
5307 selectArch("mips4");
5308 getTargetStreamer().emitDirectiveSetMips4();
5309 break;
5310 case Mips::FeatureMips5:
5311 selectArch("mips5");
5312 getTargetStreamer().emitDirectiveSetMips5();
5313 break;
5314 case Mips::FeatureMips32:
5315 selectArch("mips32");
5316 getTargetStreamer().emitDirectiveSetMips32();
5317 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005318 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005319 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005320 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005321 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005322 case Mips::FeatureMips32r3:
5323 selectArch("mips32r3");
5324 getTargetStreamer().emitDirectiveSetMips32R3();
5325 break;
5326 case Mips::FeatureMips32r5:
5327 selectArch("mips32r5");
5328 getTargetStreamer().emitDirectiveSetMips32R5();
5329 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005330 case Mips::FeatureMips32r6:
5331 selectArch("mips32r6");
5332 getTargetStreamer().emitDirectiveSetMips32R6();
5333 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005334 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005335 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005336 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005337 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005338 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005339 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005340 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005341 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005342 case Mips::FeatureMips64r3:
5343 selectArch("mips64r3");
5344 getTargetStreamer().emitDirectiveSetMips64R3();
5345 break;
5346 case Mips::FeatureMips64r5:
5347 selectArch("mips64r5");
5348 getTargetStreamer().emitDirectiveSetMips64R5();
5349 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005350 case Mips::FeatureMips64r6:
5351 selectArch("mips64r6");
5352 getTargetStreamer().emitDirectiveSetMips64R6();
5353 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005354 }
5355 return false;
5356}
5357
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005358bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005359 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005360 if (getLexer().isNot(AsmToken::Comma)) {
5361 SMLoc Loc = getLexer().getLoc();
5362 Parser.eatToEndOfStatement();
5363 return Error(Loc, ErrorStr);
5364 }
5365
Matheus Almeida2852af82014-04-22 10:15:54 +00005366 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005367 return true;
5368}
5369
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005370// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5371// In this class, it is only used for .cprestore.
5372// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5373// MipsTargetELFStreamer and MipsAsmParser.
5374bool MipsAsmParser::isPicAndNotNxxAbi() {
5375 return inPicMode() && !(isABI_N32() || isABI_N64());
5376}
5377
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005378bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005379 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005380 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005381
Toma Tabacudde4c462014-11-06 10:02:45 +00005382 if (inMips16Mode()) {
5383 reportParseError(".cpload is not supported in Mips16 mode");
5384 return false;
5385 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005386
David Blaikie960ea3f2014-06-08 16:18:35 +00005387 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005388 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005389 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5390 reportParseError("expected register containing function address");
5391 return false;
5392 }
5393
David Blaikie960ea3f2014-06-08 16:18:35 +00005394 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5395 if (!RegOpnd.isGPRAsmReg()) {
5396 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005397 return false;
5398 }
5399
Toma Tabacudde4c462014-11-06 10:02:45 +00005400 // If this is not the end of the statement, report an error.
5401 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5402 reportParseError("unexpected token, expected end of statement");
5403 return false;
5404 }
5405
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005406 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005407 return false;
5408}
5409
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005410bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5411 MCAsmParser &Parser = getParser();
5412
5413 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5414 // is used in non-PIC mode.
5415
5416 if (inMips16Mode()) {
5417 reportParseError(".cprestore is not supported in Mips16 mode");
5418 return false;
5419 }
5420
5421 // Get the stack offset value.
5422 const MCExpr *StackOffset;
5423 int64_t StackOffsetVal;
5424 if (Parser.parseExpression(StackOffset)) {
5425 reportParseError("expected stack offset value");
5426 return false;
5427 }
5428
5429 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5430 reportParseError("stack offset is not an absolute expression");
5431 return false;
5432 }
5433
5434 if (StackOffsetVal < 0) {
5435 Warning(Loc, ".cprestore with negative stack offset has no effect");
5436 IsCpRestoreSet = false;
5437 } else {
5438 IsCpRestoreSet = true;
5439 CpRestoreOffset = StackOffsetVal;
5440 }
5441
5442 // If this is not the end of the statement, report an error.
5443 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5444 reportParseError("unexpected token, expected end of statement");
5445 return false;
5446 }
5447
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005448 if (!getTargetStreamer().emitDirectiveCpRestore(
5449 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005450 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005451 Parser.Lex(); // Consume the EndOfStatement.
5452 return false;
5453}
5454
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005455bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005456 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005457 unsigned FuncReg;
5458 unsigned Save;
5459 bool SaveIsReg = true;
5460
Matheus Almeida7e815762014-06-18 13:08:59 +00005461 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005462 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005463 if (ResTy == MatchOperand_NoMatch) {
5464 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005465 return false;
5466 }
5467
5468 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5469 if (!FuncRegOpnd.isGPRAsmReg()) {
5470 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5471 Parser.eatToEndOfStatement();
5472 return false;
5473 }
5474
5475 FuncReg = FuncRegOpnd.getGPR32Reg();
5476 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005477
Toma Tabacu65f10572014-09-16 15:00:52 +00005478 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005479 return true;
5480
Toma Tabacu13964452014-09-04 13:23:44 +00005481 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005482 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005483 const MCExpr *OffsetExpr;
5484 int64_t OffsetVal;
5485 SMLoc ExprLoc = getLexer().getLoc();
5486
5487 if (Parser.parseExpression(OffsetExpr) ||
5488 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5489 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005490 Parser.eatToEndOfStatement();
5491 return false;
5492 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005493
5494 Save = OffsetVal;
5495 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005496 } else {
5497 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5498 if (!SaveOpnd.isGPRAsmReg()) {
5499 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5500 Parser.eatToEndOfStatement();
5501 return false;
5502 }
5503 Save = SaveOpnd.getGPR32Reg();
5504 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005505
Toma Tabacu65f10572014-09-16 15:00:52 +00005506 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005507 return true;
5508
Toma Tabacu8874eac2015-02-18 13:46:53 +00005509 const MCExpr *Expr;
5510 if (Parser.parseExpression(Expr)) {
5511 reportParseError("expected expression");
5512 return false;
5513 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005514
Toma Tabacu8874eac2015-02-18 13:46:53 +00005515 if (Expr->getKind() != MCExpr::SymbolRef) {
5516 reportParseError("expected symbol");
5517 return false;
5518 }
5519 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5520
Daniel Sandersf173dda2015-09-22 10:50:09 +00005521 CpSaveLocation = Save;
5522 CpSaveLocationIsRegister = SaveIsReg;
5523
Toma Tabacu8874eac2015-02-18 13:46:53 +00005524 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5525 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005526 return false;
5527}
5528
Daniel Sandersf173dda2015-09-22 10:50:09 +00005529bool MipsAsmParser::parseDirectiveCPReturn() {
5530 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5531 CpSaveLocationIsRegister);
5532 return false;
5533}
5534
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005535bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005536 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005537 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5538 const AsmToken &Tok = Parser.getTok();
5539
5540 if (Tok.getString() == "2008") {
5541 Parser.Lex();
5542 getTargetStreamer().emitDirectiveNaN2008();
5543 return false;
5544 } else if (Tok.getString() == "legacy") {
5545 Parser.Lex();
5546 getTargetStreamer().emitDirectiveNaNLegacy();
5547 return false;
5548 }
5549 }
5550 // If we don't recognize the option passed to the .nan
5551 // directive (e.g. no option or unknown option), emit an error.
5552 reportParseError("invalid option in .nan directive");
5553 return false;
5554}
5555
Jack Carter0b744b32012-10-04 02:29:46 +00005556bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005557 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005558 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005559 const AsmToken &Tok = Parser.getTok();
5560
5561 if (Tok.getString() == "noat") {
5562 return parseSetNoAtDirective();
5563 } else if (Tok.getString() == "at") {
5564 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005565 } else if (Tok.getString() == "arch") {
5566 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005567 } else if (Tok.getString() == "fp") {
5568 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005569 } else if (Tok.getString() == "oddspreg") {
5570 return parseSetOddSPRegDirective();
5571 } else if (Tok.getString() == "nooddspreg") {
5572 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005573 } else if (Tok.getString() == "pop") {
5574 return parseSetPopDirective();
5575 } else if (Tok.getString() == "push") {
5576 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005577 } else if (Tok.getString() == "reorder") {
5578 return parseSetReorderDirective();
5579 } else if (Tok.getString() == "noreorder") {
5580 return parseSetNoReorderDirective();
5581 } else if (Tok.getString() == "macro") {
5582 return parseSetMacroDirective();
5583 } else if (Tok.getString() == "nomacro") {
5584 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005585 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005586 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005587 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005588 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005589 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005590 getTargetStreamer().emitDirectiveSetNoMicroMips();
5591 Parser.eatToEndOfStatement();
5592 return false;
5593 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005594 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005595 } else if (Tok.getString() == "mips0") {
5596 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005597 } else if (Tok.getString() == "mips1") {
5598 return parseSetFeature(Mips::FeatureMips1);
5599 } else if (Tok.getString() == "mips2") {
5600 return parseSetFeature(Mips::FeatureMips2);
5601 } else if (Tok.getString() == "mips3") {
5602 return parseSetFeature(Mips::FeatureMips3);
5603 } else if (Tok.getString() == "mips4") {
5604 return parseSetFeature(Mips::FeatureMips4);
5605 } else if (Tok.getString() == "mips5") {
5606 return parseSetFeature(Mips::FeatureMips5);
5607 } else if (Tok.getString() == "mips32") {
5608 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005609 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005610 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005611 } else if (Tok.getString() == "mips32r3") {
5612 return parseSetFeature(Mips::FeatureMips32r3);
5613 } else if (Tok.getString() == "mips32r5") {
5614 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005615 } else if (Tok.getString() == "mips32r6") {
5616 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005617 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005618 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005619 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005620 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005621 } else if (Tok.getString() == "mips64r3") {
5622 return parseSetFeature(Mips::FeatureMips64r3);
5623 } else if (Tok.getString() == "mips64r5") {
5624 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005625 } else if (Tok.getString() == "mips64r6") {
5626 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005627 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005628 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005629 } else if (Tok.getString() == "nodsp") {
5630 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005631 } else if (Tok.getString() == "msa") {
5632 return parseSetMsaDirective();
5633 } else if (Tok.getString() == "nomsa") {
5634 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005635 } else if (Tok.getString() == "softfloat") {
5636 return parseSetSoftFloatDirective();
5637 } else if (Tok.getString() == "hardfloat") {
5638 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005639 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005640 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005641 parseSetAssignment();
5642 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005643 }
Jack Carter07c818d2013-01-25 01:31:34 +00005644
Jack Carter0b744b32012-10-04 02:29:46 +00005645 return true;
5646}
5647
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005648/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005649/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005650bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005651 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005652 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5653 for (;;) {
5654 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005655 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005656 return true;
5657
5658 getParser().getStreamer().EmitValue(Value, Size);
5659
5660 if (getLexer().is(AsmToken::EndOfStatement))
5661 break;
5662
Jack Carter07c818d2013-01-25 01:31:34 +00005663 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005664 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005665 Parser.Lex();
5666 }
5667 }
5668
5669 Parser.Lex();
5670 return false;
5671}
5672
Vladimir Medic4c299852013-11-06 11:27:05 +00005673/// parseDirectiveGpWord
5674/// ::= .gpword local_sym
5675bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005676 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005677 const MCExpr *Value;
5678 // EmitGPRel32Value requires an expression, so we are using base class
5679 // method to evaluate the expression.
5680 if (getParser().parseExpression(Value))
5681 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005682 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005683
Vladimir Medice10c1122013-11-13 13:18:04 +00005684 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005685 return Error(getLexer().getLoc(),
5686 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005687 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005688 return false;
5689}
5690
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005691/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005692/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005693bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005694 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005695 const MCExpr *Value;
5696 // EmitGPRel64Value requires an expression, so we are using base class
5697 // method to evaluate the expression.
5698 if (getParser().parseExpression(Value))
5699 return true;
5700 getParser().getStreamer().EmitGPRel64Value(Value);
5701
5702 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005703 return Error(getLexer().getLoc(),
5704 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005705 Parser.Lex(); // Eat EndOfStatement token.
5706 return false;
5707}
5708
Jack Carter0cd3c192014-01-06 23:27:31 +00005709bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005710 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005711 // Get the option token.
5712 AsmToken Tok = Parser.getTok();
5713 // At the moment only identifiers are supported.
5714 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005715 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005716 Parser.eatToEndOfStatement();
5717 return false;
5718 }
5719
5720 StringRef Option = Tok.getIdentifier();
5721
5722 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005723 // MipsAsmParser needs to know if the current PIC mode changes.
5724 IsPicEnabled = false;
5725
Jack Carter0cd3c192014-01-06 23:27:31 +00005726 getTargetStreamer().emitDirectiveOptionPic0();
5727 Parser.Lex();
5728 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5729 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005730 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005731 Parser.eatToEndOfStatement();
5732 }
5733 return false;
5734 }
5735
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005736 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005737 // MipsAsmParser needs to know if the current PIC mode changes.
5738 IsPicEnabled = true;
5739
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005740 getTargetStreamer().emitDirectiveOptionPic2();
5741 Parser.Lex();
5742 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5743 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005744 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005745 Parser.eatToEndOfStatement();
5746 }
5747 return false;
5748 }
5749
Jack Carter0cd3c192014-01-06 23:27:31 +00005750 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005751 Warning(Parser.getTok().getLoc(),
5752 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005753 Parser.eatToEndOfStatement();
5754 return false;
5755}
5756
Toma Tabacu9ca50962015-04-16 09:53:47 +00005757/// parseInsnDirective
5758/// ::= .insn
5759bool MipsAsmParser::parseInsnDirective() {
5760 // If this is not the end of the statement, report an error.
5761 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5762 reportParseError("unexpected token, expected end of statement");
5763 return false;
5764 }
5765
5766 // The actual label marking happens in
5767 // MipsELFStreamer::createPendingLabelRelocs().
5768 getTargetStreamer().emitDirectiveInsn();
5769
5770 getParser().Lex(); // Eat EndOfStatement token.
5771 return false;
5772}
5773
Simon Atanasyanbe186202016-02-11 06:45:54 +00005774/// parseSSectionDirective
5775/// ::= .sbss
5776/// ::= .sdata
5777bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5778 // If this is not the end of the statement, report an error.
5779 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5780 reportParseError("unexpected token, expected end of statement");
5781 return false;
5782 }
5783
5784 MCSection *ELFSection = getContext().getELFSection(
5785 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5786 getParser().getStreamer().SwitchSection(ELFSection);
5787
5788 getParser().Lex(); // Eat EndOfStatement token.
5789 return false;
5790}
5791
Daniel Sanders7e527422014-07-10 13:38:23 +00005792/// parseDirectiveModule
5793/// ::= .module oddspreg
5794/// ::= .module nooddspreg
5795/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005796/// ::= .module softfloat
5797/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005798bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005799 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005800 MCAsmLexer &Lexer = getLexer();
5801 SMLoc L = Lexer.getLoc();
5802
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005803 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005804 // TODO : get a better message.
5805 reportParseError(".module directive must appear before any code");
5806 return false;
5807 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005808
Toma Tabacuc405c822015-01-23 10:40:19 +00005809 StringRef Option;
5810 if (Parser.parseIdentifier(Option)) {
5811 reportParseError("expected .module option identifier");
5812 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005813 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005814
Toma Tabacuc405c822015-01-23 10:40:19 +00005815 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005816 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005817
Toma Tabacu3c499582015-06-25 10:56:57 +00005818 // Synchronize the abiflags information with the FeatureBits information we
5819 // changed above.
5820 getTargetStreamer().updateABIInfo(*this);
5821
5822 // If printing assembly, use the recently updated abiflags information.
5823 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5824 // emitted at the end).
5825 getTargetStreamer().emitDirectiveModuleOddSPReg();
5826
Toma Tabacuc405c822015-01-23 10:40:19 +00005827 // If this is not the end of the statement, report an error.
5828 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5829 reportParseError("unexpected token, expected end of statement");
5830 return false;
5831 }
5832
5833 return false; // parseDirectiveModule has finished successfully.
5834 } else if (Option == "nooddspreg") {
5835 if (!isABI_O32()) {
5836 Error(L, "'.module nooddspreg' requires the O32 ABI");
5837 return false;
5838 }
5839
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005840 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005841
Toma Tabacu3c499582015-06-25 10:56:57 +00005842 // Synchronize the abiflags information with the FeatureBits information we
5843 // changed above.
5844 getTargetStreamer().updateABIInfo(*this);
5845
5846 // If printing assembly, use the recently updated abiflags information.
5847 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5848 // emitted at the end).
5849 getTargetStreamer().emitDirectiveModuleOddSPReg();
5850
Toma Tabacuc405c822015-01-23 10:40:19 +00005851 // If this is not the end of the statement, report an error.
5852 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5853 reportParseError("unexpected token, expected end of statement");
5854 return false;
5855 }
5856
5857 return false; // parseDirectiveModule has finished successfully.
5858 } else if (Option == "fp") {
5859 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005860 } else if (Option == "softfloat") {
5861 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5862
5863 // Synchronize the ABI Flags information with the FeatureBits information we
5864 // updated above.
5865 getTargetStreamer().updateABIInfo(*this);
5866
5867 // If printing assembly, use the recently updated ABI Flags information.
5868 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5869 // emitted later).
5870 getTargetStreamer().emitDirectiveModuleSoftFloat();
5871
5872 // If this is not the end of the statement, report an error.
5873 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5874 reportParseError("unexpected token, expected end of statement");
5875 return false;
5876 }
5877
5878 return false; // parseDirectiveModule has finished successfully.
5879 } else if (Option == "hardfloat") {
5880 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5881
5882 // Synchronize the ABI Flags information with the FeatureBits information we
5883 // updated above.
5884 getTargetStreamer().updateABIInfo(*this);
5885
5886 // If printing assembly, use the recently updated ABI Flags information.
5887 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5888 // emitted later).
5889 getTargetStreamer().emitDirectiveModuleHardFloat();
5890
5891 // If this is not the end of the statement, report an error.
5892 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5893 reportParseError("unexpected token, expected end of statement");
5894 return false;
5895 }
5896
5897 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005898 } else {
5899 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5900 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005901}
5902
5903/// parseDirectiveModuleFP
5904/// ::= =32
5905/// ::= =xx
5906/// ::= =64
5907bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005908 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005909 MCAsmLexer &Lexer = getLexer();
5910
5911 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005912 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005913 return false;
5914 }
5915 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005916
Daniel Sanders7e527422014-07-10 13:38:23 +00005917 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005918 if (!parseFpABIValue(FpABI, ".module"))
5919 return false;
5920
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005921 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005922 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005923 return false;
5924 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005925
Toma Tabacua64e5402015-06-25 12:44:38 +00005926 // Synchronize the abiflags information with the FeatureBits information we
5927 // changed above.
5928 getTargetStreamer().updateABIInfo(*this);
5929
5930 // If printing assembly, use the recently updated abiflags information.
5931 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5932 // emitted at the end).
5933 getTargetStreamer().emitDirectiveModuleFP();
5934
Daniel Sanders7e527422014-07-10 13:38:23 +00005935 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005936 return false;
5937}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005938
Daniel Sanders7e527422014-07-10 13:38:23 +00005939bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005940 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005941 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005942 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005943 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005944
5945 if (Lexer.is(AsmToken::Identifier)) {
5946 StringRef Value = Parser.getTok().getString();
5947 Parser.Lex();
5948
5949 if (Value != "xx") {
5950 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5951 return false;
5952 }
5953
5954 if (!isABI_O32()) {
5955 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5956 return false;
5957 }
5958
Daniel Sanders7e527422014-07-10 13:38:23 +00005959 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005960 if (ModuleLevelOptions) {
5961 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5962 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5963 } else {
5964 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5965 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5966 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005967 return true;
5968 }
5969
5970 if (Lexer.is(AsmToken::Integer)) {
5971 unsigned Value = Parser.getTok().getIntVal();
5972 Parser.Lex();
5973
5974 if (Value != 32 && Value != 64) {
5975 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5976 return false;
5977 }
5978
5979 if (Value == 32) {
5980 if (!isABI_O32()) {
5981 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5982 return false;
5983 }
5984
Daniel Sanders7e527422014-07-10 13:38:23 +00005985 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005986 if (ModuleLevelOptions) {
5987 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5988 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5989 } else {
5990 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5991 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5992 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005993 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005994 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005995 if (ModuleLevelOptions) {
5996 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5997 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5998 } else {
5999 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
6000 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6001 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006002 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006003
Daniel Sanders7e527422014-07-10 13:38:23 +00006004 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006005 }
6006
6007 return false;
6008}
6009
Jack Carter0b744b32012-10-04 02:29:46 +00006010bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006011 // This returns false if this function recognizes the directive
6012 // regardless of whether it is successfully handles or reports an
6013 // error. Otherwise it returns true to give the generic parser a
6014 // chance at recognizing it.
6015
Rafael Espindola961d4692014-11-11 05:18:41 +00006016 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006017 StringRef IDVal = DirectiveID.getString();
6018
Nirav Dave996fc132016-05-05 14:15:46 +00006019 if (IDVal == ".cpload") {
6020 parseDirectiveCpLoad(DirectiveID.getLoc());
6021 return false;
6022 }
6023 if (IDVal == ".cprestore") {
6024 parseDirectiveCpRestore(DirectiveID.getLoc());
6025 return false;
6026 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006027 if (IDVal == ".dword") {
6028 parseDataDirective(8, DirectiveID.getLoc());
6029 return false;
6030 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006031 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006032 StringRef SymbolName;
6033
6034 if (Parser.parseIdentifier(SymbolName)) {
6035 reportParseError("expected identifier after .ent");
6036 return false;
6037 }
6038
6039 // There's an undocumented extension that allows an integer to
6040 // follow the name of the procedure which AFAICS is ignored by GAS.
6041 // Example: .ent foo,2
6042 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6043 if (getLexer().isNot(AsmToken::Comma)) {
6044 // Even though we accept this undocumented extension for compatibility
6045 // reasons, the additional integer argument does not actually change
6046 // the behaviour of the '.ent' directive, so we would like to discourage
6047 // its use. We do this by not referring to the extended version in
6048 // error messages which are not directly related to its use.
6049 reportParseError("unexpected token, expected end of statement");
6050 return false;
6051 }
6052 Parser.Lex(); // Eat the comma.
6053 const MCExpr *DummyNumber;
6054 int64_t DummyNumberVal;
6055 // If the user was explicitly trying to use the extended version,
6056 // we still give helpful extension-related error messages.
6057 if (Parser.parseExpression(DummyNumber)) {
6058 reportParseError("expected number after comma");
6059 return false;
6060 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006061 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006062 reportParseError("expected an absolute expression after comma");
6063 return false;
6064 }
6065 }
6066
6067 // If this is not the end of the statement, report an error.
6068 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6069 reportParseError("unexpected token, expected end of statement");
6070 return false;
6071 }
6072
Jim Grosbach6f482002015-05-18 18:43:14 +00006073 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006074
6075 getTargetStreamer().emitDirectiveEnt(*Sym);
6076 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006077 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006078 return false;
6079 }
6080
Jack Carter07c818d2013-01-25 01:31:34 +00006081 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006082 StringRef SymbolName;
6083
6084 if (Parser.parseIdentifier(SymbolName)) {
6085 reportParseError("expected identifier after .end");
6086 return false;
6087 }
6088
6089 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6090 reportParseError("unexpected token, expected end of statement");
6091 return false;
6092 }
6093
6094 if (CurrentFn == nullptr) {
6095 reportParseError(".end used without .ent");
6096 return false;
6097 }
6098
6099 if ((SymbolName != CurrentFn->getName())) {
6100 reportParseError(".end symbol does not match .ent symbol");
6101 return false;
6102 }
6103
6104 getTargetStreamer().emitDirectiveEnd(SymbolName);
6105 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006106 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006107 return false;
6108 }
6109
Jack Carter07c818d2013-01-25 01:31:34 +00006110 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006111 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6112 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006113 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006114 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6115 reportParseError("expected stack register");
6116 return false;
6117 }
6118
6119 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6120 if (!StackRegOpnd.isGPRAsmReg()) {
6121 reportParseError(StackRegOpnd.getStartLoc(),
6122 "expected general purpose register");
6123 return false;
6124 }
6125 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6126
6127 if (Parser.getTok().is(AsmToken::Comma))
6128 Parser.Lex();
6129 else {
6130 reportParseError("unexpected token, expected comma");
6131 return false;
6132 }
6133
6134 // Parse the frame size.
6135 const MCExpr *FrameSize;
6136 int64_t FrameSizeVal;
6137
6138 if (Parser.parseExpression(FrameSize)) {
6139 reportParseError("expected frame size value");
6140 return false;
6141 }
6142
Jim Grosbach13760bd2015-05-30 01:25:56 +00006143 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006144 reportParseError("frame size not an absolute expression");
6145 return false;
6146 }
6147
6148 if (Parser.getTok().is(AsmToken::Comma))
6149 Parser.Lex();
6150 else {
6151 reportParseError("unexpected token, expected comma");
6152 return false;
6153 }
6154
6155 // Parse the return register.
6156 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006157 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006158 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6159 reportParseError("expected return register");
6160 return false;
6161 }
6162
6163 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6164 if (!ReturnRegOpnd.isGPRAsmReg()) {
6165 reportParseError(ReturnRegOpnd.getStartLoc(),
6166 "expected general purpose register");
6167 return false;
6168 }
6169
6170 // If this is not the end of the statement, report an error.
6171 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6172 reportParseError("unexpected token, expected end of statement");
6173 return false;
6174 }
6175
6176 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6177 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006178 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006179 return false;
6180 }
6181
Jack Carter07c818d2013-01-25 01:31:34 +00006182 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006183 parseDirectiveSet();
6184 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006185 }
6186
Daniel Sandersd97a6342014-08-13 10:07:34 +00006187 if (IDVal == ".mask" || IDVal == ".fmask") {
6188 // .mask bitmask, frame_offset
6189 // bitmask: One bit for each register used.
6190 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6191 // first register is expected to be saved.
6192 // Examples:
6193 // .mask 0x80000000, -4
6194 // .fmask 0x80000000, -4
6195 //
Jack Carterbe332172012-09-07 00:48:02 +00006196
Daniel Sandersd97a6342014-08-13 10:07:34 +00006197 // Parse the bitmask
6198 const MCExpr *BitMask;
6199 int64_t BitMaskVal;
6200
6201 if (Parser.parseExpression(BitMask)) {
6202 reportParseError("expected bitmask value");
6203 return false;
6204 }
6205
Jim Grosbach13760bd2015-05-30 01:25:56 +00006206 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006207 reportParseError("bitmask not an absolute expression");
6208 return false;
6209 }
6210
6211 if (Parser.getTok().is(AsmToken::Comma))
6212 Parser.Lex();
6213 else {
6214 reportParseError("unexpected token, expected comma");
6215 return false;
6216 }
6217
6218 // Parse the frame_offset
6219 const MCExpr *FrameOffset;
6220 int64_t FrameOffsetVal;
6221
6222 if (Parser.parseExpression(FrameOffset)) {
6223 reportParseError("expected frame offset value");
6224 return false;
6225 }
6226
Jim Grosbach13760bd2015-05-30 01:25:56 +00006227 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006228 reportParseError("frame offset not an absolute expression");
6229 return false;
6230 }
6231
6232 // If this is not the end of the statement, report an error.
6233 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6234 reportParseError("unexpected token, expected end of statement");
6235 return false;
6236 }
6237
6238 if (IDVal == ".mask")
6239 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6240 else
6241 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006242 return false;
6243 }
6244
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006245 if (IDVal == ".nan")
6246 return parseDirectiveNaN();
6247
Jack Carter07c818d2013-01-25 01:31:34 +00006248 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006249 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006250 return false;
6251 }
6252
Rafael Espindolab59fb732014-03-28 18:50:26 +00006253 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006254 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006255 return false;
6256 }
6257
Jack Carter07c818d2013-01-25 01:31:34 +00006258 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006259 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006260 return false;
6261 }
6262
Scott Egertond1aeb052016-02-15 16:11:51 +00006263 if (IDVal == ".hword") {
6264 parseDataDirective(2, DirectiveID.getLoc());
6265 return false;
6266 }
6267
Nirav Dave996fc132016-05-05 14:15:46 +00006268 if (IDVal == ".option") {
6269 parseDirectiveOption();
6270 return false;
6271 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006272
6273 if (IDVal == ".abicalls") {
6274 getTargetStreamer().emitDirectiveAbiCalls();
6275 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006276 Error(Parser.getTok().getLoc(),
6277 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006278 // Clear line
6279 Parser.eatToEndOfStatement();
6280 }
6281 return false;
6282 }
6283
Nirav Dave996fc132016-05-05 14:15:46 +00006284 if (IDVal == ".cpsetup") {
6285 parseDirectiveCPSetup();
6286 return false;
6287 }
6288 if (IDVal == ".cpreturn") {
6289 parseDirectiveCPReturn();
6290 return false;
6291 }
6292 if (IDVal == ".module") {
6293 parseDirectiveModule();
6294 return false;
6295 }
6296 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6297 parseInternalDirectiveReallowModule();
6298 return false;
6299 }
6300 if (IDVal == ".insn") {
6301 parseInsnDirective();
6302 return false;
6303 }
6304 if (IDVal == ".sbss") {
6305 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6306 return false;
6307 }
6308 if (IDVal == ".sdata") {
6309 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6310 return false;
6311 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006312
Rafael Espindola870c4e92012-01-11 03:56:41 +00006313 return true;
6314}
6315
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006316bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6317 // If this is not the end of the statement, report an error.
6318 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6319 reportParseError("unexpected token, expected end of statement");
6320 return false;
6321 }
6322
6323 getTargetStreamer().reallowModuleDirective();
6324
6325 getParser().Lex(); // Eat EndOfStatement token.
6326 return false;
6327}
6328
Rafael Espindola870c4e92012-01-11 03:56:41 +00006329extern "C" void LLVMInitializeMipsAsmParser() {
6330 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6331 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6332 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6333 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6334}
Jack Carterb4dbc172012-09-05 23:34:03 +00006335
6336#define GET_REGISTER_MATCHER
6337#define GET_MATCHER_IMPLEMENTATION
6338#include "MipsGenAsmMatcher.inc"