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