blob: 14e63ad0c2be7f825546a58fef61cb7cb9d0edd4 [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"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000017#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000018#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000022#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000023#include "llvm/MC/MCParser/MCAsmLexer.h"
24#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000025#include "llvm/MC/MCStreamer.h"
26#include "llvm/MC/MCSubtargetInfo.h"
27#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000028#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000029#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000030#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000031#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000032#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000033#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000034#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000035
36using namespace llvm;
37
Chandler Carruthe96dd892014-04-21 22:55:11 +000038#define DEBUG_TYPE "mips-asm-parser"
39
Joey Gouly0e76fa72013-09-12 10:28:05 +000040namespace llvm {
41class MCInstrInfo;
42}
43
Rafael Espindola870c4e92012-01-11 03:56:41 +000044namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000045class MipsAssemblerOptions {
46public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000047 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000048 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000049
Toma Tabacu9db22db2014-09-09 10:15:38 +000050 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000051 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000052 Reorder = Opts->isReorder();
53 Macro = Opts->isMacro();
54 Features = Opts->getFeatures();
55 }
56
Toma Tabacub19cf202015-04-27 13:12:59 +000057 unsigned getATRegIndex() const { return ATReg; }
58 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000059 if (Reg > 31)
60 return false;
61
62 ATReg = Reg;
63 return true;
64 }
Jack Carter0b744b32012-10-04 02:29:46 +000065
Toma Tabacu9db22db2014-09-09 10:15:38 +000066 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000067 void setReorder() { Reorder = true; }
68 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000069
Toma Tabacu9db22db2014-09-09 10:15:38 +000070 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000071 void setMacro() { Macro = true; }
72 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000073
Toma Tabacu465acfd2015-06-09 13:33:26 +000074 const FeatureBitset &getFeatures() const { return Features; }
75 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000076
Daniel Sandersf0df2212014-08-04 12:20:00 +000077 // Set of features that are either architecture features or referenced
78 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
79 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
80 // The reason we need this mask is explained in the selectArch function.
81 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000082 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000083
Jack Carter0b744b32012-10-04 02:29:46 +000084private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000085 unsigned ATReg;
86 bool Reorder;
87 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000088 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000089};
90}
91
Michael Kupersteindb0712f2015-05-26 10:47:10 +000092const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
93 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
94 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
95 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
96 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
97 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
98 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
99 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
100 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
101};
102
Jack Carter0b744b32012-10-04 02:29:46 +0000103namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000104class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000105 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000106 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000107 return static_cast<MipsTargetStreamer &>(TS);
108 }
109
Eric Christophera5762812015-01-26 17:33:46 +0000110 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000111 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000112 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
113 // nullptr, which indicates that no function is currently
114 // selected. This usually happens after an '.end func'
115 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000116 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000117 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000118 bool IsCpRestoreSet;
119 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000120 unsigned CpSaveLocation;
121 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
122 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000123
Daniel Sandersef638fe2014-10-03 15:37:37 +0000124 // Print a warning along with its fix-it message at the given range.
125 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
126 SMRange Range, bool ShowColors = true);
127
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000128#define GET_ASSEMBLER_HEADER
129#include "MipsGenAsmMatcher.inc"
130
Matheus Almeida595fcab2014-06-11 15:05:56 +0000131 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
132
Chad Rosier49963552012-10-13 00:26:04 +0000133 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000134 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000135 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000136 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000137
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000138 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000139 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000140
Toma Tabacu13964452014-09-04 13:23:44 +0000141 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000144
David Blaikie960ea3f2014-06-08 16:18:35 +0000145 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
146 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000147
Craig Topper56c590a2014-04-29 07:58:02 +0000148 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000149
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000150 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
151 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000152 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000153 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000154 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
155 SMLoc S);
156 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
157 OperandMatchResultTy parseImm(OperandVector &Operands);
158 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
159 OperandMatchResultTy parseInvNum(OperandVector &Operands);
160 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
161 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
162 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
163 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000164
David Blaikie960ea3f2014-06-08 16:18:35 +0000165 bool searchSymbolAlias(OperandVector &Operands);
166
Toma Tabacu13964452014-09-04 13:23:44 +0000167 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000168
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000169 enum MacroExpanderResultTy {
170 MER_NotAMacro,
171 MER_Success,
172 MER_Fail,
173 };
Jack Carter30a59822012-10-04 04:03:53 +0000174
Matheus Almeida3813d572014-06-19 14:39:14 +0000175 // Expands assembly pseudo instructions.
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000176 MacroExpanderResultTy
177 tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
178 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000179
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000180 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
181 SmallVectorImpl<MCInst> &Instructions);
182
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000183 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000184 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000185 SmallVectorImpl<MCInst> &Instructions);
186
Toma Tabacuf712ede2015-06-17 14:31:51 +0000187 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
188 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
189 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000190
Toma Tabacu00e98672015-05-01 12:19:27 +0000191 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000192 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000193
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000194 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
195 const MCOperand &Offset, bool Is32BitAddress,
196 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000197
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000198 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
199 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000200
Jack Carter9e65aa32013-03-22 00:05:30 +0000201 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000202 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
203 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000204
205 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
206 SmallVectorImpl<MCInst> &Instructions);
207
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000208 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
209 SmallVectorImpl<MCInst> &Instructions);
210
Toma Tabacue1e460d2015-06-11 10:36:10 +0000211 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
212 SmallVectorImpl<MCInst> &Instructions);
213
Toma Tabacu1a108322015-06-17 13:20:24 +0000214 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
215 SmallVectorImpl<MCInst> &Instructions);
216
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000217 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
218 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
219 const bool Signed);
220
Daniel Sanders6394ee52015-10-15 14:52:58 +0000221 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
222 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000223
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000224 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
225 SmallVectorImpl<MCInst> &Instructions);
226
Zoran Jovanovic00f998b2015-11-19 14:15:03 +0000227 bool expandRotation(MCInst &Inst, SMLoc IDLoc,
228 SmallVectorImpl<MCInst> &Instructions);
229 bool expandRotationImm(MCInst &Inst, SMLoc IDLoc,
230 SmallVectorImpl<MCInst> &Instructions);
231 bool expandDRotation(MCInst &Inst, SMLoc IDLoc,
232 SmallVectorImpl<MCInst> &Instructions);
233 bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
234 SmallVectorImpl<MCInst> &Instructions);
235
Toma Tabacu234482a2015-03-16 12:03:39 +0000236 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
237 SmallVectorImpl<MCInst> &Instructions);
238
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000239 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000240 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000241
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000242 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
243 SmallVectorImpl<MCInst> &Instructions);
244
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000245 bool reportParseError(Twine ErrorMsg);
246 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000247
Jack Carterb5cf5902013-04-17 00:18:04 +0000248 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000249 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000250
Vladimir Medic4c299852013-11-06 11:27:05 +0000251 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000252
253 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000254 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000255 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000256 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000257 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000258 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000259 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000260 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000261 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000262 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000263 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000264 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000265 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000266
267 bool parseSetAtDirective();
268 bool parseSetNoAtDirective();
269 bool parseSetMacroDirective();
270 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000271 bool parseSetMsaDirective();
272 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000273 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000274 bool parseSetReorderDirective();
275 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000276 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000277 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000278 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000279 bool parseSetOddSPRegDirective();
280 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000281 bool parseSetPopDirective();
282 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000283 bool parseSetSoftFloatDirective();
284 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000285
Jack Carterd76b2372013-03-21 21:44:16 +0000286 bool parseSetAssignment();
287
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000288 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000289 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000290 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000291 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000292 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000293 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
294 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000295
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000296 bool parseInternalDirectiveReallowModule();
297
Jack Carterdc1e35d2012-09-06 20:00:02 +0000298 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000299
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000300 bool eatComma(StringRef ErrorStr);
301
Jack Carter1ac53222013-02-20 23:11:17 +0000302 int matchCPURegisterName(StringRef Symbol);
303
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000304 int matchHWRegsRegisterName(StringRef Symbol);
305
Jack Carter873c7242013-01-12 01:03:14 +0000306 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000307
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000308 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000309
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000310 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000311
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000312 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000313
Jack Carter5dc8ac92013-09-25 23:50:44 +0000314 int matchMSA128RegisterName(StringRef Name);
315
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000316 int matchMSA128CtrlRegisterName(StringRef Name);
317
Jack Carterd0bd6422013-04-18 00:41:53 +0000318 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000319
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000320 unsigned getGPR(int RegNo);
321
Toma Tabacu89a712b2015-04-15 10:48:56 +0000322 /// Returns the internal register number for the current AT. Also checks if
323 /// the current AT is unavailable (set to $0) and gives an error if it is.
324 /// This should be used in pseudo-instruction expansions which need AT.
325 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000326
327 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000328 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000329
330 // Helper function that checks if the value of a vector index is within the
331 // boundaries of accepted values for each RegisterKind
332 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
333 bool validateMSAIndex(int Val, int RegKind);
334
Daniel Sandersf0df2212014-08-04 12:20:00 +0000335 // Selects a new architecture by updating the FeatureBits with the necessary
336 // info including implied dependencies.
337 // Internally, it clears all the feature bits related to *any* architecture
338 // and selects the new one using the ToggleFeature functionality of the
339 // MCSubtargetInfo object that handles implied dependencies. The reason we
340 // clear all the arch related bits manually is because ToggleFeature only
341 // clears the features that imply the feature being cleared and not the
342 // features implied by the feature being cleared. This is easier to see
343 // with an example:
344 // --------------------------------------------------
345 // | Feature | Implies |
346 // | -------------------------------------------------|
347 // | FeatureMips1 | None |
348 // | FeatureMips2 | FeatureMips1 |
349 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
350 // | FeatureMips4 | FeatureMips3 |
351 // | ... | |
352 // --------------------------------------------------
353 //
354 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
355 // FeatureMipsGP64 | FeatureMips1)
356 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
357 void selectArch(StringRef ArchFeature) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000358 MCSubtargetInfo &STI = copySTI();
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000359 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000360 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
361 STI.setFeatureBits(FeatureBits);
362 setAvailableFeatures(
363 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000364 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000365 }
366
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000367 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000368 if (!(getSTI().getFeatureBits()[Feature])) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000369 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000370 setAvailableFeatures(
371 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000372 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000373 }
374 }
375
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000376 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000377 if (getSTI().getFeatureBits()[Feature]) {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000378 MCSubtargetInfo &STI = copySTI();
Matheus Almeida2852af82014-04-22 10:15:54 +0000379 setAvailableFeatures(
380 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000381 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000382 }
383 }
384
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000385 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
386 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000387 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000388 }
389
390 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
391 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000392 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000393 }
394
Rafael Espindola870c4e92012-01-11 03:56:41 +0000395public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000396 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000397 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000398#define GET_OPERAND_DIAGNOSTIC_TYPES
399#include "MipsGenAsmMatcher.inc"
400#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000401 };
402
Akira Hatanakab11ef082015-11-14 06:35:56 +0000403 MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000404 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000405 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000406 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
407 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000408 MCAsmParserExtension::Initialize(parser);
409
Toma Tabacu11e14a92015-04-21 11:50:52 +0000410 parser.addAliasForDirective(".asciiz", ".asciz");
411
Jack Carterb4dbc172012-09-05 23:34:03 +0000412 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000413 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000414
Toma Tabacu9db22db2014-09-09 10:15:38 +0000415 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000416 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000417 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000418
Toma Tabacu9db22db2014-09-09 10:15:38 +0000419 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000420 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000421 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000422
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000423 getTargetStreamer().updateABIInfo(*this);
424
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000425 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000426 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000427
428 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000429
Daniel Sandersa6994442015-08-18 12:33:54 +0000430 IsPicEnabled =
431 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
432
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000433 IsCpRestoreSet = false;
434 CpRestoreOffset = -1;
435
Daniel Sanders50f17232015-09-15 16:17:27 +0000436 Triple TheTriple(sti.getTargetTriple());
437 if ((TheTriple.getArch() == Triple::mips) ||
438 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000439 IsLittleEndian = false;
440 else
441 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000442 }
443
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000444 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
445 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
446
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000447 bool isGP64bit() const {
448 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
449 }
450 bool isFP64bit() const {
451 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
452 }
Eric Christophera5762812015-01-26 17:33:46 +0000453 const MipsABIInfo &getABI() const { return ABI; }
454 bool isABI_N32() const { return ABI.IsN32(); }
455 bool isABI_N64() const { return ABI.IsN64(); }
456 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000457 bool isABI_FPXX() const {
458 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
459 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000460
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000461 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000462 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000463 }
464
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000465 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000466 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000467 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000468 bool hasMips1() const {
469 return getSTI().getFeatureBits()[Mips::FeatureMips1];
470 }
471 bool hasMips2() const {
472 return getSTI().getFeatureBits()[Mips::FeatureMips2];
473 }
474 bool hasMips3() const {
475 return getSTI().getFeatureBits()[Mips::FeatureMips3];
476 }
477 bool hasMips4() const {
478 return getSTI().getFeatureBits()[Mips::FeatureMips4];
479 }
480 bool hasMips5() const {
481 return getSTI().getFeatureBits()[Mips::FeatureMips5];
482 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000483 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000484 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000485 }
486 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000487 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000488 }
489 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000490 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000491 }
492 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000493 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000494 }
Daniel Sanders17793142015-02-18 16:24:50 +0000495 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000496 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000497 }
498 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000500 }
501 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000502 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000503 }
504 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000505 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000506 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000507 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000508 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000509 }
510 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000511 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000512 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000513
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000514 bool hasDSP() const {
515 return getSTI().getFeatureBits()[Mips::FeatureDSP];
516 }
517 bool hasDSPR2() const {
518 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
519 }
520 bool hasDSPR3() const {
521 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
522 }
523 bool hasMSA() const {
524 return getSTI().getFeatureBits()[Mips::FeatureMSA];
525 }
Kai Nackee0245392015-01-27 19:11:28 +0000526 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000527 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000528 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000529
Daniel Sandersa6994442015-08-18 12:33:54 +0000530 bool inPicMode() {
531 return IsPicEnabled;
532 }
533
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000534 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000535 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000536 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000537
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000538 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000539 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000540 }
541
Eric Christophere8ae3e32015-05-07 23:10:21 +0000542 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000543 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000544 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000545
Toma Tabacud9d344b2015-04-27 14:05:04 +0000546 /// Warn if RegIndex is the same as the current AT.
547 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000548
549 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000550
551 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000552};
553}
554
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000555namespace {
556
557/// MipsOperand - Instances of this class represent a parsed Mips machine
558/// instruction.
559class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000560public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000561 /// Broad categories of register classes
562 /// The exact class is finalized by the render method.
563 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000564 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000565 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000566 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000567 RegKind_FCC = 4, /// FCC
568 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
569 RegKind_MSACtrl = 16, /// MSA control registers
570 RegKind_COP2 = 32, /// COP2
571 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
572 /// context).
573 RegKind_CCR = 128, /// CCR
574 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000575 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000576 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000577 /// Potentially any (e.g. $1)
578 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
579 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000580 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000581 };
582
583private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000584 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000585 k_Immediate, /// An immediate (possibly involving symbol references)
586 k_Memory, /// Base + Offset Memory Address
587 k_PhysRegister, /// A physical register from the Mips namespace
588 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000589 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000590 k_RegList, /// A physical register list
591 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000592 } Kind;
593
David Blaikie960ea3f2014-06-08 16:18:35 +0000594public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000595 MipsOperand(KindTy K, MipsAsmParser &Parser)
596 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
597
David Blaikie960ea3f2014-06-08 16:18:35 +0000598private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000599 /// For diagnostics, and checking the assembler temporary
600 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000601
Eric Christopher8996c5d2013-03-15 00:42:55 +0000602 struct Token {
603 const char *Data;
604 unsigned Length;
605 };
606
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000607 struct PhysRegOp {
608 unsigned Num; /// Register Number
609 };
610
611 struct RegIdxOp {
612 unsigned Index; /// Index into the register class
613 RegKind Kind; /// Bitfield of the kinds it could possibly be
614 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000615 };
616
617 struct ImmOp {
618 const MCExpr *Val;
619 };
620
621 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000622 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000623 const MCExpr *Off;
624 };
625
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000626 struct RegListOp {
627 SmallVector<unsigned, 10> *List;
628 };
629
Jack Carterb4dbc172012-09-05 23:34:03 +0000630 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000631 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000632 struct PhysRegOp PhysReg;
633 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000634 struct ImmOp Imm;
635 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000636 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000637 };
638
639 SMLoc StartLoc, EndLoc;
640
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000641 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000642 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
643 const MCRegisterInfo *RegInfo,
644 SMLoc S, SMLoc E,
645 MipsAsmParser &Parser) {
646 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000647 Op->RegIdx.Index = Index;
648 Op->RegIdx.RegInfo = RegInfo;
649 Op->RegIdx.Kind = RegKind;
650 Op->StartLoc = S;
651 Op->EndLoc = E;
652 return Op;
653 }
654
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000655public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000656 /// Coerce the register to GPR32 and return the real register for the current
657 /// target.
658 unsigned getGPR32Reg() const {
659 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000660 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000661 unsigned ClassID = Mips::GPR32RegClassID;
662 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000663 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000664
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000665 /// Coerce the register to GPR32 and return the real register for the current
666 /// target.
667 unsigned getGPRMM16Reg() const {
668 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
669 unsigned ClassID = Mips::GPR32RegClassID;
670 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
671 }
672
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000673 /// Coerce the register to GPR64 and return the real register for the current
674 /// target.
675 unsigned getGPR64Reg() const {
676 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
677 unsigned ClassID = Mips::GPR64RegClassID;
678 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000679 }
680
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000681private:
682 /// Coerce the register to AFGR64 and return the real register for the current
683 /// target.
684 unsigned getAFGR64Reg() const {
685 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
686 if (RegIdx.Index % 2 != 0)
687 AsmParser.Warning(StartLoc, "Float register should be even.");
688 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
689 .getRegister(RegIdx.Index / 2);
690 }
691
692 /// Coerce the register to FGR64 and return the real register for the current
693 /// target.
694 unsigned getFGR64Reg() const {
695 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
696 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
697 .getRegister(RegIdx.Index);
698 }
699
700 /// Coerce the register to FGR32 and return the real register for the current
701 /// target.
702 unsigned getFGR32Reg() const {
703 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
704 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
705 .getRegister(RegIdx.Index);
706 }
707
708 /// Coerce the register to FGRH32 and return the real register for the current
709 /// target.
710 unsigned getFGRH32Reg() const {
711 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
712 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
713 .getRegister(RegIdx.Index);
714 }
715
716 /// Coerce the register to FCC and return the real register for the current
717 /// target.
718 unsigned getFCCReg() const {
719 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
720 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
721 .getRegister(RegIdx.Index);
722 }
723
724 /// Coerce the register to MSA128 and return the real register for the current
725 /// target.
726 unsigned getMSA128Reg() const {
727 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
728 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
729 // identical
730 unsigned ClassID = Mips::MSA128BRegClassID;
731 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
732 }
733
734 /// Coerce the register to MSACtrl and return the real register for the
735 /// current target.
736 unsigned getMSACtrlReg() const {
737 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
738 unsigned ClassID = Mips::MSACtrlRegClassID;
739 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
740 }
741
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000742 /// Coerce the register to COP0 and return the real register for the
743 /// current target.
744 unsigned getCOP0Reg() const {
745 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
746 unsigned ClassID = Mips::COP0RegClassID;
747 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
748 }
749
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000750 /// Coerce the register to COP2 and return the real register for the
751 /// current target.
752 unsigned getCOP2Reg() const {
753 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
754 unsigned ClassID = Mips::COP2RegClassID;
755 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
756 }
757
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000758 /// Coerce the register to COP3 and return the real register for the
759 /// current target.
760 unsigned getCOP3Reg() const {
761 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
762 unsigned ClassID = Mips::COP3RegClassID;
763 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
764 }
765
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000766 /// Coerce the register to ACC64DSP and return the real register for the
767 /// current target.
768 unsigned getACC64DSPReg() const {
769 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
770 unsigned ClassID = Mips::ACC64DSPRegClassID;
771 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
772 }
773
774 /// Coerce the register to HI32DSP and return the real register for the
775 /// current target.
776 unsigned getHI32DSPReg() const {
777 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
778 unsigned ClassID = Mips::HI32DSPRegClassID;
779 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
780 }
781
782 /// Coerce the register to LO32DSP and return the real register for the
783 /// current target.
784 unsigned getLO32DSPReg() const {
785 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
786 unsigned ClassID = Mips::LO32DSPRegClassID;
787 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
788 }
789
790 /// Coerce the register to CCR and return the real register for the
791 /// current target.
792 unsigned getCCRReg() const {
793 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
794 unsigned ClassID = Mips::CCRRegClassID;
795 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
796 }
797
798 /// Coerce the register to HWRegs and return the real register for the
799 /// current target.
800 unsigned getHWRegsReg() const {
801 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
802 unsigned ClassID = Mips::HWRegsRegClassID;
803 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
804 }
805
806public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000807 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000808 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000809 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000810 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000811 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000812 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000813 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000814 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000815 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000816
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000817 void addRegOperands(MCInst &Inst, unsigned N) const {
818 llvm_unreachable("Use a custom parser instead");
819 }
820
Daniel Sanders21bce302014-04-01 12:35:23 +0000821 /// Render the operand to an MCInst as a GPR32
822 /// Asserts if the wrong number of operands are requested, or the operand
823 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000824 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
825 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000826 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000827 }
828
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000829 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
830 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000831 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000832 }
833
Jozef Kolek1904fa22014-11-24 14:25:53 +0000834 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
835 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000836 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000837 }
838
Zoran Jovanovic41688672015-02-10 16:36:20 +0000839 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
840 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000841 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000842 }
843
Daniel Sanders21bce302014-04-01 12:35:23 +0000844 /// Render the operand to an MCInst as a GPR64
845 /// Asserts if the wrong number of operands are requested, or the operand
846 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000847 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
848 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000849 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 }
851
852 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
853 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000854 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000855 }
856
857 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
858 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000859 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000860 }
861
862 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
863 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000864 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000865 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000866 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000867 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
868 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000869 }
870
871 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
872 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000873 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000874 }
875
876 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
877 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000878 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000879 }
880
881 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
882 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000883 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000884 }
885
886 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
887 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000888 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000889 }
890
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000891 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
892 assert(N == 1 && "Invalid number of operands!");
893 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
894 }
895
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000896 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
897 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000898 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000899 }
900
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000901 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
902 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000903 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000904 }
905
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000906 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
907 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000908 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000909 }
910
911 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
912 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000913 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000914 }
915
916 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
917 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000918 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000919 }
920
921 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
922 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000923 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000924 }
925
926 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
927 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000928 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000929 }
930
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000931 template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000932 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
933 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000934 uint64_t Imm = getConstantImm() - Offset;
935 Imm &= (1 << Bits) - 1;
936 Imm += Offset;
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +0000937 Imm += AdjustOffset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000938 Inst.addOperand(MCOperand::createImm(Imm));
939 }
940
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000941 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000942 assert(N == 1 && "Invalid number of operands!");
943 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000944 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000945 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000946
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000947 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000948 assert(N == 2 && "Invalid number of operands!");
949
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000950 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
951 ? getMemBase()->getGPR64Reg()
952 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000953
954 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000955 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000956 }
957
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000958 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
959 assert(N == 2 && "Invalid number of operands!");
960
Jim Grosbache9119e42015-05-13 18:37:00 +0000961 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000962
963 const MCExpr *Expr = getMemOff();
964 addExpr(Inst, Expr);
965 }
966
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000967 void addRegListOperands(MCInst &Inst, unsigned N) const {
968 assert(N == 1 && "Invalid number of operands!");
969
970 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000971 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000972 }
973
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000974 void addRegPairOperands(MCInst &Inst, unsigned N) const {
975 assert(N == 2 && "Invalid number of operands!");
976 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000977 Inst.addOperand(MCOperand::createReg(RegNo++));
978 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000979 }
980
Zoran Jovanovic41688672015-02-10 16:36:20 +0000981 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
982 assert(N == 2 && "Invalid number of operands!");
983 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000984 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000985 }
986
Craig Topper56c590a2014-04-29 07:58:02 +0000987 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000988 // As a special case until we sort out the definition of div/divu, pretend
989 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
990 if (isGPRAsmReg() && RegIdx.Index == 0)
991 return true;
992
993 return Kind == k_PhysRegister;
994 }
995 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000996 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000997 bool isConstantImm() const {
Craig Topper66059c92015-11-18 07:07:59 +0000998 return isImm() && isa<MCConstantExpr>(getImm());
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000999 }
Daniel Sanders52da7af2015-11-06 12:11:03 +00001000 bool isConstantImmz() const {
1001 return isConstantImm() && getConstantImm() == 0;
1002 }
Daniel Sandersea4f6532015-11-06 12:22:31 +00001003 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
1004 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
1005 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +00001006 template <unsigned Bits> bool isUImm() const {
1007 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
1008 }
Craig Topper56c590a2014-04-29 07:58:02 +00001009 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001010 // Note: It's not possible to pretend that other operand kinds are tokens.
1011 // The matcher emitter checks tokens first.
1012 return Kind == k_Token;
1013 }
Craig Topper56c590a2014-04-29 07:58:02 +00001014 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001015 bool isConstantMemOff() const {
Craig Topper66059c92015-11-18 07:07:59 +00001016 return isMem() && isa<MCConstantExpr>(getMemOff());
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001017 }
1018 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001019 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1020 && getMemBase()->isGPRAsmReg();
1021 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001022 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
1023 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
1024 getMemBase()->isGPRAsmReg();
1025 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001026 bool isMemWithGRPMM16Base() const {
1027 return isMem() && getMemBase()->isMM16AsmReg();
1028 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001029 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1030 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1031 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1032 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001033 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1034 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1035 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1036 && (getMemBase()->getGPR32Reg() == Mips::SP);
1037 }
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00001038 template <unsigned Bits, unsigned ShiftLeftAmount>
1039 bool isScaledUImm() const {
1040 return isConstantImm() &&
1041 isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001042 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001043 bool isRegList16() const {
1044 if (!isRegList())
1045 return false;
1046
1047 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001048 if (Size < 2 || Size > 5)
1049 return false;
1050
1051 unsigned R0 = RegList.List->front();
1052 unsigned R1 = RegList.List->back();
1053 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1054 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001055 return false;
1056
1057 int PrevReg = *RegList.List->begin();
1058 for (int i = 1; i < Size - 1; i++) {
1059 int Reg = (*(RegList.List))[i];
1060 if ( Reg != PrevReg + 1)
1061 return false;
1062 PrevReg = Reg;
1063 }
1064
1065 return true;
1066 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001067 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001068 bool isLSAImm() const {
1069 if (!isConstantImm())
1070 return false;
1071 int64_t Val = getConstantImm();
1072 return 1 <= Val && Val <= 4;
1073 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001074 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001075 bool isMovePRegPair() const {
1076 if (Kind != k_RegList || RegList.List->size() != 2)
1077 return false;
1078
1079 unsigned R0 = RegList.List->front();
1080 unsigned R1 = RegList.List->back();
1081
1082 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1083 (R0 == Mips::A1 && R1 == Mips::A3) ||
1084 (R0 == Mips::A2 && R1 == Mips::A3) ||
1085 (R0 == Mips::A0 && R1 == Mips::S5) ||
1086 (R0 == Mips::A0 && R1 == Mips::S6) ||
1087 (R0 == Mips::A0 && R1 == Mips::A1) ||
1088 (R0 == Mips::A0 && R1 == Mips::A2) ||
1089 (R0 == Mips::A0 && R1 == Mips::A3))
1090 return true;
1091
1092 return false;
1093 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001094
1095 StringRef getToken() const {
1096 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001097 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001098 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001099 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001100
Craig Topper56c590a2014-04-29 07:58:02 +00001101 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001102 // As a special case until we sort out the definition of div/divu, pretend
1103 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1104 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1105 RegIdx.Kind & RegKind_GPR)
1106 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001107
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001108 assert(Kind == k_PhysRegister && "Invalid access!");
1109 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001110 }
1111
Jack Carterb4dbc172012-09-05 23:34:03 +00001112 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001113 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001114 return Imm.Val;
1115 }
1116
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001117 int64_t getConstantImm() const {
1118 const MCExpr *Val = getImm();
1119 return static_cast<const MCConstantExpr *>(Val)->getValue();
1120 }
1121
1122 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001123 assert((Kind == k_Memory) && "Invalid access!");
1124 return Mem.Base;
1125 }
1126
1127 const MCExpr *getMemOff() const {
1128 assert((Kind == k_Memory) && "Invalid access!");
1129 return Mem.Off;
1130 }
1131
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001132 int64_t getConstantMemOff() const {
1133 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1134 }
1135
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001136 const SmallVectorImpl<unsigned> &getRegList() const {
1137 assert((Kind == k_RegList) && "Invalid access!");
1138 return *(RegList.List);
1139 }
1140
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001141 unsigned getRegPair() const {
1142 assert((Kind == k_RegPair) && "Invalid access!");
1143 return RegIdx.Index;
1144 }
1145
David Blaikie960ea3f2014-06-08 16:18:35 +00001146 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1147 MipsAsmParser &Parser) {
1148 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001149 Op->Tok.Data = Str.data();
1150 Op->Tok.Length = Str.size();
1151 Op->StartLoc = S;
1152 Op->EndLoc = S;
1153 return Op;
1154 }
1155
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001156 /// Create a numeric register (e.g. $1). The exact register remains
1157 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001158 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001159 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001160 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001161 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001162 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001163 }
1164
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001165 /// Create a register that is definitely a GPR.
1166 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001167 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001168 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001169 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001170 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001171 }
1172
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001173 /// Create a register that is definitely a FGR.
1174 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001175 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001176 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001177 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001178 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1179 }
1180
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001181 /// Create a register that is definitely a HWReg.
1182 /// This is typically only used for named registers such as $hwr_cpunum.
1183 static std::unique_ptr<MipsOperand>
1184 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1185 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1186 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1187 }
1188
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001189 /// Create a register that is definitely an FCC.
1190 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001191 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001192 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001193 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001194 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1195 }
1196
1197 /// Create a register that is definitely an ACC.
1198 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001199 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001200 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001201 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001202 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1203 }
1204
1205 /// Create a register that is definitely an MSA128.
1206 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001207 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001208 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001209 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001210 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1211 }
1212
1213 /// Create a register that is definitely an MSACtrl.
1214 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001215 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001216 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001217 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001218 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1219 }
1220
David Blaikie960ea3f2014-06-08 16:18:35 +00001221 static std::unique_ptr<MipsOperand>
1222 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1223 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001224 Op->Imm.Val = Val;
1225 Op->StartLoc = S;
1226 Op->EndLoc = E;
1227 return Op;
1228 }
1229
David Blaikie960ea3f2014-06-08 16:18:35 +00001230 static std::unique_ptr<MipsOperand>
1231 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1232 SMLoc E, MipsAsmParser &Parser) {
1233 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1234 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001235 Op->Mem.Off = Off;
1236 Op->StartLoc = S;
1237 Op->EndLoc = E;
1238 return Op;
1239 }
1240
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001241 static std::unique_ptr<MipsOperand>
1242 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1243 MipsAsmParser &Parser) {
1244 assert (Regs.size() > 0 && "Empty list not allowed");
1245
1246 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001247 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001248 Op->StartLoc = StartLoc;
1249 Op->EndLoc = EndLoc;
1250 return Op;
1251 }
1252
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001253 static std::unique_ptr<MipsOperand>
1254 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1255 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1256 Op->RegIdx.Index = RegNo;
1257 Op->StartLoc = S;
1258 Op->EndLoc = E;
1259 return Op;
1260 }
1261
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001262 bool isGPRAsmReg() const {
1263 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001264 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001265 bool isMM16AsmReg() const {
1266 if (!(isRegIdx() && RegIdx.Kind))
1267 return false;
1268 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1269 || RegIdx.Index == 16 || RegIdx.Index == 17);
1270 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001271 bool isMM16AsmRegZero() const {
1272 if (!(isRegIdx() && RegIdx.Kind))
1273 return false;
1274 return (RegIdx.Index == 0 ||
1275 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1276 RegIdx.Index == 17);
1277 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001278 bool isMM16AsmRegMoveP() const {
1279 if (!(isRegIdx() && RegIdx.Kind))
1280 return false;
1281 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1282 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1283 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001284 bool isFGRAsmReg() const {
1285 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1286 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001287 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001288 bool isHWRegsAsmReg() const {
1289 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001290 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001291 bool isCCRAsmReg() const {
1292 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001293 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001294 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001295 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1296 return false;
1297 if (!AsmParser.hasEightFccRegisters())
1298 return RegIdx.Index == 0;
1299 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001300 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001301 bool isACCAsmReg() const {
1302 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001303 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001304 bool isCOP0AsmReg() const {
1305 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1306 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001307 bool isCOP2AsmReg() const {
1308 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001309 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001310 bool isCOP3AsmReg() const {
1311 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1312 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001313 bool isMSA128AsmReg() const {
1314 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001315 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001316 bool isMSACtrlAsmReg() const {
1317 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001318 }
1319
Jack Carterb4dbc172012-09-05 23:34:03 +00001320 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001321 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001322 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001323 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001324
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001325 virtual ~MipsOperand() {
1326 switch (Kind) {
1327 case k_Immediate:
1328 break;
1329 case k_Memory:
1330 delete Mem.Base;
1331 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001332 case k_RegList:
1333 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001334 case k_PhysRegister:
1335 case k_RegisterIndex:
1336 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001337 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001338 break;
1339 }
1340 }
1341
Craig Topper56c590a2014-04-29 07:58:02 +00001342 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001343 switch (Kind) {
1344 case k_Immediate:
1345 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001346 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001347 OS << ">";
1348 break;
1349 case k_Memory:
1350 OS << "Mem<";
1351 Mem.Base->print(OS);
1352 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001353 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001354 OS << ">";
1355 break;
1356 case k_PhysRegister:
1357 OS << "PhysReg<" << PhysReg.Num << ">";
1358 break;
1359 case k_RegisterIndex:
1360 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1361 break;
1362 case k_Token:
1363 OS << Tok.Data;
1364 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001365 case k_RegList:
1366 OS << "RegList< ";
1367 for (auto Reg : (*RegList.List))
1368 OS << Reg << " ";
1369 OS << ">";
1370 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001371 case k_RegPair:
1372 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1373 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001374 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001375 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001376}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001377} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001378
Jack Carter9e65aa32013-03-22 00:05:30 +00001379namespace llvm {
1380extern const MCInstrDesc MipsInsts[];
1381}
1382static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1383 return MipsInsts[Opcode];
1384}
1385
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001386static bool hasShortDelaySlot(unsigned Opcode) {
1387 switch (Opcode) {
1388 case Mips::JALS_MM:
1389 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001390 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001391 case Mips::BGEZALS_MM:
1392 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001393 return true;
1394 default:
1395 return false;
1396 }
1397}
1398
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001399static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1400 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1401 return &SRExpr->getSymbol();
1402 }
1403
1404 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1405 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1406 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1407
1408 if (LHSSym)
1409 return LHSSym;
1410
1411 if (RHSSym)
1412 return RHSSym;
1413
1414 return nullptr;
1415 }
1416
1417 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1418 return getSingleMCSymbol(UExpr->getSubExpr());
1419
1420 return nullptr;
1421}
1422
1423static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1424 if (isa<MCSymbolRefExpr>(Expr))
1425 return 1;
1426
1427 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1428 return countMCSymbolRefExpr(BExpr->getLHS()) +
1429 countMCSymbolRefExpr(BExpr->getRHS());
1430
1431 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1432 return countMCSymbolRefExpr(UExpr->getSubExpr());
1433
1434 return 0;
1435}
1436
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001437namespace {
1438void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1439 SmallVectorImpl<MCInst> &Instructions) {
1440 MCInst tmpInst;
1441 tmpInst.setOpcode(Opcode);
1442 tmpInst.addOperand(MCOperand::createReg(Reg0));
1443 tmpInst.addOperand(Op1);
1444 tmpInst.setLoc(IDLoc);
1445 Instructions.push_back(tmpInst);
1446}
1447
1448void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1449 SmallVectorImpl<MCInst> &Instructions) {
1450 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1451}
1452
1453void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1454 SmallVectorImpl<MCInst> &Instructions) {
1455 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1456}
1457
1458void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1459 SmallVectorImpl<MCInst> &Instructions) {
1460 MCInst tmpInst;
1461 tmpInst.setOpcode(Opcode);
1462 tmpInst.addOperand(MCOperand::createImm(Imm1));
1463 tmpInst.addOperand(MCOperand::createImm(Imm2));
1464 tmpInst.setLoc(IDLoc);
1465 Instructions.push_back(tmpInst);
1466}
1467
1468void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1469 SmallVectorImpl<MCInst> &Instructions) {
1470 MCInst tmpInst;
1471 tmpInst.setOpcode(Opcode);
1472 tmpInst.addOperand(MCOperand::createReg(Reg0));
1473 tmpInst.setLoc(IDLoc);
1474 Instructions.push_back(tmpInst);
1475}
1476
1477void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1478 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1479 MCInst tmpInst;
1480 tmpInst.setOpcode(Opcode);
1481 tmpInst.addOperand(MCOperand::createReg(Reg0));
1482 tmpInst.addOperand(MCOperand::createReg(Reg1));
1483 tmpInst.addOperand(Op2);
1484 tmpInst.setLoc(IDLoc);
1485 Instructions.push_back(tmpInst);
1486}
1487
1488void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1489 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1490 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1491 Instructions);
1492}
1493
1494void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1495 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1496 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1497 Instructions);
1498}
1499
1500void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1501 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1502 if (ShiftAmount >= 32) {
1503 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1504 Instructions);
1505 return;
1506 }
1507
1508 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1509}
1510} // end anonymous namespace.
1511
Jack Carter9e65aa32013-03-22 00:05:30 +00001512bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001513 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001514 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001515 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001516
Jack Carter9e65aa32013-03-22 00:05:30 +00001517 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001518
1519 if (MCID.isBranch() || MCID.isCall()) {
1520 const unsigned Opcode = Inst.getOpcode();
1521 MCOperand Offset;
1522
1523 switch (Opcode) {
1524 default:
1525 break;
Kai Nackee0245392015-01-27 19:11:28 +00001526 case Mips::BBIT0:
1527 case Mips::BBIT032:
1528 case Mips::BBIT1:
1529 case Mips::BBIT132:
1530 assert(hasCnMips() && "instruction only valid for octeon cpus");
1531 // Fall through
1532
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001533 case Mips::BEQ:
1534 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001535 case Mips::BEQ_MM:
1536 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001537 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001538 Offset = Inst.getOperand(2);
1539 if (!Offset.isImm())
1540 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001541 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001542 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001543 if (OffsetToAlignment(Offset.getImm(),
1544 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001545 return Error(IDLoc, "branch to misaligned address");
1546 break;
1547 case Mips::BGEZ:
1548 case Mips::BGTZ:
1549 case Mips::BLEZ:
1550 case Mips::BLTZ:
1551 case Mips::BGEZAL:
1552 case Mips::BLTZAL:
1553 case Mips::BC1F:
1554 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001555 case Mips::BGEZ_MM:
1556 case Mips::BGTZ_MM:
1557 case Mips::BLEZ_MM:
1558 case Mips::BLTZ_MM:
1559 case Mips::BGEZAL_MM:
1560 case Mips::BLTZAL_MM:
1561 case Mips::BC1F_MM:
1562 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001563 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001564 Offset = Inst.getOperand(1);
1565 if (!Offset.isImm())
1566 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001567 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001568 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001569 if (OffsetToAlignment(Offset.getImm(),
1570 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001571 return Error(IDLoc, "branch to misaligned address");
1572 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001573 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001574 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001575 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001576 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001577 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1578 Offset = Inst.getOperand(1);
1579 if (!Offset.isImm())
1580 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001581 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001582 return Error(IDLoc, "branch target out of range");
1583 if (OffsetToAlignment(Offset.getImm(), 2LL))
1584 return Error(IDLoc, "branch to misaligned address");
1585 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001586 }
1587 }
1588
Daniel Sandersa84989a2014-06-16 13:25:35 +00001589 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1590 // We still accept it but it is a normal nop.
1591 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1592 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1593 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1594 "nop instruction");
1595 }
1596
Kai Nackee0245392015-01-27 19:11:28 +00001597 if (hasCnMips()) {
1598 const unsigned Opcode = Inst.getOpcode();
1599 MCOperand Opnd;
1600 int Imm;
1601
1602 switch (Opcode) {
1603 default:
1604 break;
1605
1606 case Mips::BBIT0:
1607 case Mips::BBIT032:
1608 case Mips::BBIT1:
1609 case Mips::BBIT132:
1610 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1611 // The offset is handled above
1612 Opnd = Inst.getOperand(1);
1613 if (!Opnd.isImm())
1614 return Error(IDLoc, "expected immediate operand kind");
1615 Imm = Opnd.getImm();
1616 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1617 Opcode == Mips::BBIT1 ? 63 : 31))
1618 return Error(IDLoc, "immediate operand value out of range");
1619 if (Imm > 31) {
1620 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1621 : Mips::BBIT132);
1622 Inst.getOperand(1).setImm(Imm - 32);
1623 }
1624 break;
1625
Kai Nackee0245392015-01-27 19:11:28 +00001626 case Mips::SEQi:
1627 case Mips::SNEi:
1628 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1629 Opnd = Inst.getOperand(2);
1630 if (!Opnd.isImm())
1631 return Error(IDLoc, "expected immediate operand kind");
1632 Imm = Opnd.getImm();
1633 if (!isInt<10>(Imm))
1634 return Error(IDLoc, "immediate operand value out of range");
1635 break;
1636 }
1637 }
1638
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001639 // This expansion is not in a function called by tryExpandInstruction()
1640 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001641 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1642 inPicMode()) {
1643 warnIfNoMacro(IDLoc);
1644
1645 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1646
1647 // We can do this expansion if there's only 1 symbol in the argument
1648 // expression.
1649 if (countMCSymbolRefExpr(JalExpr) > 1)
1650 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1651
1652 // FIXME: This is checking the expression can be handled by the later stages
1653 // of the assembler. We ought to leave it to those later stages but
1654 // we can't do that until we stop evaluateRelocExpr() rewriting the
1655 // expressions into non-equivalent forms.
1656 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1657
1658 // FIXME: Add support for label+offset operands (currently causes an error).
1659 // FIXME: Add support for forward-declared local symbols.
1660 // FIXME: Add expansion for when the LargeGOT option is enabled.
1661 if (JalSym->isInSection() || JalSym->isTemporary()) {
1662 if (isABI_O32()) {
1663 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001664 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001665 // R_(MICRO)MIPS_GOT16 label
1666 // addiu $25, $25, 0
1667 // R_(MICRO)MIPS_LO16 label
1668 // jalr $25
1669 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1670 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1671
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001672 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1673 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1674 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1675 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001676 } else if (isABI_N32() || isABI_N64()) {
1677 // If it's a local symbol and the N32/N64 ABIs are being used,
1678 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001679 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001680 // R_(MICRO)MIPS_GOT_DISP label
1681 // jalr $25
1682 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1683
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001684 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1685 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001686 }
1687 } else {
Daniel Sandersb7002032015-11-20 13:16:35 +00001688 // If it's an external/weak symbol, we expand to:
1689 // lw/ld $25, 0($gp)
1690 // R_(MICRO)MIPS_CALL16 label
1691 // jalr $25
1692 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001693
Daniel Sandersb7002032015-11-20 13:16:35 +00001694 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1695 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001696 }
1697
1698 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001699 if (IsCpRestoreSet && inMicroMipsMode())
1700 JalrInst.setOpcode(Mips::JALRS_MM);
1701 else
1702 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001703 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1704 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1705
1706 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1707 // This relocation is supposed to be an optimization hint for the linker
1708 // and is not necessary for correctness.
1709
1710 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001711 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001712 }
1713
Jack Carter9e65aa32013-03-22 00:05:30 +00001714 if (MCID.mayLoad() || MCID.mayStore()) {
1715 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001716 // reference or immediate we may have to expand instructions.
1717 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001718 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001719 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1720 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001721 MCOperand &Op = Inst.getOperand(i);
1722 if (Op.isImm()) {
1723 int MemOffset = Op.getImm();
1724 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001725 // Offset can't exceed 16bit value.
1726 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001727 return false;
1728 }
1729 } else if (Op.isExpr()) {
1730 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001731 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001732 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001733 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001734 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001735 // Expand symbol.
1736 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001737 return false;
1738 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001739 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001740 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001741 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001742 }
1743 }
1744 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001745 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001746 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001747
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001748 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001749 if (MCID.mayLoad()) {
1750 // Try to create 16-bit GP relative load instruction.
1751 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1752 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1753 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1754 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1755 MCOperand &Op = Inst.getOperand(i);
1756 if (Op.isImm()) {
1757 int MemOffset = Op.getImm();
1758 MCOperand &DstReg = Inst.getOperand(0);
1759 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001760 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001761 getContext().getRegisterInfo()->getRegClass(
1762 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001763 (BaseReg.getReg() == Mips::GP ||
1764 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001765
1766 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1767 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001768 return false;
1769 }
1770 }
1771 }
1772 } // for
1773 } // if load
1774
1775 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1776
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001777 MCOperand Opnd;
1778 int Imm;
1779
1780 switch (Inst.getOpcode()) {
1781 default:
1782 break;
1783 case Mips::ADDIUS5_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 < -8 || Imm > 7)
1789 return Error(IDLoc, "immediate operand value out of range");
1790 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001791 case Mips::ADDIUSP_MM:
1792 Opnd = Inst.getOperand(0);
1793 if (!Opnd.isImm())
1794 return Error(IDLoc, "expected immediate operand kind");
1795 Imm = Opnd.getImm();
1796 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1797 Imm % 4 != 0)
1798 return Error(IDLoc, "immediate operand value out of range");
1799 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001800 case Mips::SLL16_MM:
1801 case Mips::SRL16_MM:
1802 Opnd = Inst.getOperand(2);
1803 if (!Opnd.isImm())
1804 return Error(IDLoc, "expected immediate operand kind");
1805 Imm = Opnd.getImm();
1806 if (Imm < 1 || Imm > 8)
1807 return Error(IDLoc, "immediate operand value out of range");
1808 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001809 case Mips::LI16_MM:
1810 Opnd = Inst.getOperand(1);
1811 if (!Opnd.isImm())
1812 return Error(IDLoc, "expected immediate operand kind");
1813 Imm = Opnd.getImm();
1814 if (Imm < -1 || Imm > 126)
1815 return Error(IDLoc, "immediate operand value out of range");
1816 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001817 case Mips::ADDIUR2_MM:
1818 Opnd = Inst.getOperand(2);
1819 if (!Opnd.isImm())
1820 return Error(IDLoc, "expected immediate operand kind");
1821 Imm = Opnd.getImm();
1822 if (!(Imm == 1 || Imm == -1 ||
1823 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1824 return Error(IDLoc, "immediate operand value out of range");
1825 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001826 case Mips::ADDIUR1SP_MM:
1827 Opnd = Inst.getOperand(1);
1828 if (!Opnd.isImm())
1829 return Error(IDLoc, "expected immediate operand kind");
1830 Imm = Opnd.getImm();
1831 if (OffsetToAlignment(Imm, 4LL))
1832 return Error(IDLoc, "misaligned immediate operand value");
1833 if (Imm < 0 || Imm > 255)
1834 return Error(IDLoc, "immediate operand value out of range");
1835 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001836 case Mips::ANDI16_MM:
1837 Opnd = Inst.getOperand(2);
1838 if (!Opnd.isImm())
1839 return Error(IDLoc, "expected immediate operand kind");
1840 Imm = Opnd.getImm();
1841 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1842 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1843 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1844 return Error(IDLoc, "immediate operand value out of range");
1845 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001846 case Mips::LBU16_MM:
1847 Opnd = Inst.getOperand(2);
1848 if (!Opnd.isImm())
1849 return Error(IDLoc, "expected immediate operand kind");
1850 Imm = Opnd.getImm();
1851 if (Imm < -1 || Imm > 14)
1852 return Error(IDLoc, "immediate operand value out of range");
1853 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001854 case Mips::TEQ_MM:
1855 case Mips::TGE_MM:
1856 case Mips::TGEU_MM:
1857 case Mips::TLT_MM:
1858 case Mips::TLTU_MM:
1859 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001860 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001861 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001862 Opnd = Inst.getOperand(2);
1863 if (!Opnd.isImm())
1864 return Error(IDLoc, "expected immediate operand kind");
1865 Imm = Opnd.getImm();
1866 if (Imm < 0 || Imm > 15)
1867 return Error(IDLoc, "immediate operand value out of range");
1868 break;
1869 case Mips::LHU16_MM:
1870 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001871 case Mips::SH16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001872 Opnd = Inst.getOperand(2);
1873 if (!Opnd.isImm())
1874 return Error(IDLoc, "expected immediate operand kind");
1875 Imm = Opnd.getImm();
1876 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1877 return Error(IDLoc, "immediate operand value out of range");
1878 break;
1879 case Mips::LW16_MM:
1880 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001881 case Mips::SW16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001882 Opnd = Inst.getOperand(2);
1883 if (!Opnd.isImm())
1884 return Error(IDLoc, "expected immediate operand kind");
1885 Imm = Opnd.getImm();
1886 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1887 return Error(IDLoc, "immediate operand value out of range");
1888 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001889 case Mips::ADDIUPC_MM:
1890 MCOperand Opnd = Inst.getOperand(1);
1891 if (!Opnd.isImm())
1892 return Error(IDLoc, "expected immediate operand kind");
1893 int Imm = Opnd.getImm();
Craig Topper55b1f292015-10-10 20:17:07 +00001894 if ((Imm % 4 != 0) || !isInt<25>(Imm))
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001895 return Error(IDLoc, "immediate operand value out of range");
1896 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001897 }
1898 }
1899
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001900 MacroExpanderResultTy ExpandResult =
1901 tryExpandInstruction(Inst, IDLoc, Instructions);
1902 switch (ExpandResult) {
1903 case MER_NotAMacro:
Jack Carter9e65aa32013-03-22 00:05:30 +00001904 Instructions.push_back(Inst);
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001905 break;
1906 case MER_Success:
1907 break;
1908 case MER_Fail:
1909 return true;
1910 }
Jack Carter9e65aa32013-03-22 00:05:30 +00001911
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001912 // If this instruction has a delay slot and .set reorder is active,
1913 // emit a NOP after it.
1914 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1915 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1916
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001917 if ((Inst.getOpcode() == Mips::JalOneReg ||
1918 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1919 isPicAndNotNxxAbi()) {
1920 if (IsCpRestoreSet) {
1921 // We need a NOP between the JALR and the LW:
1922 // If .set reorder has been used, we've already emitted a NOP.
1923 // If .set noreorder has been used, we need to emit a NOP at this point.
1924 if (!AssemblerOptions.back()->isReorder())
1925 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1926
1927 // Load the $gp from the stack.
1928 SmallVector<MCInst, 3> LoadInsts;
1929 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1930 IDLoc, LoadInsts);
1931
1932 for (const MCInst &Inst : LoadInsts)
1933 Instructions.push_back(Inst);
1934
1935 } else
1936 Warning(IDLoc, "no .cprestore used in PIC mode");
1937 }
1938
Jack Carter9e65aa32013-03-22 00:05:30 +00001939 return false;
1940}
1941
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001942MipsAsmParser::MacroExpanderResultTy
1943MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
1944 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001945 switch (Inst.getOpcode()) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001946 default:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001947 return MER_NotAMacro;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001948 case Mips::LoadImm32:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001949 return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
1950 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001951 case Mips::LoadImm64:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001952 return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
1953 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001954 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001955 case Mips::LoadAddrImm64:
1956 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1957 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1958 "expected immediate operand kind");
1959
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001960 return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
1961 Inst.getOperand(1),
1962 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
1963 Instructions)
1964 ? MER_Fail
1965 : MER_Success;
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001966 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001967 case Mips::LoadAddrReg64:
1968 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1969 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1970 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1971 "expected immediate operand kind");
1972
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001973 return expandLoadAddress(Inst.getOperand(0).getReg(),
1974 Inst.getOperand(1).getReg(), Inst.getOperand(2),
1975 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
1976 Instructions)
1977 ? MER_Fail
1978 : MER_Success;
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001979 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001980 case Mips::B_MMR6_Pseudo:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001981 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
1982 : MER_Success;
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001983 case Mips::SWM_MM:
1984 case Mips::LWM_MM:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001985 return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
1986 : MER_Success;
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001987 case Mips::JalOneReg:
1988 case Mips::JalTwoReg:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001989 return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
1990 : MER_Success;
Toma Tabacue1e460d2015-06-11 10:36:10 +00001991 case Mips::BneImm:
1992 case Mips::BeqImm:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001993 return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu1a108322015-06-17 13:20:24 +00001994 case Mips::BLT:
1995 case Mips::BLE:
1996 case Mips::BGE:
1997 case Mips::BGT:
1998 case Mips::BLTU:
1999 case Mips::BLEU:
2000 case Mips::BGEU:
2001 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002002 case Mips::BLTL:
2003 case Mips::BLEL:
2004 case Mips::BGEL:
2005 case Mips::BGTL:
2006 case Mips::BLTUL:
2007 case Mips::BLEUL:
2008 case Mips::BGEUL:
2009 case Mips::BGTUL:
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002010 case Mips::BLTImmMacro:
2011 case Mips::BLEImmMacro:
2012 case Mips::BGEImmMacro:
2013 case Mips::BGTImmMacro:
2014 case Mips::BLTUImmMacro:
2015 case Mips::BLEUImmMacro:
2016 case Mips::BGEUImmMacro:
2017 case Mips::BGTUImmMacro:
2018 case Mips::BLTLImmMacro:
2019 case Mips::BLELImmMacro:
2020 case Mips::BGELImmMacro:
2021 case Mips::BGTLImmMacro:
2022 case Mips::BLTULImmMacro:
2023 case Mips::BLEULImmMacro:
2024 case Mips::BGEULImmMacro:
2025 case Mips::BGTULImmMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002026 return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
2027 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002028 case Mips::SDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002029 return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
2030 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002031 case Mips::DSDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002032 return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
2033 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002034 case Mips::UDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002035 return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
2036 : MER_Success;
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002037 case Mips::DUDivMacro:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002038 return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
2039 : MER_Success;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002040 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002041 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002042 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002043 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002044 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002045 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2046 case Mips::NORImm:
2047 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2048 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002049 case Mips::ADDi:
2050 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002051 case Mips::SLTi:
2052 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002053 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2054 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2055 int64_t ImmValue = Inst.getOperand(2).getImm();
2056 if (isInt<16>(ImmValue))
2057 return MER_NotAMacro;
2058 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2059 : MER_Success;
2060 }
2061 return MER_NotAMacro;
2062 case Mips::ANDi:
2063 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002064 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002065 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2066 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2067 int64_t ImmValue = Inst.getOperand(2).getImm();
2068 if (isUInt<16>(ImmValue))
2069 return MER_NotAMacro;
2070 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2071 : MER_Success;
2072 }
2073 return MER_NotAMacro;
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00002074 case Mips::ROL:
2075 case Mips::ROR:
2076 return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail
2077 : MER_Success;
2078 case Mips::ROLImm:
2079 case Mips::RORImm:
2080 return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2081 : MER_Success;
2082 case Mips::DROL:
2083 case Mips::DROR:
2084 return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail
2085 : MER_Success;
2086 case Mips::DROLImm:
2087 case Mips::DRORImm:
2088 return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
2089 : MER_Success;
Jack Carterd0bd6422013-04-18 00:41:53 +00002090 }
Jack Carter30a59822012-10-04 04:03:53 +00002091}
Jack Carter92995f12012-10-06 00:53:28 +00002092
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002093bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2094 SmallVectorImpl<MCInst> &Instructions) {
2095 // Create a JALR instruction which is going to replace the pseudo-JAL.
2096 MCInst JalrInst;
2097 JalrInst.setLoc(IDLoc);
2098 const MCOperand FirstRegOp = Inst.getOperand(0);
2099 const unsigned Opcode = Inst.getOpcode();
2100
2101 if (Opcode == Mips::JalOneReg) {
2102 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002103 if (IsCpRestoreSet && inMicroMipsMode()) {
2104 JalrInst.setOpcode(Mips::JALRS16_MM);
2105 JalrInst.addOperand(FirstRegOp);
2106 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002107 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002108 JalrInst.addOperand(FirstRegOp);
2109 } else {
2110 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002111 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002112 JalrInst.addOperand(FirstRegOp);
2113 }
2114 } else if (Opcode == Mips::JalTwoReg) {
2115 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002116 if (IsCpRestoreSet && inMicroMipsMode())
2117 JalrInst.setOpcode(Mips::JALRS_MM);
2118 else
2119 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002120 JalrInst.addOperand(FirstRegOp);
2121 const MCOperand SecondRegOp = Inst.getOperand(1);
2122 JalrInst.addOperand(SecondRegOp);
2123 }
2124 Instructions.push_back(JalrInst);
2125
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002126 // If .set reorder is active and branch instruction has a delay slot,
2127 // emit a NOP after it.
2128 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2129 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002130 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002131 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002132
2133 return false;
2134}
2135
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002136/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002137template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002138 unsigned BitNum = findFirstSet(x);
2139
2140 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2141}
2142
2143/// Load (or add) an immediate into a register.
2144///
2145/// @param ImmValue The immediate to load.
2146/// @param DstReg The register that will hold the immediate.
2147/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2148/// for a simple initialization.
2149/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2150/// @param IsAddress True if the immediate represents an address. False if it
2151/// is an integer.
2152/// @param IDLoc Location of the immediate in the source file.
2153/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002154bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002155 unsigned SrcReg, bool Is32BitImm,
2156 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002157 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002158 if (!Is32BitImm && !isGP64bit()) {
2159 Error(IDLoc, "instruction requires a 64-bit architecture");
2160 return true;
2161 }
2162
Daniel Sanders03f9c012015-07-14 12:24:22 +00002163 if (Is32BitImm) {
2164 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2165 // Sign extend up to 64-bit so that the predicates match the hardware
2166 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2167 // true.
2168 ImmValue = SignExtend64<32>(ImmValue);
2169 } else {
2170 Error(IDLoc, "instruction requires a 32-bit immediate");
2171 return true;
2172 }
2173 }
2174
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002175 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2176 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2177
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002178 bool UseSrcReg = false;
2179 if (SrcReg != Mips::NoRegister)
2180 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002181
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002182 unsigned TmpReg = DstReg;
2183 if (UseSrcReg && (DstReg == SrcReg)) {
2184 // At this point we need AT to perform the expansions and we exit if it is
2185 // not available.
2186 unsigned ATReg = getATReg(IDLoc);
2187 if (!ATReg)
2188 return true;
2189 TmpReg = ATReg;
2190 }
2191
Daniel Sanders03f9c012015-07-14 12:24:22 +00002192 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002193 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002194 SrcReg = ZeroReg;
2195
2196 // This doesn't quite follow the usual ABI expectations for N32 but matches
2197 // traditional assembler behaviour. N32 would normally use addiu for both
2198 // integers and addresses.
2199 if (IsAddress && !Is32BitImm) {
2200 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2201 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002202 }
2203
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002204 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2205 return false;
2206 }
2207
2208 if (isUInt<16>(ImmValue)) {
2209 unsigned TmpReg = DstReg;
2210 if (SrcReg == DstReg) {
2211 TmpReg = getATReg(IDLoc);
2212 if (!TmpReg)
2213 return true;
2214 }
2215
2216 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002217 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002218 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2219 return false;
2220 }
2221
2222 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002223 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002224
Toma Tabacu79588102015-04-29 10:19:56 +00002225 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2226 uint16_t Bits15To0 = ImmValue & 0xffff;
2227
Toma Tabacua3d056f2015-05-15 09:42:11 +00002228 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002229 // Traditional behaviour seems to special case this particular value. It's
2230 // not clear why other masks are handled differently.
2231 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002232 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002233 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2234 if (UseSrcReg)
2235 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2236 return false;
2237 }
2238
2239 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002240 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002241 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002242 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002243 if (Bits15To0)
2244 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2245 if (UseSrcReg)
2246 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2247 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002248 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002249
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002250 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2251 if (Bits15To0)
2252 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002253 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002254 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2255 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002256 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002257
2258 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2259 if (Is32BitImm) {
2260 Error(IDLoc, "instruction requires a 32-bit immediate");
2261 return true;
2262 }
2263
2264 // Traditionally, these immediates are shifted as little as possible and as
2265 // such we align the most significant bit to bit 15 of our temporary.
2266 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2267 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2268 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2269 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2270 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2271 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2272
2273 if (UseSrcReg)
2274 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2275
2276 return false;
2277 }
2278
2279 warnIfNoMacro(IDLoc);
2280
2281 // The remaining case is packed with a sequence of dsll and ori with zeros
2282 // being omitted and any neighbouring dsll's being coalesced.
2283 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2284
2285 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2286 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2287 IDLoc, Instructions))
2288 return false;
2289
2290 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2291 // skip it and defer the shift to the next chunk.
2292 unsigned ShiftCarriedForwards = 16;
2293 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2294 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2295
2296 if (ImmChunk != 0) {
2297 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2298 Instructions);
2299 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2300 ShiftCarriedForwards = 0;
2301 }
2302
2303 ShiftCarriedForwards += 16;
2304 }
2305 ShiftCarriedForwards -= 16;
2306
2307 // Finish any remaining shifts left by trailing zeros.
2308 if (ShiftCarriedForwards)
2309 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2310 Instructions);
2311
2312 if (UseSrcReg)
2313 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2314
Matheus Almeida3813d572014-06-19 14:39:14 +00002315 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002316}
Jack Carter92995f12012-10-06 00:53:28 +00002317
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002318bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2319 SmallVectorImpl<MCInst> &Instructions) {
2320 const MCOperand &ImmOp = Inst.getOperand(1);
2321 assert(ImmOp.isImm() && "expected immediate operand kind");
2322 const MCOperand &DstRegOp = Inst.getOperand(0);
2323 assert(DstRegOp.isReg() && "expected register operand kind");
2324
2325 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002326 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002327 return true;
2328
2329 return false;
2330}
2331
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002332bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2333 const MCOperand &Offset,
2334 bool Is32BitAddress, SMLoc IDLoc,
2335 SmallVectorImpl<MCInst> &Instructions) {
2336 // la can't produce a usable address when addresses are 64-bit.
2337 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2338 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2339 // We currently can't do this because we depend on the equality
2340 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2341 Error(IDLoc, "la used to load 64-bit address");
2342 // Continue as if we had 'dla' instead.
2343 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002344 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002345
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002346 // dla requires 64-bit addresses.
2347 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2348 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002349 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002350 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002351
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002352 if (!Offset.isImm())
2353 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2354 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002355
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002356 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2357 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002358}
2359
Toma Tabacuf712ede2015-06-17 14:31:51 +00002360bool MipsAsmParser::loadAndAddSymbolAddress(
2361 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2362 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002363 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002364
Daniel Sandersd5a89412015-10-05 13:19:29 +00002365 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2366 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2367 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2368 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2369 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002370
Toma Tabacufb9d1252015-06-22 12:08:39 +00002371 bool UseSrcReg = SrcReg != Mips::NoRegister;
2372
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002373 // This is the 64-bit symbol address expansion.
2374 if (ABI.ArePtrs64bit() && isGP64bit()) {
2375 // We always need AT for the 64-bit expansion.
2376 // If it is not available we exit.
2377 unsigned ATReg = getATReg(IDLoc);
2378 if (!ATReg)
2379 return true;
2380
Daniel Sandersd5a89412015-10-05 13:19:29 +00002381 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2382 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2383 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2384 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002385
2386 if (UseSrcReg && (DstReg == SrcReg)) {
2387 // If $rs is the same as $rd:
2388 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2389 // daddiu $at, $at, %higher(sym)
2390 // dsll $at, $at, 16
2391 // daddiu $at, $at, %hi(sym)
2392 // dsll $at, $at, 16
2393 // daddiu $at, $at, %lo(sym)
2394 // daddu $rd, $at, $rd
2395 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2396 Instructions);
2397 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2398 IDLoc, Instructions);
2399 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2400 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2401 Instructions);
2402 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2403 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2404 Instructions);
2405 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2406
2407 return false;
2408 }
2409
2410 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2411 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2412 // lui $at, %hi(sym)
2413 // daddiu $rd, $rd, %higher(sym)
2414 // daddiu $at, $at, %lo(sym)
2415 // dsll32 $rd, $rd, 0
2416 // daddu $rd, $rd, $at
2417 // (daddu $rd, $rd, $rs)
2418 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2419 Instructions);
2420 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2421 Instructions);
2422 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2423 IDLoc, Instructions);
2424 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2425 Instructions);
2426 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2427 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2428 if (UseSrcReg)
2429 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2430
2431 return false;
2432 }
2433
2434 // And now, the 32-bit symbol address expansion:
2435 // If $rs is the same as $rd:
2436 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2437 // ori $at, $at, %lo(sym)
2438 // addu $rd, $at, $rd
2439 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2440 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2441 // ori $rd, $rd, %lo(sym)
2442 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002443 unsigned TmpReg = DstReg;
2444 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002445 // If $rs is the same as $rd, we need to use AT.
2446 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002447 unsigned ATReg = getATReg(IDLoc);
2448 if (!ATReg)
2449 return true;
2450 TmpReg = ATReg;
2451 }
2452
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002453 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2454 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2455 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002456
Toma Tabacufb9d1252015-06-22 12:08:39 +00002457 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002458 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2459 else
2460 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002461
Toma Tabacu674825c2015-06-16 12:16:24 +00002462 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002463}
2464
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002465bool MipsAsmParser::expandUncondBranchMMPseudo(
2466 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002467 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2468 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002469
2470 MCOperand Offset = Inst.getOperand(0);
2471 if (Offset.isExpr()) {
2472 Inst.clear();
2473 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002474 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2475 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2476 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002477 } else {
2478 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002479 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002480 // If offset fits into 11 bits then this instruction becomes microMIPS
2481 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002482 if (inMicroMipsMode())
2483 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002484 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002485 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002486 Error(IDLoc, "branch target out of range");
2487 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2488 Error(IDLoc, "branch to misaligned address");
2489 Inst.clear();
2490 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002491 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2492 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2493 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002494 }
2495 }
2496 Instructions.push_back(Inst);
2497
Zoran Jovanovicada70912015-09-07 11:56:37 +00002498 // If .set reorder is active and branch instruction has a delay slot,
2499 // emit a NOP after it.
2500 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2501 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002502 createNop(true, IDLoc, Instructions);
2503
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002504 return false;
2505}
2506
Toma Tabacue1e460d2015-06-11 10:36:10 +00002507bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2508 SmallVectorImpl<MCInst> &Instructions) {
2509 const MCOperand &DstRegOp = Inst.getOperand(0);
2510 assert(DstRegOp.isReg() && "expected register operand kind");
2511
2512 const MCOperand &ImmOp = Inst.getOperand(1);
2513 assert(ImmOp.isImm() && "expected immediate operand kind");
2514
2515 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2516 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2517
2518 unsigned OpCode = 0;
2519 switch(Inst.getOpcode()) {
2520 case Mips::BneImm:
2521 OpCode = Mips::BNE;
2522 break;
2523 case Mips::BeqImm:
2524 OpCode = Mips::BEQ;
2525 break;
2526 default:
2527 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2528 break;
2529 }
2530
2531 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002532 if (ImmValue == 0)
2533 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2534 Instructions);
2535 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002536 warnIfNoMacro(IDLoc);
2537
2538 unsigned ATReg = getATReg(IDLoc);
2539 if (!ATReg)
2540 return true;
2541
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002542 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2543 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002544 return true;
2545
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002546 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002547 }
2548 return false;
2549}
2550
Jack Carter9e65aa32013-03-22 00:05:30 +00002551void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002552 SmallVectorImpl<MCInst> &Instructions,
2553 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002554 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002555 const MCExpr *ExprOffset;
2556 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002557 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002558 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2559 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002560 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002561 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2562 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002563 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002564 if (isImmOpnd) {
2565 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2566 ImmOffset = Inst.getOperand(2).getImm();
2567 LoOffset = ImmOffset & 0x0000ffff;
2568 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002569 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002570 if (LoOffset & 0x8000)
2571 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002572 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002573 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002574 // These are some of the types of expansions we perform here:
2575 // 1) lw $8, sym => lui $8, %hi(sym)
2576 // lw $8, %lo(sym)($8)
2577 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2578 // add $8, $8, $9
2579 // lw $8, %lo(offset)($9)
2580 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2581 // add $at, $at, $8
2582 // lw $8, %lo(offset)($at)
2583 // 4) sw $8, sym => lui $at, %hi(sym)
2584 // sw $8, %lo(sym)($at)
2585 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2586 // add $at, $at, $8
2587 // sw $8, %lo(offset)($at)
2588 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2589 // ldc1 $f0, %lo(sym)($at)
2590 //
2591 // For load instructions we can use the destination register as a temporary
2592 // if base and dst are different (examples 1 and 2) and if the base register
2593 // is general purpose otherwise we must use $at (example 6) and error if it's
2594 // not available. For stores we must use $at (examples 4 and 5) because we
2595 // must not clobber the source register setting up the offset.
2596 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2597 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2598 unsigned RegClassIDOp0 =
2599 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2600 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2601 (RegClassIDOp0 == Mips::GPR64RegClassID);
2602 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002603 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002604 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002605 // At this point we need AT to perform the expansions and we exit if it is
2606 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002607 TmpRegNum = getATReg(IDLoc);
2608 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002609 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002610 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002611
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002612 emitRX(Mips::LUi, TmpRegNum,
2613 isImmOpnd ? MCOperand::createImm(HiOffset)
2614 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2615 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002616 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002617 if (BaseRegNum != Mips::ZERO)
2618 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002619 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002620 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002621 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2622 isImmOpnd
2623 ? MCOperand::createImm(LoOffset)
2624 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2625 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002626}
2627
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002628bool
2629MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2630 SmallVectorImpl<MCInst> &Instructions) {
2631 unsigned OpNum = Inst.getNumOperands();
2632 unsigned Opcode = Inst.getOpcode();
2633 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2634
2635 assert (Inst.getOperand(OpNum - 1).isImm() &&
2636 Inst.getOperand(OpNum - 2).isReg() &&
2637 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2638
2639 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2640 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002641 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2642 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2643 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2644 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002645 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002646 if (inMicroMipsMode() && hasMips32r6())
2647 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2648 else
2649 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2650 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002651
2652 Inst.setOpcode(NewOpcode);
2653 Instructions.push_back(Inst);
2654 return false;
2655}
2656
Toma Tabacu1a108322015-06-17 13:20:24 +00002657bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2658 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002659 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002660 unsigned PseudoOpcode = Inst.getOpcode();
2661 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002662 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002663 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2664
2665 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002666 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002667
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002668 unsigned TrgReg;
2669 if (TrgOp.isReg())
2670 TrgReg = TrgOp.getReg();
2671 else if (TrgOp.isImm()) {
2672 warnIfNoMacro(IDLoc);
2673 EmittedNoMacroWarning = true;
2674
2675 TrgReg = getATReg(IDLoc);
2676 if (!TrgReg)
2677 return true;
2678
2679 switch(PseudoOpcode) {
2680 default:
2681 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2682 case Mips::BLTImmMacro:
2683 PseudoOpcode = Mips::BLT;
2684 break;
2685 case Mips::BLEImmMacro:
2686 PseudoOpcode = Mips::BLE;
2687 break;
2688 case Mips::BGEImmMacro:
2689 PseudoOpcode = Mips::BGE;
2690 break;
2691 case Mips::BGTImmMacro:
2692 PseudoOpcode = Mips::BGT;
2693 break;
2694 case Mips::BLTUImmMacro:
2695 PseudoOpcode = Mips::BLTU;
2696 break;
2697 case Mips::BLEUImmMacro:
2698 PseudoOpcode = Mips::BLEU;
2699 break;
2700 case Mips::BGEUImmMacro:
2701 PseudoOpcode = Mips::BGEU;
2702 break;
2703 case Mips::BGTUImmMacro:
2704 PseudoOpcode = Mips::BGTU;
2705 break;
2706 case Mips::BLTLImmMacro:
2707 PseudoOpcode = Mips::BLTL;
2708 break;
2709 case Mips::BLELImmMacro:
2710 PseudoOpcode = Mips::BLEL;
2711 break;
2712 case Mips::BGELImmMacro:
2713 PseudoOpcode = Mips::BGEL;
2714 break;
2715 case Mips::BGTLImmMacro:
2716 PseudoOpcode = Mips::BGTL;
2717 break;
2718 case Mips::BLTULImmMacro:
2719 PseudoOpcode = Mips::BLTUL;
2720 break;
2721 case Mips::BLEULImmMacro:
2722 PseudoOpcode = Mips::BLEUL;
2723 break;
2724 case Mips::BGEULImmMacro:
2725 PseudoOpcode = Mips::BGEUL;
2726 break;
2727 case Mips::BGTULImmMacro:
2728 PseudoOpcode = Mips::BGTUL;
2729 break;
2730 }
2731
2732 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2733 false, IDLoc, Instructions))
2734 return true;
2735 }
2736
Toma Tabacu1a108322015-06-17 13:20:24 +00002737 switch (PseudoOpcode) {
2738 case Mips::BLT:
2739 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002740 case Mips::BLTL:
2741 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002742 AcceptsEquality = false;
2743 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002744 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2745 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002746 ZeroSrcOpcode = Mips::BGTZ;
2747 ZeroTrgOpcode = Mips::BLTZ;
2748 break;
2749 case Mips::BLE:
2750 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002751 case Mips::BLEL:
2752 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002753 AcceptsEquality = true;
2754 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002755 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2756 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002757 ZeroSrcOpcode = Mips::BGEZ;
2758 ZeroTrgOpcode = Mips::BLEZ;
2759 break;
2760 case Mips::BGE:
2761 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002762 case Mips::BGEL:
2763 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002764 AcceptsEquality = true;
2765 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002766 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2767 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002768 ZeroSrcOpcode = Mips::BLEZ;
2769 ZeroTrgOpcode = Mips::BGEZ;
2770 break;
2771 case Mips::BGT:
2772 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002773 case Mips::BGTL:
2774 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002775 AcceptsEquality = false;
2776 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002777 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2778 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002779 ZeroSrcOpcode = Mips::BLTZ;
2780 ZeroTrgOpcode = Mips::BGTZ;
2781 break;
2782 default:
2783 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2784 }
2785
Toma Tabacu1a108322015-06-17 13:20:24 +00002786 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2787 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2788 if (IsSrcRegZero && IsTrgRegZero) {
2789 // FIXME: All of these Opcode-specific if's are needed for compatibility
2790 // with GAS' behaviour. However, they may not generate the most efficient
2791 // code in some circumstances.
2792 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002793 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2794 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002795 return false;
2796 }
2797 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002798 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2799 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002800 Warning(IDLoc, "branch is always taken");
2801 return false;
2802 }
2803 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002804 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2805 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002806 Warning(IDLoc, "branch is always taken");
2807 return false;
2808 }
2809 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002810 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2811 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002812 return false;
2813 }
2814 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002815 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2816 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002817 return false;
2818 }
2819 if (AcceptsEquality) {
2820 // If both registers are $0 and the pseudo-branch accepts equality, it
2821 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002822 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2823 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002824 Warning(IDLoc, "branch is always taken");
2825 return false;
2826 }
2827 // If both registers are $0 and the pseudo-branch does not accept
2828 // equality, it will never be taken, so we don't have to emit anything.
2829 return false;
2830 }
2831 if (IsSrcRegZero || IsTrgRegZero) {
2832 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2833 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2834 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2835 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2836 // the pseudo-branch will never be taken, so we don't emit anything.
2837 // This only applies to unsigned pseudo-branches.
2838 return false;
2839 }
2840 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2841 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2842 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2843 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2844 // the pseudo-branch will always be taken, so we emit an unconditional
2845 // branch.
2846 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002847 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2848 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002849 Warning(IDLoc, "branch is always taken");
2850 return false;
2851 }
2852 if (IsUnsigned) {
2853 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2854 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2855 // the pseudo-branch will be taken only when the non-zero register is
2856 // different from 0, so we emit a BNEZ.
2857 //
2858 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2859 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2860 // the pseudo-branch will be taken only when the non-zero register is
2861 // equal to 0, so we emit a BEQZ.
2862 //
2863 // Because only BLEU and BGEU branch on equality, we can use the
2864 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002865 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2866 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2867 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002868 return false;
2869 }
2870 // If we have a signed pseudo-branch and one of the registers is $0,
2871 // we can use an appropriate compare-to-zero branch. We select which one
2872 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002873 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2874 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2875 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002876 return false;
2877 }
2878
2879 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2880 // expansions. If it is not available, we return.
2881 unsigned ATRegNum = getATReg(IDLoc);
2882 if (!ATRegNum)
2883 return true;
2884
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002885 if (!EmittedNoMacroWarning)
2886 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002887
2888 // SLT fits well with 2 of our 4 pseudo-branches:
2889 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2890 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2891 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2892 // This is accomplished by using a BNEZ with the result of the SLT.
2893 //
2894 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2895 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2896 // Because only BGE and BLE branch on equality, we can use the
2897 // AcceptsEquality variable to decide when to emit the BEQZ.
2898 // Note that the order of the SLT arguments doesn't change between
2899 // opposites.
2900 //
2901 // The same applies to the unsigned variants, except that SLTu is used
2902 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002903 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2904 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2905 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002906
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002907 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2908 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2909 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2910 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002911 return false;
2912}
2913
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002914bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2915 SmallVectorImpl<MCInst> &Instructions,
2916 const bool IsMips64, const bool Signed) {
2917 if (hasMips32r6()) {
2918 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2919 return false;
2920 }
2921
2922 warnIfNoMacro(IDLoc);
2923
2924 const MCOperand &RsRegOp = Inst.getOperand(0);
2925 assert(RsRegOp.isReg() && "expected register operand kind");
2926 unsigned RsReg = RsRegOp.getReg();
2927
2928 const MCOperand &RtRegOp = Inst.getOperand(1);
2929 assert(RtRegOp.isReg() && "expected register operand kind");
2930 unsigned RtReg = RtRegOp.getReg();
2931 unsigned DivOp;
2932 unsigned ZeroReg;
2933
2934 if (IsMips64) {
2935 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2936 ZeroReg = Mips::ZERO_64;
2937 } else {
2938 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2939 ZeroReg = Mips::ZERO;
2940 }
2941
2942 bool UseTraps = useTraps();
2943
2944 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2945 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2946 Warning(IDLoc, "dividing zero by zero");
2947 if (IsMips64) {
2948 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2949 if (UseTraps) {
2950 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2951 return false;
2952 }
2953
2954 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2955 return false;
2956 }
2957 } else {
2958 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2959 return false;
2960 }
2961 }
2962
2963 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2964 Warning(IDLoc, "division by zero");
2965 if (Signed) {
2966 if (UseTraps) {
2967 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2968 return false;
2969 }
2970
2971 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2972 return false;
2973 }
2974 }
2975
2976 // FIXME: The values for these two BranchTarget variables may be different in
2977 // micromips. These magic numbers need to be removed.
2978 unsigned BranchTargetNoTraps;
2979 unsigned BranchTarget;
2980
2981 if (UseTraps) {
2982 BranchTarget = IsMips64 ? 12 : 8;
2983 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2984 } else {
2985 BranchTarget = IsMips64 ? 20 : 16;
2986 BranchTargetNoTraps = 8;
2987 // Branch to the li instruction.
2988 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2989 Instructions);
2990 }
2991
2992 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2993
2994 if (!UseTraps)
2995 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2996
2997 if (!Signed) {
2998 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2999 return false;
3000 }
3001
3002 unsigned ATReg = getATReg(IDLoc);
3003 if (!ATReg)
3004 return true;
3005
3006 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
3007 if (IsMips64) {
3008 // Branch to the mflo instruction.
3009 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3010 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
3011 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
3012 } else {
3013 // Branch to the mflo instruction.
3014 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3015 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
3016 }
3017
3018 if (UseTraps)
3019 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3020 else {
3021 // Branch to the mflo instruction.
3022 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3023 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3024 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3025 }
3026 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3027 return false;
3028}
3029
Daniel Sanders6394ee52015-10-15 14:52:58 +00003030bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3031 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003032 if (hasMips32r6() || hasMips64r6()) {
3033 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3034 return false;
3035 }
3036
3037 warnIfNoMacro(IDLoc);
3038
3039 const MCOperand &DstRegOp = Inst.getOperand(0);
3040 assert(DstRegOp.isReg() && "expected register operand kind");
3041
3042 const MCOperand &SrcRegOp = Inst.getOperand(1);
3043 assert(SrcRegOp.isReg() && "expected register operand kind");
3044
3045 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3046 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3047
3048 unsigned DstReg = DstRegOp.getReg();
3049 unsigned SrcReg = SrcRegOp.getReg();
3050 int64_t OffsetValue = OffsetImmOp.getImm();
3051
3052 // NOTE: We always need AT for ULHU, as it is always used as the source
3053 // register for one of the LBu's.
3054 unsigned ATReg = getATReg(IDLoc);
3055 if (!ATReg)
3056 return true;
3057
3058 // When the value of offset+1 does not fit in 16 bits, we have to load the
3059 // offset in AT, (D)ADDu the original source register (if there was one), and
3060 // then use AT as the source register for the 2 generated LBu's.
3061 bool LoadedOffsetInAT = false;
3062 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3063 LoadedOffsetInAT = true;
3064
3065 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003066 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003067 return true;
3068
3069 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3070 // because it will make our output more similar to GAS'. For example,
3071 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3072 // instead of just an "ori $1, $9, 32768".
3073 // NOTE: If there is no source register specified in the ULHU, the parser
3074 // will interpret it as $0.
3075 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3076 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3077 }
3078
3079 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3080 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3081 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3082
3083 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3084 if (isLittle()) {
3085 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3086 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3087 } else {
3088 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3089 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3090 }
3091
3092 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3093
Daniel Sanders6394ee52015-10-15 14:52:58 +00003094 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3095 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003096
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003097 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3098 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003099
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003100 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003101
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003102 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003103
3104 return false;
3105}
3106
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003107bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3108 SmallVectorImpl<MCInst> &Instructions) {
3109 if (hasMips32r6() || hasMips64r6()) {
3110 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3111 return false;
3112 }
3113
3114 const MCOperand &DstRegOp = Inst.getOperand(0);
3115 assert(DstRegOp.isReg() && "expected register operand kind");
3116
3117 const MCOperand &SrcRegOp = Inst.getOperand(1);
3118 assert(SrcRegOp.isReg() && "expected register operand kind");
3119
3120 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3121 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3122
3123 unsigned SrcReg = SrcRegOp.getReg();
3124 int64_t OffsetValue = OffsetImmOp.getImm();
3125 unsigned ATReg = 0;
3126
3127 // When the value of offset+3 does not fit in 16 bits, we have to load the
3128 // offset in AT, (D)ADDu the original source register (if there was one), and
3129 // then use AT as the source register for the generated LWL and LWR.
3130 bool LoadedOffsetInAT = false;
3131 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3132 ATReg = getATReg(IDLoc);
3133 if (!ATReg)
3134 return true;
3135 LoadedOffsetInAT = true;
3136
3137 warnIfNoMacro(IDLoc);
3138
3139 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003140 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003141 return true;
3142
3143 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3144 // because it will make our output more similar to GAS'. For example,
3145 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3146 // instead of just an "ori $1, $9, 32768".
3147 // NOTE: If there is no source register specified in the ULW, the parser
3148 // will interpret it as $0.
3149 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3150 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3151 }
3152
3153 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3154 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3155 if (isLittle()) {
3156 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3157 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3158 } else {
3159 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3160 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3161 }
3162
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003163 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3164 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003165
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003166 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3167 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003168
3169 return false;
3170}
3171
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003172bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3173 SmallVectorImpl<MCInst> &Instructions) {
3174
3175 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3176 assert (Inst.getOperand(0).isReg() &&
3177 Inst.getOperand(1).isReg() &&
3178 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3179
3180 unsigned ATReg = Mips::NoRegister;
3181 unsigned FinalDstReg = Mips::NoRegister;
3182 unsigned DstReg = Inst.getOperand(0).getReg();
3183 unsigned SrcReg = Inst.getOperand(1).getReg();
3184 int64_t ImmValue = Inst.getOperand(2).getImm();
3185
3186 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3187
3188 unsigned FinalOpcode = Inst.getOpcode();
3189
3190 if (DstReg == SrcReg) {
3191 ATReg = getATReg(Inst.getLoc());
3192 if (!ATReg)
3193 return true;
3194 FinalDstReg = DstReg;
3195 DstReg = ATReg;
3196 }
3197
3198 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3199 switch (FinalOpcode) {
3200 default:
3201 llvm_unreachable("unimplemented expansion");
3202 case (Mips::ADDi):
3203 FinalOpcode = Mips::ADD;
3204 break;
3205 case (Mips::ADDiu):
3206 FinalOpcode = Mips::ADDu;
3207 break;
3208 case (Mips::ANDi):
3209 FinalOpcode = Mips::AND;
3210 break;
3211 case (Mips::NORImm):
3212 FinalOpcode = Mips::NOR;
3213 break;
3214 case (Mips::ORi):
3215 FinalOpcode = Mips::OR;
3216 break;
3217 case (Mips::SLTi):
3218 FinalOpcode = Mips::SLT;
3219 break;
3220 case (Mips::SLTiu):
3221 FinalOpcode = Mips::SLTu;
3222 break;
3223 case (Mips::XORi):
3224 FinalOpcode = Mips::XOR;
3225 break;
3226 }
3227
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003228 if (FinalDstReg == Mips::NoRegister)
3229 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3230 else
3231 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3232 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003233 return false;
3234 }
3235 return true;
3236}
3237
Zoran Jovanovic00f998b2015-11-19 14:15:03 +00003238bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
3239 SmallVectorImpl<MCInst> &Instructions) {
3240 unsigned ATReg = Mips::NoRegister;
3241 unsigned DReg = Inst.getOperand(0).getReg();
3242 unsigned SReg = Inst.getOperand(1).getReg();
3243 unsigned TReg = Inst.getOperand(2).getReg();
3244 unsigned TmpReg = DReg;
3245
3246 unsigned FirstShift = Mips::NOP;
3247 unsigned SecondShift = Mips::NOP;
3248
3249 if (hasMips32r2()) {
3250
3251 if (DReg == SReg) {
3252 TmpReg = getATReg(Inst.getLoc());
3253 if (!TmpReg)
3254 return true;
3255 }
3256
3257 if (Inst.getOpcode() == Mips::ROL) {
3258 emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3259 emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3260 return false;
3261 }
3262
3263 if (Inst.getOpcode() == Mips::ROR) {
3264 emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3265 return false;
3266 }
3267
3268 return true;
3269 }
3270
3271 if (hasMips32()) {
3272
3273 switch (Inst.getOpcode()) {
3274 default:
3275 llvm_unreachable("unexpected instruction opcode");
3276 case Mips::ROL:
3277 FirstShift = Mips::SRLV;
3278 SecondShift = Mips::SLLV;
3279 break;
3280 case Mips::ROR:
3281 FirstShift = Mips::SLLV;
3282 SecondShift = Mips::SRLV;
3283 break;
3284 }
3285
3286 ATReg = getATReg(Inst.getLoc());
3287 if (!ATReg)
3288 return true;
3289
3290 emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3291 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3292 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3293 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3294
3295 return false;
3296 }
3297
3298 return true;
3299}
3300
3301bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
3302 SmallVectorImpl<MCInst> &Instructions) {
3303
3304 unsigned ATReg = Mips::NoRegister;
3305 unsigned DReg = Inst.getOperand(0).getReg();
3306 unsigned SReg = Inst.getOperand(1).getReg();
3307 int64_t ImmValue = Inst.getOperand(2).getImm();
3308
3309 unsigned FirstShift = Mips::NOP;
3310 unsigned SecondShift = Mips::NOP;
3311
3312 if (hasMips32r2()) {
3313
3314 if (Inst.getOpcode() == Mips::ROLImm) {
3315 uint64_t MaxShift = 32;
3316 uint64_t ShiftValue = ImmValue;
3317 if (ImmValue != 0)
3318 ShiftValue = MaxShift - ImmValue;
3319 emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3320 return false;
3321 }
3322
3323 if (Inst.getOpcode() == Mips::RORImm) {
3324 emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3325 return false;
3326 }
3327
3328 return true;
3329 }
3330
3331 if (hasMips32()) {
3332
3333 if (ImmValue == 0) {
3334 emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3335 return false;
3336 }
3337
3338 switch (Inst.getOpcode()) {
3339 default:
3340 llvm_unreachable("unexpected instruction opcode");
3341 case Mips::ROLImm:
3342 FirstShift = Mips::SLL;
3343 SecondShift = Mips::SRL;
3344 break;
3345 case Mips::RORImm:
3346 FirstShift = Mips::SRL;
3347 SecondShift = Mips::SLL;
3348 break;
3349 }
3350
3351 ATReg = getATReg(Inst.getLoc());
3352 if (!ATReg)
3353 return true;
3354
3355 emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions);
3356 emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions);
3357 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3358
3359 return false;
3360 }
3361
3362 return true;
3363}
3364
3365bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
3366 SmallVectorImpl<MCInst> &Instructions) {
3367
3368 unsigned ATReg = Mips::NoRegister;
3369 unsigned DReg = Inst.getOperand(0).getReg();
3370 unsigned SReg = Inst.getOperand(1).getReg();
3371 unsigned TReg = Inst.getOperand(2).getReg();
3372 unsigned TmpReg = DReg;
3373
3374 unsigned FirstShift = Mips::NOP;
3375 unsigned SecondShift = Mips::NOP;
3376
3377 if (hasMips64r2()) {
3378
3379 if (TmpReg == SReg) {
3380 TmpReg = getATReg(Inst.getLoc());
3381 if (!TmpReg)
3382 return true;
3383 }
3384
3385 if (Inst.getOpcode() == Mips::DROL) {
3386 emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3387 emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
3388 return false;
3389 }
3390
3391 if (Inst.getOpcode() == Mips::DROR) {
3392 emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3393 return false;
3394 }
3395
3396 return true;
3397 }
3398
3399 if (hasMips64()) {
3400
3401 switch (Inst.getOpcode()) {
3402 default:
3403 llvm_unreachable("unexpected instruction opcode");
3404 case Mips::DROL:
3405 FirstShift = Mips::DSRLV;
3406 SecondShift = Mips::DSLLV;
3407 break;
3408 case Mips::DROR:
3409 FirstShift = Mips::DSLLV;
3410 SecondShift = Mips::DSRLV;
3411 break;
3412 }
3413
3414 ATReg = getATReg(Inst.getLoc());
3415 if (!ATReg)
3416 return true;
3417
3418 emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
3419 emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
3420 emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
3421 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3422
3423 return false;
3424 }
3425
3426 return true;
3427}
3428
3429bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
3430 SmallVectorImpl<MCInst> &Instructions) {
3431
3432 unsigned ATReg = Mips::NoRegister;
3433 unsigned DReg = Inst.getOperand(0).getReg();
3434 unsigned SReg = Inst.getOperand(1).getReg();
3435 int64_t ImmValue = Inst.getOperand(2).getImm() % 64;
3436
3437 unsigned FirstShift = Mips::NOP;
3438 unsigned SecondShift = Mips::NOP;
3439
3440 MCInst TmpInst;
3441
3442 if (hasMips64r2()) {
3443
3444 unsigned FinalOpcode = Mips::NOP;
3445 if (ImmValue == 0)
3446 FinalOpcode = Mips::DROTR;
3447 else if (ImmValue % 32 == 0)
3448 FinalOpcode = Mips::DROTR32;
3449 else if ((ImmValue >= 1) && (ImmValue <= 32)) {
3450 if (Inst.getOpcode() == Mips::DROLImm)
3451 FinalOpcode = Mips::DROTR32;
3452 else
3453 FinalOpcode = Mips::DROTR;
3454 } else if (ImmValue >= 33) {
3455 if (Inst.getOpcode() == Mips::DROLImm)
3456 FinalOpcode = Mips::DROTR;
3457 else
3458 FinalOpcode = Mips::DROTR32;
3459 }
3460
3461 uint64_t ShiftValue = ImmValue % 32;
3462 if (Inst.getOpcode() == Mips::DROLImm)
3463 ShiftValue = (32 - ImmValue % 32) % 32;
3464
3465 emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
3466
3467 return false;
3468 }
3469
3470 if (hasMips64()) {
3471
3472 if (ImmValue == 0) {
3473 emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
3474 return false;
3475 }
3476
3477 switch (Inst.getOpcode()) {
3478 default:
3479 llvm_unreachable("unexpected instruction opcode");
3480 case Mips::DROLImm:
3481 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3482 FirstShift = Mips::DSLL;
3483 SecondShift = Mips::DSRL32;
3484 }
3485 if (ImmValue == 32) {
3486 FirstShift = Mips::DSLL32;
3487 SecondShift = Mips::DSRL32;
3488 }
3489 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3490 FirstShift = Mips::DSLL32;
3491 SecondShift = Mips::DSRL;
3492 }
3493 break;
3494 case Mips::DRORImm:
3495 if ((ImmValue >= 1) && (ImmValue <= 31)) {
3496 FirstShift = Mips::DSRL;
3497 SecondShift = Mips::DSLL32;
3498 }
3499 if (ImmValue == 32) {
3500 FirstShift = Mips::DSRL32;
3501 SecondShift = Mips::DSLL32;
3502 }
3503 if ((ImmValue >= 33) && (ImmValue <= 63)) {
3504 FirstShift = Mips::DSRL32;
3505 SecondShift = Mips::DSLL;
3506 }
3507 break;
3508 }
3509
3510 ATReg = getATReg(Inst.getLoc());
3511 if (!ATReg)
3512 return true;
3513
3514 emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions);
3515 emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions);
3516 emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
3517
3518 return false;
3519 }
3520
3521 return true;
3522}
3523
Toma Tabacu234482a2015-03-16 12:03:39 +00003524void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3525 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003526 if (hasShortDelaySlot)
3527 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3528 else
3529 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003530}
3531
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003532void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003533 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003534 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003535 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3536 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003537}
3538
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003539void MipsAsmParser::createCpRestoreMemOp(
3540 bool IsLoad, int StackOffset, SMLoc IDLoc,
3541 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003542 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003543 if (!isInt<16>(StackOffset)) {
3544 MCInst MemInst;
3545 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3546 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3547 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3548 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003549 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003550 return;
3551 }
3552
3553 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3554 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003555}
3556
Matheus Almeida595fcab2014-06-11 15:05:56 +00003557unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3558 // As described by the Mips32r2 spec, the registers Rd and Rs for
3559 // jalr.hb must be different.
3560 unsigned Opcode = Inst.getOpcode();
3561
3562 if (Opcode == Mips::JALR_HB &&
3563 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3564 return Match_RequiresDifferentSrcAndDst;
3565
3566 return Match_Success;
3567}
3568
Daniel Sanders52da7af2015-11-06 12:11:03 +00003569static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3570 uint64_t ErrorInfo) {
3571 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3572 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3573 if (ErrorLoc == SMLoc())
3574 return Loc;
3575 return ErrorLoc;
3576 }
3577 return Loc;
3578}
3579
David Blaikie960ea3f2014-06-08 16:18:35 +00003580bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3581 OperandVector &Operands,
3582 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003583 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003584 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003585
Jack Carterb4dbc172012-09-05 23:34:03 +00003586 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003587 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003588 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003589 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003590
3591 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003592 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003593 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003594 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003595 for (unsigned i = 0; i < Instructions.size(); i++)
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003596 Out.EmitInstruction(Instructions[i], getSTI());
Jack Carterb4dbc172012-09-05 23:34:03 +00003597 return false;
3598 }
3599 case Match_MissingFeature:
3600 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3601 return true;
3602 case Match_InvalidOperand: {
3603 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003604 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003605 if (ErrorInfo >= Operands.size())
3606 return Error(IDLoc, "too few operands for instruction");
3607
Daniel Sanders52da7af2015-11-06 12:11:03 +00003608 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003609 if (ErrorLoc == SMLoc())
3610 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003611 }
3612
3613 return Error(ErrorLoc, "invalid operand for instruction");
3614 }
3615 case Match_MnemonicFail:
3616 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003617 case Match_RequiresDifferentSrcAndDst:
3618 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003619 case Match_Immz:
3620 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003621 case Match_UImm1_0:
3622 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3623 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003624 case Match_UImm2_0:
3625 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3626 "expected 2-bit unsigned immediate");
3627 case Match_UImm2_1:
3628 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3629 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003630 case Match_UImm3_0:
3631 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3632 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003633 case Match_UImm4_0:
3634 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3635 "expected 4-bit unsigned immediate");
Daniel Sandersdaa4b6f2015-11-26 16:35:41 +00003636 case Match_UImm5_0:
3637 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3638 "expected 5-bit unsigned immediate");
3639 case Match_UImm5_32:
3640 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3641 "expected immediate in range 32 .. 63");
3642 case Match_UImm5_0_Report_UImm6:
3643 // This is used on UImm5 operands that have a corresponding UImm5_32
3644 // operand to avoid confusing the user.
3645 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3646 "expected 6-bit unsigned immediate");
3647 case Match_UImm5_Lsl2:
3648 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3649 "expected both 7-bit unsigned immediate and multiple of 4");
Daniel Sanders59d092f2015-12-08 13:49:19 +00003650 case Match_UImm6_0:
3651 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3652 "expected 6-bit unsigned immediate");
Daniel Sanders106d2d42015-12-08 14:42:10 +00003653 case Match_UImm8_0:
3654 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3655 "expected 8-bit unsigned immediate");
Daniel Sanders3c722312015-12-09 13:48:05 +00003656 case Match_UImm10_0:
3657 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3658 "expected 10-bit unsigned immediate");
Jack Carterb4dbc172012-09-05 23:34:03 +00003659 }
Craig Topper589ceee2015-01-03 08:16:34 +00003660
3661 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003662}
3663
Toma Tabacud9d344b2015-04-27 14:05:04 +00003664void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3665 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3666 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3667 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003668}
3669
Toma Tabacu81496c12015-05-20 08:54:45 +00003670void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3671 if (!AssemblerOptions.back()->isMacro())
3672 Warning(Loc, "macro instruction expanded into multiple instructions");
3673}
3674
Daniel Sandersef638fe2014-10-03 15:37:37 +00003675void
3676MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3677 SMRange Range, bool ShowColors) {
3678 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003679 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003680 ShowColors);
3681}
3682
Jack Carter1ac53222013-02-20 23:11:17 +00003683int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003684 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003685
Vladimir Medic4c299852013-11-06 11:27:05 +00003686 CC = StringSwitch<unsigned>(Name)
3687 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003688 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003689 .Case("a0", 4)
3690 .Case("a1", 5)
3691 .Case("a2", 6)
3692 .Case("a3", 7)
3693 .Case("v0", 2)
3694 .Case("v1", 3)
3695 .Case("s0", 16)
3696 .Case("s1", 17)
3697 .Case("s2", 18)
3698 .Case("s3", 19)
3699 .Case("s4", 20)
3700 .Case("s5", 21)
3701 .Case("s6", 22)
3702 .Case("s7", 23)
3703 .Case("k0", 26)
3704 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003705 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003706 .Case("sp", 29)
3707 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003708 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003709 .Case("ra", 31)
3710 .Case("t0", 8)
3711 .Case("t1", 9)
3712 .Case("t2", 10)
3713 .Case("t3", 11)
3714 .Case("t4", 12)
3715 .Case("t5", 13)
3716 .Case("t6", 14)
3717 .Case("t7", 15)
3718 .Case("t8", 24)
3719 .Case("t9", 25)
3720 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003721
Toma Tabacufda445c2014-09-15 15:33:01 +00003722 if (!(isABI_N32() || isABI_N64()))
3723 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003724
Daniel Sandersef638fe2014-10-03 15:37:37 +00003725 if (12 <= CC && CC <= 15) {
3726 // Name is one of t4-t7
3727 AsmToken RegTok = getLexer().peekTok();
3728 SMRange RegRange = RegTok.getLocRange();
3729
3730 StringRef FixedName = StringSwitch<StringRef>(Name)
3731 .Case("t4", "t0")
3732 .Case("t5", "t1")
3733 .Case("t6", "t2")
3734 .Case("t7", "t3")
3735 .Default("");
3736 assert(FixedName != "" && "Register name is not one of t4-t7.");
3737
3738 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3739 "Did you mean $" + FixedName + "?", RegRange);
3740 }
3741
Toma Tabacufda445c2014-09-15 15:33:01 +00003742 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3743 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3744 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3745 if (8 <= CC && CC <= 11)
3746 CC += 4;
3747
3748 if (CC == -1)
3749 CC = StringSwitch<unsigned>(Name)
3750 .Case("a4", 8)
3751 .Case("a5", 9)
3752 .Case("a6", 10)
3753 .Case("a7", 11)
3754 .Case("kt0", 26)
3755 .Case("kt1", 27)
3756 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003757
3758 return CC;
3759}
Jack Carterd0bd6422013-04-18 00:41:53 +00003760
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003761int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3762 int CC;
3763
3764 CC = StringSwitch<unsigned>(Name)
3765 .Case("hwr_cpunum", 0)
3766 .Case("hwr_synci_step", 1)
3767 .Case("hwr_cc", 2)
3768 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003769 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003770 .Default(-1);
3771
3772 return CC;
3773}
3774
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003775int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003776
Jack Cartera63b16a2012-09-07 00:23:42 +00003777 if (Name[0] == 'f') {
3778 StringRef NumString = Name.substr(1);
3779 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003780 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003781 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003782 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003783 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003784 return IntVal;
3785 }
3786 return -1;
3787}
Jack Cartera63b16a2012-09-07 00:23:42 +00003788
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003789int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3790
3791 if (Name.startswith("fcc")) {
3792 StringRef NumString = Name.substr(3);
3793 unsigned IntVal;
3794 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003795 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003796 if (IntVal > 7) // There are only 8 fcc registers.
3797 return -1;
3798 return IntVal;
3799 }
3800 return -1;
3801}
3802
3803int MipsAsmParser::matchACRegisterName(StringRef Name) {
3804
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003805 if (Name.startswith("ac")) {
3806 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003807 unsigned IntVal;
3808 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003809 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003810 if (IntVal > 3) // There are only 3 acc registers.
3811 return -1;
3812 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003813 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003814 return -1;
3815}
Jack Carterd0bd6422013-04-18 00:41:53 +00003816
Jack Carter5dc8ac92013-09-25 23:50:44 +00003817int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3818 unsigned IntVal;
3819
3820 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3821 return -1;
3822
3823 if (IntVal > 31)
3824 return -1;
3825
3826 return IntVal;
3827}
3828
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003829int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3830 int CC;
3831
3832 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003833 .Case("msair", 0)
3834 .Case("msacsr", 1)
3835 .Case("msaaccess", 2)
3836 .Case("msasave", 3)
3837 .Case("msamodify", 4)
3838 .Case("msarequest", 5)
3839 .Case("msamap", 6)
3840 .Case("msaunmap", 7)
3841 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003842
3843 return CC;
3844}
3845
Toma Tabacu89a712b2015-04-15 10:48:56 +00003846unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003847 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003848 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003849 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003850 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003851 return 0;
3852 }
3853 unsigned AT = getReg(
3854 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003855 return AT;
3856}
Jack Carter0b744b32012-10-04 02:29:46 +00003857
Jack Carterd0bd6422013-04-18 00:41:53 +00003858unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003859 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003860}
3861
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003862unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003863 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003864 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003865}
3866
Jack Carter873c7242013-01-12 01:03:14 +00003867int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003868 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003869 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003870 return -1;
3871
Jack Carter873c7242013-01-12 01:03:14 +00003872 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003873}
3874
Toma Tabacu13964452014-09-04 13:23:44 +00003875bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003876 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003877 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003878
Jack Carter30a59822012-10-04 04:03:53 +00003879 // Check if the current operand has a custom associated parser, if so, try to
3880 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003881 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3882 if (ResTy == MatchOperand_Success)
3883 return false;
3884 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3885 // there was a match, but an error occurred, in which case, just return that
3886 // the operand parsing failed.
3887 if (ResTy == MatchOperand_ParseFail)
3888 return true;
3889
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003890 DEBUG(dbgs() << ".. Generic Parser\n");
3891
Jack Carterb4dbc172012-09-05 23:34:03 +00003892 switch (getLexer().getKind()) {
3893 default:
3894 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3895 return true;
3896 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003897 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003898 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003899
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003900 // Almost all registers have been parsed by custom parsers. There is only
3901 // one exception to this. $zero (and it's alias $0) will reach this point
3902 // for div, divu, and similar instructions because it is not an operand
3903 // to the instruction definition but an explicit register. Special case
3904 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003905 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003906 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003907
Jack Carterd0bd6422013-04-18 00:41:53 +00003908 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003909 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003910 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003911 return true;
3912
Jack Carter873c7242013-01-12 01:03:14 +00003913 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003914 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003915 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003916 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003917 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003918
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003919 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003920 return false;
3921 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003922 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003923 case AsmToken::LParen:
3924 case AsmToken::Minus:
3925 case AsmToken::Plus:
3926 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003927 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003928 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003929 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003930 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003931 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003932 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003933 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003934 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003935 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003936 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003937 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003938 return true;
3939
Jack Carter873c7242013-01-12 01:03:14 +00003940 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3941
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003942 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003943 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003944 } // case AsmToken::Percent
3945 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003946 return true;
3947}
3948
Vladimir Medic4c299852013-11-06 11:27:05 +00003949const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003950 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003951 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003952 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003953 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003954 // It's a constant, evaluate reloc value.
3955 int16_t Val;
3956 switch (getVariantKind(RelocStr)) {
3957 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3958 // Get the 1st 16-bits.
3959 Val = MCE->getValue() & 0xffff;
3960 break;
3961 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3962 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3963 // 16 bits being negative.
3964 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3965 break;
3966 case MCSymbolRefExpr::VK_Mips_HIGHER:
3967 // Get the 3rd 16-bits.
3968 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3969 break;
3970 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3971 // Get the 4th 16-bits.
3972 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3973 break;
3974 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003975 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003976 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003977 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003978 }
3979
Jack Carterb5cf5902013-04-17 00:18:04 +00003980 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003981 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003982 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003983 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003984 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003985 return Res;
3986 }
3987
3988 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003989 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3990
Sasa Stankovic06c47802014-04-03 10:37:45 +00003991 // Try to create target expression.
3992 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003993 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003994
Jack Carterd0bd6422013-04-18 00:41:53 +00003995 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3996 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003997 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003998 return Res;
3999 }
4000
4001 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004002 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004003 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00004004 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00004005 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004006 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00004007 return Expr;
4008}
4009
4010bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
4011
4012 switch (Expr->getKind()) {
4013 case MCExpr::Constant:
4014 return true;
4015 case MCExpr::SymbolRef:
4016 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
4017 case MCExpr::Binary:
4018 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
4019 if (!isEvaluated(BE->getLHS()))
4020 return false;
4021 return isEvaluated(BE->getRHS());
4022 }
4023 case MCExpr::Unary:
4024 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00004025 case MCExpr::Target:
4026 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004027 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004028 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00004029}
Jack Carterd0bd6422013-04-18 00:41:53 +00004030
Jack Carterb5cf5902013-04-17 00:18:04 +00004031bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004032 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004033 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00004034 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00004035 if (Tok.isNot(AsmToken::Identifier))
4036 return true;
4037
Yaron Keren075759a2015-03-30 15:42:36 +00004038 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00004039
Jack Carterd0bd6422013-04-18 00:41:53 +00004040 Parser.Lex(); // Eat the identifier.
4041 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004042 const MCExpr *IdVal;
4043 SMLoc EndLoc;
4044
4045 if (getLexer().getKind() == AsmToken::LParen) {
4046 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004047 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004048 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004049 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004050 const AsmToken &nextTok = Parser.getTok();
4051 if (nextTok.isNot(AsmToken::Identifier))
4052 return true;
4053 Str += "(%";
4054 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00004055 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00004056 if (getLexer().getKind() != AsmToken::LParen)
4057 return true;
4058 } else
4059 break;
4060 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004061 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00004062 return true;
4063
4064 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00004065 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004066
4067 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00004068 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004069
Jack Carterd0bd6422013-04-18 00:41:53 +00004070 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00004071 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004072}
4073
Jack Carterb4dbc172012-09-05 23:34:03 +00004074bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
4075 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004076 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00004077 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004078 if (ResTy == MatchOperand_Success) {
4079 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00004080 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004081 StartLoc = Operand.getStartLoc();
4082 EndLoc = Operand.getEndLoc();
4083
4084 // AFAIK, we only support numeric registers and named GPR's in CFI
4085 // directives.
4086 // Don't worry about eating tokens before failing. Using an unrecognised
4087 // register is a parse error.
4088 if (Operand.isGPRAsmReg()) {
4089 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004090 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004091 }
4092
4093 return (RegNo == (unsigned)-1);
4094 }
4095
4096 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00004097 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00004098}
4099
Jack Carterb5cf5902013-04-17 00:18:04 +00004100bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004101 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00004102 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004103 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004104 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00004105
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004106 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00004107 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004108 ++NumOfLParen;
4109 }
Jack Carter873c7242013-01-12 01:03:14 +00004110
Jack Carterd0bd6422013-04-18 00:41:53 +00004111 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004112 default:
4113 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00004114 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00004115 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00004116 case AsmToken::Integer:
4117 case AsmToken::Minus:
4118 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00004119 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00004120 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00004121 else
4122 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00004123 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00004124 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004125 break;
Jack Carter873c7242013-01-12 01:03:14 +00004126 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00004127 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004128 }
Jack Carterb5cf5902013-04-17 00:18:04 +00004129 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004130}
4131
David Blaikie960ea3f2014-06-08 16:18:35 +00004132MipsAsmParser::OperandMatchResultTy
4133MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004134 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004135 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00004136 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00004137 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00004138 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004139 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00004140 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00004141 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00004142
Jack Carterb5cf5902013-04-17 00:18:04 +00004143 if (getLexer().getKind() == AsmToken::LParen) {
4144 Parser.Lex();
4145 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004146 }
4147
Jack Carterb5cf5902013-04-17 00:18:04 +00004148 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00004149 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00004150 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004151
Jack Carterd0bd6422013-04-18 00:41:53 +00004152 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004153 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004154 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00004155 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00004156 SMLoc E =
4157 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004158 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004159 return MatchOperand_Success;
4160 }
4161 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004162 SMLoc E =
4163 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00004164
Jack Carterd0bd6422013-04-18 00:41:53 +00004165 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004166 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00004167 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004168 S, E, *this);
4169 Operands.push_back(
4170 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00004171 return MatchOperand_Success;
4172 }
4173 Error(Parser.getTok().getLoc(), "'(' expected");
4174 return MatchOperand_ParseFail;
4175 }
4176
Jack Carterd0bd6422013-04-18 00:41:53 +00004177 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00004178 }
4179
Toma Tabacu13964452014-09-04 13:23:44 +00004180 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004181 if (Res != MatchOperand_Success)
4182 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00004183
Vladimir Medic27c87ea2013-08-13 13:07:09 +00004184 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00004185 Error(Parser.getTok().getLoc(), "')' expected");
4186 return MatchOperand_ParseFail;
4187 }
4188
Jack Carter873c7242013-01-12 01:03:14 +00004189 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4190
Jack Carterd0bd6422013-04-18 00:41:53 +00004191 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004192
Craig Topper062a2ba2014-04-25 05:30:21 +00004193 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004194 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00004195
Jack Carterd0bd6422013-04-18 00:41:53 +00004196 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004197 std::unique_ptr<MipsOperand> op(
4198 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00004199 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00004200 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00004201 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00004202 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00004203 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
4204 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004205 if (IdVal->evaluateAsAbsolute(Imm))
4206 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00004207 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00004208 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00004209 getContext());
4210 }
4211
David Blaikie960ea3f2014-06-08 16:18:35 +00004212 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004213 return MatchOperand_Success;
4214}
4215
David Blaikie960ea3f2014-06-08 16:18:35 +00004216bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004217 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00004218 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00004219 if (Sym) {
4220 SMLoc S = Parser.getTok().getLoc();
4221 const MCExpr *Expr;
4222 if (Sym->isVariable())
4223 Expr = Sym->getVariableValue();
4224 else
4225 return false;
4226 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00004227 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00004228 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00004229 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004230 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004231 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00004232 if (ResTy == MatchOperand_Success) {
4233 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00004234 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00004235 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004236 llvm_unreachable("Should never ParseFail");
4237 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00004238 }
4239 } else if (Expr->getKind() == MCExpr::Constant) {
4240 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00004241 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00004242 Operands.push_back(
4243 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00004244 return true;
4245 }
4246 }
4247 return false;
4248}
Jack Carterd0bd6422013-04-18 00:41:53 +00004249
Jack Carter873c7242013-01-12 01:03:14 +00004250MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004251MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00004252 StringRef Identifier,
4253 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004254 int Index = matchCPURegisterName(Identifier);
4255 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004256 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004257 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4258 return MatchOperand_Success;
4259 }
4260
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00004261 Index = matchHWRegsRegisterName(Identifier);
4262 if (Index != -1) {
4263 Operands.push_back(MipsOperand::createHWRegsReg(
4264 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4265 return MatchOperand_Success;
4266 }
4267
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004268 Index = matchFPURegisterName(Identifier);
4269 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004270 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004271 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4272 return MatchOperand_Success;
4273 }
4274
4275 Index = matchFCCRegisterName(Identifier);
4276 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004277 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004278 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4279 return MatchOperand_Success;
4280 }
4281
4282 Index = matchACRegisterName(Identifier);
4283 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004284 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004285 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4286 return MatchOperand_Success;
4287 }
4288
4289 Index = matchMSA128RegisterName(Identifier);
4290 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004291 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004292 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4293 return MatchOperand_Success;
4294 }
4295
4296 Index = matchMSA128CtrlRegisterName(Identifier);
4297 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00004298 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004299 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
4300 return MatchOperand_Success;
4301 }
4302
4303 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004304}
4305
4306MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004307MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004308 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004309 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004310
4311 if (Token.is(AsmToken::Identifier)) {
4312 DEBUG(dbgs() << ".. identifier\n");
4313 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004314 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004315 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004316 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004317 } else if (Token.is(AsmToken::Integer)) {
4318 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004319 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004320 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4321 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004322 return MatchOperand_Success;
4323 }
4324
4325 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4326
4327 return MatchOperand_NoMatch;
4328}
4329
David Blaikie960ea3f2014-06-08 16:18:35 +00004330MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004331MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004332 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004333 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004334
4335 auto Token = Parser.getTok();
4336
4337 SMLoc S = Token.getLoc();
4338
4339 if (Token.isNot(AsmToken::Dollar)) {
4340 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4341 if (Token.is(AsmToken::Identifier)) {
4342 if (searchSymbolAlias(Operands))
4343 return MatchOperand_Success;
4344 }
4345 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4346 return MatchOperand_NoMatch;
4347 }
4348 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004349
Toma Tabacu13964452014-09-04 13:23:44 +00004350 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004351 if (ResTy == MatchOperand_Success) {
4352 Parser.Lex(); // $
4353 Parser.Lex(); // identifier
4354 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004355 return ResTy;
4356}
4357
4358MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004359MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004360 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004361 switch (getLexer().getKind()) {
4362 default:
4363 return MatchOperand_NoMatch;
4364 case AsmToken::LParen:
4365 case AsmToken::Minus:
4366 case AsmToken::Plus:
4367 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004368 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004369 case AsmToken::String:
4370 break;
4371 }
4372
4373 const MCExpr *IdVal;
4374 SMLoc S = Parser.getTok().getLoc();
4375 if (getParser().parseExpression(IdVal))
4376 return MatchOperand_ParseFail;
4377
4378 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4379 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4380 return MatchOperand_Success;
4381}
4382
David Blaikie960ea3f2014-06-08 16:18:35 +00004383MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004384MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004385 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004386 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004387
4388 SMLoc S = getLexer().getLoc();
4389
4390 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004391 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004392 if (ResTy != MatchOperand_NoMatch)
4393 return ResTy;
4394
Daniel Sanders315386c2014-04-01 10:40:14 +00004395 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004396 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004397 if (ResTy != MatchOperand_NoMatch)
4398 return ResTy;
4399
Daniel Sandersffd84362014-04-01 10:41:48 +00004400 const MCExpr *Expr = nullptr;
4401 if (Parser.parseExpression(Expr)) {
4402 // We have no way of knowing if a symbol was consumed so we must ParseFail
4403 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004404 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004405 Operands.push_back(
4406 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004407 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004408}
4409
Vladimir Medic2b953d02013-10-01 09:48:56 +00004410MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004411MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004412 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004413 const MCExpr *IdVal;
4414 // If the first token is '$' we may have register operand.
4415 if (Parser.getTok().is(AsmToken::Dollar))
4416 return MatchOperand_NoMatch;
4417 SMLoc S = Parser.getTok().getLoc();
4418 if (getParser().parseExpression(IdVal))
4419 return MatchOperand_ParseFail;
4420 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004421 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004422 int64_t Val = MCE->getValue();
4423 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4424 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004425 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004426 return MatchOperand_Success;
4427}
4428
Matheus Almeida779c5932013-11-18 12:32:49 +00004429MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004430MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004431 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004432 switch (getLexer().getKind()) {
4433 default:
4434 return MatchOperand_NoMatch;
4435 case AsmToken::LParen:
4436 case AsmToken::Plus:
4437 case AsmToken::Minus:
4438 case AsmToken::Integer:
4439 break;
4440 }
4441
4442 const MCExpr *Expr;
4443 SMLoc S = Parser.getTok().getLoc();
4444
4445 if (getParser().parseExpression(Expr))
4446 return MatchOperand_ParseFail;
4447
4448 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004449 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004450 Error(S, "expected immediate value");
4451 return MatchOperand_ParseFail;
4452 }
4453
4454 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4455 // and because the CPU always adds one to the immediate field, the allowed
4456 // range becomes 1..4. We'll only check the range here and will deal
4457 // with the addition/subtraction when actually decoding/encoding
4458 // the instruction.
4459 if (Val < 1 || Val > 4) {
4460 Error(S, "immediate not in range (1..4)");
4461 return MatchOperand_ParseFail;
4462 }
4463
Jack Carter3b2c96e2014-01-22 23:31:38 +00004464 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004465 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004466 return MatchOperand_Success;
4467}
4468
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004469MipsAsmParser::OperandMatchResultTy
4470MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4471 MCAsmParser &Parser = getParser();
4472 SmallVector<unsigned, 10> Regs;
4473 unsigned RegNo;
4474 unsigned PrevReg = Mips::NoRegister;
4475 bool RegRange = false;
4476 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4477
4478 if (Parser.getTok().isNot(AsmToken::Dollar))
4479 return MatchOperand_ParseFail;
4480
4481 SMLoc S = Parser.getTok().getLoc();
4482 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4483 SMLoc E = getLexer().getLoc();
4484 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4485 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4486 if (RegRange) {
4487 // Remove last register operand because registers from register range
4488 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004489 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4490 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004491 Regs.push_back(RegNo);
4492 } else {
4493 unsigned TmpReg = PrevReg + 1;
4494 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004495 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4496 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4497 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004498 Error(E, "invalid register operand");
4499 return MatchOperand_ParseFail;
4500 }
4501
4502 PrevReg = TmpReg;
4503 Regs.push_back(TmpReg++);
4504 }
4505 }
4506
4507 RegRange = false;
4508 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004509 if ((PrevReg == Mips::NoRegister) &&
4510 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4511 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004512 Error(E, "$16 or $31 expected");
4513 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004514 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4515 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4516 !isGP64bit()) ||
4517 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4518 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4519 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004520 Error(E, "invalid register operand");
4521 return MatchOperand_ParseFail;
4522 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004523 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4524 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4525 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004526 Error(E, "consecutive register numbers expected");
4527 return MatchOperand_ParseFail;
4528 }
4529
4530 Regs.push_back(RegNo);
4531 }
4532
4533 if (Parser.getTok().is(AsmToken::Minus))
4534 RegRange = true;
4535
4536 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4537 !Parser.getTok().isNot(AsmToken::Comma)) {
4538 Error(E, "',' or '-' expected");
4539 return MatchOperand_ParseFail;
4540 }
4541
4542 Lex(); // Consume comma or minus
4543 if (Parser.getTok().isNot(AsmToken::Dollar))
4544 break;
4545
4546 PrevReg = RegNo;
4547 }
4548
4549 SMLoc E = Parser.getTok().getLoc();
4550 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4551 parseMemOperand(Operands);
4552 return MatchOperand_Success;
4553}
4554
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004555MipsAsmParser::OperandMatchResultTy
4556MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4557 MCAsmParser &Parser = getParser();
4558
4559 SMLoc S = Parser.getTok().getLoc();
4560 if (parseAnyRegister(Operands) != MatchOperand_Success)
4561 return MatchOperand_ParseFail;
4562
4563 SMLoc E = Parser.getTok().getLoc();
4564 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4565 unsigned Reg = Op.getGPR32Reg();
4566 Operands.pop_back();
4567 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4568 return MatchOperand_Success;
4569}
4570
Zoran Jovanovic41688672015-02-10 16:36:20 +00004571MipsAsmParser::OperandMatchResultTy
4572MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4573 MCAsmParser &Parser = getParser();
4574 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4575 SmallVector<unsigned, 10> Regs;
4576
4577 if (Parser.getTok().isNot(AsmToken::Dollar))
4578 return MatchOperand_ParseFail;
4579
4580 SMLoc S = Parser.getTok().getLoc();
4581
4582 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4583 return MatchOperand_ParseFail;
4584
4585 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4586 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4587 Regs.push_back(RegNo);
4588
4589 SMLoc E = Parser.getTok().getLoc();
4590 if (Parser.getTok().isNot(AsmToken::Comma)) {
4591 Error(E, "',' expected");
4592 return MatchOperand_ParseFail;
4593 }
4594
4595 // Remove comma.
4596 Parser.Lex();
4597
4598 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4599 return MatchOperand_ParseFail;
4600
4601 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4602 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4603 Regs.push_back(RegNo);
4604
4605 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4606
4607 return MatchOperand_Success;
4608}
4609
Jack Carterdc1e35d2012-09-06 20:00:02 +00004610MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4611
Vladimir Medic4c299852013-11-06 11:27:05 +00004612 MCSymbolRefExpr::VariantKind VK =
4613 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4614 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4615 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4616 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4617 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4618 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4619 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4620 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4621 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4622 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4623 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4624 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4625 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4626 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4627 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4628 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4629 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4630 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004631 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4632 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4633 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4634 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4635 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4636 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004637 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4638 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004639 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004640
Matheus Almeida2852af82014-04-22 10:15:54 +00004641 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004642
Jack Carterdc1e35d2012-09-06 20:00:02 +00004643 return VK;
4644}
Jack Cartera63b16a2012-09-07 00:23:42 +00004645
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004646/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4647/// either this.
4648/// ::= '(', register, ')'
4649/// handle it before we iterate so we don't get tripped up by the lack of
4650/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004651bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004652 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004653 if (getLexer().is(AsmToken::LParen)) {
4654 Operands.push_back(
4655 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4656 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004657 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004658 SMLoc Loc = getLexer().getLoc();
4659 Parser.eatToEndOfStatement();
4660 return Error(Loc, "unexpected token in argument list");
4661 }
4662 if (Parser.getTok().isNot(AsmToken::RParen)) {
4663 SMLoc Loc = getLexer().getLoc();
4664 Parser.eatToEndOfStatement();
4665 return Error(Loc, "unexpected token, expected ')'");
4666 }
4667 Operands.push_back(
4668 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4669 Parser.Lex();
4670 }
4671 return false;
4672}
4673
4674/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4675/// either one of these.
4676/// ::= '[', register, ']'
4677/// ::= '[', integer, ']'
4678/// handle it before we iterate so we don't get tripped up by the lack of
4679/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004680bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004681 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004682 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004683 if (getLexer().is(AsmToken::LBrac)) {
4684 Operands.push_back(
4685 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4686 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004687 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004688 SMLoc Loc = getLexer().getLoc();
4689 Parser.eatToEndOfStatement();
4690 return Error(Loc, "unexpected token in argument list");
4691 }
4692 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4693 SMLoc Loc = getLexer().getLoc();
4694 Parser.eatToEndOfStatement();
4695 return Error(Loc, "unexpected token, expected ']'");
4696 }
4697 Operands.push_back(
4698 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4699 Parser.Lex();
4700 }
4701 return false;
4702}
4703
David Blaikie960ea3f2014-06-08 16:18:35 +00004704bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4705 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004706 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004707 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004708
4709 // We have reached first instruction, module directive are now forbidden.
4710 getTargetStreamer().forbidModuleDirective();
4711
Vladimir Medic74593e62013-07-17 15:00:42 +00004712 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004713 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004714 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004715 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004716 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004717 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004718 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004719
4720 // Read the remaining operands.
4721 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4722 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004723 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004724 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004725 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004726 return Error(Loc, "unexpected token in argument list");
4727 }
Toma Tabacu13964452014-09-04 13:23:44 +00004728 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004729 return true;
4730 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004731
Jack Carterd0bd6422013-04-18 00:41:53 +00004732 while (getLexer().is(AsmToken::Comma)) {
4733 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004734 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004735 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004736 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004737 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004738 return Error(Loc, "unexpected token in argument list");
4739 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004740 // Parse bracket and parenthesis suffixes before we iterate
4741 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004742 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004743 return true;
4744 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004745 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004746 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004747 }
4748 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004749 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4750 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004751 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004752 return Error(Loc, "unexpected token in argument list");
4753 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004754 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004755 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004756}
4757
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004758bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004759 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004760 SMLoc Loc = getLexer().getLoc();
4761 Parser.eatToEndOfStatement();
4762 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004763}
4764
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004765bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004766 return Error(Loc, ErrorMsg);
4767}
4768
Jack Carter0b744b32012-10-04 02:29:46 +00004769bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004770 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004771 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004772
4773 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004774 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004775
4776 Parser.Lex(); // Eat "noat".
4777
Jack Carterd0bd6422013-04-18 00:41:53 +00004778 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004779 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004780 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004781 return false;
4782 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004783
4784 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004785 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004786 return false;
4787}
Jack Carterd0bd6422013-04-18 00:41:53 +00004788
Jack Carter0b744b32012-10-04 02:29:46 +00004789bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004790 // Line can be: ".set at", which sets $at to $1
4791 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004792 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004793 Parser.Lex(); // Eat "at".
4794
Jack Carter0b744b32012-10-04 02:29:46 +00004795 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004796 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004797 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004798
4799 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004800 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004801 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004802 }
4803
4804 if (getLexer().isNot(AsmToken::Equal)) {
4805 reportParseError("unexpected token, expected equals sign");
4806 return false;
4807 }
4808 Parser.Lex(); // Eat "=".
4809
4810 if (getLexer().isNot(AsmToken::Dollar)) {
4811 if (getLexer().is(AsmToken::EndOfStatement)) {
4812 reportParseError("no register specified");
4813 return false;
4814 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004815 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004816 return false;
4817 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004818 }
4819 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004820
Toma Tabacu16a74492015-02-13 10:30:57 +00004821 // Find out what "reg" is.
4822 unsigned AtRegNo;
4823 const AsmToken &Reg = Parser.getTok();
4824 if (Reg.is(AsmToken::Identifier)) {
4825 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4826 } else if (Reg.is(AsmToken::Integer)) {
4827 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004828 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004829 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004830 return false;
4831 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004832
4833 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004834 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004835 reportParseError("invalid register");
4836 return false;
4837 }
4838 Parser.Lex(); // Eat "reg".
4839
4840 // If this is not the end of the statement, report an error.
4841 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4842 reportParseError("unexpected token, expected end of statement");
4843 return false;
4844 }
4845
4846 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4847
4848 Parser.Lex(); // Consume the EndOfStatement.
4849 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004850}
4851
4852bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004853 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004854 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004855 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004856 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004857 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004858 return false;
4859 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004860 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004861 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004862 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004863 return false;
4864}
4865
4866bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004867 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004868 Parser.Lex();
4869 // If this is not the end of the statement, report an error.
4870 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004871 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004872 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004873 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004874 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004875 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004876 Parser.Lex(); // Consume the EndOfStatement.
4877 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004878}
4879
4880bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004881 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004882 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004883 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004884 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004885 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004886 return false;
4887 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004888 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004889 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004890 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004891 return false;
4892}
4893
4894bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004895 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004896 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004897 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004898 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004899 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004900 return false;
4901 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004902 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004903 reportParseError("`noreorder' must be set before `nomacro'");
4904 return false;
4905 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004906 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004907 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004908 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004909 return false;
4910}
Jack Carterd76b2372013-03-21 21:44:16 +00004911
Daniel Sanders44934432014-08-07 12:03:36 +00004912bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004913 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004914 Parser.Lex();
4915
4916 // If this is not the end of the statement, report an error.
4917 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004918 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004919
4920 setFeatureBits(Mips::FeatureMSA, "msa");
4921 getTargetStreamer().emitDirectiveSetMsa();
4922 return false;
4923}
4924
4925bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004926 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004927 Parser.Lex();
4928
4929 // If this is not the end of the statement, report an error.
4930 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004931 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004932
4933 clearFeatureBits(Mips::FeatureMSA, "msa");
4934 getTargetStreamer().emitDirectiveSetNoMsa();
4935 return false;
4936}
4937
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004938bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004939 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004940 Parser.Lex(); // Eat "nodsp".
4941
4942 // If this is not the end of the statement, report an error.
4943 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4944 reportParseError("unexpected token, expected end of statement");
4945 return false;
4946 }
4947
4948 clearFeatureBits(Mips::FeatureDSP, "dsp");
4949 getTargetStreamer().emitDirectiveSetNoDsp();
4950 return false;
4951}
4952
Toma Tabacucc2502d2014-11-04 17:18:07 +00004953bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004954 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004955 Parser.Lex(); // Eat "mips16".
4956
Jack Carter39536722014-01-22 23:08:42 +00004957 // If this is not the end of the statement, report an error.
4958 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004959 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004960 return false;
4961 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004962
4963 setFeatureBits(Mips::FeatureMips16, "mips16");
4964 getTargetStreamer().emitDirectiveSetMips16();
4965 Parser.Lex(); // Consume the EndOfStatement.
4966 return false;
4967}
4968
4969bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004970 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004971 Parser.Lex(); // Eat "nomips16".
4972
4973 // If this is not the end of the statement, report an error.
4974 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4975 reportParseError("unexpected token, expected end of statement");
4976 return false;
4977 }
4978
4979 clearFeatureBits(Mips::FeatureMips16, "mips16");
4980 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004981 Parser.Lex(); // Consume the EndOfStatement.
4982 return false;
4983}
4984
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004985bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004986 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004987 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004988 // Line can be: .set fp=32
4989 // .set fp=xx
4990 // .set fp=64
4991 Parser.Lex(); // Eat fp token
4992 AsmToken Tok = Parser.getTok();
4993 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004994 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004995 return false;
4996 }
4997 Parser.Lex(); // Eat '=' token.
4998 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004999
5000 if (!parseFpABIValue(FpAbiVal, ".set"))
5001 return false;
5002
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005003 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005004 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005005 return false;
5006 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005007 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005008 Parser.Lex(); // Consume the EndOfStatement.
5009 return false;
5010}
5011
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005012bool MipsAsmParser::parseSetOddSPRegDirective() {
5013 MCAsmParser &Parser = getParser();
5014
5015 Parser.Lex(); // Eat "oddspreg".
5016 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5017 reportParseError("unexpected token, expected end of statement");
5018 return false;
5019 }
5020
5021 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5022 getTargetStreamer().emitDirectiveSetOddSPReg();
5023 return false;
5024}
5025
5026bool MipsAsmParser::parseSetNoOddSPRegDirective() {
5027 MCAsmParser &Parser = getParser();
5028
5029 Parser.Lex(); // Eat "nooddspreg".
5030 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5031 reportParseError("unexpected token, expected end of statement");
5032 return false;
5033 }
5034
5035 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
5036 getTargetStreamer().emitDirectiveSetNoOddSPReg();
5037 return false;
5038}
5039
Toma Tabacu9db22db2014-09-09 10:15:38 +00005040bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005041 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005042 SMLoc Loc = getLexer().getLoc();
5043
5044 Parser.Lex();
5045 if (getLexer().isNot(AsmToken::EndOfStatement))
5046 return reportParseError("unexpected token, expected end of statement");
5047
5048 // Always keep an element on the options "stack" to prevent the user
5049 // from changing the initial options. This is how we remember them.
5050 if (AssemblerOptions.size() == 2)
5051 return reportParseError(Loc, ".set pop with no .set push");
5052
Akira Hatanakab11ef082015-11-14 06:35:56 +00005053 MCSubtargetInfo &STI = copySTI();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005054 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005055 setAvailableFeatures(
5056 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
5057 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00005058
5059 getTargetStreamer().emitDirectiveSetPop();
5060 return false;
5061}
5062
5063bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005064 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005065 Parser.Lex();
5066 if (getLexer().isNot(AsmToken::EndOfStatement))
5067 return reportParseError("unexpected token, expected end of statement");
5068
5069 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00005070 AssemblerOptions.push_back(
5071 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00005072
5073 getTargetStreamer().emitDirectiveSetPush();
5074 return false;
5075}
5076
Toma Tabacu29696502015-06-02 09:48:04 +00005077bool MipsAsmParser::parseSetSoftFloatDirective() {
5078 MCAsmParser &Parser = getParser();
5079 Parser.Lex();
5080 if (getLexer().isNot(AsmToken::EndOfStatement))
5081 return reportParseError("unexpected token, expected end of statement");
5082
5083 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5084 getTargetStreamer().emitDirectiveSetSoftFloat();
5085 return false;
5086}
5087
5088bool MipsAsmParser::parseSetHardFloatDirective() {
5089 MCAsmParser &Parser = getParser();
5090 Parser.Lex();
5091 if (getLexer().isNot(AsmToken::EndOfStatement))
5092 return reportParseError("unexpected token, expected end of statement");
5093
5094 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5095 getTargetStreamer().emitDirectiveSetHardFloat();
5096 return false;
5097}
5098
Jack Carterd76b2372013-03-21 21:44:16 +00005099bool MipsAsmParser::parseSetAssignment() {
5100 StringRef Name;
5101 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00005102 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00005103
5104 if (Parser.parseIdentifier(Name))
5105 reportParseError("expected identifier after .set");
5106
5107 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005108 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00005109 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00005110
Jack Carter3b2c96e2014-01-22 23:31:38 +00005111 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00005112 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00005113
Jim Grosbach6f482002015-05-18 18:43:14 +00005114 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00005115 Sym->setVariableValue(Value);
5116
5117 return false;
5118}
Jack Carterd0bd6422013-04-18 00:41:53 +00005119
Toma Tabacu26647792014-09-09 12:52:14 +00005120bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005121 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00005122 Parser.Lex();
5123 if (getLexer().isNot(AsmToken::EndOfStatement))
5124 return reportParseError("unexpected token, expected end of statement");
5125
5126 // Reset assembler options to their initial values.
Akira Hatanakab11ef082015-11-14 06:35:56 +00005127 MCSubtargetInfo &STI = copySTI();
Toma Tabacu465acfd2015-06-09 13:33:26 +00005128 setAvailableFeatures(
5129 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
5130 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00005131 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
5132
5133 getTargetStreamer().emitDirectiveSetMips0();
5134 return false;
5135}
5136
Toma Tabacu85618b32014-08-19 14:22:52 +00005137bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005138 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00005139 Parser.Lex();
5140 if (getLexer().isNot(AsmToken::Equal))
5141 return reportParseError("unexpected token, expected equals sign");
5142
5143 Parser.Lex();
5144 StringRef Arch;
5145 if (Parser.parseIdentifier(Arch))
5146 return reportParseError("expected arch identifier");
5147
5148 StringRef ArchFeatureName =
5149 StringSwitch<StringRef>(Arch)
5150 .Case("mips1", "mips1")
5151 .Case("mips2", "mips2")
5152 .Case("mips3", "mips3")
5153 .Case("mips4", "mips4")
5154 .Case("mips5", "mips5")
5155 .Case("mips32", "mips32")
5156 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005157 .Case("mips32r3", "mips32r3")
5158 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005159 .Case("mips32r6", "mips32r6")
5160 .Case("mips64", "mips64")
5161 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00005162 .Case("mips64r3", "mips64r3")
5163 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00005164 .Case("mips64r6", "mips64r6")
5165 .Case("cnmips", "cnmips")
5166 .Case("r4000", "mips3") // This is an implementation of Mips3.
5167 .Default("");
5168
5169 if (ArchFeatureName.empty())
5170 return reportParseError("unsupported architecture");
5171
5172 selectArch(ArchFeatureName);
5173 getTargetStreamer().emitDirectiveSetArch(Arch);
5174 return false;
5175}
5176
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005177bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005178 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005179 Parser.Lex();
5180 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005181 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005182
Matheus Almeida2852af82014-04-22 10:15:54 +00005183 switch (Feature) {
5184 default:
5185 llvm_unreachable("Unimplemented feature");
5186 case Mips::FeatureDSP:
5187 setFeatureBits(Mips::FeatureDSP, "dsp");
5188 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005189 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005190 case Mips::FeatureMicroMips:
5191 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005192 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005193 case Mips::FeatureMips1:
5194 selectArch("mips1");
5195 getTargetStreamer().emitDirectiveSetMips1();
5196 break;
5197 case Mips::FeatureMips2:
5198 selectArch("mips2");
5199 getTargetStreamer().emitDirectiveSetMips2();
5200 break;
5201 case Mips::FeatureMips3:
5202 selectArch("mips3");
5203 getTargetStreamer().emitDirectiveSetMips3();
5204 break;
5205 case Mips::FeatureMips4:
5206 selectArch("mips4");
5207 getTargetStreamer().emitDirectiveSetMips4();
5208 break;
5209 case Mips::FeatureMips5:
5210 selectArch("mips5");
5211 getTargetStreamer().emitDirectiveSetMips5();
5212 break;
5213 case Mips::FeatureMips32:
5214 selectArch("mips32");
5215 getTargetStreamer().emitDirectiveSetMips32();
5216 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005217 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005218 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005219 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005220 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005221 case Mips::FeatureMips32r3:
5222 selectArch("mips32r3");
5223 getTargetStreamer().emitDirectiveSetMips32R3();
5224 break;
5225 case Mips::FeatureMips32r5:
5226 selectArch("mips32r5");
5227 getTargetStreamer().emitDirectiveSetMips32R5();
5228 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005229 case Mips::FeatureMips32r6:
5230 selectArch("mips32r6");
5231 getTargetStreamer().emitDirectiveSetMips32R6();
5232 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005233 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005234 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00005235 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005236 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00005237 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00005238 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00005239 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005240 break;
Daniel Sanders17793142015-02-18 16:24:50 +00005241 case Mips::FeatureMips64r3:
5242 selectArch("mips64r3");
5243 getTargetStreamer().emitDirectiveSetMips64R3();
5244 break;
5245 case Mips::FeatureMips64r5:
5246 selectArch("mips64r5");
5247 getTargetStreamer().emitDirectiveSetMips64R5();
5248 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00005249 case Mips::FeatureMips64r6:
5250 selectArch("mips64r6");
5251 getTargetStreamer().emitDirectiveSetMips64R6();
5252 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00005253 }
5254 return false;
5255}
5256
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005257bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005258 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005259 if (getLexer().isNot(AsmToken::Comma)) {
5260 SMLoc Loc = getLexer().getLoc();
5261 Parser.eatToEndOfStatement();
5262 return Error(Loc, ErrorStr);
5263 }
5264
Matheus Almeida2852af82014-04-22 10:15:54 +00005265 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005266 return true;
5267}
5268
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005269// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
5270// In this class, it is only used for .cprestore.
5271// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
5272// MipsTargetELFStreamer and MipsAsmParser.
5273bool MipsAsmParser::isPicAndNotNxxAbi() {
5274 return inPicMode() && !(isABI_N32() || isABI_N64());
5275}
5276
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005277bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00005278 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00005279 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005280
Toma Tabacudde4c462014-11-06 10:02:45 +00005281 if (inMips16Mode()) {
5282 reportParseError(".cpload is not supported in Mips16 mode");
5283 return false;
5284 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005285
David Blaikie960ea3f2014-06-08 16:18:35 +00005286 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00005287 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005288 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5289 reportParseError("expected register containing function address");
5290 return false;
5291 }
5292
David Blaikie960ea3f2014-06-08 16:18:35 +00005293 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
5294 if (!RegOpnd.isGPRAsmReg()) {
5295 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005296 return false;
5297 }
5298
Toma Tabacudde4c462014-11-06 10:02:45 +00005299 // If this is not the end of the statement, report an error.
5300 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5301 reportParseError("unexpected token, expected end of statement");
5302 return false;
5303 }
5304
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005305 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005306 return false;
5307}
5308
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005309bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5310 MCAsmParser &Parser = getParser();
5311
5312 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5313 // is used in non-PIC mode.
5314
5315 if (inMips16Mode()) {
5316 reportParseError(".cprestore is not supported in Mips16 mode");
5317 return false;
5318 }
5319
5320 // Get the stack offset value.
5321 const MCExpr *StackOffset;
5322 int64_t StackOffsetVal;
5323 if (Parser.parseExpression(StackOffset)) {
5324 reportParseError("expected stack offset value");
5325 return false;
5326 }
5327
5328 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5329 reportParseError("stack offset is not an absolute expression");
5330 return false;
5331 }
5332
5333 if (StackOffsetVal < 0) {
5334 Warning(Loc, ".cprestore with negative stack offset has no effect");
5335 IsCpRestoreSet = false;
5336 } else {
5337 IsCpRestoreSet = true;
5338 CpRestoreOffset = StackOffsetVal;
5339 }
5340
5341 // If this is not the end of the statement, report an error.
5342 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5343 reportParseError("unexpected token, expected end of statement");
5344 return false;
5345 }
5346
5347 // Store the $gp on the stack.
5348 SmallVector<MCInst, 3> StoreInsts;
5349 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5350 StoreInsts);
5351
5352 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5353 Parser.Lex(); // Consume the EndOfStatement.
5354 return false;
5355}
5356
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005357bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005358 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005359 unsigned FuncReg;
5360 unsigned Save;
5361 bool SaveIsReg = true;
5362
Matheus Almeida7e815762014-06-18 13:08:59 +00005363 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005364 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005365 if (ResTy == MatchOperand_NoMatch) {
5366 reportParseError("expected register containing function address");
5367 Parser.eatToEndOfStatement();
5368 return false;
5369 }
5370
5371 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5372 if (!FuncRegOpnd.isGPRAsmReg()) {
5373 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5374 Parser.eatToEndOfStatement();
5375 return false;
5376 }
5377
5378 FuncReg = FuncRegOpnd.getGPR32Reg();
5379 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005380
Toma Tabacu65f10572014-09-16 15:00:52 +00005381 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005382 return true;
5383
Toma Tabacu13964452014-09-04 13:23:44 +00005384 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005385 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005386 const MCExpr *OffsetExpr;
5387 int64_t OffsetVal;
5388 SMLoc ExprLoc = getLexer().getLoc();
5389
5390 if (Parser.parseExpression(OffsetExpr) ||
5391 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5392 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005393 Parser.eatToEndOfStatement();
5394 return false;
5395 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005396
5397 Save = OffsetVal;
5398 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005399 } else {
5400 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5401 if (!SaveOpnd.isGPRAsmReg()) {
5402 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5403 Parser.eatToEndOfStatement();
5404 return false;
5405 }
5406 Save = SaveOpnd.getGPR32Reg();
5407 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005408
Toma Tabacu65f10572014-09-16 15:00:52 +00005409 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005410 return true;
5411
Toma Tabacu8874eac2015-02-18 13:46:53 +00005412 const MCExpr *Expr;
5413 if (Parser.parseExpression(Expr)) {
5414 reportParseError("expected expression");
5415 return false;
5416 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005417
Toma Tabacu8874eac2015-02-18 13:46:53 +00005418 if (Expr->getKind() != MCExpr::SymbolRef) {
5419 reportParseError("expected symbol");
5420 return false;
5421 }
5422 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5423
Daniel Sandersf173dda2015-09-22 10:50:09 +00005424 CpSaveLocation = Save;
5425 CpSaveLocationIsRegister = SaveIsReg;
5426
Toma Tabacu8874eac2015-02-18 13:46:53 +00005427 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5428 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005429 return false;
5430}
5431
Daniel Sandersf173dda2015-09-22 10:50:09 +00005432bool MipsAsmParser::parseDirectiveCPReturn() {
5433 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5434 CpSaveLocationIsRegister);
5435 return false;
5436}
5437
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005438bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005439 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005440 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5441 const AsmToken &Tok = Parser.getTok();
5442
5443 if (Tok.getString() == "2008") {
5444 Parser.Lex();
5445 getTargetStreamer().emitDirectiveNaN2008();
5446 return false;
5447 } else if (Tok.getString() == "legacy") {
5448 Parser.Lex();
5449 getTargetStreamer().emitDirectiveNaNLegacy();
5450 return false;
5451 }
5452 }
5453 // If we don't recognize the option passed to the .nan
5454 // directive (e.g. no option or unknown option), emit an error.
5455 reportParseError("invalid option in .nan directive");
5456 return false;
5457}
5458
Jack Carter0b744b32012-10-04 02:29:46 +00005459bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005460 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005461 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005462 const AsmToken &Tok = Parser.getTok();
5463
5464 if (Tok.getString() == "noat") {
5465 return parseSetNoAtDirective();
5466 } else if (Tok.getString() == "at") {
5467 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005468 } else if (Tok.getString() == "arch") {
5469 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005470 } else if (Tok.getString() == "fp") {
5471 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005472 } else if (Tok.getString() == "oddspreg") {
5473 return parseSetOddSPRegDirective();
5474 } else if (Tok.getString() == "nooddspreg") {
5475 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005476 } else if (Tok.getString() == "pop") {
5477 return parseSetPopDirective();
5478 } else if (Tok.getString() == "push") {
5479 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005480 } else if (Tok.getString() == "reorder") {
5481 return parseSetReorderDirective();
5482 } else if (Tok.getString() == "noreorder") {
5483 return parseSetNoReorderDirective();
5484 } else if (Tok.getString() == "macro") {
5485 return parseSetMacroDirective();
5486 } else if (Tok.getString() == "nomacro") {
5487 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005488 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005489 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005490 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005491 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005492 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005493 getTargetStreamer().emitDirectiveSetNoMicroMips();
5494 Parser.eatToEndOfStatement();
5495 return false;
5496 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005497 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005498 } else if (Tok.getString() == "mips0") {
5499 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005500 } else if (Tok.getString() == "mips1") {
5501 return parseSetFeature(Mips::FeatureMips1);
5502 } else if (Tok.getString() == "mips2") {
5503 return parseSetFeature(Mips::FeatureMips2);
5504 } else if (Tok.getString() == "mips3") {
5505 return parseSetFeature(Mips::FeatureMips3);
5506 } else if (Tok.getString() == "mips4") {
5507 return parseSetFeature(Mips::FeatureMips4);
5508 } else if (Tok.getString() == "mips5") {
5509 return parseSetFeature(Mips::FeatureMips5);
5510 } else if (Tok.getString() == "mips32") {
5511 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005512 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005513 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005514 } else if (Tok.getString() == "mips32r3") {
5515 return parseSetFeature(Mips::FeatureMips32r3);
5516 } else if (Tok.getString() == "mips32r5") {
5517 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005518 } else if (Tok.getString() == "mips32r6") {
5519 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005520 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005521 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005522 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005523 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005524 } else if (Tok.getString() == "mips64r3") {
5525 return parseSetFeature(Mips::FeatureMips64r3);
5526 } else if (Tok.getString() == "mips64r5") {
5527 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005528 } else if (Tok.getString() == "mips64r6") {
5529 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005530 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005531 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005532 } else if (Tok.getString() == "nodsp") {
5533 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005534 } else if (Tok.getString() == "msa") {
5535 return parseSetMsaDirective();
5536 } else if (Tok.getString() == "nomsa") {
5537 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005538 } else if (Tok.getString() == "softfloat") {
5539 return parseSetSoftFloatDirective();
5540 } else if (Tok.getString() == "hardfloat") {
5541 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005542 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005543 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005544 parseSetAssignment();
5545 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005546 }
Jack Carter07c818d2013-01-25 01:31:34 +00005547
Jack Carter0b744b32012-10-04 02:29:46 +00005548 return true;
5549}
5550
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005551/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005552/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005553bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005554 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005555 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5556 for (;;) {
5557 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005558 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005559 return true;
5560
5561 getParser().getStreamer().EmitValue(Value, Size);
5562
5563 if (getLexer().is(AsmToken::EndOfStatement))
5564 break;
5565
Jack Carter07c818d2013-01-25 01:31:34 +00005566 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005567 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005568 Parser.Lex();
5569 }
5570 }
5571
5572 Parser.Lex();
5573 return false;
5574}
5575
Vladimir Medic4c299852013-11-06 11:27:05 +00005576/// parseDirectiveGpWord
5577/// ::= .gpword local_sym
5578bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005579 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005580 const MCExpr *Value;
5581 // EmitGPRel32Value requires an expression, so we are using base class
5582 // method to evaluate the expression.
5583 if (getParser().parseExpression(Value))
5584 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005585 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005586
Vladimir Medice10c1122013-11-13 13:18:04 +00005587 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005588 return Error(getLexer().getLoc(),
5589 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005590 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005591 return false;
5592}
5593
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005594/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005595/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005596bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005597 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005598 const MCExpr *Value;
5599 // EmitGPRel64Value requires an expression, so we are using base class
5600 // method to evaluate the expression.
5601 if (getParser().parseExpression(Value))
5602 return true;
5603 getParser().getStreamer().EmitGPRel64Value(Value);
5604
5605 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005606 return Error(getLexer().getLoc(),
5607 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005608 Parser.Lex(); // Eat EndOfStatement token.
5609 return false;
5610}
5611
Jack Carter0cd3c192014-01-06 23:27:31 +00005612bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005613 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005614 // Get the option token.
5615 AsmToken Tok = Parser.getTok();
5616 // At the moment only identifiers are supported.
5617 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005618 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005619 Parser.eatToEndOfStatement();
5620 return false;
5621 }
5622
5623 StringRef Option = Tok.getIdentifier();
5624
5625 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005626 // MipsAsmParser needs to know if the current PIC mode changes.
5627 IsPicEnabled = false;
5628
Jack Carter0cd3c192014-01-06 23:27:31 +00005629 getTargetStreamer().emitDirectiveOptionPic0();
5630 Parser.Lex();
5631 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5632 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005633 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005634 Parser.eatToEndOfStatement();
5635 }
5636 return false;
5637 }
5638
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005639 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005640 // MipsAsmParser needs to know if the current PIC mode changes.
5641 IsPicEnabled = true;
5642
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005643 getTargetStreamer().emitDirectiveOptionPic2();
5644 Parser.Lex();
5645 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5646 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005647 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005648 Parser.eatToEndOfStatement();
5649 }
5650 return false;
5651 }
5652
Jack Carter0cd3c192014-01-06 23:27:31 +00005653 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005654 Warning(Parser.getTok().getLoc(),
5655 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005656 Parser.eatToEndOfStatement();
5657 return false;
5658}
5659
Toma Tabacu9ca50962015-04-16 09:53:47 +00005660/// parseInsnDirective
5661/// ::= .insn
5662bool MipsAsmParser::parseInsnDirective() {
5663 // If this is not the end of the statement, report an error.
5664 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5665 reportParseError("unexpected token, expected end of statement");
5666 return false;
5667 }
5668
5669 // The actual label marking happens in
5670 // MipsELFStreamer::createPendingLabelRelocs().
5671 getTargetStreamer().emitDirectiveInsn();
5672
5673 getParser().Lex(); // Eat EndOfStatement token.
5674 return false;
5675}
5676
Daniel Sanders7e527422014-07-10 13:38:23 +00005677/// parseDirectiveModule
5678/// ::= .module oddspreg
5679/// ::= .module nooddspreg
5680/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005681/// ::= .module softfloat
5682/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005683bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005684 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005685 MCAsmLexer &Lexer = getLexer();
5686 SMLoc L = Lexer.getLoc();
5687
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005688 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005689 // TODO : get a better message.
5690 reportParseError(".module directive must appear before any code");
5691 return false;
5692 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005693
Toma Tabacuc405c822015-01-23 10:40:19 +00005694 StringRef Option;
5695 if (Parser.parseIdentifier(Option)) {
5696 reportParseError("expected .module option identifier");
5697 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005698 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005699
Toma Tabacuc405c822015-01-23 10:40:19 +00005700 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005701 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005702
Toma Tabacu3c499582015-06-25 10:56:57 +00005703 // Synchronize the abiflags information with the FeatureBits information we
5704 // changed above.
5705 getTargetStreamer().updateABIInfo(*this);
5706
5707 // If printing assembly, use the recently updated abiflags information.
5708 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5709 // emitted at the end).
5710 getTargetStreamer().emitDirectiveModuleOddSPReg();
5711
Toma Tabacuc405c822015-01-23 10:40:19 +00005712 // If this is not the end of the statement, report an error.
5713 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5714 reportParseError("unexpected token, expected end of statement");
5715 return false;
5716 }
5717
5718 return false; // parseDirectiveModule has finished successfully.
5719 } else if (Option == "nooddspreg") {
5720 if (!isABI_O32()) {
5721 Error(L, "'.module nooddspreg' requires the O32 ABI");
5722 return false;
5723 }
5724
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005725 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005726
Toma Tabacu3c499582015-06-25 10:56:57 +00005727 // Synchronize the abiflags information with the FeatureBits information we
5728 // changed above.
5729 getTargetStreamer().updateABIInfo(*this);
5730
5731 // If printing assembly, use the recently updated abiflags information.
5732 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5733 // emitted at the end).
5734 getTargetStreamer().emitDirectiveModuleOddSPReg();
5735
Toma Tabacuc405c822015-01-23 10:40:19 +00005736 // If this is not the end of the statement, report an error.
5737 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5738 reportParseError("unexpected token, expected end of statement");
5739 return false;
5740 }
5741
5742 return false; // parseDirectiveModule has finished successfully.
5743 } else if (Option == "fp") {
5744 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005745 } else if (Option == "softfloat") {
5746 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5747
5748 // Synchronize the ABI Flags information with the FeatureBits information we
5749 // updated above.
5750 getTargetStreamer().updateABIInfo(*this);
5751
5752 // If printing assembly, use the recently updated ABI Flags information.
5753 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5754 // emitted later).
5755 getTargetStreamer().emitDirectiveModuleSoftFloat();
5756
5757 // If this is not the end of the statement, report an error.
5758 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5759 reportParseError("unexpected token, expected end of statement");
5760 return false;
5761 }
5762
5763 return false; // parseDirectiveModule has finished successfully.
5764 } else if (Option == "hardfloat") {
5765 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5766
5767 // Synchronize the ABI Flags information with the FeatureBits information we
5768 // updated above.
5769 getTargetStreamer().updateABIInfo(*this);
5770
5771 // If printing assembly, use the recently updated ABI Flags information.
5772 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5773 // emitted later).
5774 getTargetStreamer().emitDirectiveModuleHardFloat();
5775
5776 // If this is not the end of the statement, report an error.
5777 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5778 reportParseError("unexpected token, expected end of statement");
5779 return false;
5780 }
5781
5782 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005783 } else {
5784 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5785 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005786}
5787
5788/// parseDirectiveModuleFP
5789/// ::= =32
5790/// ::= =xx
5791/// ::= =64
5792bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005793 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005794 MCAsmLexer &Lexer = getLexer();
5795
5796 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005797 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005798 return false;
5799 }
5800 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005801
Daniel Sanders7e527422014-07-10 13:38:23 +00005802 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005803 if (!parseFpABIValue(FpABI, ".module"))
5804 return false;
5805
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005806 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005807 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005808 return false;
5809 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005810
Toma Tabacua64e5402015-06-25 12:44:38 +00005811 // Synchronize the abiflags information with the FeatureBits information we
5812 // changed above.
5813 getTargetStreamer().updateABIInfo(*this);
5814
5815 // If printing assembly, use the recently updated abiflags information.
5816 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5817 // emitted at the end).
5818 getTargetStreamer().emitDirectiveModuleFP();
5819
Daniel Sanders7e527422014-07-10 13:38:23 +00005820 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005821 return false;
5822}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005823
Daniel Sanders7e527422014-07-10 13:38:23 +00005824bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005825 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005826 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005827 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005828 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005829
5830 if (Lexer.is(AsmToken::Identifier)) {
5831 StringRef Value = Parser.getTok().getString();
5832 Parser.Lex();
5833
5834 if (Value != "xx") {
5835 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5836 return false;
5837 }
5838
5839 if (!isABI_O32()) {
5840 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5841 return false;
5842 }
5843
Daniel Sanders7e527422014-07-10 13:38:23 +00005844 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005845 if (ModuleLevelOptions) {
5846 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5847 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5848 } else {
5849 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5850 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5851 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005852 return true;
5853 }
5854
5855 if (Lexer.is(AsmToken::Integer)) {
5856 unsigned Value = Parser.getTok().getIntVal();
5857 Parser.Lex();
5858
5859 if (Value != 32 && Value != 64) {
5860 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5861 return false;
5862 }
5863
5864 if (Value == 32) {
5865 if (!isABI_O32()) {
5866 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5867 return false;
5868 }
5869
Daniel Sanders7e527422014-07-10 13:38:23 +00005870 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005871 if (ModuleLevelOptions) {
5872 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5873 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5874 } else {
5875 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5876 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5877 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005878 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005879 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005880 if (ModuleLevelOptions) {
5881 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5882 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5883 } else {
5884 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5885 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5886 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005887 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005888
Daniel Sanders7e527422014-07-10 13:38:23 +00005889 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005890 }
5891
5892 return false;
5893}
5894
Jack Carter0b744b32012-10-04 02:29:46 +00005895bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005896 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005897 StringRef IDVal = DirectiveID.getString();
5898
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005899 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005900 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005901 if (IDVal == ".cprestore")
5902 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005903 if (IDVal == ".dword") {
5904 parseDataDirective(8, DirectiveID.getLoc());
5905 return false;
5906 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005907 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005908 StringRef SymbolName;
5909
5910 if (Parser.parseIdentifier(SymbolName)) {
5911 reportParseError("expected identifier after .ent");
5912 return false;
5913 }
5914
5915 // There's an undocumented extension that allows an integer to
5916 // follow the name of the procedure which AFAICS is ignored by GAS.
5917 // Example: .ent foo,2
5918 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5919 if (getLexer().isNot(AsmToken::Comma)) {
5920 // Even though we accept this undocumented extension for compatibility
5921 // reasons, the additional integer argument does not actually change
5922 // the behaviour of the '.ent' directive, so we would like to discourage
5923 // its use. We do this by not referring to the extended version in
5924 // error messages which are not directly related to its use.
5925 reportParseError("unexpected token, expected end of statement");
5926 return false;
5927 }
5928 Parser.Lex(); // Eat the comma.
5929 const MCExpr *DummyNumber;
5930 int64_t DummyNumberVal;
5931 // If the user was explicitly trying to use the extended version,
5932 // we still give helpful extension-related error messages.
5933 if (Parser.parseExpression(DummyNumber)) {
5934 reportParseError("expected number after comma");
5935 return false;
5936 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005937 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005938 reportParseError("expected an absolute expression after comma");
5939 return false;
5940 }
5941 }
5942
5943 // If this is not the end of the statement, report an error.
5944 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5945 reportParseError("unexpected token, expected end of statement");
5946 return false;
5947 }
5948
Jim Grosbach6f482002015-05-18 18:43:14 +00005949 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005950
5951 getTargetStreamer().emitDirectiveEnt(*Sym);
5952 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005953 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005954 return false;
5955 }
5956
Jack Carter07c818d2013-01-25 01:31:34 +00005957 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005958 StringRef SymbolName;
5959
5960 if (Parser.parseIdentifier(SymbolName)) {
5961 reportParseError("expected identifier after .end");
5962 return false;
5963 }
5964
5965 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5966 reportParseError("unexpected token, expected end of statement");
5967 return false;
5968 }
5969
5970 if (CurrentFn == nullptr) {
5971 reportParseError(".end used without .ent");
5972 return false;
5973 }
5974
5975 if ((SymbolName != CurrentFn->getName())) {
5976 reportParseError(".end symbol does not match .ent symbol");
5977 return false;
5978 }
5979
5980 getTargetStreamer().emitDirectiveEnd(SymbolName);
5981 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005982 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005983 return false;
5984 }
5985
Jack Carter07c818d2013-01-25 01:31:34 +00005986 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005987 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5988 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005989 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005990 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5991 reportParseError("expected stack register");
5992 return false;
5993 }
5994
5995 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5996 if (!StackRegOpnd.isGPRAsmReg()) {
5997 reportParseError(StackRegOpnd.getStartLoc(),
5998 "expected general purpose register");
5999 return false;
6000 }
6001 unsigned StackReg = StackRegOpnd.getGPR32Reg();
6002
6003 if (Parser.getTok().is(AsmToken::Comma))
6004 Parser.Lex();
6005 else {
6006 reportParseError("unexpected token, expected comma");
6007 return false;
6008 }
6009
6010 // Parse the frame size.
6011 const MCExpr *FrameSize;
6012 int64_t FrameSizeVal;
6013
6014 if (Parser.parseExpression(FrameSize)) {
6015 reportParseError("expected frame size value");
6016 return false;
6017 }
6018
Jim Grosbach13760bd2015-05-30 01:25:56 +00006019 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006020 reportParseError("frame size not an absolute expression");
6021 return false;
6022 }
6023
6024 if (Parser.getTok().is(AsmToken::Comma))
6025 Parser.Lex();
6026 else {
6027 reportParseError("unexpected token, expected comma");
6028 return false;
6029 }
6030
6031 // Parse the return register.
6032 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00006033 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00006034 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
6035 reportParseError("expected return register");
6036 return false;
6037 }
6038
6039 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
6040 if (!ReturnRegOpnd.isGPRAsmReg()) {
6041 reportParseError(ReturnRegOpnd.getStartLoc(),
6042 "expected general purpose register");
6043 return false;
6044 }
6045
6046 // If this is not the end of the statement, report an error.
6047 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6048 reportParseError("unexpected token, expected end of statement");
6049 return false;
6050 }
6051
6052 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
6053 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00006054 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00006055 return false;
6056 }
6057
Jack Carter07c818d2013-01-25 01:31:34 +00006058 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00006059 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00006060 }
6061
Daniel Sandersd97a6342014-08-13 10:07:34 +00006062 if (IDVal == ".mask" || IDVal == ".fmask") {
6063 // .mask bitmask, frame_offset
6064 // bitmask: One bit for each register used.
6065 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
6066 // first register is expected to be saved.
6067 // Examples:
6068 // .mask 0x80000000, -4
6069 // .fmask 0x80000000, -4
6070 //
Jack Carterbe332172012-09-07 00:48:02 +00006071
Daniel Sandersd97a6342014-08-13 10:07:34 +00006072 // Parse the bitmask
6073 const MCExpr *BitMask;
6074 int64_t BitMaskVal;
6075
6076 if (Parser.parseExpression(BitMask)) {
6077 reportParseError("expected bitmask value");
6078 return false;
6079 }
6080
Jim Grosbach13760bd2015-05-30 01:25:56 +00006081 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006082 reportParseError("bitmask not an absolute expression");
6083 return false;
6084 }
6085
6086 if (Parser.getTok().is(AsmToken::Comma))
6087 Parser.Lex();
6088 else {
6089 reportParseError("unexpected token, expected comma");
6090 return false;
6091 }
6092
6093 // Parse the frame_offset
6094 const MCExpr *FrameOffset;
6095 int64_t FrameOffsetVal;
6096
6097 if (Parser.parseExpression(FrameOffset)) {
6098 reportParseError("expected frame offset value");
6099 return false;
6100 }
6101
Jim Grosbach13760bd2015-05-30 01:25:56 +00006102 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00006103 reportParseError("frame offset not an absolute expression");
6104 return false;
6105 }
6106
6107 // If this is not the end of the statement, report an error.
6108 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6109 reportParseError("unexpected token, expected end of statement");
6110 return false;
6111 }
6112
6113 if (IDVal == ".mask")
6114 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
6115 else
6116 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00006117 return false;
6118 }
6119
Matheus Almeida0051f2d2014-04-16 15:48:55 +00006120 if (IDVal == ".nan")
6121 return parseDirectiveNaN();
6122
Jack Carter07c818d2013-01-25 01:31:34 +00006123 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00006124 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00006125 return false;
6126 }
6127
Rafael Espindolab59fb732014-03-28 18:50:26 +00006128 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00006129 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00006130 return false;
6131 }
6132
Jack Carter07c818d2013-01-25 01:31:34 +00006133 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00006134 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00006135 return false;
6136 }
6137
Jack Carter0cd3c192014-01-06 23:27:31 +00006138 if (IDVal == ".option")
6139 return parseDirectiveOption();
6140
6141 if (IDVal == ".abicalls") {
6142 getTargetStreamer().emitDirectiveAbiCalls();
6143 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00006144 Error(Parser.getTok().getLoc(),
6145 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00006146 // Clear line
6147 Parser.eatToEndOfStatement();
6148 }
6149 return false;
6150 }
6151
Daniel Sanders5bce5f62014-03-27 13:52:53 +00006152 if (IDVal == ".cpsetup")
6153 return parseDirectiveCPSetup();
6154
Daniel Sandersf173dda2015-09-22 10:50:09 +00006155 if (IDVal == ".cpreturn")
6156 return parseDirectiveCPReturn();
6157
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00006158 if (IDVal == ".module")
6159 return parseDirectiveModule();
6160
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006161 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
6162 return parseInternalDirectiveReallowModule();
6163
Toma Tabacu9ca50962015-04-16 09:53:47 +00006164 if (IDVal == ".insn")
6165 return parseInsnDirective();
6166
Rafael Espindola870c4e92012-01-11 03:56:41 +00006167 return true;
6168}
6169
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00006170bool MipsAsmParser::parseInternalDirectiveReallowModule() {
6171 // If this is not the end of the statement, report an error.
6172 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6173 reportParseError("unexpected token, expected end of statement");
6174 return false;
6175 }
6176
6177 getTargetStreamer().reallowModuleDirective();
6178
6179 getParser().Lex(); // Eat EndOfStatement token.
6180 return false;
6181}
6182
Rafael Espindola870c4e92012-01-11 03:56:41 +00006183extern "C" void LLVMInitializeMipsAsmParser() {
6184 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
6185 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
6186 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
6187 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
6188}
Jack Carterb4dbc172012-09-05 23:34:03 +00006189
6190#define GET_REGISTER_MATCHER
6191#define GET_MATCHER_IMPLEMENTATION
6192#include "MipsGenAsmMatcher.inc"