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 |
| 11 /// This file declares the InstMIPS32 and OperandMIPS32 classes and their | 11 /// This file declares the InstMIPS32 and OperandMIPS32 classes and their |
| 12 /// subclasses. This represents the machine instructions and operands used for | 12 /// subclasses. This represents the machine instructions and operands used for |
| 13 /// MIPS32 code selection. | 13 /// MIPS32 code selection. |
| 14 /// | 14 /// |
| 15 //===----------------------------------------------------------------------===// | 15 //===----------------------------------------------------------------------===// |
| 16 | 16 |
| 17 #ifndef SUBZERO_SRC_ICEINSTMIPS32_H | 17 #ifndef SUBZERO_SRC_ICEINSTMIPS32_H |
| 18 #define SUBZERO_SRC_ICEINSTMIPS32_H | 18 #define SUBZERO_SRC_ICEINSTMIPS32_H |
| 19 | 19 |
| 20 #include "IceDefs.h" | 20 #include "IceDefs.h" |
| 21 #include "IceInst.h" | 21 #include "IceInst.h" |
| 22 #include "IceInstMIPS32.def" | 22 #include "IceInstMIPS32.def" |
| 23 #include "IceOperand.h" | 23 #include "IceOperand.h" |
| 24 | 24 |
| 25 namespace Ice { | 25 namespace Ice { |
| 26 | 26 |
| 27 class TargetMIPS32; | 27 class TargetMIPS32; |
| 28 | 28 |
| 29 /// OperandMips32 extends the Operand hierarchy. | |
| 30 // | |
| 31 class OperandMIPS32 : public Operand { | |
| 32 OperandMIPS32() = delete; | |
| 33 OperandMIPS32(const OperandMIPS32 &) = delete; | |
| 34 OperandMIPS32 &operator=(const OperandMIPS32 &) = delete; | |
| 35 | |
| 36 public: | |
| 37 enum OperandKindMIPS32 { | |
| 38 k__Start = Operand::kTarget, | |
| 39 kMem, | |
| 40 }; | |
| 41 | |
| 42 using Operand::dump; | |
| 43 void dump(const Cfg *, Ostream &Str) const override { | |
| 44 if (BuildDefs::dump()) | |
| 45 Str << "<OperandMIPS32>"; | |
| 46 } | |
| 47 void emit(const Cfg *Func) const override { | |
|
Jim Stichnoth
2015/10/18 11:48:39
Remove this emit() method?
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
| 48 if (!BuildDefs::dump()) | |
| 49 return; | |
| 50 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 51 // if (isRegReg()) { | |
| 52 Str << "reed\t"; | |
| 53 } | |
| 54 | |
| 55 protected: | |
| 56 OperandMIPS32(OperandKindMIPS32 Kind, Type Ty) | |
| 57 : Operand(static_cast<OperandKind>(Kind), Ty) {} | |
| 58 }; | |
| 59 | |
| 60 class OperandMIPS32Mem : public OperandMIPS32 { | |
| 61 OperandMIPS32Mem() = delete; | |
| 62 OperandMIPS32Mem(const OperandMIPS32Mem &) = delete; | |
| 63 OperandMIPS32Mem &operator=(const OperandMIPS32Mem &) = delete; | |
| 64 | |
| 65 public: | |
| 66 /// Memory operand addressing mode. | |
| 67 /// The enum value also carries the encoding. | |
| 68 // TODO(jvoung): unify with the assembler. | |
| 69 enum AddrMode { Offset }; | |
| 70 | |
| 71 /// NOTE: The Variable-typed operands have to be registers. | |
| 72 /// | |
| 73 /// Reg + Imm. The Immediate actually has a limited number of bits | |
| 74 /// for encoding, so check canHoldOffset first. It cannot handle | |
| 75 /// general Constant operands like ConstantRelocatable, since a relocatable | |
| 76 /// can potentially take up too many bits. | |
| 77 static OperandMIPS32Mem *create(Cfg *Func, Type Ty, Variable *Base, | |
| 78 ConstantInteger32 *ImmOffset, | |
| 79 AddrMode Mode = Offset) { | |
| 80 return new (Func->allocate<OperandMIPS32Mem>()) | |
| 81 OperandMIPS32Mem(Func, Ty, Base, ImmOffset, Mode); | |
| 82 } | |
| 83 | |
| 84 Variable *getBase() const { return Base; } | |
| 85 ConstantInteger32 *getOffset() const { return ImmOffset; } | |
| 86 AddrMode getAddrMode() const { return Mode; } | |
| 87 | |
| 88 void emit(const Cfg *Func) const override; | |
| 89 using OperandMIPS32::dump; | |
| 90 // void dump(const Cfg *Func, Ostream &Str) const override; | |
|
Jim Stichnoth
2015/10/18 11:48:39
remove commented-out code
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
| 91 | |
| 92 static bool classof(const Operand *Operand) { | |
| 93 return Operand->getKind() == static_cast<OperandKind>(kMem); | |
| 94 } | |
| 95 | |
| 96 /// Return true if a load/store instruction for an element of type Ty | |
| 97 /// can encode the Offset directly in the immediate field of the 32-bit | |
| 98 /// MIPS instruction. For some types, if the load is Sign extending, then | |
| 99 /// the range is reduced. | |
| 100 static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset); | |
| 101 | |
| 102 virtual void dump(const Cfg *Func, Ostream &Str) const override { | |
|
Jim Stichnoth
2015/10/18 11:48:39
I don't think you need both "virtual" and "overrid
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
| 103 (void)Func; | |
| 104 (void)Str; | |
| 105 } | |
| 106 | |
| 107 private: | |
| 108 OperandMIPS32Mem(Cfg *Func, Type Ty, Variable *Base, | |
| 109 ConstantInteger32 *ImmOffset, AddrMode Mode); | |
| 110 | |
| 111 Variable *Base; | |
| 112 ConstantInteger32 *ImmOffset; | |
| 113 // Variable *Index; | |
|
Jim Stichnoth
2015/10/18 11:48:39
remove
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
| 114 AddrMode Mode; | |
| 115 }; | |
| 116 | |
| 29 /// Base class for Mips instructions. | 117 /// Base class for Mips instructions. |
| 30 class InstMIPS32 : public InstTarget { | 118 class InstMIPS32 : public InstTarget { |
| 31 InstMIPS32() = delete; | 119 InstMIPS32() = delete; |
| 32 InstMIPS32(const InstMIPS32 &) = delete; | 120 InstMIPS32(const InstMIPS32 &) = delete; |
| 33 InstMIPS32 &operator=(const InstMIPS32 &) = delete; | 121 InstMIPS32 &operator=(const InstMIPS32 &) = delete; |
| 34 | 122 |
| 35 public: | 123 public: |
| 36 enum InstKindMIPS32 { k__Start = Inst::Target, Ret }; | 124 enum InstKindMIPS32 { |
| 125 k__Start = Inst::Target, | |
| 126 Addiu, | |
| 127 La, | |
| 128 Lui, | |
| 129 Mov, // actually a pseudo op for addi rd, rs, 0 | |
| 130 Ori, | |
| 131 Ret | |
| 132 }; | |
| 37 | 133 |
| 38 static const char *getWidthString(Type Ty); | 134 static const char *getWidthString(Type Ty); |
| 39 | 135 |
| 40 void dump(const Cfg *Func) const override; | 136 void dump(const Cfg *Func) const override; |
| 41 | 137 |
| 138 void dumpOpcode(Ostream &Str, const char *Opcode, Type Ty) const { | |
| 139 Str << Opcode << "." << Ty; | |
| 140 } | |
| 141 | |
| 142 /// Shared emit routines for common forms of instructions. | |
| 143 static void emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst, | |
| 144 const Cfg *Func); | |
| 145 | |
| 42 protected: | 146 protected: |
| 43 InstMIPS32(Cfg *Func, InstKindMIPS32 Kind, SizeT Maxsrcs, Variable *Dest) | 147 InstMIPS32(Cfg *Func, InstKindMIPS32 Kind, SizeT Maxsrcs, Variable *Dest) |
| 44 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} | 148 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} |
| 45 static bool isClassof(const Inst *Inst, InstKindMIPS32 MyKind) { | 149 static bool isClassof(const Inst *Inst, InstKindMIPS32 MyKind) { |
| 46 return Inst->getKind() == static_cast<InstKind>(MyKind); | 150 return Inst->getKind() == static_cast<InstKind>(MyKind); |
| 47 } | 151 } |
| 48 }; | 152 }; |
| 49 | 153 |
| 50 /// Ret pseudo-instruction. This is actually a "jr" instruction with an "ra" | 154 /// Ret pseudo-instruction. This is actually a "jr" instruction with an "ra" |
| 51 /// register operand, but epilogue lowering will search for a Ret instead of a | 155 /// register operand, but epilogue lowering will search for a Ret instead of a |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 68 } | 172 } |
| 69 void emit(const Cfg *Func) const override; | 173 void emit(const Cfg *Func) const override; |
| 70 void emitIAS(const Cfg *Func) const override; | 174 void emitIAS(const Cfg *Func) const override; |
| 71 void dump(const Cfg *Func) const override; | 175 void dump(const Cfg *Func) const override; |
| 72 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } | 176 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } |
| 73 | 177 |
| 74 private: | 178 private: |
| 75 InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source); | 179 InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source); |
| 76 }; | 180 }; |
| 77 | 181 |
| 182 /// Instructions of the form x := op(y). | |
| 183 template <InstMIPS32::InstKindMIPS32 K> | |
| 184 class InstMIPS32UnaryopGPR : public InstMIPS32 { | |
| 185 InstMIPS32UnaryopGPR() = delete; | |
| 186 InstMIPS32UnaryopGPR(const InstMIPS32UnaryopGPR &) = delete; | |
| 187 InstMIPS32UnaryopGPR &operator=(const InstMIPS32UnaryopGPR &) = delete; | |
| 188 | |
| 189 public: | |
| 190 static InstMIPS32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 191 return new (Func->allocate<InstMIPS32UnaryopGPR>()) | |
| 192 InstMIPS32UnaryopGPR(Func, Dest, Src); | |
| 193 } | |
| 194 void emit(const Cfg *Func) const override { | |
| 195 if (!BuildDefs::dump()) | |
| 196 return; | |
| 197 emitUnaryopGPR(Opcode, this, Func); | |
| 198 } | |
| 199 void emitIAS(const Cfg *Func) const override { | |
| 200 (void)Func; | |
| 201 llvm_unreachable("Not yet implemented"); | |
| 202 } | |
| 203 void dump(const Cfg *Func) const override { | |
| 204 if (!BuildDefs::dump()) | |
| 205 return; | |
| 206 Ostream &Str = Func->getContext()->getStrDump(); | |
| 207 dumpOpcode(Str, Opcode, getDest()->getType()); | |
| 208 Str << " "; | |
| 209 dumpDest(Func); | |
| 210 Str << ", "; | |
| 211 dumpSources(Func); | |
| 212 } | |
| 213 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | |
| 214 | |
| 215 protected: | |
| 216 InstMIPS32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) | |
| 217 : InstMIPS32(Func, K, 2, Dest) { | |
| 218 addSource(Src); | |
| 219 } | |
| 220 | |
| 221 private: | |
| 222 static const char *Opcode; | |
| 223 }; | |
| 224 | |
| 225 template <InstMIPS32::InstKindMIPS32 K, bool Signed = false> | |
| 226 class InstMIPS32Imm16 : public InstMIPS32 { | |
| 227 InstMIPS32Imm16() = delete; | |
| 228 InstMIPS32Imm16(const InstMIPS32Imm16 &) = delete; | |
| 229 InstMIPS32Imm16 &operator=(const InstMIPS32Imm16 &) = delete; | |
| 230 | |
| 231 public: | |
| 232 static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, Operand *Source, | |
| 233 uint32_t Imm) { | |
| 234 return new (Func->allocate<InstMIPS32Imm16>()) | |
| 235 InstMIPS32Imm16(Func, Dest, Source, Imm); | |
| 236 } | |
| 237 | |
| 238 static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, uint32_t Imm) { | |
| 239 return new (Func->allocate<InstMIPS32Imm16>()) | |
| 240 InstMIPS32Imm16(Func, Dest, Imm); | |
| 241 } | |
| 242 | |
| 243 void emit(const Cfg *Func) const override { | |
| 244 (void)Func; | |
|
Jim Stichnoth
2015/10/18 11:48:39
remove this, as Func is used below.
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
| 245 if (!BuildDefs::dump()) | |
| 246 return; | |
| 247 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 248 Str << "\t" << Opcode << "\t"; | |
| 249 getDest()->emit(Func); | |
| 250 if (getSrcSize() > 0) { | |
| 251 Str << ", "; | |
| 252 getSrc(0)->emit(Func); | |
| 253 } | |
| 254 Str << ", "; | |
| 255 if (Signed) | |
| 256 Str << (int32_t)Imm; | |
| 257 else | |
| 258 Str << Imm; | |
| 259 Str << "\n"; | |
| 260 } | |
| 261 | |
| 262 void emitIAS(const Cfg *Func) const override { | |
| 263 (void)Func; | |
| 264 llvm_unreachable("Not yet implemented"); | |
| 265 } | |
| 266 void dump(const Cfg *Func) const override { | |
| 267 if (!BuildDefs::dump()) | |
| 268 return; | |
| 269 Ostream &Str = Func->getContext()->getStrDump(); | |
| 270 Str << " "; | |
| 271 Str << "\t" << Opcode << "\t"; | |
| 272 dumpDest(Func); | |
| 273 Str << ", "; | |
| 274 dumpSources(Func); | |
| 275 if (Signed) | |
| 276 Str << (int32_t)Imm; | |
| 277 else | |
| 278 Str << Imm; | |
| 279 Str << "\n"; | |
| 280 } | |
| 281 | |
| 282 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | |
| 283 | |
| 284 private: | |
| 285 InstMIPS32Imm16(Cfg *Func, Variable *Dest, Operand *Source, uint32_t Imm) | |
| 286 : InstMIPS32(Func, K, 2, Dest) { | |
| 287 this->Dead = Dest; | |
|
Jim Stichnoth
2015/10/18 11:48:39
I think maybe you meant to set this->Dest, not thi
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
| 288 addSource(Source); | |
| 289 this->Imm = Imm; | |
|
Jim Stichnoth
2015/10/18 11:48:38
Initialize this->Imm in the initializer list.
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
| 290 } | |
| 291 | |
| 292 InstMIPS32Imm16(Cfg *Func, Variable *Dest, uint32_t Imm) | |
| 293 : InstMIPS32(Func, K, 1, Dest) { | |
| 294 this->Dest = Dest; | |
|
Jim Stichnoth
2015/10/18 11:48:38
Dest is already initialized in the Inst base class
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
| 295 this->Imm = Imm; | |
|
Jim Stichnoth
2015/10/18 11:48:38
Initialize in the initializer list.
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
| 296 } | |
| 297 | |
| 298 static const char *Opcode; | |
| 299 | |
| 300 uint32_t Imm; | |
|
Jim Stichnoth
2015/10/18 11:48:38
If you initialize Imm everywhere via an initialize
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
| 301 }; | |
| 302 | |
| 303 typedef InstMIPS32Imm16<InstMIPS32::Addiu, true> InstMIPS32Addiu; | |
| 304 typedef InstMIPS32Imm16<InstMIPS32::Lui> InstMIPS32Lui; | |
| 305 typedef InstMIPS32UnaryopGPR<InstMIPS32::Mov> InstMIPS32MovBase; | |
| 306 typedef InstMIPS32UnaryopGPR<InstMIPS32::La> InstMIPS32La; | |
| 307 typedef InstMIPS32Imm16<InstMIPS32::Ori> InstMIPS32Ori; | |
| 308 | |
| 309 /// Handles (some of) vmov's various formats. | |
| 310 class InstMIPS32Mov final : public InstMIPS32 { | |
| 311 InstMIPS32Mov() = delete; | |
| 312 InstMIPS32Mov(const InstMIPS32Mov &) = delete; | |
| 313 InstMIPS32Mov &operator=(const InstMIPS32Mov &) = delete; | |
| 314 | |
| 315 public: | |
| 316 static InstMIPS32Mov *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 317 return new (Func->allocate<InstMIPS32Mov>()) InstMIPS32Mov(Func, Dest, Src); | |
| 318 } | |
| 319 bool isRedundantAssign() const override { | |
| 320 return !isMultiDest() && !isMultiSource() && | |
| 321 checkForRedundantAssign(getDest(), getSrc(0)); | |
| 322 } | |
| 323 bool isSimpleAssign() const override { return true; } | |
| 324 void emit(const Cfg *Func) const override; | |
| 325 void emitIAS(const Cfg *Func) const override; | |
| 326 void dump(const Cfg *Func) const override; | |
| 327 static bool classof(const Inst *Inst) { return isClassof(Inst, Mov); } | |
| 328 | |
| 329 bool isMultiDest() const { return DestHi != nullptr; } | |
| 330 | |
| 331 bool isMultiSource() const { | |
| 332 assert(getSrcSize() == 1 || getSrcSize() == 2); | |
| 333 return getSrcSize() == 2; | |
| 334 } | |
| 335 | |
| 336 Variable *getDestHi() const { return DestHi; } | |
| 337 | |
| 338 private: | |
| 339 InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src); | |
| 340 | |
| 341 void emitMultiDestSingleSource(const Cfg *Func) const; | |
| 342 void emitSingleDestMultiSource(const Cfg *Func) const; | |
| 343 void emitSingleDestSingleSource(const Cfg *Func) const; | |
| 344 | |
| 345 Variable *DestHi = nullptr; | |
| 346 }; | |
| 347 | |
| 78 } // end of namespace Ice | 348 } // end of namespace Ice |
| 79 | 349 |
| 80 #endif // SUBZERO_SRC_ICEINSTMIPS32_H | 350 #endif // SUBZERO_SRC_ICEINSTMIPS32_H |
| OLD | NEW |