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