blob: 7b93811cdc699c8895d0c03365d90b0870b9b5d7 [file] [log] [blame]
Jim Stichnoth6da4cef2015-06-11 13:26:33 -07001//===- subzero/src/IceInstMIPS32.h - MIPS32 machine instrs --*- C++ -*-=== //
2//
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
31class TargetMIPS32;
Reed Kotlerd00d48d2015-07-08 09:49:07 -070032
Jim Stichnothac8da5c2015-10-21 06:57:46 -070033/// OperandMips32 extends the Operand hierarchy.
34//
35class OperandMIPS32 : public Operand {
36 OperandMIPS32() = delete;
37 OperandMIPS32(const OperandMIPS32 &) = delete;
38 OperandMIPS32 &operator=(const OperandMIPS32 &) = delete;
39
40public:
41 enum OperandKindMIPS32 {
42 k__Start = Operand::kTarget,
43 kMem,
44 };
45
46 using Operand::dump;
47 void dump(const Cfg *, Ostream &Str) const override {
48 if (BuildDefs::dump())
49 Str << "<OperandMIPS32>";
50 }
Karl Schimpf2fee2a22015-10-22 08:19:26 -070051
Jim Stichnothac8da5c2015-10-21 06:57:46 -070052protected:
53 OperandMIPS32(OperandKindMIPS32 Kind, Type Ty)
54 : Operand(static_cast<OperandKind>(Kind), Ty) {}
55};
56
57class OperandMIPS32Mem : public OperandMIPS32 {
58 OperandMIPS32Mem() = delete;
59 OperandMIPS32Mem(const OperandMIPS32Mem &) = delete;
60 OperandMIPS32Mem &operator=(const OperandMIPS32Mem &) = delete;
61
62public:
63 /// Memory operand addressing mode.
64 /// The enum value also carries the encoding.
65 // TODO(jvoung): unify with the assembler.
66 enum AddrMode { Offset };
67
68 /// NOTE: The Variable-typed operands have to be registers.
69 ///
70 /// Reg + Imm. The Immediate actually has a limited number of bits
71 /// for encoding, so check canHoldOffset first. It cannot handle
72 /// general Constant operands like ConstantRelocatable, since a relocatable
73 /// can potentially take up too many bits.
74 static OperandMIPS32Mem *create(Cfg *Func, Type Ty, Variable *Base,
75 ConstantInteger32 *ImmOffset,
76 AddrMode Mode = Offset) {
77 return new (Func->allocate<OperandMIPS32Mem>())
78 OperandMIPS32Mem(Func, Ty, Base, ImmOffset, Mode);
79 }
80
81 Variable *getBase() const { return Base; }
82 ConstantInteger32 *getOffset() const { return ImmOffset; }
83 AddrMode getAddrMode() const { return Mode; }
84
85 void emit(const Cfg *Func) const override;
86 using OperandMIPS32::dump;
87
88 static bool classof(const Operand *Operand) {
89 return Operand->getKind() == static_cast<OperandKind>(kMem);
90 }
91
92 /// Return true if a load/store instruction for an element of type Ty
93 /// can encode the Offset directly in the immediate field of the 32-bit
94 /// MIPS instruction. For some types, if the load is Sign extending, then
95 /// the range is reduced.
96 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset);
97
98 void dump(const Cfg *Func, Ostream &Str) const override {
99 (void)Func;
100 (void)Str;
101 }
102
103private:
104 OperandMIPS32Mem(Cfg *Func, Type Ty, Variable *Base,
105 ConstantInteger32 *ImmOffset, AddrMode Mode);
106
107 Variable *Base;
108 ConstantInteger32 *ImmOffset;
109 AddrMode Mode;
110};
111
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700112/// Base class for Mips instructions.
113class InstMIPS32 : public InstTarget {
114 InstMIPS32() = delete;
115 InstMIPS32(const InstMIPS32 &) = delete;
116 InstMIPS32 &operator=(const InstMIPS32 &) = delete;
117
118public:
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700119 enum InstKindMIPS32 {
120 k__Start = Inst::Target,
Reed Kotler37af5b02015-11-05 17:07:19 -0800121 Add,
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700122 Add_d,
123 Add_s,
Sagar Thakur1a478b12016-04-25 08:39:19 -0700124 Addiu,
Reed Kotler00e36042016-02-01 20:52:19 -0800125 Addu,
Reed Kotler37af5b02015-11-05 17:07:19 -0800126 And,
Sagar Thakur38dcb592016-05-09 11:57:59 -0700127 Andi,
Reed Kotler3fe4b572016-02-23 18:59:43 -0800128 Br,
Reed Kotler00e36042016-02-01 20:52:19 -0800129 Call,
Srdjan Obucina418135a2016-06-02 06:47:06 -0700130 Cvt_d_l,
131 Cvt_d_s,
132 Cvt_d_w,
133 Cvt_s_d,
134 Cvt_s_l,
135 Cvt_s_w,
Srdjan Obucinaae93eee2016-05-18 11:31:15 -0700136 Div,
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700137 Div_d,
138 Div_s,
Srdjan Obucinaae93eee2016-05-18 11:31:15 -0700139 Divu,
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700140 La,
Reed Kotler3fe4b572016-02-23 18:59:43 -0800141 Label,
Srdjan Obucina418135a2016-06-02 06:47:06 -0700142 Ldc1,
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700143 Lui,
Srdjan Obucina418135a2016-06-02 06:47:06 -0700144 Lw,
145 Lwc1,
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700146 Mfc1,
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800147 Mfhi,
148 Mflo,
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700149 Mov, // actually a pseudo op for addi rd, rs, 0
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700150 Mov_d,
151 Mov_s,
152 Mtc1,
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800153 Mthi,
154 Mtlo,
Reed Kotler37af5b02015-11-05 17:07:19 -0800155 Mul,
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700156 Mul_d,
157 Mul_s,
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800158 Mult,
159 Multu,
Reed Kotler37af5b02015-11-05 17:07:19 -0800160 Or,
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700161 Ori,
Reed Kotler37af5b02015-11-05 17:07:19 -0800162 Ret,
Srdjan Obucina418135a2016-06-02 06:47:06 -0700163 Sdc1,
Sagar Thakur38dcb592016-05-09 11:57:59 -0700164 Sll,
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -0700165 Sllv,
Sagar Thakur1a478b12016-04-25 08:39:19 -0700166 Slt,
167 Slti,
168 Sltiu,
169 Sltu,
Sagar Thakur38dcb592016-05-09 11:57:59 -0700170 Sra,
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -0700171 Srav,
172 Srl,
173 Srlv,
Reed Kotler37af5b02015-11-05 17:07:19 -0800174 Sub,
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700175 Sub_d,
176 Sub_s,
Reed Kotler00e36042016-02-01 20:52:19 -0800177 Subu,
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700178 Sw,
Srdjan Obucina418135a2016-06-02 06:47:06 -0700179 Swc1,
180 Trunc_l_d,
181 Trunc_l_s,
182 Trunc_w_d,
183 Trunc_w_s,
Sagar Thakur1a478b12016-04-25 08:39:19 -0700184 Xor,
185 Xori
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700186 };
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700187
188 static const char *getWidthString(Type Ty);
189
190 void dump(const Cfg *Func) const override;
191
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700192 void dumpOpcode(Ostream &Str, const char *Opcode, Type Ty) const {
193 Str << Opcode << "." << Ty;
194 }
195
Reed Kotler00e36042016-02-01 20:52:19 -0800196 // TODO(rkotler): while branching is not implemented
197 bool repointEdges(CfgNode *, CfgNode *) override { return true; }
198
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700199 /// Shared emit routines for common forms of instructions.
200 static void emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst,
201 const Cfg *Func);
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800202 static void emitUnaryopGPRFLoHi(const char *Opcode, const InstMIPS32 *Inst,
203 const Cfg *Func);
204 static void emitUnaryopGPRTLoHi(const char *Opcode, const InstMIPS32 *Inst,
205 const Cfg *Func);
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700206 static void emitTwoAddr(const char *Opcode, const InstMIPS32 *Inst,
207 const Cfg *Func);
Reed Kotler37af5b02015-11-05 17:07:19 -0800208 static void emitThreeAddr(const char *Opcode, const InstMIPS32 *Inst,
209 const Cfg *Func);
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800210 static void emitThreeAddrLoHi(const char *Opcode, const InstMIPS32 *Inst,
211 const Cfg *Func);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700212
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700213protected:
214 InstMIPS32(Cfg *Func, InstKindMIPS32 Kind, SizeT Maxsrcs, Variable *Dest)
215 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700216 static bool isClassof(const Inst *Inst, InstKindMIPS32 MyKind) {
217 return Inst->getKind() == static_cast<InstKind>(MyKind);
218 }
219};
220
Andrew Scull57e12682015-09-16 11:30:19 -0700221/// Ret pseudo-instruction. This is actually a "jr" instruction with an "ra"
222/// register operand, but epilogue lowering will search for a Ret instead of a
223/// generic "jr". This instruction also takes a Source operand (for non-void
224/// returning functions) for liveness analysis, though a FakeUse before the ret
225/// would do just as well.
226// TODO(reed kotler): This needs was take from the ARM port and needs to be
227// scrubbed in the future.
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700228class InstMIPS32Ret : public InstMIPS32 {
229
230 InstMIPS32Ret() = delete;
231 InstMIPS32Ret(const InstMIPS32Ret &) = delete;
232 InstMIPS32Ret &operator=(const InstMIPS32Ret &) = delete;
233
234public:
235 static InstMIPS32Ret *create(Cfg *Func, Variable *RA,
236 Variable *Source = nullptr) {
237 return new (Func->allocate<InstMIPS32Ret>())
238 InstMIPS32Ret(Func, RA, Source);
239 }
240 void emit(const Cfg *Func) const override;
241 void emitIAS(const Cfg *Func) const override;
242 void dump(const Cfg *Func) const override;
243 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); }
244
245private:
246 InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source);
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700247};
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700248
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700249/// Instructions of the form x := op(y).
250template <InstMIPS32::InstKindMIPS32 K>
251class InstMIPS32UnaryopGPR : public InstMIPS32 {
252 InstMIPS32UnaryopGPR() = delete;
253 InstMIPS32UnaryopGPR(const InstMIPS32UnaryopGPR &) = delete;
254 InstMIPS32UnaryopGPR &operator=(const InstMIPS32UnaryopGPR &) = delete;
255
256public:
257 static InstMIPS32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src) {
258 return new (Func->allocate<InstMIPS32UnaryopGPR>())
259 InstMIPS32UnaryopGPR(Func, Dest, Src);
260 }
261 void emit(const Cfg *Func) const override {
262 if (!BuildDefs::dump())
263 return;
264 emitUnaryopGPR(Opcode, this, Func);
265 }
266 void emitIAS(const Cfg *Func) const override {
267 (void)Func;
268 llvm_unreachable("Not yet implemented");
269 }
270 void dump(const Cfg *Func) const override {
271 if (!BuildDefs::dump())
272 return;
273 Ostream &Str = Func->getContext()->getStrDump();
274 dumpOpcode(Str, Opcode, getDest()->getType());
275 Str << " ";
276 dumpDest(Func);
277 Str << ", ";
278 dumpSources(Func);
279 }
280 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
281
282protected:
283 InstMIPS32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src)
284 : InstMIPS32(Func, K, 1, Dest) {
285 addSource(Src);
286 }
287
288private:
289 static const char *Opcode;
290};
291
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700292/// Instructions of the form opcode reg, reg.
293template <InstMIPS32::InstKindMIPS32 K>
294class InstMIPS32TwoAddrFPR : public InstMIPS32 {
295 InstMIPS32TwoAddrFPR() = delete;
296 InstMIPS32TwoAddrFPR(const InstMIPS32TwoAddrFPR &) = delete;
297 InstMIPS32TwoAddrFPR &operator=(const InstMIPS32TwoAddrFPR &) = delete;
298
299public:
300 static InstMIPS32TwoAddrFPR *create(Cfg *Func, Variable *Dest,
301 Variable *Src0) {
302 return new (Func->allocate<InstMIPS32TwoAddrFPR>())
303 InstMIPS32TwoAddrFPR(Func, Dest, Src0);
304 }
305 void emit(const Cfg *Func) const override {
306 if (!BuildDefs::dump())
307 return;
308 emitTwoAddr(Opcode, this, Func);
309 }
310 void emitIAS(const Cfg *Func) const override {
311 (void)Func;
312 llvm_unreachable("Not yet implemented");
313 }
314
315 void dump(const Cfg *Func) const override {
316 if (!BuildDefs::dump())
317 return;
318 Ostream &Str = Func->getContext()->getStrDump();
319 dumpDest(Func);
320 Str << " = ";
321 dumpOpcode(Str, Opcode, getDest()->getType());
322 Str << " ";
323 dumpSources(Func);
324 }
325 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
326
327private:
328 InstMIPS32TwoAddrFPR(Cfg *Func, Variable *Dest, Variable *Src0)
329 : InstMIPS32(Func, K, 1, Dest) {
330 addSource(Src0);
331 }
332
333 static const char *Opcode;
334};
335
336/// Instructions of the form opcode reg, reg.
337template <InstMIPS32::InstKindMIPS32 K>
338class InstMIPS32TwoAddrGPR : public InstMIPS32 {
339 InstMIPS32TwoAddrGPR() = delete;
340 InstMIPS32TwoAddrGPR(const InstMIPS32TwoAddrGPR &) = delete;
341 InstMIPS32TwoAddrGPR &operator=(const InstMIPS32TwoAddrGPR &) = delete;
342
343public:
344 static InstMIPS32TwoAddrGPR *create(Cfg *Func, Variable *Dest,
345 Variable *Src0) {
346 return new (Func->allocate<InstMIPS32TwoAddrGPR>())
347 InstMIPS32TwoAddrGPR(Func, Dest, Src0);
348 }
349 void emit(const Cfg *Func) const override {
350 if (!BuildDefs::dump())
351 return;
352 emitTwoAddr(Opcode, this, Func);
353 }
354 void emitIAS(const Cfg *Func) const override {
355 (void)Func;
356 llvm_unreachable("Not yet implemented");
357 }
358
359 void dump(const Cfg *Func) const override {
360 if (!BuildDefs::dump())
361 return;
362 Ostream &Str = Func->getContext()->getStrDump();
363 dumpDest(Func);
364 Str << " = ";
365 dumpOpcode(Str, Opcode, getDest()->getType());
366 Str << " ";
367 dumpSources(Func);
368 }
369 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
370
371private:
372 InstMIPS32TwoAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0)
373 : InstMIPS32(Func, K, 1, Dest) {
374 addSource(Src0);
375 }
376
377 static const char *Opcode;
378};
379
380/// Instructions of the form x := y op z. May have the side-effect of setting
381/// status flags.
382template <InstMIPS32::InstKindMIPS32 K>
383class InstMIPS32ThreeAddrFPR : public InstMIPS32 {
384 InstMIPS32ThreeAddrFPR() = delete;
385 InstMIPS32ThreeAddrFPR(const InstMIPS32ThreeAddrFPR &) = delete;
386 InstMIPS32ThreeAddrFPR &operator=(const InstMIPS32ThreeAddrFPR &) = delete;
387
388public:
389 /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
390 /// must be registers.
391 static InstMIPS32ThreeAddrFPR *create(Cfg *Func, Variable *Dest,
392 Variable *Src0, Variable *Src1) {
393 return new (Func->allocate<InstMIPS32ThreeAddrFPR>())
394 InstMIPS32ThreeAddrFPR(Func, Dest, Src0, Src1);
395 }
396 void emit(const Cfg *Func) const override {
397 if (!BuildDefs::dump())
398 return;
399 emitThreeAddr(Opcode, this, Func);
400 }
401 void emitIAS(const Cfg *Func) const override {
402 (void)Func;
403 llvm_unreachable("Not yet implemented");
404 }
405
406 void dump(const Cfg *Func) const override {
407 if (!BuildDefs::dump())
408 return;
409 Ostream &Str = Func->getContext()->getStrDump();
410 dumpDest(Func);
411 Str << " = ";
412 dumpOpcode(Str, Opcode, getDest()->getType());
413 Str << " ";
414 dumpSources(Func);
415 }
416 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
417
418private:
419 InstMIPS32ThreeAddrFPR(Cfg *Func, Variable *Dest, Variable *Src0,
420 Variable *Src1)
421 : InstMIPS32(Func, K, 2, Dest) {
422 addSource(Src0);
423 addSource(Src1);
424 }
425
426 static const char *Opcode;
427};
428
Reed Kotler37af5b02015-11-05 17:07:19 -0800429/// Instructions of the form x := y op z. May have the side-effect of setting
430/// status flags.
431template <InstMIPS32::InstKindMIPS32 K>
432class InstMIPS32ThreeAddrGPR : public InstMIPS32 {
433 InstMIPS32ThreeAddrGPR() = delete;
434 InstMIPS32ThreeAddrGPR(const InstMIPS32ThreeAddrGPR &) = delete;
435 InstMIPS32ThreeAddrGPR &operator=(const InstMIPS32ThreeAddrGPR &) = delete;
436
437public:
438 /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
439 /// must be registers.
440 static InstMIPS32ThreeAddrGPR *create(Cfg *Func, Variable *Dest,
441 Variable *Src0, Variable *Src1) {
442 return new (Func->allocate<InstMIPS32ThreeAddrGPR>())
443 InstMIPS32ThreeAddrGPR(Func, Dest, Src0, Src1);
444 }
445 void emit(const Cfg *Func) const override {
446 if (!BuildDefs::dump())
447 return;
448 emitThreeAddr(Opcode, this, Func);
449 }
450 void emitIAS(const Cfg *Func) const override {
451 (void)Func;
452 llvm_unreachable("Not yet implemented");
453 }
454
455 void dump(const Cfg *Func) const override {
456 if (!BuildDefs::dump())
457 return;
458 Ostream &Str = Func->getContext()->getStrDump();
459 dumpDest(Func);
460 Str << " = ";
461 dumpOpcode(Str, Opcode, getDest()->getType());
462 Str << " ";
463 dumpSources(Func);
464 }
465 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
466
467private:
468 InstMIPS32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
469 Variable *Src1)
470 : InstMIPS32(Func, K, 2, Dest) {
471 addSource(Src0);
472 addSource(Src1);
473 }
474
475 static const char *Opcode;
476};
477
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700478// InstMIPS32Memory represents instructions which loads/stores data on memory
479// Its format is "OPCODE GPR, OFFSET(BASE GPR)"
480template <InstMIPS32::InstKindMIPS32 K>
481class InstMIPS32Memory : public InstMIPS32 {
482 InstMIPS32Memory() = delete;
483 InstMIPS32Memory(const InstMIPS32Memory &) = delete;
484 InstMIPS32Memory &operator=(const InstMIPS32Memory &) = delete;
485
486public:
487 static InstMIPS32Memory *create(Cfg *Func, Variable *Value,
488 OperandMIPS32Mem *Mem) {
489 return new (Func->allocate<InstMIPS32Memory>())
490 InstMIPS32Memory(Func, Value, Mem);
491 }
492
493 void emit(const Cfg *Func) const override {
494 if (!BuildDefs::dump())
495 return;
496 Ostream &Str = Func->getContext()->getStrEmit();
497 assert(getSrcSize() == 2);
498 Str << "\t" << Opcode << "\t";
499 getSrc(0)->emit(Func);
500 Str << ", ";
501 getSrc(1)->emit(Func);
502 }
503
504 void emitIAS(const Cfg *Func) const override {
505 (void)Func;
506 llvm_unreachable("Not yet implemented");
507 }
508
509 void dump(const Cfg *Func) const override {
510 if (!BuildDefs::dump())
511 return;
512 Ostream &Str = Func->getContext()->getStrDump();
513 Str << "\t" << Opcode << "\t";
514 Str << " ";
515 getSrc(1)->dump(Func);
516 Str << ", ";
517 getSrc(0)->dump(Func);
518 }
519 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
520
521private:
522 InstMIPS32Memory(Cfg *Func, Variable *Value, OperandMIPS32Mem *Mem)
523 : InstMIPS32(Func, K, 2, nullptr) {
524 addSource(Value);
525 addSource(Mem);
526 }
527 static const char *Opcode;
528};
529
Reed Kotler3fe4b572016-02-23 18:59:43 -0800530// InstMIPS32Label represents an intra-block label that is the target of an
531// intra-block branch. The offset between the label and the branch must be fit
532// in the instruction immediate (considered "near").
533class InstMIPS32Label : public InstMIPS32 {
534 InstMIPS32Label() = delete;
535 InstMIPS32Label(const InstMIPS32Label &) = delete;
536 InstMIPS32Label &operator=(const InstMIPS32Label &) = delete;
537
538public:
539 static InstMIPS32Label *create(Cfg *Func, TargetMIPS32 *Target) {
540 return new (Func->allocate<InstMIPS32Label>())
541 InstMIPS32Label(Func, Target);
542 }
543 uint32_t getEmitInstCount() const override { return 0; }
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700544 GlobalString getLabelName() const { return Name; }
Reed Kotler3fe4b572016-02-23 18:59:43 -0800545 SizeT getNumber() const { return Number; }
546 void emit(const Cfg *Func) const override;
547 void emitIAS(const Cfg *Func) const override;
548 void dump(const Cfg *Func) const override;
549
550 static bool classof(const Inst *Instr) { return isClassof(Instr, Label); }
551
552private:
553 InstMIPS32Label(Cfg *Func, TargetMIPS32 *Target);
554
Jim Stichnoth09802a92016-02-24 07:05:12 -0800555 // RelocOffset *OffsetReloc = nullptr;
Reed Kotler3fe4b572016-02-23 18:59:43 -0800556 SizeT Number; // used for unique label generation.
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700557 GlobalString Name;
Reed Kotler3fe4b572016-02-23 18:59:43 -0800558};
559
560/// Direct branch instruction.
561class InstMIPS32Br : public InstMIPS32 {
562 InstMIPS32Br() = delete;
563 InstMIPS32Br(const InstMIPS32Br &) = delete;
564 InstMIPS32Br &operator=(const InstMIPS32Br &) = delete;
565
566public:
567 /// Create an unconditional branch to a node.
568 static InstMIPS32Br *create(Cfg *Func, CfgNode *Target) {
569 constexpr CfgNode *NoCondTarget = nullptr;
570 constexpr InstMIPS32Label *NoLabel = nullptr;
571 return new (Func->allocate<InstMIPS32Br>())
Sagar Thakur5cce7612016-05-24 06:25:50 -0700572 InstMIPS32Br(Func, NoCondTarget, Target, NoLabel, CondMIPS32::AL);
Reed Kotler3fe4b572016-02-23 18:59:43 -0800573 }
Sagar Thakur5cce7612016-05-24 06:25:50 -0700574
575 /// Create a conditional branch to the false node.
576 static InstMIPS32Br *create(Cfg *Func, CfgNode *TargetTrue,
577 CfgNode *TargetFalse, Operand *Src0,
578 Operand *Src1, CondMIPS32::Cond Cond) {
579 constexpr InstMIPS32Label *NoLabel = nullptr;
580 return new (Func->allocate<InstMIPS32Br>())
581 InstMIPS32Br(Func, TargetTrue, TargetFalse, Src0, Src1, NoLabel, Cond);
582 }
583
584 static InstMIPS32Br *create(Cfg *Func, CfgNode *TargetTrue,
585 CfgNode *TargetFalse, Operand *Src0,
586 CondMIPS32::Cond Cond) {
587 constexpr InstMIPS32Label *NoLabel = nullptr;
588 return new (Func->allocate<InstMIPS32Br>())
589 InstMIPS32Br(Func, TargetTrue, TargetFalse, Src0, NoLabel, Cond);
590 }
591
Reed Kotler3fe4b572016-02-23 18:59:43 -0800592 const CfgNode *getTargetTrue() const { return TargetTrue; }
593 const CfgNode *getTargetFalse() const { return TargetFalse; }
594
Sagar Thakur5cce7612016-05-24 06:25:50 -0700595 bool isUnconditionalBranch() const override {
596 return Predicate == CondMIPS32::AL;
597 }
Reed Kotler3fe4b572016-02-23 18:59:43 -0800598 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override {
599 (void)OldNode;
600 (void)NewNode;
601 return true;
602 };
603 void emit(const Cfg *Func) const override;
604 void emitIAS(const Cfg *Func) const override { (void)Func; };
Sagar Thakur5cce7612016-05-24 06:25:50 -0700605 void dump(const Cfg *Func) const override;
Reed Kotler3fe4b572016-02-23 18:59:43 -0800606 static bool classof(const Inst *Instr) { return isClassof(Instr, Br); }
607
608private:
609 InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
Sagar Thakur5cce7612016-05-24 06:25:50 -0700610 const InstMIPS32Label *Label, const CondMIPS32::Cond Cond);
611
612 InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
613 Operand *Src0, const InstMIPS32Label *Label,
614 const CondMIPS32::Cond Cond);
615
616 InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
617 Operand *Src0, Operand *Src1, const InstMIPS32Label *Label,
618 const CondMIPS32::Cond Cond);
Reed Kotler3fe4b572016-02-23 18:59:43 -0800619
620 const CfgNode *TargetTrue;
621 const CfgNode *TargetFalse;
622 const InstMIPS32Label *Label; // Intra-block branch target
Sagar Thakur5cce7612016-05-24 06:25:50 -0700623 const CondMIPS32::Cond Predicate;
Reed Kotler3fe4b572016-02-23 18:59:43 -0800624};
625
Reed Kotler00e36042016-02-01 20:52:19 -0800626class InstMIPS32Call : public InstMIPS32 {
627 InstMIPS32Call() = delete;
628 InstMIPS32Call(const InstMIPS32Call &) = delete;
629 InstMIPS32Call &operator=(const InstMIPS32Call &) = delete;
630
631public:
632 static InstMIPS32Call *create(Cfg *Func, Variable *Dest,
633 Operand *CallTarget) {
634 return new (Func->allocate<InstMIPS32Call>())
635 InstMIPS32Call(Func, Dest, CallTarget);
636 }
637 Operand *getCallTarget() const { return getSrc(0); }
638 void emit(const Cfg *Func) const override;
639 void emitIAS(const Cfg *Func) const override;
640 void dump(const Cfg *Func) const override;
641 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); }
642
643private:
644 InstMIPS32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
645};
646
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700647template <InstMIPS32::InstKindMIPS32 K, bool Signed = false>
648class InstMIPS32Imm16 : public InstMIPS32 {
649 InstMIPS32Imm16() = delete;
650 InstMIPS32Imm16(const InstMIPS32Imm16 &) = delete;
651 InstMIPS32Imm16 &operator=(const InstMIPS32Imm16 &) = delete;
652
653public:
654 static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, Operand *Source,
655 uint32_t Imm) {
656 return new (Func->allocate<InstMIPS32Imm16>())
657 InstMIPS32Imm16(Func, Dest, Source, Imm);
658 }
659
660 static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, uint32_t Imm) {
661 return new (Func->allocate<InstMIPS32Imm16>())
662 InstMIPS32Imm16(Func, Dest, Imm);
663 }
664
665 void emit(const Cfg *Func) const override {
666 if (!BuildDefs::dump())
667 return;
668 Ostream &Str = Func->getContext()->getStrEmit();
669 Str << "\t" << Opcode << "\t";
670 getDest()->emit(Func);
671 if (getSrcSize() > 0) {
672 Str << ", ";
673 getSrc(0)->emit(Func);
674 }
675 Str << ", ";
676 if (Signed)
677 Str << (int32_t)Imm;
678 else
679 Str << Imm;
680 Str << "\n";
681 }
682
683 void emitIAS(const Cfg *Func) const override {
684 (void)Func;
685 llvm_unreachable("Not yet implemented");
686 }
687 void dump(const Cfg *Func) const override {
688 if (!BuildDefs::dump())
689 return;
690 Ostream &Str = Func->getContext()->getStrDump();
691 Str << " ";
692 Str << "\t" << Opcode << "\t";
693 dumpDest(Func);
694 Str << ", ";
695 dumpSources(Func);
696 if (Signed)
697 Str << (int32_t)Imm;
698 else
699 Str << Imm;
700 Str << "\n";
701 }
702
703 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
704
705private:
706 InstMIPS32Imm16(Cfg *Func, Variable *Dest, Operand *Source, uint32_t Imm)
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700707 : InstMIPS32(Func, K, 1, Dest), Imm(Imm) {
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700708 addSource(Source);
709 }
710
711 InstMIPS32Imm16(Cfg *Func, Variable *Dest, uint32_t Imm)
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700712 : InstMIPS32(Func, K, 0, Dest), Imm(Imm) {}
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700713
714 static const char *Opcode;
715
716 const uint32_t Imm;
717};
718
Reed Kotler37af5b02015-11-05 17:07:19 -0800719using InstMIPS32Add = InstMIPS32ThreeAddrGPR<InstMIPS32::Add>;
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700720using InstMIPS32Add_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Add_d>;
721using InstMIPS32Add_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Add_s>;
Reed Kotler00e36042016-02-01 20:52:19 -0800722using InstMIPS32Addu = InstMIPS32ThreeAddrGPR<InstMIPS32::Addu>;
Reed Kotler37af5b02015-11-05 17:07:19 -0800723using InstMIPS32Addiu = InstMIPS32Imm16<InstMIPS32::Addiu, true>;
724using InstMIPS32And = InstMIPS32ThreeAddrGPR<InstMIPS32::And>;
Sagar Thakur38dcb592016-05-09 11:57:59 -0700725using InstMIPS32Andi = InstMIPS32Imm16<InstMIPS32::Andi>;
Srdjan Obucina418135a2016-06-02 06:47:06 -0700726using InstMIPS32Cvt_d_s = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_d_s>;
727using InstMIPS32Cvt_d_l = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_d_l>;
728using InstMIPS32Cvt_d_w = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_d_w>;
729using InstMIPS32Cvt_s_d = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_d>;
730using InstMIPS32Cvt_s_l = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_l>;
731using InstMIPS32Cvt_s_w = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_w>;
Srdjan Obucinaae93eee2016-05-18 11:31:15 -0700732using InstMIPS32Div = InstMIPS32ThreeAddrGPR<InstMIPS32::Div>;
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700733using InstMIPS32Div_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Div_d>;
734using InstMIPS32Div_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Div_s>;
Srdjan Obucinaae93eee2016-05-18 11:31:15 -0700735using InstMIPS32Divu = InstMIPS32ThreeAddrGPR<InstMIPS32::Divu>;
Reed Kotler37af5b02015-11-05 17:07:19 -0800736using InstMIPS32La = InstMIPS32UnaryopGPR<InstMIPS32::La>;
Srdjan Obucina418135a2016-06-02 06:47:06 -0700737using InstMIPS32Ldc1 = InstMIPS32Memory<InstMIPS32::Ldc1>;
738using InstMIPS32Lui = InstMIPS32Imm16<InstMIPS32::Lui>;
Sagar Thakur633394c2016-06-25 08:34:10 -0700739using InstMIPS32Lw = InstMIPS32Memory<InstMIPS32::Lw>;
Srdjan Obucina418135a2016-06-02 06:47:06 -0700740using InstMIPS32Lwc1 = InstMIPS32Memory<InstMIPS32::Lwc1>;
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700741using InstMIPS32Mfc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mfc1>;
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800742using InstMIPS32Mfhi = InstMIPS32UnaryopGPR<InstMIPS32::Mfhi>;
743using InstMIPS32Mflo = InstMIPS32UnaryopGPR<InstMIPS32::Mflo>;
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700744using InstMIPS32Mov_d = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_d>;
745using InstMIPS32Mov_s = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_s>;
746using InstMIPS32Mtc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mtc1>;
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800747using InstMIPS32Mthi = InstMIPS32UnaryopGPR<InstMIPS32::Mthi>;
748using InstMIPS32Mtlo = InstMIPS32UnaryopGPR<InstMIPS32::Mtlo>;
Reed Kotler37af5b02015-11-05 17:07:19 -0800749using InstMIPS32Mul = InstMIPS32ThreeAddrGPR<InstMIPS32::Mul>;
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700750using InstMIPS32Mul_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Mul_d>;
751using InstMIPS32Mul_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Mul_s>;
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800752using InstMIPS32Mult = InstMIPS32ThreeAddrGPR<InstMIPS32::Mult>;
753using InstMIPS32Multu = InstMIPS32ThreeAddrGPR<InstMIPS32::Multu>;
Reed Kotler37af5b02015-11-05 17:07:19 -0800754using InstMIPS32Or = InstMIPS32ThreeAddrGPR<InstMIPS32::Or>;
755using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>;
Srdjan Obucina418135a2016-06-02 06:47:06 -0700756using InstMIPS32Sdc1 = InstMIPS32Memory<InstMIPS32::Sdc1>;
Sagar Thakur38dcb592016-05-09 11:57:59 -0700757using InstMIPS32Sll = InstMIPS32Imm16<InstMIPS32::Sll>;
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -0700758using InstMIPS32Sllv = InstMIPS32ThreeAddrGPR<InstMIPS32::Sllv>;
Sagar Thakur1a478b12016-04-25 08:39:19 -0700759using InstMIPS32Slt = InstMIPS32ThreeAddrGPR<InstMIPS32::Slt>;
760using InstMIPS32Slti = InstMIPS32Imm16<InstMIPS32::Slti>;
761using InstMIPS32Sltiu = InstMIPS32Imm16<InstMIPS32::Sltiu>;
Reed Kotler00e36042016-02-01 20:52:19 -0800762using InstMIPS32Sltu = InstMIPS32ThreeAddrGPR<InstMIPS32::Sltu>;
Sagar Thakur38dcb592016-05-09 11:57:59 -0700763using InstMIPS32Sra = InstMIPS32Imm16<InstMIPS32::Sra>;
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -0700764using InstMIPS32Srav = InstMIPS32ThreeAddrGPR<InstMIPS32::Srav>;
765using InstMIPS32Srl = InstMIPS32Imm16<InstMIPS32::Srl>;
766using InstMIPS32Srlv = InstMIPS32ThreeAddrGPR<InstMIPS32::Srlv>;
Reed Kotler37af5b02015-11-05 17:07:19 -0800767using InstMIPS32Sub = InstMIPS32ThreeAddrGPR<InstMIPS32::Sub>;
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700768using InstMIPS32Sub_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Sub_d>;
769using InstMIPS32Sub_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Sub_s>;
Reed Kotler00e36042016-02-01 20:52:19 -0800770using InstMIPS32Subu = InstMIPS32ThreeAddrGPR<InstMIPS32::Subu>;
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700771using InstMIPS32Sw = InstMIPS32Memory<InstMIPS32::Sw>;
Srdjan Obucina418135a2016-06-02 06:47:06 -0700772using InstMIPS32Swc1 = InstMIPS32Memory<InstMIPS32::Swc1>;
773using InstMIPS32Trunc_l_d = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_l_d>;
774using InstMIPS32Trunc_l_s = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_l_s>;
775using InstMIPS32Trunc_w_d = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_w_d>;
776using InstMIPS32Trunc_w_s = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_w_s>;
Reed Kotler37af5b02015-11-05 17:07:19 -0800777using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>;
778using InstMIPS32Xor = InstMIPS32ThreeAddrGPR<InstMIPS32::Xor>;
Sagar Thakur1a478b12016-04-25 08:39:19 -0700779using InstMIPS32Xori = InstMIPS32Imm16<InstMIPS32::Xori>;
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700780
781/// Handles (some of) vmov's various formats.
782class InstMIPS32Mov final : public InstMIPS32 {
783 InstMIPS32Mov() = delete;
784 InstMIPS32Mov(const InstMIPS32Mov &) = delete;
785 InstMIPS32Mov &operator=(const InstMIPS32Mov &) = delete;
786
787public:
788 static InstMIPS32Mov *create(Cfg *Func, Variable *Dest, Operand *Src) {
789 return new (Func->allocate<InstMIPS32Mov>()) InstMIPS32Mov(Func, Dest, Src);
790 }
791 bool isRedundantAssign() const override {
792 return !isMultiDest() && !isMultiSource() &&
793 checkForRedundantAssign(getDest(), getSrc(0));
794 }
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700795 // bool isSimpleAssign() const override { return true; }
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700796 void emit(const Cfg *Func) const override;
797 void emitIAS(const Cfg *Func) const override;
798 void dump(const Cfg *Func) const override;
799 static bool classof(const Inst *Inst) { return isClassof(Inst, Mov); }
800
801 bool isMultiDest() const { return DestHi != nullptr; }
802
803 bool isMultiSource() const {
804 assert(getSrcSize() == 1 || getSrcSize() == 2);
805 return getSrcSize() == 2;
806 }
807
808 Variable *getDestHi() const { return DestHi; }
809
810private:
811 InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src);
812
813 void emitMultiDestSingleSource(const Cfg *Func) const;
814 void emitSingleDestMultiSource(const Cfg *Func) const;
815 void emitSingleDestSingleSource(const Cfg *Func) const;
816
817 Variable *DestHi = nullptr;
818};
819
Jim Stichnoth8159aae2016-02-25 00:13:46 -0800820// Declare partial template specializations of emit() methods that already have
821// default implementations. Without this, there is the possibility of ODR
822// violations and link errors.
823
824template <> void InstMIPS32Mflo::emit(const Cfg *Func) const;
825template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const;
826template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const;
827template <> void InstMIPS32Mthi::emit(const Cfg *Func) const;
828template <> void InstMIPS32Mult::emit(const Cfg *Func) const;
829template <> void InstMIPS32Multu::emit(const Cfg *Func) const;
830
John Porto4a566862016-01-04 09:33:41 -0800831} // end of namespace MIPS32
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700832} // end of namespace Ice
833
834#endif // SUBZERO_SRC_ICEINSTMIPS32_H