1 //===- subzero/src/IceInstMIPS32.h - MIPS32 machine instrs --*- 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 InstMIPS32 and OperandMIPS32 classes and their 12 /// subclasses. 13 /// 14 /// This represents the machine instructions and operands used for MIPS32 code 15 /// selection. 16 /// 17 //===----------------------------------------------------------------------===// 18 19 #ifndef SUBZERO_SRC_ICEINSTMIPS32_H 20 #define SUBZERO_SRC_ICEINSTMIPS32_H 21 22 #include "IceConditionCodesMIPS32.h" 23 #include "IceDefs.h" 24 #include "IceInst.h" 25 #include "IceInstMIPS32.def" 26 #include "IceOperand.h" 27 28 namespace Ice { 29 namespace MIPS32 { 30 31 enum RelocOp { RO_No, RO_Hi, RO_Lo, RO_Jal }; 32 enum Int64Part { Int64_Hi, Int64_Lo }; 33 34 inline void emitRelocOp(Ostream &Str, RelocOp Reloc) { 35 switch (Reloc) { 36 default: 37 break; 38 case RO_Hi: 39 Str << "%hi"; 40 break; 41 case RO_Lo: 42 Str << "%lo"; 43 break; 44 } 45 } 46 47 class TargetMIPS32; 48 49 /// OperandMips32 extends the Operand hierarchy. 50 // 51 class OperandMIPS32 : public Operand { 52 OperandMIPS32() = delete; 53 OperandMIPS32(const OperandMIPS32 &) = delete; 54 OperandMIPS32 &operator=(const OperandMIPS32 &) = delete; 55 56 public: 57 enum OperandKindMIPS32 { 58 k__Start = Operand::kTarget, 59 kFCC, 60 kMem, 61 }; 62 63 using Operand::dump; 64 void dump(const Cfg *, Ostream &Str) const override { 65 if (BuildDefs::dump()) 66 Str << "<OperandMIPS32>"; 67 } 68 69 protected: 70 OperandMIPS32(OperandKindMIPS32 Kind, Type Ty) 71 : Operand(static_cast<OperandKind>(Kind), Ty) {} 72 }; 73 74 class OperandMIPS32FCC : public OperandMIPS32 { 75 OperandMIPS32FCC() = delete; 76 OperandMIPS32FCC(const OperandMIPS32FCC &) = delete; 77 OperandMIPS32FCC &operator=(const OperandMIPS32FCC &) = delete; 78 79 public: 80 using FCC = enum { FCC0 = 0, FCC1, FCC2, FCC3, FCC4, FCC5, FCC6, FCC7 }; 81 static OperandMIPS32FCC *create(Cfg *Func, OperandMIPS32FCC::FCC FCC) { 82 return new (Func->allocate<OperandMIPS32FCC>()) OperandMIPS32FCC(FCC); 83 } 84 85 OperandMIPS32FCC::FCC getFCC() const { return FpCondCode; } 86 87 void emit(const Cfg *Func) const override { 88 if (!BuildDefs::dump()) 89 return; 90 Ostream &Str = Func->getContext()->getStrEmit(); 91 Str << "$fcc" << static_cast<uint16_t>(FpCondCode); 92 } 93 94 static bool classof(const Operand *Operand) { 95 return Operand->getKind() == static_cast<OperandKind>(kFCC); 96 } 97 98 void dump(const Cfg *Func, Ostream &Str) const override { 99 if (!BuildDefs::dump()) 100 return; 101 (void)Func; 102 Str << "$fcc" << static_cast<uint16_t>(FpCondCode); 103 } 104 105 private: 106 OperandMIPS32FCC(OperandMIPS32FCC::FCC CC) 107 : OperandMIPS32(kFCC, IceType_i32), FpCondCode(CC){}; 108 109 const OperandMIPS32FCC::FCC FpCondCode; 110 }; 111 112 class OperandMIPS32Mem : public OperandMIPS32 { 113 OperandMIPS32Mem() = delete; 114 OperandMIPS32Mem(const OperandMIPS32Mem &) = delete; 115 OperandMIPS32Mem &operator=(const OperandMIPS32Mem &) = delete; 116 117 public: 118 /// Memory operand addressing mode. 119 /// The enum value also carries the encoding. 120 // TODO(jvoung): unify with the assembler. 121 enum AddrMode { Offset }; 122 123 /// NOTE: The Variable-typed operands have to be registers. 124 /// 125 /// Reg + Imm. The Immediate actually has a limited number of bits 126 /// for encoding, so check canHoldOffset first. It cannot handle 127 /// general Constant operands like ConstantRelocatable, since a relocatable 128 /// can potentially take up too many bits. 129 static OperandMIPS32Mem *create(Cfg *Func, Type Ty, Variable *Base, 130 Operand *ImmOffset, AddrMode Mode = Offset) { 131 return new (Func->allocate<OperandMIPS32Mem>()) 132 OperandMIPS32Mem(Func, Ty, Base, ImmOffset, Mode); 133 } 134 135 Variable *getBase() const { return Base; } 136 Operand *getOffset() const { return ImmOffset; } 137 AddrMode getAddrMode() const { return Mode; } 138 139 void emit(const Cfg *Func) const override; 140 using OperandMIPS32::dump; 141 142 static bool classof(const Operand *Operand) { 143 return Operand->getKind() == static_cast<OperandKind>(kMem); 144 } 145 146 /// Return true if a load/store instruction for an element of type Ty 147 /// can encode the Offset directly in the immediate field of the 32-bit 148 /// MIPS instruction. For some types, if the load is Sign extending, then 149 /// the range is reduced. 150 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset); 151 152 void dump(const Cfg *Func, Ostream &Str) const override { 153 if (!BuildDefs::dump()) 154 return; 155 Str << "["; 156 if (Func) 157 getBase()->dump(Func); 158 else 159 getBase()->dump(Str); 160 Str << ", "; 161 getOffset()->dump(Func, Str); 162 Str << "] AddrMode=="; 163 if (getAddrMode() == Offset) { 164 Str << "Offset"; 165 } else { 166 Str << "Unknown"; 167 } 168 } 169 170 private: 171 OperandMIPS32Mem(Cfg *Func, Type Ty, Variable *Base, Operand *ImmOffset, 172 AddrMode Mode); 173 174 Variable *Base; 175 Operand *const ImmOffset; 176 const AddrMode Mode; 177 }; 178 179 /// Base class for Mips instructions. 180 class InstMIPS32 : public InstTarget { 181 InstMIPS32() = delete; 182 InstMIPS32(const InstMIPS32 &) = delete; 183 InstMIPS32 &operator=(const InstMIPS32 &) = delete; 184 185 public: 186 enum InstKindMIPS32 { 187 k__Start = Inst::Target, 188 Abs_d, 189 Abs_s, 190 Add, 191 Add_d, 192 Add_s, 193 Addi, 194 Addiu, 195 Addu, 196 And, 197 Andi, 198 Br, 199 C_eq_d, 200 C_eq_s, 201 C_ole_d, 202 C_ole_s, 203 C_olt_d, 204 C_olt_s, 205 C_ueq_d, 206 C_ueq_s, 207 C_ule_d, 208 C_ule_s, 209 C_ult_d, 210 C_ult_s, 211 C_un_d, 212 C_un_s, 213 Call, 214 Clz, 215 Cvt_d_l, 216 Cvt_d_s, 217 Cvt_d_w, 218 Cvt_s_d, 219 Cvt_s_l, 220 Cvt_s_w, 221 Div, 222 Div_d, 223 Div_s, 224 Divu, 225 La, 226 Label, 227 Ldc1, 228 Ll, 229 Lui, 230 Lw, 231 Lwc1, 232 Mfc1, 233 Mfhi, 234 Mflo, 235 Mov, // actually a pseudo op for addi rd, rs, 0 236 Mov_fp, 237 Mov_d, 238 Mov_s, 239 Movf, 240 Movn, 241 Movn_d, 242 Movn_s, 243 Movt, 244 Movz, 245 Movz_d, 246 Movz_s, 247 Mtc1, 248 Mthi, 249 Mtlo, 250 Mul, 251 Mul_d, 252 Mul_s, 253 Mult, 254 Multu, 255 Nor, 256 Or, 257 Ori, 258 Ret, 259 Sc, 260 Sdc1, 261 Sll, 262 Sllv, 263 Slt, 264 Slti, 265 Sltiu, 266 Sltu, 267 Sra, 268 Srav, 269 Srl, 270 Srlv, 271 Sqrt_d, 272 Sqrt_s, 273 Sub, 274 Sub_d, 275 Sub_s, 276 Subu, 277 Sw, 278 Swc1, 279 Sync, 280 Teq, 281 Trunc_l_d, 282 Trunc_l_s, 283 Trunc_w_d, 284 Trunc_w_s, 285 Xor, 286 Xori 287 }; 288 289 static constexpr size_t InstSize = sizeof(uint32_t); 290 291 static const char *getWidthString(Type Ty); 292 293 CondMIPS32::Cond getOppositeCondition(CondMIPS32::Cond Cond); 294 295 void dump(const Cfg *Func) const override; 296 297 void dumpOpcode(Ostream &Str, const char *Opcode, Type Ty) const { 298 Str << Opcode << "." << Ty; 299 } 300 301 // TODO(rkotler): while branching is not implemented 302 bool repointEdges(CfgNode *, CfgNode *) override { return true; } 303 304 /// Shared emit routines for common forms of instructions. 305 static void emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst, 306 const Cfg *Func); 307 static void emitUnaryopGPRFLoHi(const char *Opcode, const InstMIPS32 *Inst, 308 const Cfg *Func); 309 static void emitUnaryopGPRTLoHi(const char *Opcode, const InstMIPS32 *Inst, 310 const Cfg *Func); 311 static void emitTwoAddr(const char *Opcode, const InstMIPS32 *Inst, 312 const Cfg *Func); 313 static void emitThreeAddr(const char *Opcode, const InstMIPS32 *Inst, 314 const Cfg *Func); 315 static void emitThreeAddrLoHi(const char *Opcode, const InstMIPS32 *Inst, 316 const Cfg *Func); 317 318 protected: 319 InstMIPS32(Cfg *Func, InstKindMIPS32 Kind, SizeT Maxsrcs, Variable *Dest) 320 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} 321 static bool isClassof(const Inst *Inst, InstKindMIPS32 MyKind) { 322 return Inst->getKind() == static_cast<InstKind>(MyKind); 323 } 324 }; 325 326 /// Ret pseudo-instruction. This is actually a "jr" instruction with an "ra" 327 /// register operand, but epilogue lowering will search for a Ret instead of a 328 /// generic "jr". This instruction also takes a Source operand (for non-void 329 /// returning functions) for liveness analysis, though a FakeUse before the ret 330 /// would do just as well. 331 // TODO(reed kotler): This needs was take from the ARM port and needs to be 332 // scrubbed in the future. 333 class InstMIPS32Ret : public InstMIPS32 { 334 335 InstMIPS32Ret() = delete; 336 InstMIPS32Ret(const InstMIPS32Ret &) = delete; 337 InstMIPS32Ret &operator=(const InstMIPS32Ret &) = delete; 338 339 public: 340 static InstMIPS32Ret *create(Cfg *Func, Variable *RA, 341 Variable *Source = nullptr) { 342 return new (Func->allocate<InstMIPS32Ret>()) 343 InstMIPS32Ret(Func, RA, Source); 344 } 345 void emit(const Cfg *Func) const override; 346 void emitIAS(const Cfg *Func) const override; 347 void dump(const Cfg *Func) const override; 348 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } 349 350 private: 351 InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source); 352 }; 353 354 /// Instructions of the form x := op(y). 355 template <InstMIPS32::InstKindMIPS32 K> 356 class InstMIPS32UnaryopGPR : public InstMIPS32 { 357 InstMIPS32UnaryopGPR() = delete; 358 InstMIPS32UnaryopGPR(const InstMIPS32UnaryopGPR &) = delete; 359 InstMIPS32UnaryopGPR &operator=(const InstMIPS32UnaryopGPR &) = delete; 360 361 public: 362 static InstMIPS32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src, 363 RelocOp Reloc = RO_No) { 364 return new (Func->allocate<InstMIPS32UnaryopGPR>()) 365 InstMIPS32UnaryopGPR(Func, Dest, Src, Reloc); 366 } 367 void emit(const Cfg *Func) const override { 368 if (!BuildDefs::dump()) 369 return; 370 emitUnaryopGPR(Opcode, this, Func); 371 } 372 void emitIAS(const Cfg *Func) const override { 373 (void)Func; 374 llvm_unreachable("Not yet implemented"); 375 } 376 void dump(const Cfg *Func) const override { 377 if (!BuildDefs::dump()) 378 return; 379 Ostream &Str = Func->getContext()->getStrDump(); 380 dumpOpcode(Str, Opcode, getDest()->getType()); 381 Str << " "; 382 dumpDest(Func); 383 Str << ", "; 384 dumpSources(Func); 385 } 386 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } 387 388 protected: 389 InstMIPS32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src, 390 RelocOp Reloc = RO_No) 391 : InstMIPS32(Func, K, 1, Dest), Reloc(Reloc) { 392 addSource(Src); 393 } 394 395 private: 396 static const char *Opcode; 397 const RelocOp Reloc; 398 }; 399 400 /// Instructions of the form opcode reg, reg. 401 template <InstMIPS32::InstKindMIPS32 K> 402 class InstMIPS32TwoAddrFPR : public InstMIPS32 { 403 InstMIPS32TwoAddrFPR() = delete; 404 InstMIPS32TwoAddrFPR(const InstMIPS32TwoAddrFPR &) = delete; 405 InstMIPS32TwoAddrFPR &operator=(const InstMIPS32TwoAddrFPR &) = delete; 406 407 public: 408 static InstMIPS32TwoAddrFPR *create(Cfg *Func, Variable *Dest, 409 Variable *Src0) { 410 return new (Func->allocate<InstMIPS32TwoAddrFPR>()) 411 InstMIPS32TwoAddrFPR(Func, Dest, Src0); 412 } 413 void emit(const Cfg *Func) const override { 414 if (!BuildDefs::dump()) 415 return; 416 emitTwoAddr(Opcode, this, Func); 417 } 418 void emitIAS(const Cfg *Func) const override { 419 (void)Func; 420 llvm_unreachable("Not yet implemented"); 421 } 422 423 void dump(const Cfg *Func) const override { 424 if (!BuildDefs::dump()) 425 return; 426 Ostream &Str = Func->getContext()->getStrDump(); 427 dumpDest(Func); 428 Str << " = "; 429 dumpOpcode(Str, Opcode, getDest()->getType()); 430 Str << " "; 431 dumpSources(Func); 432 } 433 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } 434 435 private: 436 InstMIPS32TwoAddrFPR(Cfg *Func, Variable *Dest, Variable *Src0) 437 : InstMIPS32(Func, K, 1, Dest) { 438 addSource(Src0); 439 } 440 441 static const char *Opcode; 442 }; 443 444 /// Instructions of the form opcode reg, reg. 445 template <InstMIPS32::InstKindMIPS32 K> 446 class InstMIPS32TwoAddrGPR : public InstMIPS32 { 447 InstMIPS32TwoAddrGPR() = delete; 448 InstMIPS32TwoAddrGPR(const InstMIPS32TwoAddrGPR &) = delete; 449 InstMIPS32TwoAddrGPR &operator=(const InstMIPS32TwoAddrGPR &) = delete; 450 451 public: 452 static InstMIPS32TwoAddrGPR *create(Cfg *Func, Variable *Dest, 453 Variable *Src0) { 454 return new (Func->allocate<InstMIPS32TwoAddrGPR>()) 455 InstMIPS32TwoAddrGPR(Func, Dest, Src0); 456 } 457 void emit(const Cfg *Func) const override { 458 if (!BuildDefs::dump()) 459 return; 460 emitTwoAddr(Opcode, this, Func); 461 } 462 void emitIAS(const Cfg *Func) const override { 463 (void)Func; 464 llvm_unreachable("Not yet implemented"); 465 } 466 467 void dump(const Cfg *Func) const override { 468 if (!BuildDefs::dump()) 469 return; 470 Ostream &Str = Func->getContext()->getStrDump(); 471 dumpDest(Func); 472 Str << " = "; 473 dumpOpcode(Str, Opcode, getDest()->getType()); 474 Str << " "; 475 dumpSources(Func); 476 } 477 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } 478 479 private: 480 InstMIPS32TwoAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0) 481 : InstMIPS32(Func, K, 1, Dest) { 482 addSource(Src0); 483 } 484 485 static const char *Opcode; 486 }; 487 488 /// Instructions of the form x := y op z. May have the side-effect of setting 489 /// status flags. 490 template <InstMIPS32::InstKindMIPS32 K> 491 class InstMIPS32ThreeAddrFPR : public InstMIPS32 { 492 InstMIPS32ThreeAddrFPR() = delete; 493 InstMIPS32ThreeAddrFPR(const InstMIPS32ThreeAddrFPR &) = delete; 494 InstMIPS32ThreeAddrFPR &operator=(const InstMIPS32ThreeAddrFPR &) = delete; 495 496 public: 497 /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1 498 /// must be registers. 499 static InstMIPS32ThreeAddrFPR *create(Cfg *Func, Variable *Dest, 500 Variable *Src0, Variable *Src1) { 501 return new (Func->allocate<InstMIPS32ThreeAddrFPR>()) 502 InstMIPS32ThreeAddrFPR(Func, Dest, Src0, Src1); 503 } 504 void emit(const Cfg *Func) const override { 505 if (!BuildDefs::dump()) 506 return; 507 emitThreeAddr(Opcode, this, Func); 508 } 509 void emitIAS(const Cfg *Func) const override { 510 (void)Func; 511 llvm_unreachable("Not yet implemented"); 512 } 513 514 void dump(const Cfg *Func) const override { 515 if (!BuildDefs::dump()) 516 return; 517 Ostream &Str = Func->getContext()->getStrDump(); 518 dumpDest(Func); 519 Str << " = "; 520 dumpOpcode(Str, Opcode, getDest()->getType()); 521 Str << " "; 522 dumpSources(Func); 523 } 524 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } 525 526 private: 527 InstMIPS32ThreeAddrFPR(Cfg *Func, Variable *Dest, Variable *Src0, 528 Variable *Src1) 529 : InstMIPS32(Func, K, 2, Dest) { 530 addSource(Src0); 531 addSource(Src1); 532 } 533 534 static const char *Opcode; 535 }; 536 537 /// Instructions of the form x := y op z. May have the side-effect of setting 538 /// status flags. 539 template <InstMIPS32::InstKindMIPS32 K> 540 class InstMIPS32ThreeAddrGPR : public InstMIPS32 { 541 InstMIPS32ThreeAddrGPR() = delete; 542 InstMIPS32ThreeAddrGPR(const InstMIPS32ThreeAddrGPR &) = delete; 543 InstMIPS32ThreeAddrGPR &operator=(const InstMIPS32ThreeAddrGPR &) = delete; 544 545 public: 546 /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1 547 /// must be registers. 548 static InstMIPS32ThreeAddrGPR *create(Cfg *Func, Variable *Dest, 549 Variable *Src0, Variable *Src1) { 550 return new (Func->allocate<InstMIPS32ThreeAddrGPR>()) 551 InstMIPS32ThreeAddrGPR(Func, Dest, Src0, Src1); 552 } 553 void emit(const Cfg *Func) const override { 554 if (!BuildDefs::dump()) 555 return; 556 emitThreeAddr(Opcode, this, Func); 557 } 558 void emitIAS(const Cfg *Func) const override { 559 (void)Func; 560 llvm_unreachable("Not yet implemented"); 561 } 562 563 void dump(const Cfg *Func) const override { 564 if (!BuildDefs::dump()) 565 return; 566 Ostream &Str = Func->getContext()->getStrDump(); 567 dumpDest(Func); 568 Str << " = "; 569 dumpOpcode(Str, Opcode, getDest()->getType()); 570 Str << " "; 571 dumpSources(Func); 572 } 573 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } 574 575 private: 576 InstMIPS32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0, 577 Variable *Src1) 578 : InstMIPS32(Func, K, 2, Dest) { 579 addSource(Src0); 580 addSource(Src1); 581 } 582 583 static const char *Opcode; 584 }; 585 586 // InstMIPS32Load represents instructions which loads data from memory 587 // Its format is "OPCODE GPR, OFFSET(BASE GPR)" 588 template <InstMIPS32::InstKindMIPS32 K> 589 class InstMIPS32Load : public InstMIPS32 { 590 InstMIPS32Load() = delete; 591 InstMIPS32Load(const InstMIPS32Load &) = delete; 592 InstMIPS32Load &operator=(const InstMIPS32Load &) = delete; 593 594 public: 595 static InstMIPS32Load *create(Cfg *Func, Variable *Value, 596 OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) { 597 return new (Func->allocate<InstMIPS32Load>()) 598 InstMIPS32Load(Func, Value, Mem, Reloc); 599 } 600 601 void emit(const Cfg *Func) const override { 602 if (!BuildDefs::dump()) 603 return; 604 Ostream &Str = Func->getContext()->getStrEmit(); 605 const Type Ty = getDest()->getType(); 606 607 if (getKind() == static_cast<InstKind>(Ll)) { 608 Str << "\t" << Opcode << "\t"; 609 } else { 610 switch (Ty) { 611 case IceType_i1: 612 case IceType_i8: 613 Str << "\t" 614 "lb" 615 "\t"; 616 break; 617 case IceType_i16: 618 Str << "\t" 619 "lh" 620 "\t"; 621 break; 622 case IceType_i32: 623 Str << "\t" 624 "lw" 625 "\t"; 626 break; 627 case IceType_f32: 628 Str << "\t" 629 "lwc1" 630 "\t"; 631 break; 632 case IceType_f64: 633 Str << "\t" 634 "ldc1" 635 "\t"; 636 break; 637 default: 638 llvm_unreachable("InstMIPS32Load unknown type"); 639 } 640 } 641 getDest()->emit(Func); 642 Str << ", "; 643 emitRelocOp(Str, Reloc); 644 getSrc(0)->emit(Func); 645 } 646 647 void emitIAS(const Cfg *Func) const override { 648 (void)Func; 649 llvm_unreachable("Not yet implemented"); 650 } 651 652 void dump(const Cfg *Func) const override { 653 if (!BuildDefs::dump()) 654 return; 655 Ostream &Str = Func->getContext()->getStrDump(); 656 dumpOpcode(Str, Opcode, getDest()->getType()); 657 Str << " "; 658 getDest()->dump(Func); 659 Str << ", "; 660 emitRelocOp(Str, Reloc); 661 getSrc(0)->dump(Func); 662 } 663 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } 664 665 private: 666 InstMIPS32Load(Cfg *Func, Variable *Value, OperandMIPS32Mem *Mem, 667 RelocOp Reloc = RO_No) 668 : InstMIPS32(Func, K, 2, Value), Reloc(Reloc) { 669 addSource(Mem); 670 } 671 static const char *Opcode; 672 const RelocOp Reloc; 673 }; 674 675 // InstMIPS32Store represents instructions which stores data to memory 676 // Its format is "OPCODE GPR, OFFSET(BASE GPR)" 677 template <InstMIPS32::InstKindMIPS32 K> 678 class InstMIPS32Store : public InstMIPS32 { 679 InstMIPS32Store() = delete; 680 InstMIPS32Store(const InstMIPS32Store &) = delete; 681 InstMIPS32Store &operator=(const InstMIPS32Store &) = delete; 682 683 public: 684 static InstMIPS32Store *create(Cfg *Func, Variable *Value, 685 OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) { 686 return new (Func->allocate<InstMIPS32Store>()) 687 InstMIPS32Store(Func, Value, Mem, Reloc); 688 } 689 690 void emit(const Cfg *Func) const override { 691 if (!BuildDefs::dump()) 692 return; 693 Ostream &Str = Func->getContext()->getStrEmit(); 694 assert(getSrcSize() == 2); 695 const Type Ty = getSrc(0)->getType(); 696 697 if (getKind() == static_cast<InstKind>(Sc)) { 698 Str << "\t" << Opcode << "\t"; 699 } else { 700 switch (Ty) { 701 case IceType_i1: 702 case IceType_i8: 703 Str << "\t" 704 "sb" 705 "\t"; 706 break; 707 case IceType_i16: 708 Str << "\t" 709 "sh" 710 "\t"; 711 break; 712 case IceType_i32: 713 Str << "\t" 714 "sw" 715 "\t"; 716 break; 717 case IceType_f32: 718 Str << "\t" 719 "swc1" 720 "\t"; 721 break; 722 case IceType_f64: 723 Str << "\t" 724 "sdc1" 725 "\t"; 726 break; 727 default: 728 llvm_unreachable("InstMIPS32Store unknown type"); 729 } 730 } 731 getSrc(0)->emit(Func); 732 Str << ", "; 733 emitRelocOp(Str, Reloc); 734 getSrc(1)->emit(Func); 735 } 736 737 void emitIAS(const Cfg *Func) const override { 738 (void)Func; 739 llvm_unreachable("InstMIPS32Store: Not yet implemented"); 740 } 741 742 void dump(const Cfg *Func) const override { 743 if (!BuildDefs::dump()) 744 return; 745 Ostream &Str = Func->getContext()->getStrDump(); 746 dumpOpcode(Str, Opcode, getSrc(0)->getType()); 747 Str << " "; 748 getSrc(0)->dump(Func); 749 Str << ", "; 750 emitRelocOp(Str, Reloc); 751 getSrc(1)->dump(Func); 752 } 753 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } 754 755 private: 756 InstMIPS32Store(Cfg *Func, Variable *Value, OperandMIPS32Mem *Mem, 757 RelocOp Reloc = RO_No) 758 : InstMIPS32(Func, K, 2, nullptr), Reloc(Reloc) { 759 addSource(Value); 760 addSource(Mem); 761 } 762 static const char *Opcode; 763 const RelocOp Reloc; 764 }; 765 766 // InstMIPS32Label represents an intra-block label that is the target of an 767 // intra-block branch. The offset between the label and the branch must be fit 768 // in the instruction immediate (considered "near"). 769 class InstMIPS32Label : public InstMIPS32 { 770 InstMIPS32Label() = delete; 771 InstMIPS32Label(const InstMIPS32Label &) = delete; 772 InstMIPS32Label &operator=(const InstMIPS32Label &) = delete; 773 774 public: 775 static InstMIPS32Label *create(Cfg *Func, TargetMIPS32 *Target) { 776 return new (Func->allocate<InstMIPS32Label>()) 777 InstMIPS32Label(Func, Target); 778 } 779 uint32_t getEmitInstCount() const override { return 0; } 780 GlobalString getLabelName() const { return Name; } 781 SizeT getNumber() const { return Number; } 782 void emit(const Cfg *Func) const override; 783 void emitIAS(const Cfg *Func) const override; 784 void dump(const Cfg *Func) const override; 785 786 static bool classof(const Inst *Instr) { return isClassof(Instr, Label); } 787 788 private: 789 InstMIPS32Label(Cfg *Func, TargetMIPS32 *Target); 790 791 // RelocOffset *OffsetReloc = nullptr; 792 SizeT Number; // used for unique label generation. 793 GlobalString Name; 794 }; 795 796 /// Direct branch instruction. 797 class InstMIPS32Br : public InstMIPS32 { 798 InstMIPS32Br() = delete; 799 InstMIPS32Br(const InstMIPS32Br &) = delete; 800 InstMIPS32Br &operator=(const InstMIPS32Br &) = delete; 801 802 public: 803 /// Create an unconditional branch to a node. 804 static InstMIPS32Br *create(Cfg *Func, CfgNode *Target) { 805 constexpr CfgNode *NoCondTarget = nullptr; 806 constexpr InstMIPS32Label *NoLabel = nullptr; 807 return new (Func->allocate<InstMIPS32Br>()) 808 InstMIPS32Br(Func, NoCondTarget, Target, NoLabel, CondMIPS32::AL); 809 } 810 811 static InstMIPS32Br *create(Cfg *Func, CfgNode *Target, 812 const InstMIPS32Label *Label) { 813 constexpr CfgNode *NoCondTarget = nullptr; 814 return new (Func->allocate<InstMIPS32Br>()) 815 InstMIPS32Br(Func, NoCondTarget, Target, Label, CondMIPS32::AL); 816 } 817 818 /// Create a conditional branch to the false node. 819 static InstMIPS32Br *create(Cfg *Func, CfgNode *TargetTrue, 820 CfgNode *TargetFalse, Operand *Src0, 821 Operand *Src1, CondMIPS32::Cond Cond) { 822 constexpr InstMIPS32Label *NoLabel = nullptr; 823 return new (Func->allocate<InstMIPS32Br>()) 824 InstMIPS32Br(Func, TargetTrue, TargetFalse, Src0, Src1, NoLabel, Cond); 825 } 826 827 static InstMIPS32Br *create(Cfg *Func, CfgNode *TargetTrue, 828 CfgNode *TargetFalse, Operand *Src0, 829 CondMIPS32::Cond Cond) { 830 constexpr InstMIPS32Label *NoLabel = nullptr; 831 return new (Func->allocate<InstMIPS32Br>()) 832 InstMIPS32Br(Func, TargetTrue, TargetFalse, Src0, NoLabel, Cond); 833 } 834 835 static InstMIPS32Br *create(Cfg *Func, CfgNode *TargetTrue, 836 CfgNode *TargetFalse, Operand *Src0, 837 Operand *Src1, const InstMIPS32Label *Label, 838 CondMIPS32::Cond Cond) { 839 return new (Func->allocate<InstMIPS32Br>()) 840 InstMIPS32Br(Func, TargetTrue, TargetFalse, Src0, Src1, Label, Cond); 841 } 842 843 const CfgNode *getTargetTrue() const { return TargetTrue; } 844 const CfgNode *getTargetFalse() const { return TargetFalse; } 845 CondMIPS32::Cond getPredicate() const { return Predicate; } 846 void setPredicate(CondMIPS32::Cond Pred) { Predicate = Pred; } 847 bool optimizeBranch(const CfgNode *NextNode); 848 bool isUnconditionalBranch() const override { 849 return Predicate == CondMIPS32::AL; 850 } 851 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 852 void emit(const Cfg *Func) const override; 853 void emitIAS(const Cfg *Func) const override; 854 void dump(const Cfg *Func) const override; 855 static bool classof(const Inst *Instr) { return isClassof(Instr, Br); } 856 857 private: 858 InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, 859 const InstMIPS32Label *Label, const CondMIPS32::Cond Cond); 860 861 InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, 862 Operand *Src0, const InstMIPS32Label *Label, 863 const CondMIPS32::Cond Cond); 864 865 InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, 866 Operand *Src0, Operand *Src1, const InstMIPS32Label *Label, 867 const CondMIPS32::Cond Cond); 868 869 const CfgNode *TargetTrue; 870 const CfgNode *TargetFalse; 871 const InstMIPS32Label *Label; // Intra-block branch target 872 CondMIPS32::Cond Predicate; 873 }; 874 875 class InstMIPS32Call : public InstMIPS32 { 876 InstMIPS32Call() = delete; 877 InstMIPS32Call(const InstMIPS32Call &) = delete; 878 InstMIPS32Call &operator=(const InstMIPS32Call &) = delete; 879 880 public: 881 static InstMIPS32Call *create(Cfg *Func, Variable *Dest, 882 Operand *CallTarget) { 883 return new (Func->allocate<InstMIPS32Call>()) 884 InstMIPS32Call(Func, Dest, CallTarget); 885 } 886 Operand *getCallTarget() const { return getSrc(0); } 887 void emit(const Cfg *Func) const override; 888 void emitIAS(const Cfg *Func) const override; 889 void dump(const Cfg *Func) const override; 890 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); } 891 892 private: 893 InstMIPS32Call(Cfg *Func, Variable *Dest, Operand *CallTarget); 894 }; 895 896 template <InstMIPS32::InstKindMIPS32 K> 897 class InstMIPS32FPCmp : public InstMIPS32 { 898 InstMIPS32FPCmp() = delete; 899 InstMIPS32FPCmp(const InstMIPS32FPCmp &) = delete; 900 InstMIPS32Call &operator=(const InstMIPS32FPCmp &) = delete; 901 902 public: 903 static InstMIPS32FPCmp *create(Cfg *Func, Variable *Src0, Variable *Src1) { 904 return new (Func->allocate<InstMIPS32FPCmp>()) 905 InstMIPS32FPCmp(Func, Src0, Src1); 906 } 907 908 void emit(const Cfg *Func) const override { 909 if (!BuildDefs::dump()) 910 return; 911 Ostream &Str = Func->getContext()->getStrEmit(); 912 assert(getSrcSize() == 2); 913 Str << "\t" << Opcode << "\t"; 914 getSrc(0)->emit(Func); 915 Str << ", "; 916 getSrc(1)->emit(Func); 917 } 918 919 void emitIAS(const Cfg *Func) const override { 920 (void)Func; 921 llvm_unreachable("Not yet implemented"); 922 } 923 924 void dump(const Cfg *Func) const override { 925 (void)Func; 926 if (!BuildDefs::dump()) 927 return; 928 Ostream &Str = Func->getContext()->getStrDump(); 929 dumpOpcode(Str, Opcode, getSrc(0)->getType()); 930 Str << " "; 931 dumpSources(Func); 932 } 933 934 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); } 935 936 private: 937 InstMIPS32FPCmp(Cfg *Func, Variable *Src0, Variable *Src1) 938 : InstMIPS32(Func, K, 2, nullptr) { 939 addSource(Src0); 940 addSource(Src1); 941 }; 942 943 static const char *Opcode; 944 }; 945 946 class InstMIPS32Sync : public InstMIPS32 { 947 InstMIPS32Sync() = delete; 948 InstMIPS32Sync(const InstMIPS32Sync &) = delete; 949 InstMIPS32Sync &operator=(const InstMIPS32Sync &) = delete; 950 951 public: 952 static InstMIPS32Sync *create(Cfg *Func) { 953 return new (Func->allocate<InstMIPS32Sync>()) InstMIPS32Sync(Func); 954 } 955 956 void emit(const Cfg *Func) const override { 957 if (!BuildDefs::dump()) 958 return; 959 Ostream &Str = Func->getContext()->getStrEmit(); 960 Str << "\t" << Opcode << "\t"; 961 } 962 963 void dump(const Cfg *Func) const override { 964 if (!BuildDefs::dump()) 965 return; 966 Func->getContext()->getStrDump() << Opcode << "\t"; 967 } 968 969 static bool classof(const Inst *Inst) { 970 return isClassof(Inst, InstMIPS32::Sync); 971 } 972 973 void emitIAS(const Cfg *Func) const override; 974 975 private: 976 InstMIPS32Sync(Cfg *Func) : InstMIPS32(Func, InstMIPS32::Sync, 0, nullptr) {} 977 static const char *Opcode; 978 }; 979 980 // Trap 981 template <InstMIPS32::InstKindMIPS32 K> 982 class InstMIPS32Trap : public InstMIPS32 { 983 InstMIPS32Trap() = delete; 984 InstMIPS32Trap(const InstMIPS32Trap &) = delete; 985 InstMIPS32Trap &operator=(const InstMIPS32Trap &) = delete; 986 987 public: 988 static InstMIPS32Trap *create(Cfg *Func, Operand *Src0, Operand *Src1, 989 uint32_t Tcode) { 990 return new (Func->allocate<InstMIPS32Trap>()) 991 InstMIPS32Trap(Func, Src0, Src1, Tcode); 992 } 993 994 uint32_t getTrapCode() const { return TrapCode; } 995 996 void emit(const Cfg *Func) const override { 997 if (!BuildDefs::dump()) 998 return; 999 Ostream &Str = Func->getContext()->getStrEmit(); 1000 Str << "\t" << Opcode << "\t"; 1001 getSrc(0)->emit(Func); 1002 Str << ", "; 1003 getSrc(1)->emit(Func); 1004 Str << ", " << TrapCode; 1005 } 1006 1007 void emitIAS(const Cfg *Func) const override { 1008 (void)Func; 1009 llvm_unreachable("Not yet implemented"); 1010 } 1011 1012 void dump(const Cfg *Func) const override { 1013 if (!BuildDefs::dump()) 1014 return; 1015 Ostream &Str = Func->getContext()->getStrDump(); 1016 dumpOpcode(Str, Opcode, getSrc(0)->getType()); 1017 Str << " "; 1018 dumpSources(Func); 1019 Str << ", " << TrapCode; 1020 } 1021 1022 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } 1023 1024 private: 1025 InstMIPS32Trap(Cfg *Func, Operand *Src0, Operand *Src1, const uint32_t Tcode) 1026 : InstMIPS32(Func, K, 2, nullptr), TrapCode(Tcode) { 1027 addSource(Src0); 1028 addSource(Src1); 1029 } 1030 1031 static const char *Opcode; 1032 const uint32_t TrapCode; 1033 }; 1034 1035 template <InstMIPS32::InstKindMIPS32 K, bool Signed = false> 1036 class InstMIPS32Imm16 : public InstMIPS32 { 1037 InstMIPS32Imm16() = delete; 1038 InstMIPS32Imm16(const InstMIPS32Imm16 &) = delete; 1039 InstMIPS32Imm16 &operator=(const InstMIPS32Imm16 &) = delete; 1040 1041 public: 1042 static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, Operand *Source, 1043 uint32_t Imm, RelocOp Reloc = RO_No) { 1044 return new (Func->allocate<InstMIPS32Imm16>()) 1045 InstMIPS32Imm16(Func, Dest, Source, Imm, Reloc); 1046 } 1047 1048 static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, uint32_t Imm, 1049 RelocOp Reloc = RO_No) { 1050 return new (Func->allocate<InstMIPS32Imm16>()) 1051 InstMIPS32Imm16(Func, Dest, Imm, Reloc); 1052 } 1053 1054 static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, Operand *Src0, 1055 Operand *Src1, RelocOp Reloc) { 1056 return new (Func->allocate<InstMIPS32Imm16>()) 1057 InstMIPS32Imm16(Func, Dest, Src0, Src1, Reloc); 1058 } 1059 1060 void emit(const Cfg *Func) const override { 1061 if (!BuildDefs::dump()) 1062 return; 1063 Ostream &Str = Func->getContext()->getStrEmit(); 1064 Str << "\t" << Opcode << "\t"; 1065 getDest()->emit(Func); 1066 if (getSrcSize() > 0) { 1067 Str << ", "; 1068 getSrc(0)->emit(Func); 1069 } 1070 Str << ", "; 1071 if (Reloc == RO_No) { 1072 if (Signed) 1073 Str << (int32_t)Imm; 1074 else 1075 Str << Imm; 1076 } else { 1077 auto *CR = llvm::dyn_cast<ConstantRelocatable>(getSrc(1)); 1078 emitRelocOp(Str, Reloc); 1079 Str << "("; 1080 CR->emitWithoutPrefix(Func->getTarget()); 1081 Str << ")"; 1082 } 1083 } 1084 1085 void emitIAS(const Cfg *Func) const override { 1086 (void)Func; 1087 llvm_unreachable("Not yet implemented"); 1088 } 1089 void dump(const Cfg *Func) const override { 1090 if (!BuildDefs::dump()) 1091 return; 1092 Ostream &Str = Func->getContext()->getStrDump(); 1093 dumpOpcode(Str, Opcode, getDest()->getType()); 1094 Str << " "; 1095 dumpDest(Func); 1096 Str << ", "; 1097 if (Reloc == RO_No) { 1098 dumpSources(Func); 1099 Str << ", "; 1100 if (Signed) 1101 Str << (int32_t)Imm; 1102 else 1103 Str << Imm; 1104 } else { 1105 getSrc(0)->dump(Func); 1106 Str << ","; 1107 emitRelocOp(Str, Reloc); 1108 Str << "("; 1109 getSrc(1)->dump(Func); 1110 Str << ")"; 1111 } 1112 } 1113 1114 uint32_t getImmediateValue() const { return Imm; } 1115 1116 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } 1117 1118 private: 1119 InstMIPS32Imm16(Cfg *Func, Variable *Dest, Operand *Source, uint32_t Imm, 1120 RelocOp Reloc = RO_No) 1121 : InstMIPS32(Func, K, 1, Dest), Reloc(Reloc), Imm(Imm) { 1122 addSource(Source); 1123 } 1124 1125 InstMIPS32Imm16(Cfg *Func, Variable *Dest, uint32_t Imm, 1126 RelocOp Reloc = RO_No) 1127 : InstMIPS32(Func, K, 0, Dest), Reloc(Reloc), Imm(Imm) {} 1128 1129 InstMIPS32Imm16(Cfg *Func, Variable *Dest, Operand *Src0, Operand *Src1, 1130 RelocOp Reloc = RO_No) 1131 : InstMIPS32(Func, K, 1, Dest), Reloc(Reloc), Imm(0) { 1132 addSource(Src0); 1133 addSource(Src1); 1134 } 1135 1136 static const char *Opcode; 1137 const RelocOp Reloc; 1138 const uint32_t Imm; 1139 }; 1140 1141 /// Conditional mov 1142 template <InstMIPS32::InstKindMIPS32 K> 1143 class InstMIPS32MovConditional : public InstMIPS32 { 1144 InstMIPS32MovConditional() = delete; 1145 InstMIPS32MovConditional(const InstMIPS32MovConditional &) = delete; 1146 InstMIPS32MovConditional & 1147 operator=(const InstMIPS32MovConditional &) = delete; 1148 1149 public: 1150 static InstMIPS32MovConditional *create(Cfg *Func, Variable *Dest, 1151 Variable *Src, Operand *FCC) { 1152 return new (Func->allocate<InstMIPS32MovConditional>()) 1153 InstMIPS32MovConditional(Func, Dest, Src, FCC); 1154 } 1155 1156 void emit(const Cfg *Func) const override { 1157 if (!BuildDefs::dump()) 1158 return; 1159 Ostream &Str = Func->getContext()->getStrEmit(); 1160 assert(getSrcSize() == 2); 1161 Str << "\t" << Opcode << "\t"; 1162 getDest()->emit(Func); 1163 Str << ", "; 1164 getSrc(0)->emit(Func); 1165 Str << ", "; 1166 getSrc(1)->emit(Func); 1167 } 1168 1169 void emitIAS(const Cfg *Func) const override { 1170 (void)Func; 1171 llvm_unreachable("Not yet implemented"); 1172 } 1173 1174 void dump(const Cfg *Func) const override { 1175 if (!BuildDefs::dump()) 1176 return; 1177 Ostream &Str = Func->getContext()->getStrDump(); 1178 dumpDest(Func); 1179 Str << " = "; 1180 dumpOpcode(Str, Opcode, getDest()->getType()); 1181 Str << " "; 1182 dumpSources(Func); 1183 } 1184 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } 1185 1186 private: 1187 InstMIPS32MovConditional(Cfg *Func, Variable *Dest, Variable *Src, 1188 Operand *FCC) 1189 : InstMIPS32(Func, K, 2, Dest) { 1190 addSource(Src); 1191 addSource(FCC); 1192 } 1193 1194 static const char *Opcode; 1195 }; 1196 1197 using InstMIPS32Abs_d = InstMIPS32TwoAddrFPR<InstMIPS32::Abs_d>; 1198 using InstMIPS32Abs_s = InstMIPS32TwoAddrFPR<InstMIPS32::Abs_s>; 1199 using InstMIPS32Add = InstMIPS32ThreeAddrGPR<InstMIPS32::Add>; 1200 using InstMIPS32Add_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Add_d>; 1201 using InstMIPS32Add_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Add_s>; 1202 using InstMIPS32Addu = InstMIPS32ThreeAddrGPR<InstMIPS32::Addu>; 1203 using InstMIPS32Addi = InstMIPS32Imm16<InstMIPS32::Addi, true>; 1204 using InstMIPS32Addiu = InstMIPS32Imm16<InstMIPS32::Addiu, true>; 1205 using InstMIPS32And = InstMIPS32ThreeAddrGPR<InstMIPS32::And>; 1206 using InstMIPS32Andi = InstMIPS32Imm16<InstMIPS32::Andi>; 1207 using InstMIPS32C_eq_d = InstMIPS32FPCmp<InstMIPS32::C_eq_d>; 1208 using InstMIPS32C_eq_s = InstMIPS32FPCmp<InstMIPS32::C_eq_s>; 1209 using InstMIPS32C_ole_d = InstMIPS32FPCmp<InstMIPS32::C_ole_d>; 1210 using InstMIPS32C_ole_s = InstMIPS32FPCmp<InstMIPS32::C_ole_s>; 1211 using InstMIPS32C_olt_d = InstMIPS32FPCmp<InstMIPS32::C_olt_d>; 1212 using InstMIPS32C_olt_s = InstMIPS32FPCmp<InstMIPS32::C_olt_s>; 1213 using InstMIPS32C_ueq_d = InstMIPS32FPCmp<InstMIPS32::C_ueq_d>; 1214 using InstMIPS32C_ueq_s = InstMIPS32FPCmp<InstMIPS32::C_ueq_s>; 1215 using InstMIPS32C_ule_d = InstMIPS32FPCmp<InstMIPS32::C_ule_d>; 1216 using InstMIPS32C_ule_s = InstMIPS32FPCmp<InstMIPS32::C_ule_s>; 1217 using InstMIPS32C_ult_d = InstMIPS32FPCmp<InstMIPS32::C_ult_d>; 1218 using InstMIPS32C_ult_s = InstMIPS32FPCmp<InstMIPS32::C_ult_s>; 1219 using InstMIPS32C_un_d = InstMIPS32FPCmp<InstMIPS32::C_un_d>; 1220 using InstMIPS32C_un_s = InstMIPS32FPCmp<InstMIPS32::C_un_s>; 1221 using InstMIPS32Clz = InstMIPS32TwoAddrGPR<InstMIPS32::Clz>; 1222 using InstMIPS32Cvt_d_s = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_d_s>; 1223 using InstMIPS32Cvt_d_l = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_d_l>; 1224 using InstMIPS32Cvt_d_w = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_d_w>; 1225 using InstMIPS32Cvt_s_d = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_d>; 1226 using InstMIPS32Cvt_s_l = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_l>; 1227 using InstMIPS32Cvt_s_w = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_w>; 1228 using InstMIPS32Div = InstMIPS32ThreeAddrGPR<InstMIPS32::Div>; 1229 using InstMIPS32Div_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Div_d>; 1230 using InstMIPS32Div_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Div_s>; 1231 using InstMIPS32Divu = InstMIPS32ThreeAddrGPR<InstMIPS32::Divu>; 1232 using InstMIPS32La = InstMIPS32UnaryopGPR<InstMIPS32::La>; 1233 using InstMIPS32Ldc1 = InstMIPS32Load<InstMIPS32::Ldc1>; 1234 using InstMIPS32Ll = InstMIPS32Load<InstMIPS32::Ll>; 1235 using InstMIPS32Lui = InstMIPS32UnaryopGPR<InstMIPS32::Lui>; 1236 using InstMIPS32Lw = InstMIPS32Load<InstMIPS32::Lw>; 1237 using InstMIPS32Lwc1 = InstMIPS32Load<InstMIPS32::Lwc1>; 1238 using InstMIPS32Mfc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mfc1>; 1239 using InstMIPS32Mfhi = InstMIPS32UnaryopGPR<InstMIPS32::Mfhi>; 1240 using InstMIPS32Mflo = InstMIPS32UnaryopGPR<InstMIPS32::Mflo>; 1241 using InstMIPS32Mov_d = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_d>; 1242 using InstMIPS32Mov_s = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_s>; 1243 using InstMIPS32Movf = InstMIPS32MovConditional<InstMIPS32::Movf>; 1244 using InstMIPS32Movn = InstMIPS32ThreeAddrGPR<InstMIPS32::Movn>; 1245 using InstMIPS32Movn_d = InstMIPS32ThreeAddrGPR<InstMIPS32::Movn_d>; 1246 using InstMIPS32Movn_s = InstMIPS32ThreeAddrGPR<InstMIPS32::Movn_s>; 1247 using InstMIPS32Movt = InstMIPS32MovConditional<InstMIPS32::Movt>; 1248 using InstMIPS32Movz = InstMIPS32ThreeAddrGPR<InstMIPS32::Movz>; 1249 using InstMIPS32Movz_d = InstMIPS32ThreeAddrGPR<InstMIPS32::Movz_d>; 1250 using InstMIPS32Movz_s = InstMIPS32ThreeAddrGPR<InstMIPS32::Movz_s>; 1251 using InstMIPS32Mtc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mtc1>; 1252 using InstMIPS32Mthi = InstMIPS32UnaryopGPR<InstMIPS32::Mthi>; 1253 using InstMIPS32Mtlo = InstMIPS32UnaryopGPR<InstMIPS32::Mtlo>; 1254 using InstMIPS32Mul = InstMIPS32ThreeAddrGPR<InstMIPS32::Mul>; 1255 using InstMIPS32Mul_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Mul_d>; 1256 using InstMIPS32Mul_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Mul_s>; 1257 using InstMIPS32Mult = InstMIPS32ThreeAddrGPR<InstMIPS32::Mult>; 1258 using InstMIPS32Multu = InstMIPS32ThreeAddrGPR<InstMIPS32::Multu>; 1259 using InstMIPS32Nor = InstMIPS32ThreeAddrGPR<InstMIPS32::Nor>; 1260 using InstMIPS32Or = InstMIPS32ThreeAddrGPR<InstMIPS32::Or>; 1261 using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>; 1262 using InstMIPS32Sc = InstMIPS32Store<InstMIPS32::Sc>; 1263 using InstMIPS32Sdc1 = InstMIPS32Store<InstMIPS32::Sdc1>; 1264 using InstMIPS32Sll = InstMIPS32Imm16<InstMIPS32::Sll>; 1265 using InstMIPS32Sllv = InstMIPS32ThreeAddrGPR<InstMIPS32::Sllv>; 1266 using InstMIPS32Slt = InstMIPS32ThreeAddrGPR<InstMIPS32::Slt>; 1267 using InstMIPS32Slti = InstMIPS32Imm16<InstMIPS32::Slti>; 1268 using InstMIPS32Sltiu = InstMIPS32Imm16<InstMIPS32::Sltiu>; 1269 using InstMIPS32Sltu = InstMIPS32ThreeAddrGPR<InstMIPS32::Sltu>; 1270 using InstMIPS32Sqrt_d = InstMIPS32TwoAddrFPR<InstMIPS32::Sqrt_d>; 1271 using InstMIPS32Sqrt_s = InstMIPS32TwoAddrFPR<InstMIPS32::Sqrt_s>; 1272 using InstMIPS32Sra = InstMIPS32Imm16<InstMIPS32::Sra>; 1273 using InstMIPS32Srav = InstMIPS32ThreeAddrGPR<InstMIPS32::Srav>; 1274 using InstMIPS32Srl = InstMIPS32Imm16<InstMIPS32::Srl>; 1275 using InstMIPS32Srlv = InstMIPS32ThreeAddrGPR<InstMIPS32::Srlv>; 1276 using InstMIPS32Sub = InstMIPS32ThreeAddrGPR<InstMIPS32::Sub>; 1277 using InstMIPS32Sub_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Sub_d>; 1278 using InstMIPS32Sub_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Sub_s>; 1279 using InstMIPS32Subu = InstMIPS32ThreeAddrGPR<InstMIPS32::Subu>; 1280 using InstMIPS32Sw = InstMIPS32Store<InstMIPS32::Sw>; 1281 using InstMIPS32Swc1 = InstMIPS32Store<InstMIPS32::Swc1>; 1282 using InstMIPS32Teq = InstMIPS32Trap<InstMIPS32::Teq>; 1283 using InstMIPS32Trunc_l_d = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_l_d>; 1284 using InstMIPS32Trunc_l_s = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_l_s>; 1285 using InstMIPS32Trunc_w_d = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_w_d>; 1286 using InstMIPS32Trunc_w_s = InstMIPS32TwoAddrFPR<InstMIPS32::Trunc_w_s>; 1287 using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>; 1288 using InstMIPS32Xor = InstMIPS32ThreeAddrGPR<InstMIPS32::Xor>; 1289 using InstMIPS32Xori = InstMIPS32Imm16<InstMIPS32::Xori>; 1290 1291 /// Handles (some of) vmov's various formats. 1292 class InstMIPS32Mov final : public InstMIPS32 { 1293 InstMIPS32Mov() = delete; 1294 InstMIPS32Mov(const InstMIPS32Mov &) = delete; 1295 InstMIPS32Mov &operator=(const InstMIPS32Mov &) = delete; 1296 1297 public: 1298 static InstMIPS32Mov *create(Cfg *Func, Variable *Dest, Operand *Src, 1299 Operand *Src2) { 1300 return new (Func->allocate<InstMIPS32Mov>()) 1301 InstMIPS32Mov(Func, Dest, Src, Src2); 1302 } 1303 1304 bool isRedundantAssign() const override { 1305 return checkForRedundantAssign(getDest(), getSrc(0)); 1306 } 1307 // bool isSimpleAssign() const override { return true; } 1308 void emit(const Cfg *Func) const override; 1309 void emitIAS(const Cfg *Func) const override; 1310 void dump(const Cfg *Func) const override; 1311 static bool classof(const Inst *Inst) { return isClassof(Inst, Mov); } 1312 1313 Variable *getDestHi() const { return DestHi; } 1314 1315 private: 1316 InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src, Operand *Src2); 1317 1318 void emitMultiDestSingleSource(const Cfg *Func) const; 1319 void emitSingleDestMultiSource(const Cfg *Func) const; 1320 void emitSingleDestSingleSource(const Cfg *Func) const; 1321 1322 Variable *DestHi = nullptr; 1323 }; 1324 1325 /// Handle double to i64 move 1326 class InstMIPS32MovFP64ToI64 final : public InstMIPS32 { 1327 InstMIPS32MovFP64ToI64() = delete; 1328 InstMIPS32MovFP64ToI64(const InstMIPS32MovFP64ToI64 &) = delete; 1329 InstMIPS32MovFP64ToI64 &operator=(const InstMIPS32MovFP64ToI64 &) = delete; 1330 1331 public: 1332 static InstMIPS32MovFP64ToI64 *create(Cfg *Func, Variable *Dest, Operand *Src, 1333 Int64Part Int64HiLo) { 1334 return new (Func->allocate<InstMIPS32MovFP64ToI64>()) 1335 InstMIPS32MovFP64ToI64(Func, Dest, Src, Int64HiLo); 1336 } 1337 1338 bool isRedundantAssign() const override { 1339 return checkForRedundantAssign(getDest(), getSrc(0)); 1340 } 1341 1342 void dump(const Cfg *Func) const override { 1343 if (!BuildDefs::dump()) 1344 return; 1345 Ostream &Str = Func->getContext()->getStrDump(); 1346 getDest()->dump(Func); 1347 Str << " = "; 1348 dumpOpcode(Str, "mov_fp", getDest()->getType()); 1349 Str << " "; 1350 getSrc(0)->dump(Func); 1351 } 1352 1353 Int64Part getInt64Part() const { return Int64HiLo; } 1354 1355 static bool classof(const Inst *Inst) { return isClassof(Inst, Mov_fp); } 1356 1357 private: 1358 InstMIPS32MovFP64ToI64(Cfg *Func, Variable *Dest, Operand *Src, 1359 Int64Part Int64HiLo); 1360 const Int64Part Int64HiLo; 1361 }; 1362 1363 // Declare partial template specializations of emit() methods that already have 1364 // default implementations. Without this, there is the possibility of ODR 1365 // violations and link errors. 1366 1367 template <> void InstMIPS32Abs_d::emitIAS(const Cfg *Func) const; 1368 template <> void InstMIPS32Abs_s::emitIAS(const Cfg *Func) const; 1369 template <> void InstMIPS32Add_d::emitIAS(const Cfg *Func) const; 1370 template <> void InstMIPS32Add_s::emitIAS(const Cfg *Func) const; 1371 template <> void InstMIPS32Addi::emitIAS(const Cfg *Func) const; 1372 template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const; 1373 template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const; 1374 template <> void InstMIPS32And::emitIAS(const Cfg *Func) const; 1375 template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const; 1376 template <> void InstMIPS32C_eq_d::emitIAS(const Cfg *Func) const; 1377 template <> void InstMIPS32C_eq_s::emitIAS(const Cfg *Func) const; 1378 template <> void InstMIPS32C_ole_d::emitIAS(const Cfg *Func) const; 1379 template <> void InstMIPS32C_ole_s::emitIAS(const Cfg *Func) const; 1380 template <> void InstMIPS32C_olt_d::emitIAS(const Cfg *Func) const; 1381 template <> void InstMIPS32C_olt_s::emitIAS(const Cfg *Func) const; 1382 template <> void InstMIPS32C_ueq_d::emitIAS(const Cfg *Func) const; 1383 template <> void InstMIPS32C_ueq_s::emitIAS(const Cfg *Func) const; 1384 template <> void InstMIPS32C_ule_d::emitIAS(const Cfg *Func) const; 1385 template <> void InstMIPS32C_ule_s::emitIAS(const Cfg *Func) const; 1386 template <> void InstMIPS32C_ult_d::emitIAS(const Cfg *Func) const; 1387 template <> void InstMIPS32C_ult_s::emitIAS(const Cfg *Func) const; 1388 template <> void InstMIPS32C_un_d::emitIAS(const Cfg *Func) const; 1389 template <> void InstMIPS32C_un_s::emitIAS(const Cfg *Func) const; 1390 template <> void InstMIPS32Clz::emitIAS(const Cfg *Func) const; 1391 template <> void InstMIPS32Cvt_d_l::emitIAS(const Cfg *Func) const; 1392 template <> void InstMIPS32Cvt_d_s::emitIAS(const Cfg *Func) const; 1393 template <> void InstMIPS32Cvt_d_w::emitIAS(const Cfg *Func) const; 1394 template <> void InstMIPS32Cvt_s_d::emitIAS(const Cfg *Func) const; 1395 template <> void InstMIPS32Cvt_s_l::emitIAS(const Cfg *Func) const; 1396 template <> void InstMIPS32Cvt_s_w::emitIAS(const Cfg *Func) const; 1397 template <> void InstMIPS32Div::emitIAS(const Cfg *Func) const; 1398 template <> void InstMIPS32Div_d::emitIAS(const Cfg *Func) const; 1399 template <> void InstMIPS32Div_s::emitIAS(const Cfg *Func) const; 1400 template <> void InstMIPS32Divu::emitIAS(const Cfg *Func) const; 1401 template <> void InstMIPS32Ldc1::emitIAS(const Cfg *Func) const; 1402 template <> void InstMIPS32Ll::emitIAS(const Cfg *Func) const; 1403 template <> void InstMIPS32Lui::emit(const Cfg *Func) const; 1404 template <> void InstMIPS32Lui::emitIAS(const Cfg *Func) const; 1405 template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const; 1406 template <> void InstMIPS32Lwc1::emitIAS(const Cfg *Func) const; 1407 template <> void InstMIPS32Mfc1::emitIAS(const Cfg *Func) const; 1408 template <> void InstMIPS32Mflo::emit(const Cfg *Func) const; 1409 template <> void InstMIPS32Mflo::emitIAS(const Cfg *Func) const; 1410 template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const; 1411 template <> void InstMIPS32Mfhi::emitIAS(const Cfg *Func) const; 1412 template <> void InstMIPS32Mov_d::emitIAS(const Cfg *Func) const; 1413 template <> void InstMIPS32Mov_s::emitIAS(const Cfg *Func) const; 1414 template <> void InstMIPS32Movf::emitIAS(const Cfg *Func) const; 1415 template <> void InstMIPS32Movn::emitIAS(const Cfg *Func) const; 1416 template <> void InstMIPS32Movn_d::emitIAS(const Cfg *Func) const; 1417 template <> void InstMIPS32Movn_s::emitIAS(const Cfg *Func) const; 1418 template <> void InstMIPS32Movt::emitIAS(const Cfg *Func) const; 1419 template <> void InstMIPS32Movz::emitIAS(const Cfg *Func) const; 1420 template <> void InstMIPS32Movz_d::emitIAS(const Cfg *Func) const; 1421 template <> void InstMIPS32Movz_s::emitIAS(const Cfg *Func) const; 1422 template <> void InstMIPS32Mtc1::emit(const Cfg *Func) const; 1423 template <> void InstMIPS32Mtc1::emitIAS(const Cfg *Func) const; 1424 template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const; 1425 template <> void InstMIPS32Mtlo::emitIAS(const Cfg *Func) const; 1426 template <> void InstMIPS32Mthi::emit(const Cfg *Func) const; 1427 template <> void InstMIPS32Mthi::emitIAS(const Cfg *Func) const; 1428 template <> void InstMIPS32Mul::emitIAS(const Cfg *Func) const; 1429 template <> void InstMIPS32Mul_d::emitIAS(const Cfg *Func) const; 1430 template <> void InstMIPS32Mul_s::emitIAS(const Cfg *Func) const; 1431 template <> void InstMIPS32Mult::emit(const Cfg *Func) const; 1432 template <> void InstMIPS32Multu::emit(const Cfg *Func) const; 1433 template <> void InstMIPS32Multu::emitIAS(const Cfg *Func) const; 1434 template <> void InstMIPS32Nor::emitIAS(const Cfg *Func) const; 1435 template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const; 1436 template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const; 1437 template <> void InstMIPS32Sc::emitIAS(const Cfg *Func) const; 1438 template <> void InstMIPS32Sdc1::emitIAS(const Cfg *Func) const; 1439 template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const; 1440 template <> void InstMIPS32Sllv::emitIAS(const Cfg *Func) const; 1441 template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const; 1442 template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const; 1443 template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const; 1444 template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const; 1445 template <> void InstMIPS32Sqrt_d::emitIAS(const Cfg *Func) const; 1446 template <> void InstMIPS32Sqrt_s::emitIAS(const Cfg *Func) const; 1447 template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const; 1448 template <> void InstMIPS32Swc1::emitIAS(const Cfg *Func) const; 1449 template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const; 1450 template <> void InstMIPS32Srav::emitIAS(const Cfg *Func) const; 1451 template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const; 1452 template <> void InstMIPS32Srlv::emitIAS(const Cfg *Func) const; 1453 template <> void InstMIPS32Sub_d::emitIAS(const Cfg *Func) const; 1454 template <> void InstMIPS32Sub_s::emitIAS(const Cfg *Func) const; 1455 template <> void InstMIPS32Subu::emitIAS(const Cfg *Func) const; 1456 template <> void InstMIPS32Teq::emitIAS(const Cfg *Func) const; 1457 template <> void InstMIPS32Trunc_l_d::emitIAS(const Cfg *Func) const; 1458 template <> void InstMIPS32Trunc_l_s::emitIAS(const Cfg *Func) const; 1459 template <> void InstMIPS32Trunc_w_d::emitIAS(const Cfg *Func) const; 1460 template <> void InstMIPS32Trunc_w_s::emitIAS(const Cfg *Func) const; 1461 template <> void InstMIPS32Xor::emitIAS(const Cfg *Func) const; 1462 template <> void InstMIPS32Xori::emitIAS(const Cfg *Func) const; 1463 1464 } // end of namespace MIPS32 1465 } // end of namespace Ice 1466 1467 #endif // SUBZERO_SRC_ICEINSTMIPS32_H 1468