• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- subzero/src/IceTargetLoweringMIPS32.h - MIPS32 lowering ---*- 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 TargetLoweringMIPS32 class, which implements the
12 /// TargetLowering interface for the MIPS 32-bit architecture.
13 ///
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H
17 #define SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H
18 
19 #include "IceAssemblerMIPS32.h"
20 #include "IceDefs.h"
21 #include "IceInstMIPS32.h"
22 #include "IceRegistersMIPS32.h"
23 #include "IceTargetLowering.h"
24 
25 namespace Ice {
26 namespace MIPS32 {
27 
28 class TargetMIPS32 : public TargetLowering {
29   TargetMIPS32() = delete;
30   TargetMIPS32(const TargetMIPS32 &) = delete;
31   TargetMIPS32 &operator=(const TargetMIPS32 &) = delete;
32 
33 public:
34   ~TargetMIPS32() override = default;
35 
36   static void staticInit(GlobalContext *Ctx);
shouldBePooled(const Constant * C)37   static bool shouldBePooled(const Constant *C) {
38     if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(C)) {
39       return !Utils::isPositiveZero(ConstDouble->getValue());
40     }
41     if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(C)) {
42       return !Utils::isPositiveZero(ConstFloat->getValue());
43     }
44     return false;
45   }
getPointerType()46   static ::Ice::Type getPointerType() { return ::Ice::IceType_i32; }
create(Cfg * Func)47   static std::unique_ptr<::Ice::TargetLowering> create(Cfg *Func) {
48     return makeUnique<TargetMIPS32>(Func);
49   }
50 
createAssembler()51   std::unique_ptr<::Ice::Assembler> createAssembler() const override {
52     return makeUnique<MIPS32::AssemblerMIPS32>();
53   }
54 
initNodeForLowering(CfgNode * Node)55   void initNodeForLowering(CfgNode *Node) override {
56     Computations.forgetProducers();
57     Computations.recordProducers(Node);
58     Computations.dump(Func);
59   }
60 
61   void translateOm1() override;
62   void translateO2() override;
63   bool doBranchOpt(Inst *Instr, const CfgNode *NextNode) override;
setImplicitRet(Variable * Ret)64   void setImplicitRet(Variable *Ret) { ImplicitRet = Ret; }
getImplicitRet()65   Variable *getImplicitRet() const { return ImplicitRet; }
getNumRegisters()66   SizeT getNumRegisters() const override { return RegMIPS32::Reg_NUM; }
67   Variable *getPhysicalRegister(RegNumT RegNum,
68                                 Type Ty = IceType_void) override;
69   const char *getRegName(RegNumT RegNum, Type Ty) const override;
70   SmallBitVector getRegisterSet(RegSetMask Include,
71                                 RegSetMask Exclude) const override;
72   const SmallBitVector &
getRegistersForVariable(const Variable * Var)73   getRegistersForVariable(const Variable *Var) const override {
74     RegClass RC = Var->getRegClass();
75     assert(RC < RC_Target);
76     return TypeToRegisterSet[RC];
77   }
78   const SmallBitVector &
getAllRegistersForVariable(const Variable * Var)79   getAllRegistersForVariable(const Variable *Var) const override {
80     RegClass RC = Var->getRegClass();
81     assert(RC < RC_Target);
82     return TypeToRegisterSetUnfiltered[RC];
83   }
getAliasesForRegister(RegNumT Reg)84   const SmallBitVector &getAliasesForRegister(RegNumT Reg) const override {
85     return RegisterAliases[Reg];
86   }
hasFramePointer()87   bool hasFramePointer() const override { return UsesFramePointer; }
setHasFramePointer()88   void setHasFramePointer() override { UsesFramePointer = true; }
getStackReg()89   RegNumT getStackReg() const override { return RegMIPS32::Reg_SP; }
getFrameReg()90   RegNumT getFrameReg() const override { return RegMIPS32::Reg_FP; }
getFrameOrStackReg()91   RegNumT getFrameOrStackReg() const override {
92     return UsesFramePointer ? getFrameReg() : getStackReg();
93   }
getReservedTmpReg()94   RegNumT getReservedTmpReg() const { return RegMIPS32::Reg_AT; }
typeWidthInBytesOnStack(Type Ty)95   size_t typeWidthInBytesOnStack(Type Ty) const override {
96     // Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16
97     // are rounded up to 4 bytes.
98     return (typeWidthInBytes(Ty) + 3) & ~3;
99   }
100   uint32_t getStackAlignment() const override;
reserveFixedAllocaArea(size_t Size,size_t Align)101   void reserveFixedAllocaArea(size_t Size, size_t Align) override {
102     FixedAllocaSizeBytes = Size;
103     assert(llvm::isPowerOf2_32(Align));
104     FixedAllocaAlignBytes = Align;
105     PrologEmitsFixedAllocas = true;
106   }
getFrameFixedAllocaOffset()107   int32_t getFrameFixedAllocaOffset() const override {
108     int32_t FixedAllocaOffset =
109         Utils::applyAlignment(CurrentAllocaOffset, FixedAllocaAlignBytes);
110     return FixedAllocaOffset - MaxOutArgsSizeBytes;
111   }
112 
maxOutArgsSizeBytes()113   uint32_t maxOutArgsSizeBytes() const override { return MaxOutArgsSizeBytes; }
114 
getFramePointerOffset(uint32_t CurrentOffset,uint32_t Size)115   uint32_t getFramePointerOffset(uint32_t CurrentOffset,
116                                  uint32_t Size) const override {
117     (void)Size;
118     return CurrentOffset + MaxOutArgsSizeBytes;
119   }
120 
shouldSplitToVariable64On32(Type Ty)121   bool shouldSplitToVariable64On32(Type Ty) const override {
122     return Ty == IceType_i64;
123   }
124 
shouldSplitToVariableVecOn32(Type Ty)125   bool shouldSplitToVariableVecOn32(Type Ty) const override {
126     return isVectorType(Ty);
127   }
128 
129   // TODO(ascull): what is the best size of MIPS?
getMinJumpTableSize()130   SizeT getMinJumpTableSize() const override { return 3; }
131   void emitJumpTable(const Cfg *Func,
132                      const InstJumpTable *JumpTable) const override;
133 
134   void emitVariable(const Variable *Var) const override;
135 
emit(const ConstantInteger32 * C)136   void emit(const ConstantInteger32 *C) const final {
137     if (!BuildDefs::dump())
138       return;
139     Ostream &Str = Ctx->getStrEmit();
140     Str << C->getValue();
141   }
emit(const ConstantInteger64 * C)142   void emit(const ConstantInteger64 *C) const final {
143     (void)C;
144     llvm::report_fatal_error("Not yet implemented");
145   }
emit(const ConstantFloat * C)146   void emit(const ConstantFloat *C) const final {
147     (void)C;
148     llvm::report_fatal_error("Not yet implemented");
149   }
emit(const ConstantDouble * C)150   void emit(const ConstantDouble *C) const final {
151     (void)C;
152     llvm::report_fatal_error("Not yet implemented");
153   }
emit(const ConstantUndef * C)154   void emit(const ConstantUndef *C) const final {
155     (void)C;
156     llvm::report_fatal_error("Not yet implemented");
157   }
emit(const ConstantRelocatable * C)158   void emit(const ConstantRelocatable *C) const final {
159     (void)C;
160     llvm::report_fatal_error("Not yet implemented");
161   }
162 
163   // The following are helpers that insert lowered MIPS32 instructions with
164   // minimal syntactic overhead, so that the lowering code can look as close to
165   // assembly as practical.
_add(Variable * Dest,Variable * Src0,Variable * Src1)166   void _add(Variable *Dest, Variable *Src0, Variable *Src1) {
167     Context.insert<InstMIPS32Add>(Dest, Src0, Src1);
168   }
169 
_addu(Variable * Dest,Variable * Src0,Variable * Src1)170   void _addu(Variable *Dest, Variable *Src0, Variable *Src1) {
171     Context.insert<InstMIPS32Addu>(Dest, Src0, Src1);
172   }
173 
_and(Variable * Dest,Variable * Src0,Variable * Src1)174   void _and(Variable *Dest, Variable *Src0, Variable *Src1) {
175     Context.insert<InstMIPS32And>(Dest, Src0, Src1);
176   }
177 
_andi(Variable * Dest,Variable * Src,uint32_t Imm)178   void _andi(Variable *Dest, Variable *Src, uint32_t Imm) {
179     Context.insert<InstMIPS32Andi>(Dest, Src, Imm);
180   }
181 
_br(CfgNode * Target)182   void _br(CfgNode *Target) { Context.insert<InstMIPS32Br>(Target); }
183 
_br(CfgNode * Target,const InstMIPS32Label * Label)184   void _br(CfgNode *Target, const InstMIPS32Label *Label) {
185     Context.insert<InstMIPS32Br>(Target, Label);
186   }
187 
_br(CfgNode * TargetTrue,CfgNode * TargetFalse,Operand * Src0,Operand * Src1,CondMIPS32::Cond Condition)188   void _br(CfgNode *TargetTrue, CfgNode *TargetFalse, Operand *Src0,
189            Operand *Src1, CondMIPS32::Cond Condition) {
190     Context.insert<InstMIPS32Br>(TargetTrue, TargetFalse, Src0, Src1,
191                                  Condition);
192   }
193 
_br(CfgNode * TargetTrue,CfgNode * TargetFalse,Operand * Src0,CondMIPS32::Cond Condition)194   void _br(CfgNode *TargetTrue, CfgNode *TargetFalse, Operand *Src0,
195            CondMIPS32::Cond Condition) {
196     Context.insert<InstMIPS32Br>(TargetTrue, TargetFalse, Src0, Condition);
197   }
198 
_br(CfgNode * TargetTrue,CfgNode * TargetFalse,Operand * Src0,Operand * Src1,const InstMIPS32Label * Label,CondMIPS32::Cond Condition)199   void _br(CfgNode *TargetTrue, CfgNode *TargetFalse, Operand *Src0,
200            Operand *Src1, const InstMIPS32Label *Label,
201            CondMIPS32::Cond Condition) {
202     Context.insert<InstMIPS32Br>(TargetTrue, TargetFalse, Src0, Src1, Label,
203                                  Condition);
204   }
205 
206   void _ret(Variable *RA, Variable *Src0 = nullptr) {
207     Context.insert<InstMIPS32Ret>(RA, Src0);
208   }
209 
_abs_d(Variable * Dest,Variable * Src)210   void _abs_d(Variable *Dest, Variable *Src) {
211     Context.insert<InstMIPS32Abs_d>(Dest, Src);
212   }
213 
_abs_s(Variable * Dest,Variable * Src)214   void _abs_s(Variable *Dest, Variable *Src) {
215     Context.insert<InstMIPS32Abs_s>(Dest, Src);
216   }
217 
_addi(Variable * Dest,Variable * Src,uint32_t Imm)218   void _addi(Variable *Dest, Variable *Src, uint32_t Imm) {
219     Context.insert<InstMIPS32Addi>(Dest, Src, Imm);
220   }
221 
_add_d(Variable * Dest,Variable * Src0,Variable * Src1)222   void _add_d(Variable *Dest, Variable *Src0, Variable *Src1) {
223     Context.insert<InstMIPS32Add_d>(Dest, Src0, Src1);
224   }
225 
_add_s(Variable * Dest,Variable * Src0,Variable * Src1)226   void _add_s(Variable *Dest, Variable *Src0, Variable *Src1) {
227     Context.insert<InstMIPS32Add_s>(Dest, Src0, Src1);
228   }
229 
_addiu(Variable * Dest,Variable * Src,uint32_t Imm)230   void _addiu(Variable *Dest, Variable *Src, uint32_t Imm) {
231     Context.insert<InstMIPS32Addiu>(Dest, Src, Imm);
232   }
233 
_addiu(Variable * Dest,Variable * Src0,Operand * Src1,RelocOp Reloc)234   void _addiu(Variable *Dest, Variable *Src0, Operand *Src1, RelocOp Reloc) {
235     Context.insert<InstMIPS32Addiu>(Dest, Src0, Src1, Reloc);
236   }
237 
_c_eq_d(Variable * Src0,Variable * Src1)238   void _c_eq_d(Variable *Src0, Variable *Src1) {
239     Context.insert<InstMIPS32C_eq_d>(Src0, Src1);
240   }
241 
_c_eq_s(Variable * Src0,Variable * Src1)242   void _c_eq_s(Variable *Src0, Variable *Src1) {
243     Context.insert<InstMIPS32C_eq_s>(Src0, Src1);
244   }
245 
_c_ole_d(Variable * Src0,Variable * Src1)246   void _c_ole_d(Variable *Src0, Variable *Src1) {
247     Context.insert<InstMIPS32C_ole_d>(Src0, Src1);
248   }
249 
_c_ole_s(Variable * Src0,Variable * Src1)250   void _c_ole_s(Variable *Src0, Variable *Src1) {
251     Context.insert<InstMIPS32C_ole_s>(Src0, Src1);
252   }
253 
_c_olt_d(Variable * Src0,Variable * Src1)254   void _c_olt_d(Variable *Src0, Variable *Src1) {
255     Context.insert<InstMIPS32C_olt_d>(Src0, Src1);
256   }
257 
_c_olt_s(Variable * Src0,Variable * Src1)258   void _c_olt_s(Variable *Src0, Variable *Src1) {
259     Context.insert<InstMIPS32C_olt_s>(Src0, Src1);
260   }
261 
_c_ueq_d(Variable * Src0,Variable * Src1)262   void _c_ueq_d(Variable *Src0, Variable *Src1) {
263     Context.insert<InstMIPS32C_ueq_d>(Src0, Src1);
264   }
265 
_c_ueq_s(Variable * Src0,Variable * Src1)266   void _c_ueq_s(Variable *Src0, Variable *Src1) {
267     Context.insert<InstMIPS32C_ueq_s>(Src0, Src1);
268   }
269 
_c_ule_d(Variable * Src0,Variable * Src1)270   void _c_ule_d(Variable *Src0, Variable *Src1) {
271     Context.insert<InstMIPS32C_ule_d>(Src0, Src1);
272   }
273 
_c_ule_s(Variable * Src0,Variable * Src1)274   void _c_ule_s(Variable *Src0, Variable *Src1) {
275     Context.insert<InstMIPS32C_ule_s>(Src0, Src1);
276   }
277 
_c_ult_d(Variable * Src0,Variable * Src1)278   void _c_ult_d(Variable *Src0, Variable *Src1) {
279     Context.insert<InstMIPS32C_ult_d>(Src0, Src1);
280   }
281 
_c_ult_s(Variable * Src0,Variable * Src1)282   void _c_ult_s(Variable *Src0, Variable *Src1) {
283     Context.insert<InstMIPS32C_ult_s>(Src0, Src1);
284   }
285 
_c_un_d(Variable * Src0,Variable * Src1)286   void _c_un_d(Variable *Src0, Variable *Src1) {
287     Context.insert<InstMIPS32C_un_d>(Src0, Src1);
288   }
289 
_c_un_s(Variable * Src0,Variable * Src1)290   void _c_un_s(Variable *Src0, Variable *Src1) {
291     Context.insert<InstMIPS32C_un_s>(Src0, Src1);
292   }
293 
_clz(Variable * Dest,Variable * Src)294   void _clz(Variable *Dest, Variable *Src) {
295     Context.insert<InstMIPS32Clz>(Dest, Src);
296   }
297 
_cvt_d_l(Variable * Dest,Variable * Src)298   void _cvt_d_l(Variable *Dest, Variable *Src) {
299     Context.insert<InstMIPS32Cvt_d_l>(Dest, Src);
300   }
301 
_cvt_d_s(Variable * Dest,Variable * Src)302   void _cvt_d_s(Variable *Dest, Variable *Src) {
303     Context.insert<InstMIPS32Cvt_d_s>(Dest, Src);
304   }
305 
_cvt_d_w(Variable * Dest,Variable * Src)306   void _cvt_d_w(Variable *Dest, Variable *Src) {
307     Context.insert<InstMIPS32Cvt_d_w>(Dest, Src);
308   }
309 
_cvt_s_d(Variable * Dest,Variable * Src)310   void _cvt_s_d(Variable *Dest, Variable *Src) {
311     Context.insert<InstMIPS32Cvt_s_d>(Dest, Src);
312   }
313 
_cvt_s_l(Variable * Dest,Variable * Src)314   void _cvt_s_l(Variable *Dest, Variable *Src) {
315     Context.insert<InstMIPS32Cvt_s_l>(Dest, Src);
316   }
317 
_cvt_s_w(Variable * Dest,Variable * Src)318   void _cvt_s_w(Variable *Dest, Variable *Src) {
319     Context.insert<InstMIPS32Cvt_s_w>(Dest, Src);
320   }
321 
_div(Variable * Dest,Variable * Src0,Variable * Src1)322   void _div(Variable *Dest, Variable *Src0, Variable *Src1) {
323     Context.insert<InstMIPS32Div>(Dest, Src0, Src1);
324   }
325 
_div_d(Variable * Dest,Variable * Src0,Variable * Src1)326   void _div_d(Variable *Dest, Variable *Src0, Variable *Src1) {
327     Context.insert<InstMIPS32Div_d>(Dest, Src0, Src1);
328   }
329 
_div_s(Variable * Dest,Variable * Src0,Variable * Src1)330   void _div_s(Variable *Dest, Variable *Src0, Variable *Src1) {
331     Context.insert<InstMIPS32Div_s>(Dest, Src0, Src1);
332   }
333 
_divu(Variable * Dest,Variable * Src0,Variable * Src1)334   void _divu(Variable *Dest, Variable *Src0, Variable *Src1) {
335     Context.insert<InstMIPS32Divu>(Dest, Src0, Src1);
336   }
337 
338   void _ldc1(Variable *Value, OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) {
339     Context.insert<InstMIPS32Ldc1>(Value, Mem, Reloc);
340   }
341 
_ll(Variable * Value,OperandMIPS32Mem * Mem)342   void _ll(Variable *Value, OperandMIPS32Mem *Mem) {
343     Context.insert<InstMIPS32Ll>(Value, Mem);
344   }
345 
_lw(Variable * Value,OperandMIPS32Mem * Mem)346   void _lw(Variable *Value, OperandMIPS32Mem *Mem) {
347     Context.insert<InstMIPS32Lw>(Value, Mem);
348   }
349 
350   void _lwc1(Variable *Value, OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) {
351     Context.insert<InstMIPS32Lwc1>(Value, Mem, Reloc);
352   }
353 
354   void _lui(Variable *Dest, Operand *Src, RelocOp Reloc = RO_No) {
355     Context.insert<InstMIPS32Lui>(Dest, Src, Reloc);
356   }
357 
_mfc1(Variable * Dest,Variable * Src)358   void _mfc1(Variable *Dest, Variable *Src) {
359     Context.insert<InstMIPS32Mfc1>(Dest, Src);
360   }
361 
_mfhi(Variable * Dest,Operand * Src)362   void _mfhi(Variable *Dest, Operand *Src) {
363     Context.insert<InstMIPS32Mfhi>(Dest, Src);
364   }
365 
_mflo(Variable * Dest,Operand * Src)366   void _mflo(Variable *Dest, Operand *Src) {
367     Context.insert<InstMIPS32Mflo>(Dest, Src);
368   }
369 
370   void _mov(Variable *Dest, Operand *Src0, Operand *Src1 = nullptr) {
371     assert(Dest != nullptr);
372     // Variable* Src0_ = llvm::dyn_cast<Variable>(Src0);
373     if (llvm::isa<ConstantRelocatable>(Src0)) {
374       Context.insert<InstMIPS32La>(Dest, Src0);
375     } else {
376       auto *Instr = Context.insert<InstMIPS32Mov>(Dest, Src0, Src1);
377       if (Instr->getDestHi() != nullptr) {
378         // If DestHi is available, then Dest must be a Variable64On32. We add a
379         // fake-def for Instr.DestHi here.
380         assert(llvm::isa<Variable64On32>(Dest));
381         Context.insert<InstFakeDef>(Instr->getDestHi());
382       }
383     }
384   }
385 
386   void _mov_redefined(Variable *Dest, Operand *Src0, Operand *Src1 = nullptr) {
387     if (llvm::isa<ConstantRelocatable>(Src0)) {
388       Context.insert<InstMIPS32La>(Dest, Src0);
389     } else {
390       auto *Instr = Context.insert<InstMIPS32Mov>(Dest, Src0, Src1);
391       Instr->setDestRedefined();
392       if (Instr->getDestHi() != nullptr) {
393         // If Instr is multi-dest, then Dest must be a Variable64On32. We add a
394         // fake-def for Instr.DestHi here.
395         assert(llvm::isa<Variable64On32>(Dest));
396         Context.insert<InstFakeDef>(Instr->getDestHi());
397       }
398     }
399   }
400 
_mov_fp64_to_i64(Variable * Dest,Operand * Src,Int64Part Int64HiLo)401   void _mov_fp64_to_i64(Variable *Dest, Operand *Src, Int64Part Int64HiLo) {
402     assert(Dest != nullptr);
403     Context.insert<InstMIPS32MovFP64ToI64>(Dest, Src, Int64HiLo);
404   }
405 
_mov_d(Variable * Dest,Variable * Src)406   void _mov_d(Variable *Dest, Variable *Src) {
407     Context.insert<InstMIPS32Mov_d>(Dest, Src);
408   }
409 
_mov_s(Variable * Dest,Variable * Src)410   void _mov_s(Variable *Dest, Variable *Src) {
411     Context.insert<InstMIPS32Mov_s>(Dest, Src);
412   }
413 
_movf(Variable * Dest,Variable * Src0,Operand * FCC)414   void _movf(Variable *Dest, Variable *Src0, Operand *FCC) {
415     Context.insert<InstMIPS32Movf>(Dest, Src0, FCC)->setDestRedefined();
416   }
417 
_movn(Variable * Dest,Variable * Src0,Variable * Src1)418   void _movn(Variable *Dest, Variable *Src0, Variable *Src1) {
419     Context.insert<InstMIPS32Movn>(Dest, Src0, Src1)->setDestRedefined();
420   }
421 
_movn_d(Variable * Dest,Variable * Src0,Variable * Src1)422   void _movn_d(Variable *Dest, Variable *Src0, Variable *Src1) {
423     Context.insert<InstMIPS32Movn_d>(Dest, Src0, Src1)->setDestRedefined();
424   }
425 
_movn_s(Variable * Dest,Variable * Src0,Variable * Src1)426   void _movn_s(Variable *Dest, Variable *Src0, Variable *Src1) {
427     Context.insert<InstMIPS32Movn_s>(Dest, Src0, Src1)->setDestRedefined();
428   }
429 
_movt(Variable * Dest,Variable * Src0,Operand * FCC)430   void _movt(Variable *Dest, Variable *Src0, Operand *FCC) {
431     Context.insert<InstMIPS32Movt>(Dest, Src0, FCC)->setDestRedefined();
432   }
433 
_movz(Variable * Dest,Variable * Src0,Variable * Src1)434   void _movz(Variable *Dest, Variable *Src0, Variable *Src1) {
435     Context.insert<InstMIPS32Movz>(Dest, Src0, Src1)->setDestRedefined();
436   }
437 
_movz_d(Variable * Dest,Variable * Src0,Variable * Src1)438   void _movz_d(Variable *Dest, Variable *Src0, Variable *Src1) {
439     Context.insert<InstMIPS32Movz_d>(Dest, Src0, Src1)->setDestRedefined();
440   }
441 
_movz_s(Variable * Dest,Variable * Src0,Variable * Src1)442   void _movz_s(Variable *Dest, Variable *Src0, Variable *Src1) {
443     Context.insert<InstMIPS32Movz_s>(Dest, Src0, Src1)->setDestRedefined();
444   }
445 
_mtc1(Variable * Dest,Variable * Src)446   void _mtc1(Variable *Dest, Variable *Src) {
447     Context.insert<InstMIPS32Mtc1>(Dest, Src);
448   }
449 
_mthi(Variable * Dest,Operand * Src)450   void _mthi(Variable *Dest, Operand *Src) {
451     Context.insert<InstMIPS32Mthi>(Dest, Src);
452   }
453 
_mtlo(Variable * Dest,Operand * Src)454   void _mtlo(Variable *Dest, Operand *Src) {
455     Context.insert<InstMIPS32Mtlo>(Dest, Src);
456   }
457 
_mul(Variable * Dest,Variable * Src0,Variable * Src1)458   void _mul(Variable *Dest, Variable *Src0, Variable *Src1) {
459     Context.insert<InstMIPS32Mul>(Dest, Src0, Src1);
460   }
461 
_mul_d(Variable * Dest,Variable * Src0,Variable * Src1)462   void _mul_d(Variable *Dest, Variable *Src0, Variable *Src1) {
463     Context.insert<InstMIPS32Mul_d>(Dest, Src0, Src1);
464   }
465 
_mul_s(Variable * Dest,Variable * Src0,Variable * Src1)466   void _mul_s(Variable *Dest, Variable *Src0, Variable *Src1) {
467     Context.insert<InstMIPS32Mul_s>(Dest, Src0, Src1);
468   }
469 
_mult(Variable * Dest,Variable * Src0,Variable * Src1)470   void _mult(Variable *Dest, Variable *Src0, Variable *Src1) {
471     Context.insert<InstMIPS32Mult>(Dest, Src0, Src1);
472   }
473 
_multu(Variable * Dest,Variable * Src0,Variable * Src1)474   void _multu(Variable *Dest, Variable *Src0, Variable *Src1) {
475     Context.insert<InstMIPS32Multu>(Dest, Src0, Src1);
476   }
477 
_nop()478   void _nop() { Context.insert<InstMIPS32Sll>(getZero(), getZero(), 0); }
479 
_nor(Variable * Dest,Variable * Src0,Variable * Src1)480   void _nor(Variable *Dest, Variable *Src0, Variable *Src1) {
481     Context.insert<InstMIPS32Nor>(Dest, Src0, Src1);
482   }
483 
_not(Variable * Dest,Variable * Src0)484   void _not(Variable *Dest, Variable *Src0) {
485     Context.insert<InstMIPS32Nor>(Dest, Src0, getZero());
486   }
487 
_or(Variable * Dest,Variable * Src0,Variable * Src1)488   void _or(Variable *Dest, Variable *Src0, Variable *Src1) {
489     Context.insert<InstMIPS32Or>(Dest, Src0, Src1);
490   }
491 
_ori(Variable * Dest,Variable * Src,uint32_t Imm)492   void _ori(Variable *Dest, Variable *Src, uint32_t Imm) {
493     Context.insert<InstMIPS32Ori>(Dest, Src, Imm);
494   }
495 
_sc(Variable * Value,OperandMIPS32Mem * Mem)496   InstMIPS32Sc *_sc(Variable *Value, OperandMIPS32Mem *Mem) {
497     return Context.insert<InstMIPS32Sc>(Value, Mem);
498   }
499 
_sdc1(Variable * Value,OperandMIPS32Mem * Mem)500   void _sdc1(Variable *Value, OperandMIPS32Mem *Mem) {
501     Context.insert<InstMIPS32Sdc1>(Value, Mem);
502   }
503 
_sll(Variable * Dest,Variable * Src,uint32_t Imm)504   void _sll(Variable *Dest, Variable *Src, uint32_t Imm) {
505     Context.insert<InstMIPS32Sll>(Dest, Src, Imm);
506   }
507 
_sllv(Variable * Dest,Variable * Src0,Variable * Src1)508   void _sllv(Variable *Dest, Variable *Src0, Variable *Src1) {
509     Context.insert<InstMIPS32Sllv>(Dest, Src0, Src1);
510   }
511 
_slt(Variable * Dest,Variable * Src0,Variable * Src1)512   void _slt(Variable *Dest, Variable *Src0, Variable *Src1) {
513     Context.insert<InstMIPS32Slt>(Dest, Src0, Src1);
514   }
515 
_slti(Variable * Dest,Variable * Src,uint32_t Imm)516   void _slti(Variable *Dest, Variable *Src, uint32_t Imm) {
517     Context.insert<InstMIPS32Slti>(Dest, Src, Imm);
518   }
519 
_sltiu(Variable * Dest,Variable * Src,uint32_t Imm)520   void _sltiu(Variable *Dest, Variable *Src, uint32_t Imm) {
521     Context.insert<InstMIPS32Sltiu>(Dest, Src, Imm);
522   }
523 
_sltu(Variable * Dest,Variable * Src0,Variable * Src1)524   void _sltu(Variable *Dest, Variable *Src0, Variable *Src1) {
525     Context.insert<InstMIPS32Sltu>(Dest, Src0, Src1);
526   }
527 
_sqrt_d(Variable * Dest,Variable * Src)528   void _sqrt_d(Variable *Dest, Variable *Src) {
529     Context.insert<InstMIPS32Sqrt_d>(Dest, Src);
530   }
531 
_sqrt_s(Variable * Dest,Variable * Src)532   void _sqrt_s(Variable *Dest, Variable *Src) {
533     Context.insert<InstMIPS32Sqrt_s>(Dest, Src);
534   }
535 
_sra(Variable * Dest,Variable * Src,uint32_t Imm)536   void _sra(Variable *Dest, Variable *Src, uint32_t Imm) {
537     Context.insert<InstMIPS32Sra>(Dest, Src, Imm);
538   }
539 
_srav(Variable * Dest,Variable * Src0,Variable * Src1)540   void _srav(Variable *Dest, Variable *Src0, Variable *Src1) {
541     Context.insert<InstMIPS32Srav>(Dest, Src0, Src1);
542   }
543 
_srl(Variable * Dest,Variable * Src,uint32_t Imm)544   void _srl(Variable *Dest, Variable *Src, uint32_t Imm) {
545     Context.insert<InstMIPS32Srl>(Dest, Src, Imm);
546   }
547 
_srlv(Variable * Dest,Variable * Src0,Variable * Src1)548   void _srlv(Variable *Dest, Variable *Src0, Variable *Src1) {
549     Context.insert<InstMIPS32Srlv>(Dest, Src0, Src1);
550   }
551 
_sub(Variable * Dest,Variable * Src0,Variable * Src1)552   void _sub(Variable *Dest, Variable *Src0, Variable *Src1) {
553     Context.insert<InstMIPS32Sub>(Dest, Src0, Src1);
554   }
555 
_sub_d(Variable * Dest,Variable * Src0,Variable * Src1)556   void _sub_d(Variable *Dest, Variable *Src0, Variable *Src1) {
557     Context.insert<InstMIPS32Sub_d>(Dest, Src0, Src1);
558   }
559 
_sub_s(Variable * Dest,Variable * Src0,Variable * Src1)560   void _sub_s(Variable *Dest, Variable *Src0, Variable *Src1) {
561     Context.insert<InstMIPS32Sub_s>(Dest, Src0, Src1);
562   }
563 
_subu(Variable * Dest,Variable * Src0,Variable * Src1)564   void _subu(Variable *Dest, Variable *Src0, Variable *Src1) {
565     Context.insert<InstMIPS32Subu>(Dest, Src0, Src1);
566   }
567 
_sw(Variable * Value,OperandMIPS32Mem * Mem)568   void _sw(Variable *Value, OperandMIPS32Mem *Mem) {
569     Context.insert<InstMIPS32Sw>(Value, Mem);
570   }
571 
_swc1(Variable * Value,OperandMIPS32Mem * Mem)572   void _swc1(Variable *Value, OperandMIPS32Mem *Mem) {
573     Context.insert<InstMIPS32Swc1>(Value, Mem);
574   }
575 
_sync()576   void _sync() { Context.insert<InstMIPS32Sync>(); }
577 
_teq(Variable * Src0,Variable * Src1,uint32_t TrapCode)578   void _teq(Variable *Src0, Variable *Src1, uint32_t TrapCode) {
579     Context.insert<InstMIPS32Teq>(Src0, Src1, TrapCode);
580   }
581 
_trunc_l_d(Variable * Dest,Variable * Src)582   void _trunc_l_d(Variable *Dest, Variable *Src) {
583     Context.insert<InstMIPS32Trunc_l_d>(Dest, Src);
584   }
585 
_trunc_l_s(Variable * Dest,Variable * Src)586   void _trunc_l_s(Variable *Dest, Variable *Src) {
587     Context.insert<InstMIPS32Trunc_l_s>(Dest, Src);
588   }
589 
_trunc_w_d(Variable * Dest,Variable * Src)590   void _trunc_w_d(Variable *Dest, Variable *Src) {
591     Context.insert<InstMIPS32Trunc_w_d>(Dest, Src);
592   }
593 
_trunc_w_s(Variable * Dest,Variable * Src)594   void _trunc_w_s(Variable *Dest, Variable *Src) {
595     Context.insert<InstMIPS32Trunc_w_s>(Dest, Src);
596   }
597 
_xor(Variable * Dest,Variable * Src0,Variable * Src1)598   void _xor(Variable *Dest, Variable *Src0, Variable *Src1) {
599     Context.insert<InstMIPS32Xor>(Dest, Src0, Src1);
600   }
601 
_xori(Variable * Dest,Variable * Src,uint32_t Imm)602   void _xori(Variable *Dest, Variable *Src, uint32_t Imm) {
603     Context.insert<InstMIPS32Xori>(Dest, Src, Imm);
604   }
605 
606   void lowerArguments() override;
607 
608   /// Make a pass through the SortedSpilledVariables and actually assign stack
609   /// slots. SpillAreaPaddingBytes takes into account stack alignment padding.
610   /// The SpillArea starts after that amount of padding. This matches the scheme
611   /// in getVarStackSlotParams, where there may be a separate multi-block global
612   /// var spill area and a local var spill area.
613   void assignVarStackSlots(VarList &SortedSpilledVariables,
614                            size_t SpillAreaPaddingBytes,
615                            size_t SpillAreaSizeBytes,
616                            size_t GlobalsAndSubsequentPaddingSize);
617 
618   /// Operand legalization helpers.  To deal with address mode constraints,
619   /// the helpers will create a new Operand and emit instructions that
620   /// guarantee that the Operand kind is one of those indicated by the
621   /// LegalMask (a bitmask of allowed kinds).  If the input Operand is known
622   /// to already meet the constraints, it may be simply returned as the result,
623   /// without creating any new instructions or operands.
624   enum OperandLegalization {
625     Legal_None = 0,
626     Legal_Reg = 1 << 0, // physical register, not stack location
627     Legal_Imm = 1 << 1,
628     Legal_Mem = 1 << 2,
629     Legal_Rematerializable = 1 << 3,
630     Legal_Default = ~Legal_None
631   };
632   typedef uint32_t LegalMask;
633   Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
634                     RegNumT RegNum = RegNumT());
635 
636   Variable *legalizeToVar(Operand *From, RegNumT RegNum = RegNumT());
637 
638   Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT());
639 
640   Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT());
641 
getZero()642   Variable *getZero() {
643     auto *Zero = makeReg(IceType_i32, RegMIPS32::Reg_ZERO);
644     Context.insert<InstFakeDef>(Zero);
645     return Zero;
646   }
647 
648   Variable *I32Reg(RegNumT RegNum = RegNumT()) {
649     return makeReg(IceType_i32, RegNum);
650   }
651 
652   Variable *F32Reg(RegNumT RegNum = RegNumT()) {
653     return makeReg(IceType_f32, RegNum);
654   }
655 
656   Variable *F64Reg(RegNumT RegNum = RegNumT()) {
657     return makeReg(IceType_f64, RegNum);
658   }
659 
660   static Type stackSlotType();
661   Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT());
662 
663   void unsetIfNonLeafFunc();
664 
665   // Iterates over the CFG and determines the maximum outgoing stack arguments
666   // bytes. This information is later used during addProlog() to pre-allocate
667   // the outargs area
668   void findMaxStackOutArgsSize();
669 
670   void postLowerLegalization();
671 
672   void addProlog(CfgNode *Node) override;
673   void addEpilog(CfgNode *Node) override;
674 
675   // Ensure that a 64-bit Variable has been split into 2 32-bit
676   // Variables, creating them if necessary.  This is needed for all
677   // I64 operations.
678   void split64(Variable *Var);
679   Operand *loOperand(Operand *Operand);
680   Operand *hiOperand(Operand *Operand);
681   Operand *getOperandAtIndex(Operand *Operand, Type BaseType, uint32_t Index);
682 
683   void finishArgumentLowering(Variable *Arg, bool PartialOnStack,
684                               Variable *FramePtr, size_t BasicFrameOffset,
685                               size_t *InArgsSizeBytes);
686 
687   Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT());
688 
689   /// Helper class that understands the Calling Convention and register
690   /// assignments as per MIPS O32 abi.
691   class CallingConv {
692     CallingConv(const CallingConv &) = delete;
693     CallingConv &operator=(const CallingConv &) = delete;
694 
695   public:
696     CallingConv();
697     ~CallingConv() = default;
698 
699     /// argInReg returns true if there is a Register available for the requested
700     /// type, and false otherwise. If it returns true, Reg is set to the
701     /// appropriate register number. Note that, when Ty == IceType_i64, Reg will
702     /// be an I64 register pair.
703     bool argInReg(Type Ty, uint32_t ArgNo, RegNumT *Reg);
discardReg(RegNumT Reg)704     void discardReg(RegNumT Reg) { GPRegsUsed |= RegisterAliases[Reg]; }
705 
706   private:
707     // argInGPR is used to find if any GPR register is available for argument of
708     // type Ty
709     bool argInGPR(Type Ty, RegNumT *Reg);
710     /// argInVFP is to floating-point/vector types what argInGPR is for integer
711     /// types.
712     bool argInVFP(Type Ty, RegNumT *Reg);
713     inline void discardNextGPRAndItsAliases(CfgVector<RegNumT> *Regs);
714     inline void alignGPR(CfgVector<RegNumT> *Regs);
715     void discardUnavailableGPRsAndTheirAliases(CfgVector<RegNumT> *Regs);
716     SmallBitVector GPRegsUsed;
717     CfgVector<RegNumT> GPRArgs;
718     CfgVector<RegNumT> I64Args;
719 
720     void discardUnavailableVFPRegsAndTheirAliases(CfgVector<RegNumT> *Regs);
721     SmallBitVector VFPRegsUsed;
722     CfgVector<RegNumT> FP32Args;
723     CfgVector<RegNumT> FP64Args;
724     // UseFPRegs is a flag indicating if FP registers can be used
725     bool UseFPRegs = false;
726   };
727 
728 protected:
729   explicit TargetMIPS32(Cfg *Func);
730 
731   void postLower() override;
732 
733   void lowerAlloca(const InstAlloca *Instr) override;
734   void lowerArithmetic(const InstArithmetic *Instr) override;
735   void lowerInt64Arithmetic(const InstArithmetic *Instr, Variable *Dest,
736                             Operand *Src0, Operand *Src1);
737   void lowerAssign(const InstAssign *Instr) override;
738   void lowerBr(const InstBr *Instr) override;
739   void lowerBreakpoint(const InstBreakpoint *Instr) override;
740   void lowerCall(const InstCall *Instr) override;
741   void lowerCast(const InstCast *Instr) override;
742   void lowerExtractElement(const InstExtractElement *Instr) override;
743   void lowerFcmp(const InstFcmp *Instr) override;
744   void lowerIcmp(const InstIcmp *Instr) override;
745   void lower64Icmp(const InstIcmp *Instr);
746   void createArithInst(Intrinsics::AtomicRMWOperation Operation, Variable *Dest,
747                        Variable *Src0, Variable *Src1);
748   void lowerIntrinsic(const InstIntrinsic *Instr) override;
749   void lowerInsertElement(const InstInsertElement *Instr) override;
750   void lowerLoad(const InstLoad *Instr) override;
751   void lowerPhi(const InstPhi *Instr) override;
752   void lowerRet(const InstRet *Instr) override;
753   void lowerSelect(const InstSelect *Instr) override;
754   void lowerShuffleVector(const InstShuffleVector *Instr) override;
755   void lowerStore(const InstStore *Instr) override;
756   void lowerSwitch(const InstSwitch *Instr) override;
757   void lowerUnreachable(const InstUnreachable *Instr) override;
758   void lowerOther(const Inst *Instr) override;
759   void prelowerPhis() override;
760   uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override;
761   void genTargetHelperCallFor(Inst *Instr) override;
762   void doAddressOptLoad() override;
763   void doAddressOptStore() override;
764 
765   OperandMIPS32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
766 
767   class PostLoweringLegalizer {
768     PostLoweringLegalizer() = delete;
769     PostLoweringLegalizer(const PostLoweringLegalizer &) = delete;
770     PostLoweringLegalizer &operator=(const PostLoweringLegalizer &) = delete;
771 
772   public:
PostLoweringLegalizer(TargetMIPS32 * Target)773     explicit PostLoweringLegalizer(TargetMIPS32 *Target)
774         : Target(Target), StackOrFrameReg(Target->getPhysicalRegister(
775                               Target->getFrameOrStackReg())) {}
776 
777     /// Legalizes Mem. if Mem.Base is a rematerializable variable,
778     /// Mem.Offset is fixed up.
779     OperandMIPS32Mem *legalizeMemOperand(OperandMIPS32Mem *Mem);
780 
781     /// Legalizes Immediate if larger value overflows range of 16 bits
782     Variable *legalizeImmediate(int32_t Imm);
783 
784     /// Legalizes Mov if its Source (or Destination) is a spilled Variable, or
785     /// if its Source is a Rematerializable variable (this form is used in lieu
786     /// of lea, which is not available in MIPS.)
787     ///
788     /// Moves to memory become store instructions, and moves from memory, loads.
789     void legalizeMov(InstMIPS32Mov *Mov);
790     void legalizeMovFp(InstMIPS32MovFP64ToI64 *MovInstr);
791 
792   private:
793     /// Creates a new Base register centered around [Base, +/- Offset].
794     Variable *newBaseRegister(Variable *Base, int32_t Offset,
795                               RegNumT ScratchRegNum);
796 
797     TargetMIPS32 *const Target;
798     Variable *const StackOrFrameReg;
799   };
800 
801   bool UsesFramePointer = false;
802   bool NeedsStackAlignment = false;
803   bool MaybeLeafFunc = true;
804   bool PrologEmitsFixedAllocas = false;
805   bool VariableAllocaUsed = false;
806   uint32_t MaxOutArgsSizeBytes = 0;
807   uint32_t TotalStackSizeBytes = 0;
808   uint32_t CurrentAllocaOffset = 0;
809   uint32_t VariableAllocaAlignBytes = 0;
810   static SmallBitVector TypeToRegisterSet[RCMIPS32_NUM];
811   static SmallBitVector TypeToRegisterSetUnfiltered[RCMIPS32_NUM];
812   static SmallBitVector RegisterAliases[RegMIPS32::Reg_NUM];
813   SmallBitVector RegsUsed;
814   VarList PhysicalRegisters[IceType_NUM];
815   VarList PreservedGPRs;
816   static constexpr uint32_t CHAR_BITS = 8;
817   static constexpr uint32_t INT32_BITS = 32;
818   size_t SpillAreaSizeBytes = 0;
819   size_t FixedAllocaSizeBytes = 0;
820   size_t FixedAllocaAlignBytes = 0;
821   size_t PreservedRegsSizeBytes = 0;
822   Variable *ImplicitRet = nullptr; /// Implicit return
823 
824 private:
825   ENABLE_MAKE_UNIQUE;
826 
827   OperandMIPS32Mem *formAddressingMode(Type Ty, Cfg *Func, const Inst *LdSt,
828                                        Operand *Base);
829 
830   class ComputationTracker {
831   public:
832     ComputationTracker() = default;
833     ~ComputationTracker() = default;
834 
forgetProducers()835     void forgetProducers() { KnownComputations.clear(); }
836     void recordProducers(CfgNode *Node);
837 
getProducerOf(const Operand * Opnd)838     const Inst *getProducerOf(const Operand *Opnd) const {
839       auto *Var = llvm::dyn_cast<Variable>(Opnd);
840       if (Var == nullptr) {
841         return nullptr;
842       }
843 
844       auto Iter = KnownComputations.find(Var->getIndex());
845       if (Iter == KnownComputations.end()) {
846         return nullptr;
847       }
848 
849       return Iter->second.Instr;
850     }
851 
dump(const Cfg * Func)852     void dump(const Cfg *Func) const {
853       if (!BuildDefs::dump() || !Func->isVerbose(IceV_Folding))
854         return;
855       OstreamLocker L(Func->getContext());
856       Ostream &Str = Func->getContext()->getStrDump();
857       Str << "foldable producer:\n";
858       for (const auto &Computation : KnownComputations) {
859         Str << "    ";
860         Computation.second.Instr->dump(Func);
861         Str << "\n";
862       }
863       Str << "\n";
864     }
865 
866   private:
867     class ComputationEntry {
868     public:
ComputationEntry(Inst * I,Type Ty)869       ComputationEntry(Inst *I, Type Ty) : Instr(I), ComputationType(Ty) {}
870       Inst *const Instr;
871       // Boolean folding is disabled for variables whose live range is multi
872       // block. We conservatively initialize IsLiveOut to true, and set it to
873       // false once we find the end of the live range for the variable defined
874       // by this instruction. If liveness analysis is not performed (e.g., in
875       // Om1 mode) IsLiveOut will never be set to false, and folding will be
876       // disabled.
877       bool IsLiveOut = true;
878       int32_t NumUses = 0;
879       Type ComputationType;
880     };
881 
882     // ComputationMap maps a Variable number to a payload identifying which
883     // instruction defined it.
884     using ComputationMap = CfgUnorderedMap<SizeT, ComputationEntry>;
885     ComputationMap KnownComputations;
886   };
887 
888   ComputationTracker Computations;
889 };
890 
891 class TargetDataMIPS32 final : public TargetDataLowering {
892   TargetDataMIPS32() = delete;
893   TargetDataMIPS32(const TargetDataMIPS32 &) = delete;
894   TargetDataMIPS32 &operator=(const TargetDataMIPS32 &) = delete;
895 
896 public:
create(GlobalContext * Ctx)897   static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
898     return std::unique_ptr<TargetDataLowering>(new TargetDataMIPS32(Ctx));
899   }
900 
901   void lowerGlobals(const VariableDeclarationList &Vars,
902                     const std::string &SectionSuffix) override;
903   void lowerConstants() override;
904   void lowerJumpTables() override;
905   void emitTargetRODataSections() override;
906 
907 protected:
908   explicit TargetDataMIPS32(GlobalContext *Ctx);
909 
910 private:
911   ~TargetDataMIPS32() override = default;
912 };
913 
914 class TargetHeaderMIPS32 final : public TargetHeaderLowering {
915   TargetHeaderMIPS32() = delete;
916   TargetHeaderMIPS32(const TargetHeaderMIPS32 &) = delete;
917   TargetHeaderMIPS32 &operator=(const TargetHeaderMIPS32 &) = delete;
918 
919 public:
create(GlobalContext * Ctx)920   static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
921     return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderMIPS32(Ctx));
922   }
923 
924   void lower() override;
925 
926 protected:
927   explicit TargetHeaderMIPS32(GlobalContext *Ctx);
928 
929 private:
930   ~TargetHeaderMIPS32() = default;
931 };
932 
933 // This structure (with some minor modifications) is copied from
934 // llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h file.
935 struct MipsABIFlagsSection {
936 
937   // Version of the MIPS.abiflags section
938   enum AFL_VERSION {
939     AFL_VERSION_V0 = 0 // Version 0
940   };
941 
942   // The level of the ISA: 1-5, 32, 64.
943   enum AFL_ISA_LEVEL {
944     AFL_ISA_LEVEL_NONE = 0,
945     AFL_ISA_LEVEL_MIPS32 = 32, // MIPS32
946   };
947 
948   // The revision of ISA: 0 for MIPS V and below, 1-n otherwise.
949   enum AFL_ISA_REV {
950     AFL_ISA_REV_NONE = 0,
951     AFL_ISA_REV_R1 = 1, // R1
952   };
953 
954   // Values for the xxx_size bytes of an ABI flags structure.
955   enum AFL_REG {
956     AFL_REG_NONE = 0x00, // No registers.
957     AFL_REG_32 = 0x01,   // 32-bit registers.
958     AFL_REG_64 = 0x02,   // 64-bit registers.
959     AFL_REG_128 = 0x03   // 128-bit registers.
960   };
961 
962   // Values for the fp_abi word of an ABI flags structure.
963   enum AFL_FP_ABI {
964     AFL_FP_ANY = 0,
965     AFL_FP_DOUBLE = 1,
966     AFL_FP_XX = 5,
967     AFL_FP_64 = 6,
968     AFL_FP_64A = 7
969   };
970 
971   // Values for the isa_ext word of an ABI flags structure.
972   enum AFL_EXT {
973     AFL_EXT_NONE = 0,
974     AFL_EXT_XLR = 1,          // RMI Xlr instruction.
975     AFL_EXT_OCTEON2 = 2,      // Cavium Networks Octeon2.
976     AFL_EXT_OCTEONP = 3,      // Cavium Networks OcteonP.
977     AFL_EXT_LOONGSON_3A = 4,  // Loongson 3A.
978     AFL_EXT_OCTEON = 5,       // Cavium Networks Octeon.
979     AFL_EXT_5900 = 6,         // MIPS R5900 instruction.
980     AFL_EXT_4650 = 7,         // MIPS R4650 instruction.
981     AFL_EXT_4010 = 8,         // LSI R4010 instruction.
982     AFL_EXT_4100 = 9,         // NEC VR4100 instruction.
983     AFL_EXT_3900 = 10,        // Toshiba R3900 instruction.
984     AFL_EXT_10000 = 11,       // MIPS R10000 instruction.
985     AFL_EXT_SB1 = 12,         // Broadcom SB-1 instruction.
986     AFL_EXT_4111 = 13,        // NEC VR4111/VR4181 instruction.
987     AFL_EXT_4120 = 14,        // NEC VR4120 instruction.
988     AFL_EXT_5400 = 15,        // NEC VR5400 instruction.
989     AFL_EXT_5500 = 16,        // NEC VR5500 instruction.
990     AFL_EXT_LOONGSON_2E = 17, // ST Microelectronics Loongson 2E.
991     AFL_EXT_LOONGSON_2F = 18  // ST Microelectronics Loongson 2F.
992   };
993 
994   // Masks for the ases word of an ABI flags structure.
995   enum AFL_ASE {
996     AFL_ASE_NONE = 0x00000000,
997     AFL_ASE_DSP = 0x00000001,       // DSP ASE.
998     AFL_ASE_DSPR2 = 0x00000002,     // DSP R2 ASE.
999     AFL_ASE_EVA = 0x00000004,       // Enhanced VA Scheme.
1000     AFL_ASE_MCU = 0x00000008,       // MCU (MicroController) ASE.
1001     AFL_ASE_MDMX = 0x00000010,      // MDMX ASE.
1002     AFL_ASE_MIPS3D = 0x00000020,    // MIPS-3D ASE.
1003     AFL_ASE_MT = 0x00000040,        // MT ASE.
1004     AFL_ASE_SMARTMIPS = 0x00000080, // SmartMIPS ASE.
1005     AFL_ASE_VIRT = 0x00000100,      // VZ ASE.
1006     AFL_ASE_MSA = 0x00000200,       // MSA ASE.
1007     AFL_ASE_MIPS16 = 0x00000400,    // MIPS16 ASE.
1008     AFL_ASE_MICROMIPS = 0x00000800, // MICROMIPS ASE.
1009     AFL_ASE_XPA = 0x00001000        // XPA ASE.
1010   };
1011 
1012   enum AFL_FLAGS1 { AFL_FLAGS1_NONE = 0, AFL_FLAGS1_ODDSPREG = 1 };
1013 
1014   enum AFL_FLAGS2 { AFL_FLAGS2_NONE = 0 };
1015 
1016   uint16_t Version = AFL_VERSION_V0;
1017   uint8_t ISALevel = AFL_ISA_LEVEL_MIPS32;
1018   uint8_t ISARevision = AFL_ISA_REV_R1;
1019   uint8_t GPRSize = AFL_REG_32;
1020   uint8_t CPR1Size = AFL_REG_32;
1021   uint8_t CPR2Size = AFL_REG_NONE;
1022   uint8_t FPABI = AFL_FP_DOUBLE;
1023   uint32_t Extension = AFL_EXT_NONE;
1024   uint32_t ASE = AFL_ASE_NONE;
1025   uint32_t Flags1 = AFL_FLAGS1_ODDSPREG;
1026   uint32_t Flags2 = AFL_FLAGS2_NONE;
1027 
1028   MipsABIFlagsSection() = default;
1029 };
1030 
1031 } // end of namespace MIPS32
1032 } // end of namespace Ice
1033 
1034 #endif // SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H
1035