blob: 71121fce35d48c380e77f03e0b8acbdffb9bdf9a [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 warnIfNoMacro(IDLoc);
2950
Zoran Jovanovic973405b2016-05-16 08:57:59 +00002951 const MCOperand &RdRegOp = Inst.getOperand(0);
2952 assert(RdRegOp.isReg() && "expected register operand kind");
2953 unsigned RdReg = RdRegOp.getReg();
2954
2955 const MCOperand &RsRegOp = Inst.getOperand(1);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002956 assert(RsRegOp.isReg() && "expected register operand kind");
2957 unsigned RsReg = RsRegOp.getReg();
2958
Zoran Jovanovic973405b2016-05-16 08:57:59 +00002959 const MCOperand &RtRegOp = Inst.getOperand(2);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002960 assert(RtRegOp.isReg() && "expected register operand kind");
2961 unsigned RtReg = RtRegOp.getReg();
2962 unsigned DivOp;
2963 unsigned ZeroReg;
2964
2965 if (IsMips64) {
2966 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2967 ZeroReg = Mips::ZERO_64;
2968 } else {
2969 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2970 ZeroReg = Mips::ZERO;
2971 }
2972
2973 bool UseTraps = useTraps();
2974
2975 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2976 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2977 Warning(IDLoc, "dividing zero by zero");
2978 if (IsMips64) {
2979 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2980 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002981 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002982 return false;
2983 }
2984
Daniel Sandersa736b372016-04-29 13:33:12 +00002985 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002986 return false;
2987 }
2988 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00002989 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002990 return false;
2991 }
2992 }
2993
2994 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2995 Warning(IDLoc, "division by zero");
2996 if (Signed) {
2997 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002998 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002999 return false;
3000 }
3001
Daniel Sandersa736b372016-04-29 13:33:12 +00003002 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003003 return false;
3004 }
3005 }
3006
3007 // FIXME: The values for these two BranchTarget variables may be different in
3008 // micromips. These magic numbers need to be removed.
3009 unsigned BranchTargetNoTraps;
3010 unsigned BranchTarget;
3011
3012 if (UseTraps) {
3013 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00003014 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003015 } else {
3016 BranchTarget = IsMips64 ? 20 : 16;
3017 BranchTargetNoTraps = 8;
3018 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003019 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003020 }
3021
Daniel Sandersa736b372016-04-29 13:33:12 +00003022 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003023
3024 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003025 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003026
3027 if (!Signed) {
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003028 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003029 return false;
3030 }
3031
3032 unsigned ATReg = getATReg(IDLoc);
3033 if (!ATReg)
3034 return true;
3035
Daniel Sandersa736b372016-04-29 13:33:12 +00003036 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003037 if (IsMips64) {
3038 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003039 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3040 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3041 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003042 } else {
3043 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003044 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3045 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003046 }
3047
3048 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003049 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003050 else {
3051 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003052 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3053 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3054 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003055 }
Zoran Jovanovic973405b2016-05-16 08:57:59 +00003056 TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003057 return false;
3058}
3059
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003060bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003061 SMLoc IDLoc, MCStreamer &Out,
3062 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003063 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003064
3065 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3066 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3067 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3068
3069 unsigned FirstReg = Inst.getOperand(0).getReg();
3070 unsigned SecondReg = Inst.getOperand(1).getReg();
3071 unsigned ThirdReg = Inst.getOperand(2).getReg();
3072
3073 if (hasMips1() && !hasMips2()) {
3074 unsigned ATReg = getATReg(IDLoc);
3075 if (!ATReg)
3076 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003077 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3078 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3079 TOut.emitNop(IDLoc, STI);
3080 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3081 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3082 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3083 TOut.emitNop(IDLoc, STI);
3084 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3085 : Mips::CVT_W_S,
3086 FirstReg, SecondReg, IDLoc, STI);
3087 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3088 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003089 return false;
3090 }
3091
Daniel Sandersa736b372016-04-29 13:33:12 +00003092 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3093 : Mips::TRUNC_W_S,
3094 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003095
3096 return false;
3097}
3098
Daniel Sanders6394ee52015-10-15 14:52:58 +00003099bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003100 MCStreamer &Out, const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003101 MipsTargetStreamer &TOut = getTargetStreamer();
3102
Toma Tabacud88d79c2015-06-23 14:39:42 +00003103 if (hasMips32r6() || hasMips64r6()) {
3104 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3105 return false;
3106 }
3107
3108 warnIfNoMacro(IDLoc);
3109
3110 const MCOperand &DstRegOp = Inst.getOperand(0);
3111 assert(DstRegOp.isReg() && "expected register operand kind");
3112
3113 const MCOperand &SrcRegOp = Inst.getOperand(1);
3114 assert(SrcRegOp.isReg() && "expected register operand kind");
3115
3116 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3117 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3118
3119 unsigned DstReg = DstRegOp.getReg();
3120 unsigned SrcReg = SrcRegOp.getReg();
3121 int64_t OffsetValue = OffsetImmOp.getImm();
3122
3123 // NOTE: We always need AT for ULHU, as it is always used as the source
3124 // register for one of the LBu's.
3125 unsigned ATReg = getATReg(IDLoc);
3126 if (!ATReg)
3127 return true;
3128
3129 // When the value of offset+1 does not fit in 16 bits, we have to load the
3130 // offset in AT, (D)ADDu the original source register (if there was one), and
3131 // then use AT as the source register for the 2 generated LBu's.
3132 bool LoadedOffsetInAT = false;
3133 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3134 LoadedOffsetInAT = true;
3135
3136 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003137 true, IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003138 return true;
3139
3140 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3141 // because it will make our output more similar to GAS'. For example,
3142 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3143 // instead of just an "ori $1, $9, 32768".
3144 // NOTE: If there is no source register specified in the ULHU, the parser
3145 // will interpret it as $0.
3146 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003147 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003148 }
3149
3150 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3151 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3152 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3153
3154 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3155 if (isLittle()) {
3156 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3157 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3158 } else {
3159 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3160 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3161 }
3162
3163 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3164
Daniel Sandersa736b372016-04-29 13:33:12 +00003165 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3166 FirstLbuOffset, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003167
Daniel Sandersa736b372016-04-29 13:33:12 +00003168 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3169 STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003170
Daniel Sandersa736b372016-04-29 13:33:12 +00003171 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003172
Daniel Sandersa736b372016-04-29 13:33:12 +00003173 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003174
3175 return false;
3176}
3177
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003178bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3179 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003180 MipsTargetStreamer &TOut = getTargetStreamer();
3181
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003182 if (hasMips32r6() || hasMips64r6()) {
3183 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3184 return false;
3185 }
3186
3187 const MCOperand &DstRegOp = Inst.getOperand(0);
3188 assert(DstRegOp.isReg() && "expected register operand kind");
3189
3190 const MCOperand &SrcRegOp = Inst.getOperand(1);
3191 assert(SrcRegOp.isReg() && "expected register operand kind");
3192
3193 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3194 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3195
3196 unsigned SrcReg = SrcRegOp.getReg();
3197 int64_t OffsetValue = OffsetImmOp.getImm();
3198 unsigned ATReg = 0;
3199
3200 // When the value of offset+3 does not fit in 16 bits, we have to load the
3201 // offset in AT, (D)ADDu the original source register (if there was one), and
3202 // then use AT as the source register for the generated LWL and LWR.
3203 bool LoadedOffsetInAT = false;
3204 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3205 ATReg = getATReg(IDLoc);
3206 if (!ATReg)
3207 return true;
3208 LoadedOffsetInAT = true;
3209
3210 warnIfNoMacro(IDLoc);
3211
3212 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003213 true, IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003214 return true;
3215
3216 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3217 // because it will make our output more similar to GAS'. For example,
3218 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3219 // instead of just an "ori $1, $9, 32768".
3220 // NOTE: If there is no source register specified in the ULW, the parser
3221 // will interpret it as $0.
3222 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003223 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003224 }
3225
3226 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3227 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3228 if (isLittle()) {
3229 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3230 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3231 } else {
3232 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3233 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3234 }
3235
Daniel Sandersa736b372016-04-29 13:33:12 +00003236 TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3237 STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003238
Daniel Sandersa736b372016-04-29 13:33:12 +00003239 TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
3240 IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003241
3242 return false;
3243}
3244
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003245bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003246 MCStreamer &Out,
3247 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003248 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003249
3250 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3251 assert (Inst.getOperand(0).isReg() &&
3252 Inst.getOperand(1).isReg() &&
3253 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3254
3255 unsigned ATReg = Mips::NoRegister;
3256 unsigned FinalDstReg = Mips::NoRegister;
3257 unsigned DstReg = Inst.getOperand(0).getReg();
3258 unsigned SrcReg = Inst.getOperand(1).getReg();
3259 int64_t ImmValue = Inst.getOperand(2).getImm();
3260
3261 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3262
3263 unsigned FinalOpcode = Inst.getOpcode();
3264
3265 if (DstReg == SrcReg) {
3266 ATReg = getATReg(Inst.getLoc());
3267 if (!ATReg)
3268 return true;
3269 FinalDstReg = DstReg;
3270 DstReg = ATReg;
3271 }
3272
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003273 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003274 switch (FinalOpcode) {
3275 default:
3276 llvm_unreachable("unimplemented expansion");
3277 case (Mips::ADDi):
3278 FinalOpcode = Mips::ADD;
3279 break;
3280 case (Mips::ADDiu):
3281 FinalOpcode = Mips::ADDu;
3282 break;
3283 case (Mips::ANDi):
3284 FinalOpcode = Mips::AND;
3285 break;
3286 case (Mips::NORImm):
3287 FinalOpcode = Mips::NOR;
3288 break;
3289 case (Mips::ORi):
3290 FinalOpcode = Mips::OR;
3291 break;
3292 case (Mips::SLTi):
3293 FinalOpcode = Mips::SLT;
3294 break;
3295 case (Mips::SLTiu):
3296 FinalOpcode = Mips::SLTu;
3297 break;
3298 case (Mips::XORi):
3299 FinalOpcode = Mips::XOR;
3300 break;
3301 }
3302
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003303 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003304 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003305 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003306 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003307 return false;
3308 }
3309 return true;
3310}
3311
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003312bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3313 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003314 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003315 unsigned ATReg = Mips::NoRegister;
3316 unsigned DReg = Inst.getOperand(0).getReg();
3317 unsigned SReg = Inst.getOperand(1).getReg();
3318 unsigned TReg = Inst.getOperand(2).getReg();
3319 unsigned TmpReg = DReg;
3320
3321 unsigned FirstShift = Mips::NOP;
3322 unsigned SecondShift = Mips::NOP;
3323
3324 if (hasMips32r2()) {
3325
3326 if (DReg == SReg) {
3327 TmpReg = getATReg(Inst.getLoc());
3328 if (!TmpReg)
3329 return true;
3330 }
3331
3332 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003333 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3334 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003335 return false;
3336 }
3337
3338 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003339 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003340 return false;
3341 }
3342
3343 return true;
3344 }
3345
3346 if (hasMips32()) {
3347
3348 switch (Inst.getOpcode()) {
3349 default:
3350 llvm_unreachable("unexpected instruction opcode");
3351 case Mips::ROL:
3352 FirstShift = Mips::SRLV;
3353 SecondShift = Mips::SLLV;
3354 break;
3355 case Mips::ROR:
3356 FirstShift = Mips::SLLV;
3357 SecondShift = Mips::SRLV;
3358 break;
3359 }
3360
3361 ATReg = getATReg(Inst.getLoc());
3362 if (!ATReg)
3363 return true;
3364
Daniel Sandersa736b372016-04-29 13:33:12 +00003365 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3366 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3367 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3368 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003369
3370 return false;
3371 }
3372
3373 return true;
3374}
3375
3376bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003377 MCStreamer &Out,
3378 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003379 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003380 unsigned ATReg = Mips::NoRegister;
3381 unsigned DReg = Inst.getOperand(0).getReg();
3382 unsigned SReg = Inst.getOperand(1).getReg();
3383 int64_t ImmValue = Inst.getOperand(2).getImm();
3384
3385 unsigned FirstShift = Mips::NOP;
3386 unsigned SecondShift = Mips::NOP;
3387
3388 if (hasMips32r2()) {
3389
3390 if (Inst.getOpcode() == Mips::ROLImm) {
3391 uint64_t MaxShift = 32;
3392 uint64_t ShiftValue = ImmValue;
3393 if (ImmValue != 0)
3394 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003395 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003396 return false;
3397 }
3398
3399 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003400 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003401 return false;
3402 }
3403
3404 return true;
3405 }
3406
3407 if (hasMips32()) {
3408
3409 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003410 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003411 return false;
3412 }
3413
3414 switch (Inst.getOpcode()) {
3415 default:
3416 llvm_unreachable("unexpected instruction opcode");
3417 case Mips::ROLImm:
3418 FirstShift = Mips::SLL;
3419 SecondShift = Mips::SRL;
3420 break;
3421 case Mips::RORImm:
3422 FirstShift = Mips::SRL;
3423 SecondShift = Mips::SLL;
3424 break;
3425 }
3426
3427 ATReg = getATReg(Inst.getLoc());
3428 if (!ATReg)
3429 return true;
3430
Daniel Sandersa736b372016-04-29 13:33:12 +00003431 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3432 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3433 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003434
3435 return false;
3436 }
3437
3438 return true;
3439}
3440
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003441bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3442 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003443 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003444 unsigned ATReg = Mips::NoRegister;
3445 unsigned DReg = Inst.getOperand(0).getReg();
3446 unsigned SReg = Inst.getOperand(1).getReg();
3447 unsigned TReg = Inst.getOperand(2).getReg();
3448 unsigned TmpReg = DReg;
3449
3450 unsigned FirstShift = Mips::NOP;
3451 unsigned SecondShift = Mips::NOP;
3452
3453 if (hasMips64r2()) {
3454
3455 if (TmpReg == SReg) {
3456 TmpReg = getATReg(Inst.getLoc());
3457 if (!TmpReg)
3458 return true;
3459 }
3460
3461 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003462 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3463 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003464 return false;
3465 }
3466
3467 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003468 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003469 return false;
3470 }
3471
3472 return true;
3473 }
3474
3475 if (hasMips64()) {
3476
3477 switch (Inst.getOpcode()) {
3478 default:
3479 llvm_unreachable("unexpected instruction opcode");
3480 case Mips::DROL:
3481 FirstShift = Mips::DSRLV;
3482 SecondShift = Mips::DSLLV;
3483 break;
3484 case Mips::DROR:
3485 FirstShift = Mips::DSLLV;
3486 SecondShift = Mips::DSRLV;
3487 break;
3488 }
3489
3490 ATReg = getATReg(Inst.getLoc());
3491 if (!ATReg)
3492 return true;
3493
Daniel Sandersa736b372016-04-29 13:33:12 +00003494 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3495 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3496 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3497 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003498
3499 return false;
3500 }
3501
3502 return true;
3503}
3504
3505bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003506 MCStreamer &Out,
3507 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003508 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003509 unsigned ATReg = Mips::NoRegister;
3510 unsigned DReg = Inst.getOperand(0).getReg();
3511 unsigned SReg = Inst.getOperand(1).getReg();
3512 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3513
3514 unsigned FirstShift = Mips::NOP;
3515 unsigned SecondShift = Mips::NOP;
3516
3517 MCInst TmpInst;
3518
3519 if (hasMips64r2()) {
3520
3521 unsigned FinalOpcode = Mips::NOP;
3522 if (ImmValue == 0)
3523 FinalOpcode = Mips::DROTR;
3524 else if (ImmValue % 32 == 0)
3525 FinalOpcode = Mips::DROTR32;
3526 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3527 if (Inst.getOpcode() == Mips::DROLImm)
3528 FinalOpcode = Mips::DROTR32;
3529 else
3530 FinalOpcode = Mips::DROTR;
3531 } else if (ImmValue >= 33) {
3532 if (Inst.getOpcode() == Mips::DROLImm)
3533 FinalOpcode = Mips::DROTR;
3534 else
3535 FinalOpcode = Mips::DROTR32;
3536 }
3537
3538 uint64_t ShiftValue = ImmValue % 32;
3539 if (Inst.getOpcode() == Mips::DROLImm)
3540 ShiftValue = (32 - ImmValue % 32) % 32;
3541
Daniel Sandersa736b372016-04-29 13:33:12 +00003542 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003543
3544 return false;
3545 }
3546
3547 if (hasMips64()) {
3548
3549 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003550 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003551 return false;
3552 }
3553
3554 switch (Inst.getOpcode()) {
3555 default:
3556 llvm_unreachable("unexpected instruction opcode");
3557 case Mips::DROLImm:
3558 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3559 FirstShift = Mips::DSLL;
3560 SecondShift = Mips::DSRL32;
3561 }
3562 if (ImmValue == 32) {
3563 FirstShift = Mips::DSLL32;
3564 SecondShift = Mips::DSRL32;
3565 }
3566 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3567 FirstShift = Mips::DSLL32;
3568 SecondShift = Mips::DSRL;
3569 }
3570 break;
3571 case Mips::DRORImm:
3572 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3573 FirstShift = Mips::DSRL;
3574 SecondShift = Mips::DSLL32;
3575 }
3576 if (ImmValue == 32) {
3577 FirstShift = Mips::DSRL32;
3578 SecondShift = Mips::DSLL32;
3579 }
3580 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3581 FirstShift = Mips::DSRL32;
3582 SecondShift = Mips::DSLL;
3583 }
3584 break;
3585 }
3586
3587 ATReg = getATReg(Inst.getLoc());
3588 if (!ATReg)
3589 return true;
3590
Daniel Sandersa736b372016-04-29 13:33:12 +00003591 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3592 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3593 Inst.getLoc(), STI);
3594 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003595
3596 return false;
3597 }
3598
3599 return true;
3600}
3601
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003602bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3603 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003604 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003605 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3606 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3607
Daniel Sandersa736b372016-04-29 13:33:12 +00003608 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003609 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003610 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003611 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003612 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3613 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003614
3615 return false;
3616}
3617
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003618void MipsAsmParser::createCpRestoreMemOp(bool IsLoad, int StackOffset,
3619 SMLoc IDLoc, MCStreamer &Out,
3620 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003621 MipsTargetStreamer &TOut = getTargetStreamer();
3622
Daniel Sanders7225cd52016-04-29 16:16:49 +00003623 if (IsLoad) {
3624 TOut.emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, StackOffset,
3625 Mips::GP, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003626 return;
3627 }
3628
Daniel Sanders241c6792016-05-12 14:01:50 +00003629 TOut.emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, StackOffset,
3630 [&]() { return getATReg(IDLoc); }, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003631}
3632
Matheus Almeida595fcab2014-06-11 15:05:56 +00003633unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3634 // As described by the Mips32r2 spec, the registers Rd and Rs for
3635 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00003636 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Zlatko Buljanba553a62016-05-09 08:07:28 +00003637 // and registers Rd and Base for microMIPS lwp instruction
Matheus Almeida595fcab2014-06-11 15:05:56 +00003638 unsigned Opcode = Inst.getOpcode();
3639
Zlatko Buljanae720db2016-04-22 06:44:34 +00003640 if ((Opcode == Mips::JALR_HB || Opcode == Mips::JALRC_HB_MMR6) &&
Matheus Almeida595fcab2014-06-11 15:05:56 +00003641 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3642 return Match_RequiresDifferentSrcAndDst;
Zlatko Buljanba553a62016-05-09 08:07:28 +00003643 else if ((Opcode == Mips::LWP_MM || Opcode == Mips::LWP_MMR6) &&
3644 (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()))
3645 return Match_RequiresDifferentSrcAndDst;
Matheus Almeida595fcab2014-06-11 15:05:56 +00003646
3647 return Match_Success;
3648}
3649
Daniel Sanders52da7af2015-11-06 12:11:03 +00003650static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3651 uint64_t ErrorInfo) {
3652 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3653 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3654 if (ErrorLoc == SMLoc())
3655 return Loc;
3656 return ErrorLoc;
3657 }
3658 return Loc;
3659}
3660
David Blaikie960ea3f2014-06-08 16:18:35 +00003661bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3662 OperandVector &Operands,
3663 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003664 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003665 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003666
Jack Carterb4dbc172012-09-05 23:34:03 +00003667 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00003668 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003669 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003670
3671 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003672 case Match_Success: {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003673 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00003674 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003675 return false;
3676 }
3677 case Match_MissingFeature:
3678 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3679 return true;
3680 case Match_InvalidOperand: {
3681 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003682 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003683 if (ErrorInfo >= Operands.size())
3684 return Error(IDLoc, "too few operands for instruction");
3685
Daniel Sanders52da7af2015-11-06 12:11:03 +00003686 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003687 if (ErrorLoc == SMLoc())
3688 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003689 }
3690
3691 return Error(ErrorLoc, "invalid operand for instruction");
3692 }
3693 case Match_MnemonicFail:
3694 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003695 case Match_RequiresDifferentSrcAndDst:
3696 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003697 case Match_Immz:
3698 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003699 case Match_UImm1_0:
3700 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3701 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003702 case Match_UImm2_0:
3703 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3704 "expected 2-bit unsigned immediate");
3705 case Match_UImm2_1:
3706 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3707 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003708 case Match_UImm3_0:
3709 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3710 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003711 case Match_UImm4_0:
3712 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3713 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003714 case Match_SImm4_0:
3715 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3716 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003717 case Match_UImm5_0:
3718 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3719 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00003720 case Match_SImm5_0:
3721 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3722 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003723 case Match_UImm5_1:
3724 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3725 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003726 case Match_UImm5_32:
3727 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3728 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003729 case Match_UImm5_33:
3730 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3731 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003732 case Match_UImm5_0_Report_UImm6:
3733 // This is used on UImm5 operands that have a corresponding UImm5_32
3734 // operand to avoid confusing the user.
3735 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3736 "expected 6-bit unsigned immediate");
3737 case Match_UImm5_Lsl2:
3738 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3739 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003740 case Match_UImmRange2_64:
3741 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3742 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003743 case Match_UImm6_0:
3744 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3745 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00003746 case Match_UImm6_Lsl2:
3747 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3748 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00003749 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00003750 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3751 "expected 6-bit signed immediate");
3752 case Match_UImm7_0:
3753 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3754 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00003755 case Match_UImm7_N1:
3756 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3757 "expected immediate in range -1 .. 126");
3758 case Match_SImm7_Lsl2:
3759 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3760 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003761 case Match_UImm8_0:
3762 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3763 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003764 case Match_UImm10_0:
3765 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3766 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00003767 case Match_SImm10_0:
3768 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3769 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00003770 case Match_SImm11_0:
3771 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3772 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003773 case Match_UImm16:
3774 case Match_UImm16_Relaxed:
3775 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3776 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003777 case Match_SImm16:
3778 case Match_SImm16_Relaxed:
3779 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3780 "expected 16-bit signed immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003781 case Match_UImm20_0:
3782 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3783 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00003784 case Match_UImm26_0:
3785 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3786 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00003787 case Match_SImm32:
3788 case Match_SImm32_Relaxed:
3789 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3790 "expected 32-bit signed immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00003791 case Match_MemSImm9:
3792 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3793 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00003794 case Match_MemSImm10:
3795 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3796 "expected memory with 10-bit signed offset");
3797 case Match_MemSImm10Lsl1:
3798 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3799 "expected memory with 11-bit signed offset and multiple of 2");
3800 case Match_MemSImm10Lsl2:
3801 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3802 "expected memory with 12-bit signed offset and multiple of 4");
3803 case Match_MemSImm10Lsl3:
3804 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3805 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00003806 case Match_MemSImm11:
3807 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3808 "expected memory with 11-bit signed offset");
Zlatko Buljanba553a62016-05-09 08:07:28 +00003809 case Match_MemSImm12:
3810 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3811 "expected memory with 12-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003812 case Match_MemSImm16:
3813 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3814 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00003815 }
Craig Topper589ceee2015-01-03 08:16:34 +00003816
3817 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003818}
3819
Toma Tabacud9d344b2015-04-27 14:05:04 +00003820void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3821 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3822 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3823 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003824}
3825
Toma Tabacu81496c12015-05-20 08:54:45 +00003826void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3827 if (!AssemblerOptions.back()->isMacro())
3828 Warning(Loc, "macro instruction expanded into multiple instructions");
3829}
3830
Daniel Sandersef638fe2014-10-03 15:37:37 +00003831void
3832MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3833 SMRange Range, bool ShowColors) {
3834 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003835 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003836 ShowColors);
3837}
3838
Jack Carter1ac53222013-02-20 23:11:17 +00003839int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003840 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003841
Vladimir Medic4c299852013-11-06 11:27:05 +00003842 CC = StringSwitch<unsigned>(Name)
3843 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003844 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003845 .Case("a0", 4)
3846 .Case("a1", 5)
3847 .Case("a2", 6)
3848 .Case("a3", 7)
3849 .Case("v0", 2)
3850 .Case("v1", 3)
3851 .Case("s0", 16)
3852 .Case("s1", 17)
3853 .Case("s2", 18)
3854 .Case("s3", 19)
3855 .Case("s4", 20)
3856 .Case("s5", 21)
3857 .Case("s6", 22)
3858 .Case("s7", 23)
3859 .Case("k0", 26)
3860 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003861 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003862 .Case("sp", 29)
3863 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003864 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003865 .Case("ra", 31)
3866 .Case("t0", 8)
3867 .Case("t1", 9)
3868 .Case("t2", 10)
3869 .Case("t3", 11)
3870 .Case("t4", 12)
3871 .Case("t5", 13)
3872 .Case("t6", 14)
3873 .Case("t7", 15)
3874 .Case("t8", 24)
3875 .Case("t9", 25)
3876 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003877
Toma Tabacufda445c2014-09-15 15:33:01 +00003878 if (!(isABI_N32() || isABI_N64()))
3879 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003880
Daniel Sandersef638fe2014-10-03 15:37:37 +00003881 if (12 <= CC && CC <= 15) {
3882 // Name is one of t4-t7
3883 AsmToken RegTok = getLexer().peekTok();
3884 SMRange RegRange = RegTok.getLocRange();
3885
3886 StringRef FixedName = StringSwitch<StringRef>(Name)
3887 .Case("t4", "t0")
3888 .Case("t5", "t1")
3889 .Case("t6", "t2")
3890 .Case("t7", "t3")
3891 .Default("");
3892 assert(FixedName != "" && "Register name is not one of t4-t7.");
3893
3894 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3895 "Did you mean $" + FixedName + "?", RegRange);
3896 }
3897
Toma Tabacufda445c2014-09-15 15:33:01 +00003898 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3899 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3900 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3901 if (8 <= CC && CC <= 11)
3902 CC += 4;
3903
3904 if (CC == -1)
3905 CC = StringSwitch<unsigned>(Name)
3906 .Case("a4", 8)
3907 .Case("a5", 9)
3908 .Case("a6", 10)
3909 .Case("a7", 11)
3910 .Case("kt0", 26)
3911 .Case("kt1", 27)
3912 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003913
3914 return CC;
3915}
Jack Carterd0bd6422013-04-18 00:41:53 +00003916
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003917int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3918 int CC;
3919
3920 CC = StringSwitch<unsigned>(Name)
3921 .Case("hwr_cpunum", 0)
3922 .Case("hwr_synci_step", 1)
3923 .Case("hwr_cc", 2)
3924 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003925 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003926 .Default(-1);
3927
3928 return CC;
3929}
3930
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003931int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003932
Jack Cartera63b16a2012-09-07 00:23:42 +00003933 if (Name[0] == 'f') {
3934 StringRef NumString = Name.substr(1);
3935 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003936 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003937 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003938 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003939 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003940 return IntVal;
3941 }
3942 return -1;
3943}
Jack Cartera63b16a2012-09-07 00:23:42 +00003944
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003945int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3946
3947 if (Name.startswith("fcc")) {
3948 StringRef NumString = Name.substr(3);
3949 unsigned IntVal;
3950 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003951 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003952 if (IntVal > 7) // There are only 8 fcc registers.
3953 return -1;
3954 return IntVal;
3955 }
3956 return -1;
3957}
3958
3959int MipsAsmParser::matchACRegisterName(StringRef Name) {
3960
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003961 if (Name.startswith("ac")) {
3962 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003963 unsigned IntVal;
3964 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003965 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003966 if (IntVal > 3) // There are only 3 acc registers.
3967 return -1;
3968 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003969 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003970 return -1;
3971}
Jack Carterd0bd6422013-04-18 00:41:53 +00003972
Jack Carter5dc8ac92013-09-25 23:50:44 +00003973int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3974 unsigned IntVal;
3975
3976 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3977 return -1;
3978
3979 if (IntVal > 31)
3980 return -1;
3981
3982 return IntVal;
3983}
3984
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003985int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3986 int CC;
3987
3988 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003989 .Case("msair", 0)
3990 .Case("msacsr", 1)
3991 .Case("msaaccess", 2)
3992 .Case("msasave", 3)
3993 .Case("msamodify", 4)
3994 .Case("msarequest", 5)
3995 .Case("msamap", 6)
3996 .Case("msaunmap", 7)
3997 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003998
3999 return CC;
4000}
4001
Toma Tabacu89a712b2015-04-15 10:48:56 +00004002unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00004003 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00004004 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00004005 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00004006 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00004007 return 0;
4008 }
4009 unsigned AT = getReg(
4010 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00004011 return AT;
4012}
Jack Carter0b744b32012-10-04 02:29:46 +00004013
Jack Carterd0bd6422013-04-18 00:41:53 +00004014unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00004015 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00004016}
4017
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004018unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004019 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00004020 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004021}
4022
Jack Carter873c7242013-01-12 01:03:14 +00004023int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004024 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00004025 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00004026 return -1;
4027
Jack Carter873c7242013-01-12 01:03:14 +00004028 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00004029}
4030
Toma Tabacu13964452014-09-04 13:23:44 +00004031bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004032 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004033 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004034
Jack Carter30a59822012-10-04 04:03:53 +00004035 // Check if the current operand has a custom associated parser, if so, try to
4036 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004037 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4038 if (ResTy == MatchOperand_Success)
4039 return false;
4040 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4041 // there was a match, but an error occurred, in which case, just return that
4042 // the operand parsing failed.
4043 if (ResTy == MatchOperand_ParseFail)
4044 return true;
4045
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004046 DEBUG(dbgs() << ".. Generic Parser\n");
4047
Jack Carterb4dbc172012-09-05 23:34:03 +00004048 switch (getLexer().getKind()) {
4049 default:
4050 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4051 return true;
4052 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004053 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004054 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004055
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004056 // Almost all registers have been parsed by custom parsers. There is only
4057 // one exception to this. $zero (and it's alias $0) will reach this point
4058 // for div, divu, and similar instructions because it is not an operand
4059 // to the instruction definition but an explicit register. Special case
4060 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004061 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004062 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004063
Jack Carterd0bd6422013-04-18 00:41:53 +00004064 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004065 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004066 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004067 return true;
4068
Jack Carter873c7242013-01-12 01:03:14 +00004069 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004070 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004071 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004072 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004073 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004074
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004075 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004076 return false;
4077 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004078 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004079 case AsmToken::LParen:
4080 case AsmToken::Minus:
4081 case AsmToken::Plus:
4082 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004083 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004084 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004085 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004086 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004087 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004088 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004089 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004090 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004091 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004092 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004093 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004094 return true;
4095
Jack Carter873c7242013-01-12 01:03:14 +00004096 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4097
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004098 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004099 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004100 } // case AsmToken::Percent
4101 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004102 return true;
4103}
4104
Vladimir Medic4c299852013-11-06 11:27:05 +00004105const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004106 StringRef RelocStr) {
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004107 if (RelocStr == "hi(%neg(%gp_rel")
4108 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext());
4109 else if (RelocStr == "lo(%neg(%gp_rel")
4110 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004111
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004112 MipsMCExpr::MipsExprKind Kind =
4113 StringSwitch<MipsMCExpr::MipsExprKind>(RelocStr)
4114 .Case("call16", MipsMCExpr::MEK_GOT_CALL)
4115 .Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
4116 .Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
4117 .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
4118 .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
4119 .Case("got", MipsMCExpr::MEK_GOT)
4120 .Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
4121 .Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
4122 .Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
4123 .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
4124 .Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
4125 .Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
4126 .Case("gp_rel", MipsMCExpr::MEK_GPREL)
4127 .Case("hi", MipsMCExpr::MEK_HI)
4128 .Case("higher", MipsMCExpr::MEK_HIGHER)
4129 .Case("highest", MipsMCExpr::MEK_HIGHEST)
4130 .Case("lo", MipsMCExpr::MEK_LO)
4131 .Case("neg", MipsMCExpr::MEK_NEG)
4132 .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
4133 .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
4134 .Case("tlsgd", MipsMCExpr::MEK_TLSGD)
4135 .Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
4136 .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
4137 .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
4138 .Default(MipsMCExpr::MEK_None);
Jack Carterb5cf5902013-04-17 00:18:04 +00004139
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004140 assert(Kind != MipsMCExpr::MEK_None);
4141 return MipsMCExpr::create(Kind, Expr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004142}
4143
4144bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4145
4146 switch (Expr->getKind()) {
4147 case MCExpr::Constant:
4148 return true;
4149 case MCExpr::SymbolRef:
4150 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4151 case MCExpr::Binary:
4152 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4153 if (!isEvaluated(BE->getLHS()))
4154 return false;
4155 return isEvaluated(BE->getRHS());
4156 }
4157 case MCExpr::Unary:
4158 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004159 case MCExpr::Target:
4160 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004161 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004162 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004163}
Jack Carterd0bd6422013-04-18 00:41:53 +00004164
Jack Carterb5cf5902013-04-17 00:18:04 +00004165bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004166 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004167 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004168 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004169 if (Tok.isNot(AsmToken::Identifier))
4170 return true;
4171
Yaron Keren075759a2015-03-30 15:42:36 +00004172 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004173
Jack Carterd0bd6422013-04-18 00:41:53 +00004174 Parser.Lex(); // Eat the identifier.
4175 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004176 const MCExpr *IdVal;
4177 SMLoc EndLoc;
4178
4179 if (getLexer().getKind() == AsmToken::LParen) {
4180 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004181 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004182 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004183 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004184 const AsmToken &nextTok = Parser.getTok();
4185 if (nextTok.isNot(AsmToken::Identifier))
4186 return true;
4187 Str += "(%";
4188 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004189 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004190 if (getLexer().getKind() != AsmToken::LParen)
4191 return true;
4192 } else
4193 break;
4194 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004195 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004196 return true;
4197
4198 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004199 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004200
4201 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004202 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004203
Jack Carterd0bd6422013-04-18 00:41:53 +00004204 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004205 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004206}
4207
Jack Carterb4dbc172012-09-05 23:34:03 +00004208bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4209 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004210 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004211 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004212 if (ResTy == MatchOperand_Success) {
4213 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004214 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004215 StartLoc = Operand.getStartLoc();
4216 EndLoc = Operand.getEndLoc();
4217
4218 // AFAIK, we only support numeric registers and named GPR's in CFI
4219 // directives.
4220 // Don't worry about eating tokens before failing. Using an unrecognised
4221 // register is a parse error.
4222 if (Operand.isGPRAsmReg()) {
4223 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004224 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004225 }
4226
4227 return (RegNo == (unsigned)-1);
4228 }
4229
4230 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004231 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004232}
4233
Jack Carterb5cf5902013-04-17 00:18:04 +00004234bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004235 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004236 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004237 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004238 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004239
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004240 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004241 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004242 ++NumOfLParen;
4243 }
Jack Carter873c7242013-01-12 01:03:14 +00004244
Jack Carterd0bd6422013-04-18 00:41:53 +00004245 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004246 default:
4247 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004248 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004249 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004250 case AsmToken::Integer:
4251 case AsmToken::Minus:
4252 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004253 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004254 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004255 else
4256 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004257 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004258 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004259 break;
Jack Carter873c7242013-01-12 01:03:14 +00004260 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004261 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004262 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004263 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004264}
4265
David Blaikie960ea3f2014-06-08 16:18:35 +00004266MipsAsmParser::OperandMatchResultTy
4267MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004268 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004269 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004270 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004271 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004272 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004273 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004274 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004275 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004276
Jack Carterb5cf5902013-04-17 00:18:04 +00004277 if (getLexer().getKind() == AsmToken::LParen) {
4278 Parser.Lex();
4279 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004280 }
4281
Jack Carterb5cf5902013-04-17 00:18:04 +00004282 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004283 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004284 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004285
Jack Carterd0bd6422013-04-18 00:41:53 +00004286 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004287 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004288 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004289 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004290 SMLoc E =
4291 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004292 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004293 return MatchOperand_Success;
4294 }
4295 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004296 SMLoc E =
4297 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004298
Jack Carterd0bd6422013-04-18 00:41:53 +00004299 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004300 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004301 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004302 S, E, *this);
4303 Operands.push_back(
4304 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004305 return MatchOperand_Success;
4306 }
4307 Error(Parser.getTok().getLoc(), "'(' expected");
4308 return MatchOperand_ParseFail;
4309 }
4310
Jack Carterd0bd6422013-04-18 00:41:53 +00004311 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004312 }
4313
Toma Tabacu13964452014-09-04 13:23:44 +00004314 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004315 if (Res != MatchOperand_Success)
4316 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004317
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004318 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004319 Error(Parser.getTok().getLoc(), "')' expected");
4320 return MatchOperand_ParseFail;
4321 }
4322
Jack Carter873c7242013-01-12 01:03:14 +00004323 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4324
Jack Carterd0bd6422013-04-18 00:41:53 +00004325 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004326
Craig Topper062a2ba2014-04-25 05:30:21 +00004327 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004328 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004329
Jack Carterd0bd6422013-04-18 00:41:53 +00004330 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004331 std::unique_ptr<MipsOperand> op(
4332 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004333 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004334 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004335 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004336 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004337 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4338 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004339 if (IdVal->evaluateAsAbsolute(Imm))
4340 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004341 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004342 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004343 getContext());
4344 }
4345
David Blaikie960ea3f2014-06-08 16:18:35 +00004346 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004347 return MatchOperand_Success;
4348}
4349
David Blaikie960ea3f2014-06-08 16:18:35 +00004350bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004351 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004352 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004353 if (Sym) {
4354 SMLoc S = Parser.getTok().getLoc();
4355 const MCExpr *Expr;
4356 if (Sym->isVariable())
4357 Expr = Sym->getVariableValue();
4358 else
4359 return false;
4360 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004361 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004362 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004363 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004364 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004365 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004366 if (ResTy == MatchOperand_Success) {
4367 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004368 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004369 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004370 llvm_unreachable("Should never ParseFail");
4371 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004372 }
4373 } else if (Expr->getKind() == MCExpr::Constant) {
4374 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004375 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004376 Operands.push_back(
4377 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004378 return true;
4379 }
4380 }
4381 return false;
4382}
Jack Carterd0bd6422013-04-18 00:41:53 +00004383
Jack Carter873c7242013-01-12 01:03:14 +00004384MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004385MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004386 StringRef Identifier,
4387 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004388 int Index = matchCPURegisterName(Identifier);
4389 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004390 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004391 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4392 return MatchOperand_Success;
4393 }
4394
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004395 Index = matchHWRegsRegisterName(Identifier);
4396 if (Index != -1) {
4397 Operands.push_back(MipsOperand::createHWRegsReg(
4398 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4399 return MatchOperand_Success;
4400 }
4401
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004402 Index = matchFPURegisterName(Identifier);
4403 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004404 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004405 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4406 return MatchOperand_Success;
4407 }
4408
4409 Index = matchFCCRegisterName(Identifier);
4410 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004411 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004412 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4413 return MatchOperand_Success;
4414 }
4415
4416 Index = matchACRegisterName(Identifier);
4417 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004418 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004419 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4420 return MatchOperand_Success;
4421 }
4422
4423 Index = matchMSA128RegisterName(Identifier);
4424 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004425 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004426 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4427 return MatchOperand_Success;
4428 }
4429
4430 Index = matchMSA128CtrlRegisterName(Identifier);
4431 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004432 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004433 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4434 return MatchOperand_Success;
4435 }
4436
4437 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004438}
4439
4440MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004441MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004442 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004443 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004444
4445 if (Token.is(AsmToken::Identifier)) {
4446 DEBUG(dbgs() << ".. identifier\n");
4447 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004448 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004449 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004450 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004451 } else if (Token.is(AsmToken::Integer)) {
4452 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004453 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004454 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4455 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004456 return MatchOperand_Success;
4457 }
4458
4459 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4460
4461 return MatchOperand_NoMatch;
4462}
4463
David Blaikie960ea3f2014-06-08 16:18:35 +00004464MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004465MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004466 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004467 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004468
4469 auto Token = Parser.getTok();
4470
4471 SMLoc S = Token.getLoc();
4472
4473 if (Token.isNot(AsmToken::Dollar)) {
4474 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4475 if (Token.is(AsmToken::Identifier)) {
4476 if (searchSymbolAlias(Operands))
4477 return MatchOperand_Success;
4478 }
4479 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4480 return MatchOperand_NoMatch;
4481 }
4482 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004483
Toma Tabacu13964452014-09-04 13:23:44 +00004484 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004485 if (ResTy == MatchOperand_Success) {
4486 Parser.Lex(); // $
4487 Parser.Lex(); // identifier
4488 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004489 return ResTy;
4490}
4491
4492MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004493MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004494 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004495 switch (getLexer().getKind()) {
4496 default:
4497 return MatchOperand_NoMatch;
4498 case AsmToken::LParen:
4499 case AsmToken::Minus:
4500 case AsmToken::Plus:
4501 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004502 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004503 case AsmToken::String:
4504 break;
4505 }
4506
4507 const MCExpr *IdVal;
4508 SMLoc S = Parser.getTok().getLoc();
4509 if (getParser().parseExpression(IdVal))
4510 return MatchOperand_ParseFail;
4511
4512 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4513 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4514 return MatchOperand_Success;
4515}
4516
David Blaikie960ea3f2014-06-08 16:18:35 +00004517MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004518MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004519 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004520 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004521
4522 SMLoc S = getLexer().getLoc();
4523
4524 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004525 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004526 if (ResTy != MatchOperand_NoMatch)
4527 return ResTy;
4528
Daniel Sanders315386c2014-04-01 10:40:14 +00004529 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004530 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004531 if (ResTy != MatchOperand_NoMatch)
4532 return ResTy;
4533
Daniel Sandersffd84362014-04-01 10:41:48 +00004534 const MCExpr *Expr = nullptr;
4535 if (Parser.parseExpression(Expr)) {
4536 // We have no way of knowing if a symbol was consumed so we must ParseFail
4537 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004538 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004539 Operands.push_back(
4540 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004541 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004542}
4543
Vladimir Medic2b953d02013-10-01 09:48:56 +00004544MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004545MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004546 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004547 const MCExpr *IdVal;
4548 // If the first token is '$' we may have register operand.
4549 if (Parser.getTok().is(AsmToken::Dollar))
4550 return MatchOperand_NoMatch;
4551 SMLoc S = Parser.getTok().getLoc();
4552 if (getParser().parseExpression(IdVal))
4553 return MatchOperand_ParseFail;
4554 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004555 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004556 int64_t Val = MCE->getValue();
4557 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4558 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004559 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004560 return MatchOperand_Success;
4561}
4562
Matheus Almeida779c5932013-11-18 12:32:49 +00004563MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004564MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004565 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004566 switch (getLexer().getKind()) {
4567 default:
4568 return MatchOperand_NoMatch;
4569 case AsmToken::LParen:
4570 case AsmToken::Plus:
4571 case AsmToken::Minus:
4572 case AsmToken::Integer:
4573 break;
4574 }
4575
4576 const MCExpr *Expr;
4577 SMLoc S = Parser.getTok().getLoc();
4578
4579 if (getParser().parseExpression(Expr))
4580 return MatchOperand_ParseFail;
4581
4582 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004583 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004584 Error(S, "expected immediate value");
4585 return MatchOperand_ParseFail;
4586 }
4587
4588 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4589 // and because the CPU always adds one to the immediate field, the allowed
4590 // range becomes 1..4. We'll only check the range here and will deal
4591 // with the addition/subtraction when actually decoding/encoding
4592 // the instruction.
4593 if (Val < 1 || Val > 4) {
4594 Error(S, "immediate not in range (1..4)");
4595 return MatchOperand_ParseFail;
4596 }
4597
Jack Carter3b2c96e2014-01-22 23:31:38 +00004598 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004599 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004600 return MatchOperand_Success;
4601}
4602
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004603MipsAsmParser::OperandMatchResultTy
4604MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4605 MCAsmParser &Parser = getParser();
4606 SmallVector<unsigned, 10> Regs;
4607 unsigned RegNo;
4608 unsigned PrevReg = Mips::NoRegister;
4609 bool RegRange = false;
4610 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4611
4612 if (Parser.getTok().isNot(AsmToken::Dollar))
4613 return MatchOperand_ParseFail;
4614
4615 SMLoc S = Parser.getTok().getLoc();
4616 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4617 SMLoc E = getLexer().getLoc();
4618 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4619 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4620 if (RegRange) {
4621 // Remove last register operand because registers from register range
4622 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004623 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4624 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004625 Regs.push_back(RegNo);
4626 } else {
4627 unsigned TmpReg = PrevReg + 1;
4628 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004629 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4630 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4631 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004632 Error(E, "invalid register operand");
4633 return MatchOperand_ParseFail;
4634 }
4635
4636 PrevReg = TmpReg;
4637 Regs.push_back(TmpReg++);
4638 }
4639 }
4640
4641 RegRange = false;
4642 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004643 if ((PrevReg == Mips::NoRegister) &&
4644 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4645 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004646 Error(E, "$16 or $31 expected");
4647 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004648 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4649 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4650 !isGP64bit()) ||
4651 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4652 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4653 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004654 Error(E, "invalid register operand");
4655 return MatchOperand_ParseFail;
4656 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004657 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4658 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4659 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004660 Error(E, "consecutive register numbers expected");
4661 return MatchOperand_ParseFail;
4662 }
4663
4664 Regs.push_back(RegNo);
4665 }
4666
4667 if (Parser.getTok().is(AsmToken::Minus))
4668 RegRange = true;
4669
4670 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4671 !Parser.getTok().isNot(AsmToken::Comma)) {
4672 Error(E, "',' or '-' expected");
4673 return MatchOperand_ParseFail;
4674 }
4675
4676 Lex(); // Consume comma or minus
4677 if (Parser.getTok().isNot(AsmToken::Dollar))
4678 break;
4679
4680 PrevReg = RegNo;
4681 }
4682
4683 SMLoc E = Parser.getTok().getLoc();
4684 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4685 parseMemOperand(Operands);
4686 return MatchOperand_Success;
4687}
4688
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004689MipsAsmParser::OperandMatchResultTy
4690MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4691 MCAsmParser &Parser = getParser();
4692
4693 SMLoc S = Parser.getTok().getLoc();
4694 if (parseAnyRegister(Operands) != MatchOperand_Success)
4695 return MatchOperand_ParseFail;
4696
4697 SMLoc E = Parser.getTok().getLoc();
Daniel Sandersd044e492016-05-09 13:10:57 +00004698 MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
Zlatko Buljanba553a62016-05-09 08:07:28 +00004699
Benjamin Kramer2b68d152016-05-09 10:31:17 +00004700 Operands.pop_back();
4701 Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004702 return MatchOperand_Success;
4703}
4704
Zoran Jovanovic41688672015-02-10 16:36:20 +00004705MipsAsmParser::OperandMatchResultTy
4706MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4707 MCAsmParser &Parser = getParser();
4708 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4709 SmallVector<unsigned, 10> Regs;
4710
4711 if (Parser.getTok().isNot(AsmToken::Dollar))
4712 return MatchOperand_ParseFail;
4713
4714 SMLoc S = Parser.getTok().getLoc();
4715
4716 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4717 return MatchOperand_ParseFail;
4718
4719 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4720 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4721 Regs.push_back(RegNo);
4722
4723 SMLoc E = Parser.getTok().getLoc();
4724 if (Parser.getTok().isNot(AsmToken::Comma)) {
4725 Error(E, "',' expected");
4726 return MatchOperand_ParseFail;
4727 }
4728
4729 // Remove comma.
4730 Parser.Lex();
4731
4732 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4733 return MatchOperand_ParseFail;
4734
4735 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4736 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4737 Regs.push_back(RegNo);
4738
4739 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4740
4741 return MatchOperand_Success;
4742}
4743
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004744/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4745/// either this.
4746/// ::= '(', register, ')'
4747/// handle it before we iterate so we don't get tripped up by the lack of
4748/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004749bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004750 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004751 if (getLexer().is(AsmToken::LParen)) {
4752 Operands.push_back(
4753 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4754 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004755 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004756 SMLoc Loc = getLexer().getLoc();
4757 Parser.eatToEndOfStatement();
4758 return Error(Loc, "unexpected token in argument list");
4759 }
4760 if (Parser.getTok().isNot(AsmToken::RParen)) {
4761 SMLoc Loc = getLexer().getLoc();
4762 Parser.eatToEndOfStatement();
4763 return Error(Loc, "unexpected token, expected ')'");
4764 }
4765 Operands.push_back(
4766 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4767 Parser.Lex();
4768 }
4769 return false;
4770}
4771
4772/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4773/// either one of these.
4774/// ::= '[', register, ']'
4775/// ::= '[', integer, ']'
4776/// handle it before we iterate so we don't get tripped up by the lack of
4777/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004778bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004779 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004780 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004781 if (getLexer().is(AsmToken::LBrac)) {
4782 Operands.push_back(
4783 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4784 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004785 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004786 SMLoc Loc = getLexer().getLoc();
4787 Parser.eatToEndOfStatement();
4788 return Error(Loc, "unexpected token in argument list");
4789 }
4790 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4791 SMLoc Loc = getLexer().getLoc();
4792 Parser.eatToEndOfStatement();
4793 return Error(Loc, "unexpected token, expected ']'");
4794 }
4795 Operands.push_back(
4796 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4797 Parser.Lex();
4798 }
4799 return false;
4800}
4801
David Blaikie960ea3f2014-06-08 16:18:35 +00004802bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4803 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004804 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004805 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004806
4807 // We have reached first instruction, module directive are now forbidden.
4808 getTargetStreamer().forbidModuleDirective();
4809
Vladimir Medic74593e62013-07-17 15:00:42 +00004810 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004811 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004812 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004813 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004814 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004815 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004816 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004817
4818 // Read the remaining operands.
4819 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4820 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004821 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004822 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004823 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004824 return Error(Loc, "unexpected token in argument list");
4825 }
Toma Tabacu13964452014-09-04 13:23:44 +00004826 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004827 return true;
4828 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004829
Jack Carterd0bd6422013-04-18 00:41:53 +00004830 while (getLexer().is(AsmToken::Comma)) {
4831 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004832 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004833 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004834 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004835 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004836 return Error(Loc, "unexpected token in argument list");
4837 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004838 // Parse bracket and parenthesis suffixes before we iterate
4839 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004840 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004841 return true;
4842 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004843 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004844 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004845 }
4846 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004847 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4848 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004849 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004850 return Error(Loc, "unexpected token in argument list");
4851 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004852 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004853 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004854}
4855
Nirav Dave996fc132016-05-05 14:15:46 +00004856// FIXME: Given that these have the same name, these should both be
4857// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004858bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004859 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004860 SMLoc Loc = getLexer().getLoc();
4861 Parser.eatToEndOfStatement();
4862 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004863}
4864
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004865bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004866 return Error(Loc, ErrorMsg);
4867}
4868
Jack Carter0b744b32012-10-04 02:29:46 +00004869bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004870 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004871 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004872
4873 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004874 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004875
4876 Parser.Lex(); // Eat "noat".
4877
Jack Carterd0bd6422013-04-18 00:41:53 +00004878 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004879 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004880 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004881 return false;
4882 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004883
4884 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004885 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004886 return false;
4887}
Jack Carterd0bd6422013-04-18 00:41:53 +00004888
Jack Carter0b744b32012-10-04 02:29:46 +00004889bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004890 // Line can be: ".set at", which sets $at to $1
4891 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004892 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004893 Parser.Lex(); // Eat "at".
4894
Jack Carter0b744b32012-10-04 02:29:46 +00004895 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004896 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004897 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004898
4899 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004900 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004901 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004902 }
4903
4904 if (getLexer().isNot(AsmToken::Equal)) {
4905 reportParseError("unexpected token, expected equals sign");
4906 return false;
4907 }
4908 Parser.Lex(); // Eat "=".
4909
4910 if (getLexer().isNot(AsmToken::Dollar)) {
4911 if (getLexer().is(AsmToken::EndOfStatement)) {
4912 reportParseError("no register specified");
4913 return false;
4914 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004915 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004916 return false;
4917 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004918 }
4919 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004920
Toma Tabacu16a74492015-02-13 10:30:57 +00004921 // Find out what "reg" is.
4922 unsigned AtRegNo;
4923 const AsmToken &Reg = Parser.getTok();
4924 if (Reg.is(AsmToken::Identifier)) {
4925 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4926 } else if (Reg.is(AsmToken::Integer)) {
4927 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004928 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004929 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004930 return false;
4931 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004932
4933 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004934 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004935 reportParseError("invalid register");
4936 return false;
4937 }
4938 Parser.Lex(); // Eat "reg".
4939
4940 // If this is not the end of the statement, report an error.
4941 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4942 reportParseError("unexpected token, expected end of statement");
4943 return false;
4944 }
4945
4946 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4947
4948 Parser.Lex(); // Consume the EndOfStatement.
4949 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004950}
4951
4952bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004953 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004954 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004955 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004956 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004957 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004958 return false;
4959 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004960 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004961 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004962 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004963 return false;
4964}
4965
4966bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004967 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004968 Parser.Lex();
4969 // If this is not the end of the statement, report an error.
4970 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004971 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004972 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004973 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004974 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004975 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004976 Parser.Lex(); // Consume the EndOfStatement.
4977 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004978}
4979
4980bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004981 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004982 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004983 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004984 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004985 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004986 return false;
4987 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004988 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004989 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004990 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004991 return false;
4992}
4993
4994bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004995 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004996 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004997 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004998 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004999 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00005000 return false;
5001 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005002 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00005003 reportParseError("`noreorder' must be set before `nomacro'");
5004 return false;
5005 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00005006 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00005007 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00005008 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00005009 return false;
5010}
Jack Carterd76b2372013-03-21 21:44:16 +00005011
Daniel Sanders44934432014-08-07 12:03:36 +00005012bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005013 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005014 Parser.Lex();
5015
5016 // If this is not the end of the statement, report an error.
5017 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005018 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005019
5020 setFeatureBits(Mips::FeatureMSA, "msa");
5021 getTargetStreamer().emitDirectiveSetMsa();
5022 return false;
5023}
5024
5025bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005026 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005027 Parser.Lex();
5028
5029 // If this is not the end of the statement, report an error.
5030 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005031 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005032
5033 clearFeatureBits(Mips::FeatureMSA, "msa");
5034 getTargetStreamer().emitDirectiveSetNoMsa();
5035 return false;
5036}
5037
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005038bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005039 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005040 Parser.Lex(); // Eat "nodsp".
5041
5042 // If this is not the end of the statement, report an error.
5043 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5044 reportParseError("unexpected token, expected end of statement");
5045 return false;
5046 }
5047
5048 clearFeatureBits(Mips::FeatureDSP, "dsp");
5049 getTargetStreamer().emitDirectiveSetNoDsp();
5050 return false;
5051}
5052
Toma Tabacucc2502d2014-11-04 17:18:07 +00005053bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005054 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005055 Parser.Lex(); // Eat "mips16".
5056
Jack Carter39536722014-01-22 23:08:42 +00005057 // If this is not the end of the statement, report an error.
5058 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005059 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005060 return false;
5061 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005062
5063 setFeatureBits(Mips::FeatureMips16, "mips16");
5064 getTargetStreamer().emitDirectiveSetMips16();
5065 Parser.Lex(); // Consume the EndOfStatement.
5066 return false;
5067}
5068
5069bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005070 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005071 Parser.Lex(); // Eat "nomips16".
5072
5073 // If this is not the end of the statement, report an error.
5074 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5075 reportParseError("unexpected token, expected end of statement");
5076 return false;
5077 }
5078
5079 clearFeatureBits(Mips::FeatureMips16, "mips16");
5080 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005081 Parser.Lex(); // Consume the EndOfStatement.
5082 return false;
5083}
5084
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005085bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005086 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005087 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005088 // Line can be: .set fp=32
5089 // .set fp=xx
5090 // .set fp=64
5091 Parser.Lex(); // Eat fp token
5092 AsmToken Tok = Parser.getTok();
5093 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005094 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005095 return false;
5096 }
5097 Parser.Lex(); // Eat '=' token.
5098 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005099
5100 if (!parseFpABIValue(FpAbiVal, ".set"))
5101 return false;
5102
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005103 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005104 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005105 return false;
5106 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005107 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005108 Parser.Lex(); // Consume the EndOfStatement.
5109 return false;
5110}
5111
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005112bool MipsAsmParser::parseSetOddSPRegDirective() {
5113 MCAsmParser &Parser = getParser();
5114
5115 Parser.Lex(); // Eat "oddspreg".
5116 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5117 reportParseError("unexpected token, expected end of statement");
5118 return false;
5119 }
5120
5121 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5122 getTargetStreamer().emitDirectiveSetOddSPReg();
5123 return false;
5124}
5125
5126bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5127 MCAsmParser &Parser = getParser();
5128
5129 Parser.Lex(); // Eat "nooddspreg".
5130 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5131 reportParseError("unexpected token, expected end of statement");
5132 return false;
5133 }
5134
5135 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5136 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5137 return false;
5138}
5139
Toma Tabacu9db22db2014-09-09 10:15:38 +00005140bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005141 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005142 SMLoc Loc = getLexer().getLoc();
5143
5144 Parser.Lex();
5145 if (getLexer().isNot(AsmToken::EndOfStatement))
5146 return reportParseError("unexpected token, expected end of statement");
5147
5148 // Always keep an element on the options "stack" to prevent the user
5149 // from changing the initial options. This is how we remember them.
5150 if (AssemblerOptions.size() == 2)
5151 return reportParseError(Loc, ".set pop with no .set push");
5152
Akira Hatanakab11ef082015-11-14 06:35:56 +00005153 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005154 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005155 setAvailableFeatures(
5156 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5157 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005158
5159 getTargetStreamer().emitDirectiveSetPop();
5160 return false;
5161}
5162
5163bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005164 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005165 Parser.Lex();
5166 if (getLexer().isNot(AsmToken::EndOfStatement))
5167 return reportParseError("unexpected token, expected end of statement");
5168
5169 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005170 AssemblerOptions.push_back(
5171 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005172
5173 getTargetStreamer().emitDirectiveSetPush();
5174 return false;
5175}
5176
Toma Tabacu29696502015-06-02 09:48:04 +00005177bool MipsAsmParser::parseSetSoftFloatDirective() {
5178 MCAsmParser &Parser = getParser();
5179 Parser.Lex();
5180 if (getLexer().isNot(AsmToken::EndOfStatement))
5181 return reportParseError("unexpected token, expected end of statement");
5182
5183 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5184 getTargetStreamer().emitDirectiveSetSoftFloat();
5185 return false;
5186}
5187
5188bool MipsAsmParser::parseSetHardFloatDirective() {
5189 MCAsmParser &Parser = getParser();
5190 Parser.Lex();
5191 if (getLexer().isNot(AsmToken::EndOfStatement))
5192 return reportParseError("unexpected token, expected end of statement");
5193
5194 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5195 getTargetStreamer().emitDirectiveSetHardFloat();
5196 return false;
5197}
5198
Jack Carterd76b2372013-03-21 21:44:16 +00005199bool MipsAsmParser::parseSetAssignment() {
5200 StringRef Name;
5201 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005202 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005203
5204 if (Parser.parseIdentifier(Name))
5205 reportParseError("expected identifier after .set");
5206
5207 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005208 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005209 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005210
Jack Carter3b2c96e2014-01-22 23:31:38 +00005211 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005212 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005213
Jim Grosbach6f482002015-05-18 18:43:14 +00005214 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005215 Sym->setVariableValue(Value);
5216
5217 return false;
5218}
Jack Carterd0bd6422013-04-18 00:41:53 +00005219
Toma Tabacu26647792014-09-09 12:52:14 +00005220bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005221 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005222 Parser.Lex();
5223 if (getLexer().isNot(AsmToken::EndOfStatement))
5224 return reportParseError("unexpected token, expected end of statement");
5225
5226 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005227 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005228 setAvailableFeatures(
5229 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5230 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005231 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5232
5233 getTargetStreamer().emitDirectiveSetMips0();
5234 return false;
5235}
5236
Toma Tabacu85618b32014-08-19 14:22:52 +00005237bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005238 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005239 Parser.Lex();
5240 if (getLexer().isNot(AsmToken::Equal))
5241 return reportParseError("unexpected token, expected equals sign");
5242
5243 Parser.Lex();
5244 StringRef Arch;
5245 if (Parser.parseIdentifier(Arch))
5246 return reportParseError("expected arch identifier");
5247
5248 StringRef ArchFeatureName =
5249 StringSwitch<StringRef>(Arch)
5250 .Case("mips1", "mips1")
5251 .Case("mips2", "mips2")
5252 .Case("mips3", "mips3")
5253 .Case("mips4", "mips4")
5254 .Case("mips5", "mips5")
5255 .Case("mips32", "mips32")
5256 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005257 .Case("mips32r3", "mips32r3")
5258 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005259 .Case("mips32r6", "mips32r6")
5260 .Case("mips64", "mips64")
5261 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005262 .Case("mips64r3", "mips64r3")
5263 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005264 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005265 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005266 .Case("r4000", "mips3") // This is an implementation of Mips3.
5267 .Default("");
5268
5269 if (ArchFeatureName.empty())
5270 return reportParseError("unsupported architecture");
5271
5272 selectArch(ArchFeatureName);
5273 getTargetStreamer().emitDirectiveSetArch(Arch);
5274 return false;
5275}
5276
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005277bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005278 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005279 Parser.Lex();
5280 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005281 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005282
Matheus Almeida2852af82014-04-22 10:15:54 +00005283 switch (Feature) {
5284 default:
5285 llvm_unreachable("Unimplemented feature");
5286 case Mips::FeatureDSP:
5287 setFeatureBits(Mips::FeatureDSP, "dsp");
5288 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005289 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005290 case Mips::FeatureMicroMips:
5291 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005292 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005293 case Mips::FeatureMips1:
5294 selectArch("mips1");
5295 getTargetStreamer().emitDirectiveSetMips1();
5296 break;
5297 case Mips::FeatureMips2:
5298 selectArch("mips2");
5299 getTargetStreamer().emitDirectiveSetMips2();
5300 break;
5301 case Mips::FeatureMips3:
5302 selectArch("mips3");
5303 getTargetStreamer().emitDirectiveSetMips3();
5304 break;
5305 case Mips::FeatureMips4:
5306 selectArch("mips4");
5307 getTargetStreamer().emitDirectiveSetMips4();
5308 break;
5309 case Mips::FeatureMips5:
5310 selectArch("mips5");
5311 getTargetStreamer().emitDirectiveSetMips5();
5312 break;
5313 case Mips::FeatureMips32:
5314 selectArch("mips32");
5315 getTargetStreamer().emitDirectiveSetMips32();
5316 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005317 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005318 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005319 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005320 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005321 case Mips::FeatureMips32r3:
5322 selectArch("mips32r3");
5323 getTargetStreamer().emitDirectiveSetMips32R3();
5324 break;
5325 case Mips::FeatureMips32r5:
5326 selectArch("mips32r5");
5327 getTargetStreamer().emitDirectiveSetMips32R5();
5328 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005329 case Mips::FeatureMips32r6:
5330 selectArch("mips32r6");
5331 getTargetStreamer().emitDirectiveSetMips32R6();
5332 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005333 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005334 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005335 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005336 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005337 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005338 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005339 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005340 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005341 case Mips::FeatureMips64r3:
5342 selectArch("mips64r3");
5343 getTargetStreamer().emitDirectiveSetMips64R3();
5344 break;
5345 case Mips::FeatureMips64r5:
5346 selectArch("mips64r5");
5347 getTargetStreamer().emitDirectiveSetMips64R5();
5348 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005349 case Mips::FeatureMips64r6:
5350 selectArch("mips64r6");
5351 getTargetStreamer().emitDirectiveSetMips64R6();
5352 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005353 }
5354 return false;
5355}
5356
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005357bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005358 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005359 if (getLexer().isNot(AsmToken::Comma)) {
5360 SMLoc Loc = getLexer().getLoc();
5361 Parser.eatToEndOfStatement();
5362 return Error(Loc, ErrorStr);
5363 }
5364
Matheus Almeida2852af82014-04-22 10:15:54 +00005365 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005366 return true;
5367}
5368
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005369// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5370// In this class, it is only used for .cprestore.
5371// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5372// MipsTargetELFStreamer and MipsAsmParser.
5373bool MipsAsmParser::isPicAndNotNxxAbi() {
5374 return inPicMode() && !(isABI_N32() || isABI_N64());
5375}
5376
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005377bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005378 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005379 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005380
Toma Tabacudde4c462014-11-06 10:02:45 +00005381 if (inMips16Mode()) {
5382 reportParseError(".cpload is not supported in Mips16 mode");
5383 return false;
5384 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005385
David Blaikie960ea3f2014-06-08 16:18:35 +00005386 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005387 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005388 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5389 reportParseError("expected register containing function address");
5390 return false;
5391 }
5392
David Blaikie960ea3f2014-06-08 16:18:35 +00005393 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5394 if (!RegOpnd.isGPRAsmReg()) {
5395 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005396 return false;
5397 }
5398
Toma Tabacudde4c462014-11-06 10:02:45 +00005399 // If this is not the end of the statement, report an error.
5400 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5401 reportParseError("unexpected token, expected end of statement");
5402 return false;
5403 }
5404
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005405 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005406 return false;
5407}
5408
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005409bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5410 MCAsmParser &Parser = getParser();
5411
5412 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5413 // is used in non-PIC mode.
5414
5415 if (inMips16Mode()) {
5416 reportParseError(".cprestore is not supported in Mips16 mode");
5417 return false;
5418 }
5419
5420 // Get the stack offset value.
5421 const MCExpr *StackOffset;
5422 int64_t StackOffsetVal;
5423 if (Parser.parseExpression(StackOffset)) {
5424 reportParseError("expected stack offset value");
5425 return false;
5426 }
5427
5428 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5429 reportParseError("stack offset is not an absolute expression");
5430 return false;
5431 }
5432
5433 if (StackOffsetVal < 0) {
5434 Warning(Loc, ".cprestore with negative stack offset has no effect");
5435 IsCpRestoreSet = false;
5436 } else {
5437 IsCpRestoreSet = true;
5438 CpRestoreOffset = StackOffsetVal;
5439 }
5440
5441 // If this is not the end of the statement, report an error.
5442 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5443 reportParseError("unexpected token, expected end of statement");
5444 return false;
5445 }
5446
Daniel Sandersdf8510d2016-05-11 12:48:19 +00005447 if (!getTargetStreamer().emitDirectiveCpRestore(
5448 CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
Daniel Sanders7225cd52016-04-29 16:16:49 +00005449 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005450 Parser.Lex(); // Consume the EndOfStatement.
5451 return false;
5452}
5453
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005454bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005455 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005456 unsigned FuncReg;
5457 unsigned Save;
5458 bool SaveIsReg = true;
5459
Matheus Almeida7e815762014-06-18 13:08:59 +00005460 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005461 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005462 if (ResTy == MatchOperand_NoMatch) {
5463 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005464 return false;
5465 }
5466
5467 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5468 if (!FuncRegOpnd.isGPRAsmReg()) {
5469 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5470 Parser.eatToEndOfStatement();
5471 return false;
5472 }
5473
5474 FuncReg = FuncRegOpnd.getGPR32Reg();
5475 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005476
Toma Tabacu65f10572014-09-16 15:00:52 +00005477 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005478 return true;
5479
Toma Tabacu13964452014-09-04 13:23:44 +00005480 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005481 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005482 const MCExpr *OffsetExpr;
5483 int64_t OffsetVal;
5484 SMLoc ExprLoc = getLexer().getLoc();
5485
5486 if (Parser.parseExpression(OffsetExpr) ||
5487 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5488 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005489 Parser.eatToEndOfStatement();
5490 return false;
5491 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005492
5493 Save = OffsetVal;
5494 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005495 } else {
5496 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5497 if (!SaveOpnd.isGPRAsmReg()) {
5498 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5499 Parser.eatToEndOfStatement();
5500 return false;
5501 }
5502 Save = SaveOpnd.getGPR32Reg();
5503 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005504
Toma Tabacu65f10572014-09-16 15:00:52 +00005505 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005506 return true;
5507
Toma Tabacu8874eac2015-02-18 13:46:53 +00005508 const MCExpr *Expr;
5509 if (Parser.parseExpression(Expr)) {
5510 reportParseError("expected expression");
5511 return false;
5512 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005513
Toma Tabacu8874eac2015-02-18 13:46:53 +00005514 if (Expr->getKind() != MCExpr::SymbolRef) {
5515 reportParseError("expected symbol");
5516 return false;
5517 }
5518 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5519
Daniel Sandersf173dda2015-09-22 10:50:09 +00005520 CpSaveLocation = Save;
5521 CpSaveLocationIsRegister = SaveIsReg;
5522
Toma Tabacu8874eac2015-02-18 13:46:53 +00005523 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5524 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005525 return false;
5526}
5527
Daniel Sandersf173dda2015-09-22 10:50:09 +00005528bool MipsAsmParser::parseDirectiveCPReturn() {
5529 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5530 CpSaveLocationIsRegister);
5531 return false;
5532}
5533
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005534bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005535 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005536 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5537 const AsmToken &Tok = Parser.getTok();
5538
5539 if (Tok.getString() == "2008") {
5540 Parser.Lex();
5541 getTargetStreamer().emitDirectiveNaN2008();
5542 return false;
5543 } else if (Tok.getString() == "legacy") {
5544 Parser.Lex();
5545 getTargetStreamer().emitDirectiveNaNLegacy();
5546 return false;
5547 }
5548 }
5549 // If we don't recognize the option passed to the .nan
5550 // directive (e.g. no option or unknown option), emit an error.
5551 reportParseError("invalid option in .nan directive");
5552 return false;
5553}
5554
Jack Carter0b744b32012-10-04 02:29:46 +00005555bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005556 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005557 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005558 const AsmToken &Tok = Parser.getTok();
5559
5560 if (Tok.getString() == "noat") {
5561 return parseSetNoAtDirective();
5562 } else if (Tok.getString() == "at") {
5563 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005564 } else if (Tok.getString() == "arch") {
5565 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005566 } else if (Tok.getString() == "fp") {
5567 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005568 } else if (Tok.getString() == "oddspreg") {
5569 return parseSetOddSPRegDirective();
5570 } else if (Tok.getString() == "nooddspreg") {
5571 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005572 } else if (Tok.getString() == "pop") {
5573 return parseSetPopDirective();
5574 } else if (Tok.getString() == "push") {
5575 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005576 } else if (Tok.getString() == "reorder") {
5577 return parseSetReorderDirective();
5578 } else if (Tok.getString() == "noreorder") {
5579 return parseSetNoReorderDirective();
5580 } else if (Tok.getString() == "macro") {
5581 return parseSetMacroDirective();
5582 } else if (Tok.getString() == "nomacro") {
5583 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005584 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005585 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005586 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005587 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005588 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005589 getTargetStreamer().emitDirectiveSetNoMicroMips();
5590 Parser.eatToEndOfStatement();
5591 return false;
5592 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005593 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005594 } else if (Tok.getString() == "mips0") {
5595 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005596 } else if (Tok.getString() == "mips1") {
5597 return parseSetFeature(Mips::FeatureMips1);
5598 } else if (Tok.getString() == "mips2") {
5599 return parseSetFeature(Mips::FeatureMips2);
5600 } else if (Tok.getString() == "mips3") {
5601 return parseSetFeature(Mips::FeatureMips3);
5602 } else if (Tok.getString() == "mips4") {
5603 return parseSetFeature(Mips::FeatureMips4);
5604 } else if (Tok.getString() == "mips5") {
5605 return parseSetFeature(Mips::FeatureMips5);
5606 } else if (Tok.getString() == "mips32") {
5607 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005608 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005609 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005610 } else if (Tok.getString() == "mips32r3") {
5611 return parseSetFeature(Mips::FeatureMips32r3);
5612 } else if (Tok.getString() == "mips32r5") {
5613 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005614 } else if (Tok.getString() == "mips32r6") {
5615 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005616 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005617 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005618 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005619 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005620 } else if (Tok.getString() == "mips64r3") {
5621 return parseSetFeature(Mips::FeatureMips64r3);
5622 } else if (Tok.getString() == "mips64r5") {
5623 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005624 } else if (Tok.getString() == "mips64r6") {
5625 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005626 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005627 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005628 } else if (Tok.getString() == "nodsp") {
5629 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005630 } else if (Tok.getString() == "msa") {
5631 return parseSetMsaDirective();
5632 } else if (Tok.getString() == "nomsa") {
5633 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005634 } else if (Tok.getString() == "softfloat") {
5635 return parseSetSoftFloatDirective();
5636 } else if (Tok.getString() == "hardfloat") {
5637 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005638 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005639 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005640 parseSetAssignment();
5641 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005642 }
Jack Carter07c818d2013-01-25 01:31:34 +00005643
Jack Carter0b744b32012-10-04 02:29:46 +00005644 return true;
5645}
5646
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005647/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005648/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005649bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005650 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005651 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5652 for (;;) {
5653 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005654 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005655 return true;
5656
5657 getParser().getStreamer().EmitValue(Value, Size);
5658
5659 if (getLexer().is(AsmToken::EndOfStatement))
5660 break;
5661
Jack Carter07c818d2013-01-25 01:31:34 +00005662 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005663 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005664 Parser.Lex();
5665 }
5666 }
5667
5668 Parser.Lex();
5669 return false;
5670}
5671
Vladimir Medic4c299852013-11-06 11:27:05 +00005672/// parseDirectiveGpWord
5673/// ::= .gpword local_sym
5674bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005675 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005676 const MCExpr *Value;
5677 // EmitGPRel32Value requires an expression, so we are using base class
5678 // method to evaluate the expression.
5679 if (getParser().parseExpression(Value))
5680 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005681 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005682
Vladimir Medice10c1122013-11-13 13:18:04 +00005683 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005684 return Error(getLexer().getLoc(),
5685 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005686 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005687 return false;
5688}
5689
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005690/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005691/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005692bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005693 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005694 const MCExpr *Value;
5695 // EmitGPRel64Value requires an expression, so we are using base class
5696 // method to evaluate the expression.
5697 if (getParser().parseExpression(Value))
5698 return true;
5699 getParser().getStreamer().EmitGPRel64Value(Value);
5700
5701 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005702 return Error(getLexer().getLoc(),
5703 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005704 Parser.Lex(); // Eat EndOfStatement token.
5705 return false;
5706}
5707
Jack Carter0cd3c192014-01-06 23:27:31 +00005708bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005709 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005710 // Get the option token.
5711 AsmToken Tok = Parser.getTok();
5712 // At the moment only identifiers are supported.
5713 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005714 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005715 Parser.eatToEndOfStatement();
5716 return false;
5717 }
5718
5719 StringRef Option = Tok.getIdentifier();
5720
5721 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005722 // MipsAsmParser needs to know if the current PIC mode changes.
5723 IsPicEnabled = false;
5724
Jack Carter0cd3c192014-01-06 23:27:31 +00005725 getTargetStreamer().emitDirectiveOptionPic0();
5726 Parser.Lex();
5727 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5728 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005729 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005730 Parser.eatToEndOfStatement();
5731 }
5732 return false;
5733 }
5734
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005735 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005736 // MipsAsmParser needs to know if the current PIC mode changes.
5737 IsPicEnabled = true;
5738
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005739 getTargetStreamer().emitDirectiveOptionPic2();
5740 Parser.Lex();
5741 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5742 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005743 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005744 Parser.eatToEndOfStatement();
5745 }
5746 return false;
5747 }
5748
Jack Carter0cd3c192014-01-06 23:27:31 +00005749 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005750 Warning(Parser.getTok().getLoc(),
5751 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005752 Parser.eatToEndOfStatement();
5753 return false;
5754}
5755
Toma Tabacu9ca50962015-04-16 09:53:47 +00005756/// parseInsnDirective
5757/// ::= .insn
5758bool MipsAsmParser::parseInsnDirective() {
5759 // If this is not the end of the statement, report an error.
5760 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5761 reportParseError("unexpected token, expected end of statement");
5762 return false;
5763 }
5764
5765 // The actual label marking happens in
5766 // MipsELFStreamer::createPendingLabelRelocs().
5767 getTargetStreamer().emitDirectiveInsn();
5768
5769 getParser().Lex(); // Eat EndOfStatement token.
5770 return false;
5771}
5772
Simon Atanasyanbe186202016-02-11 06:45:54 +00005773/// parseSSectionDirective
5774/// ::= .sbss
5775/// ::= .sdata
5776bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5777 // If this is not the end of the statement, report an error.
5778 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5779 reportParseError("unexpected token, expected end of statement");
5780 return false;
5781 }
5782
5783 MCSection *ELFSection = getContext().getELFSection(
5784 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5785 getParser().getStreamer().SwitchSection(ELFSection);
5786
5787 getParser().Lex(); // Eat EndOfStatement token.
5788 return false;
5789}
5790
Daniel Sanders7e527422014-07-10 13:38:23 +00005791/// parseDirectiveModule
5792/// ::= .module oddspreg
5793/// ::= .module nooddspreg
5794/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005795/// ::= .module softfloat
5796/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005797bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005798 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005799 MCAsmLexer &Lexer = getLexer();
5800 SMLoc L = Lexer.getLoc();
5801
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005802 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005803 // TODO : get a better message.
5804 reportParseError(".module directive must appear before any code");
5805 return false;
5806 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005807
Toma Tabacuc405c822015-01-23 10:40:19 +00005808 StringRef Option;
5809 if (Parser.parseIdentifier(Option)) {
5810 reportParseError("expected .module option identifier");
5811 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005812 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005813
Toma Tabacuc405c822015-01-23 10:40:19 +00005814 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005815 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005816
Toma Tabacu3c499582015-06-25 10:56:57 +00005817 // Synchronize the abiflags information with the FeatureBits information we
5818 // changed above.
5819 getTargetStreamer().updateABIInfo(*this);
5820
5821 // If printing assembly, use the recently updated abiflags information.
5822 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5823 // emitted at the end).
5824 getTargetStreamer().emitDirectiveModuleOddSPReg();
5825
Toma Tabacuc405c822015-01-23 10:40:19 +00005826 // If this is not the end of the statement, report an error.
5827 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5828 reportParseError("unexpected token, expected end of statement");
5829 return false;
5830 }
5831
5832 return false; // parseDirectiveModule has finished successfully.
5833 } else if (Option == "nooddspreg") {
5834 if (!isABI_O32()) {
5835 Error(L, "'.module nooddspreg' requires the O32 ABI");
5836 return false;
5837 }
5838
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005839 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005840
Toma Tabacu3c499582015-06-25 10:56:57 +00005841 // Synchronize the abiflags information with the FeatureBits information we
5842 // changed above.
5843 getTargetStreamer().updateABIInfo(*this);
5844
5845 // If printing assembly, use the recently updated abiflags information.
5846 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5847 // emitted at the end).
5848 getTargetStreamer().emitDirectiveModuleOddSPReg();
5849
Toma Tabacuc405c822015-01-23 10:40:19 +00005850 // If this is not the end of the statement, report an error.
5851 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5852 reportParseError("unexpected token, expected end of statement");
5853 return false;
5854 }
5855
5856 return false; // parseDirectiveModule has finished successfully.
5857 } else if (Option == "fp") {
5858 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005859 } else if (Option == "softfloat") {
5860 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5861
5862 // Synchronize the ABI Flags information with the FeatureBits information we
5863 // updated above.
5864 getTargetStreamer().updateABIInfo(*this);
5865
5866 // If printing assembly, use the recently updated ABI Flags information.
5867 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5868 // emitted later).
5869 getTargetStreamer().emitDirectiveModuleSoftFloat();
5870
5871 // If this is not the end of the statement, report an error.
5872 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5873 reportParseError("unexpected token, expected end of statement");
5874 return false;
5875 }
5876
5877 return false; // parseDirectiveModule has finished successfully.
5878 } else if (Option == "hardfloat") {
5879 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5880
5881 // Synchronize the ABI Flags information with the FeatureBits information we
5882 // updated above.
5883 getTargetStreamer().updateABIInfo(*this);
5884
5885 // If printing assembly, use the recently updated ABI Flags information.
5886 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5887 // emitted later).
5888 getTargetStreamer().emitDirectiveModuleHardFloat();
5889
5890 // If this is not the end of the statement, report an error.
5891 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5892 reportParseError("unexpected token, expected end of statement");
5893 return false;
5894 }
5895
5896 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005897 } else {
5898 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5899 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005900}
5901
5902/// parseDirectiveModuleFP
5903/// ::= =32
5904/// ::= =xx
5905/// ::= =64
5906bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005907 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005908 MCAsmLexer &Lexer = getLexer();
5909
5910 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005911 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005912 return false;
5913 }
5914 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005915
Daniel Sanders7e527422014-07-10 13:38:23 +00005916 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005917 if (!parseFpABIValue(FpABI, ".module"))
5918 return false;
5919
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005920 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005921 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005922 return false;
5923 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005924
Toma Tabacua64e5402015-06-25 12:44:38 +00005925 // Synchronize the abiflags information with the FeatureBits information we
5926 // changed above.
5927 getTargetStreamer().updateABIInfo(*this);
5928
5929 // If printing assembly, use the recently updated abiflags information.
5930 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5931 // emitted at the end).
5932 getTargetStreamer().emitDirectiveModuleFP();
5933
Daniel Sanders7e527422014-07-10 13:38:23 +00005934 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005935 return false;
5936}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005937
Daniel Sanders7e527422014-07-10 13:38:23 +00005938bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005939 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005940 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005941 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005942 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005943
5944 if (Lexer.is(AsmToken::Identifier)) {
5945 StringRef Value = Parser.getTok().getString();
5946 Parser.Lex();
5947
5948 if (Value != "xx") {
5949 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5950 return false;
5951 }
5952
5953 if (!isABI_O32()) {
5954 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5955 return false;
5956 }
5957
Daniel Sanders7e527422014-07-10 13:38:23 +00005958 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005959 if (ModuleLevelOptions) {
5960 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5961 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5962 } else {
5963 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5964 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5965 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005966 return true;
5967 }
5968
5969 if (Lexer.is(AsmToken::Integer)) {
5970 unsigned Value = Parser.getTok().getIntVal();
5971 Parser.Lex();
5972
5973 if (Value != 32 && Value != 64) {
5974 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5975 return false;
5976 }
5977
5978 if (Value == 32) {
5979 if (!isABI_O32()) {
5980 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5981 return false;
5982 }
5983
Daniel Sanders7e527422014-07-10 13:38:23 +00005984 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005985 if (ModuleLevelOptions) {
5986 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5987 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5988 } else {
5989 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5990 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5991 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005992 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005993 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005994 if (ModuleLevelOptions) {
5995 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5996 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5997 } else {
5998 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5999 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
6000 }
Toma Tabacua64e5402015-06-25 12:44:38 +00006001 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006002
Daniel Sanders7e527422014-07-10 13:38:23 +00006003 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00006004 }
6005
6006 return false;
6007}
6008
Jack Carter0b744b32012-10-04 02:29:46 +00006009bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00006010 // This returns false if this function recognizes the directive
6011 // regardless of whether it is successfully handles or reports an
6012 // error. Otherwise it returns true to give the generic parser a
6013 // chance at recognizing it.
6014
Rafael Espindola961d4692014-11-11 05:18:41 +00006015 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00006016 StringRef IDVal = DirectiveID.getString();
6017
Nirav Dave996fc132016-05-05 14:15:46 +00006018 if (IDVal == ".cpload") {
6019 parseDirectiveCpLoad(DirectiveID.getLoc());
6020 return false;
6021 }
6022 if (IDVal == ".cprestore") {
6023 parseDirectiveCpRestore(DirectiveID.getLoc());
6024 return false;
6025 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006026 if (IDVal == ".dword") {
6027 parseDataDirective(8, DirectiveID.getLoc());
6028 return false;
6029 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006030 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006031 StringRef SymbolName;
6032
6033 if (Parser.parseIdentifier(SymbolName)) {
6034 reportParseError("expected identifier after .ent");
6035 return false;
6036 }
6037
6038 // There's an undocumented extension that allows an integer to
6039 // follow the name of the procedure which AFAICS is ignored by GAS.
6040 // Example: .ent foo,2
6041 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6042 if (getLexer().isNot(AsmToken::Comma)) {
6043 // Even though we accept this undocumented extension for compatibility
6044 // reasons, the additional integer argument does not actually change
6045 // the behaviour of the '.ent' directive, so we would like to discourage
6046 // its use. We do this by not referring to the extended version in
6047 // error messages which are not directly related to its use.
6048 reportParseError("unexpected token, expected end of statement");
6049 return false;
6050 }
6051 Parser.Lex(); // Eat the comma.
6052 const MCExpr *DummyNumber;
6053 int64_t DummyNumberVal;
6054 // If the user was explicitly trying to use the extended version,
6055 // we still give helpful extension-related error messages.
6056 if (Parser.parseExpression(DummyNumber)) {
6057 reportParseError("expected number after comma");
6058 return false;
6059 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006060 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006061 reportParseError("expected an absolute expression after comma");
6062 return false;
6063 }
6064 }
6065
6066 // If this is not the end of the statement, report an error.
6067 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6068 reportParseError("unexpected token, expected end of statement");
6069 return false;
6070 }
6071
Jim Grosbach6f482002015-05-18 18:43:14 +00006072 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006073
6074 getTargetStreamer().emitDirectiveEnt(*Sym);
6075 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006076 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006077 return false;
6078 }
6079
Jack Carter07c818d2013-01-25 01:31:34 +00006080 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006081 StringRef SymbolName;
6082
6083 if (Parser.parseIdentifier(SymbolName)) {
6084 reportParseError("expected identifier after .end");
6085 return false;
6086 }
6087
6088 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6089 reportParseError("unexpected token, expected end of statement");
6090 return false;
6091 }
6092
6093 if (CurrentFn == nullptr) {
6094 reportParseError(".end used without .ent");
6095 return false;
6096 }
6097
6098 if ((SymbolName != CurrentFn->getName())) {
6099 reportParseError(".end symbol does not match .ent symbol");
6100 return false;
6101 }
6102
6103 getTargetStreamer().emitDirectiveEnd(SymbolName);
6104 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006105 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006106 return false;
6107 }
6108
Jack Carter07c818d2013-01-25 01:31:34 +00006109 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006110 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6111 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006112 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006113 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6114 reportParseError("expected stack register");
6115 return false;
6116 }
6117
6118 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6119 if (!StackRegOpnd.isGPRAsmReg()) {
6120 reportParseError(StackRegOpnd.getStartLoc(),
6121 "expected general purpose register");
6122 return false;
6123 }
6124 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6125
6126 if (Parser.getTok().is(AsmToken::Comma))
6127 Parser.Lex();
6128 else {
6129 reportParseError("unexpected token, expected comma");
6130 return false;
6131 }
6132
6133 // Parse the frame size.
6134 const MCExpr *FrameSize;
6135 int64_t FrameSizeVal;
6136
6137 if (Parser.parseExpression(FrameSize)) {
6138 reportParseError("expected frame size value");
6139 return false;
6140 }
6141
Jim Grosbach13760bd2015-05-30 01:25:56 +00006142 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006143 reportParseError("frame size not an absolute expression");
6144 return false;
6145 }
6146
6147 if (Parser.getTok().is(AsmToken::Comma))
6148 Parser.Lex();
6149 else {
6150 reportParseError("unexpected token, expected comma");
6151 return false;
6152 }
6153
6154 // Parse the return register.
6155 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006156 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006157 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6158 reportParseError("expected return register");
6159 return false;
6160 }
6161
6162 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6163 if (!ReturnRegOpnd.isGPRAsmReg()) {
6164 reportParseError(ReturnRegOpnd.getStartLoc(),
6165 "expected general purpose register");
6166 return false;
6167 }
6168
6169 // If this is not the end of the statement, report an error.
6170 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6171 reportParseError("unexpected token, expected end of statement");
6172 return false;
6173 }
6174
6175 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6176 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006177 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006178 return false;
6179 }
6180
Jack Carter07c818d2013-01-25 01:31:34 +00006181 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006182 parseDirectiveSet();
6183 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006184 }
6185
Daniel Sandersd97a6342014-08-13 10:07:34 +00006186 if (IDVal == ".mask" || IDVal == ".fmask") {
6187 // .mask bitmask, frame_offset
6188 // bitmask: One bit for each register used.
6189 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6190 // first register is expected to be saved.
6191 // Examples:
6192 // .mask 0x80000000, -4
6193 // .fmask 0x80000000, -4
6194 //
Jack Carterbe332172012-09-07 00:48:02 +00006195
Daniel Sandersd97a6342014-08-13 10:07:34 +00006196 // Parse the bitmask
6197 const MCExpr *BitMask;
6198 int64_t BitMaskVal;
6199
6200 if (Parser.parseExpression(BitMask)) {
6201 reportParseError("expected bitmask value");
6202 return false;
6203 }
6204
Jim Grosbach13760bd2015-05-30 01:25:56 +00006205 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006206 reportParseError("bitmask not an absolute expression");
6207 return false;
6208 }
6209
6210 if (Parser.getTok().is(AsmToken::Comma))
6211 Parser.Lex();
6212 else {
6213 reportParseError("unexpected token, expected comma");
6214 return false;
6215 }
6216
6217 // Parse the frame_offset
6218 const MCExpr *FrameOffset;
6219 int64_t FrameOffsetVal;
6220
6221 if (Parser.parseExpression(FrameOffset)) {
6222 reportParseError("expected frame offset value");
6223 return false;
6224 }
6225
Jim Grosbach13760bd2015-05-30 01:25:56 +00006226 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006227 reportParseError("frame offset not an absolute expression");
6228 return false;
6229 }
6230
6231 // If this is not the end of the statement, report an error.
6232 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6233 reportParseError("unexpected token, expected end of statement");
6234 return false;
6235 }
6236
6237 if (IDVal == ".mask")
6238 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6239 else
6240 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006241 return false;
6242 }
6243
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006244 if (IDVal == ".nan")
6245 return parseDirectiveNaN();
6246
Jack Carter07c818d2013-01-25 01:31:34 +00006247 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006248 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006249 return false;
6250 }
6251
Rafael Espindolab59fb732014-03-28 18:50:26 +00006252 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006253 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006254 return false;
6255 }
6256
Jack Carter07c818d2013-01-25 01:31:34 +00006257 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006258 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006259 return false;
6260 }
6261
Scott Egertond1aeb052016-02-15 16:11:51 +00006262 if (IDVal == ".hword") {
6263 parseDataDirective(2, DirectiveID.getLoc());
6264 return false;
6265 }
6266
Nirav Dave996fc132016-05-05 14:15:46 +00006267 if (IDVal == ".option") {
6268 parseDirectiveOption();
6269 return false;
6270 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006271
6272 if (IDVal == ".abicalls") {
6273 getTargetStreamer().emitDirectiveAbiCalls();
6274 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006275 Error(Parser.getTok().getLoc(),
6276 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006277 // Clear line
6278 Parser.eatToEndOfStatement();
6279 }
6280 return false;
6281 }
6282
Nirav Dave996fc132016-05-05 14:15:46 +00006283 if (IDVal == ".cpsetup") {
6284 parseDirectiveCPSetup();
6285 return false;
6286 }
6287 if (IDVal == ".cpreturn") {
6288 parseDirectiveCPReturn();
6289 return false;
6290 }
6291 if (IDVal == ".module") {
6292 parseDirectiveModule();
6293 return false;
6294 }
6295 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6296 parseInternalDirectiveReallowModule();
6297 return false;
6298 }
6299 if (IDVal == ".insn") {
6300 parseInsnDirective();
6301 return false;
6302 }
6303 if (IDVal == ".sbss") {
6304 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6305 return false;
6306 }
6307 if (IDVal == ".sdata") {
6308 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6309 return false;
6310 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006311
Rafael Espindola870c4e92012-01-11 03:56:41 +00006312 return true;
6313}
6314
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006315bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6316 // If this is not the end of the statement, report an error.
6317 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6318 reportParseError("unexpected token, expected end of statement");
6319 return false;
6320 }
6321
6322 getTargetStreamer().reallowModuleDirective();
6323
6324 getParser().Lex(); // Eat EndOfStatement token.
6325 return false;
6326}
6327
Rafael Espindola870c4e92012-01-11 03:56:41 +00006328extern "C" void LLVMInitializeMipsAsmParser() {
6329 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6330 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6331 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6332 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6333}
Jack Carterb4dbc172012-09-05 23:34:03 +00006334
6335#define GET_REGISTER_MATCHER
6336#define GET_MATCHER_IMPLEMENTATION
6337#include "MipsGenAsmMatcher.inc"