Home | History | Annotate | Download | only in src
      1 //===- subzero/src/IceAssemblerMIPS32.h - Assembler for MIPS ----*- 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 Assembler class for MIPS32.
     12 ///
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef SUBZERO_SRC_ICEASSEMBLERMIPS32_H
     16 #define SUBZERO_SRC_ICEASSEMBLERMIPS32_H
     17 
     18 #include "IceAssembler.h"
     19 #include "IceDefs.h"
     20 #include "IceFixups.h"
     21 #include "IceInstMIPS32.h"
     22 #include "IceTargetLowering.h"
     23 
     24 namespace Ice {
     25 namespace MIPS32 {
     26 
     27 using IValueT = uint32_t;
     28 using IOffsetT = int32_t;
     29 
     30 enum FPInstDataFormat {
     31   SinglePrecision = 16,
     32   DoublePrecision = 17,
     33   Word = 20,
     34   Long = 21
     35 };
     36 
     37 class MIPS32Fixup final : public AssemblerFixup {
     38   MIPS32Fixup &operator=(const MIPS32Fixup &) = delete;
     39   MIPS32Fixup(const MIPS32Fixup &) = default;
     40 
     41 public:
     42   MIPS32Fixup() = default;
     43   size_t emit(GlobalContext *Ctx, const Assembler &Asm) const final;
     44   void emitOffset(Assembler *Asm) const;
     45 };
     46 
     47 class AssemblerMIPS32 : public Assembler {
     48   AssemblerMIPS32(const AssemblerMIPS32 &) = delete;
     49   AssemblerMIPS32 &operator=(const AssemblerMIPS32 &) = delete;
     50 
     51 public:
     52   explicit AssemblerMIPS32(bool use_far_branches = false)
     53       : Assembler(Asm_MIPS32) {
     54     // This mode is only needed and implemented for MIPS32 and ARM.
     55     assert(!use_far_branches);
     56     (void)use_far_branches;
     57   }
     58   ~AssemblerMIPS32() override {
     59     if (BuildDefs::asserts()) {
     60       for (const Label *Label : CfgNodeLabels) {
     61         Label->finalCheck();
     62       }
     63       for (const Label *Label : LocalLabels) {
     64         Label->finalCheck();
     65       }
     66     }
     67   }
     68 
     69   MIPS32Fixup *createMIPS32Fixup(const RelocOp Reloc, const Constant *RelOp);
     70 
     71   void trap();
     72 
     73   void nop();
     74 
     75   void emitRsRt(IValueT Opcode, const Operand *OpRs, const Operand *OpRt,
     76                 const char *InsnName);
     77 
     78   void emitRtRsImm16(IValueT Opcode, const Operand *OpRt, const Operand *OpRs,
     79                      uint32_t Imm, const char *InsnName);
     80 
     81   void emitRtRsImm16Rel(IValueT Opcode, const Operand *OpRt,
     82                         const Operand *OpRs, const Operand *OpImm,
     83                         const RelocOp Reloc, const char *InsnName);
     84 
     85   void emitFtRsImm16(IValueT Opcode, const Operand *OpFt, const Operand *OpRs,
     86                      uint32_t Imm, const char *InsnName);
     87 
     88   void emitRdRtSa(IValueT Opcode, const Operand *OpRd, const Operand *OpRt,
     89                   uint32_t Sa, const char *InsnName);
     90 
     91   void emitRdRsRt(IValueT Opcode, const Operand *OpRd, const Operand *OpRs,
     92                   const Operand *OpRt, const char *InsnName);
     93 
     94   void emitCOP1Fcmp(IValueT Opcode, FPInstDataFormat Format,
     95                     const Operand *OpFs, const Operand *OpFt, IValueT CC,
     96                     const char *InsnName);
     97 
     98   void emitCOP1FmtFsFd(IValueT Opcode, FPInstDataFormat Format,
     99                        const Operand *OpFd, const Operand *OpFs,
    100                        const char *InsnName);
    101 
    102   void emitCOP1FmtFtFsFd(IValueT Opcode, FPInstDataFormat Format,
    103                          const Operand *OpFd, const Operand *OpFs,
    104                          const Operand *OpFt, const char *InsnName);
    105 
    106   void emitCOP1FmtRtFsFd(IValueT Opcode, FPInstDataFormat Format,
    107                          const Operand *OpFd, const Operand *OpFs,
    108                          const Operand *OpRt, const char *InsnName);
    109 
    110   void emitCOP1MovRtFs(IValueT Opcode, const Operand *OpRt, const Operand *OpFs,
    111                        const char *InsnName);
    112 
    113   void emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs,
    114               const Operand *OpRt, IOffsetT Offset);
    115 
    116   void abs_d(const Operand *OpFd, const Operand *OpFs);
    117 
    118   void abs_s(const Operand *OpFd, const Operand *OpFs);
    119 
    120   void addi(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
    121 
    122   void add_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
    123 
    124   void add_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
    125 
    126   void addu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
    127 
    128   void addiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
    129 
    130   void addiu(const Operand *OpRt, const Operand *OpRs, const Operand *OpImm,
    131              const RelocOp Reloc);
    132 
    133   void and_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
    134 
    135   void andi(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
    136 
    137   void b(Label *TargetLabel);
    138 
    139   void c_eq_d(const Operand *OpFd, const Operand *OpFs);
    140 
    141   void c_eq_s(const Operand *OpFd, const Operand *OpFs);
    142 
    143   void c_ole_d(const Operand *OpFd, const Operand *OpFs);
    144 
    145   void c_ole_s(const Operand *OpFd, const Operand *OpFs);
    146 
    147   void c_olt_d(const Operand *OpFd, const Operand *OpFs);
    148 
    149   void c_olt_s(const Operand *OpFd, const Operand *OpFs);
    150 
    151   void c_ueq_d(const Operand *OpFd, const Operand *OpFs);
    152 
    153   void c_ueq_s(const Operand *OpFd, const Operand *OpFs);
    154 
    155   void c_ule_d(const Operand *OpFd, const Operand *OpFs);
    156 
    157   void c_ule_s(const Operand *OpFd, const Operand *OpFs);
    158 
    159   void c_ult_d(const Operand *OpFd, const Operand *OpFs);
    160 
    161   void c_ult_s(const Operand *OpFd, const Operand *OpFs);
    162 
    163   void c_un_d(const Operand *OpFd, const Operand *OpFs);
    164 
    165   void c_un_s(const Operand *OpFd, const Operand *OpFs);
    166 
    167   void clz(const Operand *OpRd, const Operand *OpRs);
    168 
    169   void cvt_d_l(const Operand *OpFd, const Operand *OpFs);
    170 
    171   void cvt_d_s(const Operand *OpFd, const Operand *OpFs);
    172 
    173   void cvt_d_w(const Operand *OpFd, const Operand *OpFs);
    174 
    175   void cvt_s_d(const Operand *OpFd, const Operand *OpFs);
    176 
    177   void cvt_s_l(const Operand *OpFd, const Operand *OpFs);
    178 
    179   void cvt_s_w(const Operand *OpFd, const Operand *OpFs);
    180 
    181   void div(const Operand *OpRs, const Operand *OpRt);
    182 
    183   void div_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
    184 
    185   void div_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
    186 
    187   void divu(const Operand *OpRs, const Operand *OpRt);
    188 
    189   void jal(const ConstantRelocatable *Target);
    190 
    191   void jalr(const Operand *OpRs, const Operand *OpRd);
    192 
    193   void lui(const Operand *OpRt, const Operand *OpImm, const RelocOp Reloc);
    194 
    195   void ldc1(const Operand *OpRt, const Operand *OpBase, const Operand *OpOff,
    196             const RelocOp Reloc);
    197 
    198   void ll(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
    199 
    200   void lw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
    201 
    202   void lwc1(const Operand *OpRt, const Operand *OpBase, const Operand *OpOff,
    203             const RelocOp Reloc);
    204 
    205   void mfc1(const Operand *OpRt, const Operand *OpFs);
    206 
    207   void mfhi(const Operand *OpRd);
    208 
    209   void mflo(const Operand *OpRd);
    210 
    211   void mov_d(const Operand *OpFd, const Operand *OpFs);
    212 
    213   void mov_s(const Operand *OpFd, const Operand *OpFs);
    214 
    215   void move(const Operand *OpRd, const Operand *OpRs);
    216 
    217   void movf(const Operand *OpRd, const Operand *OpRs, const Operand *OpCc);
    218 
    219   void movn(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
    220 
    221   void movn_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
    222 
    223   void movn_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
    224 
    225   void movt(const Operand *OpRd, const Operand *OpRs, const Operand *OpCc);
    226 
    227   void movz(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
    228 
    229   void movz_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
    230 
    231   void movz_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
    232 
    233   void mtc1(const Operand *OpRt, const Operand *OpFs);
    234 
    235   void mthi(const Operand *OpRs);
    236 
    237   void mtlo(const Operand *OpRs);
    238 
    239   void mul(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
    240 
    241   void mul_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
    242 
    243   void mul_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
    244 
    245   void mult(const Operand *OpRs, const Operand *OpRt);
    246 
    247   void multu(const Operand *OpRs, const Operand *OpRt);
    248 
    249   void nor(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
    250 
    251   void or_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
    252 
    253   void ori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
    254 
    255   void ret(void);
    256 
    257   void sc(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
    258 
    259   void sll(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
    260 
    261   void sllv(const Operand *OpRd, const Operand *OpRt, const Operand *OpRs);
    262 
    263   void slt(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
    264 
    265   void slti(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
    266 
    267   void sltiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
    268 
    269   void sltu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
    270 
    271   void sqrt_d(const Operand *OpFd, const Operand *OpFs);
    272 
    273   void sqrt_s(const Operand *OpFd, const Operand *OpFs);
    274 
    275   void sra(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
    276 
    277   void srav(const Operand *OpRd, const Operand *OpRt, const Operand *OpRs);
    278 
    279   void srl(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa);
    280 
    281   void srlv(const Operand *OpRd, const Operand *OpRt, const Operand *OpRs);
    282 
    283   void sub_d(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
    284 
    285   void sub_s(const Operand *OpFd, const Operand *OpFs, const Operand *OpFt);
    286 
    287   void subu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
    288 
    289   void sdc1(const Operand *OpRt, const Operand *OpBase, const Operand *OpOff,
    290             const RelocOp Reloc);
    291 
    292   void sw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset);
    293 
    294   void swc1(const Operand *OpRt, const Operand *OpBase, const Operand *OpOff,
    295             const RelocOp Reloc);
    296 
    297   void sync();
    298 
    299   void teq(const Operand *OpRs, const Operand *OpRt, const uint32_t TrapCode);
    300 
    301   void trunc_l_d(const Operand *OpFd, const Operand *OpFs);
    302 
    303   void trunc_l_s(const Operand *OpFd, const Operand *OpFs);
    304 
    305   void trunc_w_d(const Operand *OpFd, const Operand *OpFs);
    306 
    307   void trunc_w_s(const Operand *OpFd, const Operand *OpFs);
    308 
    309   void xor_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt);
    310 
    311   void xori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm);
    312 
    313   void bcc(const CondMIPS32::Cond Cond, const Operand *OpRs,
    314            const Operand *OpRt, Label *TargetLabel);
    315 
    316   void bzc(const CondMIPS32::Cond Cond, const Operand *OpRs,
    317            Label *TargetLabel);
    318 
    319   void alignFunction() override {
    320     const SizeT Align = 1 << getBundleAlignLog2Bytes();
    321     SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align);
    322     constexpr SizeT InstSize = sizeof(IValueT);
    323     assert(BytesNeeded % InstMIPS32::InstSize == 0);
    324     while (BytesNeeded > 0) {
    325       trap();
    326       BytesNeeded -= InstSize;
    327     }
    328   }
    329 
    330   SizeT getBundleAlignLog2Bytes() const override { return 4; }
    331 
    332   const char *getAlignDirective() const override { return ".p2alignl"; }
    333 
    334   llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override;
    335 
    336   void padWithNop(intptr_t Padding) override;
    337 
    338   void bind(Label *label);
    339 
    340   void emitTextInst(const std::string &Text, SizeT InstSize);
    341 
    342   Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override {
    343     assert(NodeNumber < CfgNodeLabels.size());
    344     return CfgNodeLabels[NodeNumber];
    345   }
    346 
    347   Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) {
    348     return getOrCreateLabel(NodeNumber, CfgNodeLabels);
    349   }
    350 
    351   Label *getOrCreateLocalLabel(SizeT Number) {
    352     return getOrCreateLabel(Number, LocalLabels);
    353   }
    354 
    355   void bindLocalLabel(const InstMIPS32Label *InstL, SizeT Number) {
    356     if (BuildDefs::dump() && !getFlags().getDisableHybridAssembly()) {
    357       constexpr SizeT InstSize = 0;
    358       emitTextInst(InstL->getLabelName() + ":", InstSize);
    359     }
    360     Label *L = getOrCreateLocalLabel(Number);
    361     if (!getPreliminary())
    362       this->bind(L);
    363   }
    364 
    365   bool fixupIsPCRel(FixupKind Kind) const override {
    366     (void)Kind;
    367     return false;
    368   }
    369 
    370   static bool classof(const Assembler *Asm) {
    371     return Asm->getKind() == Asm_MIPS32;
    372   }
    373 
    374 private:
    375   ENABLE_MAKE_UNIQUE;
    376 
    377   using LabelVector = std::vector<Label *>;
    378   LabelVector CfgNodeLabels;
    379   LabelVector LocalLabels;
    380 
    381   // Returns the offset encoded in the branch instruction Inst.
    382   static IOffsetT decodeBranchOffset(IValueT Inst);
    383 
    384   Label *getOrCreateLabel(SizeT Number, LabelVector &Labels);
    385 
    386   void bindCfgNodeLabel(const CfgNode *) override;
    387 
    388   void emitInst(IValueT Value) {
    389     AssemblerBuffer::EnsureCapacity _(&Buffer);
    390     Buffer.emit<IValueT>(Value);
    391   }
    392 };
    393 
    394 } // end of namespace MIPS32
    395 } // end of namespace Ice
    396 
    397 #endif // SUBZERO_SRC_ICEASSEMBLERMIPS32_H
    398