Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceInstMIPS32.h - MIPS32 machine instrs --*- C++ -*-=== // | 1 //===- subzero/src/IceInstMIPS32.h - MIPS32 machine instrs --*- C++ -*-=== // |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 | 21 |
| 22 #include "IceConditionCodesMIPS32.h" | 22 #include "IceConditionCodesMIPS32.h" |
| 23 #include "IceDefs.h" | 23 #include "IceDefs.h" |
| 24 #include "IceInst.h" | 24 #include "IceInst.h" |
| 25 #include "IceInstMIPS32.def" | 25 #include "IceInstMIPS32.def" |
| 26 #include "IceOperand.h" | 26 #include "IceOperand.h" |
| 27 | 27 |
| 28 namespace Ice { | 28 namespace Ice { |
| 29 namespace MIPS32 { | 29 namespace MIPS32 { |
| 30 | 30 |
| 31 enum relocOp { no, hi, lo }; | |
|
Jim Stichnoth
2016/07/05 14:29:27
Capitalize these per LLVM coding convention. I.e.
| |
| 32 | |
| 33 inline void emitRelocOp(Ostream &Str, relocOp reloc) { | |
|
Jim Stichnoth
2016/07/05 14:29:27
Also capitalize variable names, i.e. "Reloc".
| |
| 34 switch (reloc) { | |
| 35 case no: | |
| 36 break; | |
| 37 case lo: | |
| 38 Str << "%lo"; | |
| 39 break; | |
| 40 case hi: | |
| 41 Str << "%hi"; | |
| 42 break; | |
| 43 } | |
| 44 } | |
| 45 | |
| 31 class TargetMIPS32; | 46 class TargetMIPS32; |
| 32 | 47 |
| 33 /// OperandMips32 extends the Operand hierarchy. | 48 /// OperandMips32 extends the Operand hierarchy. |
| 34 // | 49 // |
| 35 class OperandMIPS32 : public Operand { | 50 class OperandMIPS32 : public Operand { |
| 36 OperandMIPS32() = delete; | 51 OperandMIPS32() = delete; |
| 37 OperandMIPS32(const OperandMIPS32 &) = delete; | 52 OperandMIPS32(const OperandMIPS32 &) = delete; |
| 38 OperandMIPS32 &operator=(const OperandMIPS32 &) = delete; | 53 OperandMIPS32 &operator=(const OperandMIPS32 &) = delete; |
| 39 | 54 |
| 40 public: | 55 public: |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 65 // TODO(jvoung): unify with the assembler. | 80 // TODO(jvoung): unify with the assembler. |
| 66 enum AddrMode { Offset }; | 81 enum AddrMode { Offset }; |
| 67 | 82 |
| 68 /// NOTE: The Variable-typed operands have to be registers. | 83 /// NOTE: The Variable-typed operands have to be registers. |
| 69 /// | 84 /// |
| 70 /// Reg + Imm. The Immediate actually has a limited number of bits | 85 /// Reg + Imm. The Immediate actually has a limited number of bits |
| 71 /// for encoding, so check canHoldOffset first. It cannot handle | 86 /// for encoding, so check canHoldOffset first. It cannot handle |
| 72 /// general Constant operands like ConstantRelocatable, since a relocatable | 87 /// general Constant operands like ConstantRelocatable, since a relocatable |
| 73 /// can potentially take up too many bits. | 88 /// can potentially take up too many bits. |
| 74 static OperandMIPS32Mem *create(Cfg *Func, Type Ty, Variable *Base, | 89 static OperandMIPS32Mem *create(Cfg *Func, Type Ty, Variable *Base, |
| 75 ConstantInteger32 *ImmOffset, | 90 Operand *ImmOffset, AddrMode Mode = Offset) { |
| 76 AddrMode Mode = Offset) { | |
| 77 return new (Func->allocate<OperandMIPS32Mem>()) | 91 return new (Func->allocate<OperandMIPS32Mem>()) |
| 78 OperandMIPS32Mem(Func, Ty, Base, ImmOffset, Mode); | 92 OperandMIPS32Mem(Func, Ty, Base, ImmOffset, Mode); |
| 79 } | 93 } |
| 80 | 94 |
| 81 Variable *getBase() const { return Base; } | 95 Variable *getBase() const { return Base; } |
| 82 ConstantInteger32 *getOffset() const { return ImmOffset; } | 96 Operand *getOffset() const { return ImmOffset; } |
| 83 AddrMode getAddrMode() const { return Mode; } | 97 AddrMode getAddrMode() const { return Mode; } |
| 84 | 98 |
| 85 void emit(const Cfg *Func) const override; | 99 void emit(const Cfg *Func) const override; |
| 86 using OperandMIPS32::dump; | 100 using OperandMIPS32::dump; |
| 87 | 101 |
| 88 static bool classof(const Operand *Operand) { | 102 static bool classof(const Operand *Operand) { |
| 89 return Operand->getKind() == static_cast<OperandKind>(kMem); | 103 return Operand->getKind() == static_cast<OperandKind>(kMem); |
| 90 } | 104 } |
| 91 | 105 |
| 92 /// Return true if a load/store instruction for an element of type Ty | 106 /// Return true if a load/store instruction for an element of type Ty |
| 93 /// can encode the Offset directly in the immediate field of the 32-bit | 107 /// can encode the Offset directly in the immediate field of the 32-bit |
| 94 /// MIPS instruction. For some types, if the load is Sign extending, then | 108 /// MIPS instruction. For some types, if the load is Sign extending, then |
| 95 /// the range is reduced. | 109 /// the range is reduced. |
| 96 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset); | 110 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset); |
| 97 | 111 |
| 98 void dump(const Cfg *Func, Ostream &Str) const override { | 112 void dump(const Cfg *Func, Ostream &Str) const override { |
| 99 (void)Func; | 113 (void)Func; |
| 100 (void)Str; | 114 (void)Str; |
| 101 } | 115 } |
| 102 | 116 |
| 103 private: | 117 private: |
| 104 OperandMIPS32Mem(Cfg *Func, Type Ty, Variable *Base, | 118 OperandMIPS32Mem(Cfg *Func, Type Ty, Variable *Base, Operand *ImmOffset, |
| 105 ConstantInteger32 *ImmOffset, AddrMode Mode); | 119 AddrMode Mode); |
| 106 | 120 |
| 107 Variable *Base; | 121 Variable *Base; |
|
Jim Stichnoth
2016/07/05 14:29:27
Seems like these fields could be "final", i.e.
mohit.bhakkad
2016/07/06 08:00:28
I didn't changed Base to constant pointer, as its
| |
| 108 ConstantInteger32 *ImmOffset; | 122 Operand *ImmOffset; |
| 109 AddrMode Mode; | 123 AddrMode Mode; |
| 110 }; | 124 }; |
| 111 | 125 |
| 112 /// Base class for Mips instructions. | 126 /// Base class for Mips instructions. |
| 113 class InstMIPS32 : public InstTarget { | 127 class InstMIPS32 : public InstTarget { |
| 114 InstMIPS32() = delete; | 128 InstMIPS32() = delete; |
| 115 InstMIPS32(const InstMIPS32 &) = delete; | 129 InstMIPS32(const InstMIPS32 &) = delete; |
| 116 InstMIPS32 &operator=(const InstMIPS32 &) = delete; | 130 InstMIPS32 &operator=(const InstMIPS32 &) = delete; |
| 117 | 131 |
| 118 public: | 132 public: |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 247 }; | 261 }; |
| 248 | 262 |
| 249 /// Instructions of the form x := op(y). | 263 /// Instructions of the form x := op(y). |
| 250 template <InstMIPS32::InstKindMIPS32 K> | 264 template <InstMIPS32::InstKindMIPS32 K> |
| 251 class InstMIPS32UnaryopGPR : public InstMIPS32 { | 265 class InstMIPS32UnaryopGPR : public InstMIPS32 { |
| 252 InstMIPS32UnaryopGPR() = delete; | 266 InstMIPS32UnaryopGPR() = delete; |
| 253 InstMIPS32UnaryopGPR(const InstMIPS32UnaryopGPR &) = delete; | 267 InstMIPS32UnaryopGPR(const InstMIPS32UnaryopGPR &) = delete; |
| 254 InstMIPS32UnaryopGPR &operator=(const InstMIPS32UnaryopGPR &) = delete; | 268 InstMIPS32UnaryopGPR &operator=(const InstMIPS32UnaryopGPR &) = delete; |
| 255 | 269 |
| 256 public: | 270 public: |
| 257 static InstMIPS32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src) { | 271 static InstMIPS32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src, |
| 272 relocOp reloc = no) { | |
| 258 return new (Func->allocate<InstMIPS32UnaryopGPR>()) | 273 return new (Func->allocate<InstMIPS32UnaryopGPR>()) |
| 259 InstMIPS32UnaryopGPR(Func, Dest, Src); | 274 InstMIPS32UnaryopGPR(Func, Dest, Src, reloc); |
| 260 } | 275 } |
| 261 void emit(const Cfg *Func) const override { | 276 void emit(const Cfg *Func) const override { |
| 262 if (!BuildDefs::dump()) | 277 if (!BuildDefs::dump()) |
| 263 return; | 278 return; |
| 264 emitUnaryopGPR(Opcode, this, Func); | 279 emitUnaryopGPR(Opcode, this, Func); |
| 265 } | 280 } |
| 266 void emitIAS(const Cfg *Func) const override { | 281 void emitIAS(const Cfg *Func) const override { |
| 267 (void)Func; | 282 (void)Func; |
| 268 llvm_unreachable("Not yet implemented"); | 283 llvm_unreachable("Not yet implemented"); |
| 269 } | 284 } |
| 270 void dump(const Cfg *Func) const override { | 285 void dump(const Cfg *Func) const override { |
| 271 if (!BuildDefs::dump()) | 286 if (!BuildDefs::dump()) |
| 272 return; | 287 return; |
| 273 Ostream &Str = Func->getContext()->getStrDump(); | 288 Ostream &Str = Func->getContext()->getStrDump(); |
| 274 dumpOpcode(Str, Opcode, getDest()->getType()); | 289 dumpOpcode(Str, Opcode, getDest()->getType()); |
| 275 Str << " "; | 290 Str << " "; |
| 276 dumpDest(Func); | 291 dumpDest(Func); |
| 277 Str << ", "; | 292 Str << ", "; |
| 278 dumpSources(Func); | 293 dumpSources(Func); |
| 279 } | 294 } |
| 280 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 295 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 281 | 296 |
| 282 protected: | 297 protected: |
| 283 InstMIPS32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) | 298 InstMIPS32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src, |
| 284 : InstMIPS32(Func, K, 1, Dest) { | 299 relocOp reloc = no) |
| 300 : InstMIPS32(Func, K, 1, Dest), reloc(reloc) { | |
| 285 addSource(Src); | 301 addSource(Src); |
| 286 } | 302 } |
| 287 | 303 |
| 288 private: | 304 private: |
| 289 static const char *Opcode; | 305 static const char *Opcode; |
| 306 relocOp reloc; | |
| 290 }; | 307 }; |
| 291 | 308 |
| 292 /// Instructions of the form opcode reg, reg. | 309 /// Instructions of the form opcode reg, reg. |
| 293 template <InstMIPS32::InstKindMIPS32 K> | 310 template <InstMIPS32::InstKindMIPS32 K> |
| 294 class InstMIPS32TwoAddrFPR : public InstMIPS32 { | 311 class InstMIPS32TwoAddrFPR : public InstMIPS32 { |
| 295 InstMIPS32TwoAddrFPR() = delete; | 312 InstMIPS32TwoAddrFPR() = delete; |
| 296 InstMIPS32TwoAddrFPR(const InstMIPS32TwoAddrFPR &) = delete; | 313 InstMIPS32TwoAddrFPR(const InstMIPS32TwoAddrFPR &) = delete; |
| 297 InstMIPS32TwoAddrFPR &operator=(const InstMIPS32TwoAddrFPR &) = delete; | 314 InstMIPS32TwoAddrFPR &operator=(const InstMIPS32TwoAddrFPR &) = delete; |
| 298 | 315 |
| 299 public: | 316 public: |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 478 // InstMIPS32Memory represents instructions which loads/stores data on memory | 495 // InstMIPS32Memory represents instructions which loads/stores data on memory |
| 479 // Its format is "OPCODE GPR, OFFSET(BASE GPR)" | 496 // Its format is "OPCODE GPR, OFFSET(BASE GPR)" |
| 480 template <InstMIPS32::InstKindMIPS32 K> | 497 template <InstMIPS32::InstKindMIPS32 K> |
| 481 class InstMIPS32Memory : public InstMIPS32 { | 498 class InstMIPS32Memory : public InstMIPS32 { |
| 482 InstMIPS32Memory() = delete; | 499 InstMIPS32Memory() = delete; |
| 483 InstMIPS32Memory(const InstMIPS32Memory &) = delete; | 500 InstMIPS32Memory(const InstMIPS32Memory &) = delete; |
| 484 InstMIPS32Memory &operator=(const InstMIPS32Memory &) = delete; | 501 InstMIPS32Memory &operator=(const InstMIPS32Memory &) = delete; |
| 485 | 502 |
| 486 public: | 503 public: |
| 487 static InstMIPS32Memory *create(Cfg *Func, Variable *Value, | 504 static InstMIPS32Memory *create(Cfg *Func, Variable *Value, |
| 488 OperandMIPS32Mem *Mem) { | 505 OperandMIPS32Mem *Mem, relocOp reloc = no) { |
| 489 return new (Func->allocate<InstMIPS32Memory>()) | 506 return new (Func->allocate<InstMIPS32Memory>()) |
| 490 InstMIPS32Memory(Func, Value, Mem); | 507 InstMIPS32Memory(Func, Value, Mem, reloc); |
| 491 } | 508 } |
| 492 | 509 |
| 493 void emit(const Cfg *Func) const override { | 510 void emit(const Cfg *Func) const override { |
| 494 if (!BuildDefs::dump()) | 511 if (!BuildDefs::dump()) |
| 495 return; | 512 return; |
| 496 Ostream &Str = Func->getContext()->getStrEmit(); | 513 Ostream &Str = Func->getContext()->getStrEmit(); |
| 497 assert(getSrcSize() == 2); | 514 assert(getSrcSize() == 2); |
| 498 Str << "\t" << Opcode << "\t"; | 515 Str << "\t" << Opcode << "\t"; |
| 499 getSrc(0)->emit(Func); | 516 getSrc(0)->emit(Func); |
| 500 Str << ", "; | 517 Str << ", "; |
| 518 emitRelocOp(Str, reloc); | |
| 519 Str << (reloc ? "(" : ""); | |
| 501 getSrc(1)->emit(Func); | 520 getSrc(1)->emit(Func); |
| 521 Str << (reloc ? ")" : ""); | |
| 502 } | 522 } |
| 503 | 523 |
| 504 void emitIAS(const Cfg *Func) const override { | 524 void emitIAS(const Cfg *Func) const override { |
| 505 (void)Func; | 525 (void)Func; |
| 506 llvm_unreachable("Not yet implemented"); | 526 llvm_unreachable("Not yet implemented"); |
| 507 } | 527 } |
| 508 | 528 |
| 509 void dump(const Cfg *Func) const override { | 529 void dump(const Cfg *Func) const override { |
| 510 if (!BuildDefs::dump()) | 530 if (!BuildDefs::dump()) |
| 511 return; | 531 return; |
| 512 Ostream &Str = Func->getContext()->getStrDump(); | 532 Ostream &Str = Func->getContext()->getStrDump(); |
| 513 Str << "\t" << Opcode << "\t"; | 533 Str << "\t" << Opcode << "\t"; |
| 514 Str << " "; | 534 getSrc(0)->dump(Func); |
| 535 Str << ", "; | |
| 536 emitRelocOp(Str, reloc); | |
| 537 Str << (reloc ? "(" : ""); | |
| 515 getSrc(1)->dump(Func); | 538 getSrc(1)->dump(Func); |
| 516 Str << ", "; | 539 Str << (reloc ? ")" : ""); |
| 517 getSrc(0)->dump(Func); | |
| 518 } | 540 } |
| 519 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 541 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 520 | 542 |
| 521 private: | 543 private: |
| 522 InstMIPS32Memory(Cfg *Func, Variable *Value, OperandMIPS32Mem *Mem) | 544 InstMIPS32Memory(Cfg *Func, Variable *Value, OperandMIPS32Mem *Mem, |
| 523 : InstMIPS32(Func, K, 2, nullptr) { | 545 relocOp reloc = no) |
| 546 : InstMIPS32(Func, K, 2, nullptr), reloc(reloc) { | |
| 524 addSource(Value); | 547 addSource(Value); |
| 525 addSource(Mem); | 548 addSource(Mem); |
| 526 } | 549 } |
| 527 static const char *Opcode; | 550 static const char *Opcode; |
| 551 relocOp reloc; | |
|
Jim Stichnoth
2016/07/05 14:29:27
maybe "const relocOp reloc" ?
| |
| 528 }; | 552 }; |
| 529 | 553 |
| 530 // InstMIPS32Label represents an intra-block label that is the target of an | 554 // InstMIPS32Label represents an intra-block label that is the target of an |
| 531 // intra-block branch. The offset between the label and the branch must be fit | 555 // intra-block branch. The offset between the label and the branch must be fit |
| 532 // in the instruction immediate (considered "near"). | 556 // in the instruction immediate (considered "near"). |
| 533 class InstMIPS32Label : public InstMIPS32 { | 557 class InstMIPS32Label : public InstMIPS32 { |
| 534 InstMIPS32Label() = delete; | 558 InstMIPS32Label() = delete; |
| 535 InstMIPS32Label(const InstMIPS32Label &) = delete; | 559 InstMIPS32Label(const InstMIPS32Label &) = delete; |
| 536 InstMIPS32Label &operator=(const InstMIPS32Label &) = delete; | 560 InstMIPS32Label &operator=(const InstMIPS32Label &) = delete; |
| 537 | 561 |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 728 using InstMIPS32Cvt_d_w = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_d_w>; | 752 using InstMIPS32Cvt_d_w = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_d_w>; |
| 729 using InstMIPS32Cvt_s_d = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_d>; | 753 using InstMIPS32Cvt_s_d = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_d>; |
| 730 using InstMIPS32Cvt_s_l = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_l>; | 754 using InstMIPS32Cvt_s_l = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_l>; |
| 731 using InstMIPS32Cvt_s_w = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_w>; | 755 using InstMIPS32Cvt_s_w = InstMIPS32TwoAddrFPR<InstMIPS32::Cvt_s_w>; |
| 732 using InstMIPS32Div = InstMIPS32ThreeAddrGPR<InstMIPS32::Div>; | 756 using InstMIPS32Div = InstMIPS32ThreeAddrGPR<InstMIPS32::Div>; |
| 733 using InstMIPS32Div_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Div_d>; | 757 using InstMIPS32Div_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Div_d>; |
| 734 using InstMIPS32Div_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Div_s>; | 758 using InstMIPS32Div_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Div_s>; |
| 735 using InstMIPS32Divu = InstMIPS32ThreeAddrGPR<InstMIPS32::Divu>; | 759 using InstMIPS32Divu = InstMIPS32ThreeAddrGPR<InstMIPS32::Divu>; |
| 736 using InstMIPS32La = InstMIPS32UnaryopGPR<InstMIPS32::La>; | 760 using InstMIPS32La = InstMIPS32UnaryopGPR<InstMIPS32::La>; |
| 737 using InstMIPS32Ldc1 = InstMIPS32Memory<InstMIPS32::Ldc1>; | 761 using InstMIPS32Ldc1 = InstMIPS32Memory<InstMIPS32::Ldc1>; |
| 738 using InstMIPS32Lui = InstMIPS32Imm16<InstMIPS32::Lui>; | 762 using InstMIPS32Lui = InstMIPS32UnaryopGPR<InstMIPS32::Lui>; |
| 739 using InstMIPS32Lw = InstMIPS32Memory<InstMIPS32::Lw>; | 763 using InstMIPS32Lw = InstMIPS32Memory<InstMIPS32::Lw>; |
| 740 using InstMIPS32Lwc1 = InstMIPS32Memory<InstMIPS32::Lwc1>; | 764 using InstMIPS32Lwc1 = InstMIPS32Memory<InstMIPS32::Lwc1>; |
| 741 using InstMIPS32Mfc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mfc1>; | 765 using InstMIPS32Mfc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mfc1>; |
| 742 using InstMIPS32Mfhi = InstMIPS32UnaryopGPR<InstMIPS32::Mfhi>; | 766 using InstMIPS32Mfhi = InstMIPS32UnaryopGPR<InstMIPS32::Mfhi>; |
| 743 using InstMIPS32Mflo = InstMIPS32UnaryopGPR<InstMIPS32::Mflo>; | 767 using InstMIPS32Mflo = InstMIPS32UnaryopGPR<InstMIPS32::Mflo>; |
| 744 using InstMIPS32Mov_d = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_d>; | 768 using InstMIPS32Mov_d = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_d>; |
| 745 using InstMIPS32Mov_s = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_s>; | 769 using InstMIPS32Mov_s = InstMIPS32TwoAddrFPR<InstMIPS32::Mov_s>; |
| 746 using InstMIPS32Mtc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mtc1>; | 770 using InstMIPS32Mtc1 = InstMIPS32TwoAddrGPR<InstMIPS32::Mtc1>; |
| 747 using InstMIPS32Mthi = InstMIPS32UnaryopGPR<InstMIPS32::Mthi>; | 771 using InstMIPS32Mthi = InstMIPS32UnaryopGPR<InstMIPS32::Mthi>; |
| 748 using InstMIPS32Mtlo = InstMIPS32UnaryopGPR<InstMIPS32::Mtlo>; | 772 using InstMIPS32Mtlo = InstMIPS32UnaryopGPR<InstMIPS32::Mtlo>; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 820 // Declare partial template specializations of emit() methods that already have | 844 // Declare partial template specializations of emit() methods that already have |
| 821 // default implementations. Without this, there is the possibility of ODR | 845 // default implementations. Without this, there is the possibility of ODR |
| 822 // violations and link errors. | 846 // violations and link errors. |
| 823 | 847 |
| 824 template <> void InstMIPS32Mflo::emit(const Cfg *Func) const; | 848 template <> void InstMIPS32Mflo::emit(const Cfg *Func) const; |
| 825 template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const; | 849 template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const; |
| 826 template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const; | 850 template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const; |
| 827 template <> void InstMIPS32Mthi::emit(const Cfg *Func) const; | 851 template <> void InstMIPS32Mthi::emit(const Cfg *Func) const; |
| 828 template <> void InstMIPS32Mult::emit(const Cfg *Func) const; | 852 template <> void InstMIPS32Mult::emit(const Cfg *Func) const; |
| 829 template <> void InstMIPS32Multu::emit(const Cfg *Func) const; | 853 template <> void InstMIPS32Multu::emit(const Cfg *Func) const; |
| 854 template <> void InstMIPS32Lui::emit(const Cfg *Func) const; | |
| 830 | 855 |
| 831 } // end of namespace MIPS32 | 856 } // end of namespace MIPS32 |
| 832 } // end of namespace Ice | 857 } // end of namespace Ice |
| 833 | 858 |
| 834 #endif // SUBZERO_SRC_ICEINSTMIPS32_H | 859 #endif // SUBZERO_SRC_ICEINSTMIPS32_H |
| OLD | NEW |