blob: eff27b75e760a0c4f4c6ed3f41fb8f692293d4e9 [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
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004833bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004834 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004835 SMLoc Loc = getLexer().getLoc();
4836 Parser.eatToEndOfStatement();
4837 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004838}
4839
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004840bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004841 return Error(Loc, ErrorMsg);
4842}
4843
Jack Carter0b744b32012-10-04 02:29:46 +00004844bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004845 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004846 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004847
4848 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004849 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004850
4851 Parser.Lex(); // Eat "noat".
4852
Jack Carterd0bd6422013-04-18 00:41:53 +00004853 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004854 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004855 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004856 return false;
4857 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004858
4859 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004860 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004861 return false;
4862}
Jack Carterd0bd6422013-04-18 00:41:53 +00004863
Jack Carter0b744b32012-10-04 02:29:46 +00004864bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004865 // Line can be: ".set at", which sets $at to $1
4866 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004867 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004868 Parser.Lex(); // Eat "at".
4869
Jack Carter0b744b32012-10-04 02:29:46 +00004870 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004871 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004872 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004873
4874 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004875 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004876 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004877 }
4878
4879 if (getLexer().isNot(AsmToken::Equal)) {
4880 reportParseError("unexpected token, expected equals sign");
4881 return false;
4882 }
4883 Parser.Lex(); // Eat "=".
4884
4885 if (getLexer().isNot(AsmToken::Dollar)) {
4886 if (getLexer().is(AsmToken::EndOfStatement)) {
4887 reportParseError("no register specified");
4888 return false;
4889 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004890 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004891 return false;
4892 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004893 }
4894 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004895
Toma Tabacu16a74492015-02-13 10:30:57 +00004896 // Find out what "reg" is.
4897 unsigned AtRegNo;
4898 const AsmToken &Reg = Parser.getTok();
4899 if (Reg.is(AsmToken::Identifier)) {
4900 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4901 } else if (Reg.is(AsmToken::Integer)) {
4902 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004903 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004904 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004905 return false;
4906 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004907
4908 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004909 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004910 reportParseError("invalid register");
4911 return false;
4912 }
4913 Parser.Lex(); // Eat "reg".
4914
4915 // If this is not the end of the statement, report an error.
4916 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4917 reportParseError("unexpected token, expected end of statement");
4918 return false;
4919 }
4920
4921 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4922
4923 Parser.Lex(); // Consume the EndOfStatement.
4924 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004925}
4926
4927bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004928 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004929 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004930 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004931 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004932 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004933 return false;
4934 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004935 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004936 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004937 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004938 return false;
4939}
4940
4941bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004942 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004943 Parser.Lex();
4944 // If this is not the end of the statement, report an error.
4945 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004946 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004947 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004948 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004949 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004950 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004951 Parser.Lex(); // Consume the EndOfStatement.
4952 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004953}
4954
4955bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004956 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004957 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004958 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004959 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004960 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004961 return false;
4962 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004963 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004964 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004965 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004966 return false;
4967}
4968
4969bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004970 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004971 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004972 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004973 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004974 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004975 return false;
4976 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004977 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004978 reportParseError("`noreorder' must be set before `nomacro'");
4979 return false;
4980 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004981 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004982 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004983 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004984 return false;
4985}
Jack Carterd76b2372013-03-21 21:44:16 +00004986
Daniel Sanders44934432014-08-07 12:03:36 +00004987bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004988 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004989 Parser.Lex();
4990
4991 // If this is not the end of the statement, report an error.
4992 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004993 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004994
4995 setFeatureBits(Mips::FeatureMSA, "msa");
4996 getTargetStreamer().emitDirectiveSetMsa();
4997 return false;
4998}
4999
5000bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005001 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00005002 Parser.Lex();
5003
5004 // If this is not the end of the statement, report an error.
5005 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005006 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00005007
5008 clearFeatureBits(Mips::FeatureMSA, "msa");
5009 getTargetStreamer().emitDirectiveSetNoMsa();
5010 return false;
5011}
5012
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005013bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005014 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005015 Parser.Lex(); // Eat "nodsp".
5016
5017 // If this is not the end of the statement, report an error.
5018 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5019 reportParseError("unexpected token, expected end of statement");
5020 return false;
5021 }
5022
5023 clearFeatureBits(Mips::FeatureDSP, "dsp");
5024 getTargetStreamer().emitDirectiveSetNoDsp();
5025 return false;
5026}
5027
Toma Tabacucc2502d2014-11-04 17:18:07 +00005028bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005029 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005030 Parser.Lex(); // Eat "mips16".
5031
Jack Carter39536722014-01-22 23:08:42 +00005032 // If this is not the end of the statement, report an error.
5033 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005034 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00005035 return false;
5036 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00005037
5038 setFeatureBits(Mips::FeatureMips16, "mips16");
5039 getTargetStreamer().emitDirectiveSetMips16();
5040 Parser.Lex(); // Consume the EndOfStatement.
5041 return false;
5042}
5043
5044bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005045 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00005046 Parser.Lex(); // Eat "nomips16".
5047
5048 // If this is not the end of the statement, report an error.
5049 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5050 reportParseError("unexpected token, expected end of statement");
5051 return false;
5052 }
5053
5054 clearFeatureBits(Mips::FeatureMips16, "mips16");
5055 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00005056 Parser.Lex(); // Consume the EndOfStatement.
5057 return false;
5058}
5059
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005060bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005061 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005062 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005063 // Line can be: .set fp=32
5064 // .set fp=xx
5065 // .set fp=64
5066 Parser.Lex(); // Eat fp token
5067 AsmToken Tok = Parser.getTok();
5068 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005069 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005070 return false;
5071 }
5072 Parser.Lex(); // Eat '=' token.
5073 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005074
5075 if (!parseFpABIValue(FpAbiVal, ".set"))
5076 return false;
5077
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005078 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005079 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005080 return false;
5081 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005082 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005083 Parser.Lex(); // Consume the EndOfStatement.
5084 return false;
5085}
5086
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005087bool MipsAsmParser::parseSetOddSPRegDirective() {
5088 MCAsmParser &Parser = getParser();
5089
5090 Parser.Lex(); // Eat "oddspreg".
5091 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5092 reportParseError("unexpected token, expected end of statement");
5093 return false;
5094 }
5095
5096 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5097 getTargetStreamer().emitDirectiveSetOddSPReg();
5098 return false;
5099}
5100
5101bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5102 MCAsmParser &Parser = getParser();
5103
5104 Parser.Lex(); // Eat "nooddspreg".
5105 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5106 reportParseError("unexpected token, expected end of statement");
5107 return false;
5108 }
5109
5110 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5111 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5112 return false;
5113}
5114
Toma Tabacu9db22db2014-09-09 10:15:38 +00005115bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005116 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005117 SMLoc Loc = getLexer().getLoc();
5118
5119 Parser.Lex();
5120 if (getLexer().isNot(AsmToken::EndOfStatement))
5121 return reportParseError("unexpected token, expected end of statement");
5122
5123 // Always keep an element on the options "stack" to prevent the user
5124 // from changing the initial options. This is how we remember them.
5125 if (AssemblerOptions.size() == 2)
5126 return reportParseError(Loc, ".set pop with no .set push");
5127
Akira Hatanakab11ef082015-11-14 06:35:56 +00005128 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005129 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005130 setAvailableFeatures(
5131 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5132 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005133
5134 getTargetStreamer().emitDirectiveSetPop();
5135 return false;
5136}
5137
5138bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005139 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005140 Parser.Lex();
5141 if (getLexer().isNot(AsmToken::EndOfStatement))
5142 return reportParseError("unexpected token, expected end of statement");
5143
5144 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005145 AssemblerOptions.push_back(
5146 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005147
5148 getTargetStreamer().emitDirectiveSetPush();
5149 return false;
5150}
5151
Toma Tabacu29696502015-06-02 09:48:04 +00005152bool MipsAsmParser::parseSetSoftFloatDirective() {
5153 MCAsmParser &Parser = getParser();
5154 Parser.Lex();
5155 if (getLexer().isNot(AsmToken::EndOfStatement))
5156 return reportParseError("unexpected token, expected end of statement");
5157
5158 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5159 getTargetStreamer().emitDirectiveSetSoftFloat();
5160 return false;
5161}
5162
5163bool MipsAsmParser::parseSetHardFloatDirective() {
5164 MCAsmParser &Parser = getParser();
5165 Parser.Lex();
5166 if (getLexer().isNot(AsmToken::EndOfStatement))
5167 return reportParseError("unexpected token, expected end of statement");
5168
5169 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5170 getTargetStreamer().emitDirectiveSetHardFloat();
5171 return false;
5172}
5173
Jack Carterd76b2372013-03-21 21:44:16 +00005174bool MipsAsmParser::parseSetAssignment() {
5175 StringRef Name;
5176 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005177 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005178
5179 if (Parser.parseIdentifier(Name))
5180 reportParseError("expected identifier after .set");
5181
5182 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005183 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005184 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005185
Jack Carter3b2c96e2014-01-22 23:31:38 +00005186 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005187 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005188
Jim Grosbach6f482002015-05-18 18:43:14 +00005189 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005190 Sym->setVariableValue(Value);
5191
5192 return false;
5193}
Jack Carterd0bd6422013-04-18 00:41:53 +00005194
Toma Tabacu26647792014-09-09 12:52:14 +00005195bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005196 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005197 Parser.Lex();
5198 if (getLexer().isNot(AsmToken::EndOfStatement))
5199 return reportParseError("unexpected token, expected end of statement");
5200
5201 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005202 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005203 setAvailableFeatures(
5204 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5205 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005206 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5207
5208 getTargetStreamer().emitDirectiveSetMips0();
5209 return false;
5210}
5211
Toma Tabacu85618b32014-08-19 14:22:52 +00005212bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005213 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005214 Parser.Lex();
5215 if (getLexer().isNot(AsmToken::Equal))
5216 return reportParseError("unexpected token, expected equals sign");
5217
5218 Parser.Lex();
5219 StringRef Arch;
5220 if (Parser.parseIdentifier(Arch))
5221 return reportParseError("expected arch identifier");
5222
5223 StringRef ArchFeatureName =
5224 StringSwitch<StringRef>(Arch)
5225 .Case("mips1", "mips1")
5226 .Case("mips2", "mips2")
5227 .Case("mips3", "mips3")
5228 .Case("mips4", "mips4")
5229 .Case("mips5", "mips5")
5230 .Case("mips32", "mips32")
5231 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005232 .Case("mips32r3", "mips32r3")
5233 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005234 .Case("mips32r6", "mips32r6")
5235 .Case("mips64", "mips64")
5236 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005237 .Case("mips64r3", "mips64r3")
5238 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005239 .Case("mips64r6", "mips64r6")
Petar Jovanovic48e4db12016-04-12 15:28:16 +00005240 .Case("octeon", "cnmips")
Toma Tabacu85618b32014-08-19 14:22:52 +00005241 .Case("r4000", "mips3") // This is an implementation of Mips3.
5242 .Default("");
5243
5244 if (ArchFeatureName.empty())
5245 return reportParseError("unsupported architecture");
5246
5247 selectArch(ArchFeatureName);
5248 getTargetStreamer().emitDirectiveSetArch(Arch);
5249 return false;
5250}
5251
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005252bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005253 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005254 Parser.Lex();
5255 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005256 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005257
Matheus Almeida2852af82014-04-22 10:15:54 +00005258 switch (Feature) {
5259 default:
5260 llvm_unreachable("Unimplemented feature");
5261 case Mips::FeatureDSP:
5262 setFeatureBits(Mips::FeatureDSP, "dsp");
5263 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005264 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005265 case Mips::FeatureMicroMips:
5266 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005267 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005268 case Mips::FeatureMips1:
5269 selectArch("mips1");
5270 getTargetStreamer().emitDirectiveSetMips1();
5271 break;
5272 case Mips::FeatureMips2:
5273 selectArch("mips2");
5274 getTargetStreamer().emitDirectiveSetMips2();
5275 break;
5276 case Mips::FeatureMips3:
5277 selectArch("mips3");
5278 getTargetStreamer().emitDirectiveSetMips3();
5279 break;
5280 case Mips::FeatureMips4:
5281 selectArch("mips4");
5282 getTargetStreamer().emitDirectiveSetMips4();
5283 break;
5284 case Mips::FeatureMips5:
5285 selectArch("mips5");
5286 getTargetStreamer().emitDirectiveSetMips5();
5287 break;
5288 case Mips::FeatureMips32:
5289 selectArch("mips32");
5290 getTargetStreamer().emitDirectiveSetMips32();
5291 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005292 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005293 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005294 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005295 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005296 case Mips::FeatureMips32r3:
5297 selectArch("mips32r3");
5298 getTargetStreamer().emitDirectiveSetMips32R3();
5299 break;
5300 case Mips::FeatureMips32r5:
5301 selectArch("mips32r5");
5302 getTargetStreamer().emitDirectiveSetMips32R5();
5303 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005304 case Mips::FeatureMips32r6:
5305 selectArch("mips32r6");
5306 getTargetStreamer().emitDirectiveSetMips32R6();
5307 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005308 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005309 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005310 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005311 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005312 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005313 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005314 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005315 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005316 case Mips::FeatureMips64r3:
5317 selectArch("mips64r3");
5318 getTargetStreamer().emitDirectiveSetMips64R3();
5319 break;
5320 case Mips::FeatureMips64r5:
5321 selectArch("mips64r5");
5322 getTargetStreamer().emitDirectiveSetMips64R5();
5323 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005324 case Mips::FeatureMips64r6:
5325 selectArch("mips64r6");
5326 getTargetStreamer().emitDirectiveSetMips64R6();
5327 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005328 }
5329 return false;
5330}
5331
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005332bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005333 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005334 if (getLexer().isNot(AsmToken::Comma)) {
5335 SMLoc Loc = getLexer().getLoc();
5336 Parser.eatToEndOfStatement();
5337 return Error(Loc, ErrorStr);
5338 }
5339
Matheus Almeida2852af82014-04-22 10:15:54 +00005340 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005341 return true;
5342}
5343
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005344// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5345// In this class, it is only used for .cprestore.
5346// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5347// MipsTargetELFStreamer and MipsAsmParser.
5348bool MipsAsmParser::isPicAndNotNxxAbi() {
5349 return inPicMode() && !(isABI_N32() || isABI_N64());
5350}
5351
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005352bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005353 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005354 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005355
Toma Tabacudde4c462014-11-06 10:02:45 +00005356 if (inMips16Mode()) {
5357 reportParseError(".cpload is not supported in Mips16 mode");
5358 return false;
5359 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005360
David Blaikie960ea3f2014-06-08 16:18:35 +00005361 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005362 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005363 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5364 reportParseError("expected register containing function address");
5365 return false;
5366 }
5367
David Blaikie960ea3f2014-06-08 16:18:35 +00005368 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5369 if (!RegOpnd.isGPRAsmReg()) {
5370 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005371 return false;
5372 }
5373
Toma Tabacudde4c462014-11-06 10:02:45 +00005374 // If this is not the end of the statement, report an error.
5375 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5376 reportParseError("unexpected token, expected end of statement");
5377 return false;
5378 }
5379
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005380 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005381 return false;
5382}
5383
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005384bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5385 MCAsmParser &Parser = getParser();
5386
5387 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5388 // is used in non-PIC mode.
5389
5390 if (inMips16Mode()) {
5391 reportParseError(".cprestore is not supported in Mips16 mode");
5392 return false;
5393 }
5394
5395 // Get the stack offset value.
5396 const MCExpr *StackOffset;
5397 int64_t StackOffsetVal;
5398 if (Parser.parseExpression(StackOffset)) {
5399 reportParseError("expected stack offset value");
5400 return false;
5401 }
5402
5403 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5404 reportParseError("stack offset is not an absolute expression");
5405 return false;
5406 }
5407
5408 if (StackOffsetVal < 0) {
5409 Warning(Loc, ".cprestore with negative stack offset has no effect");
5410 IsCpRestoreSet = false;
5411 } else {
5412 IsCpRestoreSet = true;
5413 CpRestoreOffset = StackOffsetVal;
5414 }
5415
5416 // If this is not the end of the statement, report an error.
5417 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5418 reportParseError("unexpected token, expected end of statement");
5419 return false;
5420 }
5421
Daniel Sanders7225cd52016-04-29 16:16:49 +00005422 unsigned ATReg = getATReg(Loc);
5423 if (!ATReg)
5424 return true;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005425
Daniel Sanders7225cd52016-04-29 16:16:49 +00005426 getTargetStreamer().emitDirectiveCpRestore(CpRestoreOffset, ATReg, Loc, STI);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005427 Parser.Lex(); // Consume the EndOfStatement.
5428 return false;
5429}
5430
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005431bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005432 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005433 unsigned FuncReg;
5434 unsigned Save;
5435 bool SaveIsReg = true;
5436
Matheus Almeida7e815762014-06-18 13:08:59 +00005437 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005438 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005439 if (ResTy == MatchOperand_NoMatch) {
5440 reportParseError("expected register containing function address");
5441 Parser.eatToEndOfStatement();
5442 return false;
5443 }
5444
5445 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5446 if (!FuncRegOpnd.isGPRAsmReg()) {
5447 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5448 Parser.eatToEndOfStatement();
5449 return false;
5450 }
5451
5452 FuncReg = FuncRegOpnd.getGPR32Reg();
5453 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005454
Toma Tabacu65f10572014-09-16 15:00:52 +00005455 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005456 return true;
5457
Toma Tabacu13964452014-09-04 13:23:44 +00005458 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005459 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005460 const MCExpr *OffsetExpr;
5461 int64_t OffsetVal;
5462 SMLoc ExprLoc = getLexer().getLoc();
5463
5464 if (Parser.parseExpression(OffsetExpr) ||
5465 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5466 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005467 Parser.eatToEndOfStatement();
5468 return false;
5469 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005470
5471 Save = OffsetVal;
5472 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005473 } else {
5474 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5475 if (!SaveOpnd.isGPRAsmReg()) {
5476 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5477 Parser.eatToEndOfStatement();
5478 return false;
5479 }
5480 Save = SaveOpnd.getGPR32Reg();
5481 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005482
Toma Tabacu65f10572014-09-16 15:00:52 +00005483 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005484 return true;
5485
Toma Tabacu8874eac2015-02-18 13:46:53 +00005486 const MCExpr *Expr;
5487 if (Parser.parseExpression(Expr)) {
5488 reportParseError("expected expression");
5489 return false;
5490 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005491
Toma Tabacu8874eac2015-02-18 13:46:53 +00005492 if (Expr->getKind() != MCExpr::SymbolRef) {
5493 reportParseError("expected symbol");
5494 return false;
5495 }
5496 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5497
Daniel Sandersf173dda2015-09-22 10:50:09 +00005498 CpSaveLocation = Save;
5499 CpSaveLocationIsRegister = SaveIsReg;
5500
Toma Tabacu8874eac2015-02-18 13:46:53 +00005501 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5502 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005503 return false;
5504}
5505
Daniel Sandersf173dda2015-09-22 10:50:09 +00005506bool MipsAsmParser::parseDirectiveCPReturn() {
5507 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5508 CpSaveLocationIsRegister);
5509 return false;
5510}
5511
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005512bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005513 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005514 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5515 const AsmToken &Tok = Parser.getTok();
5516
5517 if (Tok.getString() == "2008") {
5518 Parser.Lex();
5519 getTargetStreamer().emitDirectiveNaN2008();
5520 return false;
5521 } else if (Tok.getString() == "legacy") {
5522 Parser.Lex();
5523 getTargetStreamer().emitDirectiveNaNLegacy();
5524 return false;
5525 }
5526 }
5527 // If we don't recognize the option passed to the .nan
5528 // directive (e.g. no option or unknown option), emit an error.
5529 reportParseError("invalid option in .nan directive");
5530 return false;
5531}
5532
Jack Carter0b744b32012-10-04 02:29:46 +00005533bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005534 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005535 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005536 const AsmToken &Tok = Parser.getTok();
5537
5538 if (Tok.getString() == "noat") {
5539 return parseSetNoAtDirective();
5540 } else if (Tok.getString() == "at") {
5541 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005542 } else if (Tok.getString() == "arch") {
5543 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005544 } else if (Tok.getString() == "fp") {
5545 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005546 } else if (Tok.getString() == "oddspreg") {
5547 return parseSetOddSPRegDirective();
5548 } else if (Tok.getString() == "nooddspreg") {
5549 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005550 } else if (Tok.getString() == "pop") {
5551 return parseSetPopDirective();
5552 } else if (Tok.getString() == "push") {
5553 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005554 } else if (Tok.getString() == "reorder") {
5555 return parseSetReorderDirective();
5556 } else if (Tok.getString() == "noreorder") {
5557 return parseSetNoReorderDirective();
5558 } else if (Tok.getString() == "macro") {
5559 return parseSetMacroDirective();
5560 } else if (Tok.getString() == "nomacro") {
5561 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005562 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005563 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005564 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005565 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005566 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005567 getTargetStreamer().emitDirectiveSetNoMicroMips();
5568 Parser.eatToEndOfStatement();
5569 return false;
5570 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005571 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005572 } else if (Tok.getString() == "mips0") {
5573 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005574 } else if (Tok.getString() == "mips1") {
5575 return parseSetFeature(Mips::FeatureMips1);
5576 } else if (Tok.getString() == "mips2") {
5577 return parseSetFeature(Mips::FeatureMips2);
5578 } else if (Tok.getString() == "mips3") {
5579 return parseSetFeature(Mips::FeatureMips3);
5580 } else if (Tok.getString() == "mips4") {
5581 return parseSetFeature(Mips::FeatureMips4);
5582 } else if (Tok.getString() == "mips5") {
5583 return parseSetFeature(Mips::FeatureMips5);
5584 } else if (Tok.getString() == "mips32") {
5585 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005586 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005587 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005588 } else if (Tok.getString() == "mips32r3") {
5589 return parseSetFeature(Mips::FeatureMips32r3);
5590 } else if (Tok.getString() == "mips32r5") {
5591 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005592 } else if (Tok.getString() == "mips32r6") {
5593 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005594 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005595 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005596 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005597 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005598 } else if (Tok.getString() == "mips64r3") {
5599 return parseSetFeature(Mips::FeatureMips64r3);
5600 } else if (Tok.getString() == "mips64r5") {
5601 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005602 } else if (Tok.getString() == "mips64r6") {
5603 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005604 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005605 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005606 } else if (Tok.getString() == "nodsp") {
5607 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005608 } else if (Tok.getString() == "msa") {
5609 return parseSetMsaDirective();
5610 } else if (Tok.getString() == "nomsa") {
5611 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005612 } else if (Tok.getString() == "softfloat") {
5613 return parseSetSoftFloatDirective();
5614 } else if (Tok.getString() == "hardfloat") {
5615 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005616 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005617 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005618 parseSetAssignment();
5619 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005620 }
Jack Carter07c818d2013-01-25 01:31:34 +00005621
Jack Carter0b744b32012-10-04 02:29:46 +00005622 return true;
5623}
5624
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005625/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005626/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005627bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005628 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005629 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5630 for (;;) {
5631 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005632 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005633 return true;
5634
5635 getParser().getStreamer().EmitValue(Value, Size);
5636
5637 if (getLexer().is(AsmToken::EndOfStatement))
5638 break;
5639
Jack Carter07c818d2013-01-25 01:31:34 +00005640 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005641 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005642 Parser.Lex();
5643 }
5644 }
5645
5646 Parser.Lex();
5647 return false;
5648}
5649
Vladimir Medic4c299852013-11-06 11:27:05 +00005650/// parseDirectiveGpWord
5651/// ::= .gpword local_sym
5652bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005653 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005654 const MCExpr *Value;
5655 // EmitGPRel32Value requires an expression, so we are using base class
5656 // method to evaluate the expression.
5657 if (getParser().parseExpression(Value))
5658 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005659 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005660
Vladimir Medice10c1122013-11-13 13:18:04 +00005661 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005662 return Error(getLexer().getLoc(),
5663 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005664 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005665 return false;
5666}
5667
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005668/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005669/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005670bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005671 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005672 const MCExpr *Value;
5673 // EmitGPRel64Value requires an expression, so we are using base class
5674 // method to evaluate the expression.
5675 if (getParser().parseExpression(Value))
5676 return true;
5677 getParser().getStreamer().EmitGPRel64Value(Value);
5678
5679 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005680 return Error(getLexer().getLoc(),
5681 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005682 Parser.Lex(); // Eat EndOfStatement token.
5683 return false;
5684}
5685
Jack Carter0cd3c192014-01-06 23:27:31 +00005686bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005687 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005688 // Get the option token.
5689 AsmToken Tok = Parser.getTok();
5690 // At the moment only identifiers are supported.
5691 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005692 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005693 Parser.eatToEndOfStatement();
5694 return false;
5695 }
5696
5697 StringRef Option = Tok.getIdentifier();
5698
5699 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005700 // MipsAsmParser needs to know if the current PIC mode changes.
5701 IsPicEnabled = false;
5702
Jack Carter0cd3c192014-01-06 23:27:31 +00005703 getTargetStreamer().emitDirectiveOptionPic0();
5704 Parser.Lex();
5705 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5706 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005707 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005708 Parser.eatToEndOfStatement();
5709 }
5710 return false;
5711 }
5712
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005713 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005714 // MipsAsmParser needs to know if the current PIC mode changes.
5715 IsPicEnabled = true;
5716
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005717 getTargetStreamer().emitDirectiveOptionPic2();
5718 Parser.Lex();
5719 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5720 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005721 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005722 Parser.eatToEndOfStatement();
5723 }
5724 return false;
5725 }
5726
Jack Carter0cd3c192014-01-06 23:27:31 +00005727 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005728 Warning(Parser.getTok().getLoc(),
5729 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005730 Parser.eatToEndOfStatement();
5731 return false;
5732}
5733
Toma Tabacu9ca50962015-04-16 09:53:47 +00005734/// parseInsnDirective
5735/// ::= .insn
5736bool MipsAsmParser::parseInsnDirective() {
5737 // If this is not the end of the statement, report an error.
5738 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5739 reportParseError("unexpected token, expected end of statement");
5740 return false;
5741 }
5742
5743 // The actual label marking happens in
5744 // MipsELFStreamer::createPendingLabelRelocs().
5745 getTargetStreamer().emitDirectiveInsn();
5746
5747 getParser().Lex(); // Eat EndOfStatement token.
5748 return false;
5749}
5750
Simon Atanasyanbe186202016-02-11 06:45:54 +00005751/// parseSSectionDirective
5752/// ::= .sbss
5753/// ::= .sdata
5754bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
5755 // If this is not the end of the statement, report an error.
5756 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5757 reportParseError("unexpected token, expected end of statement");
5758 return false;
5759 }
5760
5761 MCSection *ELFSection = getContext().getELFSection(
5762 Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
5763 getParser().getStreamer().SwitchSection(ELFSection);
5764
5765 getParser().Lex(); // Eat EndOfStatement token.
5766 return false;
5767}
5768
Daniel Sanders7e527422014-07-10 13:38:23 +00005769/// parseDirectiveModule
5770/// ::= .module oddspreg
5771/// ::= .module nooddspreg
5772/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005773/// ::= .module softfloat
5774/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005775bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005776 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005777 MCAsmLexer &Lexer = getLexer();
5778 SMLoc L = Lexer.getLoc();
5779
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005780 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005781 // TODO : get a better message.
5782 reportParseError(".module directive must appear before any code");
5783 return false;
5784 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005785
Toma Tabacuc405c822015-01-23 10:40:19 +00005786 StringRef Option;
5787 if (Parser.parseIdentifier(Option)) {
5788 reportParseError("expected .module option identifier");
5789 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005790 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005791
Toma Tabacuc405c822015-01-23 10:40:19 +00005792 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005793 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005794
Toma Tabacu3c499582015-06-25 10:56:57 +00005795 // Synchronize the abiflags information with the FeatureBits information we
5796 // changed above.
5797 getTargetStreamer().updateABIInfo(*this);
5798
5799 // If printing assembly, use the recently updated abiflags information.
5800 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5801 // emitted at the end).
5802 getTargetStreamer().emitDirectiveModuleOddSPReg();
5803
Toma Tabacuc405c822015-01-23 10:40:19 +00005804 // If this is not the end of the statement, report an error.
5805 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5806 reportParseError("unexpected token, expected end of statement");
5807 return false;
5808 }
5809
5810 return false; // parseDirectiveModule has finished successfully.
5811 } else if (Option == "nooddspreg") {
5812 if (!isABI_O32()) {
5813 Error(L, "'.module nooddspreg' requires the O32 ABI");
5814 return false;
5815 }
5816
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005817 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005818
Toma Tabacu3c499582015-06-25 10:56:57 +00005819 // Synchronize the abiflags information with the FeatureBits information we
5820 // changed above.
5821 getTargetStreamer().updateABIInfo(*this);
5822
5823 // If printing assembly, use the recently updated abiflags information.
5824 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5825 // emitted at the end).
5826 getTargetStreamer().emitDirectiveModuleOddSPReg();
5827
Toma Tabacuc405c822015-01-23 10:40:19 +00005828 // If this is not the end of the statement, report an error.
5829 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5830 reportParseError("unexpected token, expected end of statement");
5831 return false;
5832 }
5833
5834 return false; // parseDirectiveModule has finished successfully.
5835 } else if (Option == "fp") {
5836 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005837 } else if (Option == "softfloat") {
5838 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5839
5840 // Synchronize the ABI Flags information with the FeatureBits information we
5841 // updated above.
5842 getTargetStreamer().updateABIInfo(*this);
5843
5844 // If printing assembly, use the recently updated ABI Flags information.
5845 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5846 // emitted later).
5847 getTargetStreamer().emitDirectiveModuleSoftFloat();
5848
5849 // If this is not the end of the statement, report an error.
5850 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5851 reportParseError("unexpected token, expected end of statement");
5852 return false;
5853 }
5854
5855 return false; // parseDirectiveModule has finished successfully.
5856 } else if (Option == "hardfloat") {
5857 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5858
5859 // Synchronize the ABI Flags information with the FeatureBits information we
5860 // updated above.
5861 getTargetStreamer().updateABIInfo(*this);
5862
5863 // If printing assembly, use the recently updated ABI Flags information.
5864 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5865 // emitted later).
5866 getTargetStreamer().emitDirectiveModuleHardFloat();
5867
5868 // If this is not the end of the statement, report an error.
5869 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5870 reportParseError("unexpected token, expected end of statement");
5871 return false;
5872 }
5873
5874 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005875 } else {
5876 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5877 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005878}
5879
5880/// parseDirectiveModuleFP
5881/// ::= =32
5882/// ::= =xx
5883/// ::= =64
5884bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005885 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005886 MCAsmLexer &Lexer = getLexer();
5887
5888 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005889 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005890 return false;
5891 }
5892 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005893
Daniel Sanders7e527422014-07-10 13:38:23 +00005894 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005895 if (!parseFpABIValue(FpABI, ".module"))
5896 return false;
5897
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005898 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005899 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005900 return false;
5901 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005902
Toma Tabacua64e5402015-06-25 12:44:38 +00005903 // Synchronize the abiflags information with the FeatureBits information we
5904 // changed above.
5905 getTargetStreamer().updateABIInfo(*this);
5906
5907 // If printing assembly, use the recently updated abiflags information.
5908 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5909 // emitted at the end).
5910 getTargetStreamer().emitDirectiveModuleFP();
5911
Daniel Sanders7e527422014-07-10 13:38:23 +00005912 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005913 return false;
5914}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005915
Daniel Sanders7e527422014-07-10 13:38:23 +00005916bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005917 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005918 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005919 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005920 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005921
5922 if (Lexer.is(AsmToken::Identifier)) {
5923 StringRef Value = Parser.getTok().getString();
5924 Parser.Lex();
5925
5926 if (Value != "xx") {
5927 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5928 return false;
5929 }
5930
5931 if (!isABI_O32()) {
5932 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5933 return false;
5934 }
5935
Daniel Sanders7e527422014-07-10 13:38:23 +00005936 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005937 if (ModuleLevelOptions) {
5938 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5939 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5940 } else {
5941 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5942 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5943 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005944 return true;
5945 }
5946
5947 if (Lexer.is(AsmToken::Integer)) {
5948 unsigned Value = Parser.getTok().getIntVal();
5949 Parser.Lex();
5950
5951 if (Value != 32 && Value != 64) {
5952 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5953 return false;
5954 }
5955
5956 if (Value == 32) {
5957 if (!isABI_O32()) {
5958 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5959 return false;
5960 }
5961
Daniel Sanders7e527422014-07-10 13:38:23 +00005962 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005963 if (ModuleLevelOptions) {
5964 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5965 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5966 } else {
5967 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5968 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5969 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005970 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005971 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005972 if (ModuleLevelOptions) {
5973 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5974 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5975 } else {
5976 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5977 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5978 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005979 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005980
Daniel Sanders7e527422014-07-10 13:38:23 +00005981 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005982 }
5983
5984 return false;
5985}
5986
Jack Carter0b744b32012-10-04 02:29:46 +00005987bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005988 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005989 StringRef IDVal = DirectiveID.getString();
5990
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005991 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005992 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005993 if (IDVal == ".cprestore")
5994 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005995 if (IDVal == ".dword") {
5996 parseDataDirective(8, DirectiveID.getLoc());
5997 return false;
5998 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005999 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006000 StringRef SymbolName;
6001
6002 if (Parser.parseIdentifier(SymbolName)) {
6003 reportParseError("expected identifier after .ent");
6004 return false;
6005 }
6006
6007 // There's an undocumented extension that allows an integer to
6008 // follow the name of the procedure which AFAICS is ignored by GAS.
6009 // Example: .ent foo,2
6010 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6011 if (getLexer().isNot(AsmToken::Comma)) {
6012 // Even though we accept this undocumented extension for compatibility
6013 // reasons, the additional integer argument does not actually change
6014 // the behaviour of the '.ent' directive, so we would like to discourage
6015 // its use. We do this by not referring to the extended version in
6016 // error messages which are not directly related to its use.
6017 reportParseError("unexpected token, expected end of statement");
6018 return false;
6019 }
6020 Parser.Lex(); // Eat the comma.
6021 const MCExpr *DummyNumber;
6022 int64_t DummyNumberVal;
6023 // If the user was explicitly trying to use the extended version,
6024 // we still give helpful extension-related error messages.
6025 if (Parser.parseExpression(DummyNumber)) {
6026 reportParseError("expected number after comma");
6027 return false;
6028 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00006029 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006030 reportParseError("expected an absolute expression after comma");
6031 return false;
6032 }
6033 }
6034
6035 // If this is not the end of the statement, report an error.
6036 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6037 reportParseError("unexpected token, expected end of statement");
6038 return false;
6039 }
6040
Jim Grosbach6f482002015-05-18 18:43:14 +00006041 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006042
6043 getTargetStreamer().emitDirectiveEnt(*Sym);
6044 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006045 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006046 return false;
6047 }
6048
Jack Carter07c818d2013-01-25 01:31:34 +00006049 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006050 StringRef SymbolName;
6051
6052 if (Parser.parseIdentifier(SymbolName)) {
6053 reportParseError("expected identifier after .end");
6054 return false;
6055 }
6056
6057 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6058 reportParseError("unexpected token, expected end of statement");
6059 return false;
6060 }
6061
6062 if (CurrentFn == nullptr) {
6063 reportParseError(".end used without .ent");
6064 return false;
6065 }
6066
6067 if ((SymbolName != CurrentFn->getName())) {
6068 reportParseError(".end symbol does not match .ent symbol");
6069 return false;
6070 }
6071
6072 getTargetStreamer().emitDirectiveEnd(SymbolName);
6073 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006074 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006075 return false;
6076 }
6077
Jack Carter07c818d2013-01-25 01:31:34 +00006078 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006079 // .frame $stack_reg, frame_size_in_bytes, $return_reg
6080 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00006081 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006082 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6083 reportParseError("expected stack register");
6084 return false;
6085 }
6086
6087 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6088 if (!StackRegOpnd.isGPRAsmReg()) {
6089 reportParseError(StackRegOpnd.getStartLoc(),
6090 "expected general purpose register");
6091 return false;
6092 }
6093 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6094
6095 if (Parser.getTok().is(AsmToken::Comma))
6096 Parser.Lex();
6097 else {
6098 reportParseError("unexpected token, expected comma");
6099 return false;
6100 }
6101
6102 // Parse the frame size.
6103 const MCExpr *FrameSize;
6104 int64_t FrameSizeVal;
6105
6106 if (Parser.parseExpression(FrameSize)) {
6107 reportParseError("expected frame size value");
6108 return false;
6109 }
6110
Jim Grosbach13760bd2015-05-30 01:25:56 +00006111 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006112 reportParseError("frame size not an absolute expression");
6113 return false;
6114 }
6115
6116 if (Parser.getTok().is(AsmToken::Comma))
6117 Parser.Lex();
6118 else {
6119 reportParseError("unexpected token, expected comma");
6120 return false;
6121 }
6122
6123 // Parse the return register.
6124 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006125 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006126 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6127 reportParseError("expected return register");
6128 return false;
6129 }
6130
6131 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6132 if (!ReturnRegOpnd.isGPRAsmReg()) {
6133 reportParseError(ReturnRegOpnd.getStartLoc(),
6134 "expected general purpose register");
6135 return false;
6136 }
6137
6138 // If this is not the end of the statement, report an error.
6139 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6140 reportParseError("unexpected token, expected end of statement");
6141 return false;
6142 }
6143
6144 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6145 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006146 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006147 return false;
6148 }
6149
Jack Carter07c818d2013-01-25 01:31:34 +00006150 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00006151 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00006152 }
6153
Daniel Sandersd97a6342014-08-13 10:07:34 +00006154 if (IDVal == ".mask" || IDVal == ".fmask") {
6155 // .mask bitmask, frame_offset
6156 // bitmask: One bit for each register used.
6157 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6158 // first register is expected to be saved.
6159 // Examples:
6160 // .mask 0x80000000, -4
6161 // .fmask 0x80000000, -4
6162 //
Jack Carterbe332172012-09-07 00:48:02 +00006163
Daniel Sandersd97a6342014-08-13 10:07:34 +00006164 // Parse the bitmask
6165 const MCExpr *BitMask;
6166 int64_t BitMaskVal;
6167
6168 if (Parser.parseExpression(BitMask)) {
6169 reportParseError("expected bitmask value");
6170 return false;
6171 }
6172
Jim Grosbach13760bd2015-05-30 01:25:56 +00006173 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006174 reportParseError("bitmask not an absolute expression");
6175 return false;
6176 }
6177
6178 if (Parser.getTok().is(AsmToken::Comma))
6179 Parser.Lex();
6180 else {
6181 reportParseError("unexpected token, expected comma");
6182 return false;
6183 }
6184
6185 // Parse the frame_offset
6186 const MCExpr *FrameOffset;
6187 int64_t FrameOffsetVal;
6188
6189 if (Parser.parseExpression(FrameOffset)) {
6190 reportParseError("expected frame offset value");
6191 return false;
6192 }
6193
Jim Grosbach13760bd2015-05-30 01:25:56 +00006194 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006195 reportParseError("frame offset not an absolute expression");
6196 return false;
6197 }
6198
6199 // If this is not the end of the statement, report an error.
6200 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6201 reportParseError("unexpected token, expected end of statement");
6202 return false;
6203 }
6204
6205 if (IDVal == ".mask")
6206 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6207 else
6208 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006209 return false;
6210 }
6211
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006212 if (IDVal == ".nan")
6213 return parseDirectiveNaN();
6214
Jack Carter07c818d2013-01-25 01:31:34 +00006215 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006216 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006217 return false;
6218 }
6219
Rafael Espindolab59fb732014-03-28 18:50:26 +00006220 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006221 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006222 return false;
6223 }
6224
Jack Carter07c818d2013-01-25 01:31:34 +00006225 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006226 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006227 return false;
6228 }
6229
Scott Egertond1aeb052016-02-15 16:11:51 +00006230 if (IDVal == ".hword") {
6231 parseDataDirective(2, DirectiveID.getLoc());
6232 return false;
6233 }
6234
Jack Carter0cd3c192014-01-06 23:27:31 +00006235 if (IDVal == ".option")
6236 return parseDirectiveOption();
6237
6238 if (IDVal == ".abicalls") {
6239 getTargetStreamer().emitDirectiveAbiCalls();
6240 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006241 Error(Parser.getTok().getLoc(),
6242 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006243 // Clear line
6244 Parser.eatToEndOfStatement();
6245 }
6246 return false;
6247 }
6248
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006249 if (IDVal == ".cpsetup")
6250 return parseDirectiveCPSetup();
6251
Daniel Sandersf173dda2015-09-22 10:50:09 +00006252 if (IDVal == ".cpreturn")
6253 return parseDirectiveCPReturn();
6254
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006255 if (IDVal == ".module")
6256 return parseDirectiveModule();
6257
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006258 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
6259 return parseInternalDirectiveReallowModule();
6260
Toma Tabacu9ca50962015-04-16 09:53:47 +00006261 if (IDVal == ".insn")
6262 return parseInsnDirective();
6263
Simon Atanasyanbe186202016-02-11 06:45:54 +00006264 if (IDVal == ".sbss")
6265 return parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
6266 if (IDVal == ".sdata")
6267 return parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
6268
Rafael Espindola870c4e92012-01-11 03:56:41 +00006269 return true;
6270}
6271
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006272bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6273 // If this is not the end of the statement, report an error.
6274 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6275 reportParseError("unexpected token, expected end of statement");
6276 return false;
6277 }
6278
6279 getTargetStreamer().reallowModuleDirective();
6280
6281 getParser().Lex(); // Eat EndOfStatement token.
6282 return false;
6283}
6284
Rafael Espindola870c4e92012-01-11 03:56:41 +00006285extern "C" void LLVMInitializeMipsAsmParser() {
6286 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6287 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6288 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6289 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6290}
Jack Carterb4dbc172012-09-05 23:34:03 +00006291
6292#define GET_REGISTER_MATCHER
6293#define GET_MATCHER_IMPLEMENTATION
6294#include "MipsGenAsmMatcher.inc"