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) Assembler(Asm_MIPS32)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 } ~AssemblerMIPS32()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 alignFunction()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 getBundleAlignLog2Bytes()330 SizeT getBundleAlignLog2Bytes() const override { return 4; } 331 getAlignDirective()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 getCfgNodeLabel(SizeT NodeNumber)342 Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override { 343 assert(NodeNumber < CfgNodeLabels.size()); 344 return CfgNodeLabels[NodeNumber]; 345 } 346 getOrCreateCfgNodeLabel(SizeT NodeNumber)347 Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) { 348 return getOrCreateLabel(NodeNumber, CfgNodeLabels); 349 } 350 getOrCreateLocalLabel(SizeT Number)351 Label *getOrCreateLocalLabel(SizeT Number) { 352 return getOrCreateLabel(Number, LocalLabels); 353 } 354 bindLocalLabel(const InstMIPS32Label * InstL,SizeT Number)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 fixupIsPCRel(FixupKind Kind)365 bool fixupIsPCRel(FixupKind Kind) const override { 366 (void)Kind; 367 return false; 368 } 369 classof(const Assembler * Asm)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 emitInst(IValueT Value)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