blob: aaffbcffaaedf2372be93596580c534bd2859eab [file] [log] [blame]
Jaydeep Patil135f5db2016-08-29 05:14:05 -07001//===- subzero/src/IceInstMIPS32.h - MIPS32 machine instrs --*- C++ -*-----===//
Jim Stichnoth6da4cef2015-06-11 13:26:33 -07002//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Declares the InstMIPS32 and OperandMIPS32 classes and their
12/// subclasses.
13///
14/// This represents the machine instructions and operands used for MIPS32 code
15/// selection.
Andrew Scull9612d322015-07-06 14:53:25 -070016///
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070017//===----------------------------------------------------------------------===//
18
19#ifndef SUBZERO_SRC_ICEINSTMIPS32_H
20#define SUBZERO_SRC_ICEINSTMIPS32_H
21
Sagar Thakur5cce7612016-05-24 06:25:50 -070022#include "IceConditionCodesMIPS32.h"
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070023#include "IceDefs.h"
Reed Kotlerd00d48d2015-07-08 09:49:07 -070024#include "IceInst.h"
25#include "IceInstMIPS32.def"
26#include "IceOperand.h"
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070027
28namespace Ice {
John Porto4a566862016-01-04 09:33:41 -080029namespace MIPS32 {
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070030
Jaydeep Patil130aca72016-10-28 05:30:54 -070031enum RelocOp { RO_No, RO_Hi, RO_Lo, RO_Jal };
Jaydeep Patil2bbda7f2017-01-10 21:48:58 -080032enum Int64Part { Int64_Hi, Int64_Lo };
Mohit Bhakkadd1e97772016-07-07 05:07:35 -070033
34inline void emitRelocOp(Ostream &Str, RelocOp Reloc) {
35 switch (Reloc) {
Jaydeep Patil130aca72016-10-28 05:30:54 -070036 default:
Mohit Bhakkadd1e97772016-07-07 05:07:35 -070037 break;
38 case RO_Hi:
39 Str << "%hi";
40 break;
41 case RO_Lo:
42 Str << "%lo";
43 break;
44 }
45}
46
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070047class TargetMIPS32;
Reed Kotlerd00d48d2015-07-08 09:49:07 -070048
Jim Stichnothac8da5c2015-10-21 06:57:46 -070049/// OperandMips32 extends the Operand hierarchy.
50//
51class OperandMIPS32 : public Operand {
52 OperandMIPS32() = delete;
53 OperandMIPS32(const OperandMIPS32 &) = delete;
54 OperandMIPS32 &operator=(const OperandMIPS32 &) = delete;
55
56public:
57 enum OperandKindMIPS32 {
58 k__Start = Operand::kTarget,
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -070059 kFCC,
Jim Stichnothac8da5c2015-10-21 06:57:46 -070060 kMem,
61 };
62
63 using Operand::dump;
64 void dump(const Cfg *, Ostream &Str) const override {
65 if (BuildDefs::dump())
66 Str << "<OperandMIPS32>";
67 }
Karl Schimpf2fee2a22015-10-22 08:19:26 -070068
Jim Stichnothac8da5c2015-10-21 06:57:46 -070069protected:
70 OperandMIPS32(OperandKindMIPS32 Kind, Type Ty)
71 : Operand(static_cast<OperandKind>(Kind), Ty) {}
72};
73
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -070074class OperandMIPS32FCC : public OperandMIPS32 {
75 OperandMIPS32FCC() = delete;
76 OperandMIPS32FCC(const OperandMIPS32FCC &) = delete;
77 OperandMIPS32FCC &operator=(const OperandMIPS32FCC &) = delete;
78
79public:
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -070080 using FCC = enum { FCC0 = 0, FCC1, FCC2, FCC3, FCC4, FCC5, FCC6, FCC7 };
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -070081 static OperandMIPS32FCC *create(Cfg *Func, OperandMIPS32FCC::FCC FCC) {
82 return new (Func->allocate<OperandMIPS32FCC>()) OperandMIPS32FCC(FCC);
83 }
84
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -070085 OperandMIPS32FCC::FCC getFCC() const { return FpCondCode; }
86
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -070087 void emit(const Cfg *Func) const override {
88 if (!BuildDefs::dump())
89 return;
90 Ostream &Str = Func->getContext()->getStrEmit();
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -070091 Str << "$fcc" << static_cast<uint16_t>(FpCondCode);
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -070092 }
93
94 static bool classof(const Operand *Operand) {
95 return Operand->getKind() == static_cast<OperandKind>(kFCC);
96 }
97
98 void dump(const Cfg *Func, Ostream &Str) const override {
Jaydeep Patild8954472016-09-21 06:24:41 -070099 if (!BuildDefs::dump())
100 return;
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700101 (void)Func;
Jaydeep Patild8954472016-09-21 06:24:41 -0700102 Str << "$fcc" << static_cast<uint16_t>(FpCondCode);
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700103 }
104
105private:
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -0700106 OperandMIPS32FCC(OperandMIPS32FCC::FCC CC)
107 : OperandMIPS32(kFCC, IceType_i32), FpCondCode(CC){};
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700108
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -0700109 const OperandMIPS32FCC::FCC FpCondCode;
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700110};
111
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700112class OperandMIPS32Mem : public OperandMIPS32 {
113 OperandMIPS32Mem() = delete;
114 OperandMIPS32Mem(const OperandMIPS32Mem &) = delete;
115 OperandMIPS32Mem &operator=(const OperandMIPS32Mem &) = delete;
116
117public:
118 /// Memory operand addressing mode.
119 /// The enum value also carries the encoding.
120 // TODO(jvoung): unify with the assembler.
121 enum AddrMode { Offset };
122
123 /// NOTE: The Variable-typed operands have to be registers.
124 ///
125 /// Reg + Imm. The Immediate actually has a limited number of bits
126 /// for encoding, so check canHoldOffset first. It cannot handle
127 /// general Constant operands like ConstantRelocatable, since a relocatable
128 /// can potentially take up too many bits.
129 static OperandMIPS32Mem *create(Cfg *Func, Type Ty, Variable *Base,
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700130 Operand *ImmOffset, AddrMode Mode = Offset) {
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700131 return new (Func->allocate<OperandMIPS32Mem>())
132 OperandMIPS32Mem(Func, Ty, Base, ImmOffset, Mode);
133 }
134
135 Variable *getBase() const { return Base; }
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700136 Operand *getOffset() const { return ImmOffset; }
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700137 AddrMode getAddrMode() const { return Mode; }
138
139 void emit(const Cfg *Func) const override;
140 using OperandMIPS32::dump;
141
142 static bool classof(const Operand *Operand) {
143 return Operand->getKind() == static_cast<OperandKind>(kMem);
144 }
145
146 /// Return true if a load/store instruction for an element of type Ty
147 /// can encode the Offset directly in the immediate field of the 32-bit
148 /// MIPS instruction. For some types, if the load is Sign extending, then
149 /// the range is reduced.
150 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset);
151
152 void dump(const Cfg *Func, Ostream &Str) const override {
Jaydeep Patil1d0690b2016-09-04 07:19:08 -0700153 if (!BuildDefs::dump())
154 return;
155 Str << "[";
156 if (Func)
157 getBase()->dump(Func);
158 else
159 getBase()->dump(Str);
160 Str << ", ";
161 getOffset()->dump(Func, Str);
162 Str << "] AddrMode==";
163 if (getAddrMode() == Offset) {
164 Str << "Offset";
165 } else {
166 Str << "Unknown";
167 }
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700168 }
169
170private:
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700171 OperandMIPS32Mem(Cfg *Func, Type Ty, Variable *Base, Operand *ImmOffset,
172 AddrMode Mode);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700173
174 Variable *Base;
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700175 Operand *const ImmOffset;
176 const AddrMode Mode;
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700177};
178
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700179/// Base class for Mips instructions.
180class InstMIPS32 : public InstTarget {
181 InstMIPS32() = delete;
182 InstMIPS32(const InstMIPS32 &) = delete;
183 InstMIPS32 &operator=(const InstMIPS32 &) = delete;
184
185public:
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700186 enum InstKindMIPS32 {
187 k__Start = Inst::Target,
Srdjan Obucina53d05682016-09-10 08:25:37 -0700188 Abs_d,
189 Abs_s,
Reed Kotler37af5b02015-11-05 17:07:19 -0800190 Add,
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700191 Add_d,
192 Add_s,
Jaydeep Patil130aca72016-10-28 05:30:54 -0700193 Addi,
Sagar Thakur1a478b12016-04-25 08:39:19 -0700194 Addiu,
Reed Kotler00e36042016-02-01 20:52:19 -0800195 Addu,
Reed Kotler37af5b02015-11-05 17:07:19 -0800196 And,
Sagar Thakur38dcb592016-05-09 11:57:59 -0700197 Andi,
Reed Kotler3fe4b572016-02-23 18:59:43 -0800198 Br,
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700199 C_eq_d,
200 C_eq_s,
201 C_ole_d,
202 C_ole_s,
203 C_olt_d,
204 C_olt_s,
205 C_ueq_d,
206 C_ueq_s,
207 C_ule_d,
208 C_ule_s,
209 C_ult_d,
210 C_ult_s,
211 C_un_d,
212 C_un_s,
Reed Kotler00e36042016-02-01 20:52:19 -0800213 Call,
Srdjan Obucinad27ce3d2016-09-22 12:56:12 -0700214 Clz,
Srdjan Obucina418135a2016-06-02 06:47:06 -0700215 Cvt_d_l,
216 Cvt_d_s,
217 Cvt_d_w,
218 Cvt_s_d,
219 Cvt_s_l,
220 Cvt_s_w,
Srdjan Obucinaae93eee2016-05-18 11:31:15 -0700221 Div,
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700222 Div_d,
223 Div_s,
Srdjan Obucinaae93eee2016-05-18 11:31:15 -0700224 Divu,
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700225 La,
Reed Kotler3fe4b572016-02-23 18:59:43 -0800226 Label,
Srdjan Obucina418135a2016-06-02 06:47:06 -0700227 Ldc1,
Sagar Thakurbecb85f2016-11-18 12:15:46 -0800228 Ll,
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700229 Lui,
Srdjan Obucina418135a2016-06-02 06:47:06 -0700230 Lw,
231 Lwc1,
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700232 Mfc1,
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800233 Mfhi,
234 Mflo,
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700235 Mov, // actually a pseudo op for addi rd, rs, 0
Jaydeep Patil2bbda7f2017-01-10 21:48:58 -0800236 Mov_fp,
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700237 Mov_d,
238 Mov_s,
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700239 Movf,
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700240 Movn,
241 Movn_d,
242 Movn_s,
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700243 Movt,
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700244 Movz,
245 Movz_d,
246 Movz_s,
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700247 Mtc1,
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800248 Mthi,
249 Mtlo,
Reed Kotler37af5b02015-11-05 17:07:19 -0800250 Mul,
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700251 Mul_d,
252 Mul_s,
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800253 Mult,
254 Multu,
Srdjan Obucinacadda792016-09-22 11:24:44 -0700255 Nor,
Reed Kotler37af5b02015-11-05 17:07:19 -0800256 Or,
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700257 Ori,
Reed Kotler37af5b02015-11-05 17:07:19 -0800258 Ret,
Sagar Thakurbecb85f2016-11-18 12:15:46 -0800259 Sc,
Srdjan Obucina418135a2016-06-02 06:47:06 -0700260 Sdc1,
Sagar Thakur38dcb592016-05-09 11:57:59 -0700261 Sll,
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -0700262 Sllv,
Sagar Thakur1a478b12016-04-25 08:39:19 -0700263 Slt,
264 Slti,
265 Sltiu,
266 Sltu,
Sagar Thakur38dcb592016-05-09 11:57:59 -0700267 Sra,
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -0700268 Srav,
269 Srl,
270 Srlv,
Srdjan Obucina53d05682016-09-10 08:25:37 -0700271 Sqrt_d,
272 Sqrt_s,
Reed Kotler37af5b02015-11-05 17:07:19 -0800273 Sub,
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700274 Sub_d,
275 Sub_s,
Reed Kotler00e36042016-02-01 20:52:19 -0800276 Subu,
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700277 Sw,
Srdjan Obucina418135a2016-06-02 06:47:06 -0700278 Swc1,
Sagar Thakurbecb85f2016-11-18 12:15:46 -0800279 Sync,
Jaydeep Patilcc6dea72016-09-19 16:48:34 -0700280 Teq,
Srdjan Obucina418135a2016-06-02 06:47:06 -0700281 Trunc_l_d,
282 Trunc_l_s,
283 Trunc_w_d,
284 Trunc_w_s,
Sagar Thakur1a478b12016-04-25 08:39:19 -0700285 Xor,
286 Xori
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700287 };
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700288
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700289 static constexpr size_t InstSize = sizeof(uint32_t);
290
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700291 static const char *getWidthString(Type Ty);
292
Jaydeep Patil13f0ca32016-08-26 13:27:40 -0700293 CondMIPS32::Cond getOppositeCondition(CondMIPS32::Cond Cond);
294
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700295 void dump(const Cfg *Func) const override;
296
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700297 void dumpOpcode(Ostream &Str, const char *Opcode, Type Ty) const {
298 Str << Opcode << "." << Ty;
299 }
300
Reed Kotler00e36042016-02-01 20:52:19 -0800301 // TODO(rkotler): while branching is not implemented
302 bool repointEdges(CfgNode *, CfgNode *) override { return true; }
303
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700304 /// Shared emit routines for common forms of instructions.
305 static void emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst,
306 const Cfg *Func);
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800307 static void emitUnaryopGPRFLoHi(const char *Opcode, const InstMIPS32 *Inst,
308 const Cfg *Func);
309 static void emitUnaryopGPRTLoHi(const char *Opcode, const InstMIPS32 *Inst,
310 const Cfg *Func);
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700311 static void emitTwoAddr(const char *Opcode, const InstMIPS32 *Inst,
312 const Cfg *Func);
Reed Kotler37af5b02015-11-05 17:07:19 -0800313 static void emitThreeAddr(const char *Opcode, const InstMIPS32 *Inst,
314 const Cfg *Func);
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800315 static void emitThreeAddrLoHi(const char *Opcode, const InstMIPS32 *Inst,
316 const Cfg *Func);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700317
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700318protected:
319 InstMIPS32(Cfg *Func, InstKindMIPS32 Kind, SizeT Maxsrcs, Variable *Dest)
320 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700321 static bool isClassof(const Inst *Inst, InstKindMIPS32 MyKind) {
322 return Inst->getKind() == static_cast<InstKind>(MyKind);
323 }
324};
325
Andrew Scull57e12682015-09-16 11:30:19 -0700326/// Ret pseudo-instruction. This is actually a "jr" instruction with an "ra"
327/// register operand, but epilogue lowering will search for a Ret instead of a
328/// generic "jr". This instruction also takes a Source operand (for non-void
329/// returning functions) for liveness analysis, though a FakeUse before the ret
330/// would do just as well.
331// TODO(reed kotler): This needs was take from the ARM port and needs to be
332// scrubbed in the future.
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700333class InstMIPS32Ret : public InstMIPS32 {
334
335 InstMIPS32Ret() = delete;
336 InstMIPS32Ret(const InstMIPS32Ret &) = delete;
337 InstMIPS32Ret &operator=(const InstMIPS32Ret &) = delete;
338
339public:
340 static InstMIPS32Ret *create(Cfg *Func, Variable *RA,
341 Variable *Source = nullptr) {
342 return new (Func->allocate<InstMIPS32Ret>())
343 InstMIPS32Ret(Func, RA, Source);
344 }
345 void emit(const Cfg *Func) const override;
346 void emitIAS(const Cfg *Func) const override;
347 void dump(const Cfg *Func) const override;
348 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); }
349
350private:
351 InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source);
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700352};
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700353
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700354/// Instructions of the form x := op(y).
355template <InstMIPS32::InstKindMIPS32 K>
356class InstMIPS32UnaryopGPR : public InstMIPS32 {
357 InstMIPS32UnaryopGPR() = delete;
358 InstMIPS32UnaryopGPR(const InstMIPS32UnaryopGPR &) = delete;
359 InstMIPS32UnaryopGPR &operator=(const InstMIPS32UnaryopGPR &) = delete;
360
361public:
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700362 static InstMIPS32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
363 RelocOp Reloc = RO_No) {
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700364 return new (Func->allocate<InstMIPS32UnaryopGPR>())
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700365 InstMIPS32UnaryopGPR(Func, Dest, Src, Reloc);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700366 }
367 void emit(const Cfg *Func) const override {
368 if (!BuildDefs::dump())
369 return;
370 emitUnaryopGPR(Opcode, this, Func);
371 }
372 void emitIAS(const Cfg *Func) const override {
373 (void)Func;
374 llvm_unreachable("Not yet implemented");
375 }
376 void dump(const Cfg *Func) const override {
377 if (!BuildDefs::dump())
378 return;
379 Ostream &Str = Func->getContext()->getStrDump();
380 dumpOpcode(Str, Opcode, getDest()->getType());
381 Str << " ";
382 dumpDest(Func);
383 Str << ", ";
384 dumpSources(Func);
385 }
386 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
387
388protected:
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700389 InstMIPS32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src,
390 RelocOp Reloc = RO_No)
391 : InstMIPS32(Func, K, 1, Dest), Reloc(Reloc) {
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700392 addSource(Src);
393 }
394
395private:
396 static const char *Opcode;
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700397 const RelocOp Reloc;
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700398};
399
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700400/// Instructions of the form opcode reg, reg.
401template <InstMIPS32::InstKindMIPS32 K>
402class InstMIPS32TwoAddrFPR : public InstMIPS32 {
403 InstMIPS32TwoAddrFPR() = delete;
404 InstMIPS32TwoAddrFPR(const InstMIPS32TwoAddrFPR &) = delete;
405 InstMIPS32TwoAddrFPR &operator=(const InstMIPS32TwoAddrFPR &) = delete;
406
407public:
408 static InstMIPS32TwoAddrFPR *create(Cfg *Func, Variable *Dest,
409 Variable *Src0) {
410 return new (Func->allocate<InstMIPS32TwoAddrFPR>())
411 InstMIPS32TwoAddrFPR(Func, Dest, Src0);
412 }
413 void emit(const Cfg *Func) const override {
414 if (!BuildDefs::dump())
415 return;
416 emitTwoAddr(Opcode, this, Func);
417 }
418 void emitIAS(const Cfg *Func) const override {
419 (void)Func;
420 llvm_unreachable("Not yet implemented");
421 }
422
423 void dump(const Cfg *Func) const override {
424 if (!BuildDefs::dump())
425 return;
426 Ostream &Str = Func->getContext()->getStrDump();
427 dumpDest(Func);
428 Str << " = ";
429 dumpOpcode(Str, Opcode, getDest()->getType());
430 Str << " ";
431 dumpSources(Func);
432 }
433 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
434
435private:
436 InstMIPS32TwoAddrFPR(Cfg *Func, Variable *Dest, Variable *Src0)
437 : InstMIPS32(Func, K, 1, Dest) {
438 addSource(Src0);
439 }
440
441 static const char *Opcode;
442};
443
444/// Instructions of the form opcode reg, reg.
445template <InstMIPS32::InstKindMIPS32 K>
446class InstMIPS32TwoAddrGPR : public InstMIPS32 {
447 InstMIPS32TwoAddrGPR() = delete;
448 InstMIPS32TwoAddrGPR(const InstMIPS32TwoAddrGPR &) = delete;
449 InstMIPS32TwoAddrGPR &operator=(const InstMIPS32TwoAddrGPR &) = delete;
450
451public:
452 static InstMIPS32TwoAddrGPR *create(Cfg *Func, Variable *Dest,
453 Variable *Src0) {
454 return new (Func->allocate<InstMIPS32TwoAddrGPR>())
455 InstMIPS32TwoAddrGPR(Func, Dest, Src0);
456 }
457 void emit(const Cfg *Func) const override {
458 if (!BuildDefs::dump())
459 return;
460 emitTwoAddr(Opcode, this, Func);
461 }
462 void emitIAS(const Cfg *Func) const override {
463 (void)Func;
464 llvm_unreachable("Not yet implemented");
465 }
466
467 void dump(const Cfg *Func) const override {
468 if (!BuildDefs::dump())
469 return;
470 Ostream &Str = Func->getContext()->getStrDump();
471 dumpDest(Func);
472 Str << " = ";
473 dumpOpcode(Str, Opcode, getDest()->getType());
474 Str << " ";
475 dumpSources(Func);
476 }
477 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
478
479private:
480 InstMIPS32TwoAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0)
481 : InstMIPS32(Func, K, 1, Dest) {
482 addSource(Src0);
483 }
484
485 static const char *Opcode;
486};
487
488/// Instructions of the form x := y op z. May have the side-effect of setting
489/// status flags.
490template <InstMIPS32::InstKindMIPS32 K>
491class InstMIPS32ThreeAddrFPR : public InstMIPS32 {
492 InstMIPS32ThreeAddrFPR() = delete;
493 InstMIPS32ThreeAddrFPR(const InstMIPS32ThreeAddrFPR &) = delete;
494 InstMIPS32ThreeAddrFPR &operator=(const InstMIPS32ThreeAddrFPR &) = delete;
495
496public:
497 /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
498 /// must be registers.
499 static InstMIPS32ThreeAddrFPR *create(Cfg *Func, Variable *Dest,
500 Variable *Src0, Variable *Src1) {
501 return new (Func->allocate<InstMIPS32ThreeAddrFPR>())
502 InstMIPS32ThreeAddrFPR(Func, Dest, Src0, Src1);
503 }
504 void emit(const Cfg *Func) const override {
505 if (!BuildDefs::dump())
506 return;
507 emitThreeAddr(Opcode, this, Func);
508 }
509 void emitIAS(const Cfg *Func) const override {
510 (void)Func;
511 llvm_unreachable("Not yet implemented");
512 }
513
514 void dump(const Cfg *Func) const override {
515 if (!BuildDefs::dump())
516 return;
517 Ostream &Str = Func->getContext()->getStrDump();
518 dumpDest(Func);
519 Str << " = ";
520 dumpOpcode(Str, Opcode, getDest()->getType());
521 Str << " ";
522 dumpSources(Func);
523 }
524 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
525
526private:
527 InstMIPS32ThreeAddrFPR(Cfg *Func, Variable *Dest, Variable *Src0,
528 Variable *Src1)
529 : InstMIPS32(Func, K, 2, Dest) {
530 addSource(Src0);
531 addSource(Src1);
532 }
533
534 static const char *Opcode;
535};
536
Reed Kotler37af5b02015-11-05 17:07:19 -0800537/// Instructions of the form x := y op z. May have the side-effect of setting
538/// status flags.
539template <InstMIPS32::InstKindMIPS32 K>
540class InstMIPS32ThreeAddrGPR : public InstMIPS32 {
541 InstMIPS32ThreeAddrGPR() = delete;
542 InstMIPS32ThreeAddrGPR(const InstMIPS32ThreeAddrGPR &) = delete;
543 InstMIPS32ThreeAddrGPR &operator=(const InstMIPS32ThreeAddrGPR &) = delete;
544
545public:
546 /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
547 /// must be registers.
548 static InstMIPS32ThreeAddrGPR *create(Cfg *Func, Variable *Dest,
549 Variable *Src0, Variable *Src1) {
550 return new (Func->allocate<InstMIPS32ThreeAddrGPR>())
551 InstMIPS32ThreeAddrGPR(Func, Dest, Src0, Src1);
552 }
553 void emit(const Cfg *Func) const override {
554 if (!BuildDefs::dump())
555 return;
556 emitThreeAddr(Opcode, this, Func);
557 }
558 void emitIAS(const Cfg *Func) const override {
559 (void)Func;
560 llvm_unreachable("Not yet implemented");
561 }
562
563 void dump(const Cfg *Func) const override {
564 if (!BuildDefs::dump())
565 return;
566 Ostream &Str = Func->getContext()->getStrDump();
567 dumpDest(Func);
568 Str << " = ";
569 dumpOpcode(Str, Opcode, getDest()->getType());
570 Str << " ";
571 dumpSources(Func);
572 }
573 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
574
575private:
576 InstMIPS32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
577 Variable *Src1)
578 : InstMIPS32(Func, K, 2, Dest) {
579 addSource(Src0);
580 addSource(Src1);
581 }
582
583 static const char *Opcode;
584};
585
Jaydeep Patilb1a0fb12016-08-18 22:37:30 -0700586// InstMIPS32Load represents instructions which loads data from memory
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700587// Its format is "OPCODE GPR, OFFSET(BASE GPR)"
588template <InstMIPS32::InstKindMIPS32 K>
Jaydeep Patilb1a0fb12016-08-18 22:37:30 -0700589class InstMIPS32Load : public InstMIPS32 {
590 InstMIPS32Load() = delete;
591 InstMIPS32Load(const InstMIPS32Load &) = delete;
592 InstMIPS32Load &operator=(const InstMIPS32Load &) = delete;
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700593
594public:
Jaydeep Patilb1a0fb12016-08-18 22:37:30 -0700595 static InstMIPS32Load *create(Cfg *Func, Variable *Value,
Jaydeep Patil8b322412016-08-18 22:43:43 -0700596 OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) {
Jaydeep Patilb1a0fb12016-08-18 22:37:30 -0700597 return new (Func->allocate<InstMIPS32Load>())
598 InstMIPS32Load(Func, Value, Mem, Reloc);
599 }
600
601 void emit(const Cfg *Func) const override {
602 if (!BuildDefs::dump())
603 return;
604 Ostream &Str = Func->getContext()->getStrEmit();
Jaydeep Patil1d0690b2016-09-04 07:19:08 -0700605 const Type Ty = getDest()->getType();
Sagar Thakurbecb85f2016-11-18 12:15:46 -0800606
607 if (getKind() == static_cast<InstKind>(Ll)) {
608 Str << "\t" << Opcode << "\t";
609 } else {
610 switch (Ty) {
611 case IceType_i1:
612 case IceType_i8:
613 Str << "\t"
614 "lb"
615 "\t";
616 break;
617 case IceType_i16:
618 Str << "\t"
619 "lh"
620 "\t";
621 break;
622 case IceType_i32:
623 Str << "\t"
624 "lw"
625 "\t";
626 break;
627 case IceType_f32:
628 Str << "\t"
629 "lwc1"
630 "\t";
631 break;
632 case IceType_f64:
633 Str << "\t"
634 "ldc1"
635 "\t";
636 break;
637 default:
638 llvm_unreachable("InstMIPS32Load unknown type");
639 }
Jaydeep Patil1d0690b2016-09-04 07:19:08 -0700640 }
Jaydeep Patilb1a0fb12016-08-18 22:37:30 -0700641 getDest()->emit(Func);
642 Str << ", ";
643 emitRelocOp(Str, Reloc);
644 getSrc(0)->emit(Func);
645 }
646
647 void emitIAS(const Cfg *Func) const override {
648 (void)Func;
649 llvm_unreachable("Not yet implemented");
650 }
651
652 void dump(const Cfg *Func) const override {
653 if (!BuildDefs::dump())
654 return;
655 Ostream &Str = Func->getContext()->getStrDump();
Jaydeep Patil1d0690b2016-09-04 07:19:08 -0700656 dumpOpcode(Str, Opcode, getDest()->getType());
657 Str << " ";
Jaydeep Patilb1a0fb12016-08-18 22:37:30 -0700658 getDest()->dump(Func);
659 Str << ", ";
660 emitRelocOp(Str, Reloc);
Jaydeep Patilb1a0fb12016-08-18 22:37:30 -0700661 getSrc(0)->dump(Func);
Jaydeep Patilb1a0fb12016-08-18 22:37:30 -0700662 }
663 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
664
665private:
666 InstMIPS32Load(Cfg *Func, Variable *Value, OperandMIPS32Mem *Mem,
Jaydeep Patil8b322412016-08-18 22:43:43 -0700667 RelocOp Reloc = RO_No)
Jaydeep Patilb1a0fb12016-08-18 22:37:30 -0700668 : InstMIPS32(Func, K, 2, Value), Reloc(Reloc) {
669 addSource(Mem);
670 }
671 static const char *Opcode;
672 const RelocOp Reloc;
673};
674
675// InstMIPS32Store represents instructions which stores data to memory
676// Its format is "OPCODE GPR, OFFSET(BASE GPR)"
677template <InstMIPS32::InstKindMIPS32 K>
678class InstMIPS32Store : public InstMIPS32 {
679 InstMIPS32Store() = delete;
680 InstMIPS32Store(const InstMIPS32Store &) = delete;
681 InstMIPS32Store &operator=(const InstMIPS32Store &) = delete;
682
683public:
684 static InstMIPS32Store *create(Cfg *Func, Variable *Value,
Jaydeep Patil8b322412016-08-18 22:43:43 -0700685 OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) {
Jaydeep Patilb1a0fb12016-08-18 22:37:30 -0700686 return new (Func->allocate<InstMIPS32Store>())
687 InstMIPS32Store(Func, Value, Mem, Reloc);
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700688 }
689
690 void emit(const Cfg *Func) const override {
691 if (!BuildDefs::dump())
692 return;
693 Ostream &Str = Func->getContext()->getStrEmit();
694 assert(getSrcSize() == 2);
Jaydeep Patil1d0690b2016-09-04 07:19:08 -0700695 const Type Ty = getSrc(0)->getType();
Sagar Thakurbecb85f2016-11-18 12:15:46 -0800696
697 if (getKind() == static_cast<InstKind>(Sc)) {
698 Str << "\t" << Opcode << "\t";
699 } else {
700 switch (Ty) {
701 case IceType_i1:
702 case IceType_i8:
703 Str << "\t"
704 "sb"
705 "\t";
706 break;
707 case IceType_i16:
708 Str << "\t"
709 "sh"
710 "\t";
711 break;
712 case IceType_i32:
713 Str << "\t"
714 "sw"
715 "\t";
716 break;
717 case IceType_f32:
718 Str << "\t"
719 "swc1"
720 "\t";
721 break;
722 case IceType_f64:
723 Str << "\t"
724 "sdc1"
725 "\t";
726 break;
727 default:
728 llvm_unreachable("InstMIPS32Store unknown type");
729 }
Jaydeep Patil1d0690b2016-09-04 07:19:08 -0700730 }
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700731 getSrc(0)->emit(Func);
732 Str << ", ";
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700733 emitRelocOp(Str, Reloc);
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700734 getSrc(1)->emit(Func);
735 }
736
737 void emitIAS(const Cfg *Func) const override {
738 (void)Func;
Jaydeep Patil1d0690b2016-09-04 07:19:08 -0700739 llvm_unreachable("InstMIPS32Store: Not yet implemented");
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700740 }
741
742 void dump(const Cfg *Func) const override {
743 if (!BuildDefs::dump())
744 return;
745 Ostream &Str = Func->getContext()->getStrDump();
Jaydeep Patil1d0690b2016-09-04 07:19:08 -0700746 dumpOpcode(Str, Opcode, getSrc(0)->getType());
747 Str << " ";
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700748 getSrc(0)->dump(Func);
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700749 Str << ", ";
750 emitRelocOp(Str, Reloc);
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700751 getSrc(1)->dump(Func);
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700752 }
753 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
754
755private:
Jaydeep Patilb1a0fb12016-08-18 22:37:30 -0700756 InstMIPS32Store(Cfg *Func, Variable *Value, OperandMIPS32Mem *Mem,
Jaydeep Patil8b322412016-08-18 22:43:43 -0700757 RelocOp Reloc = RO_No)
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700758 : InstMIPS32(Func, K, 2, nullptr), Reloc(Reloc) {
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700759 addSource(Value);
760 addSource(Mem);
761 }
762 static const char *Opcode;
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700763 const RelocOp Reloc;
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700764};
765
Reed Kotler3fe4b572016-02-23 18:59:43 -0800766// InstMIPS32Label represents an intra-block label that is the target of an
767// intra-block branch. The offset between the label and the branch must be fit
768// in the instruction immediate (considered "near").
769class InstMIPS32Label : public InstMIPS32 {
770 InstMIPS32Label() = delete;
771 InstMIPS32Label(const InstMIPS32Label &) = delete;
772 InstMIPS32Label &operator=(const InstMIPS32Label &) = delete;
773
774public:
775 static InstMIPS32Label *create(Cfg *Func, TargetMIPS32 *Target) {
776 return new (Func->allocate<InstMIPS32Label>())
777 InstMIPS32Label(Func, Target);
778 }
779 uint32_t getEmitInstCount() const override { return 0; }
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700780 GlobalString getLabelName() const { return Name; }
Reed Kotler3fe4b572016-02-23 18:59:43 -0800781 SizeT getNumber() const { return Number; }
782 void emit(const Cfg *Func) const override;
783 void emitIAS(const Cfg *Func) const override;
784 void dump(const Cfg *Func) const override;
785
786 static bool classof(const Inst *Instr) { return isClassof(Instr, Label); }
787
788private:
789 InstMIPS32Label(Cfg *Func, TargetMIPS32 *Target);
790
Jim Stichnoth09802a92016-02-24 07:05:12 -0800791 // RelocOffset *OffsetReloc = nullptr;
Reed Kotler3fe4b572016-02-23 18:59:43 -0800792 SizeT Number; // used for unique label generation.
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700793 GlobalString Name;
Reed Kotler3fe4b572016-02-23 18:59:43 -0800794};
795
796/// Direct branch instruction.
797class InstMIPS32Br : public InstMIPS32 {
798 InstMIPS32Br() = delete;
799 InstMIPS32Br(const InstMIPS32Br &) = delete;
800 InstMIPS32Br &operator=(const InstMIPS32Br &) = delete;
801
802public:
803 /// Create an unconditional branch to a node.
804 static InstMIPS32Br *create(Cfg *Func, CfgNode *Target) {
805 constexpr CfgNode *NoCondTarget = nullptr;
806 constexpr InstMIPS32Label *NoLabel = nullptr;
807 return new (Func->allocate<InstMIPS32Br>())
Sagar Thakur5cce7612016-05-24 06:25:50 -0700808 InstMIPS32Br(Func, NoCondTarget, Target, NoLabel, CondMIPS32::AL);
Reed Kotler3fe4b572016-02-23 18:59:43 -0800809 }
Sagar Thakur5cce7612016-05-24 06:25:50 -0700810
Sagar Thakurbecb85f2016-11-18 12:15:46 -0800811 static InstMIPS32Br *create(Cfg *Func, CfgNode *Target,
812 const InstMIPS32Label *Label) {
813 constexpr CfgNode *NoCondTarget = nullptr;
814 return new (Func->allocate<InstMIPS32Br>())
815 InstMIPS32Br(Func, NoCondTarget, Target, Label, CondMIPS32::AL);
816 }
817
Sagar Thakur5cce7612016-05-24 06:25:50 -0700818 /// Create a conditional branch to the false node.
819 static InstMIPS32Br *create(Cfg *Func, CfgNode *TargetTrue,
820 CfgNode *TargetFalse, Operand *Src0,
821 Operand *Src1, CondMIPS32::Cond Cond) {
822 constexpr InstMIPS32Label *NoLabel = nullptr;
823 return new (Func->allocate<InstMIPS32Br>())
824 InstMIPS32Br(Func, TargetTrue, TargetFalse, Src0, Src1, NoLabel, Cond);
825 }
826
827 static InstMIPS32Br *create(Cfg *Func, CfgNode *TargetTrue,
828 CfgNode *TargetFalse, Operand *Src0,
829 CondMIPS32::Cond Cond) {
830 constexpr InstMIPS32Label *NoLabel = nullptr;
831 return new (Func->allocate<InstMIPS32Br>())
832 InstMIPS32Br(Func, TargetTrue, TargetFalse, Src0, NoLabel, Cond);
833 }
834
Jaydeep Patil29823f12016-08-31 05:10:03 -0700835 static InstMIPS32Br *create(Cfg *Func, CfgNode *TargetTrue,
836 CfgNode *TargetFalse, Operand *Src0,
837 Operand *Src1, const InstMIPS32Label *Label,
838 CondMIPS32::Cond Cond) {
839 return new (Func->allocate<InstMIPS32Br>())
840 InstMIPS32Br(Func, TargetTrue, TargetFalse, Src0, Src1, Label, Cond);
841 }
842
Reed Kotler3fe4b572016-02-23 18:59:43 -0800843 const CfgNode *getTargetTrue() const { return TargetTrue; }
844 const CfgNode *getTargetFalse() const { return TargetFalse; }
Jaydeep Patil13f0ca32016-08-26 13:27:40 -0700845 CondMIPS32::Cond getPredicate() const { return Predicate; }
846 void setPredicate(CondMIPS32::Cond Pred) { Predicate = Pred; }
847 bool optimizeBranch(const CfgNode *NextNode);
Sagar Thakur5cce7612016-05-24 06:25:50 -0700848 bool isUnconditionalBranch() const override {
849 return Predicate == CondMIPS32::AL;
850 }
Jaydeep Patil8b322412016-08-18 22:43:43 -0700851 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
Reed Kotler3fe4b572016-02-23 18:59:43 -0800852 void emit(const Cfg *Func) const override;
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700853 void emitIAS(const Cfg *Func) const override;
Sagar Thakur5cce7612016-05-24 06:25:50 -0700854 void dump(const Cfg *Func) const override;
Reed Kotler3fe4b572016-02-23 18:59:43 -0800855 static bool classof(const Inst *Instr) { return isClassof(Instr, Br); }
856
857private:
858 InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
Sagar Thakur5cce7612016-05-24 06:25:50 -0700859 const InstMIPS32Label *Label, const CondMIPS32::Cond Cond);
860
861 InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
862 Operand *Src0, const InstMIPS32Label *Label,
863 const CondMIPS32::Cond Cond);
864
865 InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
866 Operand *Src0, Operand *Src1, const InstMIPS32Label *Label,
867 const CondMIPS32::Cond Cond);
Reed Kotler3fe4b572016-02-23 18:59:43 -0800868
869 const CfgNode *TargetTrue;
870 const CfgNode *TargetFalse;
871 const InstMIPS32Label *Label; // Intra-block branch target
Jaydeep Patil13f0ca32016-08-26 13:27:40 -0700872 CondMIPS32::Cond Predicate;
Reed Kotler3fe4b572016-02-23 18:59:43 -0800873};
874
Reed Kotler00e36042016-02-01 20:52:19 -0800875class InstMIPS32Call : public InstMIPS32 {
876 InstMIPS32Call() = delete;
877 InstMIPS32Call(const InstMIPS32Call &) = delete;
878 InstMIPS32Call &operator=(const InstMIPS32Call &) = delete;
879
880public:
881 static InstMIPS32Call *create(Cfg *Func, Variable *Dest,
882 Operand *CallTarget) {
883 return new (Func->allocate<InstMIPS32Call>())
884 InstMIPS32Call(Func, Dest, CallTarget);
885 }
886 Operand *getCallTarget() const { return getSrc(0); }
887 void emit(const Cfg *Func) const override;
888 void emitIAS(const Cfg *Func) const override;
889 void dump(const Cfg *Func) const override;
890 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); }
891
892private:
893 InstMIPS32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
894};
895
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700896template <InstMIPS32::InstKindMIPS32 K>
897class InstMIPS32FPCmp : public InstMIPS32 {
898 InstMIPS32FPCmp() = delete;
899 InstMIPS32FPCmp(const InstMIPS32FPCmp &) = delete;
900 InstMIPS32Call &operator=(const InstMIPS32FPCmp &) = delete;
901
902public:
903 static InstMIPS32FPCmp *create(Cfg *Func, Variable *Src0, Variable *Src1) {
904 return new (Func->allocate<InstMIPS32FPCmp>())
905 InstMIPS32FPCmp(Func, Src0, Src1);
906 }
907
908 void emit(const Cfg *Func) const override {
909 if (!BuildDefs::dump())
910 return;
911 Ostream &Str = Func->getContext()->getStrEmit();
912 assert(getSrcSize() == 2);
913 Str << "\t" << Opcode << "\t";
914 getSrc(0)->emit(Func);
915 Str << ", ";
916 getSrc(1)->emit(Func);
917 }
918
919 void emitIAS(const Cfg *Func) const override {
920 (void)Func;
921 llvm_unreachable("Not yet implemented");
922 }
923
924 void dump(const Cfg *Func) const override {
925 (void)Func;
926 if (!BuildDefs::dump())
927 return;
928 Ostream &Str = Func->getContext()->getStrDump();
929 dumpOpcode(Str, Opcode, getSrc(0)->getType());
930 Str << " ";
931 dumpSources(Func);
932 }
933
934 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); }
935
936private:
937 InstMIPS32FPCmp(Cfg *Func, Variable *Src0, Variable *Src1)
938 : InstMIPS32(Func, K, 2, nullptr) {
939 addSource(Src0);
940 addSource(Src1);
941 };
942
943 static const char *Opcode;
944};
945
Sagar Thakurbecb85f2016-11-18 12:15:46 -0800946class InstMIPS32Sync : public InstMIPS32 {
947 InstMIPS32Sync() = delete;
948 InstMIPS32Sync(const InstMIPS32Sync &) = delete;
949 InstMIPS32Sync &operator=(const InstMIPS32Sync &) = delete;
950
951public:
952 static InstMIPS32Sync *create(Cfg *Func) {
953 return new (Func->allocate<InstMIPS32Sync>()) InstMIPS32Sync(Func);
954 }
955
956 void emit(const Cfg *Func) const override {
957 if (!BuildDefs::dump())
958 return;
959 Ostream &Str = Func->getContext()->getStrEmit();
960 Str << "\t" << Opcode << "\t";
961 }
962
963 void dump(const Cfg *Func) const override {
964 if (!BuildDefs::dump())
965 return;
966 Func->getContext()->getStrDump() << Opcode << "\t";
967 }
968
969 static bool classof(const Inst *Inst) {
970 return isClassof(Inst, InstMIPS32::Sync);
971 }
972
973 void emitIAS(const Cfg *Func) const override;
974
975private:
976 InstMIPS32Sync(Cfg *Func) : InstMIPS32(Func, InstMIPS32::Sync, 0, nullptr) {}
977 static const char *Opcode;
978};
979
Jaydeep Patilcc6dea72016-09-19 16:48:34 -0700980// Trap
981template <InstMIPS32::InstKindMIPS32 K>
982class InstMIPS32Trap : public InstMIPS32 {
983 InstMIPS32Trap() = delete;
984 InstMIPS32Trap(const InstMIPS32Trap &) = delete;
985 InstMIPS32Trap &operator=(const InstMIPS32Trap &) = delete;
986
987public:
988 static InstMIPS32Trap *create(Cfg *Func, Operand *Src0, Operand *Src1,
989 uint32_t Tcode) {
990 return new (Func->allocate<InstMIPS32Trap>())
991 InstMIPS32Trap(Func, Src0, Src1, Tcode);
992 }
993
Srdjan Obucina3b61d702016-09-20 06:49:52 -0700994 uint32_t getTrapCode() const { return TrapCode; }
995
Jaydeep Patilcc6dea72016-09-19 16:48:34 -0700996 void emit(const Cfg *Func) const override {
997 if (!BuildDefs::dump())
998 return;
999 Ostream &Str = Func->getContext()->getStrEmit();
1000 Str << "\t" << Opcode << "\t";
1001 getSrc(0)->emit(Func);
1002 Str << ", ";
1003 getSrc(1)->emit(Func);
1004 Str << ", " << TrapCode;
1005 }
1006
1007 void emitIAS(const Cfg *Func) const override {
1008 (void)Func;
1009 llvm_unreachable("Not yet implemented");
1010 }
1011
1012 void dump(const Cfg *Func) const override {
1013 if (!BuildDefs::dump())
1014 return;
Jaydeep Patil958ddb72016-10-03 07:52:48 -07001015 Ostream &Str = Func->getContext()->getStrDump();
1016 dumpOpcode(Str, Opcode, getSrc(0)->getType());
1017 Str << " ";
1018 dumpSources(Func);
Jaydeep Patilcc6dea72016-09-19 16:48:34 -07001019 Str << ", " << TrapCode;
1020 }
1021
1022 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
1023
1024private:
1025 InstMIPS32Trap(Cfg *Func, Operand *Src0, Operand *Src1, const uint32_t Tcode)
1026 : InstMIPS32(Func, K, 2, nullptr), TrapCode(Tcode) {
1027 addSource(Src0);
1028 addSource(Src1);
1029 }
1030
1031 static const char *Opcode;
1032 const uint32_t TrapCode;
1033};
1034
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001035template <InstMIPS32::InstKindMIPS32 K, bool Signed = false>
1036class InstMIPS32Imm16 : public InstMIPS32 {
1037 InstMIPS32Imm16() = delete;
1038 InstMIPS32Imm16(const InstMIPS32Imm16 &) = delete;
1039 InstMIPS32Imm16 &operator=(const InstMIPS32Imm16 &) = delete;
1040
1041public:
1042 static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, Operand *Source,
Jaydeep Patil45e4d5e2016-10-16 21:50:43 -07001043 uint32_t Imm, RelocOp Reloc = RO_No) {
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001044 return new (Func->allocate<InstMIPS32Imm16>())
Jaydeep Patil45e4d5e2016-10-16 21:50:43 -07001045 InstMIPS32Imm16(Func, Dest, Source, Imm, Reloc);
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001046 }
1047
Jaydeep Patil45e4d5e2016-10-16 21:50:43 -07001048 static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, uint32_t Imm,
1049 RelocOp Reloc = RO_No) {
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001050 return new (Func->allocate<InstMIPS32Imm16>())
Jaydeep Patil45e4d5e2016-10-16 21:50:43 -07001051 InstMIPS32Imm16(Func, Dest, Imm, Reloc);
1052 }
1053
1054 static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, Operand *Src0,
1055 Operand *Src1, RelocOp Reloc) {
1056 return new (Func->allocate<InstMIPS32Imm16>())
1057 InstMIPS32Imm16(Func, Dest, Src0, Src1, Reloc);
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001058 }
1059
1060 void emit(const Cfg *Func) const override {
1061 if (!BuildDefs::dump())
1062 return;
1063 Ostream &Str = Func->getContext()->getStrEmit();
1064 Str << "\t" << Opcode << "\t";
1065 getDest()->emit(Func);
1066 if (getSrcSize() > 0) {
1067 Str << ", ";
1068 getSrc(0)->emit(Func);
1069 }
1070 Str << ", ";
Jaydeep Patil45e4d5e2016-10-16 21:50:43 -07001071 if (Reloc == RO_No) {
1072 if (Signed)
1073 Str << (int32_t)Imm;
1074 else
1075 Str << Imm;
1076 } else {
1077 auto *CR = llvm::dyn_cast<ConstantRelocatable>(getSrc(1));
1078 emitRelocOp(Str, Reloc);
1079 Str << "(";
1080 CR->emitWithoutPrefix(Func->getTarget());
1081 Str << ")";
1082 }
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001083 }
1084
1085 void emitIAS(const Cfg *Func) const override {
1086 (void)Func;
1087 llvm_unreachable("Not yet implemented");
1088 }
1089 void dump(const Cfg *Func) const override {
1090 if (!BuildDefs::dump())
1091 return;
1092 Ostream &Str = Func->getContext()->getStrDump();
Jaydeep Patil1d0690b2016-09-04 07:19:08 -07001093 dumpOpcode(Str, Opcode, getDest()->getType());
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001094 Str << " ";
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001095 dumpDest(Func);
1096 Str << ", ";
Jaydeep Patil45e4d5e2016-10-16 21:50:43 -07001097 if (Reloc == RO_No) {
1098 dumpSources(Func);
1099 Str << ", ";
1100 if (Signed)
1101 Str << (int32_t)Imm;
1102 else
1103 Str << Imm;
1104 } else {
1105 getSrc(0)->dump(Func);
1106 Str << ",";
1107 emitRelocOp(Str, Reloc);
1108 Str << "(";
1109 getSrc(1)->dump(Func);
1110 Str << ")";
1111 }
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001112 }
1113
Sagar Thakur89be8872016-10-18 07:32:21 -07001114 uint32_t getImmediateValue() const { return Imm; }
1115
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001116 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
1117
1118private:
Jaydeep Patil45e4d5e2016-10-16 21:50:43 -07001119 InstMIPS32Imm16(Cfg *Func, Variable *Dest, Operand *Source, uint32_t Imm,
1120 RelocOp Reloc = RO_No)
1121 : InstMIPS32(Func, K, 1, Dest), Reloc(Reloc), Imm(Imm) {
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001122 addSource(Source);
1123 }
1124
Jaydeep Patil45e4d5e2016-10-16 21:50:43 -07001125 InstMIPS32Imm16(Cfg *Func, Variable *Dest, uint32_t Imm,
1126 RelocOp Reloc = RO_No)
1127 : InstMIPS32(Func, K, 0, Dest), Reloc(Reloc), Imm(Imm) {}
1128
1129 InstMIPS32Imm16(Cfg *Func, Variable *Dest, Operand *Src0, Operand *Src1,
1130 RelocOp Reloc = RO_No)
1131 : InstMIPS32(Func, K, 1, Dest), Reloc(Reloc), Imm(0) {
1132 addSource(Src0);
1133 addSource(Src1);
1134 }
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001135
1136 static const char *Opcode;
Jaydeep Patil45e4d5e2016-10-16 21:50:43 -07001137 const RelocOp Reloc;
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001138 const uint32_t Imm;
1139};
1140
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -07001141/// Conditional mov
1142template <InstMIPS32::InstKindMIPS32 K>
1143class InstMIPS32MovConditional : public InstMIPS32 {
1144 InstMIPS32MovConditional() = delete;
1145 InstMIPS32MovConditional(const InstMIPS32MovConditional &) = delete;
1146 InstMIPS32MovConditional &
1147 operator=(const InstMIPS32MovConditional &) = delete;
1148
1149public:
1150 static InstMIPS32MovConditional *create(Cfg *Func, Variable *Dest,
1151 Variable *Src, Operand *FCC) {
1152 return new (Func->allocate<InstMIPS32MovConditional>())
1153 InstMIPS32MovConditional(Func, Dest, Src, FCC);
1154 }
1155
1156 void emit(const Cfg *Func) const override {
1157 if (!BuildDefs::dump())
1158 return;
1159 Ostream &Str = Func->getContext()->getStrEmit();
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -07001160 assert(getSrcSize() == 2);
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -07001161 Str << "\t" << Opcode << "\t";
1162 getDest()->emit(Func);
1163 Str << ", ";
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -07001164 getSrc(0)->emit(Func);
Jaydeep Patild8954472016-09-21 06:24:41 -07001165 Str << ", ";
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -07001166 getSrc(1)->emit(Func);
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -07001167 }
1168
1169 void emitIAS(const Cfg *Func) const override {
1170 (void)Func;
1171 llvm_unreachable("Not yet implemented");
1172 }
1173
1174 void dump(const Cfg *Func) const override {
1175 if (!BuildDefs::dump())
1176 return;
1177 Ostream &Str = Func->getContext()->getStrDump();
1178 dumpDest(Func);
1179 Str << " = ";
1180 dumpOpcode(Str, Opcode, getDest()->getType());
1181 Str << " ";
1182 dumpSources(Func);
1183 }
1184 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
1185
1186private:
1187 InstMIPS32MovConditional(Cfg *Func, Variable *Dest, Variable *Src,
1188 Operand *FCC)
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -07001189 : InstMIPS32(Func, K, 2, Dest) {
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -07001190 addSource(Src);
1191 addSource(FCC);
1192 }
1193
1194 static const char *Opcode;
1195};
1196
Srdjan Obucina53d05682016-09-10 08:25:37 -07001197using InstMIPS32Abs_d = InstMIPS32TwoAddrFPR<InstMIPS32::Abs_d>;
1198using InstMIPS32Abs_s = InstMIPS32TwoAddrFPR<InstMIPS32::Abs_s>;
Reed Kotler37af5b02015-11-05 17:07:19 -08001199using InstMIPS32Add = InstMIPS32ThreeAddrGPR<InstMIPS32::Add>;
Srdjan Obucina2f593bb2016-05-27 14:40:32 -07001200using InstMIPS32Add_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Add_d>;
1201using InstMIPS32Add_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Add_s>;
Reed Kotler00e36042016-02-01 20:52:19 -08001202using InstMIPS32Addu = InstMIPS32ThreeAddrGPR<InstMIPS32::Addu>;
Jaydeep Patil130aca72016-10-28 05:30:54 -07001203using InstMIPS32Addi = InstMIPS32Imm16<InstMIPS32::Addi, true>;
Reed Kotler37af5b02015-11-05 17:07:19 -08001204using InstMIPS32Addiu = InstMIPS32Imm16<InstMIPS32::Addiu, true>;
1205using InstMIPS32And = InstMIPS32ThreeAddrGPR<InstMIPS32::And>;
Sagar Thakur38dcb592016-05-09 11:57:59 -07001206using InstMIPS32Andi = InstMIPS32Imm16<InstMIPS32::Andi>;
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -07001207using InstMIPS32C_eq_d = InstMIPS32FPCmp<InstMIPS32::C_eq_d>;
1208using InstMIPS32C_eq_s = InstMIPS32FPCmp<InstMIPS32::C_eq_s>;
1209using InstMIPS32C_ole_d = InstMIPS32FPCmp<InstMIPS32::C_ole_d>;
1210using InstMIPS32C_ole_s = InstMIPS32FPCmp<InstMIPS32::C_ole_s>;
1211using InstMIPS32C_olt_d = InstMIPS32FPCmp<InstMIPS32::C_olt_d>;
1212using InstMIPS32C_olt_s = InstMIPS32FPCmp<InstMIPS32::C_olt_s>;
1213using InstMIPS32C_ueq_d = InstMIPS32FPCmp<InstMIPS32::C_ueq_d>;
1214using InstMIPS32C_ueq_s = InstMIPS32FPCmp<InstMIPS32::C_ueq_s>;
1215using InstMIPS32C_ule_d = InstMIPS32FPCmp<InstMIPS32::C_ule_d>;
1216using InstMIPS32C_ule_s = InstMIPS32FPCmp<InstMIPS32::C_ule_s>;
1217using InstMIPS32C_ult_d = InstMIPS32FPCmp<InstMIPS32::C_ult_d>;
1218using InstMIPS32C_ult_s = InstMIPS32FPCmp<InstMIPS32::C_ult_s>;
1219using InstMIPS32C_un_d = InstMIPS32FPCmp<InstMIPS32::C_un_d>;
1220using InstMIPS32C_un_s = InstMIPS32FPCmp<InstMIPS32::C_un_s>;
Srdjan Obucinad27ce3d2016-09-22 12:56:12 -07001221using InstMIPS32Clz = InstMIPS32TwoAddrGPR<InstMIPS32::Clz>;
Srdjan Obucina418135a2016-06-02 06:47:06 -07001222using InstMIPS32Cvt_d_s = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_d_s>;
1223using InstMIPS32Cvt_d_l = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_d_l>;
1224using InstMIPS32Cvt_d_w = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_d_w>;
1225using InstMIPS32Cvt_s_d = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_d>;
1226using InstMIPS32Cvt_s_l = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_l>;
1227using InstMIPS32Cvt_s_w = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_w>;
Srdjan Obucinaae93eee2016-05-18 11:31:15 -07001228using InstMIPS32Div = InstMIPS32ThreeAddrGPR<InstMIPS32::Div>;
Srdjan Obucina2f593bb2016-05-27 14:40:32 -07001229using InstMIPS32Div_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Div_d>;
1230using InstMIPS32Div_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Div_s>;
Srdjan Obucinaae93eee2016-05-18 11:31:15 -07001231using InstMIPS32Divu = InstMIPS32ThreeAddrGPR<InstMIPS32::Divu>;
Reed Kotler37af5b02015-11-05 17:07:19 -08001232using InstMIPS32La = InstMIPS32UnaryopGPR<InstMIPS32::La>;
Jaydeep Patilb1a0fb12016-08-18 22:37:30 -07001233using InstMIPS32Ldc1 = InstMIPS32Load<InstMIPS32::Ldc1>;
Sagar Thakurbecb85f2016-11-18 12:15:46 -08001234using InstMIPS32Ll = InstMIPS32Load<InstMIPS32::Ll>;
Mohit Bhakkadd1e97772016-07-07 05:07:35 -07001235using InstMIPS32Lui = InstMIPS32UnaryopGPR<InstMIPS32::Lui>;
Jaydeep Patilb1a0fb12016-08-18 22:37:30 -07001236using InstMIPS32Lw = InstMIPS32Load<InstMIPS32::Lw>;
1237using InstMIPS32Lwc1 = InstMIPS32Load<InstMIPS32::Lwc1>;
Srdjan Obucina2f593bb2016-05-27 14:40:32 -07001238using InstMIPS32Mfc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mfc1>;
Reed Kotlera80cdbc2016-02-19 22:03:29 -08001239using InstMIPS32Mfhi = InstMIPS32UnaryopGPR<InstMIPS32::Mfhi>;
1240using InstMIPS32Mflo = InstMIPS32UnaryopGPR<InstMIPS32::Mflo>;
Srdjan Obucina2f593bb2016-05-27 14:40:32 -07001241using InstMIPS32Mov_d = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_d>;
1242using InstMIPS32Mov_s = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_s>;
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -07001243using InstMIPS32Movf = InstMIPS32MovConditional<InstMIPS32::Movf>;
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -07001244using InstMIPS32Movn = InstMIPS32ThreeAddrGPR<InstMIPS32::Movn>;
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -07001245using InstMIPS32Movn_d = InstMIPS32ThreeAddrGPR<InstMIPS32::Movn_d>;
1246using InstMIPS32Movn_s = InstMIPS32ThreeAddrGPR<InstMIPS32::Movn_s>;
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -07001247using InstMIPS32Movt = InstMIPS32MovConditional<InstMIPS32::Movt>;
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -07001248using InstMIPS32Movz = InstMIPS32ThreeAddrGPR<InstMIPS32::Movz>;
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -07001249using InstMIPS32Movz_d = InstMIPS32ThreeAddrGPR<InstMIPS32::Movz_d>;
1250using InstMIPS32Movz_s = InstMIPS32ThreeAddrGPR<InstMIPS32::Movz_s>;
Srdjan Obucina2f593bb2016-05-27 14:40:32 -07001251using InstMIPS32Mtc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mtc1>;
Reed Kotlera80cdbc2016-02-19 22:03:29 -08001252using InstMIPS32Mthi = InstMIPS32UnaryopGPR<InstMIPS32::Mthi>;
1253using InstMIPS32Mtlo = InstMIPS32UnaryopGPR<InstMIPS32::Mtlo>;
Reed Kotler37af5b02015-11-05 17:07:19 -08001254using InstMIPS32Mul = InstMIPS32ThreeAddrGPR<InstMIPS32::Mul>;
Srdjan Obucina2f593bb2016-05-27 14:40:32 -07001255using InstMIPS32Mul_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Mul_d>;
1256using InstMIPS32Mul_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Mul_s>;
Reed Kotlera80cdbc2016-02-19 22:03:29 -08001257using InstMIPS32Mult = InstMIPS32ThreeAddrGPR<InstMIPS32::Mult>;
1258using InstMIPS32Multu = InstMIPS32ThreeAddrGPR<InstMIPS32::Multu>;
Srdjan Obucinacadda792016-09-22 11:24:44 -07001259using InstMIPS32Nor = InstMIPS32ThreeAddrGPR<InstMIPS32::Nor>;
Reed Kotler37af5b02015-11-05 17:07:19 -08001260using InstMIPS32Or = InstMIPS32ThreeAddrGPR<InstMIPS32::Or>;
1261using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>;
Sagar Thakurbecb85f2016-11-18 12:15:46 -08001262using InstMIPS32Sc = InstMIPS32Store<InstMIPS32::Sc>;
Jaydeep Patilb1a0fb12016-08-18 22:37:30 -07001263using InstMIPS32Sdc1 = InstMIPS32Store<InstMIPS32::Sdc1>;
Sagar Thakur38dcb592016-05-09 11:57:59 -07001264using InstMIPS32Sll = InstMIPS32Imm16<InstMIPS32::Sll>;
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -07001265using InstMIPS32Sllv = InstMIPS32ThreeAddrGPR<InstMIPS32::Sllv>;
Sagar Thakur1a478b12016-04-25 08:39:19 -07001266using InstMIPS32Slt = InstMIPS32ThreeAddrGPR<InstMIPS32::Slt>;
1267using InstMIPS32Slti = InstMIPS32Imm16<InstMIPS32::Slti>;
1268using InstMIPS32Sltiu = InstMIPS32Imm16<InstMIPS32::Sltiu>;
Reed Kotler00e36042016-02-01 20:52:19 -08001269using InstMIPS32Sltu = InstMIPS32ThreeAddrGPR<InstMIPS32::Sltu>;
Srdjan Obucina53d05682016-09-10 08:25:37 -07001270using InstMIPS32Sqrt_d = InstMIPS32TwoAddrFPR<InstMIPS32::Sqrt_d>;
1271using InstMIPS32Sqrt_s = InstMIPS32TwoAddrFPR<InstMIPS32::Sqrt_s>;
Sagar Thakur38dcb592016-05-09 11:57:59 -07001272using InstMIPS32Sra = InstMIPS32Imm16<InstMIPS32::Sra>;
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -07001273using InstMIPS32Srav = InstMIPS32ThreeAddrGPR<InstMIPS32::Srav>;
1274using InstMIPS32Srl = InstMIPS32Imm16<InstMIPS32::Srl>;
1275using InstMIPS32Srlv = InstMIPS32ThreeAddrGPR<InstMIPS32::Srlv>;
Reed Kotler37af5b02015-11-05 17:07:19 -08001276using InstMIPS32Sub = InstMIPS32ThreeAddrGPR<InstMIPS32::Sub>;
Srdjan Obucina2f593bb2016-05-27 14:40:32 -07001277using InstMIPS32Sub_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Sub_d>;
1278using InstMIPS32Sub_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Sub_s>;
Reed Kotler00e36042016-02-01 20:52:19 -08001279using InstMIPS32Subu = InstMIPS32ThreeAddrGPR<InstMIPS32::Subu>;
Jaydeep Patilb1a0fb12016-08-18 22:37:30 -07001280using InstMIPS32Sw = InstMIPS32Store<InstMIPS32::Sw>;
1281using InstMIPS32Swc1 = InstMIPS32Store<InstMIPS32::Swc1>;
Jaydeep Patilcc6dea72016-09-19 16:48:34 -07001282using InstMIPS32Teq = InstMIPS32Trap<InstMIPS32::Teq>;
Srdjan Obucina418135a2016-06-02 06:47:06 -07001283using InstMIPS32Trunc_l_d = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_l_d>;
1284using InstMIPS32Trunc_l_s = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_l_s>;
1285using InstMIPS32Trunc_w_d = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_w_d>;
1286using InstMIPS32Trunc_w_s = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_w_s>;
Reed Kotler37af5b02015-11-05 17:07:19 -08001287using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>;
1288using InstMIPS32Xor = InstMIPS32ThreeAddrGPR<InstMIPS32::Xor>;
Sagar Thakur1a478b12016-04-25 08:39:19 -07001289using InstMIPS32Xori = InstMIPS32Imm16<InstMIPS32::Xori>;
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001290
1291/// Handles (some of) vmov's various formats.
1292class InstMIPS32Mov final : public InstMIPS32 {
1293 InstMIPS32Mov() = delete;
1294 InstMIPS32Mov(const InstMIPS32Mov &) = delete;
1295 InstMIPS32Mov &operator=(const InstMIPS32Mov &) = delete;
1296
1297public:
Sagar Thakurb001cc42016-10-11 23:36:01 -07001298 static InstMIPS32Mov *create(Cfg *Func, Variable *Dest, Operand *Src,
1299 Operand *Src2) {
1300 return new (Func->allocate<InstMIPS32Mov>())
1301 InstMIPS32Mov(Func, Dest, Src, Src2);
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001302 }
Sagar Thakurb001cc42016-10-11 23:36:01 -07001303
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001304 bool isRedundantAssign() const override {
Sagar Thakurb001cc42016-10-11 23:36:01 -07001305 return checkForRedundantAssign(getDest(), getSrc(0));
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001306 }
Karl Schimpf2fee2a22015-10-22 08:19:26 -07001307 // bool isSimpleAssign() const override { return true; }
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001308 void emit(const Cfg *Func) const override;
1309 void emitIAS(const Cfg *Func) const override;
1310 void dump(const Cfg *Func) const override;
1311 static bool classof(const Inst *Inst) { return isClassof(Inst, Mov); }
1312
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001313 Variable *getDestHi() const { return DestHi; }
1314
1315private:
Sagar Thakurb001cc42016-10-11 23:36:01 -07001316 InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src, Operand *Src2);
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001317
1318 void emitMultiDestSingleSource(const Cfg *Func) const;
1319 void emitSingleDestMultiSource(const Cfg *Func) const;
1320 void emitSingleDestSingleSource(const Cfg *Func) const;
1321
1322 Variable *DestHi = nullptr;
1323};
1324
Jaydeep Patil2bbda7f2017-01-10 21:48:58 -08001325/// Handle double to i64 move
1326class InstMIPS32MovFP64ToI64 final : public InstMIPS32 {
1327 InstMIPS32MovFP64ToI64() = delete;
1328 InstMIPS32MovFP64ToI64(const InstMIPS32MovFP64ToI64 &) = delete;
1329 InstMIPS32MovFP64ToI64 &operator=(const InstMIPS32MovFP64ToI64 &) = delete;
1330
1331public:
1332 static InstMIPS32MovFP64ToI64 *create(Cfg *Func, Variable *Dest, Operand *Src,
1333 Int64Part Int64HiLo) {
1334 return new (Func->allocate<InstMIPS32MovFP64ToI64>())
1335 InstMIPS32MovFP64ToI64(Func, Dest, Src, Int64HiLo);
1336 }
1337
1338 bool isRedundantAssign() const override {
1339 return checkForRedundantAssign(getDest(), getSrc(0));
1340 }
1341
1342 void dump(const Cfg *Func) const override {
1343 if (!BuildDefs::dump())
1344 return;
1345 Ostream &Str = Func->getContext()->getStrDump();
1346 getDest()->dump(Func);
1347 Str << " = ";
1348 dumpOpcode(Str, "mov_fp", getDest()->getType());
1349 Str << " ";
1350 getSrc(0)->dump(Func);
1351 }
1352
1353 Int64Part getInt64Part() const { return Int64HiLo; }
1354
1355 static bool classof(const Inst *Inst) { return isClassof(Inst, Mov_fp); }
1356
1357private:
1358 InstMIPS32MovFP64ToI64(Cfg *Func, Variable *Dest, Operand *Src,
1359 Int64Part Int64HiLo);
1360 const Int64Part Int64HiLo;
1361};
1362
Jim Stichnoth8159aae2016-02-25 00:13:46 -08001363// Declare partial template specializations of emit() methods that already have
1364// default implementations. Without this, there is the possibility of ODR
1365// violations and link errors.
1366
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001367template <> void InstMIPS32Abs_d::emitIAS(const Cfg *Func) const;
1368template <> void InstMIPS32Abs_s::emitIAS(const Cfg *Func) const;
1369template <> void InstMIPS32Add_d::emitIAS(const Cfg *Func) const;
1370template <> void InstMIPS32Add_s::emitIAS(const Cfg *Func) const;
Jaydeep Patil130aca72016-10-28 05:30:54 -07001371template <> void InstMIPS32Addi::emitIAS(const Cfg *Func) const;
Jim Stichnothbcf2a512016-09-14 05:41:46 -07001372template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001373template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const;
Jim Stichnothbcf2a512016-09-14 05:41:46 -07001374template <> void InstMIPS32And::emitIAS(const Cfg *Func) const;
1375template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const;
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -07001376template <> void InstMIPS32C_eq_d::emitIAS(const Cfg *Func) const;
1377template <> void InstMIPS32C_eq_s::emitIAS(const Cfg *Func) const;
1378template <> void InstMIPS32C_ole_d::emitIAS(const Cfg *Func) const;
1379template <> void InstMIPS32C_ole_s::emitIAS(const Cfg *Func) const;
1380template <> void InstMIPS32C_olt_d::emitIAS(const Cfg *Func) const;
1381template <> void InstMIPS32C_olt_s::emitIAS(const Cfg *Func) const;
1382template <> void InstMIPS32C_ueq_d::emitIAS(const Cfg *Func) const;
1383template <> void InstMIPS32C_ueq_s::emitIAS(const Cfg *Func) const;
1384template <> void InstMIPS32C_ule_d::emitIAS(const Cfg *Func) const;
1385template <> void InstMIPS32C_ule_s::emitIAS(const Cfg *Func) const;
1386template <> void InstMIPS32C_ult_d::emitIAS(const Cfg *Func) const;
1387template <> void InstMIPS32C_ult_s::emitIAS(const Cfg *Func) const;
1388template <> void InstMIPS32C_un_d::emitIAS(const Cfg *Func) const;
1389template <> void InstMIPS32C_un_s::emitIAS(const Cfg *Func) const;
Srdjan Obucinad27ce3d2016-09-22 12:56:12 -07001390template <> void InstMIPS32Clz::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001391template <> void InstMIPS32Cvt_d_l::emitIAS(const Cfg *Func) const;
1392template <> void InstMIPS32Cvt_d_s::emitIAS(const Cfg *Func) const;
1393template <> void InstMIPS32Cvt_d_w::emitIAS(const Cfg *Func) const;
1394template <> void InstMIPS32Cvt_s_d::emitIAS(const Cfg *Func) const;
1395template <> void InstMIPS32Cvt_s_l::emitIAS(const Cfg *Func) const;
1396template <> void InstMIPS32Cvt_s_w::emitIAS(const Cfg *Func) const;
Srdjan Obucina623f8ce2016-09-26 20:03:20 -07001397template <> void InstMIPS32Div::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001398template <> void InstMIPS32Div_d::emitIAS(const Cfg *Func) const;
1399template <> void InstMIPS32Div_s::emitIAS(const Cfg *Func) const;
Srdjan Obucina6163c622016-09-27 20:38:30 -07001400template <> void InstMIPS32Divu::emitIAS(const Cfg *Func) const;
Jaydeep Patil130aca72016-10-28 05:30:54 -07001401template <> void InstMIPS32Ldc1::emitIAS(const Cfg *Func) const;
Jim Stichnoth35bbca32016-12-23 20:00:19 -08001402template <> void InstMIPS32Ll::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001403template <> void InstMIPS32Lui::emit(const Cfg *Func) const;
Srdjan Obucina175cb132016-09-27 07:00:17 -07001404template <> void InstMIPS32Lui::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001405template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const;
Jaydeep Patil130aca72016-10-28 05:30:54 -07001406template <> void InstMIPS32Lwc1::emitIAS(const Cfg *Func) const;
Srdjan Obucina623f8ce2016-09-26 20:03:20 -07001407template <> void InstMIPS32Mfc1::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001408template <> void InstMIPS32Mflo::emit(const Cfg *Func) const;
Srdjan Obucina623f8ce2016-09-26 20:03:20 -07001409template <> void InstMIPS32Mflo::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001410template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const;
Srdjan Obucina623f8ce2016-09-26 20:03:20 -07001411template <> void InstMIPS32Mfhi::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001412template <> void InstMIPS32Mov_d::emitIAS(const Cfg *Func) const;
1413template <> void InstMIPS32Mov_s::emitIAS(const Cfg *Func) const;
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -07001414template <> void InstMIPS32Movf::emitIAS(const Cfg *Func) const;
Srdjan Obucinad27ce3d2016-09-22 12:56:12 -07001415template <> void InstMIPS32Movn::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001416template <> void InstMIPS32Movn_d::emitIAS(const Cfg *Func) const;
1417template <> void InstMIPS32Movn_s::emitIAS(const Cfg *Func) const;
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -07001418template <> void InstMIPS32Movt::emitIAS(const Cfg *Func) const;
Srdjan Obucinab0f09fc2016-09-27 20:43:11 -07001419template <> void InstMIPS32Movz::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001420template <> void InstMIPS32Movz_d::emitIAS(const Cfg *Func) const;
1421template <> void InstMIPS32Movz_s::emitIAS(const Cfg *Func) const;
1422template <> void InstMIPS32Mtc1::emit(const Cfg *Func) const;
Srdjan Obucina4c49b102016-09-26 20:12:17 -07001423template <> void InstMIPS32Mtc1::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001424template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const;
Srdjan Obucina623f8ce2016-09-26 20:03:20 -07001425template <> void InstMIPS32Mtlo::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001426template <> void InstMIPS32Mthi::emit(const Cfg *Func) const;
Srdjan Obucina623f8ce2016-09-26 20:03:20 -07001427template <> void InstMIPS32Mthi::emitIAS(const Cfg *Func) const;
1428template <> void InstMIPS32Mul::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001429template <> void InstMIPS32Mul_d::emitIAS(const Cfg *Func) const;
1430template <> void InstMIPS32Mul_s::emitIAS(const Cfg *Func) const;
1431template <> void InstMIPS32Mult::emit(const Cfg *Func) const;
1432template <> void InstMIPS32Multu::emit(const Cfg *Func) const;
Srdjan Obucina623f8ce2016-09-26 20:03:20 -07001433template <> void InstMIPS32Multu::emitIAS(const Cfg *Func) const;
Srdjan Obucinacadda792016-09-22 11:24:44 -07001434template <> void InstMIPS32Nor::emitIAS(const Cfg *Func) const;
Jim Stichnothbcf2a512016-09-14 05:41:46 -07001435template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const;
1436template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const;
Jim Stichnoth35bbca32016-12-23 20:00:19 -08001437template <> void InstMIPS32Sc::emitIAS(const Cfg *Func) const;
1438template <> void InstMIPS32Sdc1::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001439template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const;
Srdjan Obucina623f8ce2016-09-26 20:03:20 -07001440template <> void InstMIPS32Sllv::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001441template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const;
1442template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const;
1443template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const;
1444template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const;
1445template <> void InstMIPS32Sqrt_d::emitIAS(const Cfg *Func) const;
1446template <> void InstMIPS32Sqrt_s::emitIAS(const Cfg *Func) const;
1447template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const;
Jim Stichnoth35bbca32016-12-23 20:00:19 -08001448template <> void InstMIPS32Swc1::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001449template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const;
Srdjan Obucinafe93fdd2016-09-28 06:38:44 -07001450template <> void InstMIPS32Srav::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001451template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const;
Srdjan Obucina623f8ce2016-09-26 20:03:20 -07001452template <> void InstMIPS32Srlv::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001453template <> void InstMIPS32Sub_d::emitIAS(const Cfg *Func) const;
1454template <> void InstMIPS32Sub_s::emitIAS(const Cfg *Func) const;
Srdjan Obucina0a7f99d2016-09-23 06:59:50 -07001455template <> void InstMIPS32Subu::emitIAS(const Cfg *Func) const;
Srdjan Obucina3b61d702016-09-20 06:49:52 -07001456template <> void InstMIPS32Teq::emitIAS(const Cfg *Func) const;
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001457template <> void InstMIPS32Trunc_l_d::emitIAS(const Cfg *Func) const;
1458template <> void InstMIPS32Trunc_l_s::emitIAS(const Cfg *Func) const;
1459template <> void InstMIPS32Trunc_w_d::emitIAS(const Cfg *Func) const;
1460template <> void InstMIPS32Trunc_w_s::emitIAS(const Cfg *Func) const;
Jim Stichnothbcf2a512016-09-14 05:41:46 -07001461template <> void InstMIPS32Xor::emitIAS(const Cfg *Func) const;
1462template <> void InstMIPS32Xori::emitIAS(const Cfg *Func) const;
Jim Stichnothbcf2a512016-09-14 05:41:46 -07001463
John Porto4a566862016-01-04 09:33:41 -08001464} // end of namespace MIPS32
Jim Stichnoth6da4cef2015-06-11 13:26:33 -07001465} // end of namespace Ice
1466
1467#endif // SUBZERO_SRC_ICEINSTMIPS32_H