blob: 001a9be332d199c51cd1fc0329722f2afa0d6698 [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!");
1010 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +00001011 Inst.addOperand(MCOperand::createReg(RegNo++));
1012 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001013 }
1014
Zoran Jovanovic41688672015-02-10 16:36:20 +00001015 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
1016 assert(N == 2 && "Invalid number of operands!");
1017 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +00001018 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +00001019 }
1020
Craig Topper56c590a2014-04-29 07:58:02 +00001021 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001022 // As a special case until we sort out the definition of div/divu, pretend
1023 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1024 if (isGPRAsmReg() && RegIdx.Index == 0)
1025 return true;
1026
1027 return Kind == k_PhysRegister;
1028 }
1029 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +00001030 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001031 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +00001032 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001033 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001034 bool isConstantImmz() const {
1035 return isConstantImm() && getConstantImm() == 0;
1036 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001037 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1038 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1039 }
Daniel Sanders85fd10b2016-03-31 14:34:00 +00001040 template <unsigned Bits> bool isSImm() const {
1041 return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
1042 }
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00001043 template <unsigned Bits> bool isUImm() const {
1044 return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
1045 }
1046 template <unsigned Bits> bool isAnyImm() const {
1047 return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
1048 isUInt<Bits>(getConstantImm()))
1049 : isImm();
1050 }
Daniel Sanders78e89022016-03-11 11:37:50 +00001051 template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
1052 return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001053 }
Hrvoje Varga46458d02016-02-25 12:53:29 +00001054 template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
1055 return isConstantImm() && getConstantImm() >= Bottom &&
1056 getConstantImm() <= Top;
1057 }
Craig Topper56c590a2014-04-29 07:58:02 +00001058 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001059 // Note: It's not possible to pretend that other operand kinds are tokens.
1060 // The matcher emitter checks tokens first.
1061 return Kind == k_Token;
1062 }
Craig Topper56c590a2014-04-29 07:58:02 +00001063 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001064 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001065 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001066 }
Daniel Sandersdc0602a2016-03-31 14:12:01 +00001067 template <unsigned Bits, unsigned ShiftAmount = 0>
1068 bool isMemWithSimmOffset() const {
1069 return isMem() && isConstantMemOff() &&
1070 isShiftedInt<Bits, ShiftAmount>(getConstantMemOff()) &&
1071 getMemBase()->isGPRAsmReg();
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001072 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001073 bool isMemWithGRPMM16Base() const {
1074 return isMem() && getMemBase()->isMM16AsmReg();
1075 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001076 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1077 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1078 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1079 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001080 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1081 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1082 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1083 && (getMemBase()->getGPR32Reg() == Mips::SP);
1084 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001085 template <unsigned Bits, unsigned ShiftLeftAmount>
1086 bool isScaledUImm() const {
1087 return isConstantImm() &&
1088 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001089 }
Daniel Sanders97297772016-03-22 14:40:00 +00001090 template <unsigned Bits, unsigned ShiftLeftAmount>
1091 bool isScaledSImm() const {
1092 return isConstantImm() &&
1093 isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
1094 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001095 bool isRegList16() const {
1096 if (!isRegList())
1097 return false;
1098
1099 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001100 if (Size < 2 || Size > 5)
1101 return false;
1102
1103 unsigned R0 = RegList.List->front();
1104 unsigned R1 = RegList.List->back();
1105 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1106 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001107 return false;
1108
1109 int PrevReg = *RegList.List->begin();
1110 for (int i = 1; i < Size - 1; i++) {
1111 int Reg = (*(RegList.List))[i];
1112 if ( Reg != PrevReg + 1)
1113 return false;
1114 PrevReg = Reg;
1115 }
1116
1117 return true;
1118 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001119 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001120 bool isLSAImm() const {
1121 if (!isConstantImm())
1122 return false;
1123 int64_t Val = getConstantImm();
1124 return 1 <= Val && Val <= 4;
1125 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001126 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001127 bool isMovePRegPair() const {
1128 if (Kind != k_RegList || RegList.List->size() != 2)
1129 return false;
1130
1131 unsigned R0 = RegList.List->front();
1132 unsigned R1 = RegList.List->back();
1133
1134 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1135 (R0 == Mips::A1 && R1 == Mips::A3) ||
1136 (R0 == Mips::A2 && R1 == Mips::A3) ||
1137 (R0 == Mips::A0 && R1 == Mips::S5) ||
1138 (R0 == Mips::A0 && R1 == Mips::S6) ||
1139 (R0 == Mips::A0 && R1 == Mips::A1) ||
1140 (R0 == Mips::A0 && R1 == Mips::A2) ||
Zlatko Buljan4807f822016-05-04 12:02:12 +00001141 (R0 == Mips::A0 && R1 == Mips::A3) ||
1142 (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
1143 (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
1144 (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
1145 (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
1146 (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
1147 (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
1148 (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
1149 (R0 == Mips::A0_64 && R1 == Mips::A3_64))
Zoran Jovanovic41688672015-02-10 16:36:20 +00001150 return true;
1151
1152 return false;
1153 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001154
1155 StringRef getToken() const {
1156 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001157 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001158 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001159 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001160
Craig Topper56c590a2014-04-29 07:58:02 +00001161 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001162 // As a special case until we sort out the definition of div/divu, pretend
1163 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1164 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1165 RegIdx.Kind & RegKind_GPR)
1166 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001167
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001168 assert(Kind == k_PhysRegister && "Invalid access!");
1169 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001170 }
1171
Jack Carterb4dbc172012-09-05 23:34:03 +00001172 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001173 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001174 return Imm.Val;
1175 }
1176
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001177 int64_t getConstantImm() const {
1178 const MCExpr *Val = getImm();
1179 return static_cast<const MCConstantExpr *>(Val)->getValue();
1180 }
1181
1182 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001183 assert((Kind == k_Memory) && "Invalid access!");
1184 return Mem.Base;
1185 }
1186
1187 const MCExpr *getMemOff() const {
1188 assert((Kind == k_Memory) && "Invalid access!");
1189 return Mem.Off;
1190 }
1191
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001192 int64_t getConstantMemOff() const {
1193 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1194 }
1195
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001196 const SmallVectorImpl<unsigned> &getRegList() const {
1197 assert((Kind == k_RegList) && "Invalid access!");
1198 return *(RegList.List);
1199 }
1200
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001201 unsigned getRegPair() const {
1202 assert((Kind == k_RegPair) && "Invalid access!");
1203 return RegIdx.Index;
1204 }
1205
David Blaikie960ea3f2014-06-08 16:18:35 +00001206 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1207 MipsAsmParser &Parser) {
1208 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001209 Op->Tok.Data = Str.data();
1210 Op->Tok.Length = Str.size();
1211 Op->StartLoc = S;
1212 Op->EndLoc = S;
1213 return Op;
1214 }
1215
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001216 /// Create a numeric register (e.g. $1). The exact register remains
1217 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001218 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001219 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001220 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001221 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001222 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001223 }
1224
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001225 /// Create a register that is definitely a GPR.
1226 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001227 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001228 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001229 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001230 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001231 }
1232
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001233 /// Create a register that is definitely a FGR.
1234 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001235 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001236 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001237 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001238 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1239 }
1240
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001241 /// Create a register that is definitely a HWReg.
1242 /// This is typically only used for named registers such as $hwr_cpunum.
1243 static std::unique_ptr<MipsOperand>
1244 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1245 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1246 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1247 }
1248
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001249 /// Create a register that is definitely an FCC.
1250 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001251 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001252 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001253 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001254 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1255 }
1256
1257 /// Create a register that is definitely an ACC.
1258 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001259 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001260 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001261 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001262 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1263 }
1264
1265 /// Create a register that is definitely an MSA128.
1266 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001267 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001268 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001269 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001270 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1271 }
1272
1273 /// Create a register that is definitely an MSACtrl.
1274 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001275 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001276 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001277 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001278 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1279 }
1280
David Blaikie960ea3f2014-06-08 16:18:35 +00001281 static std::unique_ptr<MipsOperand>
1282 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1283 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001284 Op->Imm.Val = Val;
1285 Op->StartLoc = S;
1286 Op->EndLoc = E;
1287 return Op;
1288 }
1289
David Blaikie960ea3f2014-06-08 16:18:35 +00001290 static std::unique_ptr<MipsOperand>
1291 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1292 SMLoc E, MipsAsmParser &Parser) {
1293 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1294 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001295 Op->Mem.Off = Off;
1296 Op->StartLoc = S;
1297 Op->EndLoc = E;
1298 return Op;
1299 }
1300
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001301 static std::unique_ptr<MipsOperand>
1302 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1303 MipsAsmParser &Parser) {
1304 assert (Regs.size() > 0 && "Empty list not allowed");
1305
1306 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001307 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001308 Op->StartLoc = StartLoc;
1309 Op->EndLoc = EndLoc;
1310 return Op;
1311 }
1312
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001313 static std::unique_ptr<MipsOperand>
1314 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1315 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1316 Op->RegIdx.Index = RegNo;
1317 Op->StartLoc = S;
1318 Op->EndLoc = E;
1319 return Op;
1320 }
1321
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001322 bool isGPRAsmReg() const {
1323 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001324 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001325 bool isMM16AsmReg() const {
1326 if (!(isRegIdx() && RegIdx.Kind))
1327 return false;
1328 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1329 || RegIdx.Index == 16 || RegIdx.Index == 17);
1330 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001331 bool isMM16AsmRegZero() const {
1332 if (!(isRegIdx() && RegIdx.Kind))
1333 return false;
1334 return (RegIdx.Index == 0 ||
1335 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1336 RegIdx.Index == 17);
1337 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001338 bool isMM16AsmRegMoveP() const {
1339 if (!(isRegIdx() && RegIdx.Kind))
1340 return false;
1341 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1342 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1343 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001344 bool isFGRAsmReg() const {
1345 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1346 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001347 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001348 bool isHWRegsAsmReg() const {
1349 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001350 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001351 bool isCCRAsmReg() const {
1352 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001353 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001354 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001355 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1356 return false;
1357 if (!AsmParser.hasEightFccRegisters())
1358 return RegIdx.Index == 0;
1359 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001360 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001361 bool isACCAsmReg() const {
1362 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001363 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001364 bool isCOP0AsmReg() const {
1365 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1366 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001367 bool isCOP2AsmReg() const {
1368 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001369 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001370 bool isCOP3AsmReg() const {
1371 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1372 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001373 bool isMSA128AsmReg() const {
1374 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001375 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001376 bool isMSACtrlAsmReg() const {
1377 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001378 }
1379
Jack Carterb4dbc172012-09-05 23:34:03 +00001380 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001381 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001382 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001383 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001384
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001385 virtual ~MipsOperand() {
1386 switch (Kind) {
1387 case k_Immediate:
1388 break;
1389 case k_Memory:
1390 delete Mem.Base;
1391 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001392 case k_RegList:
1393 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001394 case k_PhysRegister:
1395 case k_RegisterIndex:
1396 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001397 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001398 break;
1399 }
1400 }
1401
Craig Topper56c590a2014-04-29 07:58:02 +00001402 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001403 switch (Kind) {
1404 case k_Immediate:
1405 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001406 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001407 OS << ">";
1408 break;
1409 case k_Memory:
1410 OS << "Mem<";
1411 Mem.Base->print(OS);
1412 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001413 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001414 OS << ">";
1415 break;
1416 case k_PhysRegister:
1417 OS << "PhysReg<" << PhysReg.Num << ">";
1418 break;
1419 case k_RegisterIndex:
1420 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1421 break;
1422 case k_Token:
1423 OS << Tok.Data;
1424 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001425 case k_RegList:
1426 OS << "RegList< ";
1427 for (auto Reg : (*RegList.List))
1428 OS << Reg << " ";
1429 OS << ">";
1430 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001431 case k_RegPair:
1432 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1433 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001434 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001435 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001436}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001437} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001438
Jack Carter9e65aa32013-03-22 00:05:30 +00001439namespace llvm {
1440extern const MCInstrDesc MipsInsts[];
1441}
1442static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1443 return MipsInsts[Opcode];
1444}
1445
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001446static bool hasShortDelaySlot(unsigned Opcode) {
1447 switch (Opcode) {
1448 case Mips::JALS_MM:
1449 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001450 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001451 case Mips::BGEZALS_MM:
1452 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001453 return true;
1454 default:
1455 return false;
1456 }
1457}
1458
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001459static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1460 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1461 return &SRExpr->getSymbol();
1462 }
1463
1464 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1465 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1466 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1467
1468 if (LHSSym)
1469 return LHSSym;
1470
1471 if (RHSSym)
1472 return RHSSym;
1473
1474 return nullptr;
1475 }
1476
1477 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1478 return getSingleMCSymbol(UExpr->getSubExpr());
1479
1480 return nullptr;
1481}
1482
1483static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1484 if (isa<MCSymbolRefExpr>(Expr))
1485 return 1;
1486
1487 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1488 return countMCSymbolRefExpr(BExpr->getLHS()) +
1489 countMCSymbolRefExpr(BExpr->getRHS());
1490
1491 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1492 return countMCSymbolRefExpr(UExpr->getSubExpr());
1493
1494 return 0;
1495}
1496
Jack Carter9e65aa32013-03-22 00:05:30 +00001497bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001498 MCStreamer &Out,
1499 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001500 MipsTargetStreamer &TOut = getTargetStreamer();
Jack Carter9e65aa32013-03-22 00:05:30 +00001501 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001502 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001503
Jack Carter9e65aa32013-03-22 00:05:30 +00001504 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001505
1506 if (MCID.isBranch() || MCID.isCall()) {
1507 const unsigned Opcode = Inst.getOpcode();
1508 MCOperand Offset;
1509
1510 switch (Opcode) {
1511 default:
1512 break;
Kai Nackee0245392015-01-27 19:11:28 +00001513 case Mips::BBIT0:
1514 case Mips::BBIT032:
1515 case Mips::BBIT1:
1516 case Mips::BBIT132:
1517 assert(hasCnMips() && "instruction only valid for octeon cpus");
1518 // Fall through
1519
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001520 case Mips::BEQ:
1521 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001522 case Mips::BEQ_MM:
1523 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001524 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001525 Offset = Inst.getOperand(2);
1526 if (!Offset.isImm())
1527 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001528 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001529 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001530 if (OffsetToAlignment(Offset.getImm(),
1531 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001532 return Error(IDLoc, "branch to misaligned address");
1533 break;
1534 case Mips::BGEZ:
1535 case Mips::BGTZ:
1536 case Mips::BLEZ:
1537 case Mips::BLTZ:
1538 case Mips::BGEZAL:
1539 case Mips::BLTZAL:
1540 case Mips::BC1F:
1541 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001542 case Mips::BGEZ_MM:
1543 case Mips::BGTZ_MM:
1544 case Mips::BLEZ_MM:
1545 case Mips::BLTZ_MM:
1546 case Mips::BGEZAL_MM:
1547 case Mips::BLTZAL_MM:
1548 case Mips::BC1F_MM:
1549 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001550 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001551 Offset = Inst.getOperand(1);
1552 if (!Offset.isImm())
1553 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001554 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001555 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001556 if (OffsetToAlignment(Offset.getImm(),
1557 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001558 return Error(IDLoc, "branch to misaligned address");
1559 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001560 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001561 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001562 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001563 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001564 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1565 Offset = Inst.getOperand(1);
1566 if (!Offset.isImm())
1567 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001568 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001569 return Error(IDLoc, "branch target out of range");
1570 if (OffsetToAlignment(Offset.getImm(), 2LL))
1571 return Error(IDLoc, "branch to misaligned address");
1572 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001573 }
1574 }
1575
Daniel Sandersa84989a2014-06-16 13:25:35 +00001576 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1577 // We still accept it but it is a normal nop.
1578 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1579 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1580 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1581 "nop instruction");
1582 }
1583
Kai Nackee0245392015-01-27 19:11:28 +00001584 if (hasCnMips()) {
1585 const unsigned Opcode = Inst.getOpcode();
1586 MCOperand Opnd;
1587 int Imm;
1588
1589 switch (Opcode) {
1590 default:
1591 break;
1592
1593 case Mips::BBIT0:
1594 case Mips::BBIT032:
1595 case Mips::BBIT1:
1596 case Mips::BBIT132:
1597 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1598 // The offset is handled above
1599 Opnd = Inst.getOperand(1);
1600 if (!Opnd.isImm())
1601 return Error(IDLoc, "expected immediate operand kind");
1602 Imm = Opnd.getImm();
1603 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1604 Opcode == Mips::BBIT1 ? 63 : 31))
1605 return Error(IDLoc, "immediate operand value out of range");
1606 if (Imm > 31) {
1607 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1608 : Mips::BBIT132);
1609 Inst.getOperand(1).setImm(Imm - 32);
1610 }
1611 break;
1612
Kai Nackee0245392015-01-27 19:11:28 +00001613 case Mips::SEQi:
1614 case Mips::SNEi:
1615 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1616 Opnd = Inst.getOperand(2);
1617 if (!Opnd.isImm())
1618 return Error(IDLoc, "expected immediate operand kind");
1619 Imm = Opnd.getImm();
1620 if (!isInt<10>(Imm))
1621 return Error(IDLoc, "immediate operand value out of range");
1622 break;
1623 }
1624 }
1625
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001626 // This expansion is not in a function called by tryExpandInstruction()
1627 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001628 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1629 inPicMode()) {
1630 warnIfNoMacro(IDLoc);
1631
1632 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1633
1634 // We can do this expansion if there's only 1 symbol in the argument
1635 // expression.
1636 if (countMCSymbolRefExpr(JalExpr) > 1)
1637 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1638
1639 // FIXME: This is checking the expression can be handled by the later stages
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001640 // of the assembler. We ought to leave it to those later stages.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001641 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1642
1643 // FIXME: Add support for label+offset operands (currently causes an error).
1644 // FIXME: Add support for forward-declared local symbols.
1645 // FIXME: Add expansion for when the LargeGOT option is enabled.
1646 if (JalSym->isInSection() || JalSym->isTemporary()) {
1647 if (isABI_O32()) {
1648 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001649 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001650 // R_(MICRO)MIPS_GOT16 label
1651 // addiu $25, $25, 0
1652 // R_(MICRO)MIPS_LO16 label
1653 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001654 const MCExpr *Got16RelocExpr =
1655 MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
1656 const MCExpr *Lo16RelocExpr =
1657 MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001658
Daniel Sandersa736b372016-04-29 13:33:12 +00001659 TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
1660 MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
1661 TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1662 MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001663 } else if (isABI_N32() || isABI_N64()) {
1664 // If it's a local symbol and the N32/N64 ABIs are being used,
1665 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001666 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001667 // R_(MICRO)MIPS_GOT_DISP label
1668 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001669 const MCExpr *GotDispRelocExpr =
1670 MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001671
Daniel Sandersa736b372016-04-29 13:33:12 +00001672 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
1673 Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
1674 STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001675 }
1676 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001677 // If it's an external/weak symbol, we expand to:
1678 // lw/ld $25, 0($gp)
1679 // R_(MICRO)MIPS_CALL16 label
1680 // jalr $25
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00001681 const MCExpr *Call16RelocExpr =
1682 MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001683
Daniel Sandersa736b372016-04-29 13:33:12 +00001684 TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1685 MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001686 }
1687
1688 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001689 if (IsCpRestoreSet && inMicroMipsMode())
1690 JalrInst.setOpcode(Mips::JALRS_MM);
1691 else
1692 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001693 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1694 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1695
1696 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1697 // This relocation is supposed to be an optimization hint for the linker
1698 // and is not necessary for correctness.
1699
1700 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001701 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001702 }
1703
Jack Carter9e65aa32013-03-22 00:05:30 +00001704 if (MCID.mayLoad() || MCID.mayStore()) {
1705 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001706 // reference or immediate we may have to expand instructions.
1707 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001708 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001709 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1710 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001711 MCOperand &Op = Inst.getOperand(i);
1712 if (Op.isImm()) {
1713 int MemOffset = Op.getImm();
1714 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001715 // Offset can't exceed 16bit value.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001716 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001717 return false;
1718 }
1719 } else if (Op.isExpr()) {
1720 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001721 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001722 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001723 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001724 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001725 // Expand symbol.
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001726 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001727 return false;
1728 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001729 } else if (!isEvaluated(Expr)) {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001730 expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001731 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001732 }
1733 }
1734 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001735 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001736 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001737
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001738 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001739 if (MCID.mayLoad()) {
1740 // Try to create 16-bit GP relative load instruction.
1741 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1742 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1743 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1744 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1745 MCOperand &Op = Inst.getOperand(i);
1746 if (Op.isImm()) {
1747 int MemOffset = Op.getImm();
1748 MCOperand &DstReg = Inst.getOperand(0);
1749 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001750 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001751 getContext().getRegisterInfo()->getRegClass(
1752 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001753 (BaseReg.getReg() == Mips::GP ||
1754 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001755
Daniel Sandersa736b372016-04-29 13:33:12 +00001756 TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1757 IDLoc, STI);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001758 return false;
1759 }
1760 }
1761 }
1762 } // for
1763 } // if load
1764
1765 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1766
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001767 MCOperand Opnd;
1768 int Imm;
1769
1770 switch (Inst.getOpcode()) {
1771 default:
1772 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001773 case Mips::ADDIUSP_MM:
1774 Opnd = Inst.getOperand(0);
1775 if (!Opnd.isImm())
1776 return Error(IDLoc, "expected immediate operand kind");
1777 Imm = Opnd.getImm();
1778 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1779 Imm % 4 != 0)
1780 return Error(IDLoc, "immediate operand value out of range");
1781 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001782 case Mips::SLL16_MM:
1783 case Mips::SRL16_MM:
1784 Opnd = Inst.getOperand(2);
1785 if (!Opnd.isImm())
1786 return Error(IDLoc, "expected immediate operand kind");
1787 Imm = Opnd.getImm();
1788 if (Imm < 1 || Imm > 8)
1789 return Error(IDLoc, "immediate operand value out of range");
1790 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001791 case Mips::LI16_MM:
1792 Opnd = Inst.getOperand(1);
1793 if (!Opnd.isImm())
1794 return Error(IDLoc, "expected immediate operand kind");
1795 Imm = Opnd.getImm();
1796 if (Imm < -1 || Imm > 126)
1797 return Error(IDLoc, "immediate operand value out of range");
1798 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001799 case Mips::ADDIUR2_MM:
1800 Opnd = Inst.getOperand(2);
1801 if (!Opnd.isImm())
1802 return Error(IDLoc, "expected immediate operand kind");
1803 Imm = Opnd.getImm();
1804 if (!(Imm == 1 || Imm == -1 ||
1805 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1806 return Error(IDLoc, "immediate operand value out of range");
1807 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001808 case Mips::ANDI16_MM:
1809 Opnd = Inst.getOperand(2);
1810 if (!Opnd.isImm())
1811 return Error(IDLoc, "expected immediate operand kind");
1812 Imm = Opnd.getImm();
1813 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1814 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1815 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1816 return Error(IDLoc, "immediate operand value out of range");
1817 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001818 case Mips::LBU16_MM:
1819 Opnd = Inst.getOperand(2);
1820 if (!Opnd.isImm())
1821 return Error(IDLoc, "expected immediate operand kind");
1822 Imm = Opnd.getImm();
1823 if (Imm < -1 || Imm > 14)
1824 return Error(IDLoc, "immediate operand value out of range");
1825 break;
1826 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001827 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001828 Opnd = Inst.getOperand(2);
1829 if (!Opnd.isImm())
1830 return Error(IDLoc, "expected immediate operand kind");
1831 Imm = Opnd.getImm();
1832 if (Imm < 0 || Imm > 15)
1833 return Error(IDLoc, "immediate operand value out of range");
1834 break;
1835 case Mips::LHU16_MM:
1836 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001837 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001838 Opnd = Inst.getOperand(2);
1839 if (!Opnd.isImm())
1840 return Error(IDLoc, "expected immediate operand kind");
1841 Imm = Opnd.getImm();
1842 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1843 return Error(IDLoc, "immediate operand value out of range");
1844 break;
1845 case Mips::LW16_MM:
1846 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001847 case Mips::SW16_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 > 60 || (Imm % 4 != 0))
1853 return Error(IDLoc, "immediate operand value out of range");
1854 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001855 case Mips::ADDIUPC_MM:
1856 MCOperand Opnd = Inst.getOperand(1);
1857 if (!Opnd.isImm())
1858 return Error(IDLoc, "expected immediate operand kind");
1859 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001860 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001861 return Error(IDLoc, "immediate operand value out of range");
1862 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001863 }
1864 }
1865
Daniel Sandersd8c07762016-04-18 12:35:36 +00001866 bool FillDelaySlot =
1867 MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
1868 if (FillDelaySlot)
Daniel Sandersa736b372016-04-29 13:33:12 +00001869 TOut.emitDirectiveSetNoReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001870
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001871 MacroExpanderResultTy ExpandResult =
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001872 tryExpandInstruction(Inst, IDLoc, Out, STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001873 switch (ExpandResult) {
1874 case MER_NotAMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001875 Out.EmitInstruction(Inst, *STI);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001876 break;
1877 case MER_Success:
1878 break;
1879 case MER_Fail:
1880 return true;
1881 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001882
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001883 // If this instruction has a delay slot and .set reorder is active,
1884 // emit a NOP after it.
Daniel Sandersd8c07762016-04-18 12:35:36 +00001885 if (FillDelaySlot) {
Daniel Sandersa736b372016-04-29 13:33:12 +00001886 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
1887 TOut.emitDirectiveSetReorder();
Daniel Sandersd8c07762016-04-18 12:35:36 +00001888 }
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001889
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001890 if ((Inst.getOpcode() == Mips::JalOneReg ||
1891 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1892 isPicAndNotNxxAbi()) {
1893 if (IsCpRestoreSet) {
1894 // We need a NOP between the JALR and the LW:
1895 // If .set reorder has been used, we've already emitted a NOP.
1896 // If .set noreorder has been used, we need to emit a NOP at this point.
1897 if (!AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00001898 TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
1899 STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001900
1901 // Load the $gp from the stack.
Daniel Sanders7225cd52016-04-29 16:16:49 +00001902 TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001903 } else
1904 Warning(IDLoc, "no .cprestore used in PIC mode");
1905 }
1906
Jack Carter9e65aa32013-03-22 00:05:30 +00001907 return false;
1908}
1909
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001910MipsAsmParser::MacroExpanderResultTy
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001911MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
1912 const MCSubtargetInfo *STI) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001913 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001914 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001915 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001916 case Mips::LoadImm32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001917 return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001918 case Mips::LoadImm64:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001919 return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001920 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001921 case Mips::LoadAddrImm64:
1922 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1923 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1924 "expected immediate operand kind");
1925
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001926 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1927 Inst.getOperand(1),
1928 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001929 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001930 ? MER_Fail
1931 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001932 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001933 case Mips::LoadAddrReg64:
1934 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1935 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1936 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1937 "expected immediate operand kind");
1938
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001939 return expandLoadAddress(Inst.getOperand(0).getReg(),
1940 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1941 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001942 Out, STI)
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001943 ? MER_Fail
1944 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001945 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001946 case Mips::B_MMR6_Pseudo:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001947 return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
1948 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001949 case Mips::SWM_MM:
1950 case Mips::LWM_MM:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001951 return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
1952 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001953 case Mips::JalOneReg:
1954 case Mips::JalTwoReg:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001955 return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00001956 case Mips::BneImm:
1957 case Mips::BeqImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001958 return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00001959 case Mips::BLT:
1960 case Mips::BLE:
1961 case Mips::BGE:
1962 case Mips::BGT:
1963 case Mips::BLTU:
1964 case Mips::BLEU:
1965 case Mips::BGEU:
1966 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001967 case Mips::BLTL:
1968 case Mips::BLEL:
1969 case Mips::BGEL:
1970 case Mips::BGTL:
1971 case Mips::BLTUL:
1972 case Mips::BLEUL:
1973 case Mips::BGEUL:
1974 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00001975 case Mips::BLTImmMacro:
1976 case Mips::BLEImmMacro:
1977 case Mips::BGEImmMacro:
1978 case Mips::BGTImmMacro:
1979 case Mips::BLTUImmMacro:
1980 case Mips::BLEUImmMacro:
1981 case Mips::BGEUImmMacro:
1982 case Mips::BGTUImmMacro:
1983 case Mips::BLTLImmMacro:
1984 case Mips::BLELImmMacro:
1985 case Mips::BGELImmMacro:
1986 case Mips::BGTLImmMacro:
1987 case Mips::BLTULImmMacro:
1988 case Mips::BLEULImmMacro:
1989 case Mips::BGEULImmMacro:
1990 case Mips::BGTULImmMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001991 return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001992 case Mips::SDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001993 return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
1994 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001995 case Mips::DSDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001996 return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
1997 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001998 case Mips::UDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00001999 return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
2000 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002001 case Mips::DUDivMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002002 return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
2003 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002004 case Mips::PseudoTRUNC_W_S:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002005 return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
2006 : MER_Success;
Zoran Jovanovicd665a662016-02-22 16:00:23 +00002007 case Mips::PseudoTRUNC_W_D32:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002008 return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002009 : MER_Success;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002010 case Mips::PseudoTRUNC_W_D:
2011 return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
2012 : MER_Success;
2013 case Mips::Ulh:
2014 return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2015 case Mips::Ulhu:
2016 return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2017 case Mips::Ulw:
2018 return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2019 case Mips::NORImm:
2020 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002021 case Mips::ADDi:
2022 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002023 case Mips::SLTi:
2024 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002025 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2026 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2027 int64_t ImmValue = Inst.getOperand(2).getImm();
2028 if (isInt<16>(ImmValue))
2029 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002030 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2031 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002032 }
2033 return MER_NotAMacro;
2034 case Mips::ANDi:
2035 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002036 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002037 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2038 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2039 int64_t ImmValue = Inst.getOperand(2).getImm();
2040 if (isUInt<16>(ImmValue))
2041 return MER_NotAMacro;
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002042 return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
2043 : MER_Success;
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002044 }
2045 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002046 case Mips::ROL:
2047 case Mips::ROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002048 return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002049 case Mips::ROLImm:
2050 case Mips::RORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002051 return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002052 case Mips::DROL:
2053 case Mips::DROR:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002054 return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002055 case Mips::DROLImm:
2056 case Mips::DRORImm:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002057 return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00002058 case Mips::ABSMacro:
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002059 return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002060 }
Jack Carter30a59822012-10-04 04:03:53 +00002061}
Jack Carter92995f12012-10-06 00:53:28 +00002062
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002063bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002064 MCStreamer &Out,
2065 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002066 MipsTargetStreamer &TOut = getTargetStreamer();
2067
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002068 // Create a JALR instruction which is going to replace the pseudo-JAL.
2069 MCInst JalrInst;
2070 JalrInst.setLoc(IDLoc);
2071 const MCOperand FirstRegOp = Inst.getOperand(0);
2072 const unsigned Opcode = Inst.getOpcode();
2073
2074 if (Opcode == Mips::JalOneReg) {
2075 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002076 if (IsCpRestoreSet && inMicroMipsMode()) {
2077 JalrInst.setOpcode(Mips::JALRS16_MM);
2078 JalrInst.addOperand(FirstRegOp);
2079 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002080 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002081 JalrInst.addOperand(FirstRegOp);
2082 } else {
2083 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002084 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002085 JalrInst.addOperand(FirstRegOp);
2086 }
2087 } else if (Opcode == Mips::JalTwoReg) {
2088 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002089 if (IsCpRestoreSet && inMicroMipsMode())
2090 JalrInst.setOpcode(Mips::JALRS_MM);
2091 else
2092 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002093 JalrInst.addOperand(FirstRegOp);
2094 const MCOperand SecondRegOp = Inst.getOperand(1);
2095 JalrInst.addOperand(SecondRegOp);
2096 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002097 Out.EmitInstruction(JalrInst, *STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002098
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002099 // If .set reorder is active and branch instruction has a delay slot,
2100 // emit a NOP after it.
2101 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
Daniel Sandersa736b372016-04-29 13:33:12 +00002102 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
2103 TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
2104 STI);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002105
2106 return false;
2107}
2108
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002109/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002110template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002111 unsigned BitNum = findFirstSet(x);
2112
2113 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2114}
2115
2116/// Load (or add) an immediate into a register.
2117///
2118/// @param ImmValue The immediate to load.
2119/// @param DstReg The register that will hold the immediate.
2120/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2121/// for a simple initialization.
2122/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2123/// @param IsAddress True if the immediate represents an address. False if it
2124/// is an integer.
2125/// @param IDLoc Location of the immediate in the source file.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002126bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002127 unsigned SrcReg, bool Is32BitImm,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002128 bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
2129 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002130 MipsTargetStreamer &TOut = getTargetStreamer();
2131
Toma Tabacu00e98672015-05-01 12:19:27 +00002132 if (!Is32BitImm && !isGP64bit()) {
2133 Error(IDLoc, "instruction requires a 64-bit architecture");
2134 return true;
2135 }
2136
Daniel Sanders03f9c012015-07-14 12:24:22 +00002137 if (Is32BitImm) {
2138 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2139 // Sign extend up to 64-bit so that the predicates match the hardware
2140 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2141 // true.
2142 ImmValue = SignExtend64<32>(ImmValue);
2143 } else {
2144 Error(IDLoc, "instruction requires a 32-bit immediate");
2145 return true;
2146 }
2147 }
2148
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002149 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2150 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2151
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002152 bool UseSrcReg = false;
2153 if (SrcReg != Mips::NoRegister)
2154 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002155
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002156 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002157 if (UseSrcReg &&
2158 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002159 // At this point we need AT to perform the expansions and we exit if it is
2160 // not available.
2161 unsigned ATReg = getATReg(IDLoc);
2162 if (!ATReg)
2163 return true;
2164 TmpReg = ATReg;
2165 }
2166
Daniel Sanders03f9c012015-07-14 12:24:22 +00002167 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002168 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002169 SrcReg = ZeroReg;
2170
2171 // This doesn't quite follow the usual ABI expectations for N32 but matches
2172 // traditional assembler behaviour. N32 would normally use addiu for both
2173 // integers and addresses.
2174 if (IsAddress && !Is32BitImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002175 TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002176 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002177 }
2178
Daniel Sandersa736b372016-04-29 13:33:12 +00002179 TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002180 return false;
2181 }
2182
2183 if (isUInt<16>(ImmValue)) {
2184 unsigned TmpReg = DstReg;
2185 if (SrcReg == DstReg) {
2186 TmpReg = getATReg(IDLoc);
2187 if (!TmpReg)
2188 return true;
2189 }
2190
Daniel Sandersa736b372016-04-29 13:33:12 +00002191 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002192 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002193 TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002194 return false;
2195 }
2196
2197 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002198 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002199
Toma Tabacu79588102015-04-29 10:19:56 +00002200 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2201 uint16_t Bits15To0 = ImmValue & 0xffff;
2202
Toma Tabacua3d056f2015-05-15 09:42:11 +00002203 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002204 // Traditional behaviour seems to special case this particular value. It's
2205 // not clear why other masks are handled differently.
2206 if (ImmValue == 0xffffffff) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002207 TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
2208 TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002209 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002210 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002211 return false;
2212 }
2213
2214 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002215 // upper 32 bits.
Daniel Sandersa736b372016-04-29 13:33:12 +00002216 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
2217 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002218 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002219 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002220 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002221 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002222 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002223 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002224
Daniel Sandersa736b372016-04-29 13:33:12 +00002225 TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002226 if (Bits15To0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002227 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002228 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002229 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002230 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002231 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002232
2233 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2234 if (Is32BitImm) {
2235 Error(IDLoc, "instruction requires a 32-bit immediate");
2236 return true;
2237 }
2238
2239 // Traditionally, these immediates are shifted as little as possible and as
2240 // such we align the most significant bit to bit 15 of our temporary.
2241 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2242 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2243 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2244 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
Daniel Sandersa736b372016-04-29 13:33:12 +00002245 TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
2246 TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002247
2248 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
2251 return false;
2252 }
2253
2254 warnIfNoMacro(IDLoc);
2255
2256 // The remaining case is packed with a sequence of dsll and ori with zeros
2257 // being omitted and any neighbouring dsll's being coalesced.
2258 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2259
2260 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2261 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002262 IDLoc, Out, STI))
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002263 return false;
2264
2265 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2266 // skip it and defer the shift to the next chunk.
2267 unsigned ShiftCarriedForwards = 16;
2268 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2269 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2270
2271 if (ImmChunk != 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002272 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
2273 TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002274 ShiftCarriedForwards = 0;
2275 }
2276
2277 ShiftCarriedForwards += 16;
2278 }
2279 ShiftCarriedForwards -= 16;
2280
2281 // Finish any remaining shifts left by trailing zeros.
2282 if (ShiftCarriedForwards)
Daniel Sandersa736b372016-04-29 13:33:12 +00002283 TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002284
2285 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002286 TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002287
Matheus Almeida3813d572014-06-19 14:39:14 +00002288 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002289}
Jack Carter92995f12012-10-06 00:53:28 +00002290
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002291bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002292 MCStreamer &Out, const MCSubtargetInfo *STI) {
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002293 const MCOperand &ImmOp = Inst.getOperand(1);
2294 assert(ImmOp.isImm() && "expected immediate operand kind");
2295 const MCOperand &DstRegOp = Inst.getOperand(0);
2296 assert(DstRegOp.isReg() && "expected register operand kind");
2297
2298 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002299 Is32BitImm, false, IDLoc, Out, STI))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002300 return true;
2301
2302 return false;
2303}
2304
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002305bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2306 const MCOperand &Offset,
2307 bool Is32BitAddress, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002308 MCStreamer &Out,
2309 const MCSubtargetInfo *STI) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002310 // la can't produce a usable address when addresses are 64-bit.
2311 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2312 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2313 // We currently can't do this because we depend on the equality
2314 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2315 Error(IDLoc, "la used to load 64-bit address");
2316 // Continue as if we had 'dla' instead.
2317 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002318 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002319
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002320 // dla requires 64-bit addresses.
Scott Egerton24557012016-01-21 15:11:01 +00002321 if (!Is32BitAddress && !hasMips3()) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002322 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002323 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002324 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002325
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002326 if (!Offset.isImm())
2327 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002328 Is32BitAddress, IDLoc, Out, STI);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002329
Scott Egerton24557012016-01-21 15:11:01 +00002330 if (!ABI.ArePtrs64bit()) {
2331 // Continue as if we had 'la' whether we had 'la' or 'dla'.
2332 Is32BitAddress = true;
2333 }
2334
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002335 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002336 IDLoc, Out, STI);
Jack Carter543fdf82012-10-09 23:29:45 +00002337}
2338
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002339bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2340 unsigned DstReg, unsigned SrcReg,
2341 bool Is32BitSym, SMLoc IDLoc,
2342 MCStreamer &Out,
2343 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002344 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacu81496c12015-05-20 08:54:45 +00002345 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002346
Daniel Sandersd5a89412015-10-05 13:19:29 +00002347 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002348 const MipsMCExpr *HiExpr =
2349 MipsMCExpr::create(MipsMCExpr::MEK_HI, Symbol, getContext());
2350 const MipsMCExpr *LoExpr =
2351 MipsMCExpr::create(MipsMCExpr::MEK_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002352
Toma Tabacufb9d1252015-06-22 12:08:39 +00002353 bool UseSrcReg = SrcReg != Mips::NoRegister;
2354
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002355 // This is the 64-bit symbol address expansion.
2356 if (ABI.ArePtrs64bit() && isGP64bit()) {
2357 // We always need AT for the 64-bit expansion.
2358 // If it is not available we exit.
2359 unsigned ATReg = getATReg(IDLoc);
2360 if (!ATReg)
2361 return true;
2362
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002363 const MipsMCExpr *HighestExpr =
2364 MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, Symbol, getContext());
2365 const MipsMCExpr *HigherExpr =
2366 MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002367
Scott Egerton24557012016-01-21 15:11:01 +00002368 if (UseSrcReg &&
2369 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
2370 SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002371 // If $rs is the same as $rd:
2372 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2373 // daddiu $at, $at, %higher(sym)
2374 // dsll $at, $at, 16
2375 // daddiu $at, $at, %hi(sym)
2376 // dsll $at, $at, 16
2377 // daddiu $at, $at, %lo(sym)
2378 // daddu $rd, $at, $rd
Daniel Sandersa736b372016-04-29 13:33:12 +00002379 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2380 STI);
2381 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
2382 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2383 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2384 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
2385 IDLoc, STI);
2386 TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
2387 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2388 IDLoc, STI);
2389 TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002390
2391 return false;
2392 }
2393
2394 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2395 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2396 // lui $at, %hi(sym)
2397 // daddiu $rd, $rd, %higher(sym)
2398 // daddiu $at, $at, %lo(sym)
2399 // dsll32 $rd, $rd, 0
2400 // daddu $rd, $rd, $at
2401 // (daddu $rd, $rd, $rs)
Daniel Sandersa736b372016-04-29 13:33:12 +00002402 TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2403 STI);
2404 TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2405 TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
2406 MCOperand::createExpr(HigherExpr), IDLoc, STI);
2407 TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
2408 IDLoc, STI);
2409 TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
2410 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002411 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002412 TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002413
2414 return false;
2415 }
2416
2417 // And now, the 32-bit symbol address expansion:
2418 // If $rs is the same as $rd:
2419 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2420 // ori $at, $at, %lo(sym)
2421 // addu $rd, $at, $rd
2422 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2423 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2424 // ori $rd, $rd, %lo(sym)
2425 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002426 unsigned TmpReg = DstReg;
Scott Egerton24557012016-01-21 15:11:01 +00002427 if (UseSrcReg &&
2428 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002429 // If $rs is the same as $rd, we need to use AT.
2430 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002431 unsigned ATReg = getATReg(IDLoc);
2432 if (!ATReg)
2433 return true;
2434 TmpReg = ATReg;
2435 }
2436
Daniel Sandersa736b372016-04-29 13:33:12 +00002437 TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
2438 TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
2439 IDLoc, STI);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002440
Toma Tabacufb9d1252015-06-22 12:08:39 +00002441 if (UseSrcReg)
Daniel Sandersa736b372016-04-29 13:33:12 +00002442 TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002443 else
Scott Egerton24557012016-01-21 15:11:01 +00002444 assert(
2445 getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
Toma Tabacuf712ede2015-06-17 14:31:51 +00002446
Toma Tabacu674825c2015-06-16 12:16:24 +00002447 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002448}
2449
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002450bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
2451 MCStreamer &Out,
2452 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002453 MipsTargetStreamer &TOut = getTargetStreamer();
2454
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002455 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2456 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002457
2458 MCOperand Offset = Inst.getOperand(0);
2459 if (Offset.isExpr()) {
2460 Inst.clear();
2461 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002462 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2463 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2464 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002465 } else {
2466 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002467 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002468 // If offset fits into 11 bits then this instruction becomes microMIPS
2469 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002470 if (inMicroMipsMode())
2471 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002472 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002473 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002474 Error(IDLoc, "branch target out of range");
2475 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2476 Error(IDLoc, "branch to misaligned address");
2477 Inst.clear();
2478 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002479 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2480 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2481 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002482 }
2483 }
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002484 Out.EmitInstruction(Inst, *STI);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002485
Zoran Jovanovicada70912015-09-07 11:56:37 +00002486 // If .set reorder is active and branch instruction has a delay slot,
2487 // emit a NOP after it.
2488 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2489 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Daniel Sandersa736b372016-04-29 13:33:12 +00002490 TOut.emitEmptyDelaySlot(true, IDLoc, STI);
Toma Tabacu234482a2015-03-16 12:03:39 +00002491
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002492 return false;
2493}
2494
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002495bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2496 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002497 MipsTargetStreamer &TOut = getTargetStreamer();
Toma Tabacue1e460d2015-06-11 10:36:10 +00002498 const MCOperand &DstRegOp = Inst.getOperand(0);
2499 assert(DstRegOp.isReg() && "expected register operand kind");
2500
2501 const MCOperand &ImmOp = Inst.getOperand(1);
2502 assert(ImmOp.isImm() && "expected immediate operand kind");
2503
2504 const MCOperand &MemOffsetOp = Inst.getOperand(2);
Daniel Sanders90f0d0b2016-02-29 11:24:49 +00002505 assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
2506 "expected immediate or expression operand");
Toma Tabacue1e460d2015-06-11 10:36:10 +00002507
2508 unsigned OpCode = 0;
2509 switch(Inst.getOpcode()) {
2510 case Mips::BneImm:
2511 OpCode = Mips::BNE;
2512 break;
2513 case Mips::BeqImm:
2514 OpCode = Mips::BEQ;
2515 break;
2516 default:
2517 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2518 break;
2519 }
2520
2521 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002522 if (ImmValue == 0)
Daniel Sandersa736b372016-04-29 13:33:12 +00002523 TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2524 STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002525 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002526 warnIfNoMacro(IDLoc);
2527
2528 unsigned ATReg = getATReg(IDLoc);
2529 if (!ATReg)
2530 return true;
2531
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002532 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002533 IDLoc, Out, STI))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002534 return true;
2535
Daniel Sandersa736b372016-04-29 13:33:12 +00002536 TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002537 }
2538 return false;
2539}
2540
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002541void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
Daniel Sandersfba875f2016-04-29 13:43:45 +00002542 const MCSubtargetInfo *STI, bool IsLoad,
2543 bool IsImmOpnd) {
2544 if (IsLoad) {
2545 expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2546 return;
Scott Egertond65377d2016-03-17 10:37:51 +00002547 }
Daniel Sandersfba875f2016-04-29 13:43:45 +00002548 expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2549}
2550
2551void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2552 const MCSubtargetInfo *STI, bool IsImmOpnd) {
2553 MipsTargetStreamer &TOut = getTargetStreamer();
2554
2555 unsigned DstReg = Inst.getOperand(0).getReg();
2556 unsigned BaseReg = Inst.getOperand(1).getReg();
2557
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002558 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
Daniel Sandersfba875f2016-04-29 13:43:45 +00002559 int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2560 unsigned DstRegClassID =
2561 getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2562 bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2563 (DstRegClassID == Mips::GPR64RegClassID);
2564
2565 if (IsImmOpnd) {
2566 // Try to use DstReg as the temporary.
2567 if (IsGPR && (BaseReg != DstReg)) {
2568 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2569 Inst.getOperand(2).getImm(), DstReg, IDLoc,
2570 STI);
2571 return;
2572 }
2573
Matheus Almeida7de68e72014-06-18 14:46:05 +00002574 // At this point we need AT to perform the expansions and we exit if it is
2575 // not available.
Daniel Sandersfba875f2016-04-29 13:43:45 +00002576 unsigned ATReg = getATReg(IDLoc);
2577 if (!ATReg)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002578 return;
Daniel Sandersfba875f2016-04-29 13:43:45 +00002579
2580 TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2581 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2582 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002583 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002584
Daniel Sandersfba875f2016-04-29 13:43:45 +00002585 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002586 MCOperand LoOperand = MCOperand::createExpr(
2587 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2588 MCOperand HiOperand = MCOperand::createExpr(
2589 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002590
2591 // Try to use DstReg as the temporary.
2592 if (IsGPR && (BaseReg != DstReg)) {
2593 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2594 LoOperand, DstReg, IDLoc, STI);
2595 return;
2596 }
2597
2598 // At this point we need AT to perform the expansions and we exit if it is
2599 // not available.
2600 unsigned ATReg = getATReg(IDLoc);
2601 if (!ATReg)
2602 return;
2603
2604 TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2605 LoOperand, ATReg, IDLoc, STI);
2606}
2607
2608void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2609 const MCSubtargetInfo *STI,
2610 bool IsImmOpnd) {
2611 MipsTargetStreamer &TOut = getTargetStreamer();
2612
2613 unsigned SrcReg = Inst.getOperand(0).getReg();
2614 unsigned BaseReg = Inst.getOperand(1).getReg();
2615
2616 unsigned ATReg = getATReg(IDLoc);
2617 if (!ATReg)
2618 return;
2619
2620 if (IsImmOpnd) {
2621 TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2622 Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2623 return;
2624 }
2625
2626 const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00002627 MCOperand LoOperand = MCOperand::createExpr(
2628 MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
2629 MCOperand HiOperand = MCOperand::createExpr(
2630 MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
Daniel Sandersfba875f2016-04-29 13:43:45 +00002631 TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2632 LoOperand, ATReg, IDLoc, STI);
Jack Carter9e65aa32013-03-22 00:05:30 +00002633}
2634
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002635bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2636 MCStreamer &Out,
2637 const MCSubtargetInfo *STI) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002638 unsigned OpNum = Inst.getNumOperands();
2639 unsigned Opcode = Inst.getOpcode();
2640 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2641
2642 assert (Inst.getOperand(OpNum - 1).isImm() &&
2643 Inst.getOperand(OpNum - 2).isReg() &&
2644 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2645
2646 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2647 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002648 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2649 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2650 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2651 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002652 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002653 if (inMicroMipsMode() && hasMips32r6())
2654 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2655 else
2656 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2657 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002658
2659 Inst.setOpcode(NewOpcode);
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002660 Out.EmitInstruction(Inst, *STI);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002661 return false;
2662}
2663
Toma Tabacu1a108322015-06-17 13:20:24 +00002664bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002665 MCStreamer &Out,
2666 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002667 MipsTargetStreamer &TOut = getTargetStreamer();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002668 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002669 unsigned PseudoOpcode = Inst.getOpcode();
2670 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002671 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002672 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2673
2674 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002675 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002676
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002677 unsigned TrgReg;
2678 if (TrgOp.isReg())
2679 TrgReg = TrgOp.getReg();
2680 else if (TrgOp.isImm()) {
2681 warnIfNoMacro(IDLoc);
2682 EmittedNoMacroWarning = true;
2683
2684 TrgReg = getATReg(IDLoc);
2685 if (!TrgReg)
2686 return true;
2687
2688 switch(PseudoOpcode) {
2689 default:
2690 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2691 case Mips::BLTImmMacro:
2692 PseudoOpcode = Mips::BLT;
2693 break;
2694 case Mips::BLEImmMacro:
2695 PseudoOpcode = Mips::BLE;
2696 break;
2697 case Mips::BGEImmMacro:
2698 PseudoOpcode = Mips::BGE;
2699 break;
2700 case Mips::BGTImmMacro:
2701 PseudoOpcode = Mips::BGT;
2702 break;
2703 case Mips::BLTUImmMacro:
2704 PseudoOpcode = Mips::BLTU;
2705 break;
2706 case Mips::BLEUImmMacro:
2707 PseudoOpcode = Mips::BLEU;
2708 break;
2709 case Mips::BGEUImmMacro:
2710 PseudoOpcode = Mips::BGEU;
2711 break;
2712 case Mips::BGTUImmMacro:
2713 PseudoOpcode = Mips::BGTU;
2714 break;
2715 case Mips::BLTLImmMacro:
2716 PseudoOpcode = Mips::BLTL;
2717 break;
2718 case Mips::BLELImmMacro:
2719 PseudoOpcode = Mips::BLEL;
2720 break;
2721 case Mips::BGELImmMacro:
2722 PseudoOpcode = Mips::BGEL;
2723 break;
2724 case Mips::BGTLImmMacro:
2725 PseudoOpcode = Mips::BGTL;
2726 break;
2727 case Mips::BLTULImmMacro:
2728 PseudoOpcode = Mips::BLTUL;
2729 break;
2730 case Mips::BLEULImmMacro:
2731 PseudoOpcode = Mips::BLEUL;
2732 break;
2733 case Mips::BGEULImmMacro:
2734 PseudoOpcode = Mips::BGEUL;
2735 break;
2736 case Mips::BGTULImmMacro:
2737 PseudoOpcode = Mips::BGTUL;
2738 break;
2739 }
2740
2741 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002742 false, IDLoc, Out, STI))
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002743 return true;
2744 }
2745
Toma Tabacu1a108322015-06-17 13:20:24 +00002746 switch (PseudoOpcode) {
2747 case Mips::BLT:
2748 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002749 case Mips::BLTL:
2750 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002751 AcceptsEquality = false;
2752 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002753 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2754 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002755 ZeroSrcOpcode = Mips::BGTZ;
2756 ZeroTrgOpcode = Mips::BLTZ;
2757 break;
2758 case Mips::BLE:
2759 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002760 case Mips::BLEL:
2761 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002762 AcceptsEquality = true;
2763 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002764 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2765 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002766 ZeroSrcOpcode = Mips::BGEZ;
2767 ZeroTrgOpcode = Mips::BLEZ;
2768 break;
2769 case Mips::BGE:
2770 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002771 case Mips::BGEL:
2772 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002773 AcceptsEquality = true;
2774 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002775 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2776 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002777 ZeroSrcOpcode = Mips::BLEZ;
2778 ZeroTrgOpcode = Mips::BGEZ;
2779 break;
2780 case Mips::BGT:
2781 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002782 case Mips::BGTL:
2783 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002784 AcceptsEquality = false;
2785 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002786 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2787 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002788 ZeroSrcOpcode = Mips::BLTZ;
2789 ZeroTrgOpcode = Mips::BGTZ;
2790 break;
2791 default:
2792 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2793 }
2794
Toma Tabacu1a108322015-06-17 13:20:24 +00002795 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2796 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2797 if (IsSrcRegZero && IsTrgRegZero) {
2798 // FIXME: All of these Opcode-specific if's are needed for compatibility
2799 // with GAS' behaviour. However, they may not generate the most efficient
2800 // code in some circumstances.
2801 if (PseudoOpcode == Mips::BLT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002802 TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2803 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002804 return false;
2805 }
2806 if (PseudoOpcode == Mips::BLE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002807 TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2808 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002809 Warning(IDLoc, "branch is always taken");
2810 return false;
2811 }
2812 if (PseudoOpcode == Mips::BGE) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002813 TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2814 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002815 Warning(IDLoc, "branch is always taken");
2816 return false;
2817 }
2818 if (PseudoOpcode == Mips::BGT) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002819 TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
2820 IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002821 return false;
2822 }
2823 if (PseudoOpcode == Mips::BGTU) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002824 TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2825 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002826 return false;
2827 }
2828 if (AcceptsEquality) {
2829 // If both registers are $0 and the pseudo-branch accepts equality, it
2830 // will always be taken, so we emit an unconditional branch.
Daniel Sandersa736b372016-04-29 13:33:12 +00002831 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2832 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002833 Warning(IDLoc, "branch is always taken");
2834 return false;
2835 }
2836 // If both registers are $0 and the pseudo-branch does not accept
2837 // equality, it will never be taken, so we don't have to emit anything.
2838 return false;
2839 }
2840 if (IsSrcRegZero || IsTrgRegZero) {
2841 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2842 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2843 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2844 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2845 // the pseudo-branch will never be taken, so we don't emit anything.
2846 // This only applies to unsigned pseudo-branches.
2847 return false;
2848 }
2849 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2850 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2851 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2852 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2853 // the pseudo-branch will always be taken, so we emit an unconditional
2854 // branch.
2855 // This only applies to unsigned pseudo-branches.
Daniel Sandersa736b372016-04-29 13:33:12 +00002856 TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2857 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002858 Warning(IDLoc, "branch is always taken");
2859 return false;
2860 }
2861 if (IsUnsigned) {
2862 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2863 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2864 // the pseudo-branch will be taken only when the non-zero register is
2865 // different from 0, so we emit a BNEZ.
2866 //
2867 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2868 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2869 // the pseudo-branch will be taken only when the non-zero register is
2870 // equal to 0, so we emit a BEQZ.
2871 //
2872 // Because only BLEU and BGEU branch on equality, we can use the
2873 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sandersa736b372016-04-29 13:33:12 +00002874 TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2875 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2876 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002877 return false;
2878 }
2879 // If we have a signed pseudo-branch and one of the registers is $0,
2880 // we can use an appropriate compare-to-zero branch. We select which one
2881 // to use in the switch statement above.
Daniel Sandersa736b372016-04-29 13:33:12 +00002882 TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2883 IsSrcRegZero ? TrgReg : SrcReg,
2884 MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002885 return false;
2886 }
2887
2888 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2889 // expansions. If it is not available, we return.
2890 unsigned ATRegNum = getATReg(IDLoc);
2891 if (!ATRegNum)
2892 return true;
2893
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002894 if (!EmittedNoMacroWarning)
2895 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002896
2897 // SLT fits well with 2 of our 4 pseudo-branches:
2898 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2899 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2900 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2901 // This is accomplished by using a BNEZ with the result of the SLT.
2902 //
2903 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2904 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2905 // Because only BGE and BLE branch on equality, we can use the
2906 // AcceptsEquality variable to decide when to emit the BEQZ.
2907 // Note that the order of the SLT arguments doesn't change between
2908 // opposites.
2909 //
2910 // The same applies to the unsigned variants, except that SLTu is used
2911 // instead of SLT.
Daniel Sandersa736b372016-04-29 13:33:12 +00002912 TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2913 ReverseOrderSLT ? TrgReg : SrcReg,
2914 ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002915
Daniel Sandersa736b372016-04-29 13:33:12 +00002916 TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2917 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2918 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2919 STI);
Toma Tabacu1a108322015-06-17 13:20:24 +00002920 return false;
2921}
2922
Daniel Sandersc6924fa2016-04-18 12:06:15 +00002923bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2924 const MCSubtargetInfo *STI, const bool IsMips64,
2925 const bool Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002926 MipsTargetStreamer &TOut = getTargetStreamer();
2927
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002928 if (hasMips32r6()) {
2929 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2930 return false;
2931 }
2932
2933 warnIfNoMacro(IDLoc);
2934
2935 const MCOperand &RsRegOp = Inst.getOperand(0);
2936 assert(RsRegOp.isReg() && "expected register operand kind");
2937 unsigned RsReg = RsRegOp.getReg();
2938
2939 const MCOperand &RtRegOp = Inst.getOperand(1);
2940 assert(RtRegOp.isReg() && "expected register operand kind");
2941 unsigned RtReg = RtRegOp.getReg();
2942 unsigned DivOp;
2943 unsigned ZeroReg;
2944
2945 if (IsMips64) {
2946 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2947 ZeroReg = Mips::ZERO_64;
2948 } else {
2949 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2950 ZeroReg = Mips::ZERO;
2951 }
2952
2953 bool UseTraps = useTraps();
2954
2955 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2956 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2957 Warning(IDLoc, "dividing zero by zero");
2958 if (IsMips64) {
2959 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2960 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002961 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002962 return false;
2963 }
2964
Daniel Sandersa736b372016-04-29 13:33:12 +00002965 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002966 return false;
2967 }
2968 } else {
Daniel Sandersa736b372016-04-29 13:33:12 +00002969 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002970 return false;
2971 }
2972 }
2973
2974 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2975 Warning(IDLoc, "division by zero");
2976 if (Signed) {
2977 if (UseTraps) {
Daniel Sandersa736b372016-04-29 13:33:12 +00002978 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002979 return false;
2980 }
2981
Daniel Sandersa736b372016-04-29 13:33:12 +00002982 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002983 return false;
2984 }
2985 }
2986
2987 // FIXME: The values for these two BranchTarget variables may be different in
2988 // micromips. These magic numbers need to be removed.
2989 unsigned BranchTargetNoTraps;
2990 unsigned BranchTarget;
2991
2992 if (UseTraps) {
2993 BranchTarget = IsMips64 ? 12 : 8;
Daniel Sandersa736b372016-04-29 13:33:12 +00002994 TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002995 } else {
2996 BranchTarget = IsMips64 ? 20 : 16;
2997 BranchTargetNoTraps = 8;
2998 // Branch to the li instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00002999 TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003000 }
3001
Daniel Sandersa736b372016-04-29 13:33:12 +00003002 TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003003
3004 if (!UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003005 TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003006
3007 if (!Signed) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003008 TOut.emitR(Mips::MFLO, RsReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003009 return false;
3010 }
3011
3012 unsigned ATReg = getATReg(IDLoc);
3013 if (!ATReg)
3014 return true;
3015
Daniel Sandersa736b372016-04-29 13:33:12 +00003016 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003017 if (IsMips64) {
3018 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003019 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3020 TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
3021 TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003022 } else {
3023 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003024 TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
3025 TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003026 }
3027
3028 if (UseTraps)
Daniel Sandersa736b372016-04-29 13:33:12 +00003029 TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003030 else {
3031 // Branch to the mflo instruction.
Daniel Sandersa736b372016-04-29 13:33:12 +00003032 TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
3033 TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
3034 TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003035 }
Daniel Sandersa736b372016-04-29 13:33:12 +00003036 TOut.emitR(Mips::MFLO, RsReg, IDLoc, STI);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00003037 return false;
3038}
3039
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003040bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003041 SMLoc IDLoc, MCStreamer &Out,
3042 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003043 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003044
3045 assert(Inst.getNumOperands() == 3 && "Invalid operand count");
3046 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
3047 Inst.getOperand(2).isReg() && "Invalid instruction operand.");
3048
3049 unsigned FirstReg = Inst.getOperand(0).getReg();
3050 unsigned SecondReg = Inst.getOperand(1).getReg();
3051 unsigned ThirdReg = Inst.getOperand(2).getReg();
3052
3053 if (hasMips1() && !hasMips2()) {
3054 unsigned ATReg = getATReg(IDLoc);
3055 if (!ATReg)
3056 return true;
Daniel Sandersa736b372016-04-29 13:33:12 +00003057 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3058 TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
3059 TOut.emitNop(IDLoc, STI);
3060 TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
3061 TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
3062 TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
3063 TOut.emitNop(IDLoc, STI);
3064 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
3065 : Mips::CVT_W_S,
3066 FirstReg, SecondReg, IDLoc, STI);
3067 TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
3068 TOut.emitNop(IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003069 return false;
3070 }
3071
Daniel Sandersa736b372016-04-29 13:33:12 +00003072 TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
3073 : Mips::TRUNC_W_S,
3074 FirstReg, SecondReg, IDLoc, STI);
Zoran Jovanovicd665a662016-02-22 16:00:23 +00003075
3076 return false;
3077}
3078
Daniel Sanders6394ee52015-10-15 14:52:58 +00003079bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003080 MCStreamer &Out, const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003081 MipsTargetStreamer &TOut = getTargetStreamer();
3082
Toma Tabacud88d79c2015-06-23 14:39:42 +00003083 if (hasMips32r6() || hasMips64r6()) {
3084 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3085 return false;
3086 }
3087
3088 warnIfNoMacro(IDLoc);
3089
3090 const MCOperand &DstRegOp = Inst.getOperand(0);
3091 assert(DstRegOp.isReg() && "expected register operand kind");
3092
3093 const MCOperand &SrcRegOp = Inst.getOperand(1);
3094 assert(SrcRegOp.isReg() && "expected register operand kind");
3095
3096 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3097 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3098
3099 unsigned DstReg = DstRegOp.getReg();
3100 unsigned SrcReg = SrcRegOp.getReg();
3101 int64_t OffsetValue = OffsetImmOp.getImm();
3102
3103 // NOTE: We always need AT for ULHU, as it is always used as the source
3104 // register for one of the LBu's.
3105 unsigned ATReg = getATReg(IDLoc);
3106 if (!ATReg)
3107 return true;
3108
3109 // When the value of offset+1 does not fit in 16 bits, we have to load the
3110 // offset in AT, (D)ADDu the original source register (if there was one), and
3111 // then use AT as the source register for the 2 generated LBu's.
3112 bool LoadedOffsetInAT = false;
3113 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3114 LoadedOffsetInAT = true;
3115
3116 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003117 true, IDLoc, Out, STI))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003118 return true;
3119
3120 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3121 // because it will make our output more similar to GAS'. For example,
3122 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3123 // instead of just an "ori $1, $9, 32768".
3124 // NOTE: If there is no source register specified in the ULHU, the parser
3125 // will interpret it as $0.
3126 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003127 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003128 }
3129
3130 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3131 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3132 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3133
3134 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3135 if (isLittle()) {
3136 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3137 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3138 } else {
3139 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3140 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3141 }
3142
3143 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3144
Daniel Sandersa736b372016-04-29 13:33:12 +00003145 TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3146 FirstLbuOffset, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003147
Daniel Sandersa736b372016-04-29 13:33:12 +00003148 TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3149 STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003150
Daniel Sandersa736b372016-04-29 13:33:12 +00003151 TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003152
Daniel Sandersa736b372016-04-29 13:33:12 +00003153 TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003154
3155 return false;
3156}
3157
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003158bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3159 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003160 MipsTargetStreamer &TOut = getTargetStreamer();
3161
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003162 if (hasMips32r6() || hasMips64r6()) {
3163 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3164 return false;
3165 }
3166
3167 const MCOperand &DstRegOp = Inst.getOperand(0);
3168 assert(DstRegOp.isReg() && "expected register operand kind");
3169
3170 const MCOperand &SrcRegOp = Inst.getOperand(1);
3171 assert(SrcRegOp.isReg() && "expected register operand kind");
3172
3173 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3174 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3175
3176 unsigned SrcReg = SrcRegOp.getReg();
3177 int64_t OffsetValue = OffsetImmOp.getImm();
3178 unsigned ATReg = 0;
3179
3180 // When the value of offset+3 does not fit in 16 bits, we have to load the
3181 // offset in AT, (D)ADDu the original source register (if there was one), and
3182 // then use AT as the source register for the generated LWL and LWR.
3183 bool LoadedOffsetInAT = false;
3184 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3185 ATReg = getATReg(IDLoc);
3186 if (!ATReg)
3187 return true;
3188 LoadedOffsetInAT = true;
3189
3190 warnIfNoMacro(IDLoc);
3191
3192 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003193 true, IDLoc, Out, STI))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003194 return true;
3195
3196 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3197 // because it will make our output more similar to GAS'. For example,
3198 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3199 // instead of just an "ori $1, $9, 32768".
3200 // NOTE: If there is no source register specified in the ULW, the parser
3201 // will interpret it as $0.
3202 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
Daniel Sandersa736b372016-04-29 13:33:12 +00003203 TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003204 }
3205
3206 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3207 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3208 if (isLittle()) {
3209 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3210 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3211 } else {
3212 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3213 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3214 }
3215
Daniel Sandersa736b372016-04-29 13:33:12 +00003216 TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3217 STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003218
Daniel Sandersa736b372016-04-29 13:33:12 +00003219 TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
3220 IDLoc, STI);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003221
3222 return false;
3223}
3224
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003225bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003226 MCStreamer &Out,
3227 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003228 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003229
3230 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3231 assert (Inst.getOperand(0).isReg() &&
3232 Inst.getOperand(1).isReg() &&
3233 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3234
3235 unsigned ATReg = Mips::NoRegister;
3236 unsigned FinalDstReg = Mips::NoRegister;
3237 unsigned DstReg = Inst.getOperand(0).getReg();
3238 unsigned SrcReg = Inst.getOperand(1).getReg();
3239 int64_t ImmValue = Inst.getOperand(2).getImm();
3240
3241 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3242
3243 unsigned FinalOpcode = Inst.getOpcode();
3244
3245 if (DstReg == SrcReg) {
3246 ATReg = getATReg(Inst.getLoc());
3247 if (!ATReg)
3248 return true;
3249 FinalDstReg = DstReg;
3250 DstReg = ATReg;
3251 }
3252
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003253 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003254 switch (FinalOpcode) {
3255 default:
3256 llvm_unreachable("unimplemented expansion");
3257 case (Mips::ADDi):
3258 FinalOpcode = Mips::ADD;
3259 break;
3260 case (Mips::ADDiu):
3261 FinalOpcode = Mips::ADDu;
3262 break;
3263 case (Mips::ANDi):
3264 FinalOpcode = Mips::AND;
3265 break;
3266 case (Mips::NORImm):
3267 FinalOpcode = Mips::NOR;
3268 break;
3269 case (Mips::ORi):
3270 FinalOpcode = Mips::OR;
3271 break;
3272 case (Mips::SLTi):
3273 FinalOpcode = Mips::SLT;
3274 break;
3275 case (Mips::SLTiu):
3276 FinalOpcode = Mips::SLTu;
3277 break;
3278 case (Mips::XORi):
3279 FinalOpcode = Mips::XOR;
3280 break;
3281 }
3282
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003283 if (FinalDstReg == Mips::NoRegister)
Daniel Sandersa736b372016-04-29 13:33:12 +00003284 TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003285 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003286 TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003287 return false;
3288 }
3289 return true;
3290}
3291
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003292bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3293 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003294 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003295 unsigned ATReg = Mips::NoRegister;
3296 unsigned DReg = Inst.getOperand(0).getReg();
3297 unsigned SReg = Inst.getOperand(1).getReg();
3298 unsigned TReg = Inst.getOperand(2).getReg();
3299 unsigned TmpReg = DReg;
3300
3301 unsigned FirstShift = Mips::NOP;
3302 unsigned SecondShift = Mips::NOP;
3303
3304 if (hasMips32r2()) {
3305
3306 if (DReg == SReg) {
3307 TmpReg = getATReg(Inst.getLoc());
3308 if (!TmpReg)
3309 return true;
3310 }
3311
3312 if (Inst.getOpcode() == Mips::ROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003313 TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3314 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003315 return false;
3316 }
3317
3318 if (Inst.getOpcode() == Mips::ROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003319 TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003320 return false;
3321 }
3322
3323 return true;
3324 }
3325
3326 if (hasMips32()) {
3327
3328 switch (Inst.getOpcode()) {
3329 default:
3330 llvm_unreachable("unexpected instruction opcode");
3331 case Mips::ROL:
3332 FirstShift = Mips::SRLV;
3333 SecondShift = Mips::SLLV;
3334 break;
3335 case Mips::ROR:
3336 FirstShift = Mips::SLLV;
3337 SecondShift = Mips::SRLV;
3338 break;
3339 }
3340
3341 ATReg = getATReg(Inst.getLoc());
3342 if (!ATReg)
3343 return true;
3344
Daniel Sandersa736b372016-04-29 13:33:12 +00003345 TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3346 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3347 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3348 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003349
3350 return false;
3351 }
3352
3353 return true;
3354}
3355
3356bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003357 MCStreamer &Out,
3358 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003359 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003360 unsigned ATReg = Mips::NoRegister;
3361 unsigned DReg = Inst.getOperand(0).getReg();
3362 unsigned SReg = Inst.getOperand(1).getReg();
3363 int64_t ImmValue = Inst.getOperand(2).getImm();
3364
3365 unsigned FirstShift = Mips::NOP;
3366 unsigned SecondShift = Mips::NOP;
3367
3368 if (hasMips32r2()) {
3369
3370 if (Inst.getOpcode() == Mips::ROLImm) {
3371 uint64_t MaxShift = 32;
3372 uint64_t ShiftValue = ImmValue;
3373 if (ImmValue != 0)
3374 ShiftValue = MaxShift - ImmValue;
Daniel Sandersa736b372016-04-29 13:33:12 +00003375 TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003376 return false;
3377 }
3378
3379 if (Inst.getOpcode() == Mips::RORImm) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003380 TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003381 return false;
3382 }
3383
3384 return true;
3385 }
3386
3387 if (hasMips32()) {
3388
3389 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003390 TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003391 return false;
3392 }
3393
3394 switch (Inst.getOpcode()) {
3395 default:
3396 llvm_unreachable("unexpected instruction opcode");
3397 case Mips::ROLImm:
3398 FirstShift = Mips::SLL;
3399 SecondShift = Mips::SRL;
3400 break;
3401 case Mips::RORImm:
3402 FirstShift = Mips::SRL;
3403 SecondShift = Mips::SLL;
3404 break;
3405 }
3406
3407 ATReg = getATReg(Inst.getLoc());
3408 if (!ATReg)
3409 return true;
3410
Daniel Sandersa736b372016-04-29 13:33:12 +00003411 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
3412 TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
3413 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003414
3415 return false;
3416 }
3417
3418 return true;
3419}
3420
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003421bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3422 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003423 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003424 unsigned ATReg = Mips::NoRegister;
3425 unsigned DReg = Inst.getOperand(0).getReg();
3426 unsigned SReg = Inst.getOperand(1).getReg();
3427 unsigned TReg = Inst.getOperand(2).getReg();
3428 unsigned TmpReg = DReg;
3429
3430 unsigned FirstShift = Mips::NOP;
3431 unsigned SecondShift = Mips::NOP;
3432
3433 if (hasMips64r2()) {
3434
3435 if (TmpReg == SReg) {
3436 TmpReg = getATReg(Inst.getLoc());
3437 if (!TmpReg)
3438 return true;
3439 }
3440
3441 if (Inst.getOpcode() == Mips::DROL) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003442 TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3443 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003444 return false;
3445 }
3446
3447 if (Inst.getOpcode() == Mips::DROR) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003448 TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003449 return false;
3450 }
3451
3452 return true;
3453 }
3454
3455 if (hasMips64()) {
3456
3457 switch (Inst.getOpcode()) {
3458 default:
3459 llvm_unreachable("unexpected instruction opcode");
3460 case Mips::DROL:
3461 FirstShift = Mips::DSRLV;
3462 SecondShift = Mips::DSLLV;
3463 break;
3464 case Mips::DROR:
3465 FirstShift = Mips::DSLLV;
3466 SecondShift = Mips::DSRLV;
3467 break;
3468 }
3469
3470 ATReg = getATReg(Inst.getLoc());
3471 if (!ATReg)
3472 return true;
3473
Daniel Sandersa736b372016-04-29 13:33:12 +00003474 TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
3475 TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
3476 TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
3477 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003478
3479 return false;
3480 }
3481
3482 return true;
3483}
3484
3485bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003486 MCStreamer &Out,
3487 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003488 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003489 unsigned ATReg = Mips::NoRegister;
3490 unsigned DReg = Inst.getOperand(0).getReg();
3491 unsigned SReg = Inst.getOperand(1).getReg();
3492 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3493
3494 unsigned FirstShift = Mips::NOP;
3495 unsigned SecondShift = Mips::NOP;
3496
3497 MCInst TmpInst;
3498
3499 if (hasMips64r2()) {
3500
3501 unsigned FinalOpcode = Mips::NOP;
3502 if (ImmValue == 0)
3503 FinalOpcode = Mips::DROTR;
3504 else if (ImmValue % 32 == 0)
3505 FinalOpcode = Mips::DROTR32;
3506 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3507 if (Inst.getOpcode() == Mips::DROLImm)
3508 FinalOpcode = Mips::DROTR32;
3509 else
3510 FinalOpcode = Mips::DROTR;
3511 } else if (ImmValue >= 33) {
3512 if (Inst.getOpcode() == Mips::DROLImm)
3513 FinalOpcode = Mips::DROTR;
3514 else
3515 FinalOpcode = Mips::DROTR32;
3516 }
3517
3518 uint64_t ShiftValue = ImmValue % 32;
3519 if (Inst.getOpcode() == Mips::DROLImm)
3520 ShiftValue = (32 - ImmValue % 32) % 32;
3521
Daniel Sandersa736b372016-04-29 13:33:12 +00003522 TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003523
3524 return false;
3525 }
3526
3527 if (hasMips64()) {
3528
3529 if (ImmValue == 0) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003530 TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003531 return false;
3532 }
3533
3534 switch (Inst.getOpcode()) {
3535 default:
3536 llvm_unreachable("unexpected instruction opcode");
3537 case Mips::DROLImm:
3538 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3539 FirstShift = Mips::DSLL;
3540 SecondShift = Mips::DSRL32;
3541 }
3542 if (ImmValue == 32) {
3543 FirstShift = Mips::DSLL32;
3544 SecondShift = Mips::DSRL32;
3545 }
3546 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3547 FirstShift = Mips::DSLL32;
3548 SecondShift = Mips::DSRL;
3549 }
3550 break;
3551 case Mips::DRORImm:
3552 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3553 FirstShift = Mips::DSRL;
3554 SecondShift = Mips::DSLL32;
3555 }
3556 if (ImmValue == 32) {
3557 FirstShift = Mips::DSRL32;
3558 SecondShift = Mips::DSLL32;
3559 }
3560 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3561 FirstShift = Mips::DSRL32;
3562 SecondShift = Mips::DSLL;
3563 }
3564 break;
3565 }
3566
3567 ATReg = getATReg(Inst.getLoc());
3568 if (!ATReg)
3569 return true;
3570
Daniel Sandersa736b372016-04-29 13:33:12 +00003571 TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
3572 TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
3573 Inst.getLoc(), STI);
3574 TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003575
3576 return false;
3577 }
3578
3579 return true;
3580}
3581
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003582bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3583 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003584 MipsTargetStreamer &TOut = getTargetStreamer();
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003585 unsigned FirstRegOp = Inst.getOperand(0).getReg();
3586 unsigned SecondRegOp = Inst.getOperand(1).getReg();
3587
Daniel Sandersa736b372016-04-29 13:33:12 +00003588 TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003589 if (FirstRegOp != SecondRegOp)
Daniel Sandersa736b372016-04-29 13:33:12 +00003590 TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003591 else
Daniel Sandersa736b372016-04-29 13:33:12 +00003592 TOut.emitEmptyDelaySlot(false, IDLoc, STI);
3593 TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
Zoran Jovanovicd474ef32016-01-29 16:18:34 +00003594
3595 return false;
3596}
3597
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003598void MipsAsmParser::createCpRestoreMemOp(bool IsLoad, int StackOffset,
3599 SMLoc IDLoc, MCStreamer &Out,
3600 const MCSubtargetInfo *STI) {
Daniel Sandersa736b372016-04-29 13:33:12 +00003601 MipsTargetStreamer &TOut = getTargetStreamer();
3602
Daniel Sanders7225cd52016-04-29 16:16:49 +00003603 if (IsLoad) {
3604 TOut.emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, StackOffset,
3605 Mips::GP, IDLoc, STI);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003606 return;
3607 }
3608
Daniel Sanders7225cd52016-04-29 16:16:49 +00003609 unsigned ATReg = getATReg(IDLoc);
3610 if (!ATReg)
3611 return;
3612
3613 TOut.emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, StackOffset, ATReg,
3614 IDLoc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003615}
3616
Matheus Almeida595fcab2014-06-11 15:05:56 +00003617unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3618 // As described by the Mips32r2 spec, the registers Rd and Rs for
3619 // jalr.hb must be different.
Zlatko Buljanae720db2016-04-22 06:44:34 +00003620 // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
Matheus Almeida595fcab2014-06-11 15:05:56 +00003621 unsigned Opcode = Inst.getOpcode();
3622
Zlatko Buljanae720db2016-04-22 06:44:34 +00003623 if ((Opcode == Mips::JALR_HB || Opcode == Mips::JALRC_HB_MMR6) &&
Matheus Almeida595fcab2014-06-11 15:05:56 +00003624 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3625 return Match_RequiresDifferentSrcAndDst;
3626
3627 return Match_Success;
3628}
3629
Daniel Sanders52da7af2015-11-06 12:11:03 +00003630static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3631 uint64_t ErrorInfo) {
3632 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3633 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3634 if (ErrorLoc == SMLoc())
3635 return Loc;
3636 return ErrorLoc;
3637 }
3638 return Loc;
3639}
3640
David Blaikie960ea3f2014-06-08 16:18:35 +00003641bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3642 OperandVector &Operands,
3643 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003644 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003645 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003646
Jack Carterb4dbc172012-09-05 23:34:03 +00003647 MCInst Inst;
Vladimir Medic4c299852013-11-06 11:27:05 +00003648 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003649 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003650
3651 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003652 case Match_Success: {
Daniel Sandersc6924fa2016-04-18 12:06:15 +00003653 if (processInstruction(Inst, IDLoc, Out, STI))
Jack Carter9e65aa32013-03-22 00:05:30 +00003654 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003655 return false;
3656 }
3657 case Match_MissingFeature:
3658 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3659 return true;
3660 case Match_InvalidOperand: {
3661 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003662 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003663 if (ErrorInfo >= Operands.size())
3664 return Error(IDLoc, "too few operands for instruction");
3665
Daniel Sanders52da7af2015-11-06 12:11:03 +00003666 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003667 if (ErrorLoc == SMLoc())
3668 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003669 }
3670
3671 return Error(ErrorLoc, "invalid operand for instruction");
3672 }
3673 case Match_MnemonicFail:
3674 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003675 case Match_RequiresDifferentSrcAndDst:
3676 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003677 case Match_Immz:
3678 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003679 case Match_UImm1_0:
3680 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3681 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003682 case Match_UImm2_0:
3683 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3684 "expected 2-bit unsigned immediate");
3685 case Match_UImm2_1:
3686 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3687 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003688 case Match_UImm3_0:
3689 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3690 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003691 case Match_UImm4_0:
3692 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3693 "expected 4-bit unsigned immediate");
Daniel Sanders78e89022016-03-11 11:37:50 +00003694 case Match_SImm4_0:
3695 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3696 "expected 4-bit signed immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003697 case Match_UImm5_0:
3698 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3699 "expected 5-bit unsigned immediate");
Daniel Sanders0f17d0d2016-03-22 14:29:53 +00003700 case Match_SImm5_0:
3701 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3702 "expected 5-bit signed immediate");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003703 case Match_UImm5_1:
3704 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3705 "expected immediate in range 1 .. 32");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003706 case Match_UImm5_32:
3707 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3708 "expected immediate in range 32 .. 63");
Zlatko Buljan5da2f6c2015-12-21 13:08:58 +00003709 case Match_UImm5_33:
3710 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3711 "expected immediate in range 33 .. 64");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003712 case Match_UImm5_0_Report_UImm6:
3713 // This is used on UImm5 operands that have a corresponding UImm5_32
3714 // operand to avoid confusing the user.
3715 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3716 "expected 6-bit unsigned immediate");
3717 case Match_UImm5_Lsl2:
3718 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3719 "expected both 7-bit unsigned immediate and multiple of 4");
Hrvoje Varga46458d02016-02-25 12:53:29 +00003720 case Match_UImmRange2_64:
3721 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3722 "expected immediate in range 2 .. 64");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003723 case Match_UImm6_0:
3724 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3725 "expected 6-bit unsigned immediate");
Daniel Sanders19b7f762016-03-14 11:16:56 +00003726 case Match_UImm6_Lsl2:
3727 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3728 "expected both 8-bit unsigned immediate and multiple of 4");
Daniel Sanders78e89022016-03-11 11:37:50 +00003729 case Match_SImm6_0:
Zlatko Buljan252cca52015-12-18 08:59:37 +00003730 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3731 "expected 6-bit signed immediate");
3732 case Match_UImm7_0:
3733 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3734 "expected 7-bit unsigned immediate");
Daniel Sanders97297772016-03-22 14:40:00 +00003735 case Match_UImm7_N1:
3736 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3737 "expected immediate in range -1 .. 126");
3738 case Match_SImm7_Lsl2:
3739 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3740 "expected both 9-bit signed immediate and multiple of 4");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003741 case Match_UImm8_0:
3742 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3743 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003744 case Match_UImm10_0:
3745 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3746 "expected 10-bit unsigned immediate");
Daniel Sanders837f1512016-03-24 13:26:59 +00003747 case Match_SImm10_0:
3748 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3749 "expected 10-bit signed immediate");
Daniel Sanderseab31462016-03-31 14:23:20 +00003750 case Match_SImm11_0:
3751 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3752 "expected 11-bit signed immediate");
Daniel Sandersf8bb23e2016-02-01 15:13:31 +00003753 case Match_UImm16:
3754 case Match_UImm16_Relaxed:
3755 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3756 "expected 16-bit unsigned immediate");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003757 case Match_SImm16:
3758 case Match_SImm16_Relaxed:
3759 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3760 "expected 16-bit signed immediate");
Daniel Sanders03a8d2f2016-02-29 16:06:38 +00003761 case Match_UImm20_0:
3762 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3763 "expected 20-bit unsigned immediate");
Daniel Sanders5d3840f2016-03-29 09:40:38 +00003764 case Match_UImm26_0:
3765 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3766 "expected 26-bit unsigned immediate");
Daniel Sandersb3c27642016-04-04 15:32:49 +00003767 case Match_SImm32:
3768 case Match_SImm32_Relaxed:
3769 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3770 "expected 32-bit signed immediate");
Daniel Sanders2e9f69d2016-03-31 13:15:23 +00003771 case Match_MemSImm9:
3772 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3773 "expected memory with 9-bit signed offset");
Daniel Sandersdc0602a2016-03-31 14:12:01 +00003774 case Match_MemSImm10:
3775 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3776 "expected memory with 10-bit signed offset");
3777 case Match_MemSImm10Lsl1:
3778 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3779 "expected memory with 11-bit signed offset and multiple of 2");
3780 case Match_MemSImm10Lsl2:
3781 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3782 "expected memory with 12-bit signed offset and multiple of 4");
3783 case Match_MemSImm10Lsl3:
3784 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3785 "expected memory with 13-bit signed offset and multiple of 8");
Daniel Sanderseab31462016-03-31 14:23:20 +00003786 case Match_MemSImm11:
3787 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3788 "expected memory with 11-bit signed offset");
Daniel Sanders85fd10b2016-03-31 14:34:00 +00003789 case Match_MemSImm16:
3790 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3791 "expected memory with 16-bit signed offset");
Jack Carterb4dbc172012-09-05 23:34:03 +00003792 }
Craig Topper589ceee2015-01-03 08:16:34 +00003793
3794 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003795}
3796
Toma Tabacud9d344b2015-04-27 14:05:04 +00003797void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3798 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3799 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3800 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003801}
3802
Toma Tabacu81496c12015-05-20 08:54:45 +00003803void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3804 if (!AssemblerOptions.back()->isMacro())
3805 Warning(Loc, "macro instruction expanded into multiple instructions");
3806}
3807
Daniel Sandersef638fe2014-10-03 15:37:37 +00003808void
3809MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3810 SMRange Range, bool ShowColors) {
3811 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003812 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003813 ShowColors);
3814}
3815
Jack Carter1ac53222013-02-20 23:11:17 +00003816int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003817 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003818
Vladimir Medic4c299852013-11-06 11:27:05 +00003819 CC = StringSwitch<unsigned>(Name)
3820 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003821 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003822 .Case("a0", 4)
3823 .Case("a1", 5)
3824 .Case("a2", 6)
3825 .Case("a3", 7)
3826 .Case("v0", 2)
3827 .Case("v1", 3)
3828 .Case("s0", 16)
3829 .Case("s1", 17)
3830 .Case("s2", 18)
3831 .Case("s3", 19)
3832 .Case("s4", 20)
3833 .Case("s5", 21)
3834 .Case("s6", 22)
3835 .Case("s7", 23)
3836 .Case("k0", 26)
3837 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003838 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003839 .Case("sp", 29)
3840 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003841 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003842 .Case("ra", 31)
3843 .Case("t0", 8)
3844 .Case("t1", 9)
3845 .Case("t2", 10)
3846 .Case("t3", 11)
3847 .Case("t4", 12)
3848 .Case("t5", 13)
3849 .Case("t6", 14)
3850 .Case("t7", 15)
3851 .Case("t8", 24)
3852 .Case("t9", 25)
3853 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003854
Toma Tabacufda445c2014-09-15 15:33:01 +00003855 if (!(isABI_N32() || isABI_N64()))
3856 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003857
Daniel Sandersef638fe2014-10-03 15:37:37 +00003858 if (12 <= CC && CC <= 15) {
3859 // Name is one of t4-t7
3860 AsmToken RegTok = getLexer().peekTok();
3861 SMRange RegRange = RegTok.getLocRange();
3862
3863 StringRef FixedName = StringSwitch<StringRef>(Name)
3864 .Case("t4", "t0")
3865 .Case("t5", "t1")
3866 .Case("t6", "t2")
3867 .Case("t7", "t3")
3868 .Default("");
3869 assert(FixedName != "" && "Register name is not one of t4-t7.");
3870
3871 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3872 "Did you mean $" + FixedName + "?", RegRange);
3873 }
3874
Toma Tabacufda445c2014-09-15 15:33:01 +00003875 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3876 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3877 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3878 if (8 <= CC && CC <= 11)
3879 CC += 4;
3880
3881 if (CC == -1)
3882 CC = StringSwitch<unsigned>(Name)
3883 .Case("a4", 8)
3884 .Case("a5", 9)
3885 .Case("a6", 10)
3886 .Case("a7", 11)
3887 .Case("kt0", 26)
3888 .Case("kt1", 27)
3889 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003890
3891 return CC;
3892}
Jack Carterd0bd6422013-04-18 00:41:53 +00003893
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003894int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3895 int CC;
3896
3897 CC = StringSwitch<unsigned>(Name)
3898 .Case("hwr_cpunum", 0)
3899 .Case("hwr_synci_step", 1)
3900 .Case("hwr_cc", 2)
3901 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003902 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003903 .Default(-1);
3904
3905 return CC;
3906}
3907
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003908int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003909
Jack Cartera63b16a2012-09-07 00:23:42 +00003910 if (Name[0] == 'f') {
3911 StringRef NumString = Name.substr(1);
3912 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003913 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003914 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003915 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003916 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003917 return IntVal;
3918 }
3919 return -1;
3920}
Jack Cartera63b16a2012-09-07 00:23:42 +00003921
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003922int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3923
3924 if (Name.startswith("fcc")) {
3925 StringRef NumString = Name.substr(3);
3926 unsigned IntVal;
3927 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003928 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003929 if (IntVal > 7) // There are only 8 fcc registers.
3930 return -1;
3931 return IntVal;
3932 }
3933 return -1;
3934}
3935
3936int MipsAsmParser::matchACRegisterName(StringRef Name) {
3937
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003938 if (Name.startswith("ac")) {
3939 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003940 unsigned IntVal;
3941 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003942 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003943 if (IntVal > 3) // There are only 3 acc registers.
3944 return -1;
3945 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003946 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003947 return -1;
3948}
Jack Carterd0bd6422013-04-18 00:41:53 +00003949
Jack Carter5dc8ac92013-09-25 23:50:44 +00003950int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3951 unsigned IntVal;
3952
3953 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3954 return -1;
3955
3956 if (IntVal > 31)
3957 return -1;
3958
3959 return IntVal;
3960}
3961
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003962int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3963 int CC;
3964
3965 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003966 .Case("msair", 0)
3967 .Case("msacsr", 1)
3968 .Case("msaaccess", 2)
3969 .Case("msasave", 3)
3970 .Case("msamodify", 4)
3971 .Case("msarequest", 5)
3972 .Case("msamap", 6)
3973 .Case("msaunmap", 7)
3974 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003975
3976 return CC;
3977}
3978
Toma Tabacu89a712b2015-04-15 10:48:56 +00003979unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003980 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003981 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003982 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003983 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003984 return 0;
3985 }
3986 unsigned AT = getReg(
3987 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003988 return AT;
3989}
Jack Carter0b744b32012-10-04 02:29:46 +00003990
Jack Carterd0bd6422013-04-18 00:41:53 +00003991unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003992 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003993}
3994
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003995unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003996 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003997 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003998}
3999
Jack Carter873c7242013-01-12 01:03:14 +00004000int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004001 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00004002 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00004003 return -1;
4004
Jack Carter873c7242013-01-12 01:03:14 +00004005 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00004006}
4007
Toma Tabacu13964452014-09-04 13:23:44 +00004008bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004009 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004010 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004011
Jack Carter30a59822012-10-04 04:03:53 +00004012 // Check if the current operand has a custom associated parser, if so, try to
4013 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00004014 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4015 if (ResTy == MatchOperand_Success)
4016 return false;
4017 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4018 // there was a match, but an error occurred, in which case, just return that
4019 // the operand parsing failed.
4020 if (ResTy == MatchOperand_ParseFail)
4021 return true;
4022
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004023 DEBUG(dbgs() << ".. Generic Parser\n");
4024
Jack Carterb4dbc172012-09-05 23:34:03 +00004025 switch (getLexer().getKind()) {
4026 default:
4027 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4028 return true;
4029 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004030 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00004031 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00004032
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004033 // Almost all registers have been parsed by custom parsers. There is only
4034 // one exception to this. $zero (and it's alias $0) will reach this point
4035 // for div, divu, and similar instructions because it is not an operand
4036 // to the instruction definition but an explicit register. Special case
4037 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00004038 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00004039 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004040
Jack Carterd0bd6422013-04-18 00:41:53 +00004041 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00004042 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004043 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00004044 return true;
4045
Jack Carter873c7242013-01-12 01:03:14 +00004046 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00004047 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00004048 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00004049 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004050 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00004051
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004052 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004053 return false;
4054 }
Vladimir Medic4c299852013-11-06 11:27:05 +00004055 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00004056 case AsmToken::LParen:
4057 case AsmToken::Minus:
4058 case AsmToken::Plus:
4059 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004060 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00004061 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004062 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004063 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004064 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00004065 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00004066 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00004067 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004068 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00004069 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00004070 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00004071 return true;
4072
Jack Carter873c7242013-01-12 01:03:14 +00004073 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4074
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004075 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00004076 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004077 } // case AsmToken::Percent
4078 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00004079 return true;
4080}
4081
Vladimir Medic4c299852013-11-06 11:27:05 +00004082const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00004083 StringRef RelocStr) {
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004084 if (RelocStr == "hi(%neg(%gp_rel")
4085 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext());
4086 else if (RelocStr == "lo(%neg(%gp_rel")
4087 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004088
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004089 MipsMCExpr::MipsExprKind Kind =
4090 StringSwitch<MipsMCExpr::MipsExprKind>(RelocStr)
4091 .Case("call16", MipsMCExpr::MEK_GOT_CALL)
4092 .Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
4093 .Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
4094 .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
4095 .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
4096 .Case("got", MipsMCExpr::MEK_GOT)
4097 .Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
4098 .Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
4099 .Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
4100 .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
4101 .Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
4102 .Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
4103 .Case("gp_rel", MipsMCExpr::MEK_GPREL)
4104 .Case("hi", MipsMCExpr::MEK_HI)
4105 .Case("higher", MipsMCExpr::MEK_HIGHER)
4106 .Case("highest", MipsMCExpr::MEK_HIGHEST)
4107 .Case("lo", MipsMCExpr::MEK_LO)
4108 .Case("neg", MipsMCExpr::MEK_NEG)
4109 .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
4110 .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
4111 .Case("tlsgd", MipsMCExpr::MEK_TLSGD)
4112 .Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
4113 .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
4114 .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
4115 .Default(MipsMCExpr::MEK_None);
Jack Carterb5cf5902013-04-17 00:18:04 +00004116
Daniel Sandersfe98b2f2016-05-03 13:35:44 +00004117 assert(Kind != MipsMCExpr::MEK_None);
4118 return MipsMCExpr::create(Kind, Expr, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004119}
4120
4121bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4122
4123 switch (Expr->getKind()) {
4124 case MCExpr::Constant:
4125 return true;
4126 case MCExpr::SymbolRef:
4127 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4128 case MCExpr::Binary:
4129 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4130 if (!isEvaluated(BE->getLHS()))
4131 return false;
4132 return isEvaluated(BE->getRHS());
4133 }
4134 case MCExpr::Unary:
4135 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004136 case MCExpr::Target:
4137 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004138 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004139 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004140}
Jack Carterd0bd6422013-04-18 00:41:53 +00004141
Jack Carterb5cf5902013-04-17 00:18:04 +00004142bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004143 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004144 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004145 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004146 if (Tok.isNot(AsmToken::Identifier))
4147 return true;
4148
Yaron Keren075759a2015-03-30 15:42:36 +00004149 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004150
Jack Carterd0bd6422013-04-18 00:41:53 +00004151 Parser.Lex(); // Eat the identifier.
4152 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004153 const MCExpr *IdVal;
4154 SMLoc EndLoc;
4155
4156 if (getLexer().getKind() == AsmToken::LParen) {
4157 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004158 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004159 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004160 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004161 const AsmToken &nextTok = Parser.getTok();
4162 if (nextTok.isNot(AsmToken::Identifier))
4163 return true;
4164 Str += "(%";
4165 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004166 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004167 if (getLexer().getKind() != AsmToken::LParen)
4168 return true;
4169 } else
4170 break;
4171 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004172 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004173 return true;
4174
4175 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004176 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004177
4178 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004179 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004180
Jack Carterd0bd6422013-04-18 00:41:53 +00004181 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004182 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004183}
4184
Jack Carterb4dbc172012-09-05 23:34:03 +00004185bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4186 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004187 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004188 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004189 if (ResTy == MatchOperand_Success) {
4190 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004191 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004192 StartLoc = Operand.getStartLoc();
4193 EndLoc = Operand.getEndLoc();
4194
4195 // AFAIK, we only support numeric registers and named GPR's in CFI
4196 // directives.
4197 // Don't worry about eating tokens before failing. Using an unrecognised
4198 // register is a parse error.
4199 if (Operand.isGPRAsmReg()) {
4200 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004201 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004202 }
4203
4204 return (RegNo == (unsigned)-1);
4205 }
4206
4207 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004208 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004209}
4210
Jack Carterb5cf5902013-04-17 00:18:04 +00004211bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004212 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004213 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004214 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004215 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004216
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004217 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004218 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004219 ++NumOfLParen;
4220 }
Jack Carter873c7242013-01-12 01:03:14 +00004221
Jack Carterd0bd6422013-04-18 00:41:53 +00004222 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004223 default:
4224 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004225 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004226 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004227 case AsmToken::Integer:
4228 case AsmToken::Minus:
4229 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004230 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004231 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004232 else
4233 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004234 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004235 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004236 break;
Jack Carter873c7242013-01-12 01:03:14 +00004237 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004238 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004239 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004240 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004241}
4242
David Blaikie960ea3f2014-06-08 16:18:35 +00004243MipsAsmParser::OperandMatchResultTy
4244MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004245 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004246 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004247 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004248 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004249 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004250 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004251 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004252 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004253
Jack Carterb5cf5902013-04-17 00:18:04 +00004254 if (getLexer().getKind() == AsmToken::LParen) {
4255 Parser.Lex();
4256 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004257 }
4258
Jack Carterb5cf5902013-04-17 00:18:04 +00004259 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004260 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004261 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004262
Jack Carterd0bd6422013-04-18 00:41:53 +00004263 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004264 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004265 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004266 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004267 SMLoc E =
4268 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004269 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004270 return MatchOperand_Success;
4271 }
4272 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004273 SMLoc E =
4274 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004275
Jack Carterd0bd6422013-04-18 00:41:53 +00004276 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004277 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004278 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004279 S, E, *this);
4280 Operands.push_back(
4281 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004282 return MatchOperand_Success;
4283 }
4284 Error(Parser.getTok().getLoc(), "'(' expected");
4285 return MatchOperand_ParseFail;
4286 }
4287
Jack Carterd0bd6422013-04-18 00:41:53 +00004288 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004289 }
4290
Toma Tabacu13964452014-09-04 13:23:44 +00004291 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004292 if (Res != MatchOperand_Success)
4293 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004294
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004295 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004296 Error(Parser.getTok().getLoc(), "')' expected");
4297 return MatchOperand_ParseFail;
4298 }
4299
Jack Carter873c7242013-01-12 01:03:14 +00004300 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4301
Jack Carterd0bd6422013-04-18 00:41:53 +00004302 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004303
Craig Topper062a2ba2014-04-25 05:30:21 +00004304 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004305 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004306
Jack Carterd0bd6422013-04-18 00:41:53 +00004307 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004308 std::unique_ptr<MipsOperand> op(
4309 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004310 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004311 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004312 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004313 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004314 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4315 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004316 if (IdVal->evaluateAsAbsolute(Imm))
4317 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004318 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004319 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004320 getContext());
4321 }
4322
David Blaikie960ea3f2014-06-08 16:18:35 +00004323 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004324 return MatchOperand_Success;
4325}
4326
David Blaikie960ea3f2014-06-08 16:18:35 +00004327bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004328 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004329 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004330 if (Sym) {
4331 SMLoc S = Parser.getTok().getLoc();
4332 const MCExpr *Expr;
4333 if (Sym->isVariable())
4334 Expr = Sym->getVariableValue();
4335 else
4336 return false;
4337 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004338 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004339 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004340 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004341 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004342 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004343 if (ResTy == MatchOperand_Success) {
4344 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004345 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004346 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004347 llvm_unreachable("Should never ParseFail");
4348 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004349 }
4350 } else if (Expr->getKind() == MCExpr::Constant) {
4351 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004352 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004353 Operands.push_back(
4354 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004355 return true;
4356 }
4357 }
4358 return false;
4359}
Jack Carterd0bd6422013-04-18 00:41:53 +00004360
Jack Carter873c7242013-01-12 01:03:14 +00004361MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004362MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004363 StringRef Identifier,
4364 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004365 int Index = matchCPURegisterName(Identifier);
4366 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004367 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004368 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4369 return MatchOperand_Success;
4370 }
4371
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004372 Index = matchHWRegsRegisterName(Identifier);
4373 if (Index != -1) {
4374 Operands.push_back(MipsOperand::createHWRegsReg(
4375 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4376 return MatchOperand_Success;
4377 }
4378
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004379 Index = matchFPURegisterName(Identifier);
4380 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004381 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004382 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4383 return MatchOperand_Success;
4384 }
4385
4386 Index = matchFCCRegisterName(Identifier);
4387 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004388 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004389 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4390 return MatchOperand_Success;
4391 }
4392
4393 Index = matchACRegisterName(Identifier);
4394 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004395 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004396 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4397 return MatchOperand_Success;
4398 }
4399
4400 Index = matchMSA128RegisterName(Identifier);
4401 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004402 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004403 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4404 return MatchOperand_Success;
4405 }
4406
4407 Index = matchMSA128CtrlRegisterName(Identifier);
4408 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004409 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004410 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4411 return MatchOperand_Success;
4412 }
4413
4414 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004415}
4416
4417MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004418MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004419 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004420 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004421
4422 if (Token.is(AsmToken::Identifier)) {
4423 DEBUG(dbgs() << ".. identifier\n");
4424 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004425 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004426 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004427 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004428 } else if (Token.is(AsmToken::Integer)) {
4429 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004430 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004431 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4432 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004433 return MatchOperand_Success;
4434 }
4435
4436 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4437
4438 return MatchOperand_NoMatch;
4439}
4440
David Blaikie960ea3f2014-06-08 16:18:35 +00004441MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004442MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004443 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004444 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004445
4446 auto Token = Parser.getTok();
4447
4448 SMLoc S = Token.getLoc();
4449
4450 if (Token.isNot(AsmToken::Dollar)) {
4451 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4452 if (Token.is(AsmToken::Identifier)) {
4453 if (searchSymbolAlias(Operands))
4454 return MatchOperand_Success;
4455 }
4456 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4457 return MatchOperand_NoMatch;
4458 }
4459 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004460
Toma Tabacu13964452014-09-04 13:23:44 +00004461 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004462 if (ResTy == MatchOperand_Success) {
4463 Parser.Lex(); // $
4464 Parser.Lex(); // identifier
4465 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004466 return ResTy;
4467}
4468
4469MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004470MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004471 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004472 switch (getLexer().getKind()) {
4473 default:
4474 return MatchOperand_NoMatch;
4475 case AsmToken::LParen:
4476 case AsmToken::Minus:
4477 case AsmToken::Plus:
4478 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004479 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004480 case AsmToken::String:
4481 break;
4482 }
4483
4484 const MCExpr *IdVal;
4485 SMLoc S = Parser.getTok().getLoc();
4486 if (getParser().parseExpression(IdVal))
4487 return MatchOperand_ParseFail;
4488
4489 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4490 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4491 return MatchOperand_Success;
4492}
4493
David Blaikie960ea3f2014-06-08 16:18:35 +00004494MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004495MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004496 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004497 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004498
4499 SMLoc S = getLexer().getLoc();
4500
4501 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004502 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004503 if (ResTy != MatchOperand_NoMatch)
4504 return ResTy;
4505
Daniel Sanders315386c2014-04-01 10:40:14 +00004506 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004507 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004508 if (ResTy != MatchOperand_NoMatch)
4509 return ResTy;
4510
Daniel Sandersffd84362014-04-01 10:41:48 +00004511 const MCExpr *Expr = nullptr;
4512 if (Parser.parseExpression(Expr)) {
4513 // We have no way of knowing if a symbol was consumed so we must ParseFail
4514 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004515 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004516 Operands.push_back(
4517 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004518 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004519}
4520
Vladimir Medic2b953d02013-10-01 09:48:56 +00004521MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004522MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004523 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004524 const MCExpr *IdVal;
4525 // If the first token is '$' we may have register operand.
4526 if (Parser.getTok().is(AsmToken::Dollar))
4527 return MatchOperand_NoMatch;
4528 SMLoc S = Parser.getTok().getLoc();
4529 if (getParser().parseExpression(IdVal))
4530 return MatchOperand_ParseFail;
4531 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004532 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004533 int64_t Val = MCE->getValue();
4534 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4535 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004536 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004537 return MatchOperand_Success;
4538}
4539
Matheus Almeida779c5932013-11-18 12:32:49 +00004540MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004541MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004542 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004543 switch (getLexer().getKind()) {
4544 default:
4545 return MatchOperand_NoMatch;
4546 case AsmToken::LParen:
4547 case AsmToken::Plus:
4548 case AsmToken::Minus:
4549 case AsmToken::Integer:
4550 break;
4551 }
4552
4553 const MCExpr *Expr;
4554 SMLoc S = Parser.getTok().getLoc();
4555
4556 if (getParser().parseExpression(Expr))
4557 return MatchOperand_ParseFail;
4558
4559 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004560 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004561 Error(S, "expected immediate value");
4562 return MatchOperand_ParseFail;
4563 }
4564
4565 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4566 // and because the CPU always adds one to the immediate field, the allowed
4567 // range becomes 1..4. We'll only check the range here and will deal
4568 // with the addition/subtraction when actually decoding/encoding
4569 // the instruction.
4570 if (Val < 1 || Val > 4) {
4571 Error(S, "immediate not in range (1..4)");
4572 return MatchOperand_ParseFail;
4573 }
4574
Jack Carter3b2c96e2014-01-22 23:31:38 +00004575 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004576 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004577 return MatchOperand_Success;
4578}
4579
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004580MipsAsmParser::OperandMatchResultTy
4581MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4582 MCAsmParser &Parser = getParser();
4583 SmallVector<unsigned, 10> Regs;
4584 unsigned RegNo;
4585 unsigned PrevReg = Mips::NoRegister;
4586 bool RegRange = false;
4587 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4588
4589 if (Parser.getTok().isNot(AsmToken::Dollar))
4590 return MatchOperand_ParseFail;
4591
4592 SMLoc S = Parser.getTok().getLoc();
4593 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4594 SMLoc E = getLexer().getLoc();
4595 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4596 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4597 if (RegRange) {
4598 // Remove last register operand because registers from register range
4599 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004600 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4601 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004602 Regs.push_back(RegNo);
4603 } else {
4604 unsigned TmpReg = PrevReg + 1;
4605 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004606 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4607 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4608 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004609 Error(E, "invalid register operand");
4610 return MatchOperand_ParseFail;
4611 }
4612
4613 PrevReg = TmpReg;
4614 Regs.push_back(TmpReg++);
4615 }
4616 }
4617
4618 RegRange = false;
4619 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004620 if ((PrevReg == Mips::NoRegister) &&
4621 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4622 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004623 Error(E, "$16 or $31 expected");
4624 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004625 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4626 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4627 !isGP64bit()) ||
4628 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4629 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4630 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004631 Error(E, "invalid register operand");
4632 return MatchOperand_ParseFail;
4633 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004634 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4635 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4636 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004637 Error(E, "consecutive register numbers expected");
4638 return MatchOperand_ParseFail;
4639 }
4640
4641 Regs.push_back(RegNo);
4642 }
4643
4644 if (Parser.getTok().is(AsmToken::Minus))
4645 RegRange = true;
4646
4647 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4648 !Parser.getTok().isNot(AsmToken::Comma)) {
4649 Error(E, "',' or '-' expected");
4650 return MatchOperand_ParseFail;
4651 }
4652
4653 Lex(); // Consume comma or minus
4654 if (Parser.getTok().isNot(AsmToken::Dollar))
4655 break;
4656
4657 PrevReg = RegNo;
4658 }
4659
4660 SMLoc E = Parser.getTok().getLoc();
4661 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4662 parseMemOperand(Operands);
4663 return MatchOperand_Success;
4664}
4665
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004666MipsAsmParser::OperandMatchResultTy
4667MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4668 MCAsmParser &Parser = getParser();
4669
4670 SMLoc S = Parser.getTok().getLoc();
4671 if (parseAnyRegister(Operands) != MatchOperand_Success)
4672 return MatchOperand_ParseFail;
4673
4674 SMLoc E = Parser.getTok().getLoc();
4675 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4676 unsigned Reg = Op.getGPR32Reg();
4677 Operands.pop_back();
4678 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4679 return MatchOperand_Success;
4680}
4681
Zoran Jovanovic41688672015-02-10 16:36:20 +00004682MipsAsmParser::OperandMatchResultTy
4683MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4684 MCAsmParser &Parser = getParser();
4685 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4686 SmallVector<unsigned, 10> Regs;
4687
4688 if (Parser.getTok().isNot(AsmToken::Dollar))
4689 return MatchOperand_ParseFail;
4690
4691 SMLoc S = Parser.getTok().getLoc();
4692
4693 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4694 return MatchOperand_ParseFail;
4695
4696 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4697 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4698 Regs.push_back(RegNo);
4699
4700 SMLoc E = Parser.getTok().getLoc();
4701 if (Parser.getTok().isNot(AsmToken::Comma)) {
4702 Error(E, "',' expected");
4703 return MatchOperand_ParseFail;
4704 }
4705
4706 // Remove comma.
4707 Parser.Lex();
4708
4709 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4710 return MatchOperand_ParseFail;
4711
4712 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4713 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4714 Regs.push_back(RegNo);
4715
4716 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4717
4718 return MatchOperand_Success;
4719}
4720
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004721/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4722/// either this.
4723/// ::= '(', register, ')'
4724/// handle it before we iterate so we don't get tripped up by the lack of
4725/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004726bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004727 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004728 if (getLexer().is(AsmToken::LParen)) {
4729 Operands.push_back(
4730 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4731 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004732 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004733 SMLoc Loc = getLexer().getLoc();
4734 Parser.eatToEndOfStatement();
4735 return Error(Loc, "unexpected token in argument list");
4736 }
4737 if (Parser.getTok().isNot(AsmToken::RParen)) {
4738 SMLoc Loc = getLexer().getLoc();
4739 Parser.eatToEndOfStatement();
4740 return Error(Loc, "unexpected token, expected ')'");
4741 }
4742 Operands.push_back(
4743 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4744 Parser.Lex();
4745 }
4746 return false;
4747}
4748
4749/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4750/// either one of these.
4751/// ::= '[', register, ']'
4752/// ::= '[', integer, ']'
4753/// handle it before we iterate so we don't get tripped up by the lack of
4754/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004755bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004756 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004757 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004758 if (getLexer().is(AsmToken::LBrac)) {
4759 Operands.push_back(
4760 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4761 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004762 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004763 SMLoc Loc = getLexer().getLoc();
4764 Parser.eatToEndOfStatement();
4765 return Error(Loc, "unexpected token in argument list");
4766 }
4767 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4768 SMLoc Loc = getLexer().getLoc();
4769 Parser.eatToEndOfStatement();
4770 return Error(Loc, "unexpected token, expected ']'");
4771 }
4772 Operands.push_back(
4773 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4774 Parser.Lex();
4775 }
4776 return false;
4777}
4778
David Blaikie960ea3f2014-06-08 16:18:35 +00004779bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4780 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004781 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004782 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004783
4784 // We have reached first instruction, module directive are now forbidden.
4785 getTargetStreamer().forbidModuleDirective();
4786
Vladimir Medic74593e62013-07-17 15:00:42 +00004787 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004788 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004789 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004790 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004791 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004792 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004793 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004794
4795 // Read the remaining operands.
4796 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4797 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004798 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004799 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004800 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004801 return Error(Loc, "unexpected token in argument list");
4802 }
Toma Tabacu13964452014-09-04 13:23:44 +00004803 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004804 return true;
4805 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004806
Jack Carterd0bd6422013-04-18 00:41:53 +00004807 while (getLexer().is(AsmToken::Comma)) {
4808 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004809 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004810 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004811 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004812 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004813 return Error(Loc, "unexpected token in argument list");
4814 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004815 // Parse bracket and parenthesis suffixes before we iterate
4816 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004817 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004818 return true;
4819 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004820 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004821 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004822 }
4823 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004824 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4825 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004826 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004827 return Error(Loc, "unexpected token in argument list");
4828 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004829 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004830 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004831}
4832
Nirav Dave996fc132016-05-05 14:15:46 +00004833// FIXME: Given that these have the same name, these should both be
4834// consistent on affecting the Parser.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004835bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004836 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004837 SMLoc Loc = getLexer().getLoc();
4838 Parser.eatToEndOfStatement();
4839 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004840}
4841
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004842bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004843 return Error(Loc, ErrorMsg);
4844}
4845
Jack Carter0b744b32012-10-04 02:29:46 +00004846bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004847 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004848 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004849
4850 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004851 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004852
4853 Parser.Lex(); // Eat "noat".
4854
Jack Carterd0bd6422013-04-18 00:41:53 +00004855 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004856 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004857 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004858 return false;
4859 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004860
4861 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004862 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004863 return false;
4864}
Jack Carterd0bd6422013-04-18 00:41:53 +00004865
Jack Carter0b744b32012-10-04 02:29:46 +00004866bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004867 // Line can be: ".set at", which sets $at to $1
4868 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004869 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004870 Parser.Lex(); // Eat "at".
4871
Jack Carter0b744b32012-10-04 02:29:46 +00004872 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004873 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004874 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004875
4876 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004877 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004878 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004879 }
4880
4881 if (getLexer().isNot(AsmToken::Equal)) {
4882 reportParseError("unexpected token, expected equals sign");
4883 return false;
4884 }
4885 Parser.Lex(); // Eat "=".
4886
4887 if (getLexer().isNot(AsmToken::Dollar)) {
4888 if (getLexer().is(AsmToken::EndOfStatement)) {
4889 reportParseError("no register specified");
4890 return false;
4891 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004892 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004893 return false;
4894 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004895 }
4896 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004897
Toma Tabacu16a74492015-02-13 10:30:57 +00004898 // Find out what "reg" is.
4899 unsigned AtRegNo;
4900 const AsmToken &Reg = Parser.getTok();
4901 if (Reg.is(AsmToken::Identifier)) {
4902 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4903 } else if (Reg.is(AsmToken::Integer)) {
4904 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004905 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004906 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004907 return false;
4908 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004909
4910 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004911 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004912 reportParseError("invalid register");
4913 return false;
4914 }
4915 Parser.Lex(); // Eat "reg".
4916
4917 // If this is not the end of the statement, report an error.
4918 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4919 reportParseError("unexpected token, expected end of statement");
4920 return false;
4921 }
4922
4923 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4924
4925 Parser.Lex(); // Consume the EndOfStatement.
4926 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004927}
4928
4929bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004930 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004931 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004932 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004933 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004934 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004935 return false;
4936 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004937 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004938 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004939 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004940 return false;
4941}
4942
4943bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004944 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004945 Parser.Lex();
4946 // If this is not the end of the statement, report an error.
4947 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004948 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004949 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004950 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004951 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004952 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004953 Parser.Lex(); // Consume the EndOfStatement.
4954 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004955}
4956
4957bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004958 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004959 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004960 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004961 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004962 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004963 return false;
4964 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004965 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004966 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004967 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004968 return false;
4969}
4970
4971bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004972 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004973 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004974 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004975 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004976 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004977 return false;
4978 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004979 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004980 reportParseError("`noreorder' must be set before `nomacro'");
4981 return false;
4982 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004983 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004984 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004985 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004986 return false;
4987}
Jack Carterd76b2372013-03-21 21:44:16 +00004988
Daniel Sanders44934432014-08-07 12:03:36 +00004989bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004990 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004991 Parser.Lex();
4992
4993 // If this is not the end of the statement, report an error.
4994 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004995 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004996
4997 setFeatureBits(Mips::FeatureMSA, "msa");
4998 getTargetStreamer().emitDirectiveSetMsa();
4999 return false;
5000}
5001
5002bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005003 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005004 Parser.Lex();
5005
5006 // If this is not the end of the statement, report an error.
5007 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005008 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005009
5010 clearFeatureBits(Mips::FeatureMSA, "msa");
5011 getTargetStreamer().emitDirectiveSetNoMsa();
5012 return false;
5013}
5014
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005015bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005016 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005017 Parser.Lex(); // Eat "nodsp".
5018
5019 // If this is not the end of the statement, report an error.
5020 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5021 reportParseError("unexpected token, expected end of statement");
5022 return false;
5023 }
5024
5025 clearFeatureBits(Mips::FeatureDSP, "dsp");
5026 getTargetStreamer().emitDirectiveSetNoDsp();
5027 return false;
5028}
5029
Toma Tabacucc2502d2014-11-04 17:18:07 +00005030bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005031 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005032 Parser.Lex(); // Eat "mips16".
5033
Jack Carter39536722014-01-22 23:08:42 +00005034 // If this is not the end of the statement, report an error.
5035 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005036 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005037 return false;
5038 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005039
5040 setFeatureBits(Mips::FeatureMips16, "mips16");
5041 getTargetStreamer().emitDirectiveSetMips16();
5042 Parser.Lex(); // Consume the EndOfStatement.
5043 return false;
5044}
5045
5046bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005047 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005048 Parser.Lex(); // Eat "nomips16".
5049
5050 // If this is not the end of the statement, report an error.
5051 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5052 reportParseError("unexpected token, expected end of statement");
5053 return false;
5054 }
5055
5056 clearFeatureBits(Mips::FeatureMips16, "mips16");
5057 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005058 Parser.Lex(); // Consume the EndOfStatement.
5059 return false;
5060}
5061
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005062bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005063 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005064 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005065 // Line can be: .set fp=32
5066 // .set fp=xx
5067 // .set fp=64
5068 Parser.Lex(); // Eat fp token
5069 AsmToken Tok = Parser.getTok();
5070 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005071 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005072 return false;
5073 }
5074 Parser.Lex(); // Eat '=' token.
5075 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005076
5077 if (!parseFpABIValue(FpAbiVal, ".set"))
5078 return false;
5079
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005080 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005081 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005082 return false;
5083 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005084 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005085 Parser.Lex(); // Consume the EndOfStatement.
5086 return false;
5087}
5088
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005089bool MipsAsmParser::parseSetOddSPRegDirective() {
5090 MCAsmParser &Parser = getParser();
5091
5092 Parser.Lex(); // Eat "oddspreg".
5093 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5094 reportParseError("unexpected token, expected end of statement");
5095 return false;
5096 }
5097
5098 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5099 getTargetStreamer().emitDirectiveSetOddSPReg();
5100 return false;
5101}
5102
5103bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5104 MCAsmParser &Parser = getParser();
5105
5106 Parser.Lex(); // Eat "nooddspreg".
5107 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5108 reportParseError("unexpected token, expected end of statement");
5109 return false;
5110 }
5111
5112 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5113 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5114 return false;
5115}
5116
Toma Tabacu9db22db2014-09-09 10:15:38 +00005117bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005118 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005119 SMLoc Loc = getLexer().getLoc();
5120
5121 Parser.Lex();
5122 if (getLexer().isNot(AsmToken::EndOfStatement))
5123 return reportParseError("unexpected token, expected end of statement");
5124
5125 // Always keep an element on the options "stack" to prevent the user
5126 // from changing the initial options. This is how we remember them.
5127 if (AssemblerOptions.size() == 2)
5128 return reportParseError(Loc, ".set pop with no .set push");
5129
Akira Hatanakab11ef082015-11-14 06:35:56 +00005130 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005131 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005132 setAvailableFeatures(
5133 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5134 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005135
5136 getTargetStreamer().emitDirectiveSetPop();
5137 return false;
5138}
5139
5140bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005141 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005142 Parser.Lex();
5143 if (getLexer().isNot(AsmToken::EndOfStatement))
5144 return reportParseError("unexpected token, expected end of statement");
5145
5146 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005147 AssemblerOptions.push_back(
5148 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005149
5150 getTargetStreamer().emitDirectiveSetPush();
5151 return false;
5152}
5153
Toma Tabacu29696502015-06-02 09:48:04 +00005154bool MipsAsmParser::parseSetSoftFloatDirective() {
5155 MCAsmParser &Parser = getParser();
5156 Parser.Lex();
5157 if (getLexer().isNot(AsmToken::EndOfStatement))
5158 return reportParseError("unexpected token, expected end of statement");
5159
5160 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5161 getTargetStreamer().emitDirectiveSetSoftFloat();
5162 return false;
5163}
5164
5165bool MipsAsmParser::parseSetHardFloatDirective() {
5166 MCAsmParser &Parser = getParser();
5167 Parser.Lex();
5168 if (getLexer().isNot(AsmToken::EndOfStatement))
5169 return reportParseError("unexpected token, expected end of statement");
5170
5171 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5172 getTargetStreamer().emitDirectiveSetHardFloat();
5173 return false;
5174}
5175
Jack Carterd76b2372013-03-21 21:44:16 +00005176bool MipsAsmParser::parseSetAssignment() {
5177 StringRef Name;
5178 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005179 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005180
5181 if (Parser.parseIdentifier(Name))
5182 reportParseError("expected identifier after .set");
5183
5184 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005185 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005186 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005187
Jack Carter3b2c96e2014-01-22 23:31:38 +00005188 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005189 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005190
Jim Grosbach6f482002015-05-18 18:43:14 +00005191 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005192 Sym->setVariableValue(Value);
5193
5194 return false;
5195}
Jack Carterd0bd6422013-04-18 00:41:53 +00005196
Toma Tabacu26647792014-09-09 12:52:14 +00005197bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005198 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005199 Parser.Lex();
5200 if (getLexer().isNot(AsmToken::EndOfStatement))
5201 return reportParseError("unexpected token, expected end of statement");
5202
5203 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005204 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005205 setAvailableFeatures(
5206 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5207 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005208 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5209
5210 getTargetStreamer().emitDirectiveSetMips0();
5211 return false;
5212}
5213
Toma Tabacu85618b32014-08-19 14:22:52 +00005214bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005215 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005216 Parser.Lex();
5217 if (getLexer().isNot(AsmToken::Equal))
5218 return reportParseError("unexpected token, expected equals sign");
5219
5220 Parser.Lex();
5221 StringRef Arch;
5222 if (Parser.parseIdentifier(Arch))
5223 return reportParseError("expected arch identifier");
5224
5225 StringRef ArchFeatureName =
5226 StringSwitch<StringRef>(Arch)
5227 .Case("mips1", "mips1")
5228 .Case("mips2", "mips2")
5229 .Case("mips3", "mips3")
5230 .Case("mips4", "mips4")
5231 .Case("mips5", "mips5")
5232 .Case("mips32", "mips32")
5233 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005234 .Case("mips32r3", "mips32r3")
5235 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005236 .Case("mips32r6", "mips32r6")
5237 .Case("mips64", "mips64")
5238 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005239 .Case("mips64r3", "mips64r3")
5240 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005241 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005242 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005243 .Case("r4000", "mips3") // This is an implementation of Mips3.
5244 .Default("");
5245
5246 if (ArchFeatureName.empty())
5247 return reportParseError("unsupported architecture");
5248
5249 selectArch(ArchFeatureName);
5250 getTargetStreamer().emitDirectiveSetArch(Arch);
5251 return false;
5252}
5253
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005254bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005255 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005256 Parser.Lex();
5257 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005258 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005259
Matheus Almeida2852af82014-04-22 10:15:54 +00005260 switch (Feature) {
5261 default:
5262 llvm_unreachable("Unimplemented feature");
5263 case Mips::FeatureDSP:
5264 setFeatureBits(Mips::FeatureDSP, "dsp");
5265 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005266 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005267 case Mips::FeatureMicroMips:
5268 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005269 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005270 case Mips::FeatureMips1:
5271 selectArch("mips1");
5272 getTargetStreamer().emitDirectiveSetMips1();
5273 break;
5274 case Mips::FeatureMips2:
5275 selectArch("mips2");
5276 getTargetStreamer().emitDirectiveSetMips2();
5277 break;
5278 case Mips::FeatureMips3:
5279 selectArch("mips3");
5280 getTargetStreamer().emitDirectiveSetMips3();
5281 break;
5282 case Mips::FeatureMips4:
5283 selectArch("mips4");
5284 getTargetStreamer().emitDirectiveSetMips4();
5285 break;
5286 case Mips::FeatureMips5:
5287 selectArch("mips5");
5288 getTargetStreamer().emitDirectiveSetMips5();
5289 break;
5290 case Mips::FeatureMips32:
5291 selectArch("mips32");
5292 getTargetStreamer().emitDirectiveSetMips32();
5293 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005294 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005295 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005296 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005297 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005298 case Mips::FeatureMips32r3:
5299 selectArch("mips32r3");
5300 getTargetStreamer().emitDirectiveSetMips32R3();
5301 break;
5302 case Mips::FeatureMips32r5:
5303 selectArch("mips32r5");
5304 getTargetStreamer().emitDirectiveSetMips32R5();
5305 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005306 case Mips::FeatureMips32r6:
5307 selectArch("mips32r6");
5308 getTargetStreamer().emitDirectiveSetMips32R6();
5309 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005310 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005311 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005312 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005313 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005314 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005315 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005316 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005317 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005318 case Mips::FeatureMips64r3:
5319 selectArch("mips64r3");
5320 getTargetStreamer().emitDirectiveSetMips64R3();
5321 break;
5322 case Mips::FeatureMips64r5:
5323 selectArch("mips64r5");
5324 getTargetStreamer().emitDirectiveSetMips64R5();
5325 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005326 case Mips::FeatureMips64r6:
5327 selectArch("mips64r6");
5328 getTargetStreamer().emitDirectiveSetMips64R6();
5329 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005330 }
5331 return false;
5332}
5333
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005334bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005335 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005336 if (getLexer().isNot(AsmToken::Comma)) {
5337 SMLoc Loc = getLexer().getLoc();
5338 Parser.eatToEndOfStatement();
5339 return Error(Loc, ErrorStr);
5340 }
5341
Matheus Almeida2852af82014-04-22 10:15:54 +00005342 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005343 return true;
5344}
5345
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005346// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5347// In this class, it is only used for .cprestore.
5348// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5349// MipsTargetELFStreamer and MipsAsmParser.
5350bool MipsAsmParser::isPicAndNotNxxAbi() {
5351 return inPicMode() && !(isABI_N32() || isABI_N64());
5352}
5353
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005354bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005355 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005356 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005357
Toma Tabacudde4c462014-11-06 10:02:45 +00005358 if (inMips16Mode()) {
5359 reportParseError(".cpload is not supported in Mips16 mode");
5360 return false;
5361 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005362
David Blaikie960ea3f2014-06-08 16:18:35 +00005363 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005364 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005365 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5366 reportParseError("expected register containing function address");
5367 return false;
5368 }
5369
David Blaikie960ea3f2014-06-08 16:18:35 +00005370 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5371 if (!RegOpnd.isGPRAsmReg()) {
5372 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005373 return false;
5374 }
5375
Toma Tabacudde4c462014-11-06 10:02:45 +00005376 // If this is not the end of the statement, report an error.
5377 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5378 reportParseError("unexpected token, expected end of statement");
5379 return false;
5380 }
5381
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005382 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005383 return false;
5384}
5385
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005386bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5387 MCAsmParser &Parser = getParser();
5388
5389 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5390 // is used in non-PIC mode.
5391
5392 if (inMips16Mode()) {
5393 reportParseError(".cprestore is not supported in Mips16 mode");
5394 return false;
5395 }
5396
5397 // Get the stack offset value.
5398 const MCExpr *StackOffset;
5399 int64_t StackOffsetVal;
5400 if (Parser.parseExpression(StackOffset)) {
5401 reportParseError("expected stack offset value");
5402 return false;
5403 }
5404
5405 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5406 reportParseError("stack offset is not an absolute expression");
5407 return false;
5408 }
5409
5410 if (StackOffsetVal < 0) {
5411 Warning(Loc, ".cprestore with negative stack offset has no effect");
5412 IsCpRestoreSet = false;
5413 } else {
5414 IsCpRestoreSet = true;
5415 CpRestoreOffset = StackOffsetVal;
5416 }
5417
5418 // If this is not the end of the statement, report an error.
5419 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5420 reportParseError("unexpected token, expected end of statement");
5421 return false;
5422 }
5423
Daniel Sanders7225cd52016-04-29 16:16:49 +00005424 unsigned ATReg = getATReg(Loc);
5425 if (!ATReg)
5426 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005427
Daniel Sanders7225cd52016-04-29 16:16:49 +00005428 getTargetStreamer().emitDirectiveCpRestore(CpRestoreOffset, ATReg, Loc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005429 Parser.Lex(); // Consume the EndOfStatement.
5430 return false;
5431}
5432
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005433bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005434 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005435 unsigned FuncReg;
5436 unsigned Save;
5437 bool SaveIsReg = true;
5438
Matheus Almeida7e815762014-06-18 13:08:59 +00005439 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005440 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005441 if (ResTy == MatchOperand_NoMatch) {
5442 reportParseError("expected register containing function address");
Matheus Almeida7e815762014-06-18 13:08:59 +00005443 return false;
5444 }
5445
5446 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5447 if (!FuncRegOpnd.isGPRAsmReg()) {
5448 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5449 Parser.eatToEndOfStatement();
5450 return false;
5451 }
5452
5453 FuncReg = FuncRegOpnd.getGPR32Reg();
5454 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005455
Toma Tabacu65f10572014-09-16 15:00:52 +00005456 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005457 return true;
5458
Toma Tabacu13964452014-09-04 13:23:44 +00005459 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005460 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005461 const MCExpr *OffsetExpr;
5462 int64_t OffsetVal;
5463 SMLoc ExprLoc = getLexer().getLoc();
5464
5465 if (Parser.parseExpression(OffsetExpr) ||
5466 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5467 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005468 Parser.eatToEndOfStatement();
5469 return false;
5470 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005471
5472 Save = OffsetVal;
5473 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005474 } else {
5475 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5476 if (!SaveOpnd.isGPRAsmReg()) {
5477 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5478 Parser.eatToEndOfStatement();
5479 return false;
5480 }
5481 Save = SaveOpnd.getGPR32Reg();
5482 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005483
Toma Tabacu65f10572014-09-16 15:00:52 +00005484 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005485 return true;
5486
Toma Tabacu8874eac2015-02-18 13:46:53 +00005487 const MCExpr *Expr;
5488 if (Parser.parseExpression(Expr)) {
5489 reportParseError("expected expression");
5490 return false;
5491 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005492
Toma Tabacu8874eac2015-02-18 13:46:53 +00005493 if (Expr->getKind() != MCExpr::SymbolRef) {
5494 reportParseError("expected symbol");
5495 return false;
5496 }
5497 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5498
Daniel Sandersf173dda2015-09-22 10:50:09 +00005499 CpSaveLocation = Save;
5500 CpSaveLocationIsRegister = SaveIsReg;
5501
Toma Tabacu8874eac2015-02-18 13:46:53 +00005502 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5503 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005504 return false;
5505}
5506
Daniel Sandersf173dda2015-09-22 10:50:09 +00005507bool MipsAsmParser::parseDirectiveCPReturn() {
5508 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5509 CpSaveLocationIsRegister);
5510 return false;
5511}
5512
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005513bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005514 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005515 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5516 const AsmToken &Tok = Parser.getTok();
5517
5518 if (Tok.getString() == "2008") {
5519 Parser.Lex();
5520 getTargetStreamer().emitDirectiveNaN2008();
5521 return false;
5522 } else if (Tok.getString() == "legacy") {
5523 Parser.Lex();
5524 getTargetStreamer().emitDirectiveNaNLegacy();
5525 return false;
5526 }
5527 }
5528 // If we don't recognize the option passed to the .nan
5529 // directive (e.g. no option or unknown option), emit an error.
5530 reportParseError("invalid option in .nan directive");
5531 return false;
5532}
5533
Jack Carter0b744b32012-10-04 02:29:46 +00005534bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005535 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005536 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005537 const AsmToken &Tok = Parser.getTok();
5538
5539 if (Tok.getString() == "noat") {
5540 return parseSetNoAtDirective();
5541 } else if (Tok.getString() == "at") {
5542 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005543 } else if (Tok.getString() == "arch") {
5544 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005545 } else if (Tok.getString() == "fp") {
5546 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005547 } else if (Tok.getString() == "oddspreg") {
5548 return parseSetOddSPRegDirective();
5549 } else if (Tok.getString() == "nooddspreg") {
5550 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005551 } else if (Tok.getString() == "pop") {
5552 return parseSetPopDirective();
5553 } else if (Tok.getString() == "push") {
5554 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005555 } else if (Tok.getString() == "reorder") {
5556 return parseSetReorderDirective();
5557 } else if (Tok.getString() == "noreorder") {
5558 return parseSetNoReorderDirective();
5559 } else if (Tok.getString() == "macro") {
5560 return parseSetMacroDirective();
5561 } else if (Tok.getString() == "nomacro") {
5562 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005563 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005564 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005565 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005566 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005567 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005568 getTargetStreamer().emitDirectiveSetNoMicroMips();
5569 Parser.eatToEndOfStatement();
5570 return false;
5571 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005572 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005573 } else if (Tok.getString() == "mips0") {
5574 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005575 } else if (Tok.getString() == "mips1") {
5576 return parseSetFeature(Mips::FeatureMips1);
5577 } else if (Tok.getString() == "mips2") {
5578 return parseSetFeature(Mips::FeatureMips2);
5579 } else if (Tok.getString() == "mips3") {
5580 return parseSetFeature(Mips::FeatureMips3);
5581 } else if (Tok.getString() == "mips4") {
5582 return parseSetFeature(Mips::FeatureMips4);
5583 } else if (Tok.getString() == "mips5") {
5584 return parseSetFeature(Mips::FeatureMips5);
5585 } else if (Tok.getString() == "mips32") {
5586 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005587 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005588 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005589 } else if (Tok.getString() == "mips32r3") {
5590 return parseSetFeature(Mips::FeatureMips32r3);
5591 } else if (Tok.getString() == "mips32r5") {
5592 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005593 } else if (Tok.getString() == "mips32r6") {
5594 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005595 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005596 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005597 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005598 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005599 } else if (Tok.getString() == "mips64r3") {
5600 return parseSetFeature(Mips::FeatureMips64r3);
5601 } else if (Tok.getString() == "mips64r5") {
5602 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005603 } else if (Tok.getString() == "mips64r6") {
5604 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005605 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005606 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005607 } else if (Tok.getString() == "nodsp") {
5608 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005609 } else if (Tok.getString() == "msa") {
5610 return parseSetMsaDirective();
5611 } else if (Tok.getString() == "nomsa") {
5612 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005613 } else if (Tok.getString() == "softfloat") {
5614 return parseSetSoftFloatDirective();
5615 } else if (Tok.getString() == "hardfloat") {
5616 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005617 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005618 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005619 parseSetAssignment();
5620 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005621 }
Jack Carter07c818d2013-01-25 01:31:34 +00005622
Jack Carter0b744b32012-10-04 02:29:46 +00005623 return true;
5624}
5625
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005626/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005627/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005628bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005629 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005630 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5631 for (;;) {
5632 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005633 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005634 return true;
5635
5636 getParser().getStreamer().EmitValue(Value, Size);
5637
5638 if (getLexer().is(AsmToken::EndOfStatement))
5639 break;
5640
Jack Carter07c818d2013-01-25 01:31:34 +00005641 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005642 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005643 Parser.Lex();
5644 }
5645 }
5646
5647 Parser.Lex();
5648 return false;
5649}
5650
Vladimir Medic4c299852013-11-06 11:27:05 +00005651/// parseDirectiveGpWord
5652/// ::= .gpword local_sym
5653bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005654 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005655 const MCExpr *Value;
5656 // EmitGPRel32Value requires an expression, so we are using base class
5657 // method to evaluate the expression.
5658 if (getParser().parseExpression(Value))
5659 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005660 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005661
Vladimir Medice10c1122013-11-13 13:18:04 +00005662 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005663 return Error(getLexer().getLoc(),
5664 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005665 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005666 return false;
5667}
5668
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005669/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005670/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005671bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005672 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005673 const MCExpr *Value;
5674 // EmitGPRel64Value requires an expression, so we are using base class
5675 // method to evaluate the expression.
5676 if (getParser().parseExpression(Value))
5677 return true;
5678 getParser().getStreamer().EmitGPRel64Value(Value);
5679
5680 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005681 return Error(getLexer().getLoc(),
5682 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005683 Parser.Lex(); // Eat EndOfStatement token.
5684 return false;
5685}
5686
Jack Carter0cd3c192014-01-06 23:27:31 +00005687bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005688 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005689 // Get the option token.
5690 AsmToken Tok = Parser.getTok();
5691 // At the moment only identifiers are supported.
5692 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005693 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005694 Parser.eatToEndOfStatement();
5695 return false;
5696 }
5697
5698 StringRef Option = Tok.getIdentifier();
5699
5700 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005701 // MipsAsmParser needs to know if the current PIC mode changes.
5702 IsPicEnabled = false;
5703
Jack Carter0cd3c192014-01-06 23:27:31 +00005704 getTargetStreamer().emitDirectiveOptionPic0();
5705 Parser.Lex();
5706 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5707 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005708 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005709 Parser.eatToEndOfStatement();
5710 }
5711 return false;
5712 }
5713
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005714 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005715 // MipsAsmParser needs to know if the current PIC mode changes.
5716 IsPicEnabled = true;
5717
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005718 getTargetStreamer().emitDirectiveOptionPic2();
5719 Parser.Lex();
5720 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5721 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005722 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005723 Parser.eatToEndOfStatement();
5724 }
5725 return false;
5726 }
5727
Jack Carter0cd3c192014-01-06 23:27:31 +00005728 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005729 Warning(Parser.getTok().getLoc(),
5730 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005731 Parser.eatToEndOfStatement();
5732 return false;
5733}
5734
Toma Tabacu9ca50962015-04-16 09:53:47 +00005735/// parseInsnDirective
5736/// ::= .insn
5737bool MipsAsmParser::parseInsnDirective() {
5738 // If this is not the end of the statement, report an error.
5739 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5740 reportParseError("unexpected token, expected end of statement");
5741 return false;
5742 }
5743
5744 // The actual label marking happens in
5745 // MipsELFStreamer::createPendingLabelRelocs().
5746 getTargetStreamer().emitDirectiveInsn();
5747
5748 getParser().Lex(); // Eat EndOfStatement token.
5749 return false;
5750}
5751
Simon Atanasyanbe186202016-02-11 06:45:54 +00005752/// parseSSectionDirective
5753/// ::= .sbss
5754/// ::= .sdata
5755bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5756 // If this is not the end of the statement, report an error.
5757 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5758 reportParseError("unexpected token, expected end of statement");
5759 return false;
5760 }
5761
5762 MCSection *ELFSection = getContext().getELFSection(
5763 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5764 getParser().getStreamer().SwitchSection(ELFSection);
5765
5766 getParser().Lex(); // Eat EndOfStatement token.
5767 return false;
5768}
5769
Daniel Sanders7e527422014-07-10 13:38:23 +00005770/// parseDirectiveModule
5771/// ::= .module oddspreg
5772/// ::= .module nooddspreg
5773/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005774/// ::= .module softfloat
5775/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005776bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005777 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005778 MCAsmLexer &Lexer = getLexer();
5779 SMLoc L = Lexer.getLoc();
5780
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005781 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005782 // TODO : get a better message.
5783 reportParseError(".module directive must appear before any code");
5784 return false;
5785 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005786
Toma Tabacuc405c822015-01-23 10:40:19 +00005787 StringRef Option;
5788 if (Parser.parseIdentifier(Option)) {
5789 reportParseError("expected .module option identifier");
5790 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005791 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005792
Toma Tabacuc405c822015-01-23 10:40:19 +00005793 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005794 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005795
Toma Tabacu3c499582015-06-25 10:56:57 +00005796 // Synchronize the abiflags information with the FeatureBits information we
5797 // changed above.
5798 getTargetStreamer().updateABIInfo(*this);
5799
5800 // If printing assembly, use the recently updated abiflags information.
5801 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5802 // emitted at the end).
5803 getTargetStreamer().emitDirectiveModuleOddSPReg();
5804
Toma Tabacuc405c822015-01-23 10:40:19 +00005805 // If this is not the end of the statement, report an error.
5806 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5807 reportParseError("unexpected token, expected end of statement");
5808 return false;
5809 }
5810
5811 return false; // parseDirectiveModule has finished successfully.
5812 } else if (Option == "nooddspreg") {
5813 if (!isABI_O32()) {
5814 Error(L, "'.module nooddspreg' requires the O32 ABI");
5815 return false;
5816 }
5817
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005818 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005819
Toma Tabacu3c499582015-06-25 10:56:57 +00005820 // Synchronize the abiflags information with the FeatureBits information we
5821 // changed above.
5822 getTargetStreamer().updateABIInfo(*this);
5823
5824 // If printing assembly, use the recently updated abiflags information.
5825 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5826 // emitted at the end).
5827 getTargetStreamer().emitDirectiveModuleOddSPReg();
5828
Toma Tabacuc405c822015-01-23 10:40:19 +00005829 // If this is not the end of the statement, report an error.
5830 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5831 reportParseError("unexpected token, expected end of statement");
5832 return false;
5833 }
5834
5835 return false; // parseDirectiveModule has finished successfully.
5836 } else if (Option == "fp") {
5837 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005838 } else if (Option == "softfloat") {
5839 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5840
5841 // Synchronize the ABI Flags information with the FeatureBits information we
5842 // updated above.
5843 getTargetStreamer().updateABIInfo(*this);
5844
5845 // If printing assembly, use the recently updated ABI Flags information.
5846 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5847 // emitted later).
5848 getTargetStreamer().emitDirectiveModuleSoftFloat();
5849
5850 // 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 == "hardfloat") {
5858 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5859
5860 // Synchronize the ABI Flags information with the FeatureBits information we
5861 // updated above.
5862 getTargetStreamer().updateABIInfo(*this);
5863
5864 // If printing assembly, use the recently updated ABI Flags information.
5865 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5866 // emitted later).
5867 getTargetStreamer().emitDirectiveModuleHardFloat();
5868
5869 // If this is not the end of the statement, report an error.
5870 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5871 reportParseError("unexpected token, expected end of statement");
5872 return false;
5873 }
5874
5875 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005876 } else {
5877 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5878 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005879}
5880
5881/// parseDirectiveModuleFP
5882/// ::= =32
5883/// ::= =xx
5884/// ::= =64
5885bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005886 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005887 MCAsmLexer &Lexer = getLexer();
5888
5889 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005890 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005891 return false;
5892 }
5893 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005894
Daniel Sanders7e527422014-07-10 13:38:23 +00005895 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005896 if (!parseFpABIValue(FpABI, ".module"))
5897 return false;
5898
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005899 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005900 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005901 return false;
5902 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005903
Toma Tabacua64e5402015-06-25 12:44:38 +00005904 // Synchronize the abiflags information with the FeatureBits information we
5905 // changed above.
5906 getTargetStreamer().updateABIInfo(*this);
5907
5908 // If printing assembly, use the recently updated abiflags information.
5909 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5910 // emitted at the end).
5911 getTargetStreamer().emitDirectiveModuleFP();
5912
Daniel Sanders7e527422014-07-10 13:38:23 +00005913 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005914 return false;
5915}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005916
Daniel Sanders7e527422014-07-10 13:38:23 +00005917bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005918 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005919 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005920 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005921 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005922
5923 if (Lexer.is(AsmToken::Identifier)) {
5924 StringRef Value = Parser.getTok().getString();
5925 Parser.Lex();
5926
5927 if (Value != "xx") {
5928 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5929 return false;
5930 }
5931
5932 if (!isABI_O32()) {
5933 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5934 return false;
5935 }
5936
Daniel Sanders7e527422014-07-10 13:38:23 +00005937 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005938 if (ModuleLevelOptions) {
5939 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5940 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5941 } else {
5942 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5943 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5944 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005945 return true;
5946 }
5947
5948 if (Lexer.is(AsmToken::Integer)) {
5949 unsigned Value = Parser.getTok().getIntVal();
5950 Parser.Lex();
5951
5952 if (Value != 32 && Value != 64) {
5953 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5954 return false;
5955 }
5956
5957 if (Value == 32) {
5958 if (!isABI_O32()) {
5959 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5960 return false;
5961 }
5962
Daniel Sanders7e527422014-07-10 13:38:23 +00005963 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005964 if (ModuleLevelOptions) {
5965 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5966 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5967 } else {
5968 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5969 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5970 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005971 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005972 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005973 if (ModuleLevelOptions) {
5974 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5975 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5976 } else {
5977 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5978 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5979 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005980 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005981
Daniel Sanders7e527422014-07-10 13:38:23 +00005982 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005983 }
5984
5985 return false;
5986}
5987
Jack Carter0b744b32012-10-04 02:29:46 +00005988bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Nirav Dave996fc132016-05-05 14:15:46 +00005989 // This returns false if this function recognizes the directive
5990 // regardless of whether it is successfully handles or reports an
5991 // error. Otherwise it returns true to give the generic parser a
5992 // chance at recognizing it.
5993
Rafael Espindola961d4692014-11-11 05:18:41 +00005994 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005995 StringRef IDVal = DirectiveID.getString();
5996
Nirav Dave996fc132016-05-05 14:15:46 +00005997 if (IDVal == ".cpload") {
5998 parseDirectiveCpLoad(DirectiveID.getLoc());
5999 return false;
6000 }
6001 if (IDVal == ".cprestore") {
6002 parseDirectiveCpRestore(DirectiveID.getLoc());
6003 return false;
6004 }
Matheus Almeidaab5633b2014-03-26 15:44:18 +00006005 if (IDVal == ".dword") {
6006 parseDataDirective(8, DirectiveID.getLoc());
6007 return false;
6008 }
Jack Carterd0bd6422013-04-18 00:41:53 +00006009 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006010 StringRef SymbolName;
6011
6012 if (Parser.parseIdentifier(SymbolName)) {
6013 reportParseError("expected identifier after .ent");
6014 return false;
6015 }
6016
6017 // There's an undocumented extension that allows an integer to
6018 // follow the name of the procedure which AFAICS is ignored by GAS.
6019 // Example: .ent foo,2
6020 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6021 if (getLexer().isNot(AsmToken::Comma)) {
6022 // Even though we accept this undocumented extension for compatibility
6023 // reasons, the additional integer argument does not actually change
6024 // the behaviour of the '.ent' directive, so we would like to discourage
6025 // its use. We do this by not referring to the extended version in
6026 // error messages which are not directly related to its use.
6027 reportParseError("unexpected token, expected end of statement");
6028 return false;
6029 }
6030 Parser.Lex(); // Eat the comma.
6031 const MCExpr *DummyNumber;
6032 int64_t DummyNumberVal;
6033 // If the user was explicitly trying to use the extended version,
6034 // we still give helpful extension-related error messages.
6035 if (Parser.parseExpression(DummyNumber)) {
6036 reportParseError("expected number after comma");
6037 return false;
6038 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006039 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006040 reportParseError("expected an absolute expression after comma");
6041 return false;
6042 }
6043 }
6044
6045 // If this is not the end of the statement, report an error.
6046 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6047 reportParseError("unexpected token, expected end of statement");
6048 return false;
6049 }
6050
Jim Grosbach6f482002015-05-18 18:43:14 +00006051 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006052
6053 getTargetStreamer().emitDirectiveEnt(*Sym);
6054 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006055 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006056 return false;
6057 }
6058
Jack Carter07c818d2013-01-25 01:31:34 +00006059 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006060 StringRef SymbolName;
6061
6062 if (Parser.parseIdentifier(SymbolName)) {
6063 reportParseError("expected identifier after .end");
6064 return false;
6065 }
6066
6067 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6068 reportParseError("unexpected token, expected end of statement");
6069 return false;
6070 }
6071
6072 if (CurrentFn == nullptr) {
6073 reportParseError(".end used without .ent");
6074 return false;
6075 }
6076
6077 if ((SymbolName != CurrentFn->getName())) {
6078 reportParseError(".end symbol does not match .ent symbol");
6079 return false;
6080 }
6081
6082 getTargetStreamer().emitDirectiveEnd(SymbolName);
6083 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006084 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006085 return false;
6086 }
6087
Jack Carter07c818d2013-01-25 01:31:34 +00006088 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006089 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6090 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006091 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006092 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6093 reportParseError("expected stack register");
6094 return false;
6095 }
6096
6097 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6098 if (!StackRegOpnd.isGPRAsmReg()) {
6099 reportParseError(StackRegOpnd.getStartLoc(),
6100 "expected general purpose register");
6101 return false;
6102 }
6103 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6104
6105 if (Parser.getTok().is(AsmToken::Comma))
6106 Parser.Lex();
6107 else {
6108 reportParseError("unexpected token, expected comma");
6109 return false;
6110 }
6111
6112 // Parse the frame size.
6113 const MCExpr *FrameSize;
6114 int64_t FrameSizeVal;
6115
6116 if (Parser.parseExpression(FrameSize)) {
6117 reportParseError("expected frame size value");
6118 return false;
6119 }
6120
Jim Grosbach13760bd2015-05-30 01:25:56 +00006121 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006122 reportParseError("frame size not an absolute expression");
6123 return false;
6124 }
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 return register.
6134 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006135 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006136 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6137 reportParseError("expected return register");
6138 return false;
6139 }
6140
6141 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6142 if (!ReturnRegOpnd.isGPRAsmReg()) {
6143 reportParseError(ReturnRegOpnd.getStartLoc(),
6144 "expected general purpose register");
6145 return false;
6146 }
6147
6148 // If this is not the end of the statement, report an error.
6149 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6150 reportParseError("unexpected token, expected end of statement");
6151 return false;
6152 }
6153
6154 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6155 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006156 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006157 return false;
6158 }
6159
Jack Carter07c818d2013-01-25 01:31:34 +00006160 if (IDVal == ".set") {
Nirav Dave996fc132016-05-05 14:15:46 +00006161 parseDirectiveSet();
6162 return false;
Jack Carterbe332172012-09-07 00:48:02 +00006163 }
6164
Daniel Sandersd97a6342014-08-13 10:07:34 +00006165 if (IDVal == ".mask" || IDVal == ".fmask") {
6166 // .mask bitmask, frame_offset
6167 // bitmask: One bit for each register used.
6168 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6169 // first register is expected to be saved.
6170 // Examples:
6171 // .mask 0x80000000, -4
6172 // .fmask 0x80000000, -4
6173 //
Jack Carterbe332172012-09-07 00:48:02 +00006174
Daniel Sandersd97a6342014-08-13 10:07:34 +00006175 // Parse the bitmask
6176 const MCExpr *BitMask;
6177 int64_t BitMaskVal;
6178
6179 if (Parser.parseExpression(BitMask)) {
6180 reportParseError("expected bitmask value");
6181 return false;
6182 }
6183
Jim Grosbach13760bd2015-05-30 01:25:56 +00006184 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006185 reportParseError("bitmask not an absolute expression");
6186 return false;
6187 }
6188
6189 if (Parser.getTok().is(AsmToken::Comma))
6190 Parser.Lex();
6191 else {
6192 reportParseError("unexpected token, expected comma");
6193 return false;
6194 }
6195
6196 // Parse the frame_offset
6197 const MCExpr *FrameOffset;
6198 int64_t FrameOffsetVal;
6199
6200 if (Parser.parseExpression(FrameOffset)) {
6201 reportParseError("expected frame offset value");
6202 return false;
6203 }
6204
Jim Grosbach13760bd2015-05-30 01:25:56 +00006205 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006206 reportParseError("frame offset not an absolute expression");
6207 return false;
6208 }
6209
6210 // If this is not the end of the statement, report an error.
6211 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6212 reportParseError("unexpected token, expected end of statement");
6213 return false;
6214 }
6215
6216 if (IDVal == ".mask")
6217 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6218 else
6219 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006220 return false;
6221 }
6222
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006223 if (IDVal == ".nan")
6224 return parseDirectiveNaN();
6225
Jack Carter07c818d2013-01-25 01:31:34 +00006226 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006227 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006228 return false;
6229 }
6230
Rafael Espindolab59fb732014-03-28 18:50:26 +00006231 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006232 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006233 return false;
6234 }
6235
Jack Carter07c818d2013-01-25 01:31:34 +00006236 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006237 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006238 return false;
6239 }
6240
Scott Egertond1aeb052016-02-15 16:11:51 +00006241 if (IDVal == ".hword") {
6242 parseDataDirective(2, DirectiveID.getLoc());
6243 return false;
6244 }
6245
Nirav Dave996fc132016-05-05 14:15:46 +00006246 if (IDVal == ".option") {
6247 parseDirectiveOption();
6248 return false;
6249 }
Jack Carter0cd3c192014-01-06 23:27:31 +00006250
6251 if (IDVal == ".abicalls") {
6252 getTargetStreamer().emitDirectiveAbiCalls();
6253 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006254 Error(Parser.getTok().getLoc(),
6255 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006256 // Clear line
6257 Parser.eatToEndOfStatement();
6258 }
6259 return false;
6260 }
6261
Nirav Dave996fc132016-05-05 14:15:46 +00006262 if (IDVal == ".cpsetup") {
6263 parseDirectiveCPSetup();
6264 return false;
6265 }
6266 if (IDVal == ".cpreturn") {
6267 parseDirectiveCPReturn();
6268 return false;
6269 }
6270 if (IDVal == ".module") {
6271 parseDirectiveModule();
6272 return false;
6273 }
6274 if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
6275 parseInternalDirectiveReallowModule();
6276 return false;
6277 }
6278 if (IDVal == ".insn") {
6279 parseInsnDirective();
6280 return false;
6281 }
6282 if (IDVal == ".sbss") {
6283 parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6284 return false;
6285 }
6286 if (IDVal == ".sdata") {
6287 parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6288 return false;
6289 }
Simon Atanasyanbe186202016-02-11 06:45:54 +00006290
Rafael Espindola870c4e92012-01-11 03:56:41 +00006291 return true;
6292}
6293
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006294bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6295 // If this is not the end of the statement, report an error.
6296 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6297 reportParseError("unexpected token, expected end of statement");
6298 return false;
6299 }
6300
6301 getTargetStreamer().reallowModuleDirective();
6302
6303 getParser().Lex(); // Eat EndOfStatement token.
6304 return false;
6305}
6306
Rafael Espindola870c4e92012-01-11 03:56:41 +00006307extern "C" void LLVMInitializeMipsAsmParser() {
6308 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6309 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6310 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6311 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6312}
Jack Carterb4dbc172012-09-05 23:34:03 +00006313
6314#define GET_REGISTER_MATCHER
6315#define GET_MATCHER_IMPLEMENTATION
6316#include "MipsGenAsmMatcher.inc"