1 //===- 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 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \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.
16 ///
17 //===----------------------------------------------------------------------===//
18
19 #ifndef SUBZERO_SRC_ICEINSTMIPS32_H
20 #define SUBZERO_SRC_ICEINSTMIPS32_H
21
22 #include "IceConditionCodesMIPS32.h"
23 #include "IceDefs.h"
24 #include "IceInst.h"
25 #include "IceInstMIPS32.def"
26 #include "IceOperand.h"
27
28 namespace Ice {
29 namespace MIPS32 {
30
31 enum RelocOp { RO_No, RO_Hi, RO_Lo, RO_Jal };
32 enum Int64Part { Int64_Hi, Int64_Lo };
33
emitRelocOp(Ostream & Str,RelocOp Reloc)34 inline void emitRelocOp(Ostream &Str, RelocOp Reloc) {
35 switch (Reloc) {
36 default:
37 break;
38 case RO_Hi:
39 Str << "%hi";
40 break;
41 case RO_Lo:
42 Str << "%lo";
43 break;
44 }
45 }
46
47 class TargetMIPS32;
48
49 /// OperandMips32 extends the Operand hierarchy.
50 //
51 class OperandMIPS32 : public Operand {
52 OperandMIPS32() = delete;
53 OperandMIPS32(const OperandMIPS32 &) = delete;
54 OperandMIPS32 &operator=(const OperandMIPS32 &) = delete;
55
56 public:
57 enum OperandKindMIPS32 {
58 k__Start = Operand::kTarget,
59 kFCC,
60 kMem,
61 };
62
63 using Operand::dump;
dump(const Cfg *,Ostream & Str)64 void dump(const Cfg *, Ostream &Str) const override {
65 if (BuildDefs::dump())
66 Str << "<OperandMIPS32>";
67 }
68
69 protected:
OperandMIPS32(OperandKindMIPS32 Kind,Type Ty)70 OperandMIPS32(OperandKindMIPS32 Kind, Type Ty)
71 : Operand(static_cast<OperandKind>(Kind), Ty) {}
72 };
73
74 class OperandMIPS32FCC : public OperandMIPS32 {
75 OperandMIPS32FCC() = delete;
76 OperandMIPS32FCC(const OperandMIPS32FCC &) = delete;
77 OperandMIPS32FCC &operator=(const OperandMIPS32FCC &) = delete;
78
79 public:
80 using FCC = enum { FCC0 = 0, FCC1, FCC2, FCC3, FCC4, FCC5, FCC6, FCC7 };
create(Cfg * Func,OperandMIPS32FCC::FCC FCC)81 static OperandMIPS32FCC *create(Cfg *Func, OperandMIPS32FCC::FCC FCC) {
82 return new (Func->allocate<OperandMIPS32FCC>()) OperandMIPS32FCC(FCC);
83 }
84
getFCC()85 OperandMIPS32FCC::FCC getFCC() const { return FpCondCode; }
86
emit(const Cfg * Func)87 void emit(const Cfg *Func) const override {
88 if (!BuildDefs::dump())
89 return;
90 Ostream &Str = Func->getContext()->getStrEmit();
91 Str << "$fcc" << static_cast<uint16_t>(FpCondCode);
92 }
93
classof(const Operand * Operand)94 static bool classof(const Operand *Operand) {
95 return Operand->getKind() == static_cast<OperandKind>(kFCC);
96 }
97
dump(const Cfg * Func,Ostream & Str)98 void dump(const Cfg *Func, Ostream &Str) const override {
99 if (!BuildDefs::dump())
100 return;
101 (void)Func;
102 Str << "$fcc" << static_cast<uint16_t>(FpCondCode);
103 }
104
105 private:
OperandMIPS32FCC(OperandMIPS32FCC::FCC CC)106 OperandMIPS32FCC(OperandMIPS32FCC::FCC CC)
107 : OperandMIPS32(kFCC, IceType_i32), FpCondCode(CC){};
108
109 const OperandMIPS32FCC::FCC FpCondCode;
110 };
111
112 class OperandMIPS32Mem : public OperandMIPS32 {
113 OperandMIPS32Mem() = delete;
114 OperandMIPS32Mem(const OperandMIPS32Mem &) = delete;
115 OperandMIPS32Mem &operator=(const OperandMIPS32Mem &) = delete;
116
117 public:
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,
130 Operand *ImmOffset, AddrMode Mode = Offset) {
131 return new (Func->allocate<OperandMIPS32Mem>())
132 OperandMIPS32Mem(Func, Ty, Base, ImmOffset, Mode);
133 }
134
getBase()135 Variable *getBase() const { return Base; }
getOffset()136 Operand *getOffset() const { return ImmOffset; }
getAddrMode()137 AddrMode getAddrMode() const { return Mode; }
138
139 void emit(const Cfg *Func) const override;
140 using OperandMIPS32::dump;
141
classof(const Operand * Operand)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
dump(const Cfg * Func,Ostream & Str)152 void dump(const Cfg *Func, Ostream &Str) const override {
153 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 }
168 }
169
170 private:
171 OperandMIPS32Mem(Cfg *Func, Type Ty, Variable *Base, Operand *ImmOffset,
172 AddrMode Mode);
173
174 Variable *Base;
175 Operand *const ImmOffset;
176 const AddrMode Mode;
177 };
178
179 /// Base class for Mips instructions.
180 class InstMIPS32 : public InstTarget {
181 InstMIPS32() = delete;
182 InstMIPS32(const InstMIPS32 &) = delete;
183 InstMIPS32 &operator=(const InstMIPS32 &) = delete;
184
185 public:
186 enum InstKindMIPS32 {
187 k__Start = Inst::Target,
188 Abs_d,
189 Abs_s,
190 Add,
191 Add_d,
192 Add_s,
193 Addi,
194 Addiu,
195 Addu,
196 And,
197 Andi,
198 Br,
199 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,
213 Call,
214 Clz,
215 Cvt_d_l,
216 Cvt_d_s,
217 Cvt_d_w,
218 Cvt_s_d,
219 Cvt_s_l,
220 Cvt_s_w,
221 Div,
222 Div_d,
223 Div_s,
224 Divu,
225 La,
226 Label,
227 Ldc1,
228 Ll,
229 Lui,
230 Lw,
231 Lwc1,
232 Mfc1,
233 Mfhi,
234 Mflo,
235 Mov, // actually a pseudo op for addi rd, rs, 0
236 Mov_fp,
237 Mov_d,
238 Mov_s,
239 Movf,
240 Movn,
241 Movn_d,
242 Movn_s,
243 Movt,
244 Movz,
245 Movz_d,
246 Movz_s,
247 Mtc1,
248 Mthi,
249 Mtlo,
250 Mul,
251 Mul_d,
252 Mul_s,
253 Mult,
254 Multu,
255 Nor,
256 Or,
257 Ori,
258 Ret,
259 Sc,
260 Sdc1,
261 Sll,
262 Sllv,
263 Slt,
264 Slti,
265 Sltiu,
266 Sltu,
267 Sra,
268 Srav,
269 Srl,
270 Srlv,
271 Sqrt_d,
272 Sqrt_s,
273 Sub,
274 Sub_d,
275 Sub_s,
276 Subu,
277 Sw,
278 Swc1,
279 Sync,
280 Teq,
281 Trunc_l_d,
282 Trunc_l_s,
283 Trunc_w_d,
284 Trunc_w_s,
285 Xor,
286 Xori
287 };
288
289 static constexpr size_t InstSize = sizeof(uint32_t);
290
291 static const char *getWidthString(Type Ty);
292
293 CondMIPS32::Cond getOppositeCondition(CondMIPS32::Cond Cond);
294
295 void dump(const Cfg *Func) const override;
296
dumpOpcode(Ostream & Str,const char * Opcode,Type Ty)297 void dumpOpcode(Ostream &Str, const char *Opcode, Type Ty) const {
298 Str << Opcode << "." << Ty;
299 }
300
301 // TODO(rkotler): while branching is not implemented
repointEdges(CfgNode *,CfgNode *)302 bool repointEdges(CfgNode *, CfgNode *) override { return true; }
303
304 /// Shared emit routines for common forms of instructions.
305 static void emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst,
306 const Cfg *Func);
307 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);
311 static void emitTwoAddr(const char *Opcode, const InstMIPS32 *Inst,
312 const Cfg *Func);
313 static void emitThreeAddr(const char *Opcode, const InstMIPS32 *Inst,
314 const Cfg *Func);
315 static void emitThreeAddrLoHi(const char *Opcode, const InstMIPS32 *Inst,
316 const Cfg *Func);
317
318 protected:
InstMIPS32(Cfg * Func,InstKindMIPS32 Kind,SizeT Maxsrcs,Variable * Dest)319 InstMIPS32(Cfg *Func, InstKindMIPS32 Kind, SizeT Maxsrcs, Variable *Dest)
320 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
isClassof(const Inst * Inst,InstKindMIPS32 MyKind)321 static bool isClassof(const Inst *Inst, InstKindMIPS32 MyKind) {
322 return Inst->getKind() == static_cast<InstKind>(MyKind);
323 }
324 };
325
326 /// 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.
333 class InstMIPS32Ret : public InstMIPS32 {
334
335 InstMIPS32Ret() = delete;
336 InstMIPS32Ret(const InstMIPS32Ret &) = delete;
337 InstMIPS32Ret &operator=(const InstMIPS32Ret &) = delete;
338
339 public:
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;
classof(const Inst * Inst)348 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); }
349
350 private:
351 InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source);
352 };
353
354 /// Instructions of the form x := op(y).
355 template <InstMIPS32::InstKindMIPS32 K>
356 class InstMIPS32UnaryopGPR : public InstMIPS32 {
357 InstMIPS32UnaryopGPR() = delete;
358 InstMIPS32UnaryopGPR(const InstMIPS32UnaryopGPR &) = delete;
359 InstMIPS32UnaryopGPR &operator=(const InstMIPS32UnaryopGPR &) = delete;
360
361 public:
362 static InstMIPS32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
363 RelocOp Reloc = RO_No) {
364 return new (Func->allocate<InstMIPS32UnaryopGPR>())
365 InstMIPS32UnaryopGPR(Func, Dest, Src, Reloc);
366 }
emit(const Cfg * Func)367 void emit(const Cfg *Func) const override {
368 if (!BuildDefs::dump())
369 return;
370 emitUnaryopGPR(Opcode, this, Func);
371 }
emitIAS(const Cfg * Func)372 void emitIAS(const Cfg *Func) const override {
373 (void)Func;
374 llvm_unreachable("Not yet implemented");
375 }
dump(const Cfg * Func)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 }
classof(const Inst * Inst)386 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
387
388 protected:
389 InstMIPS32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src,
390 RelocOp Reloc = RO_No)
391 : InstMIPS32(Func, K, 1, Dest), Reloc(Reloc) {
392 addSource(Src);
393 }
394
395 private:
396 static const char *Opcode;
397 const RelocOp Reloc;
398 };
399
400 /// Instructions of the form opcode reg, reg.
401 template <InstMIPS32::InstKindMIPS32 K>
402 class InstMIPS32TwoAddrFPR : public InstMIPS32 {
403 InstMIPS32TwoAddrFPR() = delete;
404 InstMIPS32TwoAddrFPR(const InstMIPS32TwoAddrFPR &) = delete;
405 InstMIPS32TwoAddrFPR &operator=(const InstMIPS32TwoAddrFPR &) = delete;
406
407 public:
create(Cfg * Func,Variable * Dest,Variable * Src0)408 static InstMIPS32TwoAddrFPR *create(Cfg *Func, Variable *Dest,
409 Variable *Src0) {
410 return new (Func->allocate<InstMIPS32TwoAddrFPR>())
411 InstMIPS32TwoAddrFPR(Func, Dest, Src0);
412 }
emit(const Cfg * Func)413 void emit(const Cfg *Func) const override {
414 if (!BuildDefs::dump())
415 return;
416 emitTwoAddr(Opcode, this, Func);
417 }
emitIAS(const Cfg * Func)418 void emitIAS(const Cfg *Func) const override {
419 (void)Func;
420 llvm_unreachable("Not yet implemented");
421 }
422
dump(const Cfg * Func)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 }
classof(const Inst * Inst)433 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
434
435 private:
InstMIPS32TwoAddrFPR(Cfg * Func,Variable * Dest,Variable * Src0)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.
445 template <InstMIPS32::InstKindMIPS32 K>
446 class InstMIPS32TwoAddrGPR : public InstMIPS32 {
447 InstMIPS32TwoAddrGPR() = delete;
448 InstMIPS32TwoAddrGPR(const InstMIPS32TwoAddrGPR &) = delete;
449 InstMIPS32TwoAddrGPR &operator=(const InstMIPS32TwoAddrGPR &) = delete;
450
451 public:
create(Cfg * Func,Variable * Dest,Variable * Src0)452 static InstMIPS32TwoAddrGPR *create(Cfg *Func, Variable *Dest,
453 Variable *Src0) {
454 return new (Func->allocate<InstMIPS32TwoAddrGPR>())
455 InstMIPS32TwoAddrGPR(Func, Dest, Src0);
456 }
emit(const Cfg * Func)457 void emit(const Cfg *Func) const override {
458 if (!BuildDefs::dump())
459 return;
460 emitTwoAddr(Opcode, this, Func);
461 }
emitIAS(const Cfg * Func)462 void emitIAS(const Cfg *Func) const override {
463 (void)Func;
464 llvm_unreachable("Not yet implemented");
465 }
466
dump(const Cfg * Func)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 }
classof(const Inst * Inst)477 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
478
479 private:
InstMIPS32TwoAddrGPR(Cfg * Func,Variable * Dest,Variable * Src0)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.
490 template <InstMIPS32::InstKindMIPS32 K>
491 class InstMIPS32ThreeAddrFPR : public InstMIPS32 {
492 InstMIPS32ThreeAddrFPR() = delete;
493 InstMIPS32ThreeAddrFPR(const InstMIPS32ThreeAddrFPR &) = delete;
494 InstMIPS32ThreeAddrFPR &operator=(const InstMIPS32ThreeAddrFPR &) = delete;
495
496 public:
497 /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
498 /// must be registers.
create(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1)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 }
emit(const Cfg * Func)504 void emit(const Cfg *Func) const override {
505 if (!BuildDefs::dump())
506 return;
507 emitThreeAddr(Opcode, this, Func);
508 }
emitIAS(const Cfg * Func)509 void emitIAS(const Cfg *Func) const override {
510 (void)Func;
511 llvm_unreachable("Not yet implemented");
512 }
513
dump(const Cfg * Func)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 }
classof(const Inst * Inst)524 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
525
526 private:
InstMIPS32ThreeAddrFPR(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1)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
537 /// Instructions of the form x := y op z. May have the side-effect of setting
538 /// status flags.
539 template <InstMIPS32::InstKindMIPS32 K>
540 class InstMIPS32ThreeAddrGPR : public InstMIPS32 {
541 InstMIPS32ThreeAddrGPR() = delete;
542 InstMIPS32ThreeAddrGPR(const InstMIPS32ThreeAddrGPR &) = delete;
543 InstMIPS32ThreeAddrGPR &operator=(const InstMIPS32ThreeAddrGPR &) = delete;
544
545 public:
546 /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
547 /// must be registers.
create(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1)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 }
emit(const Cfg * Func)553 void emit(const Cfg *Func) const override {
554 if (!BuildDefs::dump())
555 return;
556 emitThreeAddr(Opcode, this, Func);
557 }
emitIAS(const Cfg * Func)558 void emitIAS(const Cfg *Func) const override {
559 (void)Func;
560 llvm_unreachable("Not yet implemented");
561 }
562
dump(const Cfg * Func)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 }
classof(const Inst * Inst)573 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
574
575 private:
InstMIPS32ThreeAddrGPR(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1)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
586 // InstMIPS32Load represents instructions which loads data from memory
587 // Its format is "OPCODE GPR, OFFSET(BASE GPR)"
588 template <InstMIPS32::InstKindMIPS32 K>
589 class InstMIPS32Load : public InstMIPS32 {
590 InstMIPS32Load() = delete;
591 InstMIPS32Load(const InstMIPS32Load &) = delete;
592 InstMIPS32Load &operator=(const InstMIPS32Load &) = delete;
593
594 public:
595 static InstMIPS32Load *create(Cfg *Func, Variable *Value,
596 OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) {
597 return new (Func->allocate<InstMIPS32Load>())
598 InstMIPS32Load(Func, Value, Mem, Reloc);
599 }
600
emit(const Cfg * Func)601 void emit(const Cfg *Func) const override {
602 if (!BuildDefs::dump())
603 return;
604 Ostream &Str = Func->getContext()->getStrEmit();
605 const Type Ty = getDest()->getType();
606
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 }
640 }
641 getDest()->emit(Func);
642 Str << ", ";
643 emitRelocOp(Str, Reloc);
644 getSrc(0)->emit(Func);
645 }
646
emitIAS(const Cfg * Func)647 void emitIAS(const Cfg *Func) const override {
648 (void)Func;
649 llvm_unreachable("Not yet implemented");
650 }
651
dump(const Cfg * Func)652 void dump(const Cfg *Func) const override {
653 if (!BuildDefs::dump())
654 return;
655 Ostream &Str = Func->getContext()->getStrDump();
656 dumpOpcode(Str, Opcode, getDest()->getType());
657 Str << " ";
658 getDest()->dump(Func);
659 Str << ", ";
660 emitRelocOp(Str, Reloc);
661 getSrc(0)->dump(Func);
662 }
classof(const Inst * Inst)663 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
664
665 private:
666 InstMIPS32Load(Cfg *Func, Variable *Value, OperandMIPS32Mem *Mem,
667 RelocOp Reloc = RO_No)
668 : 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)"
677 template <InstMIPS32::InstKindMIPS32 K>
678 class InstMIPS32Store : public InstMIPS32 {
679 InstMIPS32Store() = delete;
680 InstMIPS32Store(const InstMIPS32Store &) = delete;
681 InstMIPS32Store &operator=(const InstMIPS32Store &) = delete;
682
683 public:
684 static InstMIPS32Store *create(Cfg *Func, Variable *Value,
685 OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) {
686 return new (Func->allocate<InstMIPS32Store>())
687 InstMIPS32Store(Func, Value, Mem, Reloc);
688 }
689
emit(const Cfg * Func)690 void emit(const Cfg *Func) const override {
691 if (!BuildDefs::dump())
692 return;
693 Ostream &Str = Func->getContext()->getStrEmit();
694 assert(getSrcSize() == 2);
695 const Type Ty = getSrc(0)->getType();
696
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 }
730 }
731 getSrc(0)->emit(Func);
732 Str << ", ";
733 emitRelocOp(Str, Reloc);
734 getSrc(1)->emit(Func);
735 }
736
emitIAS(const Cfg * Func)737 void emitIAS(const Cfg *Func) const override {
738 (void)Func;
739 llvm_unreachable("InstMIPS32Store: Not yet implemented");
740 }
741
dump(const Cfg * Func)742 void dump(const Cfg *Func) const override {
743 if (!BuildDefs::dump())
744 return;
745 Ostream &Str = Func->getContext()->getStrDump();
746 dumpOpcode(Str, Opcode, getSrc(0)->getType());
747 Str << " ";
748 getSrc(0)->dump(Func);
749 Str << ", ";
750 emitRelocOp(Str, Reloc);
751 getSrc(1)->dump(Func);
752 }
classof(const Inst * Inst)753 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
754
755 private:
756 InstMIPS32Store(Cfg *Func, Variable *Value, OperandMIPS32Mem *Mem,
757 RelocOp Reloc = RO_No)
758 : InstMIPS32(Func, K, 2, nullptr), Reloc(Reloc) {
759 addSource(Value);
760 addSource(Mem);
761 }
762 static const char *Opcode;
763 const RelocOp Reloc;
764 };
765
766 // 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").
769 class InstMIPS32Label : public InstMIPS32 {
770 InstMIPS32Label() = delete;
771 InstMIPS32Label(const InstMIPS32Label &) = delete;
772 InstMIPS32Label &operator=(const InstMIPS32Label &) = delete;
773
774 public:
create(Cfg * Func,TargetMIPS32 * Target)775 static InstMIPS32Label *create(Cfg *Func, TargetMIPS32 *Target) {
776 return new (Func->allocate<InstMIPS32Label>())
777 InstMIPS32Label(Func, Target);
778 }
getEmitInstCount()779 uint32_t getEmitInstCount() const override { return 0; }
getLabelName()780 GlobalString getLabelName() const { return Name; }
getNumber()781 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
classof(const Inst * Instr)786 static bool classof(const Inst *Instr) { return isClassof(Instr, Label); }
787
788 private:
789 InstMIPS32Label(Cfg *Func, TargetMIPS32 *Target);
790
791 // RelocOffset *OffsetReloc = nullptr;
792 SizeT Number; // used for unique label generation.
793 GlobalString Name;
794 };
795
796 /// Direct branch instruction.
797 class InstMIPS32Br : public InstMIPS32 {
798 InstMIPS32Br() = delete;
799 InstMIPS32Br(const InstMIPS32Br &) = delete;
800 InstMIPS32Br &operator=(const InstMIPS32Br &) = delete;
801
802 public:
803 /// Create an unconditional branch to a node.
create(Cfg * Func,CfgNode * Target)804 static InstMIPS32Br *create(Cfg *Func, CfgNode *Target) {
805 constexpr CfgNode *NoCondTarget = nullptr;
806 constexpr InstMIPS32Label *NoLabel = nullptr;
807 return new (Func->allocate<InstMIPS32Br>())
808 InstMIPS32Br(Func, NoCondTarget, Target, NoLabel, CondMIPS32::AL);
809 }
810
create(Cfg * Func,CfgNode * Target,const InstMIPS32Label * Label)811 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
818 /// Create a conditional branch to the false node.
create(Cfg * Func,CfgNode * TargetTrue,CfgNode * TargetFalse,Operand * Src0,Operand * Src1,CondMIPS32::Cond Cond)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
create(Cfg * Func,CfgNode * TargetTrue,CfgNode * TargetFalse,Operand * Src0,CondMIPS32::Cond Cond)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
create(Cfg * Func,CfgNode * TargetTrue,CfgNode * TargetFalse,Operand * Src0,Operand * Src1,const InstMIPS32Label * Label,CondMIPS32::Cond Cond)835 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
getTargetTrue()843 const CfgNode *getTargetTrue() const { return TargetTrue; }
getTargetFalse()844 const CfgNode *getTargetFalse() const { return TargetFalse; }
getPredicate()845 CondMIPS32::Cond getPredicate() const { return Predicate; }
setPredicate(CondMIPS32::Cond Pred)846 void setPredicate(CondMIPS32::Cond Pred) { Predicate = Pred; }
847 bool optimizeBranch(const CfgNode *NextNode);
isUnconditionalBranch()848 bool isUnconditionalBranch() const override {
849 return Predicate == CondMIPS32::AL;
850 }
851 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
852 void emit(const Cfg *Func) const override;
853 void emitIAS(const Cfg *Func) const override;
854 void dump(const Cfg *Func) const override;
classof(const Inst * Instr)855 static bool classof(const Inst *Instr) { return isClassof(Instr, Br); }
856
857 private:
858 InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
859 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);
868
869 const CfgNode *TargetTrue;
870 const CfgNode *TargetFalse;
871 const InstMIPS32Label *Label; // Intra-block branch target
872 CondMIPS32::Cond Predicate;
873 };
874
875 class InstMIPS32Call : public InstMIPS32 {
876 InstMIPS32Call() = delete;
877 InstMIPS32Call(const InstMIPS32Call &) = delete;
878 InstMIPS32Call &operator=(const InstMIPS32Call &) = delete;
879
880 public:
create(Cfg * Func,Variable * Dest,Operand * CallTarget)881 static InstMIPS32Call *create(Cfg *Func, Variable *Dest,
882 Operand *CallTarget) {
883 return new (Func->allocate<InstMIPS32Call>())
884 InstMIPS32Call(Func, Dest, CallTarget);
885 }
getCallTarget()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;
classof(const Inst * Inst)890 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); }
891
892 private:
893 InstMIPS32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
894 };
895
896 template <InstMIPS32::InstKindMIPS32 K>
897 class InstMIPS32FPCmp : public InstMIPS32 {
898 InstMIPS32FPCmp() = delete;
899 InstMIPS32FPCmp(const InstMIPS32FPCmp &) = delete;
900 InstMIPS32Call &operator=(const InstMIPS32FPCmp &) = delete;
901
902 public:
create(Cfg * Func,Variable * Src0,Variable * Src1)903 static InstMIPS32FPCmp *create(Cfg *Func, Variable *Src0, Variable *Src1) {
904 return new (Func->allocate<InstMIPS32FPCmp>())
905 InstMIPS32FPCmp(Func, Src0, Src1);
906 }
907
emit(const Cfg * Func)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
emitIAS(const Cfg * Func)919 void emitIAS(const Cfg *Func) const override {
920 (void)Func;
921 llvm_unreachable("Not yet implemented");
922 }
923
dump(const Cfg * Func)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
classof(const Inst * Inst)934 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); }
935
936 private:
InstMIPS32FPCmp(Cfg * Func,Variable * Src0,Variable * Src1)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
946 class InstMIPS32Sync : public InstMIPS32 {
947 InstMIPS32Sync() = delete;
948 InstMIPS32Sync(const InstMIPS32Sync &) = delete;
949 InstMIPS32Sync &operator=(const InstMIPS32Sync &) = delete;
950
951 public:
create(Cfg * Func)952 static InstMIPS32Sync *create(Cfg *Func) {
953 return new (Func->allocate<InstMIPS32Sync>()) InstMIPS32Sync(Func);
954 }
955
emit(const Cfg * Func)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
dump(const Cfg * Func)963 void dump(const Cfg *Func) const override {
964 if (!BuildDefs::dump())
965 return;
966 Func->getContext()->getStrDump() << Opcode << "\t";
967 }
968
classof(const Inst * Inst)969 static bool classof(const Inst *Inst) {
970 return isClassof(Inst, InstMIPS32::Sync);
971 }
972
973 void emitIAS(const Cfg *Func) const override;
974
975 private:
InstMIPS32Sync(Cfg * Func)976 InstMIPS32Sync(Cfg *Func) : InstMIPS32(Func, InstMIPS32::Sync, 0, nullptr) {}
977 static const char *Opcode;
978 };
979
980 // Trap
981 template <InstMIPS32::InstKindMIPS32 K>
982 class InstMIPS32Trap : public InstMIPS32 {
983 InstMIPS32Trap() = delete;
984 InstMIPS32Trap(const InstMIPS32Trap &) = delete;
985 InstMIPS32Trap &operator=(const InstMIPS32Trap &) = delete;
986
987 public:
create(Cfg * Func,Operand * Src0,Operand * Src1,uint32_t Tcode)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
getTrapCode()994 uint32_t getTrapCode() const { return TrapCode; }
995
emit(const Cfg * Func)996 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
emitIAS(const Cfg * Func)1007 void emitIAS(const Cfg *Func) const override {
1008 (void)Func;
1009 llvm_unreachable("Not yet implemented");
1010 }
1011
dump(const Cfg * Func)1012 void dump(const Cfg *Func) const override {
1013 if (!BuildDefs::dump())
1014 return;
1015 Ostream &Str = Func->getContext()->getStrDump();
1016 dumpOpcode(Str, Opcode, getSrc(0)->getType());
1017 Str << " ";
1018 dumpSources(Func);
1019 Str << ", " << TrapCode;
1020 }
1021
classof(const Inst * Inst)1022 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
1023
1024 private:
InstMIPS32Trap(Cfg * Func,Operand * Src0,Operand * Src1,const uint32_t Tcode)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
1035 template <InstMIPS32::InstKindMIPS32 K, bool Signed = false>
1036 class InstMIPS32Imm16 : public InstMIPS32 {
1037 InstMIPS32Imm16() = delete;
1038 InstMIPS32Imm16(const InstMIPS32Imm16 &) = delete;
1039 InstMIPS32Imm16 &operator=(const InstMIPS32Imm16 &) = delete;
1040
1041 public:
1042 static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, Operand *Source,
1043 uint32_t Imm, RelocOp Reloc = RO_No) {
1044 return new (Func->allocate<InstMIPS32Imm16>())
1045 InstMIPS32Imm16(Func, Dest, Source, Imm, Reloc);
1046 }
1047
1048 static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, uint32_t Imm,
1049 RelocOp Reloc = RO_No) {
1050 return new (Func->allocate<InstMIPS32Imm16>())
1051 InstMIPS32Imm16(Func, Dest, Imm, Reloc);
1052 }
1053
create(Cfg * Func,Variable * Dest,Operand * Src0,Operand * Src1,RelocOp Reloc)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);
1058 }
1059
emit(const Cfg * Func)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 << ", ";
1071 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 }
1083 }
1084
emitIAS(const Cfg * Func)1085 void emitIAS(const Cfg *Func) const override {
1086 (void)Func;
1087 llvm_unreachable("Not yet implemented");
1088 }
dump(const Cfg * Func)1089 void dump(const Cfg *Func) const override {
1090 if (!BuildDefs::dump())
1091 return;
1092 Ostream &Str = Func->getContext()->getStrDump();
1093 dumpOpcode(Str, Opcode, getDest()->getType());
1094 Str << " ";
1095 dumpDest(Func);
1096 Str << ", ";
1097 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 }
1112 }
1113
getImmediateValue()1114 uint32_t getImmediateValue() const { return Imm; }
1115
classof(const Inst * Inst)1116 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
1117
1118 private:
1119 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) {
1122 addSource(Source);
1123 }
1124
1125 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 }
1135
1136 static const char *Opcode;
1137 const RelocOp Reloc;
1138 const uint32_t Imm;
1139 };
1140
1141 /// Conditional mov
1142 template <InstMIPS32::InstKindMIPS32 K>
1143 class InstMIPS32MovConditional : public InstMIPS32 {
1144 InstMIPS32MovConditional() = delete;
1145 InstMIPS32MovConditional(const InstMIPS32MovConditional &) = delete;
1146 InstMIPS32MovConditional &
1147 operator=(const InstMIPS32MovConditional &) = delete;
1148
1149 public:
create(Cfg * Func,Variable * Dest,Variable * Src,Operand * FCC)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
emit(const Cfg * Func)1156 void emit(const Cfg *Func) const override {
1157 if (!BuildDefs::dump())
1158 return;
1159 Ostream &Str = Func->getContext()->getStrEmit();
1160 assert(getSrcSize() == 2);
1161 Str << "\t" << Opcode << "\t";
1162 getDest()->emit(Func);
1163 Str << ", ";
1164 getSrc(0)->emit(Func);
1165 Str << ", ";
1166 getSrc(1)->emit(Func);
1167 }
1168
emitIAS(const Cfg * Func)1169 void emitIAS(const Cfg *Func) const override {
1170 (void)Func;
1171 llvm_unreachable("Not yet implemented");
1172 }
1173
dump(const Cfg * Func)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 }
classof(const Inst * Inst)1184 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
1185
1186 private:
InstMIPS32MovConditional(Cfg * Func,Variable * Dest,Variable * Src,Operand * FCC)1187 InstMIPS32MovConditional(Cfg *Func, Variable *Dest, Variable *Src,
1188 Operand *FCC)
1189 : InstMIPS32(Func, K, 2, Dest) {
1190 addSource(Src);
1191 addSource(FCC);
1192 }
1193
1194 static const char *Opcode;
1195 };
1196
1197 using InstMIPS32Abs_d = InstMIPS32TwoAddrFPR<InstMIPS32::Abs_d>;
1198 using InstMIPS32Abs_s = InstMIPS32TwoAddrFPR<InstMIPS32::Abs_s>;
1199 using InstMIPS32Add = InstMIPS32ThreeAddrGPR<InstMIPS32::Add>;
1200 using InstMIPS32Add_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Add_d>;
1201 using InstMIPS32Add_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Add_s>;
1202 using InstMIPS32Addu = InstMIPS32ThreeAddrGPR<InstMIPS32::Addu>;
1203 using InstMIPS32Addi = InstMIPS32Imm16<InstMIPS32::Addi, true>;
1204 using InstMIPS32Addiu = InstMIPS32Imm16<InstMIPS32::Addiu, true>;
1205 using InstMIPS32And = InstMIPS32ThreeAddrGPR<InstMIPS32::And>;
1206 using InstMIPS32Andi = InstMIPS32Imm16<InstMIPS32::Andi>;
1207 using InstMIPS32C_eq_d = InstMIPS32FPCmp<InstMIPS32::C_eq_d>;
1208 using InstMIPS32C_eq_s = InstMIPS32FPCmp<InstMIPS32::C_eq_s>;
1209 using InstMIPS32C_ole_d = InstMIPS32FPCmp<InstMIPS32::C_ole_d>;
1210 using InstMIPS32C_ole_s = InstMIPS32FPCmp<InstMIPS32::C_ole_s>;
1211 using InstMIPS32C_olt_d = InstMIPS32FPCmp<InstMIPS32::C_olt_d>;
1212 using InstMIPS32C_olt_s = InstMIPS32FPCmp<InstMIPS32::C_olt_s>;
1213 using InstMIPS32C_ueq_d = InstMIPS32FPCmp<InstMIPS32::C_ueq_d>;
1214 using InstMIPS32C_ueq_s = InstMIPS32FPCmp<InstMIPS32::C_ueq_s>;
1215 using InstMIPS32C_ule_d = InstMIPS32FPCmp<InstMIPS32::C_ule_d>;
1216 using InstMIPS32C_ule_s = InstMIPS32FPCmp<InstMIPS32::C_ule_s>;
1217 using InstMIPS32C_ult_d = InstMIPS32FPCmp<InstMIPS32::C_ult_d>;
1218 using InstMIPS32C_ult_s = InstMIPS32FPCmp<InstMIPS32::C_ult_s>;
1219 using InstMIPS32C_un_d = InstMIPS32FPCmp<InstMIPS32::C_un_d>;
1220 using InstMIPS32C_un_s = InstMIPS32FPCmp<InstMIPS32::C_un_s>;
1221 using InstMIPS32Clz = InstMIPS32TwoAddrGPR<InstMIPS32::Clz>;
1222 using InstMIPS32Cvt_d_s = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_d_s>;
1223 using InstMIPS32Cvt_d_l = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_d_l>;
1224 using InstMIPS32Cvt_d_w = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_d_w>;
1225 using InstMIPS32Cvt_s_d = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_d>;
1226 using InstMIPS32Cvt_s_l = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_l>;
1227 using InstMIPS32Cvt_s_w = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_w>;
1228 using InstMIPS32Div = InstMIPS32ThreeAddrGPR<InstMIPS32::Div>;
1229 using InstMIPS32Div_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Div_d>;
1230 using InstMIPS32Div_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Div_s>;
1231 using InstMIPS32Divu = InstMIPS32ThreeAddrGPR<InstMIPS32::Divu>;
1232 using InstMIPS32La = InstMIPS32UnaryopGPR<InstMIPS32::La>;
1233 using InstMIPS32Ldc1 = InstMIPS32Load<InstMIPS32::Ldc1>;
1234 using InstMIPS32Ll = InstMIPS32Load<InstMIPS32::Ll>;
1235 using InstMIPS32Lui = InstMIPS32UnaryopGPR<InstMIPS32::Lui>;
1236 using InstMIPS32Lw = InstMIPS32Load<InstMIPS32::Lw>;
1237 using InstMIPS32Lwc1 = InstMIPS32Load<InstMIPS32::Lwc1>;
1238 using InstMIPS32Mfc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mfc1>;
1239 using InstMIPS32Mfhi = InstMIPS32UnaryopGPR<InstMIPS32::Mfhi>;
1240 using InstMIPS32Mflo = InstMIPS32UnaryopGPR<InstMIPS32::Mflo>;
1241 using InstMIPS32Mov_d = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_d>;
1242 using InstMIPS32Mov_s = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_s>;
1243 using InstMIPS32Movf = InstMIPS32MovConditional<InstMIPS32::Movf>;
1244 using InstMIPS32Movn = InstMIPS32ThreeAddrGPR<InstMIPS32::Movn>;
1245 using InstMIPS32Movn_d = InstMIPS32ThreeAddrGPR<InstMIPS32::Movn_d>;
1246 using InstMIPS32Movn_s = InstMIPS32ThreeAddrGPR<InstMIPS32::Movn_s>;
1247 using InstMIPS32Movt = InstMIPS32MovConditional<InstMIPS32::Movt>;
1248 using InstMIPS32Movz = InstMIPS32ThreeAddrGPR<InstMIPS32::Movz>;
1249 using InstMIPS32Movz_d = InstMIPS32ThreeAddrGPR<InstMIPS32::Movz_d>;
1250 using InstMIPS32Movz_s = InstMIPS32ThreeAddrGPR<InstMIPS32::Movz_s>;
1251 using InstMIPS32Mtc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mtc1>;
1252 using InstMIPS32Mthi = InstMIPS32UnaryopGPR<InstMIPS32::Mthi>;
1253 using InstMIPS32Mtlo = InstMIPS32UnaryopGPR<InstMIPS32::Mtlo>;
1254 using InstMIPS32Mul = InstMIPS32ThreeAddrGPR<InstMIPS32::Mul>;
1255 using InstMIPS32Mul_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Mul_d>;
1256 using InstMIPS32Mul_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Mul_s>;
1257 using InstMIPS32Mult = InstMIPS32ThreeAddrGPR<InstMIPS32::Mult>;
1258 using InstMIPS32Multu = InstMIPS32ThreeAddrGPR<InstMIPS32::Multu>;
1259 using InstMIPS32Nor = InstMIPS32ThreeAddrGPR<InstMIPS32::Nor>;
1260 using InstMIPS32Or = InstMIPS32ThreeAddrGPR<InstMIPS32::Or>;
1261 using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>;
1262 using InstMIPS32Sc = InstMIPS32Store<InstMIPS32::Sc>;
1263 using InstMIPS32Sdc1 = InstMIPS32Store<InstMIPS32::Sdc1>;
1264 using InstMIPS32Sll = InstMIPS32Imm16<InstMIPS32::Sll>;
1265 using InstMIPS32Sllv = InstMIPS32ThreeAddrGPR<InstMIPS32::Sllv>;
1266 using InstMIPS32Slt = InstMIPS32ThreeAddrGPR<InstMIPS32::Slt>;
1267 using InstMIPS32Slti = InstMIPS32Imm16<InstMIPS32::Slti>;
1268 using InstMIPS32Sltiu = InstMIPS32Imm16<InstMIPS32::Sltiu>;
1269 using InstMIPS32Sltu = InstMIPS32ThreeAddrGPR<InstMIPS32::Sltu>;
1270 using InstMIPS32Sqrt_d = InstMIPS32TwoAddrFPR<InstMIPS32::Sqrt_d>;
1271 using InstMIPS32Sqrt_s = InstMIPS32TwoAddrFPR<InstMIPS32::Sqrt_s>;
1272 using InstMIPS32Sra = InstMIPS32Imm16<InstMIPS32::Sra>;
1273 using InstMIPS32Srav = InstMIPS32ThreeAddrGPR<InstMIPS32::Srav>;
1274 using InstMIPS32Srl = InstMIPS32Imm16<InstMIPS32::Srl>;
1275 using InstMIPS32Srlv = InstMIPS32ThreeAddrGPR<InstMIPS32::Srlv>;
1276 using InstMIPS32Sub = InstMIPS32ThreeAddrGPR<InstMIPS32::Sub>;
1277 using InstMIPS32Sub_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Sub_d>;
1278 using InstMIPS32Sub_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Sub_s>;
1279 using InstMIPS32Subu = InstMIPS32ThreeAddrGPR<InstMIPS32::Subu>;
1280 using InstMIPS32Sw = InstMIPS32Store<InstMIPS32::Sw>;
1281 using InstMIPS32Swc1 = InstMIPS32Store<InstMIPS32::Swc1>;
1282 using InstMIPS32Teq = InstMIPS32Trap<InstMIPS32::Teq>;
1283 using InstMIPS32Trunc_l_d = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_l_d>;
1284 using InstMIPS32Trunc_l_s = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_l_s>;
1285 using InstMIPS32Trunc_w_d = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_w_d>;
1286 using InstMIPS32Trunc_w_s = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_w_s>;
1287 using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>;
1288 using InstMIPS32Xor = InstMIPS32ThreeAddrGPR<InstMIPS32::Xor>;
1289 using InstMIPS32Xori = InstMIPS32Imm16<InstMIPS32::Xori>;
1290
1291 /// Handles (some of) vmov's various formats.
1292 class InstMIPS32Mov final : public InstMIPS32 {
1293 InstMIPS32Mov() = delete;
1294 InstMIPS32Mov(const InstMIPS32Mov &) = delete;
1295 InstMIPS32Mov &operator=(const InstMIPS32Mov &) = delete;
1296
1297 public:
create(Cfg * Func,Variable * Dest,Operand * Src,Operand * Src2)1298 static InstMIPS32Mov *create(Cfg *Func, Variable *Dest, Operand *Src,
1299 Operand *Src2) {
1300 return new (Func->allocate<InstMIPS32Mov>())
1301 InstMIPS32Mov(Func, Dest, Src, Src2);
1302 }
1303
isRedundantAssign()1304 bool isRedundantAssign() const override {
1305 return checkForRedundantAssign(getDest(), getSrc(0));
1306 }
1307 // bool isSimpleAssign() const override { return true; }
1308 void emit(const Cfg *Func) const override;
1309 void emitIAS(const Cfg *Func) const override;
1310 void dump(const Cfg *Func) const override;
classof(const Inst * Inst)1311 static bool classof(const Inst *Inst) { return isClassof(Inst, Mov); }
1312
getDestHi()1313 Variable *getDestHi() const { return DestHi; }
1314
1315 private:
1316 InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src, Operand *Src2);
1317
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
1325 /// Handle double to i64 move
1326 class InstMIPS32MovFP64ToI64 final : public InstMIPS32 {
1327 InstMIPS32MovFP64ToI64() = delete;
1328 InstMIPS32MovFP64ToI64(const InstMIPS32MovFP64ToI64 &) = delete;
1329 InstMIPS32MovFP64ToI64 &operator=(const InstMIPS32MovFP64ToI64 &) = delete;
1330
1331 public:
create(Cfg * Func,Variable * Dest,Operand * Src,Int64Part Int64HiLo)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
isRedundantAssign()1338 bool isRedundantAssign() const override {
1339 return checkForRedundantAssign(getDest(), getSrc(0));
1340 }
1341
dump(const Cfg * Func)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
getInt64Part()1353 Int64Part getInt64Part() const { return Int64HiLo; }
1354
classof(const Inst * Inst)1355 static bool classof(const Inst *Inst) { return isClassof(Inst, Mov_fp); }
1356
1357 private:
1358 InstMIPS32MovFP64ToI64(Cfg *Func, Variable *Dest, Operand *Src,
1359 Int64Part Int64HiLo);
1360 const Int64Part Int64HiLo;
1361 };
1362
1363 // 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
1367 template <> void InstMIPS32Abs_d::emitIAS(const Cfg *Func) const;
1368 template <> void InstMIPS32Abs_s::emitIAS(const Cfg *Func) const;
1369 template <> void InstMIPS32Add_d::emitIAS(const Cfg *Func) const;
1370 template <> void InstMIPS32Add_s::emitIAS(const Cfg *Func) const;
1371 template <> void InstMIPS32Addi::emitIAS(const Cfg *Func) const;
1372 template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const;
1373 template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const;
1374 template <> void InstMIPS32And::emitIAS(const Cfg *Func) const;
1375 template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const;
1376 template <> void InstMIPS32C_eq_d::emitIAS(const Cfg *Func) const;
1377 template <> void InstMIPS32C_eq_s::emitIAS(const Cfg *Func) const;
1378 template <> void InstMIPS32C_ole_d::emitIAS(const Cfg *Func) const;
1379 template <> void InstMIPS32C_ole_s::emitIAS(const Cfg *Func) const;
1380 template <> void InstMIPS32C_olt_d::emitIAS(const Cfg *Func) const;
1381 template <> void InstMIPS32C_olt_s::emitIAS(const Cfg *Func) const;
1382 template <> void InstMIPS32C_ueq_d::emitIAS(const Cfg *Func) const;
1383 template <> void InstMIPS32C_ueq_s::emitIAS(const Cfg *Func) const;
1384 template <> void InstMIPS32C_ule_d::emitIAS(const Cfg *Func) const;
1385 template <> void InstMIPS32C_ule_s::emitIAS(const Cfg *Func) const;
1386 template <> void InstMIPS32C_ult_d::emitIAS(const Cfg *Func) const;
1387 template <> void InstMIPS32C_ult_s::emitIAS(const Cfg *Func) const;
1388 template <> void InstMIPS32C_un_d::emitIAS(const Cfg *Func) const;
1389 template <> void InstMIPS32C_un_s::emitIAS(const Cfg *Func) const;
1390 template <> void InstMIPS32Clz::emitIAS(const Cfg *Func) const;
1391 template <> void InstMIPS32Cvt_d_l::emitIAS(const Cfg *Func) const;
1392 template <> void InstMIPS32Cvt_d_s::emitIAS(const Cfg *Func) const;
1393 template <> void InstMIPS32Cvt_d_w::emitIAS(const Cfg *Func) const;
1394 template <> void InstMIPS32Cvt_s_d::emitIAS(const Cfg *Func) const;
1395 template <> void InstMIPS32Cvt_s_l::emitIAS(const Cfg *Func) const;
1396 template <> void InstMIPS32Cvt_s_w::emitIAS(const Cfg *Func) const;
1397 template <> void InstMIPS32Div::emitIAS(const Cfg *Func) const;
1398 template <> void InstMIPS32Div_d::emitIAS(const Cfg *Func) const;
1399 template <> void InstMIPS32Div_s::emitIAS(const Cfg *Func) const;
1400 template <> void InstMIPS32Divu::emitIAS(const Cfg *Func) const;
1401 template <> void InstMIPS32Ldc1::emitIAS(const Cfg *Func) const;
1402 template <> void InstMIPS32Ll::emitIAS(const Cfg *Func) const;
1403 template <> void InstMIPS32Lui::emit(const Cfg *Func) const;
1404 template <> void InstMIPS32Lui::emitIAS(const Cfg *Func) const;
1405 template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const;
1406 template <> void InstMIPS32Lwc1::emitIAS(const Cfg *Func) const;
1407 template <> void InstMIPS32Mfc1::emitIAS(const Cfg *Func) const;
1408 template <> void InstMIPS32Mflo::emit(const Cfg *Func) const;
1409 template <> void InstMIPS32Mflo::emitIAS(const Cfg *Func) const;
1410 template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const;
1411 template <> void InstMIPS32Mfhi::emitIAS(const Cfg *Func) const;
1412 template <> void InstMIPS32Mov_d::emitIAS(const Cfg *Func) const;
1413 template <> void InstMIPS32Mov_s::emitIAS(const Cfg *Func) const;
1414 template <> void InstMIPS32Movf::emitIAS(const Cfg *Func) const;
1415 template <> void InstMIPS32Movn::emitIAS(const Cfg *Func) const;
1416 template <> void InstMIPS32Movn_d::emitIAS(const Cfg *Func) const;
1417 template <> void InstMIPS32Movn_s::emitIAS(const Cfg *Func) const;
1418 template <> void InstMIPS32Movt::emitIAS(const Cfg *Func) const;
1419 template <> void InstMIPS32Movz::emitIAS(const Cfg *Func) const;
1420 template <> void InstMIPS32Movz_d::emitIAS(const Cfg *Func) const;
1421 template <> void InstMIPS32Movz_s::emitIAS(const Cfg *Func) const;
1422 template <> void InstMIPS32Mtc1::emit(const Cfg *Func) const;
1423 template <> void InstMIPS32Mtc1::emitIAS(const Cfg *Func) const;
1424 template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const;
1425 template <> void InstMIPS32Mtlo::emitIAS(const Cfg *Func) const;
1426 template <> void InstMIPS32Mthi::emit(const Cfg *Func) const;
1427 template <> void InstMIPS32Mthi::emitIAS(const Cfg *Func) const;
1428 template <> void InstMIPS32Mul::emitIAS(const Cfg *Func) const;
1429 template <> void InstMIPS32Mul_d::emitIAS(const Cfg *Func) const;
1430 template <> void InstMIPS32Mul_s::emitIAS(const Cfg *Func) const;
1431 template <> void InstMIPS32Mult::emit(const Cfg *Func) const;
1432 template <> void InstMIPS32Multu::emit(const Cfg *Func) const;
1433 template <> void InstMIPS32Multu::emitIAS(const Cfg *Func) const;
1434 template <> void InstMIPS32Nor::emitIAS(const Cfg *Func) const;
1435 template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const;
1436 template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const;
1437 template <> void InstMIPS32Sc::emitIAS(const Cfg *Func) const;
1438 template <> void InstMIPS32Sdc1::emitIAS(const Cfg *Func) const;
1439 template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const;
1440 template <> void InstMIPS32Sllv::emitIAS(const Cfg *Func) const;
1441 template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const;
1442 template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const;
1443 template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const;
1444 template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const;
1445 template <> void InstMIPS32Sqrt_d::emitIAS(const Cfg *Func) const;
1446 template <> void InstMIPS32Sqrt_s::emitIAS(const Cfg *Func) const;
1447 template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const;
1448 template <> void InstMIPS32Swc1::emitIAS(const Cfg *Func) const;
1449 template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const;
1450 template <> void InstMIPS32Srav::emitIAS(const Cfg *Func) const;
1451 template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const;
1452 template <> void InstMIPS32Srlv::emitIAS(const Cfg *Func) const;
1453 template <> void InstMIPS32Sub_d::emitIAS(const Cfg *Func) const;
1454 template <> void InstMIPS32Sub_s::emitIAS(const Cfg *Func) const;
1455 template <> void InstMIPS32Subu::emitIAS(const Cfg *Func) const;
1456 template <> void InstMIPS32Teq::emitIAS(const Cfg *Func) const;
1457 template <> void InstMIPS32Trunc_l_d::emitIAS(const Cfg *Func) const;
1458 template <> void InstMIPS32Trunc_l_s::emitIAS(const Cfg *Func) const;
1459 template <> void InstMIPS32Trunc_w_d::emitIAS(const Cfg *Func) const;
1460 template <> void InstMIPS32Trunc_w_s::emitIAS(const Cfg *Func) const;
1461 template <> void InstMIPS32Xor::emitIAS(const Cfg *Func) const;
1462 template <> void InstMIPS32Xori::emitIAS(const Cfg *Func) const;
1463
1464 } // end of namespace MIPS32
1465 } // end of namespace Ice
1466
1467 #endif // SUBZERO_SRC_ICEINSTMIPS32_H
1468