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