Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceInstX86Base.h - Generic x86 instructions -*- C++ -*--===// | 1 //===- subzero/src/IceInstX86Base.h - Generic x86 instructions -*- 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 /// \brief This file defines the InstX86Base template class, as well as the | 11 /// \brief This file defines the InstX86Base template class, as well as the |
| 12 /// generic X86 Instruction class hierarchy. | 12 /// generic X86 Instruction class hierarchy. |
| 13 /// | 13 /// |
| 14 /// Only X86 instructions common across all/most X86 targets should be defined | 14 /// Only X86 instructions common across all/most X86 targets should be defined |
| 15 /// here, with target-specific instructions declared in the target's traits. | 15 /// here, with target-specific instructions declared in the target's traits. |
| 16 /// | 16 /// |
| 17 //===----------------------------------------------------------------------===// | 17 //===----------------------------------------------------------------------===// |
| 18 | 18 |
| 19 #ifndef SUBZERO_SRC_ICEINSTX86BASE_H | 19 #ifndef SUBZERO_SRC_ICEINSTX86BASE_H |
| 20 #define SUBZERO_SRC_ICEINSTX86BASE_H | 20 #define SUBZERO_SRC_ICEINSTX86BASE_H |
| 21 | 21 |
| 22 #include "IceDefs.h" | 22 #include "IceDefs.h" |
| 23 #include "IceInst.h" | 23 #include "IceInst.h" |
| 24 #include "IceOperand.h" | 24 #include "IceOperand.h" |
| 25 | 25 |
| 26 namespace Ice { | 26 namespace Ice { |
| 27 | 27 |
| 28 namespace X86Internal { | 28 #ifndef X86NAMESPACE |
| 29 | 29 #error "You must define the X86 Target namespace." |
| 30 template <class Machine> struct MachineTraits; | 30 #endif |
| 31 | 31 |
| 32 template <class Machine> class InstX86Base : public InstTarget { | 32 namespace X86NAMESPACE { |
| 33 InstX86Base<Machine>() = delete; | 33 |
|
John
2015/12/30 22:07:52
The diff seems worse than it is because of changes
| |
| 34 InstX86Base<Machine>(const InstX86Base &) = delete; | 34 template <typename TraitsType> struct InstImpl { |
| 35 InstX86Base &operator=(const InstX86Base &) = delete; | 35 using Traits = TraitsType; |
| 36 | 36 using Assembler = typename Traits::Assembler; |
| 37 public: | 37 using AssemblerLabel = typename Assembler::Label; |
| 38 using Traits = MachineTraits<Machine>; | 38 using AssemblerImmediate = typename Assembler::Immediate; |
| 39 using X86TargetLowering = typename Traits::TargetLowering; | 39 using TargetLowering = typename Traits::TargetLowering; |
| 40 | 40 using Address = typename Traits::Address; |
| 41 enum InstKindX86 { | 41 using X86Operand = typename Traits::X86Operand; |
| 42 k__Start = Inst::Target, | 42 using X86OperandMem = typename Traits::X86OperandMem; |
| 43 Adc, | 43 using VariableSplit = typename Traits::VariableSplit; |
| 44 AdcRMW, | 44 |
| 45 Add, | 45 using GPRRegister = typename Traits::RegisterSet::GPRRegister; |
| 46 AddRMW, | 46 using RegisterSet = typename Traits::RegisterSet; |
| 47 Addps, | 47 using XmmRegister = typename Traits::RegisterSet::XmmRegister; |
| 48 Addss, | 48 |
| 49 And, | 49 using Cond = typename Traits::Cond; |
| 50 Andnps, | 50 using BrCond = typename Traits::Cond::BrCond; |
| 51 Andps, | 51 using CmppsCond = typename Traits::Cond::CmppsCond; |
| 52 AndRMW, | 52 |
| 53 Blendvps, | 53 template <typename SReg_t, typename DReg_t> |
| 54 Br, | 54 using CastEmitterRegOp = |
| 55 Bsf, | 55 typename Traits::Assembler::template CastEmitterRegOp<SReg_t, DReg_t>; |
| 56 Bsr, | 56 template <typename SReg_t, typename DReg_t> |
| 57 Bswap, | 57 using ThreeOpImmEmitter = |
| 58 Call, | 58 typename Traits::Assembler::template ThreeOpImmEmitter<SReg_t, DReg_t>; |
| 59 Cbwdq, | 59 using GPREmitterAddrOp = typename Traits::Assembler::GPREmitterAddrOp; |
| 60 Cmov, | 60 using GPREmitterRegOp = typename Traits::Assembler::GPREmitterRegOp; |
| 61 Cmpps, | 61 using GPREmitterShiftD = typename Traits::Assembler::GPREmitterShiftD; |
| 62 Cmpxchg, | 62 using GPREmitterShiftOp = typename Traits::Assembler::GPREmitterShiftOp; |
| 63 Cmpxchg8b, | 63 using GPREmitterOneOp = typename Traits::Assembler::GPREmitterOneOp; |
| 64 Cvt, | 64 using XmmEmitterRegOp = typename Traits::Assembler::XmmEmitterRegOp; |
| 65 Div, | 65 using XmmEmitterShiftOp = typename Traits::Assembler::XmmEmitterShiftOp; |
| 66 Divps, | 66 using XmmEmitterMovOps = typename Traits::Assembler::XmmEmitterMovOps; |
| 67 Divss, | 67 |
| 68 FakeRMW, | 68 class InstX86Base : public InstTarget { |
| 69 Fld, | 69 InstX86Base() = delete; |
| 70 Fstp, | 70 InstX86Base(const InstX86Base &) = delete; |
| 71 Icmp, | 71 InstX86Base &operator=(const InstX86Base &) = delete; |
| 72 Idiv, | 72 |
| 73 Imul, | 73 public: |
| 74 ImulImm, | 74 enum InstKindX86 { |
| 75 Insertps, | 75 k__Start = Inst::Target, |
| 76 Jmp, | 76 Adc, |
| 77 Label, | 77 AdcRMW, |
| 78 Lea, | 78 Add, |
| 79 Load, | 79 AddRMW, |
| 80 Mfence, | 80 Addps, |
| 81 Minss, | 81 Addss, |
| 82 Maxss, | 82 And, |
| 83 Mov, | 83 Andnps, |
| 84 Movd, | 84 Andps, |
| 85 Movp, | 85 AndRMW, |
| 86 Movq, | 86 Blendvps, |
| 87 MovssRegs, | 87 Br, |
| 88 Movsx, | 88 Bsf, |
| 89 Movzx, | 89 Bsr, |
| 90 Mul, | 90 Bswap, |
| 91 Mulps, | 91 Call, |
| 92 Mulss, | 92 Cbwdq, |
| 93 Neg, | 93 Cmov, |
| 94 Nop, | 94 Cmpps, |
| 95 Or, | 95 Cmpxchg, |
| 96 Orps, | 96 Cmpxchg8b, |
| 97 OrRMW, | 97 Cvt, |
| 98 Padd, | 98 Div, |
| 99 Pand, | 99 Divps, |
| 100 Pandn, | 100 Divss, |
| 101 Pblendvb, | 101 FakeRMW, |
| 102 Pcmpeq, | 102 Fld, |
| 103 Pcmpgt, | 103 Fstp, |
| 104 Pextr, | 104 Icmp, |
| 105 Pinsr, | 105 Idiv, |
| 106 Pmull, | 106 Imul, |
| 107 Pmuludq, | 107 ImulImm, |
| 108 Pop, | 108 Insertps, |
| 109 Por, | 109 Jmp, |
| 110 Pshufd, | 110 Label, |
| 111 Psll, | 111 Lea, |
| 112 Psra, | 112 Load, |
| 113 Psrl, | 113 Mfence, |
| 114 Psub, | 114 Minss, |
| 115 Push, | 115 Maxss, |
| 116 Pxor, | 116 Mov, |
| 117 Ret, | 117 Movd, |
| 118 Rol, | 118 Movp, |
| 119 Sar, | 119 Movq, |
| 120 Sbb, | 120 MovssRegs, |
| 121 SbbRMW, | 121 Movsx, |
| 122 Setcc, | 122 Movzx, |
| 123 Shl, | 123 Mul, |
| 124 Shld, | 124 Mulps, |
| 125 Shr, | 125 Mulss, |
| 126 Shrd, | 126 Neg, |
| 127 Shufps, | 127 Nop, |
| 128 Sqrtss, | 128 Or, |
| 129 Store, | 129 Orps, |
| 130 StoreP, | 130 OrRMW, |
| 131 StoreQ, | 131 Padd, |
| 132 Sub, | 132 Pand, |
| 133 SubRMW, | 133 Pandn, |
| 134 Subps, | 134 Pblendvb, |
| 135 Subss, | 135 Pcmpeq, |
| 136 Test, | 136 Pcmpgt, |
| 137 Ucomiss, | 137 Pextr, |
| 138 UD2, | 138 Pinsr, |
| 139 Xadd, | 139 Pmull, |
| 140 Xchg, | 140 Pmuludq, |
| 141 Xor, | 141 Pop, |
| 142 Xorps, | 142 Por, |
| 143 XorRMW, | 143 Pshufd, |
| 144 | 144 Psll, |
| 145 /// Intel Architecture Code Analyzer markers. These are not executable so | 145 Psra, |
| 146 /// must only be used for analysis. | 146 Psrl, |
| 147 IacaStart, | 147 Psub, |
| 148 IacaEnd | 148 Push, |
| 149 }; | 149 Pxor, |
| 150 | 150 Ret, |
| 151 enum SseSuffix { None, Packed, Scalar, Integral }; | 151 Rol, |
| 152 | 152 Sar, |
| 153 static const char *getWidthString(Type Ty); | 153 Sbb, |
| 154 static const char *getFldString(Type Ty); | 154 SbbRMW, |
| 155 static typename Traits::Cond::BrCond | 155 Setcc, |
| 156 getOppositeCondition(typename Traits::Cond::BrCond Cond); | 156 Shl, |
| 157 void dump(const Cfg *Func) const override; | 157 Shld, |
| 158 | 158 Shr, |
| 159 // Shared emit routines for common forms of instructions. | 159 Shrd, |
| 160 void emitTwoAddress(const Cfg *Func, const char *Opcode, | 160 Shufps, |
| 161 const char *Suffix = "") const; | 161 Sqrtss, |
| 162 | 162 Store, |
| 163 StoreP, | |
| 164 StoreQ, | |
| 165 Sub, | |
| 166 SubRMW, | |
| 167 Subps, | |
| 168 Subss, | |
| 169 Test, | |
| 170 Ucomiss, | |
| 171 UD2, | |
| 172 Xadd, | |
| 173 Xchg, | |
| 174 Xor, | |
| 175 Xorps, | |
| 176 XorRMW, | |
| 177 | |
| 178 /// Intel Architecture Code Analyzer markers. These are not executable so | |
| 179 /// must only be used for analysis. | |
| 180 IacaStart, | |
| 181 IacaEnd | |
| 182 }; | |
| 183 | |
| 184 enum SseSuffix { None, Packed, Scalar, Integral }; | |
| 185 | |
| 186 static const char *getWidthString(Type Ty); | |
| 187 static const char *getFldString(Type Ty); | |
| 188 static BrCond getOppositeCondition(BrCond Cond); | |
| 189 void dump(const Cfg *Func) const override; | |
| 190 | |
| 191 // Shared emit routines for common forms of instructions. | |
| 192 void emitTwoAddress(const Cfg *Func, const char *Opcode, | |
| 193 const char *Suffix = "") const; | |
| 194 | |
| 195 static TargetLowering *getTarget(const Cfg *Func) { | |
| 196 return static_cast<TargetLowering *>(Func->getTarget()); | |
| 197 } | |
| 198 | |
| 199 protected: | |
| 200 InstX86Base(Cfg *Func, InstKindX86 Kind, SizeT Maxsrcs, Variable *Dest) | |
| 201 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} | |
| 202 | |
| 203 static bool isClassof(const Inst *Inst, InstKindX86 MyKind) { | |
| 204 return Inst->getKind() == static_cast<InstKind>(MyKind); | |
| 205 } | |
| 206 // Most instructions that operate on vector arguments require vector memory | |
| 207 // operands to be fully aligned (16-byte alignment for PNaCl vector types). | |
| 208 // The stack frame layout and call ABI ensure proper alignment for stack | |
| 209 // operands, but memory operands (originating from load/store bitcode | |
| 210 // instructions) only have element-size alignment guarantees. This function | |
| 211 // validates that none of the operands is a memory operand of vector type, | |
| 212 // calling report_fatal_error() if one is found. This function should be | |
| 213 // called during emission, and maybe also in the ctor (as long as that fits | |
| 214 // the lowering style). | |
| 215 void validateVectorAddrMode() const { | |
| 216 if (this->getDest()) | |
|
Jim Stichnoth
2016/01/03 18:20:02
It looks like the "this->" in this method can be r
| |
| 217 this->validateVectorAddrModeOpnd(this->getDest()); | |
| 218 for (SizeT i = 0; i < this->getSrcSize(); ++i) { | |
| 219 this->validateVectorAddrModeOpnd(this->getSrc(i)); | |
| 220 } | |
| 221 } | |
| 222 | |
| 223 private: | |
| 224 static void validateVectorAddrModeOpnd(const Operand *Opnd) { | |
| 225 if (llvm::isa<X86OperandMem>(Opnd) && isVectorType(Opnd->getType())) { | |
| 226 llvm::report_fatal_error("Possible misaligned vector memory operation"); | |
| 227 } | |
| 228 } | |
| 229 }; | |
| 230 | |
| 231 /// InstX86FakeRMW represents a non-atomic read-modify-write operation on a | |
| 232 /// memory location. An InstX86FakeRMW is a "fake" instruction in that it | |
| 233 /// still needs to be lowered to some actual RMW instruction. | |
| 234 /// | |
| 235 /// If A is some memory address, D is some data value to apply, and OP is an | |
| 236 /// arithmetic operator, the instruction operates as: (*A) = (*A) OP D | |
| 237 class InstX86FakeRMW final : public InstX86Base { | |
| 238 InstX86FakeRMW() = delete; | |
| 239 InstX86FakeRMW(const InstX86FakeRMW &) = delete; | |
| 240 InstX86FakeRMW &operator=(const InstX86FakeRMW &) = delete; | |
| 241 | |
| 242 public: | |
| 243 static InstX86FakeRMW *create(Cfg *Func, Operand *Data, Operand *Addr, | |
| 244 Variable *Beacon, InstArithmetic::OpKind Op, | |
| 245 uint32_t Align = 1) { | |
| 246 // TODO(stichnot): Stop ignoring alignment specification. | |
| 247 (void)Align; | |
| 248 return new (Func->allocate<InstX86FakeRMW>()) | |
| 249 InstX86FakeRMW(Func, Data, Addr, Op, Beacon); | |
| 250 } | |
| 251 Operand *getAddr() const { return this->getSrc(1); } | |
| 252 Operand *getData() const { return this->getSrc(0); } | |
| 253 InstArithmetic::OpKind getOp() const { return Op; } | |
| 254 Variable *getBeacon() const { | |
| 255 return llvm::cast<Variable>(this->getSrc(2)); | |
| 256 } | |
| 257 void dump(const Cfg *Func) const override; | |
| 258 static bool classof(const Inst *Inst) { | |
| 259 return InstX86Base::isClassof(Inst, InstX86Base::FakeRMW); | |
| 260 } | |
| 261 | |
| 262 private: | |
| 263 InstArithmetic::OpKind Op; | |
| 264 InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr, | |
| 265 InstArithmetic::OpKind Op, Variable *Beacon); | |
| 266 }; | |
| 267 | |
| 268 /// InstX86Label represents an intra-block label that is the target of an | |
| 269 /// intra-block branch. The offset between the label and the branch must be | |
| 270 /// fit into one byte (considered "near"). These are used for lowering i1 | |
| 271 /// calculations, Select instructions, and 64-bit compares on a 32-bit | |
| 272 /// architecture, without basic block splitting. Basic block splitting is not | |
| 273 /// so desirable for several reasons, one of which is the impact on decisions | |
| 274 /// based on whether a variable's live range spans multiple basic blocks. | |
| 275 /// | |
| 276 /// Intra-block control flow must be used with caution. Consider the sequence | |
| 277 /// for "c = (a >= b ? x : y)". | |
| 278 /// cmp a, b | |
| 279 /// br lt, L1 | |
| 280 /// mov c, x | |
| 281 /// jmp L2 | |
| 282 /// L1: | |
| 283 /// mov c, y | |
| 284 /// L2: | |
| 285 /// | |
| 286 /// Labels L1 and L2 are intra-block labels. Without knowledge of the | |
| 287 /// intra-block control flow, liveness analysis will determine the "mov c, x" | |
| 288 /// instruction to be dead. One way to prevent this is to insert a | |
| 289 /// "FakeUse(c)" instruction anywhere between the two "mov c, ..." | |
| 290 /// instructions, e.g.: | |
| 291 /// | |
| 292 /// cmp a, b | |
| 293 /// br lt, L1 | |
| 294 /// mov c, x | |
| 295 /// jmp L2 | |
| 296 /// FakeUse(c) | |
| 297 /// L1: | |
| 298 /// mov c, y | |
| 299 /// L2: | |
| 300 /// | |
| 301 /// The down-side is that "mov c, x" can never be dead-code eliminated even if | |
| 302 /// there are no uses of c. As unlikely as this situation is, it may be | |
| 303 /// prevented by running dead code elimination before lowering. | |
| 304 class InstX86Label final : public InstX86Base { | |
| 305 InstX86Label() = delete; | |
| 306 InstX86Label(const InstX86Label &) = delete; | |
| 307 InstX86Label &operator=(const InstX86Label &) = delete; | |
| 308 | |
| 309 public: | |
| 310 static InstX86Label *create(Cfg *Func, TargetLowering *Target) { | |
| 311 return new (Func->allocate<InstX86Label>()) InstX86Label(Func, Target); | |
| 312 } | |
| 313 uint32_t getEmitInstCount() const override { return 0; } | |
| 314 IceString getName(const Cfg *Func) const; | |
| 315 SizeT getNumber() const { return Number; } | |
| 316 void emit(const Cfg *Func) const override; | |
| 317 void emitIAS(const Cfg *Func) const override; | |
| 318 void dump(const Cfg *Func) const override; | |
| 319 | |
| 320 private: | |
| 321 InstX86Label(Cfg *Func, TargetLowering *Target); | |
| 322 | |
| 323 SizeT Number; // used for unique label generation. | |
| 324 }; | |
| 325 | |
| 326 /// Conditional and unconditional branch instruction. | |
| 327 class InstX86Br final : public InstX86Base { | |
| 328 InstX86Br() = delete; | |
| 329 InstX86Br(const InstX86Br &) = delete; | |
| 330 InstX86Br &operator=(const InstX86Br &) = delete; | |
| 331 | |
| 332 public: | |
| 333 enum Mode { Near, Far }; | |
| 334 | |
| 335 /// Create a conditional branch to a node. | |
| 336 static InstX86Br *create(Cfg *Func, CfgNode *TargetTrue, | |
| 337 CfgNode *TargetFalse, BrCond Condition, | |
| 338 Mode Kind) { | |
| 339 assert(Condition != Cond::Br_None); | |
| 340 constexpr InstX86Label *NoLabel = nullptr; | |
| 341 return new (Func->allocate<InstX86Br>()) | |
| 342 InstX86Br(Func, TargetTrue, TargetFalse, NoLabel, Condition, Kind); | |
| 343 } | |
| 344 /// Create an unconditional branch to a node. | |
| 345 static InstX86Br *create(Cfg *Func, CfgNode *Target, Mode Kind) { | |
| 346 constexpr CfgNode *NoCondTarget = nullptr; | |
| 347 constexpr InstX86Label *NoLabel = nullptr; | |
| 348 return new (Func->allocate<InstX86Br>()) | |
| 349 InstX86Br(Func, NoCondTarget, Target, NoLabel, Cond::Br_None, Kind); | |
| 350 } | |
| 351 /// Create a non-terminator conditional branch to a node, with a fallthrough | |
| 352 /// to the next instruction in the current node. This is used for switch | |
| 353 /// lowering. | |
| 354 static InstX86Br *create(Cfg *Func, CfgNode *Target, BrCond Condition, | |
| 355 Mode Kind) { | |
| 356 assert(Condition != Cond::Br_None); | |
| 357 constexpr CfgNode *NoUncondTarget = nullptr; | |
| 358 constexpr InstX86Label *NoLabel = nullptr; | |
| 359 return new (Func->allocate<InstX86Br>()) | |
| 360 InstX86Br(Func, Target, NoUncondTarget, NoLabel, Condition, Kind); | |
| 361 } | |
| 362 /// Create a conditional intra-block branch (or unconditional, if | |
| 363 /// Condition==Br_None) to a label in the current block. | |
| 364 static InstX86Br *create(Cfg *Func, InstX86Label *Label, BrCond Condition, | |
| 365 Mode Kind) { | |
| 366 constexpr CfgNode *NoCondTarget = nullptr; | |
| 367 constexpr CfgNode *NoUncondTarget = nullptr; | |
| 368 return new (Func->allocate<InstX86Br>()) | |
| 369 InstX86Br(Func, NoCondTarget, NoUncondTarget, Label, Condition, Kind); | |
| 370 } | |
| 371 const CfgNode *getTargetTrue() const { return TargetTrue; } | |
| 372 const CfgNode *getTargetFalse() const { return TargetFalse; } | |
| 373 bool isNear() const { return Kind == Near; } | |
| 374 bool optimizeBranch(const CfgNode *NextNode); | |
| 375 uint32_t getEmitInstCount() const override { | |
| 376 uint32_t Sum = 0; | |
| 377 if (Label) | |
| 378 ++Sum; | |
| 379 if (getTargetTrue()) | |
| 380 ++Sum; | |
| 381 if (getTargetFalse()) | |
| 382 ++Sum; | |
| 383 return Sum; | |
| 384 } | |
| 385 bool isUnconditionalBranch() const override { | |
| 386 return !Label && Condition == Cond::Br_None; | |
| 387 } | |
| 388 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; | |
| 389 void emit(const Cfg *Func) const override; | |
| 390 void emitIAS(const Cfg *Func) const override; | |
| 391 void dump(const Cfg *Func) const override; | |
| 392 static bool classof(const Inst *Inst) { | |
| 393 return InstX86Base::isClassof(Inst, InstX86Base::Br); | |
| 394 } | |
| 395 | |
| 396 private: | |
| 397 InstX86Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, | |
| 398 const InstX86Label *Label, BrCond Condition, Mode Kind); | |
| 399 | |
| 400 BrCond Condition; | |
| 401 const CfgNode *TargetTrue; | |
| 402 const CfgNode *TargetFalse; | |
| 403 const InstX86Label *Label; // Intra-block branch target | |
| 404 const Mode Kind; | |
| 405 }; | |
| 406 | |
| 407 /// Jump to a target outside this function, such as tailcall, nacljump, | |
| 408 /// naclret, unreachable. This is different from a Branch instruction in that | |
| 409 /// there is no intra-function control flow to represent. | |
| 410 class InstX86Jmp final : public InstX86Base { | |
| 411 InstX86Jmp() = delete; | |
| 412 InstX86Jmp(const InstX86Jmp &) = delete; | |
| 413 InstX86Jmp &operator=(const InstX86Jmp &) = delete; | |
| 414 | |
| 415 public: | |
| 416 static InstX86Jmp *create(Cfg *Func, Operand *Target) { | |
| 417 return new (Func->allocate<InstX86Jmp>()) InstX86Jmp(Func, Target); | |
| 418 } | |
| 419 Operand *getJmpTarget() const { return this->getSrc(0); } | |
| 420 void emit(const Cfg *Func) const override; | |
| 421 void emitIAS(const Cfg *Func) const override; | |
| 422 void dump(const Cfg *Func) const override; | |
| 423 static bool classof(const Inst *Inst) { | |
| 424 return InstX86Base::isClassof(Inst, InstX86Base::Jmp); | |
| 425 } | |
| 426 | |
| 427 private: | |
| 428 InstX86Jmp(Cfg *Func, Operand *Target); | |
| 429 }; | |
| 430 | |
| 431 /// Call instruction. Arguments should have already been pushed. | |
| 432 class InstX86Call final : public InstX86Base { | |
| 433 InstX86Call() = delete; | |
| 434 InstX86Call(const InstX86Call &) = delete; | |
| 435 InstX86Call &operator=(const InstX86Call &) = delete; | |
| 436 | |
| 437 public: | |
| 438 static InstX86Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { | |
| 439 return new (Func->allocate<InstX86Call>()) | |
| 440 InstX86Call(Func, Dest, CallTarget); | |
| 441 } | |
| 442 Operand *getCallTarget() const { return this->getSrc(0); } | |
| 443 void emit(const Cfg *Func) const override; | |
| 444 void emitIAS(const Cfg *Func) const override; | |
| 445 void dump(const Cfg *Func) const override; | |
| 446 static bool classof(const Inst *Inst) { | |
| 447 return InstX86Base::isClassof(Inst, InstX86Base::Call); | |
| 448 } | |
| 449 | |
| 450 private: | |
| 451 InstX86Call(Cfg *Func, Variable *Dest, Operand *CallTarget); | |
| 452 }; | |
| 453 | |
| 454 /// Emit a one-operand (GPR) instruction. | |
| 455 static void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Var, | |
| 456 const GPREmitterOneOp &Emitter); | |
| 457 | |
| 458 static void emitIASAsAddrOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op0, | |
| 459 const Operand *Op1, | |
| 460 const GPREmitterAddrOp &Emitter); | |
| 461 | |
| 462 static void emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, | |
| 463 const Operand *Src, | |
| 464 const GPREmitterShiftOp &Emitter); | |
| 465 | |
| 466 static void emitIASAddrOpTyGPR(const Cfg *Func, Type Ty, const Address &Addr, | |
| 467 const Operand *Src, | |
| 468 const GPREmitterAddrOp &Emitter); | |
| 469 | |
| 470 static void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var, | |
| 471 const Operand *Src, | |
| 472 const XmmEmitterRegOp &Emitter); | |
| 473 | |
| 474 static void emitIASGPRShiftDouble(const Cfg *Func, const Variable *Dest, | |
| 475 const Operand *Src1Op, | |
| 476 const Operand *Src2Op, | |
| 477 const GPREmitterShiftD &Emitter); | |
| 478 | |
| 479 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t), | |
| 480 SReg_t (*srcEnc)(int32_t)> | |
| 481 static void emitIASCastRegOp(const Cfg *Func, Type DestTy, | |
| 482 const Variable *Dest, Type SrcTy, | |
| 483 const Operand *Src, | |
| 484 const CastEmitterRegOp<DReg_t, SReg_t> &Emitter); | |
| 485 | |
| 486 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t), | |
| 487 SReg_t (*srcEnc)(int32_t)> | |
| 163 static void | 488 static void |
| 164 emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, | 489 emitIASThreeOpImmOps(const Cfg *Func, Type DispatchTy, const Variable *Dest, |
| 165 const Operand *Src, | 490 const Operand *Src0, const Operand *Src1, |
| 166 const typename Traits::Assembler::GPREmitterShiftOp &Emitter); | 491 const ThreeOpImmEmitter<DReg_t, SReg_t> Emitter); |
| 167 | 492 |
| 168 static X86TargetLowering *getTarget(const Cfg *Func) { | 493 static void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest, |
| 169 return static_cast<X86TargetLowering *>(Func->getTarget()); | 494 const Operand *Src, |
| 170 } | 495 const XmmEmitterMovOps Emitter); |
| 171 | 496 |
| 172 protected: | 497 static void emitVariableBlendInst(const char *Opcode, const Inst *Inst, |
| 173 InstX86Base<Machine>(Cfg *Func, InstKindX86 Kind, SizeT Maxsrcs, | 498 const Cfg *Func); |
| 174 Variable *Dest) | 499 |
| 175 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} | 500 static void emitIASVariableBlendInst(const Inst *Inst, const Cfg *Func, |
| 176 | 501 const XmmEmitterRegOp &Emitter); |
| 177 static bool isClassof(const Inst *Inst, InstKindX86 MyKind) { | 502 |
| 178 return Inst->getKind() == static_cast<InstKind>(MyKind); | 503 static void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var, |
| 179 } | 504 const Operand *Src, |
| 180 // Most instructions that operate on vector arguments require vector memory | 505 const XmmEmitterShiftOp &Emitter); |
| 181 // operands to be fully aligned (16-byte alignment for PNaCl vector types). | 506 |
| 182 // The stack frame layout and call ABI ensure proper alignment for stack | 507 /// Emit a two-operand (GPR) instruction, where the dest operand is a Variable |
| 183 // operands, but memory operands (originating from load/store bitcode | 508 /// that's guaranteed to be a register. |
| 184 // instructions) only have element-size alignment guarantees. This function | 509 template <bool VarCanBeByte = true, bool SrcCanBeByte = true> |
| 185 // validates that none of the operands is a memory operand of vector type, | 510 static void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Dst, |
| 186 // calling report_fatal_error() if one is found. This function should be | 511 const Operand *Src, |
| 187 // called during emission, and maybe also in the ctor (as long as that fits | 512 const GPREmitterRegOp &Emitter); |
| 188 // the lowering style). | 513 |
| 189 void validateVectorAddrMode() const { | 514 /// Instructions of the form x := op(x). |
| 190 if (this->getDest()) | 515 template <typename InstX86Base::InstKindX86 K> |
| 191 this->validateVectorAddrModeOpnd(this->getDest()); | 516 class InstX86BaseInplaceopGPR : public InstX86Base { |
| 192 for (SizeT i = 0; i < this->getSrcSize(); ++i) { | 517 InstX86BaseInplaceopGPR() = delete; |
| 193 this->validateVectorAddrModeOpnd(this->getSrc(i)); | 518 InstX86BaseInplaceopGPR(const InstX86BaseInplaceopGPR &) = delete; |
| 194 } | 519 InstX86BaseInplaceopGPR & |
| 195 } | 520 operator=(const InstX86BaseInplaceopGPR &) = delete; |
| 196 | 521 |
| 197 private: | 522 public: |
| 198 static void validateVectorAddrModeOpnd(const Operand *Opnd) { | 523 using Base = InstX86BaseInplaceopGPR<K>; |
| 199 if (llvm::isa<typename InstX86Base<Machine>::Traits::X86OperandMem>(Opnd) && | 524 |
| 200 isVectorType(Opnd->getType())) { | 525 void emit(const Cfg *Func) const override { |
| 201 llvm::report_fatal_error("Possible misaligned vector memory operation"); | 526 if (!BuildDefs::dump()) |
| 202 } | 527 return; |
| 203 } | 528 Ostream &Str = Func->getContext()->getStrEmit(); |
| 204 }; | 529 assert(this->getSrcSize() == 1); |
| 205 | 530 Str << "\t" << Opcode << "\t"; |
| 206 /// InstX86FakeRMW represents a non-atomic read-modify-write operation on a | 531 this->getSrc(0)->emit(Func); |
| 207 /// memory location. An InstX86FakeRMW is a "fake" instruction in that it still | 532 } |
| 208 /// needs to be lowered to some actual RMW instruction. | 533 void emitIAS(const Cfg *Func) const override { |
| 209 /// | 534 assert(this->getSrcSize() == 1); |
| 210 /// If A is some memory address, D is some data value to apply, and OP is an | 535 const Variable *Var = this->getDest(); |
| 211 /// arithmetic operator, the instruction operates as: (*A) = (*A) OP D | 536 Type Ty = Var->getType(); |
| 212 template <class Machine> | 537 emitIASOpTyGPR(Func, Ty, Var, Emitter); |
| 213 class InstX86FakeRMW final : public InstX86Base<Machine> { | 538 } |
| 214 InstX86FakeRMW() = delete; | 539 void dump(const Cfg *Func) const override { |
| 215 InstX86FakeRMW(const InstX86FakeRMW &) = delete; | 540 if (!BuildDefs::dump()) |
| 216 InstX86FakeRMW &operator=(const InstX86FakeRMW &) = delete; | 541 return; |
| 217 | 542 Ostream &Str = Func->getContext()->getStrDump(); |
| 218 public: | 543 this->dumpDest(Func); |
| 219 static InstX86FakeRMW *create(Cfg *Func, Operand *Data, Operand *Addr, | 544 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; |
| 220 Variable *Beacon, InstArithmetic::OpKind Op, | 545 this->dumpSources(Func); |
| 221 uint32_t Align = 1) { | 546 } |
| 222 // TODO(stichnot): Stop ignoring alignment specification. | 547 static bool classof(const Inst *Inst) { |
| 223 (void)Align; | 548 return InstX86Base::isClassof(Inst, InstX86Base::K); |
| 224 return new (Func->allocate<InstX86FakeRMW>()) | 549 } |
| 225 InstX86FakeRMW(Func, Data, Addr, Op, Beacon); | 550 |
| 226 } | 551 protected: |
| 227 Operand *getAddr() const { return this->getSrc(1); } | 552 InstX86BaseInplaceopGPR(Cfg *Func, Operand *SrcDest) |
| 228 Operand *getData() const { return this->getSrc(0); } | 553 : InstX86Base(Func, K, 1, llvm::dyn_cast<Variable>(SrcDest)) { |
| 229 InstArithmetic::OpKind getOp() const { return Op; } | 554 this->addSource(SrcDest); |
| 230 Variable *getBeacon() const { return llvm::cast<Variable>(this->getSrc(2)); } | 555 } |
| 231 void dump(const Cfg *Func) const override; | 556 |
| 232 static bool classof(const Inst *Inst) { | 557 private: |
| 233 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::FakeRMW); | 558 static const char *Opcode; |
| 234 } | 559 static const GPREmitterOneOp Emitter; |
| 235 | 560 }; |
| 236 private: | 561 |
| 237 InstArithmetic::OpKind Op; | 562 /// Instructions of the form x := op(y). |
| 238 InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr, | 563 template <typename InstX86Base::InstKindX86 K> |
| 239 InstArithmetic::OpKind Op, Variable *Beacon); | 564 class InstX86BaseUnaryopGPR : public InstX86Base { |
| 240 }; | 565 InstX86BaseUnaryopGPR() = delete; |
| 241 | 566 InstX86BaseUnaryopGPR(const InstX86BaseUnaryopGPR &) = delete; |
| 242 /// InstX86Label represents an intra-block label that is the target of an | 567 InstX86BaseUnaryopGPR &operator=(const InstX86BaseUnaryopGPR &) = delete; |
| 243 /// intra-block branch. The offset between the label and the branch must be fit | 568 |
| 244 /// into one byte (considered "near"). These are used for lowering i1 | 569 public: |
| 245 /// calculations, Select instructions, and 64-bit compares on a 32-bit | 570 using Base = InstX86BaseUnaryopGPR<K>; |
| 246 /// architecture, without basic block splitting. Basic block splitting is not so | 571 |
| 247 /// desirable for several reasons, one of which is the impact on decisions based | 572 void emit(const Cfg *Func) const override { |
| 248 /// on whether a variable's live range spans multiple basic blocks. | 573 if (!BuildDefs::dump()) |
| 249 /// | 574 return; |
| 250 /// Intra-block control flow must be used with caution. Consider the sequence | 575 Ostream &Str = Func->getContext()->getStrEmit(); |
| 251 /// for "c = (a >= b ? x : y)". | 576 assert(this->getSrcSize() == 1); |
| 252 /// cmp a, b | 577 Type SrcTy = this->getSrc(0)->getType(); |
| 253 /// br lt, L1 | 578 Type DestTy = this->getDest()->getType(); |
| 254 /// mov c, x | 579 Str << "\t" << Opcode << this->getWidthString(SrcTy); |
| 255 /// jmp L2 | 580 // Movsx and movzx need both the source and dest type width letter to |
| 256 /// L1: | 581 // define the operation. The other unary operations have the same source |
| 257 /// mov c, y | 582 // and dest type and as a result need only one letter. |
| 258 /// L2: | 583 if (SrcTy != DestTy) |
| 259 /// | 584 Str << this->getWidthString(DestTy); |
| 260 /// Labels L1 and L2 are intra-block labels. Without knowledge of the | 585 Str << "\t"; |
| 261 /// intra-block control flow, liveness analysis will determine the "mov c, x" | 586 this->getSrc(0)->emit(Func); |
| 262 /// instruction to be dead. One way to prevent this is to insert a "FakeUse(c)" | 587 Str << ", "; |
| 263 /// instruction anywhere between the two "mov c, ..." instructions, e.g.: | 588 this->getDest()->emit(Func); |
| 264 /// | 589 } |
| 265 /// cmp a, b | 590 void emitIAS(const Cfg *Func) const override { |
| 266 /// br lt, L1 | 591 assert(this->getSrcSize() == 1); |
| 267 /// mov c, x | 592 const Variable *Var = this->getDest(); |
| 268 /// jmp L2 | 593 Type Ty = Var->getType(); |
| 269 /// FakeUse(c) | 594 const Operand *Src = this->getSrc(0); |
| 270 /// L1: | 595 emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter); |
| 271 /// mov c, y | 596 } |
| 272 /// L2: | 597 void dump(const Cfg *Func) const override { |
| 273 /// | 598 if (!BuildDefs::dump()) |
| 274 /// The down-side is that "mov c, x" can never be dead-code eliminated even if | 599 return; |
| 275 /// there are no uses of c. As unlikely as this situation is, it may be | 600 Ostream &Str = Func->getContext()->getStrDump(); |
| 276 /// prevented by running dead code elimination before lowering. | 601 this->dumpDest(Func); |
| 277 template <class Machine> | 602 Str << " = " << Opcode << "." << this->getSrc(0)->getType() << " "; |
| 278 class InstX86Label final : public InstX86Base<Machine> { | 603 this->dumpSources(Func); |
| 279 InstX86Label() = delete; | 604 } |
| 280 InstX86Label(const InstX86Label &) = delete; | 605 static bool classof(const Inst *Inst) { |
| 281 InstX86Label &operator=(const InstX86Label &) = delete; | 606 return InstX86Base::isClassof(Inst, InstX86Base::K); |
| 282 | 607 } |
| 283 public: | 608 |
| 284 static InstX86Label * | 609 protected: |
| 285 create(Cfg *Func, | 610 InstX86BaseUnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) |
| 286 typename InstX86Base<Machine>::Traits::TargetLowering *Target) { | 611 : InstX86Base(Func, K, 1, Dest) { |
| 287 return new (Func->allocate<InstX86Label>()) InstX86Label(Func, Target); | 612 this->addSource(Src); |
| 288 } | 613 } |
| 289 uint32_t getEmitInstCount() const override { return 0; } | 614 |
| 290 IceString getName(const Cfg *Func) const; | 615 static const char *Opcode; |
| 291 SizeT getNumber() const { return Number; } | 616 static const GPREmitterRegOp Emitter; |
| 292 void emit(const Cfg *Func) const override; | 617 }; |
| 293 void emitIAS(const Cfg *Func) const override; | 618 |
| 294 void dump(const Cfg *Func) const override; | 619 template <typename InstX86Base::InstKindX86 K> |
| 295 | 620 class InstX86BaseUnaryopXmm : public InstX86Base { |
| 296 private: | 621 InstX86BaseUnaryopXmm() = delete; |
| 297 InstX86Label(Cfg *Func, | 622 InstX86BaseUnaryopXmm(const InstX86BaseUnaryopXmm &) = delete; |
| 298 typename InstX86Base<Machine>::Traits::TargetLowering *Target); | 623 InstX86BaseUnaryopXmm &operator=(const InstX86BaseUnaryopXmm &) = delete; |
| 299 | 624 |
| 300 SizeT Number; // used for unique label generation. | 625 public: |
| 301 }; | 626 using Base = InstX86BaseUnaryopXmm<K>; |
| 302 | 627 |
| 303 /// Conditional and unconditional branch instruction. | 628 void emit(const Cfg *Func) const override { |
| 304 template <class Machine> class InstX86Br final : public InstX86Base<Machine> { | 629 if (!BuildDefs::dump()) |
| 305 InstX86Br() = delete; | 630 return; |
| 306 InstX86Br(const InstX86Br &) = delete; | 631 Ostream &Str = Func->getContext()->getStrEmit(); |
| 307 InstX86Br &operator=(const InstX86Br &) = delete; | 632 assert(this->getSrcSize() == 1); |
| 308 | 633 Str << "\t" << Opcode << "\t"; |
| 309 public: | 634 this->getSrc(0)->emit(Func); |
| 310 enum Mode { Near, Far }; | 635 Str << ", "; |
| 311 | 636 this->getDest()->emit(Func); |
| 312 /// Create a conditional branch to a node. | 637 } |
| 313 static InstX86Br * | 638 void emitIAS(const Cfg *Func) const override { |
| 314 create(Cfg *Func, CfgNode *TargetTrue, CfgNode *TargetFalse, | 639 Type Ty = this->getDest()->getType(); |
| 315 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, | 640 assert(this->getSrcSize() == 1); |
| 316 Mode Kind) { | 641 emitIASRegOpTyXMM(Func, Ty, this->getDest(), this->getSrc(0), Emitter); |
| 317 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None); | 642 } |
| 318 constexpr InstX86Label<Machine> *NoLabel = nullptr; | 643 void dump(const Cfg *Func) const override { |
| 319 return new (Func->allocate<InstX86Br>()) | 644 if (!BuildDefs::dump()) |
| 320 InstX86Br(Func, TargetTrue, TargetFalse, NoLabel, Condition, Kind); | 645 return; |
| 321 } | 646 Ostream &Str = Func->getContext()->getStrDump(); |
| 322 /// Create an unconditional branch to a node. | 647 this->dumpDest(Func); |
| 323 static InstX86Br *create(Cfg *Func, CfgNode *Target, Mode Kind) { | 648 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; |
| 324 constexpr CfgNode *NoCondTarget = nullptr; | 649 this->dumpSources(Func); |
| 325 constexpr InstX86Label<Machine> *NoLabel = nullptr; | 650 } |
| 326 return new (Func->allocate<InstX86Br>()) | 651 static bool classof(const Inst *Inst) { |
| 327 InstX86Br(Func, NoCondTarget, Target, NoLabel, | 652 return InstX86Base::isClassof(Inst, InstX86Base::K); |
| 328 InstX86Base<Machine>::Traits::Cond::Br_None, Kind); | 653 } |
| 329 } | 654 |
| 330 /// Create a non-terminator conditional branch to a node, with a fallthrough | 655 protected: |
| 331 /// to the next instruction in the current node. This is used for switch | 656 InstX86BaseUnaryopXmm(Cfg *Func, Variable *Dest, Operand *Src) |
| 332 /// lowering. | 657 : InstX86Base(Func, K, 1, Dest) { |
| 333 static InstX86Br * | 658 this->addSource(Src); |
| 334 create(Cfg *Func, CfgNode *Target, | 659 } |
| 335 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, | 660 |
| 336 Mode Kind) { | 661 static const char *Opcode; |
| 337 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None); | 662 static const XmmEmitterRegOp Emitter; |
| 338 constexpr CfgNode *NoUncondTarget = nullptr; | 663 }; |
| 339 constexpr InstX86Label<Machine> *NoLabel = nullptr; | 664 |
| 340 return new (Func->allocate<InstX86Br>()) | 665 template <typename InstX86Base::InstKindX86 K> |
| 341 InstX86Br(Func, Target, NoUncondTarget, NoLabel, Condition, Kind); | 666 class InstX86BaseBinopGPRShift : public InstX86Base { |
| 342 } | 667 InstX86BaseBinopGPRShift() = delete; |
| 343 /// Create a conditional intra-block branch (or unconditional, if | 668 InstX86BaseBinopGPRShift(const InstX86BaseBinopGPRShift &) = delete; |
| 344 /// Condition==Br_None) to a label in the current block. | 669 InstX86BaseBinopGPRShift & |
| 345 static InstX86Br * | 670 operator=(const InstX86BaseBinopGPRShift &) = delete; |
| 346 create(Cfg *Func, InstX86Label<Machine> *Label, | 671 |
| 347 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, | 672 public: |
| 348 Mode Kind) { | 673 using Base = InstX86BaseBinopGPRShift<K>; |
| 349 constexpr CfgNode *NoCondTarget = nullptr; | 674 |
| 350 constexpr CfgNode *NoUncondTarget = nullptr; | 675 void emit(const Cfg *Func) const override { |
| 351 return new (Func->allocate<InstX86Br>()) | 676 if (!BuildDefs::dump()) |
| 352 InstX86Br(Func, NoCondTarget, NoUncondTarget, Label, Condition, Kind); | 677 return; |
| 353 } | |
| 354 const CfgNode *getTargetTrue() const { return TargetTrue; } | |
| 355 const CfgNode *getTargetFalse() const { return TargetFalse; } | |
| 356 bool isNear() const { return Kind == Near; } | |
| 357 bool optimizeBranch(const CfgNode *NextNode); | |
| 358 uint32_t getEmitInstCount() const override { | |
| 359 uint32_t Sum = 0; | |
| 360 if (Label) | |
| 361 ++Sum; | |
| 362 if (getTargetTrue()) | |
| 363 ++Sum; | |
| 364 if (getTargetFalse()) | |
| 365 ++Sum; | |
| 366 return Sum; | |
| 367 } | |
| 368 bool isUnconditionalBranch() const override { | |
| 369 return !Label && Condition == InstX86Base<Machine>::Traits::Cond::Br_None; | |
| 370 } | |
| 371 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; | |
| 372 void emit(const Cfg *Func) const override; | |
| 373 void emitIAS(const Cfg *Func) const override; | |
| 374 void dump(const Cfg *Func) const override; | |
| 375 static bool classof(const Inst *Inst) { | |
| 376 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Br); | |
| 377 } | |
| 378 | |
| 379 private: | |
| 380 InstX86Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, | |
| 381 const InstX86Label<Machine> *Label, | |
| 382 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, | |
| 383 Mode Kind); | |
| 384 | |
| 385 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; | |
| 386 const CfgNode *TargetTrue; | |
| 387 const CfgNode *TargetFalse; | |
| 388 const InstX86Label<Machine> *Label; // Intra-block branch target | |
| 389 const Mode Kind; | |
| 390 }; | |
| 391 | |
| 392 /// Jump to a target outside this function, such as tailcall, nacljump, naclret, | |
| 393 /// unreachable. This is different from a Branch instruction in that there is no | |
| 394 /// intra-function control flow to represent. | |
| 395 template <class Machine> class InstX86Jmp final : public InstX86Base<Machine> { | |
| 396 InstX86Jmp() = delete; | |
| 397 InstX86Jmp(const InstX86Jmp &) = delete; | |
| 398 InstX86Jmp &operator=(const InstX86Jmp &) = delete; | |
| 399 | |
| 400 public: | |
| 401 static InstX86Jmp *create(Cfg *Func, Operand *Target) { | |
| 402 return new (Func->allocate<InstX86Jmp>()) InstX86Jmp(Func, Target); | |
| 403 } | |
| 404 Operand *getJmpTarget() const { return this->getSrc(0); } | |
| 405 void emit(const Cfg *Func) const override; | |
| 406 void emitIAS(const Cfg *Func) const override; | |
| 407 void dump(const Cfg *Func) const override; | |
| 408 static bool classof(const Inst *Inst) { | |
| 409 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Jmp); | |
| 410 } | |
| 411 | |
| 412 private: | |
| 413 InstX86Jmp(Cfg *Func, Operand *Target); | |
| 414 }; | |
| 415 | |
| 416 /// Call instruction. Arguments should have already been pushed. | |
| 417 template <class Machine> class InstX86Call final : public InstX86Base<Machine> { | |
| 418 InstX86Call() = delete; | |
| 419 InstX86Call(const InstX86Call &) = delete; | |
| 420 InstX86Call &operator=(const InstX86Call &) = delete; | |
| 421 | |
| 422 public: | |
| 423 static InstX86Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { | |
| 424 return new (Func->allocate<InstX86Call>()) | |
| 425 InstX86Call(Func, Dest, CallTarget); | |
| 426 } | |
| 427 Operand *getCallTarget() const { return this->getSrc(0); } | |
| 428 void emit(const Cfg *Func) const override; | |
| 429 void emitIAS(const Cfg *Func) const override; | |
| 430 void dump(const Cfg *Func) const override; | |
| 431 static bool classof(const Inst *Inst) { | |
| 432 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Call); | |
| 433 } | |
| 434 | |
| 435 private: | |
| 436 InstX86Call(Cfg *Func, Variable *Dest, Operand *CallTarget); | |
| 437 }; | |
| 438 | |
| 439 /// Emit a one-operand (GPR) instruction. | |
| 440 template <class Machine> | |
| 441 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Var, | |
| 442 const typename InstX86Base< | |
| 443 Machine>::Traits::Assembler::GPREmitterOneOp &Emitter); | |
| 444 | |
| 445 template <class Machine> | |
| 446 void emitIASAsAddrOpTyGPR( | |
| 447 const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1, | |
| 448 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp | |
| 449 &Emitter); | |
| 450 | |
| 451 /// Instructions of the form x := op(x). | |
| 452 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | |
| 453 class InstX86BaseInplaceopGPR : public InstX86Base<Machine> { | |
| 454 InstX86BaseInplaceopGPR() = delete; | |
| 455 InstX86BaseInplaceopGPR(const InstX86BaseInplaceopGPR &) = delete; | |
| 456 InstX86BaseInplaceopGPR &operator=(const InstX86BaseInplaceopGPR &) = delete; | |
| 457 | |
| 458 public: | |
| 459 using Base = InstX86BaseInplaceopGPR<Machine, K>; | |
| 460 | |
| 461 void emit(const Cfg *Func) const override { | |
| 462 if (!BuildDefs::dump()) | |
| 463 return; | |
| 464 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 465 assert(this->getSrcSize() == 1); | |
| 466 Str << "\t" << Opcode << "\t"; | |
| 467 this->getSrc(0)->emit(Func); | |
| 468 } | |
| 469 void emitIAS(const Cfg *Func) const override { | |
| 470 assert(this->getSrcSize() == 1); | |
| 471 const Variable *Var = this->getDest(); | |
| 472 Type Ty = Var->getType(); | |
| 473 emitIASOpTyGPR<Machine>(Func, Ty, Var, Emitter); | |
| 474 } | |
| 475 void dump(const Cfg *Func) const override { | |
| 476 if (!BuildDefs::dump()) | |
| 477 return; | |
| 478 Ostream &Str = Func->getContext()->getStrDump(); | |
| 479 this->dumpDest(Func); | |
| 480 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | |
| 481 this->dumpSources(Func); | |
| 482 } | |
| 483 static bool classof(const Inst *Inst) { | |
| 484 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | |
| 485 } | |
| 486 | |
| 487 protected: | |
| 488 InstX86BaseInplaceopGPR(Cfg *Func, Operand *SrcDest) | |
| 489 : InstX86Base<Machine>(Func, K, 1, llvm::dyn_cast<Variable>(SrcDest)) { | |
| 490 this->addSource(SrcDest); | |
| 491 } | |
| 492 | |
| 493 private: | |
| 494 static const char *Opcode; | |
| 495 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp | |
| 496 Emitter; | |
| 497 }; | |
| 498 | |
| 499 /// Emit a two-operand (GPR) instruction, where the dest operand is a Variable | |
| 500 /// that's guaranteed to be a register. | |
| 501 template <class Machine, bool VarCanBeByte = true, bool SrcCanBeByte = true> | |
| 502 void emitIASRegOpTyGPR( | |
| 503 const Cfg *Func, Type Ty, const Variable *Dst, const Operand *Src, | |
| 504 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp | |
| 505 &Emitter); | |
| 506 | |
| 507 /// Instructions of the form x := op(y). | |
| 508 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | |
| 509 class InstX86BaseUnaryopGPR : public InstX86Base<Machine> { | |
| 510 InstX86BaseUnaryopGPR() = delete; | |
| 511 InstX86BaseUnaryopGPR(const InstX86BaseUnaryopGPR &) = delete; | |
| 512 InstX86BaseUnaryopGPR &operator=(const InstX86BaseUnaryopGPR &) = delete; | |
| 513 | |
| 514 public: | |
| 515 using Base = InstX86BaseUnaryopGPR<Machine, K>; | |
| 516 | |
| 517 void emit(const Cfg *Func) const override { | |
| 518 if (!BuildDefs::dump()) | |
| 519 return; | |
| 520 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 521 assert(this->getSrcSize() == 1); | |
| 522 Type SrcTy = this->getSrc(0)->getType(); | |
| 523 Type DestTy = this->getDest()->getType(); | |
| 524 Str << "\t" << Opcode << this->getWidthString(SrcTy); | |
| 525 // Movsx and movzx need both the source and dest type width letter to | |
| 526 // define the operation. The other unary operations have the same source | |
| 527 // and dest type and as a result need only one letter. | |
| 528 if (SrcTy != DestTy) | |
| 529 Str << this->getWidthString(DestTy); | |
| 530 Str << "\t"; | |
| 531 this->getSrc(0)->emit(Func); | |
| 532 Str << ", "; | |
| 533 this->getDest()->emit(Func); | |
| 534 } | |
| 535 void emitIAS(const Cfg *Func) const override { | |
| 536 assert(this->getSrcSize() == 1); | |
| 537 const Variable *Var = this->getDest(); | |
| 538 Type Ty = Var->getType(); | |
| 539 const Operand *Src = this->getSrc(0); | |
| 540 emitIASRegOpTyGPR<Machine>(Func, Ty, Var, Src, Emitter); | |
| 541 } | |
| 542 void dump(const Cfg *Func) const override { | |
| 543 if (!BuildDefs::dump()) | |
| 544 return; | |
| 545 Ostream &Str = Func->getContext()->getStrDump(); | |
| 546 this->dumpDest(Func); | |
| 547 Str << " = " << Opcode << "." << this->getSrc(0)->getType() << " "; | |
| 548 this->dumpSources(Func); | |
| 549 } | |
| 550 static bool classof(const Inst *Inst) { | |
| 551 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | |
| 552 } | |
| 553 | |
| 554 protected: | |
| 555 InstX86BaseUnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) | |
| 556 : InstX86Base<Machine>(Func, K, 1, Dest) { | |
| 557 this->addSource(Src); | |
| 558 } | |
| 559 | |
| 560 static const char *Opcode; | |
| 561 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp | |
| 562 Emitter; | |
| 563 }; | |
| 564 | |
| 565 template <class Machine> | |
| 566 void emitIASRegOpTyXMM( | |
| 567 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src, | |
| 568 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp | |
| 569 &Emitter); | |
| 570 | |
| 571 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | |
| 572 class InstX86BaseUnaryopXmm : public InstX86Base<Machine> { | |
| 573 InstX86BaseUnaryopXmm() = delete; | |
| 574 InstX86BaseUnaryopXmm(const InstX86BaseUnaryopXmm &) = delete; | |
| 575 InstX86BaseUnaryopXmm &operator=(const InstX86BaseUnaryopXmm &) = delete; | |
| 576 | |
| 577 public: | |
| 578 using Base = InstX86BaseUnaryopXmm<Machine, K>; | |
| 579 | |
| 580 void emit(const Cfg *Func) const override { | |
| 581 if (!BuildDefs::dump()) | |
| 582 return; | |
| 583 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 584 assert(this->getSrcSize() == 1); | |
| 585 Str << "\t" << Opcode << "\t"; | |
| 586 this->getSrc(0)->emit(Func); | |
| 587 Str << ", "; | |
| 588 this->getDest()->emit(Func); | |
| 589 } | |
| 590 void emitIAS(const Cfg *Func) const override { | |
| 591 Type Ty = this->getDest()->getType(); | |
| 592 assert(this->getSrcSize() == 1); | |
| 593 emitIASRegOpTyXMM<Machine>(Func, Ty, this->getDest(), this->getSrc(0), | |
| 594 Emitter); | |
| 595 } | |
| 596 void dump(const Cfg *Func) const override { | |
| 597 if (!BuildDefs::dump()) | |
| 598 return; | |
| 599 Ostream &Str = Func->getContext()->getStrDump(); | |
| 600 this->dumpDest(Func); | |
| 601 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | |
| 602 this->dumpSources(Func); | |
| 603 } | |
| 604 static bool classof(const Inst *Inst) { | |
| 605 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | |
| 606 } | |
| 607 | |
| 608 protected: | |
| 609 InstX86BaseUnaryopXmm(Cfg *Func, Variable *Dest, Operand *Src) | |
| 610 : InstX86Base<Machine>(Func, K, 1, Dest) { | |
| 611 this->addSource(Src); | |
| 612 } | |
| 613 | |
| 614 static const char *Opcode; | |
| 615 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp | |
| 616 Emitter; | |
| 617 }; | |
| 618 | |
| 619 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | |
| 620 class InstX86BaseBinopGPRShift : public InstX86Base<Machine> { | |
| 621 InstX86BaseBinopGPRShift() = delete; | |
| 622 InstX86BaseBinopGPRShift(const InstX86BaseBinopGPRShift &) = delete; | |
| 623 InstX86BaseBinopGPRShift & | |
| 624 operator=(const InstX86BaseBinopGPRShift &) = delete; | |
| 625 | |
| 626 public: | |
| 627 using Base = InstX86BaseBinopGPRShift<Machine, K>; | |
| 628 | |
| 629 void emit(const Cfg *Func) const override { | |
| 630 if (!BuildDefs::dump()) | |
| 631 return; | |
| 632 this->emitTwoAddress(Func, Opcode); | |
| 633 } | |
| 634 void emitIAS(const Cfg *Func) const override { | |
| 635 Type Ty = this->getDest()->getType(); | |
| 636 assert(this->getSrcSize() == 2); | |
| 637 this->emitIASGPRShift(Func, Ty, this->getDest(), this->getSrc(1), Emitter); | |
| 638 } | |
| 639 void dump(const Cfg *Func) const override { | |
| 640 if (!BuildDefs::dump()) | |
| 641 return; | |
| 642 Ostream &Str = Func->getContext()->getStrDump(); | |
| 643 this->dumpDest(Func); | |
| 644 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | |
| 645 this->dumpSources(Func); | |
| 646 } | |
| 647 static bool classof(const Inst *Inst) { | |
| 648 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | |
| 649 } | |
| 650 | |
| 651 protected: | |
| 652 InstX86BaseBinopGPRShift(Cfg *Func, Variable *Dest, Operand *Source) | |
| 653 : InstX86Base<Machine>(Func, K, 2, Dest) { | |
| 654 this->addSource(Dest); | |
| 655 this->addSource(Source); | |
| 656 } | |
| 657 | |
| 658 static const char *Opcode; | |
| 659 static const typename InstX86Base< | |
| 660 Machine>::Traits::Assembler::GPREmitterShiftOp Emitter; | |
| 661 }; | |
| 662 | |
| 663 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | |
| 664 class InstX86BaseBinopGPR : public InstX86Base<Machine> { | |
| 665 InstX86BaseBinopGPR() = delete; | |
| 666 InstX86BaseBinopGPR(const InstX86BaseBinopGPR &) = delete; | |
| 667 InstX86BaseBinopGPR &operator=(const InstX86BaseBinopGPR &) = delete; | |
| 668 | |
| 669 public: | |
| 670 using Base = InstX86BaseBinopGPR<Machine, K>; | |
| 671 | |
| 672 void emit(const Cfg *Func) const override { | |
| 673 if (!BuildDefs::dump()) | |
| 674 return; | |
| 675 this->emitTwoAddress(Func, Opcode); | |
| 676 } | |
| 677 void emitIAS(const Cfg *Func) const override { | |
| 678 Type Ty = this->getDest()->getType(); | |
| 679 assert(this->getSrcSize() == 2); | |
| 680 emitIASRegOpTyGPR<Machine>(Func, Ty, this->getDest(), this->getSrc(1), | |
| 681 Emitter); | |
| 682 } | |
| 683 void dump(const Cfg *Func) const override { | |
| 684 if (!BuildDefs::dump()) | |
| 685 return; | |
| 686 Ostream &Str = Func->getContext()->getStrDump(); | |
| 687 this->dumpDest(Func); | |
| 688 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | |
| 689 this->dumpSources(Func); | |
| 690 } | |
| 691 static bool classof(const Inst *Inst) { | |
| 692 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | |
| 693 } | |
| 694 | |
| 695 protected: | |
| 696 InstX86BaseBinopGPR(Cfg *Func, Variable *Dest, Operand *Source) | |
| 697 : InstX86Base<Machine>(Func, K, 2, Dest) { | |
| 698 this->addSource(Dest); | |
| 699 this->addSource(Source); | |
| 700 } | |
| 701 | |
| 702 static const char *Opcode; | |
| 703 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp | |
| 704 Emitter; | |
| 705 }; | |
| 706 | |
| 707 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | |
| 708 class InstX86BaseBinopRMW : public InstX86Base<Machine> { | |
| 709 InstX86BaseBinopRMW() = delete; | |
| 710 InstX86BaseBinopRMW(const InstX86BaseBinopRMW &) = delete; | |
| 711 InstX86BaseBinopRMW &operator=(const InstX86BaseBinopRMW &) = delete; | |
| 712 | |
| 713 public: | |
| 714 using Base = InstX86BaseBinopRMW<Machine, K>; | |
| 715 | |
| 716 void emit(const Cfg *Func) const override { | |
| 717 if (!BuildDefs::dump()) | |
| 718 return; | |
| 719 this->emitTwoAddress(Func, Opcode); | |
| 720 } | |
| 721 void emitIAS(const Cfg *Func) const override { | |
| 722 Type Ty = this->getSrc(0)->getType(); | |
| 723 assert(this->getSrcSize() == 2); | |
| 724 emitIASAsAddrOpTyGPR<Machine>(Func, Ty, this->getSrc(0), this->getSrc(1), | |
| 725 Emitter); | |
| 726 } | |
| 727 void dump(const Cfg *Func) const override { | |
| 728 if (!BuildDefs::dump()) | |
| 729 return; | |
| 730 Ostream &Str = Func->getContext()->getStrDump(); | |
| 731 Str << Opcode << "." << this->getSrc(0)->getType() << " "; | |
| 732 this->dumpSources(Func); | |
| 733 } | |
| 734 static bool classof(const Inst *Inst) { | |
| 735 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | |
| 736 } | |
| 737 | |
| 738 protected: | |
| 739 InstX86BaseBinopRMW( | |
| 740 Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
| 741 Operand *Src1) | |
| 742 : InstX86Base<Machine>(Func, K, 2, nullptr) { | |
| 743 this->addSource(DestSrc0); | |
| 744 this->addSource(Src1); | |
| 745 } | |
| 746 | |
| 747 static const char *Opcode; | |
| 748 static const typename InstX86Base< | |
| 749 Machine>::Traits::Assembler::GPREmitterAddrOp Emitter; | |
| 750 }; | |
| 751 | |
| 752 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K, | |
| 753 bool NeedsElementType, | |
| 754 typename InstX86Base<Machine>::SseSuffix Suffix> | |
| 755 class InstX86BaseBinopXmm : public InstX86Base<Machine> { | |
| 756 InstX86BaseBinopXmm() = delete; | |
| 757 InstX86BaseBinopXmm(const InstX86BaseBinopXmm &) = delete; | |
| 758 InstX86BaseBinopXmm &operator=(const InstX86BaseBinopXmm &) = delete; | |
| 759 | |
| 760 public: | |
| 761 using Base = InstX86BaseBinopXmm<Machine, K, NeedsElementType, Suffix>; | |
| 762 | |
| 763 void emit(const Cfg *Func) const override { | |
| 764 if (!BuildDefs::dump()) | |
| 765 return; | |
| 766 this->validateVectorAddrMode(); | |
| 767 switch (Suffix) { | |
| 768 case InstX86Base<Machine>::SseSuffix::None: | |
| 769 this->emitTwoAddress(Func, Opcode); | 678 this->emitTwoAddress(Func, Opcode); |
| 770 break; | 679 } |
| 771 case InstX86Base<Machine>::SseSuffix::Packed: { | 680 void emitIAS(const Cfg *Func) const override { |
| 681 Type Ty = this->getDest()->getType(); | |
| 682 assert(this->getSrcSize() == 2); | |
| 683 emitIASGPRShift(Func, Ty, this->getDest(), this->getSrc(1), Emitter); | |
| 684 } | |
| 685 void dump(const Cfg *Func) const override { | |
| 686 if (!BuildDefs::dump()) | |
| 687 return; | |
| 688 Ostream &Str = Func->getContext()->getStrDump(); | |
| 689 this->dumpDest(Func); | |
| 690 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | |
| 691 this->dumpSources(Func); | |
| 692 } | |
| 693 static bool classof(const Inst *Inst) { | |
| 694 return InstX86Base::isClassof(Inst, InstX86Base::K); | |
| 695 } | |
| 696 | |
| 697 protected: | |
| 698 InstX86BaseBinopGPRShift(Cfg *Func, Variable *Dest, Operand *Source) | |
| 699 : InstX86Base(Func, K, 2, Dest) { | |
| 700 this->addSource(Dest); | |
| 701 this->addSource(Source); | |
| 702 } | |
| 703 | |
| 704 static const char *Opcode; | |
| 705 static const GPREmitterShiftOp Emitter; | |
| 706 }; | |
| 707 | |
| 708 template <typename InstX86Base::InstKindX86 K> | |
| 709 class InstX86BaseBinopGPR : public InstX86Base { | |
| 710 InstX86BaseBinopGPR() = delete; | |
| 711 InstX86BaseBinopGPR(const InstX86BaseBinopGPR &) = delete; | |
| 712 InstX86BaseBinopGPR &operator=(const InstX86BaseBinopGPR &) = delete; | |
| 713 | |
| 714 public: | |
| 715 using Base = InstX86BaseBinopGPR<K>; | |
| 716 | |
| 717 void emit(const Cfg *Func) const override { | |
| 718 if (!BuildDefs::dump()) | |
| 719 return; | |
| 720 this->emitTwoAddress(Func, Opcode); | |
| 721 } | |
| 722 void emitIAS(const Cfg *Func) const override { | |
| 723 Type Ty = this->getDest()->getType(); | |
| 724 assert(this->getSrcSize() == 2); | |
| 725 emitIASRegOpTyGPR(Func, Ty, this->getDest(), this->getSrc(1), Emitter); | |
| 726 } | |
| 727 void dump(const Cfg *Func) const override { | |
| 728 if (!BuildDefs::dump()) | |
| 729 return; | |
| 730 Ostream &Str = Func->getContext()->getStrDump(); | |
| 731 this->dumpDest(Func); | |
| 732 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | |
| 733 this->dumpSources(Func); | |
| 734 } | |
| 735 static bool classof(const Inst *Inst) { | |
| 736 return InstX86Base::isClassof(Inst, InstX86Base::K); | |
| 737 } | |
| 738 | |
| 739 protected: | |
| 740 InstX86BaseBinopGPR(Cfg *Func, Variable *Dest, Operand *Source) | |
| 741 : InstX86Base(Func, K, 2, Dest) { | |
| 742 this->addSource(Dest); | |
| 743 this->addSource(Source); | |
| 744 } | |
| 745 | |
| 746 static const char *Opcode; | |
| 747 static const GPREmitterRegOp Emitter; | |
| 748 }; | |
| 749 | |
| 750 template <typename InstX86Base::InstKindX86 K> | |
| 751 class InstX86BaseBinopRMW : public InstX86Base { | |
| 752 InstX86BaseBinopRMW() = delete; | |
| 753 InstX86BaseBinopRMW(const InstX86BaseBinopRMW &) = delete; | |
| 754 InstX86BaseBinopRMW &operator=(const InstX86BaseBinopRMW &) = delete; | |
| 755 | |
| 756 public: | |
| 757 using Base = InstX86BaseBinopRMW<K>; | |
| 758 | |
| 759 void emit(const Cfg *Func) const override { | |
| 760 if (!BuildDefs::dump()) | |
| 761 return; | |
| 762 this->emitTwoAddress(Func, Opcode); | |
| 763 } | |
| 764 void emitIAS(const Cfg *Func) const override { | |
| 765 Type Ty = this->getSrc(0)->getType(); | |
| 766 assert(this->getSrcSize() == 2); | |
| 767 emitIASAsAddrOpTyGPR(Func, Ty, this->getSrc(0), this->getSrc(1), Emitter); | |
| 768 } | |
| 769 void dump(const Cfg *Func) const override { | |
| 770 if (!BuildDefs::dump()) | |
| 771 return; | |
| 772 Ostream &Str = Func->getContext()->getStrDump(); | |
| 773 Str << Opcode << "." << this->getSrc(0)->getType() << " "; | |
| 774 this->dumpSources(Func); | |
| 775 } | |
| 776 static bool classof(const Inst *Inst) { | |
| 777 return InstX86Base::isClassof(Inst, InstX86Base::K); | |
| 778 } | |
| 779 | |
| 780 protected: | |
| 781 InstX86BaseBinopRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
| 782 : InstX86Base(Func, K, 2, nullptr) { | |
| 783 this->addSource(DestSrc0); | |
| 784 this->addSource(Src1); | |
| 785 } | |
| 786 | |
| 787 static const char *Opcode; | |
| 788 static const GPREmitterAddrOp Emitter; | |
| 789 }; | |
| 790 | |
| 791 template <typename InstX86Base::InstKindX86 K, bool NeedsElementType, | |
| 792 typename InstX86Base::SseSuffix Suffix> | |
| 793 class InstX86BaseBinopXmm : public InstX86Base { | |
| 794 InstX86BaseBinopXmm() = delete; | |
| 795 InstX86BaseBinopXmm(const InstX86BaseBinopXmm &) = delete; | |
| 796 InstX86BaseBinopXmm &operator=(const InstX86BaseBinopXmm &) = delete; | |
| 797 | |
| 798 public: | |
| 799 using Base = InstX86BaseBinopXmm<K, NeedsElementType, Suffix>; | |
| 800 | |
| 801 void emit(const Cfg *Func) const override { | |
| 802 if (!BuildDefs::dump()) | |
| 803 return; | |
| 804 this->validateVectorAddrMode(); | |
| 805 switch (Suffix) { | |
| 806 case InstX86Base::SseSuffix::None: | |
| 807 this->emitTwoAddress(Func, Opcode); | |
| 808 break; | |
| 809 case InstX86Base::SseSuffix::Packed: { | |
| 810 const Type DestTy = this->getDest()->getType(); | |
| 811 this->emitTwoAddress(Func, this->Opcode, | |
| 812 Traits::TypeAttributes[DestTy].PdPsString); | |
| 813 } break; | |
| 814 case InstX86Base::SseSuffix::Scalar: { | |
| 815 const Type DestTy = this->getDest()->getType(); | |
| 816 this->emitTwoAddress(Func, this->Opcode, | |
| 817 Traits::TypeAttributes[DestTy].SdSsString); | |
| 818 } break; | |
| 819 case InstX86Base::SseSuffix::Integral: { | |
| 820 const Type DestTy = this->getDest()->getType(); | |
| 821 this->emitTwoAddress(Func, this->Opcode, | |
| 822 Traits::TypeAttributes[DestTy].PackString); | |
| 823 } break; | |
| 824 } | |
| 825 } | |
| 826 void emitIAS(const Cfg *Func) const override { | |
| 827 this->validateVectorAddrMode(); | |
| 828 Type Ty = this->getDest()->getType(); | |
| 829 if (NeedsElementType) | |
| 830 Ty = typeElementType(Ty); | |
| 831 assert(this->getSrcSize() == 2); | |
| 832 emitIASRegOpTyXMM(Func, Ty, this->getDest(), this->getSrc(1), Emitter); | |
| 833 } | |
| 834 void dump(const Cfg *Func) const override { | |
| 835 if (!BuildDefs::dump()) | |
| 836 return; | |
| 837 Ostream &Str = Func->getContext()->getStrDump(); | |
| 838 this->dumpDest(Func); | |
| 839 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | |
| 840 this->dumpSources(Func); | |
| 841 } | |
| 842 static bool classof(const Inst *Inst) { | |
| 843 return InstX86Base::isClassof(Inst, InstX86Base::K); | |
| 844 } | |
| 845 | |
| 846 protected: | |
| 847 InstX86BaseBinopXmm(Cfg *Func, Variable *Dest, Operand *Source) | |
| 848 : InstX86Base(Func, K, 2, Dest) { | |
| 849 this->addSource(Dest); | |
| 850 this->addSource(Source); | |
| 851 } | |
| 852 | |
| 853 static const char *Opcode; | |
| 854 static const XmmEmitterRegOp Emitter; | |
| 855 }; | |
| 856 | |
| 857 template <typename InstX86Base::InstKindX86 K, bool AllowAllTypes = false> | |
| 858 class InstX86BaseBinopXmmShift : public InstX86Base { | |
| 859 InstX86BaseBinopXmmShift() = delete; | |
| 860 InstX86BaseBinopXmmShift(const InstX86BaseBinopXmmShift &) = delete; | |
| 861 InstX86BaseBinopXmmShift & | |
| 862 operator=(const InstX86BaseBinopXmmShift &) = delete; | |
| 863 | |
| 864 public: | |
| 865 using Base = InstX86BaseBinopXmmShift<K, AllowAllTypes>; | |
| 866 | |
| 867 void emit(const Cfg *Func) const override { | |
| 868 if (!BuildDefs::dump()) | |
| 869 return; | |
| 870 this->validateVectorAddrMode(); | |
| 871 // Shift operations are always integral, and hence always need a suffix. | |
| 772 const Type DestTy = this->getDest()->getType(); | 872 const Type DestTy = this->getDest()->getType(); |
| 773 this->emitTwoAddress( | 873 this->emitTwoAddress(Func, this->Opcode, |
| 774 Func, this->Opcode, | 874 Traits::TypeAttributes[DestTy].PackString); |
| 775 InstX86Base<Machine>::Traits::TypeAttributes[DestTy].PdPsString); | 875 } |
| 776 } break; | 876 void emitIAS(const Cfg *Func) const override { |
| 777 case InstX86Base<Machine>::SseSuffix::Scalar: { | 877 this->validateVectorAddrMode(); |
| 778 const Type DestTy = this->getDest()->getType(); | 878 Type Ty = this->getDest()->getType(); |
| 779 this->emitTwoAddress( | 879 assert(AllowAllTypes || isVectorType(Ty)); |
| 780 Func, this->Opcode, | 880 Type ElementTy = typeElementType(Ty); |
| 781 InstX86Base<Machine>::Traits::TypeAttributes[DestTy].SdSsString); | 881 assert(this->getSrcSize() == 2); |
| 782 } break; | 882 emitIASXmmShift(Func, ElementTy, this->getDest(), this->getSrc(1), |
| 783 case InstX86Base<Machine>::SseSuffix::Integral: { | 883 Emitter); |
| 784 const Type DestTy = this->getDest()->getType(); | 884 } |
| 785 this->emitTwoAddress( | 885 void dump(const Cfg *Func) const override { |
| 786 Func, this->Opcode, | 886 if (!BuildDefs::dump()) |
| 787 InstX86Base<Machine>::Traits::TypeAttributes[DestTy].PackString); | 887 return; |
| 788 } break; | 888 Ostream &Str = Func->getContext()->getStrDump(); |
| 789 } | 889 this->dumpDest(Func); |
| 790 } | 890 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; |
| 791 void emitIAS(const Cfg *Func) const override { | 891 this->dumpSources(Func); |
| 792 this->validateVectorAddrMode(); | 892 } |
| 793 Type Ty = this->getDest()->getType(); | 893 static bool classof(const Inst *Inst) { |
| 794 if (NeedsElementType) | 894 return InstX86Base::isClassof(Inst, InstX86Base::K); |
| 795 Ty = typeElementType(Ty); | 895 } |
| 796 assert(this->getSrcSize() == 2); | 896 |
| 797 emitIASRegOpTyXMM<Machine>(Func, Ty, this->getDest(), this->getSrc(1), | 897 protected: |
| 798 Emitter); | 898 InstX86BaseBinopXmmShift(Cfg *Func, Variable *Dest, Operand *Source) |
| 799 } | 899 : InstX86Base(Func, K, 2, Dest) { |
| 800 void dump(const Cfg *Func) const override { | 900 this->addSource(Dest); |
| 801 if (!BuildDefs::dump()) | 901 this->addSource(Source); |
| 802 return; | 902 } |
| 803 Ostream &Str = Func->getContext()->getStrDump(); | 903 |
| 804 this->dumpDest(Func); | 904 static const char *Opcode; |
| 805 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 905 static const XmmEmitterShiftOp Emitter; |
| 806 this->dumpSources(Func); | 906 }; |
| 807 } | 907 |
| 808 static bool classof(const Inst *Inst) { | 908 template <typename InstX86Base::InstKindX86 K> |
| 809 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 909 class InstX86BaseTernop : public InstX86Base { |
| 810 } | 910 InstX86BaseTernop() = delete; |
| 811 | 911 InstX86BaseTernop(const InstX86BaseTernop &) = delete; |
| 812 protected: | 912 InstX86BaseTernop &operator=(const InstX86BaseTernop &) = delete; |
| 813 InstX86BaseBinopXmm(Cfg *Func, Variable *Dest, Operand *Source) | 913 |
| 814 : InstX86Base<Machine>(Func, K, 2, Dest) { | 914 public: |
| 815 this->addSource(Dest); | 915 using Base = InstX86BaseTernop<K>; |
| 816 this->addSource(Source); | 916 |
| 817 } | 917 void emit(const Cfg *Func) const override { |
| 818 | 918 if (!BuildDefs::dump()) |
| 819 static const char *Opcode; | 919 return; |
| 820 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp | 920 Ostream &Str = Func->getContext()->getStrEmit(); |
| 821 Emitter; | 921 assert(this->getSrcSize() == 3); |
| 822 }; | 922 Str << "\t" << Opcode << "\t"; |
| 823 | 923 this->getSrc(2)->emit(Func); |
| 824 template <class Machine> | 924 Str << ", "; |
| 825 void emitIASXmmShift( | 925 this->getSrc(1)->emit(Func); |
| 826 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src, | 926 Str << ", "; |
| 827 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp | 927 this->getDest()->emit(Func); |
| 828 &Emitter); | 928 } |
| 829 | 929 void dump(const Cfg *Func) const override { |
| 830 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K, | 930 if (!BuildDefs::dump()) |
| 831 bool AllowAllTypes = false> | 931 return; |
| 832 class InstX86BaseBinopXmmShift : public InstX86Base<Machine> { | 932 Ostream &Str = Func->getContext()->getStrDump(); |
| 833 InstX86BaseBinopXmmShift() = delete; | 933 this->dumpDest(Func); |
| 834 InstX86BaseBinopXmmShift(const InstX86BaseBinopXmmShift &) = delete; | 934 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; |
| 835 InstX86BaseBinopXmmShift & | 935 this->dumpSources(Func); |
| 836 operator=(const InstX86BaseBinopXmmShift &) = delete; | 936 } |
| 837 | 937 static bool classof(const Inst *Inst) { |
| 838 public: | 938 return InstX86Base::isClassof(Inst, InstX86Base::K); |
| 839 using Base = InstX86BaseBinopXmmShift<Machine, K, AllowAllTypes>; | 939 } |
| 840 | 940 |
| 841 void emit(const Cfg *Func) const override { | 941 protected: |
| 842 if (!BuildDefs::dump()) | 942 InstX86BaseTernop(Cfg *Func, Variable *Dest, Operand *Source1, |
| 843 return; | 943 Operand *Source2) |
| 844 this->validateVectorAddrMode(); | 944 : InstX86Base(Func, K, 3, Dest) { |
| 845 // Shift operations are always integral, and hence always need a suffix. | 945 this->addSource(Dest); |
| 846 const Type DestTy = this->getDest()->getType(); | 946 this->addSource(Source1); |
| 847 this->emitTwoAddress( | 947 this->addSource(Source2); |
| 848 Func, this->Opcode, | 948 } |
| 849 InstX86Base<Machine>::Traits::TypeAttributes[DestTy].PackString); | 949 |
| 850 } | 950 static const char *Opcode; |
| 851 void emitIAS(const Cfg *Func) const override { | 951 }; |
| 852 this->validateVectorAddrMode(); | 952 |
| 853 Type Ty = this->getDest()->getType(); | 953 // Instructions of the form x := y op z |
| 854 assert(AllowAllTypes || isVectorType(Ty)); | 954 template <typename InstX86Base::InstKindX86 K> |
| 855 Type ElementTy = typeElementType(Ty); | 955 class InstX86BaseThreeAddressop : public InstX86Base { |
| 856 assert(this->getSrcSize() == 2); | 956 InstX86BaseThreeAddressop() = delete; |
| 857 emitIASXmmShift<Machine>(Func, ElementTy, this->getDest(), this->getSrc(1), | 957 InstX86BaseThreeAddressop(const InstX86BaseThreeAddressop &) = delete; |
| 858 Emitter); | 958 InstX86BaseThreeAddressop & |
| 859 } | 959 operator=(const InstX86BaseThreeAddressop &) = delete; |
| 860 void dump(const Cfg *Func) const override { | 960 |
| 861 if (!BuildDefs::dump()) | 961 public: |
| 862 return; | 962 using Base = InstX86BaseThreeAddressop<K>; |
| 863 Ostream &Str = Func->getContext()->getStrDump(); | 963 |
| 864 this->dumpDest(Func); | 964 void emit(const Cfg *Func) const override { |
| 865 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 965 if (!BuildDefs::dump()) |
| 866 this->dumpSources(Func); | 966 return; |
| 867 } | 967 Ostream &Str = Func->getContext()->getStrEmit(); |
| 868 static bool classof(const Inst *Inst) { | 968 assert(this->getSrcSize() == 2); |
| 869 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 969 Str << "\t" << Opcode << "\t"; |
| 870 } | 970 this->getSrc(1)->emit(Func); |
| 871 | 971 Str << ", "; |
| 872 protected: | 972 this->getSrc(0)->emit(Func); |
| 873 InstX86BaseBinopXmmShift(Cfg *Func, Variable *Dest, Operand *Source) | 973 Str << ", "; |
| 874 : InstX86Base<Machine>(Func, K, 2, Dest) { | 974 this->getDest()->emit(Func); |
| 875 this->addSource(Dest); | 975 } |
| 876 this->addSource(Source); | 976 void dump(const Cfg *Func) const override { |
| 877 } | 977 if (!BuildDefs::dump()) |
| 878 | 978 return; |
| 879 static const char *Opcode; | 979 Ostream &Str = Func->getContext()->getStrDump(); |
| 880 static const typename InstX86Base< | 980 this->dumpDest(Func); |
| 881 Machine>::Traits::Assembler::XmmEmitterShiftOp Emitter; | 981 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; |
| 882 }; | 982 this->dumpSources(Func); |
| 883 | 983 } |
| 884 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 984 static bool classof(const Inst *Inst) { |
| 885 class InstX86BaseTernop : public InstX86Base<Machine> { | 985 return InstX86Base::isClassof(Inst, InstX86Base::K); |
| 886 InstX86BaseTernop() = delete; | 986 } |
| 887 InstX86BaseTernop(const InstX86BaseTernop &) = delete; | 987 |
| 888 InstX86BaseTernop &operator=(const InstX86BaseTernop &) = delete; | 988 protected: |
| 889 | 989 InstX86BaseThreeAddressop(Cfg *Func, Variable *Dest, Operand *Source0, |
| 890 public: | 990 Operand *Source1) |
| 891 using Base = InstX86BaseTernop<Machine, K>; | 991 : InstX86Base(Func, K, 2, Dest) { |
| 892 | 992 this->addSource(Source0); |
| 893 void emit(const Cfg *Func) const override { | 993 this->addSource(Source1); |
| 894 if (!BuildDefs::dump()) | 994 } |
| 895 return; | 995 |
| 896 Ostream &Str = Func->getContext()->getStrEmit(); | 996 static const char *Opcode; |
| 897 assert(this->getSrcSize() == 3); | 997 }; |
| 898 Str << "\t" << Opcode << "\t"; | 998 |
| 899 this->getSrc(2)->emit(Func); | 999 /// Base class for assignment instructions |
| 900 Str << ", "; | 1000 template <typename InstX86Base::InstKindX86 K> |
| 901 this->getSrc(1)->emit(Func); | 1001 class InstX86BaseMovlike : public InstX86Base { |
| 902 Str << ", "; | 1002 InstX86BaseMovlike() = delete; |
| 903 this->getDest()->emit(Func); | 1003 InstX86BaseMovlike(const InstX86BaseMovlike &) = delete; |
| 904 } | 1004 InstX86BaseMovlike &operator=(const InstX86BaseMovlike &) = delete; |
| 905 void dump(const Cfg *Func) const override { | 1005 |
| 906 if (!BuildDefs::dump()) | 1006 public: |
| 907 return; | 1007 using Base = InstX86BaseMovlike<K>; |
| 908 Ostream &Str = Func->getContext()->getStrDump(); | 1008 |
| 909 this->dumpDest(Func); | 1009 bool isRedundantAssign() const override { |
| 910 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 1010 if (const auto *SrcVar = |
| 911 this->dumpSources(Func); | 1011 llvm::dyn_cast<const Variable>(this->getSrc(0))) { |
| 912 } | 1012 if (SrcVar->hasReg() && this->Dest->hasReg()) { |
| 913 static bool classof(const Inst *Inst) { | 1013 // An assignment between physical registers is considered redundant if |
| 914 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 1014 // they have the same base register and the same encoding. E.g.: |
| 915 } | 1015 // mov cl, ecx ==> redundant |
| 916 | 1016 // mov ch, ecx ==> not redundant due to different encodings |
| 917 protected: | 1017 // mov ch, ebp ==> not redundant due to different base registers |
| 918 InstX86BaseTernop(Cfg *Func, Variable *Dest, Operand *Source1, | 1018 // mov ecx, ecx ==> redundant, and dangerous in x86-64. i64 zexting |
| 1019 // is handled by Inst86Zext. | |
| 1020 const int32_t SrcReg = SrcVar->getRegNum(); | |
| 1021 const int32_t DestReg = this->Dest->getRegNum(); | |
| 1022 return (Traits::getEncoding(SrcReg) == | |
| 1023 Traits::getEncoding(DestReg)) && | |
| 1024 (Traits::getBaseReg(SrcReg) == Traits::getBaseReg(DestReg)); | |
| 1025 } | |
| 1026 } | |
| 1027 return checkForRedundantAssign(this->getDest(), this->getSrc(0)); | |
| 1028 } | |
| 1029 bool isVarAssign() const override { | |
| 1030 return llvm::isa<Variable>(this->getSrc(0)); | |
| 1031 } | |
| 1032 void dump(const Cfg *Func) const override { | |
| 1033 if (!BuildDefs::dump()) | |
| 1034 return; | |
| 1035 Ostream &Str = Func->getContext()->getStrDump(); | |
| 1036 Str << Opcode << "." << this->getDest()->getType() << " "; | |
| 1037 this->dumpDest(Func); | |
| 1038 Str << ", "; | |
| 1039 this->dumpSources(Func); | |
| 1040 } | |
| 1041 static bool classof(const Inst *Inst) { | |
| 1042 return InstX86Base::isClassof(Inst, InstX86Base::K); | |
| 1043 } | |
| 1044 | |
| 1045 protected: | |
| 1046 InstX86BaseMovlike(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1047 : InstX86Base(Func, K, 1, Dest) { | |
| 1048 this->addSource(Source); | |
| 1049 // For an integer assignment, make sure it's either a same-type assignment | |
| 1050 // or a truncation. | |
| 1051 assert(!isScalarIntegerType(Dest->getType()) || | |
| 1052 (typeWidthInBytes(Dest->getType()) <= | |
| 1053 typeWidthInBytes(Source->getType()))); | |
| 1054 } | |
| 1055 | |
| 1056 static const char *Opcode; | |
| 1057 }; | |
| 1058 | |
| 1059 class InstX86Bswap : public InstX86BaseInplaceopGPR<InstX86Base::Bswap> { | |
| 1060 public: | |
| 1061 static InstX86Bswap *create(Cfg *Func, Operand *SrcDest) { | |
| 1062 return new (Func->allocate<InstX86Bswap>()) InstX86Bswap(Func, SrcDest); | |
| 1063 } | |
| 1064 | |
| 1065 private: | |
| 1066 InstX86Bswap(Cfg *Func, Operand *SrcDest) | |
| 1067 : InstX86BaseInplaceopGPR<InstX86Base::Bswap>(Func, SrcDest) {} | |
| 1068 }; | |
| 1069 | |
| 1070 class InstX86Neg : public InstX86BaseInplaceopGPR<InstX86Base::Neg> { | |
| 1071 public: | |
| 1072 static InstX86Neg *create(Cfg *Func, Operand *SrcDest) { | |
| 1073 return new (Func->allocate<InstX86Neg>()) InstX86Neg(Func, SrcDest); | |
| 1074 } | |
| 1075 | |
| 1076 private: | |
| 1077 InstX86Neg(Cfg *Func, Operand *SrcDest) | |
| 1078 : InstX86BaseInplaceopGPR<InstX86Base::Neg>(Func, SrcDest) {} | |
| 1079 }; | |
| 1080 | |
| 1081 class InstX86Bsf : public InstX86BaseUnaryopGPR<InstX86Base::Bsf> { | |
| 1082 public: | |
| 1083 static InstX86Bsf *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1084 return new (Func->allocate<InstX86Bsf>()) InstX86Bsf(Func, Dest, Src); | |
| 1085 } | |
| 1086 | |
| 1087 private: | |
| 1088 InstX86Bsf(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1089 : InstX86BaseUnaryopGPR<InstX86Base::Bsf>(Func, Dest, Src) {} | |
| 1090 }; | |
| 1091 | |
| 1092 class InstX86Bsr : public InstX86BaseUnaryopGPR<InstX86Base::Bsr> { | |
| 1093 public: | |
| 1094 static InstX86Bsr *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1095 return new (Func->allocate<InstX86Bsr>()) InstX86Bsr(Func, Dest, Src); | |
| 1096 } | |
| 1097 | |
| 1098 private: | |
| 1099 InstX86Bsr(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1100 : InstX86BaseUnaryopGPR<InstX86Base::Bsr>(Func, Dest, Src) {} | |
| 1101 }; | |
| 1102 | |
| 1103 class InstX86Lea : public InstX86BaseUnaryopGPR<InstX86Base::Lea> { | |
| 1104 public: | |
| 1105 static InstX86Lea *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1106 return new (Func->allocate<InstX86Lea>()) InstX86Lea(Func, Dest, Src); | |
| 1107 } | |
| 1108 | |
| 1109 void emit(const Cfg *Func) const override; | |
| 1110 | |
| 1111 private: | |
| 1112 InstX86Lea(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1113 : InstX86BaseUnaryopGPR<InstX86Base::Lea>(Func, Dest, Src) {} | |
| 1114 }; | |
| 1115 | |
| 1116 // Cbwdq instruction - wrapper for cbw, cwd, and cdq | |
| 1117 class InstX86Cbwdq : public InstX86BaseUnaryopGPR<InstX86Base::Cbwdq> { | |
| 1118 public: | |
| 1119 static InstX86Cbwdq *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1120 return new (Func->allocate<InstX86Cbwdq>()) InstX86Cbwdq(Func, Dest, Src); | |
| 1121 } | |
| 1122 | |
| 1123 void emit(const Cfg *Func) const override; | |
| 1124 void emitIAS(const Cfg *Func) const override; | |
| 1125 | |
| 1126 private: | |
| 1127 InstX86Cbwdq(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1128 : InstX86BaseUnaryopGPR<InstX86Base::Cbwdq>(Func, Dest, Src) {} | |
| 1129 }; | |
| 1130 | |
| 1131 class InstX86Movsx : public InstX86BaseUnaryopGPR<InstX86Base::Movsx> { | |
| 1132 public: | |
| 1133 static InstX86Movsx *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1134 assert(typeWidthInBytes(Dest->getType()) > | |
| 1135 typeWidthInBytes(Src->getType())); | |
| 1136 return new (Func->allocate<InstX86Movsx>()) InstX86Movsx(Func, Dest, Src); | |
| 1137 } | |
| 1138 | |
| 1139 void emitIAS(const Cfg *Func) const override; | |
| 1140 | |
| 1141 private: | |
| 1142 InstX86Movsx(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1143 : InstX86BaseUnaryopGPR<InstX86Base::Movsx>(Func, Dest, Src) {} | |
| 1144 }; | |
| 1145 | |
| 1146 class InstX86Movzx : public InstX86BaseUnaryopGPR<InstX86Base::Movzx> { | |
| 1147 public: | |
| 1148 static InstX86Movzx *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1149 assert(typeWidthInBytes(Dest->getType()) > | |
| 1150 typeWidthInBytes(Src->getType())); | |
| 1151 return new (Func->allocate<InstX86Movzx>()) InstX86Movzx(Func, Dest, Src); | |
| 1152 } | |
| 1153 | |
| 1154 void emit(const Cfg *Func) const override; | |
| 1155 | |
| 1156 void emitIAS(const Cfg *Func) const override; | |
| 1157 | |
| 1158 private: | |
| 1159 InstX86Movzx(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1160 : InstX86BaseUnaryopGPR<InstX86Base::Movzx>(Func, Dest, Src) {} | |
| 1161 }; | |
| 1162 | |
| 1163 class InstX86Movd : public InstX86BaseUnaryopXmm<InstX86Base::Movd> { | |
| 1164 public: | |
| 1165 static InstX86Movd *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1166 return new (Func->allocate<InstX86Movd>()) InstX86Movd(Func, Dest, Src); | |
| 1167 } | |
| 1168 | |
| 1169 void emit(const Cfg *Func) const override; | |
| 1170 | |
| 1171 void emitIAS(const Cfg *Func) const override; | |
| 1172 | |
| 1173 private: | |
| 1174 InstX86Movd(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1175 : InstX86BaseUnaryopXmm<InstX86Base::Movd>(Func, Dest, Src) {} | |
| 1176 }; | |
| 1177 | |
| 1178 class InstX86Sqrtss : public InstX86BaseUnaryopXmm<InstX86Base::Sqrtss> { | |
| 1179 public: | |
| 1180 static InstX86Sqrtss *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1181 return new (Func->allocate<InstX86Sqrtss>()) | |
| 1182 InstX86Sqrtss(Func, Dest, Src); | |
| 1183 } | |
| 1184 | |
| 1185 virtual void emit(const Cfg *Func) const override; | |
| 1186 | |
| 1187 private: | |
| 1188 InstX86Sqrtss(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1189 : InstX86BaseUnaryopXmm<InstX86Base::Sqrtss>(Func, Dest, Src) {} | |
| 1190 }; | |
| 1191 | |
| 1192 /// Move/assignment instruction - wrapper for mov/movss/movsd. | |
| 1193 class InstX86Mov : public InstX86BaseMovlike<InstX86Base::Mov> { | |
| 1194 public: | |
| 1195 static InstX86Mov *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1196 assert(!isScalarIntegerType(Dest->getType()) || | |
| 1197 (typeWidthInBytes(Dest->getType()) <= | |
| 1198 typeWidthInBytes(Source->getType()))); | |
| 1199 return new (Func->allocate<InstX86Mov>()) InstX86Mov(Func, Dest, Source); | |
| 1200 } | |
| 1201 | |
| 1202 void emit(const Cfg *Func) const override; | |
| 1203 void emitIAS(const Cfg *Func) const override; | |
| 1204 | |
| 1205 private: | |
| 1206 InstX86Mov(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1207 : InstX86BaseMovlike<InstX86Base::Mov>(Func, Dest, Source) {} | |
| 1208 }; | |
| 1209 | |
| 1210 /// Move packed - copy 128 bit values between XMM registers, or mem128 and XMM | |
| 1211 /// registers. | |
| 1212 class InstX86Movp : public InstX86BaseMovlike<InstX86Base::Movp> { | |
| 1213 public: | |
| 1214 static InstX86Movp *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1215 return new (Func->allocate<InstX86Movp>()) | |
| 1216 InstX86Movp(Func, Dest, Source); | |
| 1217 } | |
| 1218 | |
| 1219 void emit(const Cfg *Func) const override; | |
| 1220 void emitIAS(const Cfg *Func) const override; | |
| 1221 | |
| 1222 private: | |
| 1223 InstX86Movp(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1224 : InstX86BaseMovlike<InstX86Base::Movp>(Func, Dest, Source) {} | |
| 1225 }; | |
| 1226 | |
| 1227 /// Movq - copy between XMM registers, or mem64 and XMM registers. | |
| 1228 class InstX86Movq : public InstX86BaseMovlike<InstX86Base::Movq> { | |
| 1229 public: | |
| 1230 static InstX86Movq *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1231 return new (Func->allocate<InstX86Movq>()) | |
| 1232 InstX86Movq(Func, Dest, Source); | |
| 1233 } | |
| 1234 | |
| 1235 void emit(const Cfg *Func) const override; | |
| 1236 void emitIAS(const Cfg *Func) const override; | |
| 1237 | |
| 1238 private: | |
| 1239 InstX86Movq(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1240 : InstX86BaseMovlike<InstX86Base::Movq>(Func, Dest, Source) {} | |
| 1241 }; | |
| 1242 | |
| 1243 class InstX86Add : public InstX86BaseBinopGPR<InstX86Base::Add> { | |
| 1244 public: | |
| 1245 static InstX86Add *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1246 return new (Func->allocate<InstX86Add>()) InstX86Add(Func, Dest, Source); | |
| 1247 } | |
| 1248 | |
| 1249 private: | |
| 1250 InstX86Add(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1251 : InstX86BaseBinopGPR<InstX86Base::Add>(Func, Dest, Source) {} | |
| 1252 }; | |
| 1253 | |
| 1254 class InstX86AddRMW : public InstX86BaseBinopRMW<InstX86Base::AddRMW> { | |
| 1255 public: | |
| 1256 static InstX86AddRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | |
| 1257 Operand *Src1) { | |
| 1258 return new (Func->allocate<InstX86AddRMW>()) | |
| 1259 InstX86AddRMW(Func, DestSrc0, Src1); | |
| 1260 } | |
| 1261 | |
| 1262 private: | |
| 1263 InstX86AddRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
| 1264 : InstX86BaseBinopRMW<InstX86Base::AddRMW>(Func, DestSrc0, Src1) {} | |
| 1265 }; | |
| 1266 | |
| 1267 class InstX86Addps | |
| 1268 : public InstX86BaseBinopXmm<InstX86Base::Addps, true, | |
| 1269 InstX86Base::SseSuffix::Packed> { | |
| 1270 public: | |
| 1271 static InstX86Addps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1272 return new (Func->allocate<InstX86Addps>()) | |
| 1273 InstX86Addps(Func, Dest, Source); | |
| 1274 } | |
| 1275 | |
| 1276 private: | |
| 1277 InstX86Addps(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1278 : InstX86BaseBinopXmm<InstX86Base::Addps, true, | |
| 1279 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
| 1280 Source) {} | |
| 1281 }; | |
| 1282 | |
| 1283 class InstX86Adc : public InstX86BaseBinopGPR<InstX86Base::Adc> { | |
| 1284 public: | |
| 1285 static InstX86Adc *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1286 return new (Func->allocate<InstX86Adc>()) InstX86Adc(Func, Dest, Source); | |
| 1287 } | |
| 1288 | |
| 1289 private: | |
| 1290 InstX86Adc(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1291 : InstX86BaseBinopGPR<InstX86Base::Adc>(Func, Dest, Source) {} | |
| 1292 }; | |
| 1293 | |
| 1294 class InstX86AdcRMW : public InstX86BaseBinopRMW<InstX86Base::AdcRMW> { | |
| 1295 public: | |
| 1296 static InstX86AdcRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | |
| 1297 Operand *Src1) { | |
| 1298 return new (Func->allocate<InstX86AdcRMW>()) | |
| 1299 InstX86AdcRMW(Func, DestSrc0, Src1); | |
| 1300 } | |
| 1301 | |
| 1302 private: | |
| 1303 InstX86AdcRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
| 1304 : InstX86BaseBinopRMW<InstX86Base::AdcRMW>(Func, DestSrc0, Src1) {} | |
| 1305 }; | |
| 1306 | |
| 1307 class InstX86Addss | |
| 1308 : public InstX86BaseBinopXmm<InstX86Base::Addss, false, | |
| 1309 InstX86Base::SseSuffix::Scalar> { | |
| 1310 public: | |
| 1311 static InstX86Addss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1312 return new (Func->allocate<InstX86Addss>()) | |
| 1313 InstX86Addss(Func, Dest, Source); | |
| 1314 } | |
| 1315 | |
| 1316 private: | |
| 1317 InstX86Addss(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1318 : InstX86BaseBinopXmm<InstX86Base::Addss, false, | |
| 1319 InstX86Base::SseSuffix::Scalar>(Func, Dest, | |
| 1320 Source) {} | |
| 1321 }; | |
| 1322 | |
| 1323 class InstX86Padd | |
| 1324 : public InstX86BaseBinopXmm<InstX86Base::Padd, true, | |
| 1325 InstX86Base::SseSuffix::Integral> { | |
| 1326 public: | |
| 1327 static InstX86Padd *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1328 return new (Func->allocate<InstX86Padd>()) | |
| 1329 InstX86Padd(Func, Dest, Source); | |
| 1330 } | |
| 1331 | |
| 1332 private: | |
| 1333 InstX86Padd(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1334 : InstX86BaseBinopXmm<InstX86Base::Padd, true, | |
| 1335 InstX86Base::SseSuffix::Integral>(Func, Dest, | |
| 1336 Source) {} | |
| 1337 }; | |
| 1338 | |
| 1339 class InstX86Sub : public InstX86BaseBinopGPR<InstX86Base::Sub> { | |
| 1340 public: | |
| 1341 static InstX86Sub *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1342 return new (Func->allocate<InstX86Sub>()) InstX86Sub(Func, Dest, Source); | |
| 1343 } | |
| 1344 | |
| 1345 private: | |
| 1346 InstX86Sub(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1347 : InstX86BaseBinopGPR<InstX86Base::Sub>(Func, Dest, Source) {} | |
| 1348 }; | |
| 1349 | |
| 1350 class InstX86SubRMW : public InstX86BaseBinopRMW<InstX86Base::SubRMW> { | |
| 1351 public: | |
| 1352 static InstX86SubRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | |
| 1353 Operand *Src1) { | |
| 1354 return new (Func->allocate<InstX86SubRMW>()) | |
| 1355 InstX86SubRMW(Func, DestSrc0, Src1); | |
| 1356 } | |
| 1357 | |
| 1358 private: | |
| 1359 InstX86SubRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
| 1360 : InstX86BaseBinopRMW<InstX86Base::SubRMW>(Func, DestSrc0, Src1) {} | |
| 1361 }; | |
| 1362 | |
| 1363 class InstX86Subps | |
| 1364 : public InstX86BaseBinopXmm<InstX86Base::Subps, true, | |
| 1365 InstX86Base::SseSuffix::Packed> { | |
| 1366 public: | |
| 1367 static InstX86Subps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1368 return new (Func->allocate<InstX86Subps>()) | |
| 1369 InstX86Subps(Func, Dest, Source); | |
| 1370 } | |
| 1371 | |
| 1372 private: | |
| 1373 InstX86Subps(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1374 : InstX86BaseBinopXmm<InstX86Base::Subps, true, | |
| 1375 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
| 1376 Source) {} | |
| 1377 }; | |
| 1378 | |
| 1379 class InstX86Subss | |
| 1380 : public InstX86BaseBinopXmm<InstX86Base::Subss, false, | |
| 1381 InstX86Base::SseSuffix::Scalar> { | |
| 1382 public: | |
| 1383 static InstX86Subss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1384 return new (Func->allocate<InstX86Subss>()) | |
| 1385 InstX86Subss(Func, Dest, Source); | |
| 1386 } | |
| 1387 | |
| 1388 private: | |
| 1389 InstX86Subss(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1390 : InstX86BaseBinopXmm<InstX86Base::Subss, false, | |
| 1391 InstX86Base::SseSuffix::Scalar>(Func, Dest, | |
| 1392 Source) {} | |
| 1393 }; | |
| 1394 | |
| 1395 class InstX86Sbb : public InstX86BaseBinopGPR<InstX86Base::Sbb> { | |
| 1396 public: | |
| 1397 static InstX86Sbb *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1398 return new (Func->allocate<InstX86Sbb>()) InstX86Sbb(Func, Dest, Source); | |
| 1399 } | |
| 1400 | |
| 1401 private: | |
| 1402 InstX86Sbb(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1403 : InstX86BaseBinopGPR<InstX86Base::Sbb>(Func, Dest, Source) {} | |
| 1404 }; | |
| 1405 | |
| 1406 class InstX86SbbRMW : public InstX86BaseBinopRMW<InstX86Base::SbbRMW> { | |
| 1407 public: | |
| 1408 static InstX86SbbRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | |
| 1409 Operand *Src1) { | |
| 1410 return new (Func->allocate<InstX86SbbRMW>()) | |
| 1411 InstX86SbbRMW(Func, DestSrc0, Src1); | |
| 1412 } | |
| 1413 | |
| 1414 private: | |
| 1415 InstX86SbbRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
| 1416 : InstX86BaseBinopRMW<InstX86Base::SbbRMW>(Func, DestSrc0, Src1) {} | |
| 1417 }; | |
| 1418 | |
| 1419 class InstX86Psub | |
| 1420 : public InstX86BaseBinopXmm<InstX86Base::Psub, true, | |
| 1421 InstX86Base::SseSuffix::Integral> { | |
| 1422 public: | |
| 1423 static InstX86Psub *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1424 return new (Func->allocate<InstX86Psub>()) | |
| 1425 InstX86Psub(Func, Dest, Source); | |
| 1426 } | |
| 1427 | |
| 1428 private: | |
| 1429 InstX86Psub(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1430 : InstX86BaseBinopXmm<InstX86Base::Psub, true, | |
| 1431 InstX86Base::SseSuffix::Integral>(Func, Dest, | |
| 1432 Source) {} | |
| 1433 }; | |
| 1434 | |
| 1435 class InstX86And : public InstX86BaseBinopGPR<InstX86Base::And> { | |
| 1436 public: | |
| 1437 static InstX86And *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1438 return new (Func->allocate<InstX86And>()) InstX86And(Func, Dest, Source); | |
| 1439 } | |
| 1440 | |
| 1441 private: | |
| 1442 InstX86And(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1443 : InstX86BaseBinopGPR<InstX86Base::And>(Func, Dest, Source) {} | |
| 1444 }; | |
| 1445 | |
| 1446 class InstX86Andnps | |
| 1447 : public InstX86BaseBinopXmm<InstX86Base::Andnps, true, | |
| 1448 InstX86Base::SseSuffix::Packed> { | |
| 1449 public: | |
| 1450 static InstX86Andnps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1451 return new (Func->allocate<InstX86Andnps>()) | |
| 1452 InstX86Andnps(Func, Dest, Source); | |
| 1453 } | |
| 1454 | |
| 1455 private: | |
| 1456 InstX86Andnps(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1457 : InstX86BaseBinopXmm<InstX86Base::Andnps, true, | |
| 1458 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
| 1459 Source) {} | |
| 1460 }; | |
| 1461 | |
| 1462 class InstX86Andps | |
| 1463 : public InstX86BaseBinopXmm<InstX86Base::Andps, true, | |
| 1464 InstX86Base::SseSuffix::Packed> { | |
| 1465 public: | |
| 1466 static InstX86Andps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1467 return new (Func->allocate<InstX86Andps>()) | |
| 1468 InstX86Andps(Func, Dest, Source); | |
| 1469 } | |
| 1470 | |
| 1471 private: | |
| 1472 InstX86Andps(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1473 : InstX86BaseBinopXmm<InstX86Base::Andps, true, | |
| 1474 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
| 1475 Source) {} | |
| 1476 }; | |
| 1477 | |
| 1478 class InstX86AndRMW : public InstX86BaseBinopRMW<InstX86Base::AndRMW> { | |
| 1479 public: | |
| 1480 static InstX86AndRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | |
| 1481 Operand *Src1) { | |
| 1482 return new (Func->allocate<InstX86AndRMW>()) | |
| 1483 InstX86AndRMW(Func, DestSrc0, Src1); | |
| 1484 } | |
| 1485 | |
| 1486 private: | |
| 1487 InstX86AndRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
| 1488 : InstX86BaseBinopRMW<InstX86Base::AndRMW>(Func, DestSrc0, Src1) {} | |
| 1489 }; | |
| 1490 | |
| 1491 class InstX86Pand : public InstX86BaseBinopXmm<InstX86Base::Pand, false, | |
| 1492 InstX86Base::SseSuffix::None> { | |
| 1493 public: | |
| 1494 static InstX86Pand *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1495 return new (Func->allocate<InstX86Pand>()) | |
| 1496 InstX86Pand(Func, Dest, Source); | |
| 1497 } | |
| 1498 | |
| 1499 private: | |
| 1500 InstX86Pand(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1501 : InstX86BaseBinopXmm<InstX86Base::Pand, false, | |
| 1502 InstX86Base::SseSuffix::None>(Func, Dest, | |
| 1503 Source) {} | |
| 1504 }; | |
| 1505 | |
| 1506 class InstX86Pandn | |
| 1507 : public InstX86BaseBinopXmm<InstX86Base::Pandn, false, | |
| 1508 InstX86Base::SseSuffix::None> { | |
| 1509 public: | |
| 1510 static InstX86Pandn *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1511 return new (Func->allocate<InstX86Pandn>()) | |
| 1512 InstX86Pandn(Func, Dest, Source); | |
| 1513 } | |
| 1514 | |
| 1515 private: | |
| 1516 InstX86Pandn(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1517 : InstX86BaseBinopXmm<InstX86Base::Pandn, false, | |
| 1518 InstX86Base::SseSuffix::None>(Func, Dest, | |
| 1519 Source) {} | |
| 1520 }; | |
| 1521 | |
| 1522 class InstX86Maxss | |
| 1523 : public InstX86BaseBinopXmm<InstX86Base::Maxss, true, | |
| 1524 InstX86Base::SseSuffix::Scalar> { | |
| 1525 public: | |
| 1526 static InstX86Maxss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1527 return new (Func->allocate<InstX86Maxss>()) | |
| 1528 InstX86Maxss(Func, Dest, Source); | |
| 1529 } | |
| 1530 | |
| 1531 private: | |
| 1532 InstX86Maxss(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1533 : InstX86BaseBinopXmm<InstX86Base::Maxss, true, | |
| 1534 InstX86Base::SseSuffix::Scalar>(Func, Dest, | |
| 1535 Source) {} | |
| 1536 }; | |
| 1537 | |
| 1538 class InstX86Minss | |
| 1539 : public InstX86BaseBinopXmm<InstX86Base::Minss, true, | |
| 1540 InstX86Base::SseSuffix::Scalar> { | |
| 1541 public: | |
| 1542 static InstX86Minss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1543 return new (Func->allocate<InstX86Minss>()) | |
| 1544 InstX86Minss(Func, Dest, Source); | |
| 1545 } | |
| 1546 | |
| 1547 private: | |
| 1548 InstX86Minss(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1549 : InstX86BaseBinopXmm<InstX86Base::Minss, true, | |
| 1550 InstX86Base::SseSuffix::Scalar>(Func, Dest, | |
| 1551 Source) {} | |
| 1552 }; | |
| 1553 | |
| 1554 class InstX86Or : public InstX86BaseBinopGPR<InstX86Base::Or> { | |
| 1555 public: | |
| 1556 static InstX86Or *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1557 return new (Func->allocate<InstX86Or>()) InstX86Or(Func, Dest, Source); | |
| 1558 } | |
| 1559 | |
| 1560 private: | |
| 1561 InstX86Or(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1562 : InstX86BaseBinopGPR<InstX86Base::Or>(Func, Dest, Source) {} | |
| 1563 }; | |
| 1564 | |
| 1565 class InstX86Orps | |
| 1566 : public InstX86BaseBinopXmm<InstX86Base::Orps, true, | |
| 1567 InstX86Base::SseSuffix::Packed> { | |
| 1568 public: | |
| 1569 static InstX86Orps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1570 return new (Func->allocate<InstX86Orps>()) | |
| 1571 InstX86Orps(Func, Dest, Source); | |
| 1572 } | |
| 1573 | |
| 1574 private: | |
| 1575 InstX86Orps(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1576 : InstX86BaseBinopXmm<InstX86Base::Orps, true, | |
| 1577 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
| 1578 Source) {} | |
| 1579 }; | |
| 1580 | |
| 1581 class InstX86OrRMW : public InstX86BaseBinopRMW<InstX86Base::OrRMW> { | |
| 1582 public: | |
| 1583 static InstX86OrRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | |
| 1584 Operand *Src1) { | |
| 1585 return new (Func->allocate<InstX86OrRMW>()) | |
| 1586 InstX86OrRMW(Func, DestSrc0, Src1); | |
| 1587 } | |
| 1588 | |
| 1589 private: | |
| 1590 InstX86OrRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
| 1591 : InstX86BaseBinopRMW<InstX86Base::OrRMW>(Func, DestSrc0, Src1) {} | |
| 1592 }; | |
| 1593 | |
| 1594 class InstX86Por : public InstX86BaseBinopXmm<InstX86Base::Por, false, | |
| 1595 InstX86Base::SseSuffix::None> { | |
| 1596 public: | |
| 1597 static InstX86Por *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1598 return new (Func->allocate<InstX86Por>()) InstX86Por(Func, Dest, Source); | |
| 1599 } | |
| 1600 | |
| 1601 private: | |
| 1602 InstX86Por(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1603 : InstX86BaseBinopXmm<InstX86Base::Por, false, | |
| 1604 InstX86Base::SseSuffix::None>(Func, Dest, | |
| 1605 Source) {} | |
| 1606 }; | |
| 1607 | |
| 1608 class InstX86Xor : public InstX86BaseBinopGPR<InstX86Base::Xor> { | |
| 1609 public: | |
| 1610 static InstX86Xor *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1611 return new (Func->allocate<InstX86Xor>()) InstX86Xor(Func, Dest, Source); | |
| 1612 } | |
| 1613 | |
| 1614 private: | |
| 1615 InstX86Xor(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1616 : InstX86BaseBinopGPR<InstX86Base::Xor>(Func, Dest, Source) {} | |
| 1617 }; | |
| 1618 | |
| 1619 class InstX86Xorps | |
| 1620 : public InstX86BaseBinopXmm<InstX86Base::Xorps, true, | |
| 1621 InstX86Base::SseSuffix::Packed> { | |
| 1622 public: | |
| 1623 static InstX86Xorps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1624 return new (Func->allocate<InstX86Xorps>()) | |
| 1625 InstX86Xorps(Func, Dest, Source); | |
| 1626 } | |
| 1627 | |
| 1628 private: | |
| 1629 InstX86Xorps(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1630 : InstX86BaseBinopXmm<InstX86Base::Xorps, true, | |
| 1631 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
| 1632 Source) {} | |
| 1633 }; | |
| 1634 | |
| 1635 class InstX86XorRMW : public InstX86BaseBinopRMW<InstX86Base::XorRMW> { | |
| 1636 public: | |
| 1637 static InstX86XorRMW *create(Cfg *Func, X86OperandMem *DestSrc0, | |
| 1638 Operand *Src1) { | |
| 1639 return new (Func->allocate<InstX86XorRMW>()) | |
| 1640 InstX86XorRMW(Func, DestSrc0, Src1); | |
| 1641 } | |
| 1642 | |
| 1643 private: | |
| 1644 InstX86XorRMW(Cfg *Func, X86OperandMem *DestSrc0, Operand *Src1) | |
| 1645 : InstX86BaseBinopRMW<InstX86Base::XorRMW>(Func, DestSrc0, Src1) {} | |
| 1646 }; | |
| 1647 | |
| 1648 class InstX86Pxor : public InstX86BaseBinopXmm<InstX86Base::Pxor, false, | |
| 1649 InstX86Base::SseSuffix::None> { | |
| 1650 public: | |
| 1651 static InstX86Pxor *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1652 return new (Func->allocate<InstX86Pxor>()) | |
| 1653 InstX86Pxor(Func, Dest, Source); | |
| 1654 } | |
| 1655 | |
| 1656 private: | |
| 1657 InstX86Pxor(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1658 : InstX86BaseBinopXmm<InstX86Base::Pxor, false, | |
| 1659 InstX86Base::SseSuffix::None>(Func, Dest, | |
| 1660 Source) {} | |
| 1661 }; | |
| 1662 | |
| 1663 class InstX86Imul : public InstX86BaseBinopGPR<InstX86Base::Imul> { | |
| 1664 public: | |
| 1665 static InstX86Imul *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1666 return new (Func->allocate<InstX86Imul>()) | |
| 1667 InstX86Imul(Func, Dest, Source); | |
| 1668 } | |
| 1669 | |
| 1670 void emit(const Cfg *Func) const override; | |
| 1671 void emitIAS(const Cfg *Func) const override; | |
| 1672 | |
| 1673 private: | |
| 1674 InstX86Imul(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1675 : InstX86BaseBinopGPR<InstX86Base::Imul>(Func, Dest, Source) {} | |
| 1676 }; | |
| 1677 | |
| 1678 class InstX86ImulImm | |
| 1679 : public InstX86BaseThreeAddressop<InstX86Base::ImulImm> { | |
| 1680 public: | |
| 1681 static InstX86ImulImm *create(Cfg *Func, Variable *Dest, Operand *Source0, | |
| 1682 Operand *Source1) { | |
| 1683 return new (Func->allocate<InstX86ImulImm>()) | |
| 1684 InstX86ImulImm(Func, Dest, Source0, Source1); | |
| 1685 } | |
| 1686 | |
| 1687 void emit(const Cfg *Func) const override; | |
| 1688 void emitIAS(const Cfg *Func) const override; | |
| 1689 | |
| 1690 private: | |
| 1691 InstX86ImulImm(Cfg *Func, Variable *Dest, Operand *Source0, | |
| 1692 Operand *Source1) | |
| 1693 : InstX86BaseThreeAddressop<InstX86Base::ImulImm>(Func, Dest, Source0, | |
| 1694 Source1) {} | |
| 1695 }; | |
| 1696 | |
| 1697 class InstX86Mulps | |
| 1698 : public InstX86BaseBinopXmm<InstX86Base::Mulps, true, | |
| 1699 InstX86Base::SseSuffix::Packed> { | |
| 1700 public: | |
| 1701 static InstX86Mulps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1702 return new (Func->allocate<InstX86Mulps>()) | |
| 1703 InstX86Mulps(Func, Dest, Source); | |
| 1704 } | |
| 1705 | |
| 1706 private: | |
| 1707 InstX86Mulps(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1708 : InstX86BaseBinopXmm<InstX86Base::Mulps, true, | |
| 1709 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
| 1710 Source) {} | |
| 1711 }; | |
| 1712 | |
| 1713 class InstX86Mulss | |
| 1714 : public InstX86BaseBinopXmm<InstX86Base::Mulss, false, | |
| 1715 InstX86Base::SseSuffix::Scalar> { | |
| 1716 public: | |
| 1717 static InstX86Mulss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1718 return new (Func->allocate<InstX86Mulss>()) | |
| 1719 InstX86Mulss(Func, Dest, Source); | |
| 1720 } | |
| 1721 | |
| 1722 private: | |
| 1723 InstX86Mulss(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1724 : InstX86BaseBinopXmm<InstX86Base::Mulss, false, | |
| 1725 InstX86Base::SseSuffix::Scalar>(Func, Dest, | |
| 1726 Source) {} | |
| 1727 }; | |
| 1728 | |
| 1729 class InstX86Pmull | |
| 1730 : public InstX86BaseBinopXmm<InstX86Base::Pmull, true, | |
| 1731 InstX86Base::SseSuffix::Integral> { | |
| 1732 public: | |
| 1733 static InstX86Pmull *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1734 bool TypesAreValid = | |
| 1735 Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v8i16; | |
| 1736 auto *Target = InstX86Base::getTarget(Func); | |
| 1737 bool InstructionSetIsValid = | |
| 1738 Dest->getType() == IceType_v8i16 || | |
| 1739 Target->getInstructionSet() >= Traits::SSE4_1; | |
| 1740 (void)TypesAreValid; | |
| 1741 (void)InstructionSetIsValid; | |
| 1742 assert(TypesAreValid); | |
| 1743 assert(InstructionSetIsValid); | |
| 1744 return new (Func->allocate<InstX86Pmull>()) | |
| 1745 InstX86Pmull(Func, Dest, Source); | |
| 1746 } | |
| 1747 | |
| 1748 private: | |
| 1749 InstX86Pmull(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1750 : InstX86BaseBinopXmm<InstX86Base::Pmull, true, | |
| 1751 InstX86Base::SseSuffix::Integral>(Func, Dest, | |
| 1752 Source) {} | |
| 1753 }; | |
| 1754 | |
| 1755 class InstX86Pmuludq | |
| 1756 : public InstX86BaseBinopXmm<InstX86Base::Pmuludq, false, | |
| 1757 InstX86Base::SseSuffix::None> { | |
| 1758 public: | |
| 1759 static InstX86Pmuludq *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1760 assert(Dest->getType() == IceType_v4i32 && | |
| 1761 Source->getType() == IceType_v4i32); | |
| 1762 return new (Func->allocate<InstX86Pmuludq>()) | |
| 1763 InstX86Pmuludq(Func, Dest, Source); | |
| 1764 } | |
| 1765 | |
| 1766 private: | |
| 1767 InstX86Pmuludq(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1768 : InstX86BaseBinopXmm<InstX86Base::Pmuludq, false, | |
| 1769 InstX86Base::SseSuffix::None>(Func, Dest, | |
| 1770 Source) {} | |
| 1771 }; | |
| 1772 | |
| 1773 class InstX86Divps | |
| 1774 : public InstX86BaseBinopXmm<InstX86Base::Divps, true, | |
| 1775 InstX86Base::SseSuffix::Packed> { | |
| 1776 public: | |
| 1777 static InstX86Divps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1778 return new (Func->allocate<InstX86Divps>()) | |
| 1779 InstX86Divps(Func, Dest, Source); | |
| 1780 } | |
| 1781 | |
| 1782 private: | |
| 1783 InstX86Divps(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1784 : InstX86BaseBinopXmm<InstX86Base::Divps, true, | |
| 1785 InstX86Base::SseSuffix::Packed>(Func, Dest, | |
| 1786 Source) {} | |
| 1787 }; | |
| 1788 | |
| 1789 class InstX86Divss | |
| 1790 : public InstX86BaseBinopXmm<InstX86Base::Divss, false, | |
| 1791 InstX86Base::SseSuffix::Scalar> { | |
| 1792 public: | |
| 1793 static InstX86Divss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1794 return new (Func->allocate<InstX86Divss>()) | |
| 1795 InstX86Divss(Func, Dest, Source); | |
| 1796 } | |
| 1797 | |
| 1798 private: | |
| 1799 InstX86Divss(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1800 : InstX86BaseBinopXmm<InstX86Base::Divss, false, | |
| 1801 InstX86Base::SseSuffix::Scalar>(Func, Dest, | |
| 1802 Source) {} | |
| 1803 }; | |
| 1804 | |
| 1805 class InstX86Rol : public InstX86BaseBinopGPRShift<InstX86Base::Rol> { | |
| 1806 public: | |
| 1807 static InstX86Rol *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1808 return new (Func->allocate<InstX86Rol>()) InstX86Rol(Func, Dest, Source); | |
| 1809 } | |
| 1810 | |
| 1811 private: | |
| 1812 InstX86Rol(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1813 : InstX86BaseBinopGPRShift<InstX86Base::Rol>(Func, Dest, Source) {} | |
| 1814 }; | |
| 1815 | |
| 1816 class InstX86Shl : public InstX86BaseBinopGPRShift<InstX86Base::Shl> { | |
| 1817 public: | |
| 1818 static InstX86Shl *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1819 return new (Func->allocate<InstX86Shl>()) InstX86Shl(Func, Dest, Source); | |
| 1820 } | |
| 1821 | |
| 1822 private: | |
| 1823 InstX86Shl(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1824 : InstX86BaseBinopGPRShift<InstX86Base::Shl>(Func, Dest, Source) {} | |
| 1825 }; | |
| 1826 | |
| 1827 class InstX86Psll : public InstX86BaseBinopXmmShift<InstX86Base::Psll> { | |
| 1828 public: | |
| 1829 static InstX86Psll *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1830 assert( | |
| 1831 Dest->getType() == IceType_v8i16 || Dest->getType() == IceType_v8i1 || | |
| 1832 Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v4i1); | |
| 1833 return new (Func->allocate<InstX86Psll>()) | |
| 1834 InstX86Psll(Func, Dest, Source); | |
| 1835 } | |
| 1836 | |
| 1837 private: | |
| 1838 InstX86Psll(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1839 : InstX86BaseBinopXmmShift<InstX86Base::Psll>(Func, Dest, Source) {} | |
| 1840 }; | |
| 1841 | |
| 1842 class InstX86Psrl : public InstX86BaseBinopXmmShift<InstX86Base::Psrl, true> { | |
| 1843 public: | |
| 1844 static InstX86Psrl *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1845 return new (Func->allocate<InstX86Psrl>()) | |
| 1846 InstX86Psrl(Func, Dest, Source); | |
| 1847 } | |
| 1848 | |
| 1849 private: | |
| 1850 InstX86Psrl(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1851 : InstX86BaseBinopXmmShift<InstX86Base::Psrl, true>(Func, Dest, | |
| 1852 Source) {} | |
| 1853 }; | |
| 1854 | |
| 1855 class InstX86Shr : public InstX86BaseBinopGPRShift<InstX86Base::Shr> { | |
| 1856 public: | |
| 1857 static InstX86Shr *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1858 return new (Func->allocate<InstX86Shr>()) InstX86Shr(Func, Dest, Source); | |
| 1859 } | |
| 1860 | |
| 1861 private: | |
| 1862 InstX86Shr(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1863 : InstX86BaseBinopGPRShift<InstX86Base::Shr>(Func, Dest, Source) {} | |
| 1864 }; | |
| 1865 | |
| 1866 class InstX86Sar : public InstX86BaseBinopGPRShift<InstX86Base::Sar> { | |
| 1867 public: | |
| 1868 static InstX86Sar *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1869 return new (Func->allocate<InstX86Sar>()) InstX86Sar(Func, Dest, Source); | |
| 1870 } | |
| 1871 | |
| 1872 private: | |
| 1873 InstX86Sar(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1874 : InstX86BaseBinopGPRShift<InstX86Base::Sar>(Func, Dest, Source) {} | |
| 1875 }; | |
| 1876 | |
| 1877 class InstX86Psra : public InstX86BaseBinopXmmShift<InstX86Base::Psra> { | |
| 1878 public: | |
| 1879 static InstX86Psra *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1880 assert( | |
| 1881 Dest->getType() == IceType_v8i16 || Dest->getType() == IceType_v8i1 || | |
| 1882 Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v4i1); | |
| 1883 return new (Func->allocate<InstX86Psra>()) | |
| 1884 InstX86Psra(Func, Dest, Source); | |
| 1885 } | |
| 1886 | |
| 1887 private: | |
| 1888 InstX86Psra(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1889 : InstX86BaseBinopXmmShift<InstX86Base::Psra>(Func, Dest, Source) {} | |
| 1890 }; | |
| 1891 | |
| 1892 class InstX86Pcmpeq | |
| 1893 : public InstX86BaseBinopXmm<InstX86Base::Pcmpeq, true, | |
| 1894 InstX86Base::SseSuffix::Integral> { | |
| 1895 public: | |
| 1896 static InstX86Pcmpeq *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1897 return new (Func->allocate<InstX86Pcmpeq>()) | |
| 1898 InstX86Pcmpeq(Func, Dest, Source); | |
| 1899 } | |
| 1900 | |
| 1901 private: | |
| 1902 InstX86Pcmpeq(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1903 : InstX86BaseBinopXmm<InstX86Base::Pcmpeq, true, | |
| 1904 InstX86Base::SseSuffix::Integral>(Func, Dest, | |
| 1905 Source) {} | |
| 1906 }; | |
| 1907 | |
| 1908 class InstX86Pcmpgt | |
| 1909 : public InstX86BaseBinopXmm<InstX86Base::Pcmpgt, true, | |
| 1910 InstX86Base::SseSuffix::Integral> { | |
| 1911 public: | |
| 1912 static InstX86Pcmpgt *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1913 return new (Func->allocate<InstX86Pcmpgt>()) | |
| 1914 InstX86Pcmpgt(Func, Dest, Source); | |
| 1915 } | |
| 1916 | |
| 1917 private: | |
| 1918 InstX86Pcmpgt(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1919 : InstX86BaseBinopXmm<InstX86Base::Pcmpgt, true, | |
| 1920 InstX86Base::SseSuffix::Integral>(Func, Dest, | |
| 1921 Source) {} | |
| 1922 }; | |
| 1923 | |
| 1924 /// movss is only a binary operation when the source and dest operands are | |
| 1925 /// both registers (the high bits of dest are left untouched). In other cases, | |
| 1926 /// it behaves like a copy (mov-like) operation (and the high bits of dest are | |
| 1927 /// cleared). InstX86Movss will assert that both its source and dest operands | |
| 1928 /// are registers, so the lowering code should use _mov instead of _movss in | |
| 1929 /// cases where a copy operation is intended. | |
| 1930 class InstX86MovssRegs | |
| 1931 : public InstX86BaseBinopXmm<InstX86Base::MovssRegs, false, | |
| 1932 InstX86Base::SseSuffix::None> { | |
| 1933 public: | |
| 1934 static InstX86MovssRegs *create(Cfg *Func, Variable *Dest, | |
| 1935 Operand *Source) { | |
| 1936 return new (Func->allocate<InstX86MovssRegs>()) | |
| 1937 InstX86MovssRegs(Func, Dest, Source); | |
| 1938 } | |
| 1939 | |
| 1940 void emitIAS(const Cfg *Func) const override; | |
| 1941 | |
| 1942 private: | |
| 1943 InstX86MovssRegs(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1944 : InstX86BaseBinopXmm<InstX86Base::MovssRegs, false, | |
| 1945 InstX86Base::SseSuffix::None>(Func, Dest, | |
| 1946 Source) {} | |
| 1947 }; | |
| 1948 | |
| 1949 class InstX86Idiv : public InstX86BaseTernop<InstX86Base::Idiv> { | |
| 1950 public: | |
| 1951 static InstX86Idiv *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
| 1952 Operand *Source2) { | |
| 1953 return new (Func->allocate<InstX86Idiv>()) | |
| 1954 InstX86Idiv(Func, Dest, Source1, Source2); | |
| 1955 } | |
| 1956 | |
| 1957 void emit(const Cfg *Func) const override; | |
| 1958 void emitIAS(const Cfg *Func) const override; | |
| 1959 | |
| 1960 private: | |
| 1961 InstX86Idiv(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | |
| 1962 : InstX86BaseTernop<InstX86Base::Idiv>(Func, Dest, Source1, Source2) {} | |
| 1963 }; | |
| 1964 | |
| 1965 class InstX86Div : public InstX86BaseTernop<InstX86Base::Div> { | |
| 1966 public: | |
| 1967 static InstX86Div *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
| 1968 Operand *Source2) { | |
| 1969 return new (Func->allocate<InstX86Div>()) | |
| 1970 InstX86Div(Func, Dest, Source1, Source2); | |
| 1971 } | |
| 1972 | |
| 1973 void emit(const Cfg *Func) const override; | |
| 1974 void emitIAS(const Cfg *Func) const override; | |
| 1975 | |
| 1976 private: | |
| 1977 InstX86Div(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | |
| 1978 : InstX86BaseTernop<InstX86Base::Div>(Func, Dest, Source1, Source2) {} | |
| 1979 }; | |
| 1980 | |
| 1981 class InstX86Insertps : public InstX86BaseTernop<InstX86Base::Insertps> { | |
| 1982 public: | |
| 1983 static InstX86Insertps *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
| 1984 Operand *Source2) { | |
| 1985 return new (Func->allocate<InstX86Insertps>()) | |
| 1986 InstX86Insertps(Func, Dest, Source1, Source2); | |
| 1987 } | |
| 1988 | |
| 1989 void emitIAS(const Cfg *Func) const override; | |
| 1990 | |
| 1991 private: | |
| 1992 InstX86Insertps(Cfg *Func, Variable *Dest, Operand *Source1, | |
| 919 Operand *Source2) | 1993 Operand *Source2) |
| 920 : InstX86Base<Machine>(Func, K, 3, Dest) { | 1994 : InstX86BaseTernop<InstX86Base::Insertps>(Func, Dest, Source1, |
| 921 this->addSource(Dest); | 1995 Source2) {} |
| 922 this->addSource(Source1); | 1996 }; |
| 923 this->addSource(Source2); | 1997 |
| 924 } | 1998 class InstX86Pinsr : public InstX86BaseTernop<InstX86Base::Pinsr> { |
| 925 | 1999 public: |
| 926 static const char *Opcode; | 2000 static InstX86Pinsr *create(Cfg *Func, Variable *Dest, Operand *Source1, |
| 927 }; | 2001 Operand *Source2) { |
| 928 | 2002 // pinsrb and pinsrd are SSE4.1 instructions. |
| 929 // Instructions of the form x := y op z | 2003 assert( |
| 930 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 2004 Dest->getType() == IceType_v8i16 || Dest->getType() == IceType_v8i1 || |
| 931 class InstX86BaseThreeAddressop : public InstX86Base<Machine> { | 2005 InstX86Base::getTarget(Func)->getInstructionSet() >= Traits::SSE4_1); |
| 932 InstX86BaseThreeAddressop() = delete; | 2006 return new (Func->allocate<InstX86Pinsr>()) |
| 933 InstX86BaseThreeAddressop(const InstX86BaseThreeAddressop &) = delete; | 2007 InstX86Pinsr(Func, Dest, Source1, Source2); |
| 934 InstX86BaseThreeAddressop & | 2008 } |
| 935 operator=(const InstX86BaseThreeAddressop &) = delete; | 2009 |
| 936 | 2010 void emit(const Cfg *Func) const override; |
| 937 public: | 2011 void emitIAS(const Cfg *Func) const override; |
| 938 using Base = InstX86BaseThreeAddressop<Machine, K>; | 2012 |
| 939 | 2013 private: |
| 940 void emit(const Cfg *Func) const override { | 2014 InstX86Pinsr(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) |
| 941 if (!BuildDefs::dump()) | 2015 : InstX86BaseTernop<InstX86Base::Pinsr>(Func, Dest, Source1, Source2) {} |
| 942 return; | 2016 }; |
| 943 Ostream &Str = Func->getContext()->getStrEmit(); | 2017 |
| 944 assert(this->getSrcSize() == 2); | 2018 class InstX86Shufps : public InstX86BaseTernop<InstX86Base::Shufps> { |
| 945 Str << "\t" << Opcode << "\t"; | 2019 public: |
| 946 this->getSrc(1)->emit(Func); | 2020 static InstX86Shufps *create(Cfg *Func, Variable *Dest, Operand *Source1, |
| 947 Str << ", "; | 2021 Operand *Source2) { |
| 948 this->getSrc(0)->emit(Func); | 2022 return new (Func->allocate<InstX86Shufps>()) |
| 949 Str << ", "; | 2023 InstX86Shufps(Func, Dest, Source1, Source2); |
| 950 this->getDest()->emit(Func); | 2024 } |
| 951 } | 2025 |
| 952 void dump(const Cfg *Func) const override { | 2026 void emitIAS(const Cfg *Func) const override; |
| 953 if (!BuildDefs::dump()) | 2027 |
| 954 return; | 2028 private: |
| 955 Ostream &Str = Func->getContext()->getStrDump(); | 2029 InstX86Shufps(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) |
| 956 this->dumpDest(Func); | 2030 : InstX86BaseTernop<InstX86Base::Shufps>(Func, Dest, Source1, Source2) { |
| 957 Str << " = " << Opcode << "." << this->getDest()->getType() << " "; | 2031 } |
| 958 this->dumpSources(Func); | 2032 }; |
| 959 } | 2033 |
| 960 static bool classof(const Inst *Inst) { | 2034 class InstX86Blendvps : public InstX86BaseTernop<InstX86Base::Blendvps> { |
| 961 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | 2035 public: |
| 962 } | 2036 static InstX86Blendvps *create(Cfg *Func, Variable *Dest, Operand *Source1, |
| 963 | 2037 Operand *Source2) { |
| 964 protected: | 2038 assert(InstX86Base::getTarget(Func)->getInstructionSet() >= |
| 965 InstX86BaseThreeAddressop(Cfg *Func, Variable *Dest, Operand *Source0, | 2039 Traits::SSE4_1); |
| 966 Operand *Source1) | 2040 return new (Func->allocate<InstX86Blendvps>()) |
| 967 : InstX86Base<Machine>(Func, K, 2, Dest) { | 2041 InstX86Blendvps(Func, Dest, Source1, Source2); |
| 968 this->addSource(Source0); | 2042 } |
| 969 this->addSource(Source1); | 2043 |
| 970 } | 2044 void emit(const Cfg *Func) const override; |
| 971 | 2045 void emitIAS(const Cfg *Fund) const override; |
| 972 static const char *Opcode; | 2046 |
| 973 }; | 2047 private: |
| 974 | 2048 InstX86Blendvps(Cfg *Func, Variable *Dest, Operand *Source1, |
| 975 /// Base class for assignment instructions | 2049 Operand *Source2) |
| 976 template <class Machine, typename InstX86Base<Machine>::InstKindX86 K> | 2050 : InstX86BaseTernop<InstX86Base::Blendvps>(Func, Dest, Source1, |
| 977 class InstX86BaseMovlike : public InstX86Base<Machine> { | 2051 Source2) {} |
| 978 InstX86BaseMovlike() = delete; | 2052 }; |
| 979 InstX86BaseMovlike(const InstX86BaseMovlike &) = delete; | 2053 |
| 980 InstX86BaseMovlike &operator=(const InstX86BaseMovlike &) = delete; | 2054 class InstX86Pblendvb : public InstX86BaseTernop<InstX86Base::Pblendvb> { |
| 981 | 2055 public: |
| 982 public: | 2056 static InstX86Pblendvb *create(Cfg *Func, Variable *Dest, Operand *Source1, |
| 983 using Base = InstX86BaseMovlike<Machine, K>; | 2057 Operand *Source2) { |
| 984 | 2058 assert(InstX86Base::getTarget(Func)->getInstructionSet() >= |
| 985 bool isRedundantAssign() const override { | 2059 Traits::SSE4_1); |
| 986 if (const auto *SrcVar = llvm::dyn_cast<const Variable>(this->getSrc(0))) { | 2060 return new (Func->allocate<InstX86Pblendvb>()) |
| 987 if (SrcVar->hasReg() && this->Dest->hasReg()) { | 2061 InstX86Pblendvb(Func, Dest, Source1, Source2); |
| 988 // An assignment between physical registers is considered redundant if | 2062 } |
| 989 // they have the same base register and the same encoding. E.g.: | 2063 |
| 990 // mov cl, ecx ==> redundant | 2064 void emit(const Cfg *Func) const override; |
| 991 // mov ch, ecx ==> not redundant due to different encodings | 2065 void emitIAS(const Cfg *Func) const override; |
| 992 // mov ch, ebp ==> not redundant due to different base registers | 2066 |
| 993 // mov ecx, ecx ==> redundant, and dangerous in x86-64. i64 zexting | 2067 private: |
| 994 // is handled by Inst86Zext. | 2068 InstX86Pblendvb(Cfg *Func, Variable *Dest, Operand *Source1, |
| 995 const int32_t SrcReg = SrcVar->getRegNum(); | 2069 Operand *Source2) |
| 996 const int32_t DestReg = this->Dest->getRegNum(); | 2070 : InstX86BaseTernop<InstX86Base::Pblendvb>(Func, Dest, Source1, |
| 997 return (InstX86Base<Machine>::Traits::getEncoding(SrcReg) == | 2071 Source2) {} |
| 998 InstX86Base<Machine>::Traits::getEncoding(DestReg)) && | 2072 }; |
| 999 (InstX86Base<Machine>::Traits::getBaseReg(SrcReg) == | 2073 |
| 1000 InstX86Base<Machine>::Traits::getBaseReg(DestReg)); | 2074 class InstX86Pextr : public InstX86BaseThreeAddressop<InstX86Base::Pextr> { |
| 1001 } | 2075 public: |
| 1002 } | 2076 static InstX86Pextr *create(Cfg *Func, Variable *Dest, Operand *Source0, |
| 1003 return checkForRedundantAssign(this->getDest(), this->getSrc(0)); | |
| 1004 } | |
| 1005 bool isVarAssign() const override { | |
| 1006 return llvm::isa<Variable>(this->getSrc(0)); | |
| 1007 } | |
| 1008 void dump(const Cfg *Func) const override { | |
| 1009 if (!BuildDefs::dump()) | |
| 1010 return; | |
| 1011 Ostream &Str = Func->getContext()->getStrDump(); | |
| 1012 Str << Opcode << "." << this->getDest()->getType() << " "; | |
| 1013 this->dumpDest(Func); | |
| 1014 Str << ", "; | |
| 1015 this->dumpSources(Func); | |
| 1016 } | |
| 1017 static bool classof(const Inst *Inst) { | |
| 1018 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::K); | |
| 1019 } | |
| 1020 | |
| 1021 protected: | |
| 1022 InstX86BaseMovlike(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1023 : InstX86Base<Machine>(Func, K, 1, Dest) { | |
| 1024 this->addSource(Source); | |
| 1025 // For an integer assignment, make sure it's either a same-type assignment | |
| 1026 // or a truncation. | |
| 1027 assert(!isScalarIntegerType(Dest->getType()) || | |
| 1028 (typeWidthInBytes(Dest->getType()) <= | |
| 1029 typeWidthInBytes(Source->getType()))); | |
| 1030 } | |
| 1031 | |
| 1032 static const char *Opcode; | |
| 1033 }; | |
| 1034 | |
| 1035 template <class Machine> | |
| 1036 class InstX86Bswap | |
| 1037 : public InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Bswap> { | |
| 1038 public: | |
| 1039 static InstX86Bswap *create(Cfg *Func, Operand *SrcDest) { | |
| 1040 return new (Func->allocate<InstX86Bswap>()) InstX86Bswap(Func, SrcDest); | |
| 1041 } | |
| 1042 | |
| 1043 private: | |
| 1044 InstX86Bswap(Cfg *Func, Operand *SrcDest) | |
| 1045 : InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Bswap>(Func, | |
| 1046 SrcDest) { | |
| 1047 } | |
| 1048 }; | |
| 1049 | |
| 1050 template <class Machine> | |
| 1051 class InstX86Neg | |
| 1052 : public InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Neg> { | |
| 1053 public: | |
| 1054 static InstX86Neg *create(Cfg *Func, Operand *SrcDest) { | |
| 1055 return new (Func->allocate<InstX86Neg>()) InstX86Neg(Func, SrcDest); | |
| 1056 } | |
| 1057 | |
| 1058 private: | |
| 1059 InstX86Neg(Cfg *Func, Operand *SrcDest) | |
| 1060 : InstX86BaseInplaceopGPR<Machine, InstX86Base<Machine>::Neg>(Func, | |
| 1061 SrcDest) {} | |
| 1062 }; | |
| 1063 | |
| 1064 template <class Machine> | |
| 1065 class InstX86Bsf | |
| 1066 : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsf> { | |
| 1067 public: | |
| 1068 static InstX86Bsf *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1069 return new (Func->allocate<InstX86Bsf>()) InstX86Bsf(Func, Dest, Src); | |
| 1070 } | |
| 1071 | |
| 1072 private: | |
| 1073 InstX86Bsf(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1074 : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsf>(Func, Dest, | |
| 1075 Src) {} | |
| 1076 }; | |
| 1077 | |
| 1078 template <class Machine> | |
| 1079 class InstX86Bsr | |
| 1080 : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsr> { | |
| 1081 public: | |
| 1082 static InstX86Bsr *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1083 return new (Func->allocate<InstX86Bsr>()) InstX86Bsr(Func, Dest, Src); | |
| 1084 } | |
| 1085 | |
| 1086 private: | |
| 1087 InstX86Bsr(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1088 : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Bsr>(Func, Dest, | |
| 1089 Src) {} | |
| 1090 }; | |
| 1091 | |
| 1092 template <class Machine> | |
| 1093 class InstX86Lea | |
| 1094 : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Lea> { | |
| 1095 public: | |
| 1096 static InstX86Lea *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1097 return new (Func->allocate<InstX86Lea>()) InstX86Lea(Func, Dest, Src); | |
| 1098 } | |
| 1099 | |
| 1100 void emit(const Cfg *Func) const override; | |
| 1101 | |
| 1102 private: | |
| 1103 InstX86Lea(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1104 : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Lea>(Func, Dest, | |
| 1105 Src) {} | |
| 1106 }; | |
| 1107 | |
| 1108 // Cbwdq instruction - wrapper for cbw, cwd, and cdq | |
| 1109 template <class Machine> | |
| 1110 class InstX86Cbwdq | |
| 1111 : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Cbwdq> { | |
| 1112 public: | |
| 1113 static InstX86Cbwdq *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1114 return new (Func->allocate<InstX86Cbwdq>()) InstX86Cbwdq(Func, Dest, Src); | |
| 1115 } | |
| 1116 | |
| 1117 void emit(const Cfg *Func) const override; | |
| 1118 void emitIAS(const Cfg *Func) const override; | |
| 1119 | |
| 1120 private: | |
| 1121 InstX86Cbwdq(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1122 : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Cbwdq>(Func, Dest, | |
| 1123 Src) {} | |
| 1124 }; | |
| 1125 | |
| 1126 template <class Machine> | |
| 1127 class InstX86Movsx | |
| 1128 : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movsx> { | |
| 1129 public: | |
| 1130 static InstX86Movsx *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1131 assert(typeWidthInBytes(Dest->getType()) > | |
| 1132 typeWidthInBytes(Src->getType())); | |
| 1133 return new (Func->allocate<InstX86Movsx>()) InstX86Movsx(Func, Dest, Src); | |
| 1134 } | |
| 1135 | |
| 1136 void emitIAS(const Cfg *Func) const override; | |
| 1137 | |
| 1138 private: | |
| 1139 InstX86Movsx(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1140 : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movsx>(Func, Dest, | |
| 1141 Src) {} | |
| 1142 }; | |
| 1143 | |
| 1144 template <class Machine> | |
| 1145 class InstX86Movzx | |
| 1146 : public InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movzx> { | |
| 1147 public: | |
| 1148 static InstX86Movzx *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1149 assert(typeWidthInBytes(Dest->getType()) > | |
| 1150 typeWidthInBytes(Src->getType())); | |
| 1151 return new (Func->allocate<InstX86Movzx>()) InstX86Movzx(Func, Dest, Src); | |
| 1152 } | |
| 1153 | |
| 1154 void emit(const Cfg *Func) const override; | |
| 1155 | |
| 1156 void emitIAS(const Cfg *Func) const override; | |
| 1157 | |
| 1158 private: | |
| 1159 InstX86Movzx(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1160 : InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movzx>(Func, Dest, | |
| 1161 Src) {} | |
| 1162 }; | |
| 1163 | |
| 1164 template <class Machine> | |
| 1165 class InstX86Movd | |
| 1166 : public InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Movd> { | |
| 1167 public: | |
| 1168 static InstX86Movd *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1169 return new (Func->allocate<InstX86Movd>()) InstX86Movd(Func, Dest, Src); | |
| 1170 } | |
| 1171 | |
| 1172 void emit(const Cfg *Func) const override; | |
| 1173 | |
| 1174 void emitIAS(const Cfg *Func) const override; | |
| 1175 | |
| 1176 private: | |
| 1177 InstX86Movd(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1178 : InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Movd>(Func, Dest, | |
| 1179 Src) {} | |
| 1180 }; | |
| 1181 | |
| 1182 template <class Machine> | |
| 1183 class InstX86Sqrtss | |
| 1184 : public InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Sqrtss> { | |
| 1185 public: | |
| 1186 static InstX86Sqrtss *create(Cfg *Func, Variable *Dest, Operand *Src) { | |
| 1187 return new (Func->allocate<InstX86Sqrtss>()) InstX86Sqrtss(Func, Dest, Src); | |
| 1188 } | |
| 1189 | |
| 1190 virtual void emit(const Cfg *Func) const override; | |
| 1191 | |
| 1192 private: | |
| 1193 InstX86Sqrtss(Cfg *Func, Variable *Dest, Operand *Src) | |
| 1194 : InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Sqrtss>(Func, Dest, | |
| 1195 Src) {} | |
| 1196 }; | |
| 1197 | |
| 1198 /// Move/assignment instruction - wrapper for mov/movss/movsd. | |
| 1199 template <class Machine> | |
| 1200 class InstX86Mov | |
| 1201 : public InstX86BaseMovlike<Machine, InstX86Base<Machine>::Mov> { | |
| 1202 public: | |
| 1203 static InstX86Mov *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1204 assert(!isScalarIntegerType(Dest->getType()) || | |
| 1205 (typeWidthInBytes(Dest->getType()) <= | |
| 1206 typeWidthInBytes(Source->getType()))); | |
| 1207 return new (Func->allocate<InstX86Mov>()) InstX86Mov(Func, Dest, Source); | |
| 1208 } | |
| 1209 | |
| 1210 void emit(const Cfg *Func) const override; | |
| 1211 void emitIAS(const Cfg *Func) const override; | |
| 1212 | |
| 1213 private: | |
| 1214 InstX86Mov(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1215 : InstX86BaseMovlike<Machine, InstX86Base<Machine>::Mov>(Func, Dest, | |
| 1216 Source) {} | |
| 1217 }; | |
| 1218 | |
| 1219 /// Move packed - copy 128 bit values between XMM registers, or mem128 and XMM | |
| 1220 /// registers. | |
| 1221 template <class Machine> | |
| 1222 class InstX86Movp | |
| 1223 : public InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movp> { | |
| 1224 public: | |
| 1225 static InstX86Movp *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1226 return new (Func->allocate<InstX86Movp>()) InstX86Movp(Func, Dest, Source); | |
| 1227 } | |
| 1228 | |
| 1229 void emit(const Cfg *Func) const override; | |
| 1230 void emitIAS(const Cfg *Func) const override; | |
| 1231 | |
| 1232 private: | |
| 1233 InstX86Movp(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1234 : InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movp>(Func, Dest, | |
| 1235 Source) {} | |
| 1236 }; | |
| 1237 | |
| 1238 /// Movq - copy between XMM registers, or mem64 and XMM registers. | |
| 1239 template <class Machine> | |
| 1240 class InstX86Movq | |
| 1241 : public InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movq> { | |
| 1242 public: | |
| 1243 static InstX86Movq *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1244 return new (Func->allocate<InstX86Movq>()) InstX86Movq(Func, Dest, Source); | |
| 1245 } | |
| 1246 | |
| 1247 void emit(const Cfg *Func) const override; | |
| 1248 void emitIAS(const Cfg *Func) const override; | |
| 1249 | |
| 1250 private: | |
| 1251 InstX86Movq(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1252 : InstX86BaseMovlike<Machine, InstX86Base<Machine>::Movq>(Func, Dest, | |
| 1253 Source) {} | |
| 1254 }; | |
| 1255 | |
| 1256 template <class Machine> | |
| 1257 class InstX86Add | |
| 1258 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Add> { | |
| 1259 public: | |
| 1260 static InstX86Add *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1261 return new (Func->allocate<InstX86Add>()) InstX86Add(Func, Dest, Source); | |
| 1262 } | |
| 1263 | |
| 1264 private: | |
| 1265 InstX86Add(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1266 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Add>(Func, Dest, | |
| 1267 Source) {} | |
| 1268 }; | |
| 1269 | |
| 1270 template <class Machine> | |
| 1271 class InstX86AddRMW | |
| 1272 : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AddRMW> { | |
| 1273 public: | |
| 1274 static InstX86AddRMW * | |
| 1275 create(Cfg *Func, | |
| 1276 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
| 1277 Operand *Src1) { | |
| 1278 return new (Func->allocate<InstX86AddRMW>()) | |
| 1279 InstX86AddRMW(Func, DestSrc0, Src1); | |
| 1280 } | |
| 1281 | |
| 1282 private: | |
| 1283 InstX86AddRMW(Cfg *Func, | |
| 1284 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
| 1285 Operand *Src1) | |
| 1286 : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AddRMW>( | |
| 1287 Func, DestSrc0, Src1) {} | |
| 1288 }; | |
| 1289 | |
| 1290 template <class Machine> | |
| 1291 class InstX86Addps | |
| 1292 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addps, true, | |
| 1293 InstX86Base<Machine>::SseSuffix::Packed> { | |
| 1294 public: | |
| 1295 static InstX86Addps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1296 return new (Func->allocate<InstX86Addps>()) | |
| 1297 InstX86Addps(Func, Dest, Source); | |
| 1298 } | |
| 1299 | |
| 1300 private: | |
| 1301 InstX86Addps(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1302 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addps, true, | |
| 1303 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | |
| 1304 Source) {} | |
| 1305 }; | |
| 1306 | |
| 1307 template <class Machine> | |
| 1308 class InstX86Adc | |
| 1309 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Adc> { | |
| 1310 public: | |
| 1311 static InstX86Adc *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1312 return new (Func->allocate<InstX86Adc>()) InstX86Adc(Func, Dest, Source); | |
| 1313 } | |
| 1314 | |
| 1315 private: | |
| 1316 InstX86Adc(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1317 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Adc>(Func, Dest, | |
| 1318 Source) {} | |
| 1319 }; | |
| 1320 | |
| 1321 template <class Machine> | |
| 1322 class InstX86AdcRMW | |
| 1323 : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AdcRMW> { | |
| 1324 public: | |
| 1325 static InstX86AdcRMW * | |
| 1326 create(Cfg *Func, | |
| 1327 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
| 1328 Operand *Src1) { | |
| 1329 return new (Func->allocate<InstX86AdcRMW>()) | |
| 1330 InstX86AdcRMW(Func, DestSrc0, Src1); | |
| 1331 } | |
| 1332 | |
| 1333 private: | |
| 1334 InstX86AdcRMW(Cfg *Func, | |
| 1335 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
| 1336 Operand *Src1) | |
| 1337 : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AdcRMW>( | |
| 1338 Func, DestSrc0, Src1) {} | |
| 1339 }; | |
| 1340 | |
| 1341 template <class Machine> | |
| 1342 class InstX86Addss | |
| 1343 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addss, false, | |
| 1344 InstX86Base<Machine>::SseSuffix::Scalar> { | |
| 1345 public: | |
| 1346 static InstX86Addss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1347 return new (Func->allocate<InstX86Addss>()) | |
| 1348 InstX86Addss(Func, Dest, Source); | |
| 1349 } | |
| 1350 | |
| 1351 private: | |
| 1352 InstX86Addss(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1353 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Addss, false, | |
| 1354 InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | |
| 1355 Source) {} | |
| 1356 }; | |
| 1357 | |
| 1358 template <class Machine> | |
| 1359 class InstX86Padd | |
| 1360 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Padd, true, | |
| 1361 InstX86Base<Machine>::SseSuffix::Integral> { | |
| 1362 public: | |
| 1363 static InstX86Padd *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1364 return new (Func->allocate<InstX86Padd>()) InstX86Padd(Func, Dest, Source); | |
| 1365 } | |
| 1366 | |
| 1367 private: | |
| 1368 InstX86Padd(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1369 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Padd, true, | |
| 1370 InstX86Base<Machine>::SseSuffix::Integral>( | |
| 1371 Func, Dest, Source) {} | |
| 1372 }; | |
| 1373 | |
| 1374 template <class Machine> | |
| 1375 class InstX86Sub | |
| 1376 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sub> { | |
| 1377 public: | |
| 1378 static InstX86Sub *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1379 return new (Func->allocate<InstX86Sub>()) InstX86Sub(Func, Dest, Source); | |
| 1380 } | |
| 1381 | |
| 1382 private: | |
| 1383 InstX86Sub(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1384 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sub>(Func, Dest, | |
| 1385 Source) {} | |
| 1386 }; | |
| 1387 | |
| 1388 template <class Machine> | |
| 1389 class InstX86SubRMW | |
| 1390 : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SubRMW> { | |
| 1391 public: | |
| 1392 static InstX86SubRMW * | |
| 1393 create(Cfg *Func, | |
| 1394 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
| 1395 Operand *Src1) { | |
| 1396 return new (Func->allocate<InstX86SubRMW>()) | |
| 1397 InstX86SubRMW(Func, DestSrc0, Src1); | |
| 1398 } | |
| 1399 | |
| 1400 private: | |
| 1401 InstX86SubRMW(Cfg *Func, | |
| 1402 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
| 1403 Operand *Src1) | |
| 1404 : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SubRMW>( | |
| 1405 Func, DestSrc0, Src1) {} | |
| 1406 }; | |
| 1407 | |
| 1408 template <class Machine> | |
| 1409 class InstX86Subps | |
| 1410 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subps, true, | |
| 1411 InstX86Base<Machine>::SseSuffix::Packed> { | |
| 1412 public: | |
| 1413 static InstX86Subps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1414 return new (Func->allocate<InstX86Subps>()) | |
| 1415 InstX86Subps(Func, Dest, Source); | |
| 1416 } | |
| 1417 | |
| 1418 private: | |
| 1419 InstX86Subps(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1420 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subps, true, | |
| 1421 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | |
| 1422 Source) {} | |
| 1423 }; | |
| 1424 | |
| 1425 template <class Machine> | |
| 1426 class InstX86Subss | |
| 1427 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subss, false, | |
| 1428 InstX86Base<Machine>::SseSuffix::Scalar> { | |
| 1429 public: | |
| 1430 static InstX86Subss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1431 return new (Func->allocate<InstX86Subss>()) | |
| 1432 InstX86Subss(Func, Dest, Source); | |
| 1433 } | |
| 1434 | |
| 1435 private: | |
| 1436 InstX86Subss(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1437 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Subss, false, | |
| 1438 InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | |
| 1439 Source) {} | |
| 1440 }; | |
| 1441 | |
| 1442 template <class Machine> | |
| 1443 class InstX86Sbb | |
| 1444 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sbb> { | |
| 1445 public: | |
| 1446 static InstX86Sbb *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1447 return new (Func->allocate<InstX86Sbb>()) InstX86Sbb(Func, Dest, Source); | |
| 1448 } | |
| 1449 | |
| 1450 private: | |
| 1451 InstX86Sbb(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1452 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Sbb>(Func, Dest, | |
| 1453 Source) {} | |
| 1454 }; | |
| 1455 | |
| 1456 template <class Machine> | |
| 1457 class InstX86SbbRMW | |
| 1458 : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SbbRMW> { | |
| 1459 public: | |
| 1460 static InstX86SbbRMW * | |
| 1461 create(Cfg *Func, | |
| 1462 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
| 1463 Operand *Src1) { | |
| 1464 return new (Func->allocate<InstX86SbbRMW>()) | |
| 1465 InstX86SbbRMW(Func, DestSrc0, Src1); | |
| 1466 } | |
| 1467 | |
| 1468 private: | |
| 1469 InstX86SbbRMW(Cfg *Func, | |
| 1470 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
| 1471 Operand *Src1) | |
| 1472 : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::SbbRMW>( | |
| 1473 Func, DestSrc0, Src1) {} | |
| 1474 }; | |
| 1475 | |
| 1476 template <class Machine> | |
| 1477 class InstX86Psub | |
| 1478 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Psub, true, | |
| 1479 InstX86Base<Machine>::SseSuffix::Integral> { | |
| 1480 public: | |
| 1481 static InstX86Psub *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1482 return new (Func->allocate<InstX86Psub>()) InstX86Psub(Func, Dest, Source); | |
| 1483 } | |
| 1484 | |
| 1485 private: | |
| 1486 InstX86Psub(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1487 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Psub, true, | |
| 1488 InstX86Base<Machine>::SseSuffix::Integral>( | |
| 1489 Func, Dest, Source) {} | |
| 1490 }; | |
| 1491 | |
| 1492 template <class Machine> | |
| 1493 class InstX86And | |
| 1494 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::And> { | |
| 1495 public: | |
| 1496 static InstX86And *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1497 return new (Func->allocate<InstX86And>()) InstX86And(Func, Dest, Source); | |
| 1498 } | |
| 1499 | |
| 1500 private: | |
| 1501 InstX86And(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1502 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::And>(Func, Dest, | |
| 1503 Source) {} | |
| 1504 }; | |
| 1505 | |
| 1506 template <class Machine> | |
| 1507 class InstX86Andnps | |
| 1508 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Andnps, true, | |
| 1509 InstX86Base<Machine>::SseSuffix::Packed> { | |
| 1510 public: | |
| 1511 static InstX86Andnps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1512 return new (Func->allocate<InstX86Andnps>()) | |
| 1513 InstX86Andnps(Func, Dest, Source); | |
| 1514 } | |
| 1515 | |
| 1516 private: | |
| 1517 InstX86Andnps(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1518 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Andnps, true, | |
| 1519 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | |
| 1520 Source) {} | |
| 1521 }; | |
| 1522 | |
| 1523 template <class Machine> | |
| 1524 class InstX86Andps | |
| 1525 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Andps, true, | |
| 1526 InstX86Base<Machine>::SseSuffix::Packed> { | |
| 1527 public: | |
| 1528 static InstX86Andps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1529 return new (Func->allocate<InstX86Andps>()) | |
| 1530 InstX86Andps(Func, Dest, Source); | |
| 1531 } | |
| 1532 | |
| 1533 private: | |
| 1534 InstX86Andps(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1535 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Andps, true, | |
| 1536 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | |
| 1537 Source) {} | |
| 1538 }; | |
| 1539 | |
| 1540 template <class Machine> | |
| 1541 class InstX86AndRMW | |
| 1542 : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AndRMW> { | |
| 1543 public: | |
| 1544 static InstX86AndRMW * | |
| 1545 create(Cfg *Func, | |
| 1546 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
| 1547 Operand *Src1) { | |
| 1548 return new (Func->allocate<InstX86AndRMW>()) | |
| 1549 InstX86AndRMW(Func, DestSrc0, Src1); | |
| 1550 } | |
| 1551 | |
| 1552 private: | |
| 1553 InstX86AndRMW(Cfg *Func, | |
| 1554 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
| 1555 Operand *Src1) | |
| 1556 : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::AndRMW>( | |
| 1557 Func, DestSrc0, Src1) {} | |
| 1558 }; | |
| 1559 | |
| 1560 template <class Machine> | |
| 1561 class InstX86Pand | |
| 1562 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pand, false, | |
| 1563 InstX86Base<Machine>::SseSuffix::None> { | |
| 1564 public: | |
| 1565 static InstX86Pand *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1566 return new (Func->allocate<InstX86Pand>()) InstX86Pand(Func, Dest, Source); | |
| 1567 } | |
| 1568 | |
| 1569 private: | |
| 1570 InstX86Pand(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1571 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pand, false, | |
| 1572 InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | |
| 1573 Source) {} | |
| 1574 }; | |
| 1575 | |
| 1576 template <class Machine> | |
| 1577 class InstX86Pandn | |
| 1578 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pandn, false, | |
| 1579 InstX86Base<Machine>::SseSuffix::None> { | |
| 1580 public: | |
| 1581 static InstX86Pandn *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1582 return new (Func->allocate<InstX86Pandn>()) | |
| 1583 InstX86Pandn(Func, Dest, Source); | |
| 1584 } | |
| 1585 | |
| 1586 private: | |
| 1587 InstX86Pandn(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1588 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pandn, false, | |
| 1589 InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | |
| 1590 Source) {} | |
| 1591 }; | |
| 1592 | |
| 1593 template <class Machine> | |
| 1594 class InstX86Maxss | |
| 1595 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Maxss, true, | |
| 1596 InstX86Base<Machine>::SseSuffix::Scalar> { | |
| 1597 public: | |
| 1598 static InstX86Maxss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1599 return new (Func->allocate<InstX86Maxss>()) | |
| 1600 InstX86Maxss(Func, Dest, Source); | |
| 1601 } | |
| 1602 | |
| 1603 private: | |
| 1604 InstX86Maxss(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1605 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Maxss, true, | |
| 1606 InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | |
| 1607 Source) {} | |
| 1608 }; | |
| 1609 | |
| 1610 template <class Machine> | |
| 1611 class InstX86Minss | |
| 1612 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Minss, true, | |
| 1613 InstX86Base<Machine>::SseSuffix::Scalar> { | |
| 1614 public: | |
| 1615 static InstX86Minss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1616 return new (Func->allocate<InstX86Minss>()) | |
| 1617 InstX86Minss(Func, Dest, Source); | |
| 1618 } | |
| 1619 | |
| 1620 private: | |
| 1621 InstX86Minss(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1622 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Minss, true, | |
| 1623 InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | |
| 1624 Source) {} | |
| 1625 }; | |
| 1626 | |
| 1627 template <class Machine> | |
| 1628 class InstX86Or | |
| 1629 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Or> { | |
| 1630 public: | |
| 1631 static InstX86Or *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1632 return new (Func->allocate<InstX86Or>()) InstX86Or(Func, Dest, Source); | |
| 1633 } | |
| 1634 | |
| 1635 private: | |
| 1636 InstX86Or(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1637 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Or>(Func, Dest, | |
| 1638 Source) {} | |
| 1639 }; | |
| 1640 | |
| 1641 template <class Machine> | |
| 1642 class InstX86Orps | |
| 1643 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Orps, true, | |
| 1644 InstX86Base<Machine>::SseSuffix::Packed> { | |
| 1645 public: | |
| 1646 static InstX86Orps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1647 return new (Func->allocate<InstX86Orps>()) InstX86Orps(Func, Dest, Source); | |
| 1648 } | |
| 1649 | |
| 1650 private: | |
| 1651 InstX86Orps(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1652 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Orps, true, | |
| 1653 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | |
| 1654 Source) {} | |
| 1655 }; | |
| 1656 | |
| 1657 template <class Machine> | |
| 1658 class InstX86OrRMW | |
| 1659 : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::OrRMW> { | |
| 1660 public: | |
| 1661 static InstX86OrRMW * | |
| 1662 create(Cfg *Func, | |
| 1663 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
| 1664 Operand *Src1) { | |
| 1665 return new (Func->allocate<InstX86OrRMW>()) | |
| 1666 InstX86OrRMW(Func, DestSrc0, Src1); | |
| 1667 } | |
| 1668 | |
| 1669 private: | |
| 1670 InstX86OrRMW(Cfg *Func, | |
| 1671 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
| 1672 Operand *Src1) | |
| 1673 : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::OrRMW>( | |
| 1674 Func, DestSrc0, Src1) {} | |
| 1675 }; | |
| 1676 | |
| 1677 template <class Machine> | |
| 1678 class InstX86Por | |
| 1679 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Por, false, | |
| 1680 InstX86Base<Machine>::SseSuffix::None> { | |
| 1681 public: | |
| 1682 static InstX86Por *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1683 return new (Func->allocate<InstX86Por>()) InstX86Por(Func, Dest, Source); | |
| 1684 } | |
| 1685 | |
| 1686 private: | |
| 1687 InstX86Por(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1688 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Por, false, | |
| 1689 InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | |
| 1690 Source) {} | |
| 1691 }; | |
| 1692 | |
| 1693 template <class Machine> | |
| 1694 class InstX86Xor | |
| 1695 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Xor> { | |
| 1696 public: | |
| 1697 static InstX86Xor *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1698 return new (Func->allocate<InstX86Xor>()) InstX86Xor(Func, Dest, Source); | |
| 1699 } | |
| 1700 | |
| 1701 private: | |
| 1702 InstX86Xor(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1703 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Xor>(Func, Dest, | |
| 1704 Source) {} | |
| 1705 }; | |
| 1706 | |
| 1707 template <class Machine> | |
| 1708 class InstX86Xorps | |
| 1709 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Xorps, true, | |
| 1710 InstX86Base<Machine>::SseSuffix::Packed> { | |
| 1711 public: | |
| 1712 static InstX86Xorps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1713 return new (Func->allocate<InstX86Xorps>()) | |
| 1714 InstX86Xorps(Func, Dest, Source); | |
| 1715 } | |
| 1716 | |
| 1717 private: | |
| 1718 InstX86Xorps(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1719 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Xorps, true, | |
| 1720 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | |
| 1721 Source) {} | |
| 1722 }; | |
| 1723 | |
| 1724 template <class Machine> | |
| 1725 class InstX86XorRMW | |
| 1726 : public InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::XorRMW> { | |
| 1727 public: | |
| 1728 static InstX86XorRMW * | |
| 1729 create(Cfg *Func, | |
| 1730 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
| 1731 Operand *Src1) { | |
| 1732 return new (Func->allocate<InstX86XorRMW>()) | |
| 1733 InstX86XorRMW(Func, DestSrc0, Src1); | |
| 1734 } | |
| 1735 | |
| 1736 private: | |
| 1737 InstX86XorRMW(Cfg *Func, | |
| 1738 typename InstX86Base<Machine>::Traits::X86OperandMem *DestSrc0, | |
| 1739 Operand *Src1) | |
| 1740 : InstX86BaseBinopRMW<Machine, InstX86Base<Machine>::XorRMW>( | |
| 1741 Func, DestSrc0, Src1) {} | |
| 1742 }; | |
| 1743 | |
| 1744 template <class Machine> | |
| 1745 class InstX86Pxor | |
| 1746 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pxor, false, | |
| 1747 InstX86Base<Machine>::SseSuffix::None> { | |
| 1748 public: | |
| 1749 static InstX86Pxor *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1750 return new (Func->allocate<InstX86Pxor>()) InstX86Pxor(Func, Dest, Source); | |
| 1751 } | |
| 1752 | |
| 1753 private: | |
| 1754 InstX86Pxor(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1755 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pxor, false, | |
| 1756 InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | |
| 1757 Source) {} | |
| 1758 }; | |
| 1759 | |
| 1760 template <class Machine> | |
| 1761 class InstX86Imul | |
| 1762 : public InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Imul> { | |
| 1763 public: | |
| 1764 static InstX86Imul *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1765 return new (Func->allocate<InstX86Imul>()) InstX86Imul(Func, Dest, Source); | |
| 1766 } | |
| 1767 | |
| 1768 void emit(const Cfg *Func) const override; | |
| 1769 void emitIAS(const Cfg *Func) const override; | |
| 1770 | |
| 1771 private: | |
| 1772 InstX86Imul(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1773 : InstX86BaseBinopGPR<Machine, InstX86Base<Machine>::Imul>(Func, Dest, | |
| 1774 Source) {} | |
| 1775 }; | |
| 1776 | |
| 1777 template <class Machine> | |
| 1778 class InstX86ImulImm | |
| 1779 : public InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::ImulImm> { | |
| 1780 public: | |
| 1781 static InstX86ImulImm *create(Cfg *Func, Variable *Dest, Operand *Source0, | |
| 1782 Operand *Source1) { | 2077 Operand *Source1) { |
| 1783 return new (Func->allocate<InstX86ImulImm>()) | 2078 assert(Source0->getType() == IceType_v8i16 || |
| 1784 InstX86ImulImm(Func, Dest, Source0, Source1); | 2079 Source0->getType() == IceType_v8i1 || |
| 1785 } | 2080 InstX86Base::getTarget(Func)->getInstructionSet() >= |
| 1786 | 2081 Traits::SSE4_1); |
| 1787 void emit(const Cfg *Func) const override; | 2082 return new (Func->allocate<InstX86Pextr>()) |
| 1788 void emitIAS(const Cfg *Func) const override; | 2083 InstX86Pextr(Func, Dest, Source0, Source1); |
| 1789 | 2084 } |
| 1790 private: | 2085 |
| 1791 InstX86ImulImm(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) | 2086 void emit(const Cfg *Func) const override; |
| 1792 : InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::ImulImm>( | 2087 void emitIAS(const Cfg *Func) const override; |
| 1793 Func, Dest, Source0, Source1) {} | 2088 |
| 1794 }; | 2089 private: |
| 1795 | 2090 InstX86Pextr(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) |
| 1796 template <class Machine> | 2091 : InstX86BaseThreeAddressop<InstX86Base::Pextr>(Func, Dest, Source0, |
| 1797 class InstX86Mulps | 2092 Source1) {} |
| 1798 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulps, true, | 2093 }; |
| 1799 InstX86Base<Machine>::SseSuffix::Packed> { | 2094 |
| 1800 public: | 2095 class InstX86Pshufd : public InstX86BaseThreeAddressop<InstX86Base::Pshufd> { |
| 1801 static InstX86Mulps *create(Cfg *Func, Variable *Dest, Operand *Source) { | 2096 public: |
| 1802 return new (Func->allocate<InstX86Mulps>()) | 2097 static InstX86Pshufd *create(Cfg *Func, Variable *Dest, Operand *Source0, |
| 1803 InstX86Mulps(Func, Dest, Source); | 2098 Operand *Source1) { |
| 1804 } | 2099 return new (Func->allocate<InstX86Pshufd>()) |
| 1805 | 2100 InstX86Pshufd(Func, Dest, Source0, Source1); |
| 1806 private: | 2101 } |
| 1807 InstX86Mulps(Cfg *Func, Variable *Dest, Operand *Source) | 2102 |
| 1808 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulps, true, | 2103 void emitIAS(const Cfg *Func) const override; |
| 1809 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | 2104 |
| 1810 Source) {} | 2105 private: |
| 1811 }; | 2106 InstX86Pshufd(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) |
| 1812 | 2107 : InstX86BaseThreeAddressop<InstX86Base::Pshufd>(Func, Dest, Source0, |
| 1813 template <class Machine> | 2108 Source1) {} |
| 1814 class InstX86Mulss | 2109 }; |
| 1815 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulss, false, | 2110 |
| 1816 InstX86Base<Machine>::SseSuffix::Scalar> { | 2111 /// Base class for a lockable x86-32 instruction (emits a locked prefix). |
| 1817 public: | 2112 class InstX86BaseLockable : public InstX86Base { |
| 1818 static InstX86Mulss *create(Cfg *Func, Variable *Dest, Operand *Source) { | 2113 InstX86BaseLockable() = delete; |
| 1819 return new (Func->allocate<InstX86Mulss>()) | 2114 InstX86BaseLockable(const InstX86BaseLockable &) = delete; |
| 1820 InstX86Mulss(Func, Dest, Source); | 2115 InstX86BaseLockable &operator=(const InstX86BaseLockable &) = delete; |
| 1821 } | 2116 |
| 1822 | 2117 protected: |
| 1823 private: | 2118 bool Locked; |
| 1824 InstX86Mulss(Cfg *Func, Variable *Dest, Operand *Source) | 2119 |
| 1825 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Mulss, false, | 2120 InstX86BaseLockable(Cfg *Func, typename InstX86Base::InstKindX86 Kind, |
| 1826 InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | 2121 SizeT Maxsrcs, Variable *Dest, bool Locked) |
| 1827 Source) {} | 2122 : InstX86Base(Func, Kind, Maxsrcs, Dest), Locked(Locked) { |
| 1828 }; | 2123 // Assume that such instructions are used for Atomics and be careful with |
| 1829 | 2124 // optimizations. |
| 1830 template <class Machine> | 2125 this->HasSideEffects = Locked; |
| 1831 class InstX86Pmull | 2126 } |
| 1832 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmull, true, | 2127 }; |
| 1833 InstX86Base<Machine>::SseSuffix::Integral> { | 2128 |
| 1834 public: | 2129 /// Mul instruction - unsigned multiply. |
| 1835 static InstX86Pmull *create(Cfg *Func, Variable *Dest, Operand *Source) { | 2130 class InstX86Mul final : public InstX86Base { |
| 1836 bool TypesAreValid = | 2131 InstX86Mul() = delete; |
| 1837 Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v8i16; | 2132 InstX86Mul(const InstX86Mul &) = delete; |
| 1838 auto *Target = InstX86Base<Machine>::getTarget(Func); | 2133 InstX86Mul &operator=(const InstX86Mul &) = delete; |
| 1839 bool InstructionSetIsValid = | 2134 |
| 1840 Dest->getType() == IceType_v8i16 || | 2135 public: |
| 1841 Target->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1; | 2136 static InstX86Mul *create(Cfg *Func, Variable *Dest, Variable *Source1, |
| 1842 (void)TypesAreValid; | |
| 1843 (void)InstructionSetIsValid; | |
| 1844 assert(TypesAreValid); | |
| 1845 assert(InstructionSetIsValid); | |
| 1846 return new (Func->allocate<InstX86Pmull>()) | |
| 1847 InstX86Pmull(Func, Dest, Source); | |
| 1848 } | |
| 1849 | |
| 1850 private: | |
| 1851 InstX86Pmull(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1852 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmull, true, | |
| 1853 InstX86Base<Machine>::SseSuffix::Integral>( | |
| 1854 Func, Dest, Source) {} | |
| 1855 }; | |
| 1856 | |
| 1857 template <class Machine> | |
| 1858 class InstX86Pmuludq | |
| 1859 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmuludq, false, | |
| 1860 InstX86Base<Machine>::SseSuffix::None> { | |
| 1861 public: | |
| 1862 static InstX86Pmuludq *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1863 assert(Dest->getType() == IceType_v4i32 && | |
| 1864 Source->getType() == IceType_v4i32); | |
| 1865 return new (Func->allocate<InstX86Pmuludq>()) | |
| 1866 InstX86Pmuludq(Func, Dest, Source); | |
| 1867 } | |
| 1868 | |
| 1869 private: | |
| 1870 InstX86Pmuludq(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1871 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pmuludq, false, | |
| 1872 InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | |
| 1873 Source) {} | |
| 1874 }; | |
| 1875 | |
| 1876 template <class Machine> | |
| 1877 class InstX86Divps | |
| 1878 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divps, true, | |
| 1879 InstX86Base<Machine>::SseSuffix::Packed> { | |
| 1880 public: | |
| 1881 static InstX86Divps *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1882 return new (Func->allocate<InstX86Divps>()) | |
| 1883 InstX86Divps(Func, Dest, Source); | |
| 1884 } | |
| 1885 | |
| 1886 private: | |
| 1887 InstX86Divps(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1888 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divps, true, | |
| 1889 InstX86Base<Machine>::SseSuffix::Packed>(Func, Dest, | |
| 1890 Source) {} | |
| 1891 }; | |
| 1892 | |
| 1893 template <class Machine> | |
| 1894 class InstX86Divss | |
| 1895 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divss, false, | |
| 1896 InstX86Base<Machine>::SseSuffix::Scalar> { | |
| 1897 public: | |
| 1898 static InstX86Divss *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1899 return new (Func->allocate<InstX86Divss>()) | |
| 1900 InstX86Divss(Func, Dest, Source); | |
| 1901 } | |
| 1902 | |
| 1903 private: | |
| 1904 InstX86Divss(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1905 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Divss, false, | |
| 1906 InstX86Base<Machine>::SseSuffix::Scalar>(Func, Dest, | |
| 1907 Source) {} | |
| 1908 }; | |
| 1909 | |
| 1910 template <class Machine> | |
| 1911 class InstX86Rol | |
| 1912 : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Rol> { | |
| 1913 public: | |
| 1914 static InstX86Rol *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1915 return new (Func->allocate<InstX86Rol>()) InstX86Rol(Func, Dest, Source); | |
| 1916 } | |
| 1917 | |
| 1918 private: | |
| 1919 InstX86Rol(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1920 : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Rol>(Func, Dest, | |
| 1921 Source) {} | |
| 1922 }; | |
| 1923 | |
| 1924 template <class Machine> | |
| 1925 class InstX86Shl | |
| 1926 : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shl> { | |
| 1927 public: | |
| 1928 static InstX86Shl *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1929 return new (Func->allocate<InstX86Shl>()) InstX86Shl(Func, Dest, Source); | |
| 1930 } | |
| 1931 | |
| 1932 private: | |
| 1933 InstX86Shl(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1934 : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shl>(Func, Dest, | |
| 1935 Source) {} | |
| 1936 }; | |
| 1937 | |
| 1938 template <class Machine> | |
| 1939 class InstX86Psll | |
| 1940 : public InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psll> { | |
| 1941 public: | |
| 1942 static InstX86Psll *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1943 assert(Dest->getType() == IceType_v8i16 || | |
| 1944 Dest->getType() == IceType_v8i1 || | |
| 1945 Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v4i1); | |
| 1946 return new (Func->allocate<InstX86Psll>()) InstX86Psll(Func, Dest, Source); | |
| 1947 } | |
| 1948 | |
| 1949 private: | |
| 1950 InstX86Psll(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1951 : InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psll>( | |
| 1952 Func, Dest, Source) {} | |
| 1953 }; | |
| 1954 | |
| 1955 template <class Machine> | |
| 1956 class InstX86Psrl | |
| 1957 : public InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psrl, | |
| 1958 true> { | |
| 1959 public: | |
| 1960 static InstX86Psrl *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1961 return new (Func->allocate<InstX86Psrl>()) InstX86Psrl(Func, Dest, Source); | |
| 1962 } | |
| 1963 | |
| 1964 private: | |
| 1965 InstX86Psrl(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1966 : InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psrl, true>( | |
| 1967 Func, Dest, Source) {} | |
| 1968 }; | |
| 1969 | |
| 1970 template <class Machine> | |
| 1971 class InstX86Shr | |
| 1972 : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shr> { | |
| 1973 public: | |
| 1974 static InstX86Shr *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1975 return new (Func->allocate<InstX86Shr>()) InstX86Shr(Func, Dest, Source); | |
| 1976 } | |
| 1977 | |
| 1978 private: | |
| 1979 InstX86Shr(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1980 : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Shr>(Func, Dest, | |
| 1981 Source) {} | |
| 1982 }; | |
| 1983 | |
| 1984 template <class Machine> | |
| 1985 class InstX86Sar | |
| 1986 : public InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Sar> { | |
| 1987 public: | |
| 1988 static InstX86Sar *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 1989 return new (Func->allocate<InstX86Sar>()) InstX86Sar(Func, Dest, Source); | |
| 1990 } | |
| 1991 | |
| 1992 private: | |
| 1993 InstX86Sar(Cfg *Func, Variable *Dest, Operand *Source) | |
| 1994 : InstX86BaseBinopGPRShift<Machine, InstX86Base<Machine>::Sar>(Func, Dest, | |
| 1995 Source) {} | |
| 1996 }; | |
| 1997 | |
| 1998 template <class Machine> | |
| 1999 class InstX86Psra | |
| 2000 : public InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psra> { | |
| 2001 public: | |
| 2002 static InstX86Psra *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 2003 assert(Dest->getType() == IceType_v8i16 || | |
| 2004 Dest->getType() == IceType_v8i1 || | |
| 2005 Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v4i1); | |
| 2006 return new (Func->allocate<InstX86Psra>()) InstX86Psra(Func, Dest, Source); | |
| 2007 } | |
| 2008 | |
| 2009 private: | |
| 2010 InstX86Psra(Cfg *Func, Variable *Dest, Operand *Source) | |
| 2011 : InstX86BaseBinopXmmShift<Machine, InstX86Base<Machine>::Psra>( | |
| 2012 Func, Dest, Source) {} | |
| 2013 }; | |
| 2014 | |
| 2015 template <class Machine> | |
| 2016 class InstX86Pcmpeq | |
| 2017 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpeq, true, | |
| 2018 InstX86Base<Machine>::SseSuffix::Integral> { | |
| 2019 public: | |
| 2020 static InstX86Pcmpeq *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 2021 return new (Func->allocate<InstX86Pcmpeq>()) | |
| 2022 InstX86Pcmpeq(Func, Dest, Source); | |
| 2023 } | |
| 2024 | |
| 2025 private: | |
| 2026 InstX86Pcmpeq(Cfg *Func, Variable *Dest, Operand *Source) | |
| 2027 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpeq, true, | |
| 2028 InstX86Base<Machine>::SseSuffix::Integral>( | |
| 2029 Func, Dest, Source) {} | |
| 2030 }; | |
| 2031 | |
| 2032 template <class Machine> | |
| 2033 class InstX86Pcmpgt | |
| 2034 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpgt, true, | |
| 2035 InstX86Base<Machine>::SseSuffix::Integral> { | |
| 2036 public: | |
| 2037 static InstX86Pcmpgt *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 2038 return new (Func->allocate<InstX86Pcmpgt>()) | |
| 2039 InstX86Pcmpgt(Func, Dest, Source); | |
| 2040 } | |
| 2041 | |
| 2042 private: | |
| 2043 InstX86Pcmpgt(Cfg *Func, Variable *Dest, Operand *Source) | |
| 2044 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::Pcmpgt, true, | |
| 2045 InstX86Base<Machine>::SseSuffix::Integral>( | |
| 2046 Func, Dest, Source) {} | |
| 2047 }; | |
| 2048 | |
| 2049 /// movss is only a binary operation when the source and dest operands are both | |
| 2050 /// registers (the high bits of dest are left untouched). In other cases, it | |
| 2051 /// behaves like a copy (mov-like) operation (and the high bits of dest are | |
| 2052 /// cleared). InstX86Movss will assert that both its source and dest operands | |
| 2053 /// are registers, so the lowering code should use _mov instead of _movss in | |
| 2054 /// cases where a copy operation is intended. | |
| 2055 template <class Machine> | |
| 2056 class InstX86MovssRegs | |
| 2057 : public InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::MovssRegs, | |
| 2058 false, InstX86Base<Machine>::SseSuffix::None> { | |
| 2059 public: | |
| 2060 static InstX86MovssRegs *create(Cfg *Func, Variable *Dest, Operand *Source) { | |
| 2061 return new (Func->allocate<InstX86MovssRegs>()) | |
| 2062 InstX86MovssRegs(Func, Dest, Source); | |
| 2063 } | |
| 2064 | |
| 2065 void emitIAS(const Cfg *Func) const override; | |
| 2066 | |
| 2067 private: | |
| 2068 InstX86MovssRegs(Cfg *Func, Variable *Dest, Operand *Source) | |
| 2069 : InstX86BaseBinopXmm<Machine, InstX86Base<Machine>::MovssRegs, false, | |
| 2070 InstX86Base<Machine>::SseSuffix::None>(Func, Dest, | |
| 2071 Source) {} | |
| 2072 }; | |
| 2073 | |
| 2074 template <class Machine> | |
| 2075 class InstX86Idiv | |
| 2076 : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Idiv> { | |
| 2077 public: | |
| 2078 static InstX86Idiv *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
| 2079 Operand *Source2) { | |
| 2080 return new (Func->allocate<InstX86Idiv>()) | |
| 2081 InstX86Idiv(Func, Dest, Source1, Source2); | |
| 2082 } | |
| 2083 | |
| 2084 void emit(const Cfg *Func) const override; | |
| 2085 void emitIAS(const Cfg *Func) const override; | |
| 2086 | |
| 2087 private: | |
| 2088 InstX86Idiv(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | |
| 2089 : InstX86BaseTernop<Machine, InstX86Base<Machine>::Idiv>( | |
| 2090 Func, Dest, Source1, Source2) {} | |
| 2091 }; | |
| 2092 | |
| 2093 template <class Machine> | |
| 2094 class InstX86Div | |
| 2095 : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Div> { | |
| 2096 public: | |
| 2097 static InstX86Div *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
| 2098 Operand *Source2) { | |
| 2099 return new (Func->allocate<InstX86Div>()) | |
| 2100 InstX86Div(Func, Dest, Source1, Source2); | |
| 2101 } | |
| 2102 | |
| 2103 void emit(const Cfg *Func) const override; | |
| 2104 void emitIAS(const Cfg *Func) const override; | |
| 2105 | |
| 2106 private: | |
| 2107 InstX86Div(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | |
| 2108 : InstX86BaseTernop<Machine, InstX86Base<Machine>::Div>( | |
| 2109 Func, Dest, Source1, Source2) {} | |
| 2110 }; | |
| 2111 | |
| 2112 template <class Machine> | |
| 2113 class InstX86Insertps | |
| 2114 : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Insertps> { | |
| 2115 public: | |
| 2116 static InstX86Insertps *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
| 2117 Operand *Source2) { | |
| 2118 return new (Func->allocate<InstX86Insertps>()) | |
| 2119 InstX86Insertps(Func, Dest, Source1, Source2); | |
| 2120 } | |
| 2121 | |
| 2122 void emitIAS(const Cfg *Func) const override; | |
| 2123 | |
| 2124 private: | |
| 2125 InstX86Insertps(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | |
| 2126 : InstX86BaseTernop<Machine, InstX86Base<Machine>::Insertps>( | |
| 2127 Func, Dest, Source1, Source2) {} | |
| 2128 }; | |
| 2129 | |
| 2130 template <class Machine> | |
| 2131 class InstX86Pinsr | |
| 2132 : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Pinsr> { | |
| 2133 public: | |
| 2134 static InstX86Pinsr *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
| 2135 Operand *Source2) { | 2137 Operand *Source2) { |
| 2136 // pinsrb and pinsrd are SSE4.1 instructions. | 2138 return new (Func->allocate<InstX86Mul>()) |
| 2137 assert(Dest->getType() == IceType_v8i16 || | 2139 InstX86Mul(Func, Dest, Source1, Source2); |
| 2138 Dest->getType() == IceType_v8i1 || | 2140 } |
| 2139 InstX86Base<Machine>::getTarget(Func)->getInstructionSet() >= | 2141 void emit(const Cfg *Func) const override; |
| 2140 InstX86Base<Machine>::Traits::SSE4_1); | 2142 void emitIAS(const Cfg *Func) const override; |
| 2141 return new (Func->allocate<InstX86Pinsr>()) | 2143 void dump(const Cfg *Func) const override; |
| 2142 InstX86Pinsr(Func, Dest, Source1, Source2); | 2144 static bool classof(const Inst *Inst) { |
| 2143 } | 2145 return InstX86Base::isClassof(Inst, InstX86Base::Mul); |
| 2144 | 2146 } |
| 2145 void emit(const Cfg *Func) const override; | 2147 |
| 2146 void emitIAS(const Cfg *Func) const override; | 2148 private: |
| 2147 | 2149 InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); |
| 2148 private: | 2150 }; |
| 2149 InstX86Pinsr(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 2151 |
| 2150 : InstX86BaseTernop<Machine, InstX86Base<Machine>::Pinsr>( | 2152 /// Shld instruction - shift across a pair of operands. |
| 2151 Func, Dest, Source1, Source2) {} | 2153 class InstX86Shld final : public InstX86Base { |
| 2152 }; | 2154 InstX86Shld() = delete; |
| 2153 | 2155 InstX86Shld(const InstX86Shld &) = delete; |
| 2154 template <class Machine> | 2156 InstX86Shld &operator=(const InstX86Shld &) = delete; |
| 2155 class InstX86Shufps | 2157 |
| 2156 : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Shufps> { | 2158 public: |
| 2157 public: | 2159 static InstX86Shld *create(Cfg *Func, Variable *Dest, Variable *Source1, |
| 2158 static InstX86Shufps *create(Cfg *Func, Variable *Dest, Operand *Source1, | |
| 2159 Operand *Source2) { | 2160 Operand *Source2) { |
| 2160 return new (Func->allocate<InstX86Shufps>()) | 2161 return new (Func->allocate<InstX86Shld>()) |
| 2161 InstX86Shufps(Func, Dest, Source1, Source2); | 2162 InstX86Shld(Func, Dest, Source1, Source2); |
| 2162 } | 2163 } |
| 2163 | 2164 void emit(const Cfg *Func) const override; |
| 2164 void emitIAS(const Cfg *Func) const override; | 2165 void emitIAS(const Cfg *Func) const override; |
| 2165 | 2166 void dump(const Cfg *Func) const override; |
| 2166 private: | 2167 static bool classof(const Inst *Inst) { |
| 2167 InstX86Shufps(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 2168 return InstX86Base::isClassof(Inst, InstX86Base::Shld); |
| 2168 : InstX86BaseTernop<Machine, InstX86Base<Machine>::Shufps>( | 2169 } |
| 2169 Func, Dest, Source1, Source2) {} | 2170 |
| 2170 }; | 2171 private: |
| 2171 | 2172 InstX86Shld(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); |
| 2172 template <class Machine> | 2173 }; |
| 2173 class InstX86Blendvps | 2174 |
| 2174 : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Blendvps> { | 2175 /// Shrd instruction - shift across a pair of operands. |
| 2175 public: | 2176 class InstX86Shrd final : public InstX86Base { |
| 2176 static InstX86Blendvps *create(Cfg *Func, Variable *Dest, Operand *Source1, | 2177 InstX86Shrd() = delete; |
| 2177 Operand *Source2) { | 2178 InstX86Shrd(const InstX86Shrd &) = delete; |
| 2178 assert(InstX86Base<Machine>::getTarget(Func)->getInstructionSet() >= | 2179 InstX86Shrd &operator=(const InstX86Shrd &) = delete; |
| 2179 InstX86Base<Machine>::Traits::SSE4_1); | 2180 |
| 2180 return new (Func->allocate<InstX86Blendvps>()) | 2181 public: |
| 2181 InstX86Blendvps(Func, Dest, Source1, Source2); | 2182 static InstX86Shrd *create(Cfg *Func, Variable *Dest, Variable *Source1, |
| 2182 } | 2183 Operand *Source2) { |
| 2183 | 2184 return new (Func->allocate<InstX86Shrd>()) |
| 2184 void emit(const Cfg *Func) const override; | 2185 InstX86Shrd(Func, Dest, Source1, Source2); |
| 2185 void emitIAS(const Cfg *Fund) const override; | 2186 } |
| 2186 | 2187 void emit(const Cfg *Func) const override; |
| 2187 private: | 2188 void emitIAS(const Cfg *Func) const override; |
| 2188 InstX86Blendvps(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 2189 void dump(const Cfg *Func) const override; |
| 2189 : InstX86BaseTernop<Machine, InstX86Base<Machine>::Blendvps>( | 2190 static bool classof(const Inst *Inst) { |
| 2190 Func, Dest, Source1, Source2) {} | 2191 return InstX86Base::isClassof(Inst, InstX86Base::Shrd); |
| 2191 }; | 2192 } |
| 2192 | 2193 |
| 2193 template <class Machine> | 2194 private: |
| 2194 class InstX86Pblendvb | 2195 InstX86Shrd(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); |
| 2195 : public InstX86BaseTernop<Machine, InstX86Base<Machine>::Pblendvb> { | 2196 }; |
| 2196 public: | 2197 |
| 2197 static InstX86Pblendvb *create(Cfg *Func, Variable *Dest, Operand *Source1, | 2198 /// Conditional move instruction. |
| 2198 Operand *Source2) { | 2199 class InstX86Cmov final : public InstX86Base { |
| 2199 assert(InstX86Base<Machine>::getTarget(Func)->getInstructionSet() >= | 2200 InstX86Cmov() = delete; |
| 2200 InstX86Base<Machine>::Traits::SSE4_1); | 2201 InstX86Cmov(const InstX86Cmov &) = delete; |
| 2201 return new (Func->allocate<InstX86Pblendvb>()) | 2202 InstX86Cmov &operator=(const InstX86Cmov &) = delete; |
| 2202 InstX86Pblendvb(Func, Dest, Source1, Source2); | 2203 |
| 2203 } | 2204 public: |
| 2204 | 2205 static InstX86Cmov *create(Cfg *Func, Variable *Dest, Operand *Source, |
| 2205 void emit(const Cfg *Func) const override; | 2206 BrCond Cond) { |
| 2206 void emitIAS(const Cfg *Func) const override; | 2207 return new (Func->allocate<InstX86Cmov>()) |
| 2207 | 2208 InstX86Cmov(Func, Dest, Source, Cond); |
| 2208 private: | 2209 } |
| 2209 InstX86Pblendvb(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2) | 2210 void emit(const Cfg *Func) const override; |
| 2210 : InstX86BaseTernop<Machine, InstX86Base<Machine>::Pblendvb>( | 2211 void emitIAS(const Cfg *Func) const override; |
| 2211 Func, Dest, Source1, Source2) {} | 2212 void dump(const Cfg *Func) const override; |
| 2212 }; | 2213 static bool classof(const Inst *Inst) { |
| 2213 | 2214 return InstX86Base::isClassof(Inst, InstX86Base::Cmov); |
| 2214 template <class Machine> | 2215 } |
| 2215 class InstX86Pextr | 2216 |
| 2216 : public InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pextr> { | 2217 private: |
| 2217 public: | 2218 InstX86Cmov(Cfg *Func, Variable *Dest, Operand *Source, BrCond Cond); |
| 2218 static InstX86Pextr *create(Cfg *Func, Variable *Dest, Operand *Source0, | 2219 |
| 2219 Operand *Source1) { | 2220 BrCond Condition; |
| 2220 assert(Source0->getType() == IceType_v8i16 || | 2221 }; |
| 2221 Source0->getType() == IceType_v8i1 || | 2222 |
| 2222 InstX86Base<Machine>::getTarget(Func)->getInstructionSet() >= | 2223 /// Cmpps instruction - compare packed singled-precision floating point values |
| 2223 InstX86Base<Machine>::Traits::SSE4_1); | 2224 class InstX86Cmpps final : public InstX86Base { |
| 2224 return new (Func->allocate<InstX86Pextr>()) | 2225 InstX86Cmpps() = delete; |
| 2225 InstX86Pextr(Func, Dest, Source0, Source1); | 2226 InstX86Cmpps(const InstX86Cmpps &) = delete; |
| 2226 } | 2227 InstX86Cmpps &operator=(const InstX86Cmpps &) = delete; |
| 2227 | 2228 |
| 2228 void emit(const Cfg *Func) const override; | 2229 public: |
| 2229 void emitIAS(const Cfg *Func) const override; | 2230 static InstX86Cmpps *create(Cfg *Func, Variable *Dest, Operand *Source, |
| 2230 | 2231 CmppsCond Condition) { |
| 2231 private: | 2232 return new (Func->allocate<InstX86Cmpps>()) |
| 2232 InstX86Pextr(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) | 2233 InstX86Cmpps(Func, Dest, Source, Condition); |
| 2233 : InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pextr>( | 2234 } |
| 2234 Func, Dest, Source0, Source1) {} | 2235 void emit(const Cfg *Func) const override; |
| 2235 }; | 2236 void emitIAS(const Cfg *Func) const override; |
| 2236 | 2237 void dump(const Cfg *Func) const override; |
| 2237 template <class Machine> | 2238 static bool classof(const Inst *Inst) { |
| 2238 class InstX86Pshufd | 2239 return InstX86Base::isClassof(Inst, InstX86Base::Cmpps); |
| 2239 : public InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pshufd> { | 2240 } |
| 2240 public: | 2241 |
| 2241 static InstX86Pshufd *create(Cfg *Func, Variable *Dest, Operand *Source0, | 2242 private: |
| 2242 Operand *Source1) { | 2243 InstX86Cmpps(Cfg *Func, Variable *Dest, Operand *Source, CmppsCond Cond); |
| 2243 return new (Func->allocate<InstX86Pshufd>()) | 2244 |
| 2244 InstX86Pshufd(Func, Dest, Source0, Source1); | 2245 CmppsCond Condition; |
| 2245 } | 2246 }; |
| 2246 | 2247 |
| 2247 void emitIAS(const Cfg *Func) const override; | 2248 /// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest> |
| 2248 | 2249 /// equals eax. If so, the ZF is set and <desired> is stored in <dest>. If |
| 2249 private: | 2250 /// not, ZF is cleared and <dest> is copied to eax (or subregister). <dest> |
| 2250 InstX86Pshufd(Cfg *Func, Variable *Dest, Operand *Source0, Operand *Source1) | 2251 /// can be a register or memory, while <desired> must be a register. It is |
| 2251 : InstX86BaseThreeAddressop<Machine, InstX86Base<Machine>::Pshufd>( | 2252 /// the user's responsibility to mark eax with a FakeDef. |
| 2252 Func, Dest, Source0, Source1) {} | 2253 class InstX86Cmpxchg final : public InstX86BaseLockable { |
| 2253 }; | 2254 InstX86Cmpxchg() = delete; |
| 2254 | 2255 InstX86Cmpxchg(const InstX86Cmpxchg &) = delete; |
| 2255 /// Base class for a lockable x86-32 instruction (emits a locked prefix). | 2256 InstX86Cmpxchg &operator=(const InstX86Cmpxchg &) = delete; |
| 2256 template <class Machine> | 2257 |
| 2257 class InstX86BaseLockable : public InstX86Base<Machine> { | 2258 public: |
| 2258 InstX86BaseLockable() = delete; | 2259 static InstX86Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax, |
| 2259 InstX86BaseLockable(const InstX86BaseLockable &) = delete; | 2260 Variable *Desired, bool Locked) { |
| 2260 InstX86BaseLockable &operator=(const InstX86BaseLockable &) = delete; | 2261 return new (Func->allocate<InstX86Cmpxchg>()) |
| 2261 | 2262 InstX86Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked); |
| 2262 protected: | 2263 } |
| 2263 bool Locked; | 2264 void emit(const Cfg *Func) const override; |
| 2264 | 2265 void emitIAS(const Cfg *Func) const override; |
| 2265 InstX86BaseLockable(Cfg *Func, | 2266 void dump(const Cfg *Func) const override; |
| 2266 typename InstX86Base<Machine>::InstKindX86 Kind, | 2267 static bool classof(const Inst *Inst) { |
| 2267 SizeT Maxsrcs, Variable *Dest, bool Locked) | 2268 return InstX86Base::isClassof(Inst, InstX86Base::Cmpxchg); |
| 2268 : InstX86Base<Machine>(Func, Kind, Maxsrcs, Dest), Locked(Locked) { | 2269 } |
| 2269 // Assume that such instructions are used for Atomics and be careful with | 2270 |
| 2270 // optimizations. | 2271 private: |
| 2271 this->HasSideEffects = Locked; | 2272 InstX86Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax, |
| 2272 } | 2273 Variable *Desired, bool Locked); |
| 2273 }; | 2274 }; |
| 2274 | 2275 |
| 2275 /// Mul instruction - unsigned multiply. | 2276 /// Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64> equals |
| 2276 template <class Machine> class InstX86Mul final : public InstX86Base<Machine> { | 2277 /// edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>. If not, ZF |
| 2277 InstX86Mul() = delete; | 2278 /// is cleared and <m64> is copied to edx:eax. The caller is responsible for |
| 2278 InstX86Mul(const InstX86Mul &) = delete; | 2279 /// inserting FakeDefs to mark edx and eax as modified. <m64> must be a memory |
| 2279 InstX86Mul &operator=(const InstX86Mul &) = delete; | 2280 /// operand. |
| 2280 | 2281 class InstX86Cmpxchg8b final : public InstX86BaseLockable { |
| 2281 public: | 2282 InstX86Cmpxchg8b() = delete; |
| 2282 static InstX86Mul *create(Cfg *Func, Variable *Dest, Variable *Source1, | 2283 InstX86Cmpxchg8b(const InstX86Cmpxchg8b &) = delete; |
| 2283 Operand *Source2) { | 2284 InstX86Cmpxchg8b &operator=(const InstX86Cmpxchg8b &) = delete; |
| 2284 return new (Func->allocate<InstX86Mul>()) | 2285 |
| 2285 InstX86Mul(Func, Dest, Source1, Source2); | 2286 public: |
| 2286 } | 2287 static InstX86Cmpxchg8b *create(Cfg *Func, X86OperandMem *Dest, |
| 2287 void emit(const Cfg *Func) const override; | 2288 Variable *Edx, Variable *Eax, Variable *Ecx, |
| 2288 void emitIAS(const Cfg *Func) const override; | 2289 Variable *Ebx, bool Locked) { |
| 2289 void dump(const Cfg *Func) const override; | 2290 return new (Func->allocate<InstX86Cmpxchg8b>()) |
| 2290 static bool classof(const Inst *Inst) { | 2291 InstX86Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked); |
| 2291 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Mul); | 2292 } |
| 2292 } | 2293 void emit(const Cfg *Func) const override; |
| 2293 | 2294 void emitIAS(const Cfg *Func) const override; |
| 2294 private: | 2295 void dump(const Cfg *Func) const override; |
| 2295 InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); | 2296 static bool classof(const Inst *Inst) { |
| 2296 }; | 2297 return InstX86Base::isClassof(Inst, InstX86Base::Cmpxchg8b); |
| 2297 | 2298 } |
| 2298 /// Shld instruction - shift across a pair of operands. | 2299 |
| 2299 template <class Machine> class InstX86Shld final : public InstX86Base<Machine> { | 2300 private: |
| 2300 InstX86Shld() = delete; | 2301 InstX86Cmpxchg8b(Cfg *Func, X86OperandMem *Dest, Variable *Edx, |
| 2301 InstX86Shld(const InstX86Shld &) = delete; | 2302 Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked); |
| 2302 InstX86Shld &operator=(const InstX86Shld &) = delete; | 2303 }; |
| 2303 | 2304 |
| 2304 public: | 2305 /// Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i} as |
| 2305 static InstX86Shld *create(Cfg *Func, Variable *Dest, Variable *Source1, | 2306 /// appropriate. s=float, d=double, i=int. X and Y are determined from |
| 2306 Operand *Source2) { | 2307 /// dest/src types. Sign and zero extension on the integer operand needs to be |
| 2307 return new (Func->allocate<InstX86Shld>()) | 2308 /// done separately. |
| 2308 InstX86Shld(Func, Dest, Source1, Source2); | 2309 class InstX86Cvt final : public InstX86Base { |
| 2309 } | 2310 InstX86Cvt() = delete; |
| 2310 void emit(const Cfg *Func) const override; | 2311 InstX86Cvt(const InstX86Cvt &) = delete; |
| 2311 void emitIAS(const Cfg *Func) const override; | 2312 InstX86Cvt &operator=(const InstX86Cvt &) = delete; |
| 2312 void dump(const Cfg *Func) const override; | 2313 |
| 2313 static bool classof(const Inst *Inst) { | 2314 public: |
| 2314 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Shld); | 2315 enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq }; |
| 2315 } | 2316 static InstX86Cvt *create(Cfg *Func, Variable *Dest, Operand *Source, |
| 2316 | 2317 CvtVariant Variant) { |
| 2317 private: | 2318 return new (Func->allocate<InstX86Cvt>()) |
| 2318 InstX86Shld(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); | 2319 InstX86Cvt(Func, Dest, Source, Variant); |
| 2319 }; | 2320 } |
| 2320 | 2321 void emit(const Cfg *Func) const override; |
| 2321 /// Shrd instruction - shift across a pair of operands. | 2322 void emitIAS(const Cfg *Func) const override; |
| 2322 template <class Machine> class InstX86Shrd final : public InstX86Base<Machine> { | 2323 void dump(const Cfg *Func) const override; |
| 2323 InstX86Shrd() = delete; | 2324 static bool classof(const Inst *Inst) { |
| 2324 InstX86Shrd(const InstX86Shrd &) = delete; | 2325 return InstX86Base::isClassof(Inst, InstX86Base::Cvt); |
| 2325 InstX86Shrd &operator=(const InstX86Shrd &) = delete; | 2326 } |
| 2326 | 2327 bool isTruncating() const { return Variant == Tss2si || Variant == Tps2dq; } |
| 2327 public: | 2328 |
| 2328 static InstX86Shrd *create(Cfg *Func, Variable *Dest, Variable *Source1, | 2329 private: |
| 2329 Operand *Source2) { | 2330 CvtVariant Variant; |
| 2330 return new (Func->allocate<InstX86Shrd>()) | 2331 InstX86Cvt(Cfg *Func, Variable *Dest, Operand *Source, CvtVariant Variant); |
| 2331 InstX86Shrd(Func, Dest, Source1, Source2); | 2332 }; |
| 2332 } | 2333 |
| 2333 void emit(const Cfg *Func) const override; | 2334 /// cmp - Integer compare instruction. |
| 2334 void emitIAS(const Cfg *Func) const override; | 2335 class InstX86Icmp final : public InstX86Base { |
| 2335 void dump(const Cfg *Func) const override; | 2336 InstX86Icmp() = delete; |
| 2336 static bool classof(const Inst *Inst) { | 2337 InstX86Icmp(const InstX86Icmp &) = delete; |
| 2337 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Shrd); | 2338 InstX86Icmp &operator=(const InstX86Icmp &) = delete; |
| 2338 } | 2339 |
| 2339 | 2340 public: |
| 2340 private: | 2341 static InstX86Icmp *create(Cfg *Func, Operand *Src1, Operand *Src2) { |
| 2341 InstX86Shrd(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2); | 2342 return new (Func->allocate<InstX86Icmp>()) InstX86Icmp(Func, Src1, Src2); |
| 2342 }; | 2343 } |
| 2343 | 2344 void emit(const Cfg *Func) const override; |
| 2344 /// Conditional move instruction. | 2345 void emitIAS(const Cfg *Func) const override; |
| 2345 template <class Machine> class InstX86Cmov final : public InstX86Base<Machine> { | 2346 void dump(const Cfg *Func) const override; |
| 2346 InstX86Cmov() = delete; | 2347 static bool classof(const Inst *Inst) { |
| 2347 InstX86Cmov(const InstX86Cmov &) = delete; | 2348 return InstX86Base::isClassof(Inst, InstX86Base::Icmp); |
| 2348 InstX86Cmov &operator=(const InstX86Cmov &) = delete; | 2349 } |
| 2349 | 2350 |
| 2350 public: | 2351 private: |
| 2351 static InstX86Cmov * | 2352 InstX86Icmp(Cfg *Func, Operand *Src1, Operand *Src2); |
| 2352 create(Cfg *Func, Variable *Dest, Operand *Source, | 2353 }; |
| 2353 typename InstX86Base<Machine>::Traits::Cond::BrCond Cond) { | 2354 |
| 2354 return new (Func->allocate<InstX86Cmov>()) | 2355 /// ucomiss/ucomisd - floating-point compare instruction. |
| 2355 InstX86Cmov(Func, Dest, Source, Cond); | 2356 class InstX86Ucomiss final : public InstX86Base { |
| 2356 } | 2357 InstX86Ucomiss() = delete; |
| 2357 void emit(const Cfg *Func) const override; | 2358 InstX86Ucomiss(const InstX86Ucomiss &) = delete; |
| 2358 void emitIAS(const Cfg *Func) const override; | 2359 InstX86Ucomiss &operator=(const InstX86Ucomiss &) = delete; |
| 2359 void dump(const Cfg *Func) const override; | 2360 |
| 2360 static bool classof(const Inst *Inst) { | 2361 public: |
| 2361 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cmov); | 2362 static InstX86Ucomiss *create(Cfg *Func, Operand *Src1, Operand *Src2) { |
| 2362 } | 2363 return new (Func->allocate<InstX86Ucomiss>()) |
| 2363 | 2364 InstX86Ucomiss(Func, Src1, Src2); |
| 2364 private: | 2365 } |
| 2365 InstX86Cmov(Cfg *Func, Variable *Dest, Operand *Source, | 2366 void emit(const Cfg *Func) const override; |
| 2366 typename InstX86Base<Machine>::Traits::Cond::BrCond Cond); | 2367 void emitIAS(const Cfg *Func) const override; |
| 2367 | 2368 void dump(const Cfg *Func) const override; |
| 2368 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; | 2369 static bool classof(const Inst *Inst) { |
| 2369 }; | 2370 return InstX86Base::isClassof(Inst, InstX86Base::Ucomiss); |
| 2370 | 2371 } |
| 2371 /// Cmpps instruction - compare packed singled-precision floating point values | 2372 |
| 2372 template <class Machine> | 2373 private: |
| 2373 class InstX86Cmpps final : public InstX86Base<Machine> { | 2374 InstX86Ucomiss(Cfg *Func, Operand *Src1, Operand *Src2); |
| 2374 InstX86Cmpps() = delete; | 2375 }; |
| 2375 InstX86Cmpps(const InstX86Cmpps &) = delete; | 2376 |
| 2376 InstX86Cmpps &operator=(const InstX86Cmpps &) = delete; | 2377 /// UD2 instruction. |
| 2377 | 2378 class InstX86UD2 final : public InstX86Base { |
| 2378 public: | 2379 InstX86UD2() = delete; |
| 2379 static InstX86Cmpps * | 2380 InstX86UD2(const InstX86UD2 &) = delete; |
| 2380 create(Cfg *Func, Variable *Dest, Operand *Source, | 2381 InstX86UD2 &operator=(const InstX86UD2 &) = delete; |
| 2381 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition) { | 2382 |
| 2382 return new (Func->allocate<InstX86Cmpps>()) | 2383 public: |
| 2383 InstX86Cmpps(Func, Dest, Source, Condition); | 2384 static InstX86UD2 *create(Cfg *Func) { |
| 2384 } | 2385 return new (Func->allocate<InstX86UD2>()) InstX86UD2(Func); |
| 2385 void emit(const Cfg *Func) const override; | 2386 } |
| 2386 void emitIAS(const Cfg *Func) const override; | 2387 void emit(const Cfg *Func) const override; |
| 2387 void dump(const Cfg *Func) const override; | 2388 void emitIAS(const Cfg *Func) const override; |
| 2388 static bool classof(const Inst *Inst) { | 2389 void dump(const Cfg *Func) const override; |
| 2389 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cmpps); | 2390 static bool classof(const Inst *Inst) { |
| 2390 } | 2391 return InstX86Base::isClassof(Inst, InstX86Base::UD2); |
| 2391 | 2392 } |
| 2392 private: | 2393 |
| 2393 InstX86Cmpps(Cfg *Func, Variable *Dest, Operand *Source, | 2394 private: |
| 2394 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Cond); | 2395 explicit InstX86UD2(Cfg *Func); |
| 2395 | 2396 }; |
| 2396 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition; | 2397 |
| 2397 }; | 2398 /// Test instruction. |
| 2398 | 2399 class InstX86Test final : public InstX86Base { |
| 2399 /// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest> | 2400 InstX86Test() = delete; |
| 2400 /// equals eax. If so, the ZF is set and <desired> is stored in <dest>. If not, | 2401 InstX86Test(const InstX86Test &) = delete; |
| 2401 /// ZF is cleared and <dest> is copied to eax (or subregister). <dest> can be a | 2402 InstX86Test &operator=(const InstX86Test &) = delete; |
| 2402 /// register or memory, while <desired> must be a register. It is the user's | 2403 |
| 2403 /// responsibility to mark eax with a FakeDef. | 2404 public: |
| 2404 template <class Machine> | 2405 static InstX86Test *create(Cfg *Func, Operand *Source1, Operand *Source2) { |
| 2405 class InstX86Cmpxchg final : public InstX86BaseLockable<Machine> { | 2406 return new (Func->allocate<InstX86Test>()) |
| 2406 InstX86Cmpxchg() = delete; | 2407 InstX86Test(Func, Source1, Source2); |
| 2407 InstX86Cmpxchg(const InstX86Cmpxchg &) = delete; | 2408 } |
| 2408 InstX86Cmpxchg &operator=(const InstX86Cmpxchg &) = delete; | 2409 void emit(const Cfg *Func) const override; |
| 2409 | 2410 void emitIAS(const Cfg *Func) const override; |
| 2410 public: | 2411 void dump(const Cfg *Func) const override; |
| 2411 static InstX86Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax, | 2412 static bool classof(const Inst *Inst) { |
| 2412 Variable *Desired, bool Locked) { | 2413 return InstX86Base::isClassof(Inst, InstX86Base::Test); |
| 2413 return new (Func->allocate<InstX86Cmpxchg>()) | 2414 } |
| 2414 InstX86Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked); | 2415 |
| 2415 } | 2416 private: |
| 2416 void emit(const Cfg *Func) const override; | 2417 InstX86Test(Cfg *Func, Operand *Source1, Operand *Source2); |
| 2417 void emitIAS(const Cfg *Func) const override; | 2418 }; |
| 2418 void dump(const Cfg *Func) const override; | 2419 |
| 2419 static bool classof(const Inst *Inst) { | 2420 /// Mfence instruction. |
| 2420 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cmpxchg); | 2421 class InstX86Mfence final : public InstX86Base { |
| 2421 } | 2422 InstX86Mfence() = delete; |
| 2422 | 2423 InstX86Mfence(const InstX86Mfence &) = delete; |
| 2423 private: | 2424 InstX86Mfence &operator=(const InstX86Mfence &) = delete; |
| 2424 InstX86Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax, | 2425 |
| 2425 Variable *Desired, bool Locked); | 2426 public: |
| 2426 }; | 2427 static InstX86Mfence *create(Cfg *Func) { |
| 2427 | 2428 return new (Func->allocate<InstX86Mfence>()) InstX86Mfence(Func); |
| 2428 /// Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64> equals | 2429 } |
| 2429 /// edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>. If not, ZF is | 2430 void emit(const Cfg *Func) const override; |
| 2430 /// cleared and <m64> is copied to edx:eax. The caller is responsible for | 2431 void emitIAS(const Cfg *Func) const override; |
| 2431 /// inserting FakeDefs to mark edx and eax as modified. <m64> must be a memory | 2432 void dump(const Cfg *Func) const override; |
| 2432 /// operand. | 2433 static bool classof(const Inst *Inst) { |
| 2433 template <class Machine> | 2434 return InstX86Base::isClassof(Inst, InstX86Base::Mfence); |
| 2434 class InstX86Cmpxchg8b final : public InstX86BaseLockable<Machine> { | 2435 } |
| 2435 InstX86Cmpxchg8b() = delete; | 2436 |
| 2436 InstX86Cmpxchg8b(const InstX86Cmpxchg8b &) = delete; | 2437 private: |
| 2437 InstX86Cmpxchg8b &operator=(const InstX86Cmpxchg8b &) = delete; | 2438 explicit InstX86Mfence(Cfg *Func); |
| 2438 | 2439 }; |
| 2439 public: | 2440 |
| 2440 static InstX86Cmpxchg8b * | 2441 /// This is essentially a "mov" instruction with anX86OperandMem operand |
| 2441 create(Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *Dest, | 2442 /// instead of Variable as the destination. It's important for liveness that |
| 2442 Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, | 2443 /// there is no Dest operand. |
| 2443 bool Locked) { | 2444 class InstX86Store final : public InstX86Base { |
| 2444 return new (Func->allocate<InstX86Cmpxchg8b>()) | 2445 InstX86Store() = delete; |
| 2445 InstX86Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked); | 2446 InstX86Store(const InstX86Store &) = delete; |
| 2446 } | 2447 InstX86Store &operator=(const InstX86Store &) = delete; |
| 2447 void emit(const Cfg *Func) const override; | 2448 |
| 2448 void emitIAS(const Cfg *Func) const override; | 2449 public: |
| 2449 void dump(const Cfg *Func) const override; | 2450 static InstX86Store *create(Cfg *Func, Operand *Value, X86Operand *Mem) { |
| 2450 static bool classof(const Inst *Inst) { | 2451 return new (Func->allocate<InstX86Store>()) |
| 2451 return InstX86Base<Machine>::isClassof(Inst, | 2452 InstX86Store(Func, Value, Mem); |
| 2452 InstX86Base<Machine>::Cmpxchg8b); | 2453 } |
| 2453 } | 2454 void emit(const Cfg *Func) const override; |
| 2454 | 2455 void emitIAS(const Cfg *Func) const override; |
| 2455 private: | 2456 void dump(const Cfg *Func) const override; |
| 2456 InstX86Cmpxchg8b(Cfg *Func, | 2457 static bool classof(const Inst *Inst) { |
| 2457 typename InstX86Base<Machine>::Traits::X86OperandMem *Dest, | 2458 return InstX86Base::isClassof(Inst, InstX86Base::Store); |
| 2458 Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, | 2459 } |
| 2459 bool Locked); | 2460 |
| 2460 }; | 2461 private: |
| 2461 | 2462 InstX86Store(Cfg *Func, Operand *Value, X86Operand *Mem); |
| 2462 /// Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i} as | 2463 }; |
| 2463 /// appropriate. s=float, d=double, i=int. X and Y are determined from dest/src | 2464 |
| 2464 /// types. Sign and zero extension on the integer operand needs to be done | 2465 /// This is essentially a vector "mov" instruction with an typename |
| 2465 /// separately. | 2466 /// X86OperandMem operand instead of Variable as the destination. It's |
| 2466 template <class Machine> class InstX86Cvt final : public InstX86Base<Machine> { | 2467 /// important for liveness that there is no Dest operand. The source must be |
| 2467 InstX86Cvt() = delete; | 2468 /// an Xmm register, since Dest is mem. |
| 2468 InstX86Cvt(const InstX86Cvt &) = delete; | 2469 class InstX86StoreP final : public InstX86Base { |
| 2469 InstX86Cvt &operator=(const InstX86Cvt &) = delete; | 2470 InstX86StoreP() = delete; |
| 2470 | 2471 InstX86StoreP(const InstX86StoreP &) = delete; |
| 2471 public: | 2472 InstX86StoreP &operator=(const InstX86StoreP &) = delete; |
| 2472 enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq }; | 2473 |
| 2473 static InstX86Cvt *create(Cfg *Func, Variable *Dest, Operand *Source, | 2474 public: |
| 2474 CvtVariant Variant) { | 2475 static InstX86StoreP *create(Cfg *Func, Variable *Value, |
| 2475 return new (Func->allocate<InstX86Cvt>()) | 2476 X86OperandMem *Mem) { |
| 2476 InstX86Cvt(Func, Dest, Source, Variant); | 2477 return new (Func->allocate<InstX86StoreP>()) |
| 2477 } | 2478 InstX86StoreP(Func, Value, Mem); |
| 2478 void emit(const Cfg *Func) const override; | 2479 } |
| 2479 void emitIAS(const Cfg *Func) const override; | 2480 void emit(const Cfg *Func) const override; |
| 2480 void dump(const Cfg *Func) const override; | 2481 void emitIAS(const Cfg *Func) const override; |
| 2481 static bool classof(const Inst *Inst) { | 2482 void dump(const Cfg *Func) const override; |
| 2482 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Cvt); | 2483 static bool classof(const Inst *Inst) { |
| 2483 } | 2484 return InstX86Base::isClassof(Inst, InstX86Base::StoreP); |
| 2484 bool isTruncating() const { return Variant == Tss2si || Variant == Tps2dq; } | 2485 } |
| 2485 | 2486 |
| 2486 private: | 2487 private: |
| 2487 CvtVariant Variant; | 2488 InstX86StoreP(Cfg *Func, Variable *Value, X86OperandMem *Mem); |
| 2488 InstX86Cvt(Cfg *Func, Variable *Dest, Operand *Source, CvtVariant Variant); | 2489 }; |
| 2489 }; | 2490 |
| 2490 | 2491 class InstX86StoreQ final : public InstX86Base { |
| 2491 /// cmp - Integer compare instruction. | 2492 InstX86StoreQ() = delete; |
| 2492 template <class Machine> class InstX86Icmp final : public InstX86Base<Machine> { | 2493 InstX86StoreQ(const InstX86StoreQ &) = delete; |
| 2493 InstX86Icmp() = delete; | 2494 InstX86StoreQ &operator=(const InstX86StoreQ &) = delete; |
| 2494 InstX86Icmp(const InstX86Icmp &) = delete; | 2495 |
| 2495 InstX86Icmp &operator=(const InstX86Icmp &) = delete; | 2496 public: |
| 2496 | 2497 static InstX86StoreQ *create(Cfg *Func, Variable *Value, |
| 2497 public: | 2498 X86OperandMem *Mem) { |
| 2498 static InstX86Icmp *create(Cfg *Func, Operand *Src1, Operand *Src2) { | 2499 return new (Func->allocate<InstX86StoreQ>()) |
| 2499 return new (Func->allocate<InstX86Icmp>()) InstX86Icmp(Func, Src1, Src2); | 2500 InstX86StoreQ(Func, Value, Mem); |
| 2500 } | 2501 } |
| 2501 void emit(const Cfg *Func) const override; | 2502 void emit(const Cfg *Func) const override; |
| 2502 void emitIAS(const Cfg *Func) const override; | 2503 void emitIAS(const Cfg *Func) const override; |
| 2503 void dump(const Cfg *Func) const override; | 2504 void dump(const Cfg *Func) const override; |
| 2504 static bool classof(const Inst *Inst) { | 2505 static bool classof(const Inst *Inst) { |
| 2505 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Icmp); | 2506 return InstX86Base::isClassof(Inst, InstX86Base::StoreQ); |
| 2506 } | 2507 } |
| 2507 | 2508 |
| 2508 private: | 2509 private: |
| 2509 InstX86Icmp(Cfg *Func, Operand *Src1, Operand *Src2); | 2510 InstX86StoreQ(Cfg *Func, Variable *Value, X86OperandMem *Mem); |
| 2510 }; | 2511 }; |
| 2511 | 2512 |
| 2512 /// ucomiss/ucomisd - floating-point compare instruction. | 2513 /// Nop instructions of varying length |
| 2513 template <class Machine> | 2514 class InstX86Nop final : public InstX86Base { |
| 2514 class InstX86Ucomiss final : public InstX86Base<Machine> { | 2515 InstX86Nop() = delete; |
| 2515 InstX86Ucomiss() = delete; | 2516 InstX86Nop(const InstX86Nop &) = delete; |
| 2516 InstX86Ucomiss(const InstX86Ucomiss &) = delete; | 2517 InstX86Nop &operator=(const InstX86Nop &) = delete; |
| 2517 InstX86Ucomiss &operator=(const InstX86Ucomiss &) = delete; | 2518 |
| 2518 | 2519 public: |
| 2519 public: | 2520 // TODO: Replace with enum. |
| 2520 static InstX86Ucomiss *create(Cfg *Func, Operand *Src1, Operand *Src2) { | 2521 using NopVariant = unsigned; |
| 2521 return new (Func->allocate<InstX86Ucomiss>()) | 2522 |
| 2522 InstX86Ucomiss(Func, Src1, Src2); | 2523 static InstX86Nop *create(Cfg *Func, NopVariant Variant) { |
| 2523 } | 2524 return new (Func->allocate<InstX86Nop>()) InstX86Nop(Func, Variant); |
| 2524 void emit(const Cfg *Func) const override; | 2525 } |
| 2525 void emitIAS(const Cfg *Func) const override; | 2526 void emit(const Cfg *Func) const override; |
| 2526 void dump(const Cfg *Func) const override; | 2527 void emitIAS(const Cfg *Func) const override; |
| 2527 static bool classof(const Inst *Inst) { | 2528 void dump(const Cfg *Func) const override; |
| 2528 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Ucomiss); | 2529 static bool classof(const Inst *Inst) { |
| 2529 } | 2530 return InstX86Base::isClassof(Inst, InstX86Base::Nop); |
| 2530 | 2531 } |
| 2531 private: | 2532 |
| 2532 InstX86Ucomiss(Cfg *Func, Operand *Src1, Operand *Src2); | 2533 private: |
| 2533 }; | 2534 InstX86Nop(Cfg *Func, SizeT Length); |
| 2534 | 2535 |
| 2535 /// UD2 instruction. | 2536 NopVariant Variant; |
| 2536 template <class Machine> class InstX86UD2 final : public InstX86Base<Machine> { | 2537 }; |
| 2537 InstX86UD2() = delete; | 2538 |
| 2538 InstX86UD2(const InstX86UD2 &) = delete; | 2539 /// Fld - load a value onto the x87 FP stack. |
| 2539 InstX86UD2 &operator=(const InstX86UD2 &) = delete; | 2540 class InstX86Fld final : public InstX86Base { |
| 2540 | 2541 InstX86Fld() = delete; |
| 2541 public: | 2542 InstX86Fld(const InstX86Fld &) = delete; |
| 2542 static InstX86UD2 *create(Cfg *Func) { | 2543 InstX86Fld &operator=(const InstX86Fld &) = delete; |
| 2543 return new (Func->allocate<InstX86UD2>()) InstX86UD2(Func); | 2544 |
| 2544 } | 2545 public: |
| 2545 void emit(const Cfg *Func) const override; | 2546 static InstX86Fld *create(Cfg *Func, Operand *Src) { |
| 2546 void emitIAS(const Cfg *Func) const override; | 2547 return new (Func->allocate<InstX86Fld>()) InstX86Fld(Func, Src); |
| 2547 void dump(const Cfg *Func) const override; | 2548 } |
| 2548 static bool classof(const Inst *Inst) { | 2549 void emit(const Cfg *Func) const override; |
| 2549 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::UD2); | 2550 void emitIAS(const Cfg *Func) const override; |
| 2550 } | 2551 void dump(const Cfg *Func) const override; |
| 2551 | 2552 static bool classof(const Inst *Inst) { |
| 2552 private: | 2553 return InstX86Base::isClassof(Inst, InstX86Base::Fld); |
| 2553 explicit InstX86UD2(Cfg *Func); | 2554 } |
| 2554 }; | 2555 |
| 2555 | 2556 private: |
| 2556 /// Test instruction. | 2557 InstX86Fld(Cfg *Func, Operand *Src); |
| 2557 template <class Machine> class InstX86Test final : public InstX86Base<Machine> { | 2558 }; |
| 2558 InstX86Test() = delete; | 2559 |
| 2559 InstX86Test(const InstX86Test &) = delete; | 2560 /// Fstp - store x87 st(0) into memory and pop st(0). |
| 2560 InstX86Test &operator=(const InstX86Test &) = delete; | 2561 class InstX86Fstp final : public InstX86Base { |
| 2561 | 2562 InstX86Fstp() = delete; |
| 2562 public: | 2563 InstX86Fstp(const InstX86Fstp &) = delete; |
| 2563 static InstX86Test *create(Cfg *Func, Operand *Source1, Operand *Source2) { | 2564 InstX86Fstp &operator=(const InstX86Fstp &) = delete; |
| 2564 return new (Func->allocate<InstX86Test>()) | 2565 |
| 2565 InstX86Test(Func, Source1, Source2); | 2566 public: |
| 2566 } | 2567 static InstX86Fstp *create(Cfg *Func, Variable *Dest) { |
| 2567 void emit(const Cfg *Func) const override; | 2568 return new (Func->allocate<InstX86Fstp>()) InstX86Fstp(Func, Dest); |
| 2568 void emitIAS(const Cfg *Func) const override; | 2569 } |
| 2569 void dump(const Cfg *Func) const override; | 2570 void emit(const Cfg *Func) const override; |
| 2570 static bool classof(const Inst *Inst) { | 2571 void emitIAS(const Cfg *Func) const override; |
| 2571 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Test); | 2572 void dump(const Cfg *Func) const override; |
| 2572 } | 2573 static bool classof(const Inst *Inst) { |
| 2573 | 2574 return InstX86Base::isClassof(Inst, InstX86Base::Fstp); |
| 2574 private: | 2575 } |
| 2575 InstX86Test(Cfg *Func, Operand *Source1, Operand *Source2); | 2576 |
| 2576 }; | 2577 private: |
| 2577 | 2578 InstX86Fstp(Cfg *Func, Variable *Dest); |
| 2578 /// Mfence instruction. | 2579 }; |
| 2579 template <class Machine> | 2580 |
| 2580 class InstX86Mfence final : public InstX86Base<Machine> { | 2581 class InstX86Pop final : public InstX86Base { |
| 2581 InstX86Mfence() = delete; | 2582 InstX86Pop() = delete; |
| 2582 InstX86Mfence(const InstX86Mfence &) = delete; | 2583 InstX86Pop(const InstX86Pop &) = delete; |
| 2583 InstX86Mfence &operator=(const InstX86Mfence &) = delete; | 2584 InstX86Pop &operator=(const InstX86Pop &) = delete; |
| 2584 | 2585 |
| 2585 public: | 2586 public: |
| 2586 static InstX86Mfence *create(Cfg *Func) { | 2587 static InstX86Pop *create(Cfg *Func, Variable *Dest) { |
| 2587 return new (Func->allocate<InstX86Mfence>()) InstX86Mfence(Func); | 2588 return new (Func->allocate<InstX86Pop>()) InstX86Pop(Func, Dest); |
| 2588 } | 2589 } |
| 2589 void emit(const Cfg *Func) const override; | 2590 void emit(const Cfg *Func) const override; |
| 2590 void emitIAS(const Cfg *Func) const override; | 2591 void emitIAS(const Cfg *Func) const override; |
| 2591 void dump(const Cfg *Func) const override; | 2592 void dump(const Cfg *Func) const override; |
| 2592 static bool classof(const Inst *Inst) { | 2593 static bool classof(const Inst *Inst) { |
| 2593 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Mfence); | 2594 return InstX86Base::isClassof(Inst, InstX86Base::Pop); |
| 2594 } | 2595 } |
| 2595 | 2596 |
| 2596 private: | 2597 private: |
| 2597 explicit InstX86Mfence(Cfg *Func); | 2598 InstX86Pop(Cfg *Func, Variable *Dest); |
| 2598 }; | 2599 }; |
| 2599 | 2600 |
| 2600 /// This is essentially a "mov" instruction with an | 2601 class InstX86Push final : public InstX86Base { |
| 2601 /// InstX86Base<Machine>::Traits::X86OperandMem operand instead of Variable as | 2602 InstX86Push() = delete; |
| 2602 /// the destination. It's important for liveness that there is no Dest operand. | 2603 InstX86Push(const InstX86Push &) = delete; |
| 2603 template <class Machine> | 2604 InstX86Push &operator=(const InstX86Push &) = delete; |
| 2604 class InstX86Store final : public InstX86Base<Machine> { | 2605 |
| 2605 InstX86Store() = delete; | 2606 public: |
| 2606 InstX86Store(const InstX86Store &) = delete; | 2607 static InstX86Push *create(Cfg *Func, Variable *Source) { |
| 2607 InstX86Store &operator=(const InstX86Store &) = delete; | 2608 return new (Func->allocate<InstX86Push>()) InstX86Push(Func, Source); |
| 2608 | 2609 } |
| 2609 public: | 2610 void emit(const Cfg *Func) const override; |
| 2610 static InstX86Store * | 2611 void emitIAS(const Cfg *Func) const override; |
| 2611 create(Cfg *Func, Operand *Value, | 2612 void dump(const Cfg *Func) const override; |
| 2612 typename InstX86Base<Machine>::Traits::X86Operand *Mem) { | 2613 static bool classof(const Inst *Inst) { |
| 2613 return new (Func->allocate<InstX86Store>()) InstX86Store(Func, Value, Mem); | 2614 return InstX86Base::isClassof(Inst, InstX86Base::Push); |
| 2614 } | 2615 } |
| 2615 void emit(const Cfg *Func) const override; | 2616 |
| 2616 void emitIAS(const Cfg *Func) const override; | 2617 private: |
| 2617 void dump(const Cfg *Func) const override; | 2618 InstX86Push(Cfg *Func, Variable *Source); |
| 2618 static bool classof(const Inst *Inst) { | 2619 }; |
| 2619 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Store); | 2620 |
| 2620 } | 2621 /// Ret instruction. Currently only supports the "ret" version that does not |
| 2621 | 2622 /// pop arguments. This instruction takes a Source operand (for non-void |
| 2622 private: | 2623 /// returning functions) for liveness analysis, though a FakeUse before the |
| 2623 InstX86Store(Cfg *Func, Operand *Value, | 2624 /// ret would do just as well. |
| 2624 typename InstX86Base<Machine>::Traits::X86Operand *Mem); | 2625 class InstX86Ret final : public InstX86Base { |
| 2625 }; | 2626 InstX86Ret() = delete; |
| 2626 | 2627 InstX86Ret(const InstX86Ret &) = delete; |
| 2627 /// This is essentially a vector "mov" instruction with an typename | 2628 InstX86Ret &operator=(const InstX86Ret &) = delete; |
| 2628 /// InstX86Base<Machine>::Traits::X86OperandMem operand instead of Variable as | 2629 |
| 2629 /// the destination. It's important for liveness that there is no Dest operand. | 2630 public: |
| 2630 /// The source must be an Xmm register, since Dest is mem. | 2631 static InstX86Ret *create(Cfg *Func, Variable *Source = nullptr) { |
| 2631 template <class Machine> | 2632 return new (Func->allocate<InstX86Ret>()) InstX86Ret(Func, Source); |
| 2632 class InstX86StoreP final : public InstX86Base<Machine> { | 2633 } |
| 2633 InstX86StoreP() = delete; | 2634 void emit(const Cfg *Func) const override; |
| 2634 InstX86StoreP(const InstX86StoreP &) = delete; | 2635 void emitIAS(const Cfg *Func) const override; |
| 2635 InstX86StoreP &operator=(const InstX86StoreP &) = delete; | 2636 void dump(const Cfg *Func) const override; |
| 2636 | 2637 static bool classof(const Inst *Inst) { |
| 2637 public: | 2638 return InstX86Base::isClassof(Inst, InstX86Base::Ret); |
| 2638 static InstX86StoreP * | 2639 } |
| 2639 create(Cfg *Func, Variable *Value, | 2640 |
| 2640 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem) { | 2641 private: |
| 2641 return new (Func->allocate<InstX86StoreP>()) | 2642 InstX86Ret(Cfg *Func, Variable *Source); |
| 2642 InstX86StoreP(Func, Value, Mem); | 2643 }; |
| 2643 } | 2644 |
| 2644 void emit(const Cfg *Func) const override; | 2645 /// Conditional set-byte instruction. |
| 2645 void emitIAS(const Cfg *Func) const override; | 2646 class InstX86Setcc final : public InstX86Base { |
| 2646 void dump(const Cfg *Func) const override; | 2647 InstX86Setcc() = delete; |
| 2647 static bool classof(const Inst *Inst) { | 2648 InstX86Setcc(const InstX86Cmov &) = delete; |
| 2648 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::StoreP); | 2649 InstX86Setcc &operator=(const InstX86Setcc &) = delete; |
| 2649 } | 2650 |
| 2650 | 2651 public: |
| 2651 private: | 2652 static InstX86Setcc *create(Cfg *Func, Variable *Dest, BrCond Cond) { |
| 2652 InstX86StoreP(Cfg *Func, Variable *Value, | 2653 return new (Func->allocate<InstX86Setcc>()) |
| 2653 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem); | 2654 InstX86Setcc(Func, Dest, Cond); |
| 2654 }; | 2655 } |
| 2655 | 2656 void emit(const Cfg *Func) const override; |
| 2656 template <class Machine> | 2657 void emitIAS(const Cfg *Func) const override; |
| 2657 class InstX86StoreQ final : public InstX86Base<Machine> { | 2658 void dump(const Cfg *Func) const override; |
| 2658 InstX86StoreQ() = delete; | 2659 static bool classof(const Inst *Inst) { |
| 2659 InstX86StoreQ(const InstX86StoreQ &) = delete; | 2660 return InstX86Base::isClassof(Inst, InstX86Base::Setcc); |
| 2660 InstX86StoreQ &operator=(const InstX86StoreQ &) = delete; | 2661 } |
| 2661 | 2662 |
| 2662 public: | 2663 private: |
| 2663 static InstX86StoreQ * | 2664 InstX86Setcc(Cfg *Func, Variable *Dest, BrCond Cond); |
| 2664 create(Cfg *Func, Variable *Value, | 2665 |
| 2665 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem) { | 2666 const BrCond Condition; |
| 2666 return new (Func->allocate<InstX86StoreQ>()) | 2667 }; |
| 2667 InstX86StoreQ(Func, Value, Mem); | 2668 |
| 2668 } | 2669 /// Exchanging Add instruction. Exchanges the first operand (destination |
| 2669 void emit(const Cfg *Func) const override; | 2670 /// operand) with the second operand (source operand), then loads the sum of |
| 2670 void emitIAS(const Cfg *Func) const override; | 2671 /// the two values into the destination operand. The destination may be a |
| 2671 void dump(const Cfg *Func) const override; | 2672 /// register or memory, while the source must be a register. |
| 2672 static bool classof(const Inst *Inst) { | 2673 /// |
| 2673 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::StoreQ); | 2674 /// Both the dest and source are updated. The caller should then insert a |
| 2674 } | 2675 /// FakeDef to reflect the second udpate. |
| 2675 | 2676 class InstX86Xadd final : public InstX86BaseLockable { |
| 2676 private: | 2677 InstX86Xadd() = delete; |
| 2677 InstX86StoreQ(Cfg *Func, Variable *Value, | 2678 InstX86Xadd(const InstX86Xadd &) = delete; |
| 2678 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem); | 2679 InstX86Xadd &operator=(const InstX86Xadd &) = delete; |
| 2679 }; | 2680 |
| 2680 | 2681 public: |
| 2681 /// Nop instructions of varying length | 2682 static InstX86Xadd *create(Cfg *Func, Operand *Dest, Variable *Source, |
| 2682 template <class Machine> class InstX86Nop final : public InstX86Base<Machine> { | 2683 bool Locked) { |
| 2683 InstX86Nop() = delete; | 2684 return new (Func->allocate<InstX86Xadd>()) |
| 2684 InstX86Nop(const InstX86Nop &) = delete; | 2685 InstX86Xadd(Func, Dest, Source, Locked); |
| 2685 InstX86Nop &operator=(const InstX86Nop &) = delete; | 2686 } |
| 2686 | 2687 void emit(const Cfg *Func) const override; |
| 2687 public: | 2688 void emitIAS(const Cfg *Func) const override; |
| 2688 // TODO: Replace with enum. | 2689 void dump(const Cfg *Func) const override; |
| 2689 using NopVariant = unsigned; | 2690 static bool classof(const Inst *Inst) { |
| 2690 | 2691 return InstX86Base::isClassof(Inst, InstX86Base::Xadd); |
| 2691 static InstX86Nop *create(Cfg *Func, NopVariant Variant) { | 2692 } |
| 2692 return new (Func->allocate<InstX86Nop>()) InstX86Nop(Func, Variant); | 2693 |
| 2693 } | 2694 private: |
| 2694 void emit(const Cfg *Func) const override; | 2695 InstX86Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked); |
| 2695 void emitIAS(const Cfg *Func) const override; | 2696 }; |
| 2696 void dump(const Cfg *Func) const override; | 2697 |
| 2697 static bool classof(const Inst *Inst) { | 2698 /// Exchange instruction. Exchanges the first operand (destination operand) |
| 2698 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Nop); | 2699 /// with the second operand (source operand). At least one of the operands |
| 2699 } | 2700 /// must be a register (and the other can be reg or mem). Both the Dest and |
| 2700 | 2701 /// Source are updated. If there is a memory operand, then the instruction is |
| 2701 private: | 2702 /// automatically "locked" without the need for a lock prefix. |
| 2702 InstX86Nop(Cfg *Func, SizeT Length); | 2703 class InstX86Xchg final : public InstX86Base { |
| 2703 | 2704 InstX86Xchg() = delete; |
| 2704 NopVariant Variant; | 2705 InstX86Xchg(const InstX86Xchg &) = delete; |
| 2705 }; | 2706 InstX86Xchg &operator=(const InstX86Xchg &) = delete; |
| 2706 | 2707 |
| 2707 /// Fld - load a value onto the x87 FP stack. | 2708 public: |
| 2708 template <class Machine> class InstX86Fld final : public InstX86Base<Machine> { | 2709 static InstX86Xchg *create(Cfg *Func, Operand *Dest, Variable *Source) { |
| 2709 InstX86Fld() = delete; | 2710 return new (Func->allocate<InstX86Xchg>()) |
| 2710 InstX86Fld(const InstX86Fld &) = delete; | 2711 InstX86Xchg(Func, Dest, Source); |
| 2711 InstX86Fld &operator=(const InstX86Fld &) = delete; | 2712 } |
| 2712 | 2713 void emit(const Cfg *Func) const override; |
| 2713 public: | 2714 void emitIAS(const Cfg *Func) const override; |
| 2714 static InstX86Fld *create(Cfg *Func, Operand *Src) { | 2715 void dump(const Cfg *Func) const override; |
| 2715 return new (Func->allocate<InstX86Fld>()) InstX86Fld(Func, Src); | 2716 static bool classof(const Inst *Inst) { |
| 2716 } | 2717 return InstX86Base::isClassof(Inst, InstX86Base::Xchg); |
| 2717 void emit(const Cfg *Func) const override; | 2718 } |
| 2718 void emitIAS(const Cfg *Func) const override; | 2719 |
| 2719 void dump(const Cfg *Func) const override; | 2720 private: |
| 2720 static bool classof(const Inst *Inst) { | 2721 InstX86Xchg(Cfg *Func, Operand *Dest, Variable *Source); |
| 2721 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Fld); | 2722 }; |
| 2722 } | 2723 |
| 2723 | 2724 /// Start marker for the Intel Architecture Code Analyzer. This is not an |
| 2724 private: | 2725 /// executable instruction and must only be used for analysis. |
| 2725 InstX86Fld(Cfg *Func, Operand *Src); | 2726 class InstX86IacaStart final : public InstX86Base { |
| 2726 }; | 2727 InstX86IacaStart() = delete; |
| 2727 | 2728 InstX86IacaStart(const InstX86IacaStart &) = delete; |
| 2728 /// Fstp - store x87 st(0) into memory and pop st(0). | 2729 InstX86IacaStart &operator=(const InstX86IacaStart &) = delete; |
| 2729 template <class Machine> class InstX86Fstp final : public InstX86Base<Machine> { | 2730 |
| 2730 InstX86Fstp() = delete; | 2731 public: |
| 2731 InstX86Fstp(const InstX86Fstp &) = delete; | 2732 static InstX86IacaStart *create(Cfg *Func) { |
| 2732 InstX86Fstp &operator=(const InstX86Fstp &) = delete; | 2733 return new (Func->allocate<InstX86IacaStart>()) InstX86IacaStart(Func); |
| 2733 | 2734 } |
| 2734 public: | 2735 void emit(const Cfg *Func) const override; |
| 2735 static InstX86Fstp *create(Cfg *Func, Variable *Dest) { | 2736 void emitIAS(const Cfg *Func) const override; |
| 2736 return new (Func->allocate<InstX86Fstp>()) InstX86Fstp(Func, Dest); | 2737 void dump(const Cfg *Func) const override; |
| 2737 } | 2738 static bool classof(const Inst *Inst) { |
| 2738 void emit(const Cfg *Func) const override; | 2739 return InstX86Base::isClassof(Inst, InstX86Base::IacaStart); |
| 2739 void emitIAS(const Cfg *Func) const override; | 2740 } |
| 2740 void dump(const Cfg *Func) const override; | 2741 |
| 2741 static bool classof(const Inst *Inst) { | 2742 private: |
| 2742 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Fstp); | 2743 InstX86IacaStart(Cfg *Func); |
| 2743 } | 2744 }; |
| 2744 | 2745 |
| 2745 private: | 2746 /// End marker for the Intel Architecture Code Analyzer. This is not an |
| 2746 InstX86Fstp(Cfg *Func, Variable *Dest); | 2747 /// executable instruction and must only be used for analysis. |
| 2747 }; | 2748 class InstX86IacaEnd final : public InstX86Base { |
| 2748 | 2749 InstX86IacaEnd() = delete; |
| 2749 template <class Machine> class InstX86Pop final : public InstX86Base<Machine> { | 2750 InstX86IacaEnd(const InstX86IacaEnd &) = delete; |
| 2750 InstX86Pop() = delete; | 2751 InstX86IacaEnd &operator=(const InstX86IacaEnd &) = delete; |
| 2751 InstX86Pop(const InstX86Pop &) = delete; | 2752 |
| 2752 InstX86Pop &operator=(const InstX86Pop &) = delete; | 2753 public: |
| 2753 | 2754 static InstX86IacaEnd *create(Cfg *Func) { |
| 2754 public: | 2755 return new (Func->allocate<InstX86IacaEnd>()) InstX86IacaEnd(Func); |
| 2755 static InstX86Pop *create(Cfg *Func, Variable *Dest) { | 2756 } |
| 2756 return new (Func->allocate<InstX86Pop>()) InstX86Pop(Func, Dest); | 2757 void emit(const Cfg *Func) const override; |
| 2757 } | 2758 void emitIAS(const Cfg *Func) const override; |
| 2758 void emit(const Cfg *Func) const override; | 2759 void dump(const Cfg *Func) const override; |
| 2759 void emitIAS(const Cfg *Func) const override; | 2760 static bool classof(const Inst *Inst) { |
| 2760 void dump(const Cfg *Func) const override; | 2761 return InstX86Base::isClassof(Inst, InstX86Base::IacaEnd); |
| 2761 static bool classof(const Inst *Inst) { | 2762 } |
| 2762 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Pop); | 2763 |
| 2763 } | 2764 private: |
| 2764 | 2765 InstX86IacaEnd(Cfg *Func); |
| 2765 private: | 2766 }; |
| 2766 InstX86Pop(Cfg *Func, Variable *Dest); | 2767 }; // struct InstImpl |
| 2767 }; | |
| 2768 | |
| 2769 template <class Machine> class InstX86Push final : public InstX86Base<Machine> { | |
| 2770 InstX86Push() = delete; | |
| 2771 InstX86Push(const InstX86Push &) = delete; | |
| 2772 InstX86Push &operator=(const InstX86Push &) = delete; | |
| 2773 | |
| 2774 public: | |
| 2775 static InstX86Push *create(Cfg *Func, Variable *Source) { | |
| 2776 return new (Func->allocate<InstX86Push>()) InstX86Push(Func, Source); | |
| 2777 } | |
| 2778 void emit(const Cfg *Func) const override; | |
| 2779 void emitIAS(const Cfg *Func) const override; | |
| 2780 void dump(const Cfg *Func) const override; | |
| 2781 static bool classof(const Inst *Inst) { | |
| 2782 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Push); | |
| 2783 } | |
| 2784 | |
| 2785 private: | |
| 2786 InstX86Push(Cfg *Func, Variable *Source); | |
| 2787 }; | |
| 2788 | |
| 2789 /// Ret instruction. Currently only supports the "ret" version that does not pop | |
| 2790 /// arguments. This instruction takes a Source operand (for non-void returning | |
| 2791 /// functions) for liveness analysis, though a FakeUse before the ret would do | |
| 2792 /// just as well. | |
| 2793 template <class Machine> class InstX86Ret final : public InstX86Base<Machine> { | |
| 2794 InstX86Ret() = delete; | |
| 2795 InstX86Ret(const InstX86Ret &) = delete; | |
| 2796 InstX86Ret &operator=(const InstX86Ret &) = delete; | |
| 2797 | |
| 2798 public: | |
| 2799 static InstX86Ret *create(Cfg *Func, Variable *Source = nullptr) { | |
| 2800 return new (Func->allocate<InstX86Ret>()) InstX86Ret(Func, Source); | |
| 2801 } | |
| 2802 void emit(const Cfg *Func) const override; | |
| 2803 void emitIAS(const Cfg *Func) const override; | |
| 2804 void dump(const Cfg *Func) const override; | |
| 2805 static bool classof(const Inst *Inst) { | |
| 2806 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Ret); | |
| 2807 } | |
| 2808 | |
| 2809 private: | |
| 2810 InstX86Ret(Cfg *Func, Variable *Source); | |
| 2811 }; | |
| 2812 | |
| 2813 /// Conditional set-byte instruction. | |
| 2814 template <class Machine> | |
| 2815 class InstX86Setcc final : public InstX86Base<Machine> { | |
| 2816 InstX86Setcc() = delete; | |
| 2817 InstX86Setcc(const InstX86Cmov<Machine> &) = delete; | |
| 2818 InstX86Setcc &operator=(const InstX86Setcc &) = delete; | |
| 2819 | |
| 2820 public: | |
| 2821 static InstX86Setcc * | |
| 2822 create(Cfg *Func, Variable *Dest, | |
| 2823 typename InstX86Base<Machine>::Traits::Cond::BrCond Cond) { | |
| 2824 return new (Func->allocate<InstX86Setcc>()) InstX86Setcc(Func, Dest, Cond); | |
| 2825 } | |
| 2826 void emit(const Cfg *Func) const override; | |
| 2827 void emitIAS(const Cfg *Func) const override; | |
| 2828 void dump(const Cfg *Func) const override; | |
| 2829 static bool classof(const Inst *Inst) { | |
| 2830 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Setcc); | |
| 2831 } | |
| 2832 | |
| 2833 private: | |
| 2834 InstX86Setcc(Cfg *Func, Variable *Dest, | |
| 2835 typename InstX86Base<Machine>::Traits::Cond::BrCond Cond); | |
| 2836 | |
| 2837 const typename InstX86Base<Machine>::Traits::Cond::BrCond Condition; | |
| 2838 }; | |
| 2839 | |
| 2840 /// Exchanging Add instruction. Exchanges the first operand (destination | |
| 2841 /// operand) with the second operand (source operand), then loads the sum of the | |
| 2842 /// two values into the destination operand. The destination may be a register | |
| 2843 /// or memory, while the source must be a register. | |
| 2844 /// | |
| 2845 /// Both the dest and source are updated. The caller should then insert a | |
| 2846 /// FakeDef to reflect the second udpate. | |
| 2847 template <class Machine> | |
| 2848 class InstX86Xadd final : public InstX86BaseLockable<Machine> { | |
| 2849 InstX86Xadd() = delete; | |
| 2850 InstX86Xadd(const InstX86Xadd &) = delete; | |
| 2851 InstX86Xadd &operator=(const InstX86Xadd &) = delete; | |
| 2852 | |
| 2853 public: | |
| 2854 static InstX86Xadd *create(Cfg *Func, Operand *Dest, Variable *Source, | |
| 2855 bool Locked) { | |
| 2856 return new (Func->allocate<InstX86Xadd>()) | |
| 2857 InstX86Xadd(Func, Dest, Source, Locked); | |
| 2858 } | |
| 2859 void emit(const Cfg *Func) const override; | |
| 2860 void emitIAS(const Cfg *Func) const override; | |
| 2861 void dump(const Cfg *Func) const override; | |
| 2862 static bool classof(const Inst *Inst) { | |
| 2863 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Xadd); | |
| 2864 } | |
| 2865 | |
| 2866 private: | |
| 2867 InstX86Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked); | |
| 2868 }; | |
| 2869 | |
| 2870 /// Exchange instruction. Exchanges the first operand (destination operand) with | |
| 2871 /// the second operand (source operand). At least one of the operands must be a | |
| 2872 /// register (and the other can be reg or mem). Both the Dest and Source are | |
| 2873 /// updated. If there is a memory operand, then the instruction is automatically | |
| 2874 /// "locked" without the need for a lock prefix. | |
| 2875 template <class Machine> class InstX86Xchg final : public InstX86Base<Machine> { | |
| 2876 InstX86Xchg() = delete; | |
| 2877 InstX86Xchg(const InstX86Xchg &) = delete; | |
| 2878 InstX86Xchg &operator=(const InstX86Xchg &) = delete; | |
| 2879 | |
| 2880 public: | |
| 2881 static InstX86Xchg *create(Cfg *Func, Operand *Dest, Variable *Source) { | |
| 2882 return new (Func->allocate<InstX86Xchg>()) InstX86Xchg(Func, Dest, Source); | |
| 2883 } | |
| 2884 void emit(const Cfg *Func) const override; | |
| 2885 void emitIAS(const Cfg *Func) const override; | |
| 2886 void dump(const Cfg *Func) const override; | |
| 2887 static bool classof(const Inst *Inst) { | |
| 2888 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::Xchg); | |
| 2889 } | |
| 2890 | |
| 2891 private: | |
| 2892 InstX86Xchg(Cfg *Func, Operand *Dest, Variable *Source); | |
| 2893 }; | |
| 2894 | |
| 2895 /// Start marker for the Intel Architecture Code Analyzer. This is not an | |
| 2896 /// executable instruction and must only be used for analysis. | |
| 2897 template <class Machine> | |
| 2898 class InstX86IacaStart final : public InstX86Base<Machine> { | |
| 2899 InstX86IacaStart() = delete; | |
| 2900 InstX86IacaStart(const InstX86IacaStart &) = delete; | |
| 2901 InstX86IacaStart &operator=(const InstX86IacaStart &) = delete; | |
| 2902 | |
| 2903 public: | |
| 2904 static InstX86IacaStart *create(Cfg *Func) { | |
| 2905 return new (Func->allocate<InstX86IacaStart>()) InstX86IacaStart(Func); | |
| 2906 } | |
| 2907 void emit(const Cfg *Func) const override; | |
| 2908 void emitIAS(const Cfg *Func) const override; | |
| 2909 void dump(const Cfg *Func) const override; | |
| 2910 static bool classof(const Inst *Inst) { | |
| 2911 return InstX86Base<Machine>::isClassof(Inst, | |
| 2912 InstX86Base<Machine>::IacaStart); | |
| 2913 } | |
| 2914 | |
| 2915 private: | |
| 2916 InstX86IacaStart(Cfg *Func); | |
| 2917 }; | |
| 2918 | |
| 2919 /// End marker for the Intel Architecture Code Analyzer. This is not an | |
| 2920 /// executable instruction and must only be used for analysis. | |
| 2921 template <class Machine> | |
| 2922 class InstX86IacaEnd final : public InstX86Base<Machine> { | |
| 2923 InstX86IacaEnd() = delete; | |
| 2924 InstX86IacaEnd(const InstX86IacaEnd &) = delete; | |
| 2925 InstX86IacaEnd &operator=(const InstX86IacaEnd &) = delete; | |
| 2926 | |
| 2927 public: | |
| 2928 static InstX86IacaEnd *create(Cfg *Func) { | |
| 2929 return new (Func->allocate<InstX86IacaEnd>()) InstX86IacaEnd(Func); | |
| 2930 } | |
| 2931 void emit(const Cfg *Func) const override; | |
| 2932 void emitIAS(const Cfg *Func) const override; | |
| 2933 void dump(const Cfg *Func) const override; | |
| 2934 static bool classof(const Inst *Inst) { | |
| 2935 return InstX86Base<Machine>::isClassof(Inst, InstX86Base<Machine>::IacaEnd); | |
| 2936 } | |
| 2937 | |
| 2938 private: | |
| 2939 InstX86IacaEnd(Cfg *Func); | |
| 2940 }; | |
| 2941 | 2768 |
| 2942 /// struct Insts is a template that can be used to instantiate all the X86 | 2769 /// struct Insts is a template that can be used to instantiate all the X86 |
| 2943 /// instructions for a target with a simple | 2770 /// instructions for a target with a simple |
| 2944 /// | 2771 /// |
| 2945 /// using Insts = ::Ice::X86Internal::Insts<TargeT>; | 2772 /// using Insts = ::Ice::X86NAMESPACE::Insts<TraitsType>; |
| 2946 template <class Machine> struct Insts { | 2773 template <typename TraitsType> struct Insts { |
| 2947 using FakeRMW = InstX86FakeRMW<Machine>; | 2774 using FakeRMW = typename InstImpl<TraitsType>::InstX86FakeRMW; |
| 2948 using Label = InstX86Label<Machine>; | 2775 using Label = typename InstImpl<TraitsType>::InstX86Label; |
| 2949 | 2776 |
| 2950 using Call = InstX86Call<Machine>; | 2777 using Call = typename InstImpl<TraitsType>::InstX86Call; |
| 2951 | 2778 |
| 2952 using Br = InstX86Br<Machine>; | 2779 using Br = typename InstImpl<TraitsType>::InstX86Br; |
| 2953 using Jmp = InstX86Jmp<Machine>; | 2780 using Jmp = typename InstImpl<TraitsType>::InstX86Jmp; |
| 2954 using Bswap = InstX86Bswap<Machine>; | 2781 using Bswap = typename InstImpl<TraitsType>::InstX86Bswap; |
| 2955 using Neg = InstX86Neg<Machine>; | 2782 using Neg = typename InstImpl<TraitsType>::InstX86Neg; |
| 2956 using Bsf = InstX86Bsf<Machine>; | 2783 using Bsf = typename InstImpl<TraitsType>::InstX86Bsf; |
| 2957 using Bsr = InstX86Bsr<Machine>; | 2784 using Bsr = typename InstImpl<TraitsType>::InstX86Bsr; |
| 2958 using Lea = InstX86Lea<Machine>; | 2785 using Lea = typename InstImpl<TraitsType>::InstX86Lea; |
| 2959 using Cbwdq = InstX86Cbwdq<Machine>; | 2786 using Cbwdq = typename InstImpl<TraitsType>::InstX86Cbwdq; |
| 2960 using Movsx = InstX86Movsx<Machine>; | 2787 using Movsx = typename InstImpl<TraitsType>::InstX86Movsx; |
| 2961 using Movzx = InstX86Movzx<Machine>; | 2788 using Movzx = typename InstImpl<TraitsType>::InstX86Movzx; |
| 2962 using Movd = InstX86Movd<Machine>; | 2789 using Movd = typename InstImpl<TraitsType>::InstX86Movd; |
| 2963 using Sqrtss = InstX86Sqrtss<Machine>; | 2790 using Sqrtss = typename InstImpl<TraitsType>::InstX86Sqrtss; |
| 2964 using Mov = InstX86Mov<Machine>; | 2791 using Mov = typename InstImpl<TraitsType>::InstX86Mov; |
| 2965 using Movp = InstX86Movp<Machine>; | 2792 using Movp = typename InstImpl<TraitsType>::InstX86Movp; |
| 2966 using Movq = InstX86Movq<Machine>; | 2793 using Movq = typename InstImpl<TraitsType>::InstX86Movq; |
| 2967 using Add = InstX86Add<Machine>; | 2794 using Add = typename InstImpl<TraitsType>::InstX86Add; |
| 2968 using AddRMW = InstX86AddRMW<Machine>; | 2795 using AddRMW = typename InstImpl<TraitsType>::InstX86AddRMW; |
| 2969 using Addps = InstX86Addps<Machine>; | 2796 using Addps = typename InstImpl<TraitsType>::InstX86Addps; |
| 2970 using Adc = InstX86Adc<Machine>; | 2797 using Adc = typename InstImpl<TraitsType>::InstX86Adc; |
| 2971 using AdcRMW = InstX86AdcRMW<Machine>; | 2798 using AdcRMW = typename InstImpl<TraitsType>::InstX86AdcRMW; |
| 2972 using Addss = InstX86Addss<Machine>; | 2799 using Addss = typename InstImpl<TraitsType>::InstX86Addss; |
| 2973 using Andnps = InstX86Andnps<Machine>; | 2800 using Andnps = typename InstImpl<TraitsType>::InstX86Andnps; |
| 2974 using Andps = InstX86Andps<Machine>; | 2801 using Andps = typename InstImpl<TraitsType>::InstX86Andps; |
| 2975 using Padd = InstX86Padd<Machine>; | 2802 using Padd = typename InstImpl<TraitsType>::InstX86Padd; |
| 2976 using Sub = InstX86Sub<Machine>; | 2803 using Sub = typename InstImpl<TraitsType>::InstX86Sub; |
| 2977 using SubRMW = InstX86SubRMW<Machine>; | 2804 using SubRMW = typename InstImpl<TraitsType>::InstX86SubRMW; |
| 2978 using Subps = InstX86Subps<Machine>; | 2805 using Subps = typename InstImpl<TraitsType>::InstX86Subps; |
| 2979 using Subss = InstX86Subss<Machine>; | 2806 using Subss = typename InstImpl<TraitsType>::InstX86Subss; |
| 2980 using Sbb = InstX86Sbb<Machine>; | 2807 using Sbb = typename InstImpl<TraitsType>::InstX86Sbb; |
| 2981 using SbbRMW = InstX86SbbRMW<Machine>; | 2808 using SbbRMW = typename InstImpl<TraitsType>::InstX86SbbRMW; |
| 2982 using Psub = InstX86Psub<Machine>; | 2809 using Psub = typename InstImpl<TraitsType>::InstX86Psub; |
| 2983 using And = InstX86And<Machine>; | 2810 using And = typename InstImpl<TraitsType>::InstX86And; |
| 2984 using AndRMW = InstX86AndRMW<Machine>; | 2811 using AndRMW = typename InstImpl<TraitsType>::InstX86AndRMW; |
| 2985 using Pand = InstX86Pand<Machine>; | 2812 using Pand = typename InstImpl<TraitsType>::InstX86Pand; |
| 2986 using Pandn = InstX86Pandn<Machine>; | 2813 using Pandn = typename InstImpl<TraitsType>::InstX86Pandn; |
| 2987 using Or = InstX86Or<Machine>; | 2814 using Or = typename InstImpl<TraitsType>::InstX86Or; |
| 2988 using Orps = InstX86Orps<Machine>; | 2815 using Orps = typename InstImpl<TraitsType>::InstX86Orps; |
| 2989 using OrRMW = InstX86OrRMW<Machine>; | 2816 using OrRMW = typename InstImpl<TraitsType>::InstX86OrRMW; |
| 2990 using Por = InstX86Por<Machine>; | 2817 using Por = typename InstImpl<TraitsType>::InstX86Por; |
| 2991 using Xor = InstX86Xor<Machine>; | 2818 using Xor = typename InstImpl<TraitsType>::InstX86Xor; |
| 2992 using Xorps = InstX86Xorps<Machine>; | 2819 using Xorps = typename InstImpl<TraitsType>::InstX86Xorps; |
| 2993 using XorRMW = InstX86XorRMW<Machine>; | 2820 using XorRMW = typename InstImpl<TraitsType>::InstX86XorRMW; |
| 2994 using Pxor = InstX86Pxor<Machine>; | 2821 using Pxor = typename InstImpl<TraitsType>::InstX86Pxor; |
| 2995 using Maxss = InstX86Maxss<Machine>; | 2822 using Maxss = typename InstImpl<TraitsType>::InstX86Maxss; |
| 2996 using Minss = InstX86Minss<Machine>; | 2823 using Minss = typename InstImpl<TraitsType>::InstX86Minss; |
| 2997 using Imul = InstX86Imul<Machine>; | 2824 using Imul = typename InstImpl<TraitsType>::InstX86Imul; |
| 2998 using ImulImm = InstX86ImulImm<Machine>; | 2825 using ImulImm = typename InstImpl<TraitsType>::InstX86ImulImm; |
| 2999 using Mulps = InstX86Mulps<Machine>; | 2826 using Mulps = typename InstImpl<TraitsType>::InstX86Mulps; |
| 3000 using Mulss = InstX86Mulss<Machine>; | 2827 using Mulss = typename InstImpl<TraitsType>::InstX86Mulss; |
| 3001 using Pmull = InstX86Pmull<Machine>; | 2828 using Pmull = typename InstImpl<TraitsType>::InstX86Pmull; |
| 3002 using Pmuludq = InstX86Pmuludq<Machine>; | 2829 using Pmuludq = typename InstImpl<TraitsType>::InstX86Pmuludq; |
| 3003 using Divps = InstX86Divps<Machine>; | 2830 using Divps = typename InstImpl<TraitsType>::InstX86Divps; |
| 3004 using Divss = InstX86Divss<Machine>; | 2831 using Divss = typename InstImpl<TraitsType>::InstX86Divss; |
| 3005 using Rol = InstX86Rol<Machine>; | 2832 using Rol = typename InstImpl<TraitsType>::InstX86Rol; |
| 3006 using Shl = InstX86Shl<Machine>; | 2833 using Shl = typename InstImpl<TraitsType>::InstX86Shl; |
| 3007 using Psll = InstX86Psll<Machine>; | 2834 using Psll = typename InstImpl<TraitsType>::InstX86Psll; |
| 3008 using Psrl = InstX86Psrl<Machine>; | 2835 using Psrl = typename InstImpl<TraitsType>::InstX86Psrl; |
| 3009 using Shr = InstX86Shr<Machine>; | 2836 using Shr = typename InstImpl<TraitsType>::InstX86Shr; |
| 3010 using Sar = InstX86Sar<Machine>; | 2837 using Sar = typename InstImpl<TraitsType>::InstX86Sar; |
| 3011 using Psra = InstX86Psra<Machine>; | 2838 using Psra = typename InstImpl<TraitsType>::InstX86Psra; |
| 3012 using Pcmpeq = InstX86Pcmpeq<Machine>; | 2839 using Pcmpeq = typename InstImpl<TraitsType>::InstX86Pcmpeq; |
| 3013 using Pcmpgt = InstX86Pcmpgt<Machine>; | 2840 using Pcmpgt = typename InstImpl<TraitsType>::InstX86Pcmpgt; |
| 3014 using MovssRegs = InstX86MovssRegs<Machine>; | 2841 using MovssRegs = typename InstImpl<TraitsType>::InstX86MovssRegs; |
| 3015 using Idiv = InstX86Idiv<Machine>; | 2842 using Idiv = typename InstImpl<TraitsType>::InstX86Idiv; |
| 3016 using Div = InstX86Div<Machine>; | 2843 using Div = typename InstImpl<TraitsType>::InstX86Div; |
| 3017 using Insertps = InstX86Insertps<Machine>; | 2844 using Insertps = typename InstImpl<TraitsType>::InstX86Insertps; |
| 3018 using Pinsr = InstX86Pinsr<Machine>; | 2845 using Pinsr = typename InstImpl<TraitsType>::InstX86Pinsr; |
| 3019 using Shufps = InstX86Shufps<Machine>; | 2846 using Shufps = typename InstImpl<TraitsType>::InstX86Shufps; |
| 3020 using Blendvps = InstX86Blendvps<Machine>; | 2847 using Blendvps = typename InstImpl<TraitsType>::InstX86Blendvps; |
| 3021 using Pblendvb = InstX86Pblendvb<Machine>; | 2848 using Pblendvb = typename InstImpl<TraitsType>::InstX86Pblendvb; |
| 3022 using Pextr = InstX86Pextr<Machine>; | 2849 using Pextr = typename InstImpl<TraitsType>::InstX86Pextr; |
| 3023 using Pshufd = InstX86Pshufd<Machine>; | 2850 using Pshufd = typename InstImpl<TraitsType>::InstX86Pshufd; |
| 3024 using Lockable = InstX86BaseLockable<Machine>; | 2851 using Lockable = typename InstImpl<TraitsType>::InstX86BaseLockable; |
| 3025 using Mul = InstX86Mul<Machine>; | 2852 using Mul = typename InstImpl<TraitsType>::InstX86Mul; |
| 3026 using Shld = InstX86Shld<Machine>; | 2853 using Shld = typename InstImpl<TraitsType>::InstX86Shld; |
| 3027 using Shrd = InstX86Shrd<Machine>; | 2854 using Shrd = typename InstImpl<TraitsType>::InstX86Shrd; |
| 3028 using Cmov = InstX86Cmov<Machine>; | 2855 using Cmov = typename InstImpl<TraitsType>::InstX86Cmov; |
| 3029 using Cmpps = InstX86Cmpps<Machine>; | 2856 using Cmpps = typename InstImpl<TraitsType>::InstX86Cmpps; |
| 3030 using Cmpxchg = InstX86Cmpxchg<Machine>; | 2857 using Cmpxchg = typename InstImpl<TraitsType>::InstX86Cmpxchg; |
| 3031 using Cmpxchg8b = InstX86Cmpxchg8b<Machine>; | 2858 using Cmpxchg8b = typename InstImpl<TraitsType>::InstX86Cmpxchg8b; |
| 3032 using Cvt = InstX86Cvt<Machine>; | 2859 using Cvt = typename InstImpl<TraitsType>::InstX86Cvt; |
| 3033 using Icmp = InstX86Icmp<Machine>; | 2860 using Icmp = typename InstImpl<TraitsType>::InstX86Icmp; |
| 3034 using Ucomiss = InstX86Ucomiss<Machine>; | 2861 using Ucomiss = typename InstImpl<TraitsType>::InstX86Ucomiss; |
| 3035 using UD2 = InstX86UD2<Machine>; | 2862 using UD2 = typename InstImpl<TraitsType>::InstX86UD2; |
| 3036 using Test = InstX86Test<Machine>; | 2863 using Test = typename InstImpl<TraitsType>::InstX86Test; |
| 3037 using Mfence = InstX86Mfence<Machine>; | 2864 using Mfence = typename InstImpl<TraitsType>::InstX86Mfence; |
| 3038 using Store = InstX86Store<Machine>; | 2865 using Store = typename InstImpl<TraitsType>::InstX86Store; |
| 3039 using StoreP = InstX86StoreP<Machine>; | 2866 using StoreP = typename InstImpl<TraitsType>::InstX86StoreP; |
| 3040 using StoreQ = InstX86StoreQ<Machine>; | 2867 using StoreQ = typename InstImpl<TraitsType>::InstX86StoreQ; |
| 3041 using Nop = InstX86Nop<Machine>; | 2868 using Nop = typename InstImpl<TraitsType>::InstX86Nop; |
| 3042 template <typename T = typename InstX86Base<Machine>::Traits> | 2869 template <typename T = typename InstImpl<TraitsType>::Traits> |
| 3043 using Fld = typename std::enable_if<T::UsesX87, InstX86Fld<Machine>>::type; | 2870 using Fld = |
| 3044 template <typename T = typename InstX86Base<Machine>::Traits> | 2871 typename std::enable_if<T::UsesX87, |
| 3045 using Fstp = typename std::enable_if<T::UsesX87, InstX86Fstp<Machine>>::type; | 2872 typename InstImpl<TraitsType>::InstX86Fld>::type; |
| 3046 using Pop = InstX86Pop<Machine>; | 2873 template <typename T = typename InstImpl<TraitsType>::Traits> |
| 3047 using Push = InstX86Push<Machine>; | 2874 using Fstp = |
| 3048 using Ret = InstX86Ret<Machine>; | 2875 typename std::enable_if<T::UsesX87, |
| 3049 using Setcc = InstX86Setcc<Machine>; | 2876 typename InstImpl<TraitsType>::InstX86Fstp>::type; |
| 3050 using Xadd = InstX86Xadd<Machine>; | 2877 using Pop = typename InstImpl<TraitsType>::InstX86Pop; |
| 3051 using Xchg = InstX86Xchg<Machine>; | 2878 using Push = typename InstImpl<TraitsType>::InstX86Push; |
| 3052 | 2879 using Ret = typename InstImpl<TraitsType>::InstX86Ret; |
| 3053 using IacaStart = InstX86IacaStart<Machine>; | 2880 using Setcc = typename InstImpl<TraitsType>::InstX86Setcc; |
| 3054 using IacaEnd = InstX86IacaEnd<Machine>; | 2881 using Xadd = typename InstImpl<TraitsType>::InstX86Xadd; |
| 2882 using Xchg = typename InstImpl<TraitsType>::InstX86Xchg; | |
| 2883 | |
| 2884 using IacaStart = typename InstImpl<TraitsType>::InstX86IacaStart; | |
| 2885 using IacaEnd = typename InstImpl<TraitsType>::InstX86IacaEnd; | |
| 3055 }; | 2886 }; |
| 3056 | 2887 |
| 3057 /// X86 Instructions have static data (particularly, opcodes and instruction | 2888 /// X86 Instructions have static data (particularly, opcodes and instruction |
| 3058 /// emitters). Each X86 target needs to define all of these, so this macro is | 2889 /// emitters). Each X86 target needs to define all of these, so this macro is |
| 3059 /// provided so that, if something changes, then all X86 targets will be updated | 2890 /// provided so that, if something changes, then all X86 targets will be updated |
| 3060 /// automatically. | 2891 /// automatically. |
| 3061 #define X86INSTS_DEFINE_STATIC_DATA(Machine) \ | 2892 #define X86INSTS_DEFINE_STATIC_DATA(X86NAMESPACE, TraitsType) \ |
| 3062 namespace Ice { \ | 2893 namespace Ice { \ |
| 3063 namespace X86Internal { \ | 2894 namespace X86NAMESPACE { \ |
| 3064 /* In-place ops */ \ | 2895 /* In-place ops */ \ |
| 3065 template <> const char *InstX86Bswap<Machine>::Base::Opcode = "bswap"; \ | 2896 template <> \ |
| 3066 template <> const char *InstX86Neg<Machine>::Base::Opcode = "neg"; \ | 2897 template <> \ |
| 2898 const char *InstImpl<TraitsType>::InstX86Bswap::Base::Opcode = "bswap"; \ | |
| 2899 template <> \ | |
| 2900 template <> \ | |
| 2901 const char *InstImpl<TraitsType>::InstX86Neg::Base::Opcode = "neg"; \ | |
| 3067 /* Unary ops */ \ | 2902 /* Unary ops */ \ |
| 3068 template <> const char *InstX86Bsf<Machine>::Base::Opcode = "bsf"; \ | 2903 template <> \ |
| 3069 template <> const char *InstX86Bsr<Machine>::Base::Opcode = "bsr"; \ | 2904 template <> \ |
| 3070 template <> const char *InstX86Lea<Machine>::Base::Opcode = "lea"; \ | 2905 const char *InstImpl<TraitsType>::InstX86Bsf::Base::Opcode = "bsf"; \ |
| 3071 template <> const char *InstX86Movd<Machine>::Base::Opcode = "movd"; \ | 2906 template <> \ |
| 3072 template <> const char *InstX86Movsx<Machine>::Base::Opcode = "movs"; \ | 2907 template <> \ |
| 3073 template <> const char *InstX86Movzx<Machine>::Base::Opcode = "movz"; \ | 2908 const char *InstImpl<TraitsType>::InstX86Bsr::Base::Opcode = "bsr"; \ |
| 3074 template <> const char *InstX86Sqrtss<Machine>::Base::Opcode = "sqrtss"; \ | 2909 template <> \ |
| 3075 template <> const char *InstX86Cbwdq<Machine>::Base::Opcode = "cbw/cwd/cdq"; \ | 2910 template <> \ |
| 2911 const char *InstImpl<TraitsType>::InstX86Lea::Base::Opcode = "lea"; \ | |
| 2912 template <> \ | |
| 2913 template <> \ | |
| 2914 const char *InstImpl<TraitsType>::InstX86Movd::Base::Opcode = "movd"; \ | |
| 2915 template <> \ | |
| 2916 template <> \ | |
| 2917 const char *InstImpl<TraitsType>::InstX86Movsx::Base::Opcode = "movs"; \ | |
| 2918 template <> \ | |
| 2919 template <> \ | |
| 2920 const char *InstImpl<TraitsType>::InstX86Movzx::Base::Opcode = "movz"; \ | |
| 2921 template <> \ | |
| 2922 template <> \ | |
| 2923 const char *InstImpl<TraitsType>::InstX86Sqrtss::Base::Opcode = "sqrtss"; \ | |
| 2924 template <> \ | |
| 2925 template <> \ | |
| 2926 const char *InstImpl<TraitsType>::InstX86Cbwdq::Base::Opcode = \ | |
| 2927 "cbw/cwd/cdq"; \ | |
| 3076 /* Mov-like ops */ \ | 2928 /* Mov-like ops */ \ |
| 3077 template <> const char *InstX86Mov<Machine>::Base::Opcode = "mov"; \ | 2929 template <> \ |
| 3078 template <> const char *InstX86Movp<Machine>::Base::Opcode = "movups"; \ | 2930 template <> \ |
| 3079 template <> const char *InstX86Movq<Machine>::Base::Opcode = "movq"; \ | 2931 const char *InstImpl<TraitsType>::InstX86Mov::Base::Opcode = "mov"; \ |
| 2932 template <> \ | |
| 2933 template <> \ | |
| 2934 const char *InstImpl<TraitsType>::InstX86Movp::Base::Opcode = "movups"; \ | |
| 2935 template <> \ | |
| 2936 template <> \ | |
| 2937 const char *InstImpl<TraitsType>::InstX86Movq::Base::Opcode = "movq"; \ | |
| 3080 /* Binary ops */ \ | 2938 /* Binary ops */ \ |
| 3081 template <> const char *InstX86Add<Machine>::Base::Opcode = "add"; \ | 2939 template <> \ |
| 3082 template <> const char *InstX86AddRMW<Machine>::Base::Opcode = "add"; \ | 2940 template <> \ |
| 3083 template <> const char *InstX86Addps<Machine>::Base::Opcode = "add"; \ | 2941 const char *InstImpl<TraitsType>::InstX86Add::Base::Opcode = "add"; \ |
| 3084 template <> const char *InstX86Adc<Machine>::Base::Opcode = "adc"; \ | 2942 template <> \ |
| 3085 template <> const char *InstX86AdcRMW<Machine>::Base::Opcode = "adc"; \ | 2943 template <> \ |
| 3086 template <> const char *InstX86Addss<Machine>::Base::Opcode = "add"; \ | 2944 const char *InstImpl<TraitsType>::InstX86AddRMW::Base::Opcode = "add"; \ |
| 3087 template <> const char *InstX86Andnps<Machine>::Base::Opcode = "andn"; \ | 2945 template <> \ |
| 3088 template <> const char *InstX86Andps<Machine>::Base::Opcode = "and"; \ | 2946 template <> \ |
| 3089 template <> const char *InstX86Maxss<Machine>::Base::Opcode = "max"; \ | 2947 const char *InstImpl<TraitsType>::InstX86Addps::Base::Opcode = "add"; \ |
| 3090 template <> const char *InstX86Minss<Machine>::Base::Opcode = "min"; \ | 2948 template <> \ |
| 3091 template <> const char *InstX86Padd<Machine>::Base::Opcode = "padd"; \ | 2949 template <> \ |
| 3092 template <> const char *InstX86Sub<Machine>::Base::Opcode = "sub"; \ | 2950 const char *InstImpl<TraitsType>::InstX86Adc::Base::Opcode = "adc"; \ |
| 3093 template <> const char *InstX86SubRMW<Machine>::Base::Opcode = "sub"; \ | 2951 template <> \ |
| 3094 template <> const char *InstX86Subps<Machine>::Base::Opcode = "sub"; \ | 2952 template <> \ |
| 3095 template <> const char *InstX86Subss<Machine>::Base::Opcode = "sub"; \ | 2953 const char *InstImpl<TraitsType>::InstX86AdcRMW::Base::Opcode = "adc"; \ |
| 3096 template <> const char *InstX86Sbb<Machine>::Base::Opcode = "sbb"; \ | 2954 template <> \ |
| 3097 template <> const char *InstX86SbbRMW<Machine>::Base::Opcode = "sbb"; \ | 2955 template <> \ |
| 3098 template <> const char *InstX86Psub<Machine>::Base::Opcode = "psub"; \ | 2956 const char *InstImpl<TraitsType>::InstX86Addss::Base::Opcode = "add"; \ |
| 3099 template <> const char *InstX86And<Machine>::Base::Opcode = "and"; \ | 2957 template <> \ |
| 3100 template <> const char *InstX86AndRMW<Machine>::Base::Opcode = "and"; \ | 2958 template <> \ |
| 3101 template <> const char *InstX86Pand<Machine>::Base::Opcode = "pand"; \ | 2959 const char *InstImpl<TraitsType>::InstX86Andnps::Base::Opcode = "andn"; \ |
| 3102 template <> const char *InstX86Pandn<Machine>::Base::Opcode = "pandn"; \ | 2960 template <> \ |
| 3103 template <> const char *InstX86Or<Machine>::Base::Opcode = "or"; \ | 2961 template <> \ |
| 3104 template <> const char *InstX86Orps<Machine>::Base::Opcode = "or"; \ | 2962 const char *InstImpl<TraitsType>::InstX86Andps::Base::Opcode = "and"; \ |
| 3105 template <> const char *InstX86OrRMW<Machine>::Base::Opcode = "or"; \ | 2963 template <> \ |
| 3106 template <> const char *InstX86Por<Machine>::Base::Opcode = "por"; \ | 2964 template <> \ |
| 3107 template <> const char *InstX86Xor<Machine>::Base::Opcode = "xor"; \ | 2965 const char *InstImpl<TraitsType>::InstX86Maxss::Base::Opcode = "max"; \ |
| 3108 template <> const char *InstX86Xorps<Machine>::Base::Opcode = "xor"; \ | 2966 template <> \ |
| 3109 template <> const char *InstX86XorRMW<Machine>::Base::Opcode = "xor"; \ | 2967 template <> \ |
| 3110 template <> const char *InstX86Pxor<Machine>::Base::Opcode = "pxor"; \ | 2968 const char *InstImpl<TraitsType>::InstX86Minss::Base::Opcode = "min"; \ |
| 3111 template <> const char *InstX86Imul<Machine>::Base::Opcode = "imul"; \ | 2969 template <> \ |
| 3112 template <> const char *InstX86ImulImm<Machine>::Base::Opcode = "imul"; \ | 2970 template <> \ |
| 3113 template <> const char *InstX86Mulps<Machine>::Base::Opcode = "mul"; \ | 2971 const char *InstImpl<TraitsType>::InstX86Padd::Base::Opcode = "padd"; \ |
| 3114 template <> const char *InstX86Mulss<Machine>::Base::Opcode = "mul"; \ | 2972 template <> \ |
| 3115 template <> const char *InstX86Pmull<Machine>::Base::Opcode = "pmull"; \ | 2973 template <> \ |
| 3116 template <> const char *InstX86Pmuludq<Machine>::Base::Opcode = "pmuludq"; \ | 2974 const char *InstImpl<TraitsType>::InstX86Sub::Base::Opcode = "sub"; \ |
| 3117 template <> const char *InstX86Div<Machine>::Base::Opcode = "div"; \ | 2975 template <> \ |
| 3118 template <> const char *InstX86Divps<Machine>::Base::Opcode = "div"; \ | 2976 template <> \ |
| 3119 template <> const char *InstX86Divss<Machine>::Base::Opcode = "div"; \ | 2977 const char *InstImpl<TraitsType>::InstX86SubRMW::Base::Opcode = "sub"; \ |
| 3120 template <> const char *InstX86Idiv<Machine>::Base::Opcode = "idiv"; \ | 2978 template <> \ |
| 3121 template <> const char *InstX86Rol<Machine>::Base::Opcode = "rol"; \ | 2979 template <> \ |
| 3122 template <> const char *InstX86Shl<Machine>::Base::Opcode = "shl"; \ | 2980 const char *InstImpl<TraitsType>::InstX86Subps::Base::Opcode = "sub"; \ |
| 3123 template <> const char *InstX86Psll<Machine>::Base::Opcode = "psll"; \ | 2981 template <> \ |
| 3124 template <> const char *InstX86Shr<Machine>::Base::Opcode = "shr"; \ | 2982 template <> \ |
| 3125 template <> const char *InstX86Sar<Machine>::Base::Opcode = "sar"; \ | 2983 const char *InstImpl<TraitsType>::InstX86Subss::Base::Opcode = "sub"; \ |
| 3126 template <> const char *InstX86Psra<Machine>::Base::Opcode = "psra"; \ | 2984 template <> \ |
| 3127 template <> const char *InstX86Psrl<Machine>::Base::Opcode = "psrl"; \ | 2985 template <> \ |
| 3128 template <> const char *InstX86Pcmpeq<Machine>::Base::Opcode = "pcmpeq"; \ | 2986 const char *InstImpl<TraitsType>::InstX86Sbb::Base::Opcode = "sbb"; \ |
| 3129 template <> const char *InstX86Pcmpgt<Machine>::Base::Opcode = "pcmpgt"; \ | 2987 template <> \ |
| 3130 template <> const char *InstX86MovssRegs<Machine>::Base::Opcode = "movss"; \ | 2988 template <> \ |
| 2989 const char *InstImpl<TraitsType>::InstX86SbbRMW::Base::Opcode = "sbb"; \ | |
| 2990 template <> \ | |
| 2991 template <> \ | |
| 2992 const char *InstImpl<TraitsType>::InstX86Psub::Base::Opcode = "psub"; \ | |
| 2993 template <> \ | |
| 2994 template <> \ | |
| 2995 const char *InstImpl<TraitsType>::InstX86And::Base::Opcode = "and"; \ | |
| 2996 template <> \ | |
| 2997 template <> \ | |
| 2998 const char *InstImpl<TraitsType>::InstX86AndRMW::Base::Opcode = "and"; \ | |
| 2999 template <> \ | |
| 3000 template <> \ | |
| 3001 const char *InstImpl<TraitsType>::InstX86Pand::Base::Opcode = "pand"; \ | |
| 3002 template <> \ | |
| 3003 template <> \ | |
| 3004 const char *InstImpl<TraitsType>::InstX86Pandn::Base::Opcode = "pandn"; \ | |
| 3005 template <> \ | |
| 3006 template <> \ | |
| 3007 const char *InstImpl<TraitsType>::InstX86Or::Base::Opcode = "or"; \ | |
| 3008 template <> \ | |
| 3009 template <> \ | |
| 3010 const char *InstImpl<TraitsType>::InstX86Orps::Base::Opcode = "or"; \ | |
| 3011 template <> \ | |
| 3012 template <> \ | |
| 3013 const char *InstImpl<TraitsType>::InstX86OrRMW::Base::Opcode = "or"; \ | |
| 3014 template <> \ | |
| 3015 template <> \ | |
| 3016 const char *InstImpl<TraitsType>::InstX86Por::Base::Opcode = "por"; \ | |
| 3017 template <> \ | |
| 3018 template <> \ | |
| 3019 const char *InstImpl<TraitsType>::InstX86Xor::Base::Opcode = "xor"; \ | |
| 3020 template <> \ | |
| 3021 template <> \ | |
| 3022 const char *InstImpl<TraitsType>::InstX86Xorps::Base::Opcode = "xor"; \ | |
| 3023 template <> \ | |
| 3024 template <> \ | |
| 3025 const char *InstImpl<TraitsType>::InstX86XorRMW::Base::Opcode = "xor"; \ | |
| 3026 template <> \ | |
| 3027 template <> \ | |
| 3028 const char *InstImpl<TraitsType>::InstX86Pxor::Base::Opcode = "pxor"; \ | |
| 3029 template <> \ | |
| 3030 template <> \ | |
| 3031 const char *InstImpl<TraitsType>::InstX86Imul::Base::Opcode = "imul"; \ | |
| 3032 template <> \ | |
| 3033 template <> \ | |
| 3034 const char *InstImpl<TraitsType>::InstX86ImulImm::Base::Opcode = "imul"; \ | |
| 3035 template <> \ | |
| 3036 template <> \ | |
| 3037 const char *InstImpl<TraitsType>::InstX86Mulps::Base::Opcode = "mul"; \ | |
| 3038 template <> \ | |
| 3039 template <> \ | |
| 3040 const char *InstImpl<TraitsType>::InstX86Mulss::Base::Opcode = "mul"; \ | |
| 3041 template <> \ | |
| 3042 template <> \ | |
| 3043 const char *InstImpl<TraitsType>::InstX86Pmull::Base::Opcode = "pmull"; \ | |
| 3044 template <> \ | |
| 3045 template <> \ | |
| 3046 const char *InstImpl<TraitsType>::InstX86Pmuludq::Base::Opcode = "pmuludq"; \ | |
| 3047 template <> \ | |
| 3048 template <> \ | |
| 3049 const char *InstImpl<TraitsType>::InstX86Div::Base::Opcode = "div"; \ | |
| 3050 template <> \ | |
| 3051 template <> \ | |
| 3052 const char *InstImpl<TraitsType>::InstX86Divps::Base::Opcode = "div"; \ | |
| 3053 template <> \ | |
| 3054 template <> \ | |
| 3055 const char *InstImpl<TraitsType>::InstX86Divss::Base::Opcode = "div"; \ | |
| 3056 template <> \ | |
| 3057 template <> \ | |
| 3058 const char *InstImpl<TraitsType>::InstX86Idiv::Base::Opcode = "idiv"; \ | |
| 3059 template <> \ | |
| 3060 template <> \ | |
| 3061 const char *InstImpl<TraitsType>::InstX86Rol::Base::Opcode = "rol"; \ | |
| 3062 template <> \ | |
| 3063 template <> \ | |
| 3064 const char *InstImpl<TraitsType>::InstX86Shl::Base::Opcode = "shl"; \ | |
| 3065 template <> \ | |
| 3066 template <> \ | |
| 3067 const char *InstImpl<TraitsType>::InstX86Psll::Base::Opcode = "psll"; \ | |
| 3068 template <> \ | |
| 3069 template <> \ | |
| 3070 const char *InstImpl<TraitsType>::InstX86Shr::Base::Opcode = "shr"; \ | |
| 3071 template <> \ | |
| 3072 template <> \ | |
| 3073 const char *InstImpl<TraitsType>::InstX86Sar::Base::Opcode = "sar"; \ | |
| 3074 template <> \ | |
| 3075 template <> \ | |
| 3076 const char *InstImpl<TraitsType>::InstX86Psra::Base::Opcode = "psra"; \ | |
| 3077 template <> \ | |
| 3078 template <> \ | |
| 3079 const char *InstImpl<TraitsType>::InstX86Psrl::Base::Opcode = "psrl"; \ | |
| 3080 template <> \ | |
| 3081 template <> \ | |
| 3082 const char *InstImpl<TraitsType>::InstX86Pcmpeq::Base::Opcode = "pcmpeq"; \ | |
| 3083 template <> \ | |
| 3084 template <> \ | |
| 3085 const char *InstImpl<TraitsType>::InstX86Pcmpgt::Base::Opcode = "pcmpgt"; \ | |
| 3086 template <> \ | |
| 3087 template <> \ | |
| 3088 const char *InstImpl<TraitsType>::InstX86MovssRegs::Base::Opcode = "movss"; \ | |
| 3131 /* Ternary ops */ \ | 3089 /* Ternary ops */ \ |
| 3132 template <> const char *InstX86Insertps<Machine>::Base::Opcode = "insertps"; \ | 3090 template <> \ |
| 3133 template <> const char *InstX86Shufps<Machine>::Base::Opcode = "shufps"; \ | 3091 template <> \ |
| 3134 template <> const char *InstX86Pinsr<Machine>::Base::Opcode = "pinsr"; \ | 3092 const char *InstImpl<TraitsType>::InstX86Insertps::Base::Opcode = \ |
| 3135 template <> const char *InstX86Blendvps<Machine>::Base::Opcode = "blendvps"; \ | 3093 "insertps"; \ |
| 3136 template <> const char *InstX86Pblendvb<Machine>::Base::Opcode = "pblendvb"; \ | 3094 template <> \ |
| 3095 template <> \ | |
| 3096 const char *InstImpl<TraitsType>::InstX86Shufps::Base::Opcode = "shufps"; \ | |
| 3097 template <> \ | |
| 3098 template <> \ | |
| 3099 const char *InstImpl<TraitsType>::InstX86Pinsr::Base::Opcode = "pinsr"; \ | |
| 3100 template <> \ | |
| 3101 template <> \ | |
| 3102 const char *InstImpl<TraitsType>::InstX86Blendvps::Base::Opcode = \ | |
| 3103 "blendvps"; \ | |
| 3104 template <> \ | |
| 3105 template <> \ | |
| 3106 const char *InstImpl<TraitsType>::InstX86Pblendvb::Base::Opcode = \ | |
| 3107 "pblendvb"; \ | |
| 3137 /* Three address ops */ \ | 3108 /* Three address ops */ \ |
| 3138 template <> const char *InstX86Pextr<Machine>::Base::Opcode = "pextr"; \ | 3109 template <> \ |
| 3139 template <> const char *InstX86Pshufd<Machine>::Base::Opcode = "pshufd"; \ | 3110 template <> \ |
| 3111 const char *InstImpl<TraitsType>::InstX86Pextr::Base::Opcode = "pextr"; \ | |
| 3112 template <> \ | |
| 3113 template <> \ | |
| 3114 const char *InstImpl<TraitsType>::InstX86Pshufd::Base::Opcode = "pshufd"; \ | |
| 3140 /* Inplace GPR ops */ \ | 3115 /* Inplace GPR ops */ \ |
| 3141 template <> \ | 3116 template <> \ |
| 3142 const InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp \ | 3117 template <> \ |
| 3143 InstX86Bswap<Machine>::Base::Emitter = { \ | 3118 const InstImpl<TraitsType>::Assembler::GPREmitterOneOp \ |
| 3144 &InstX86Base<Machine>::Traits::Assembler::bswap, \ | 3119 InstImpl<TraitsType>::InstX86Bswap::Base::Emitter = { \ |
| 3120 &InstImpl<TraitsType>::Assembler::bswap, \ | |
| 3145 nullptr /* only a reg form exists */ \ | 3121 nullptr /* only a reg form exists */ \ |
| 3146 }; \ | 3122 }; \ |
| 3147 template <> \ | 3123 template <> \ |
| 3148 const InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp \ | 3124 template <> \ |
| 3149 InstX86Neg<Machine>::Base::Emitter = { \ | 3125 const InstImpl<TraitsType>::Assembler::GPREmitterOneOp \ |
| 3150 &InstX86Base<Machine>::Traits::Assembler::neg, \ | 3126 InstImpl<TraitsType>::InstX86Neg::Base::Emitter = { \ |
| 3151 &InstX86Base<Machine>::Traits::Assembler::neg}; \ | 3127 &InstImpl<TraitsType>::Assembler::neg, \ |
| 3128 &InstImpl<TraitsType>::Assembler::neg}; \ | |
| 3152 \ | 3129 \ |
| 3153 /* Unary GPR ops */ \ | 3130 /* Unary GPR ops */ \ |
| 3131 template <> \ | |
| 3154 template <> /* uses specialized emitter. */ \ | 3132 template <> /* uses specialized emitter. */ \ |
| 3155 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3133 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
| 3156 InstX86Cbwdq<Machine>::Base::Emitter = {nullptr, nullptr, nullptr}; \ | 3134 InstImpl<TraitsType>::InstX86Cbwdq::Base::Emitter = {nullptr, nullptr, \ |
| 3157 template <> \ | 3135 nullptr}; \ |
| 3158 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3136 template <> \ |
| 3159 InstX86Bsf<Machine>::Base::Emitter = { \ | 3137 template <> \ |
| 3160 &InstX86Base<Machine>::Traits::Assembler::bsf, \ | 3138 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
| 3161 &InstX86Base<Machine>::Traits::Assembler::bsf, nullptr}; \ | 3139 InstImpl<TraitsType>::InstX86Bsf::Base::Emitter = { \ |
| 3162 template <> \ | 3140 &InstImpl<TraitsType>::Assembler::bsf, \ |
| 3163 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3141 &InstImpl<TraitsType>::Assembler::bsf, nullptr}; \ |
| 3164 InstX86Bsr<Machine>::Base::Emitter = { \ | 3142 template <> \ |
| 3165 &InstX86Base<Machine>::Traits::Assembler::bsr, \ | 3143 template <> \ |
| 3166 &InstX86Base<Machine>::Traits::Assembler::bsr, nullptr}; \ | 3144 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
| 3167 template <> \ | 3145 InstImpl<TraitsType>::InstX86Bsr::Base::Emitter = { \ |
| 3168 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3146 &InstImpl<TraitsType>::Assembler::bsr, \ |
| 3169 InstX86Lea<Machine>::Base::Emitter = { \ | 3147 &InstImpl<TraitsType>::Assembler::bsr, nullptr}; \ |
| 3148 template <> \ | |
| 3149 template <> \ | |
| 3150 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | |
| 3151 InstImpl<TraitsType>::InstX86Lea::Base::Emitter = { \ | |
| 3170 /* reg/reg and reg/imm are illegal */ nullptr, \ | 3152 /* reg/reg and reg/imm are illegal */ nullptr, \ |
| 3171 &InstX86Base<Machine>::Traits::Assembler::lea, nullptr}; \ | 3153 &InstImpl<TraitsType>::Assembler::lea, nullptr}; \ |
| 3172 template <> \ | 3154 template <> \ |
| 3173 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3155 template <> \ |
| 3174 InstX86Movsx<Machine>::Base::Emitter = { \ | 3156 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
| 3175 &InstX86Base<Machine>::Traits::Assembler::movsx, \ | 3157 InstImpl<TraitsType>::InstX86Movsx::Base::Emitter = { \ |
| 3176 &InstX86Base<Machine>::Traits::Assembler::movsx, nullptr}; \ | 3158 &InstImpl<TraitsType>::Assembler::movsx, \ |
| 3177 template <> \ | 3159 &InstImpl<TraitsType>::Assembler::movsx, nullptr}; \ |
| 3178 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3160 template <> \ |
| 3179 InstX86Movzx<Machine>::Base::Emitter = { \ | 3161 template <> \ |
| 3180 &InstX86Base<Machine>::Traits::Assembler::movzx, \ | 3162 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
| 3181 &InstX86Base<Machine>::Traits::Assembler::movzx, nullptr}; \ | 3163 InstImpl<TraitsType>::InstX86Movzx::Base::Emitter = { \ |
| 3164 &InstImpl<TraitsType>::Assembler::movzx, \ | |
| 3165 &InstImpl<TraitsType>::Assembler::movzx, nullptr}; \ | |
| 3182 \ | 3166 \ |
| 3183 /* Unary XMM ops */ \ | 3167 /* Unary XMM ops */ \ |
| 3168 template <> \ | |
| 3184 template <> /* uses specialized emitter. */ \ | 3169 template <> /* uses specialized emitter. */ \ |
| 3185 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3170 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3186 InstX86Movd<Machine>::Base::Emitter = {nullptr, nullptr}; \ | 3171 InstImpl<TraitsType>::InstX86Movd::Base::Emitter = {nullptr, nullptr}; \ |
| 3187 template <> \ | 3172 template <> \ |
| 3188 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3173 template <> \ |
| 3189 InstX86Sqrtss<Machine>::Base::Emitter = { \ | 3174 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3190 &InstX86Base<Machine>::Traits::Assembler::sqrtss, \ | 3175 InstImpl<TraitsType>::InstX86Sqrtss::Base::Emitter = { \ |
| 3191 &InstX86Base<Machine>::Traits::Assembler::sqrtss}; \ | 3176 &InstImpl<TraitsType>::Assembler::sqrtss, \ |
| 3177 &InstImpl<TraitsType>::Assembler::sqrtss}; \ | |
| 3192 \ | 3178 \ |
| 3193 /* Binary GPR ops */ \ | 3179 /* Binary GPR ops */ \ |
| 3180 template <> \ | |
| 3194 template <> /* uses specialized emitter. */ \ | 3181 template <> /* uses specialized emitter. */ \ |
| 3195 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3182 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
| 3196 InstX86Imul<Machine>::Base::Emitter = {nullptr, nullptr, nullptr}; \ | 3183 InstImpl<TraitsType>::InstX86Imul::Base::Emitter = {nullptr, nullptr, \ |
| 3197 template <> \ | 3184 nullptr}; \ |
| 3198 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3185 template <> \ |
| 3199 InstX86Add<Machine>::Base::Emitter = { \ | 3186 template <> \ |
| 3200 &InstX86Base<Machine>::Traits::Assembler::add, \ | 3187 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
| 3201 &InstX86Base<Machine>::Traits::Assembler::add, \ | 3188 InstImpl<TraitsType>::InstX86Add::Base::Emitter = { \ |
| 3202 &InstX86Base<Machine>::Traits::Assembler::add}; \ | 3189 &InstImpl<TraitsType>::Assembler::add, \ |
| 3203 template <> \ | 3190 &InstImpl<TraitsType>::Assembler::add, \ |
| 3204 const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 3191 &InstImpl<TraitsType>::Assembler::add}; \ |
| 3205 InstX86AddRMW<Machine>::Base::Emitter = { \ | 3192 template <> \ |
| 3206 &InstX86Base<Machine>::Traits::Assembler::add, \ | 3193 template <> \ |
| 3207 &InstX86Base<Machine>::Traits::Assembler::add}; \ | 3194 const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ |
| 3208 template <> \ | 3195 InstImpl<TraitsType>::InstX86AddRMW::Base::Emitter = { \ |
| 3209 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3196 &InstImpl<TraitsType>::Assembler::add, \ |
| 3210 InstX86Adc<Machine>::Base::Emitter = { \ | 3197 &InstImpl<TraitsType>::Assembler::add}; \ |
| 3211 &InstX86Base<Machine>::Traits::Assembler::adc, \ | 3198 template <> \ |
| 3212 &InstX86Base<Machine>::Traits::Assembler::adc, \ | 3199 template <> \ |
| 3213 &InstX86Base<Machine>::Traits::Assembler::adc}; \ | 3200 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
| 3214 template <> \ | 3201 InstImpl<TraitsType>::InstX86Adc::Base::Emitter = { \ |
| 3215 const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 3202 &InstImpl<TraitsType>::Assembler::adc, \ |
| 3216 InstX86AdcRMW<Machine>::Base::Emitter = { \ | 3203 &InstImpl<TraitsType>::Assembler::adc, \ |
| 3217 &InstX86Base<Machine>::Traits::Assembler::adc, \ | 3204 &InstImpl<TraitsType>::Assembler::adc}; \ |
| 3218 &InstX86Base<Machine>::Traits::Assembler::adc}; \ | 3205 template <> \ |
| 3219 template <> \ | 3206 template <> \ |
| 3220 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3207 const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ |
| 3221 InstX86And<Machine>::Base::Emitter = { \ | 3208 InstImpl<TraitsType>::InstX86AdcRMW::Base::Emitter = { \ |
| 3222 &InstX86Base<Machine>::Traits::Assembler::And, \ | 3209 &InstImpl<TraitsType>::Assembler::adc, \ |
| 3223 &InstX86Base<Machine>::Traits::Assembler::And, \ | 3210 &InstImpl<TraitsType>::Assembler::adc}; \ |
| 3224 &InstX86Base<Machine>::Traits::Assembler::And}; \ | 3211 template <> \ |
| 3225 template <> \ | 3212 template <> \ |
| 3226 const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 3213 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
| 3227 InstX86AndRMW<Machine>::Base::Emitter = { \ | 3214 InstImpl<TraitsType>::InstX86And::Base::Emitter = { \ |
| 3228 &InstX86Base<Machine>::Traits::Assembler::And, \ | 3215 &InstImpl<TraitsType>::Assembler::And, \ |
| 3229 &InstX86Base<Machine>::Traits::Assembler::And}; \ | 3216 &InstImpl<TraitsType>::Assembler::And, \ |
| 3230 template <> \ | 3217 &InstImpl<TraitsType>::Assembler::And}; \ |
| 3231 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3218 template <> \ |
| 3232 InstX86Or<Machine>::Base::Emitter = { \ | 3219 template <> \ |
| 3233 &InstX86Base<Machine>::Traits::Assembler::Or, \ | 3220 const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ |
| 3234 &InstX86Base<Machine>::Traits::Assembler::Or, \ | 3221 InstImpl<TraitsType>::InstX86AndRMW::Base::Emitter = { \ |
| 3235 &InstX86Base<Machine>::Traits::Assembler::Or}; \ | 3222 &InstImpl<TraitsType>::Assembler::And, \ |
| 3236 template <> \ | 3223 &InstImpl<TraitsType>::Assembler::And}; \ |
| 3237 const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 3224 template <> \ |
| 3238 InstX86OrRMW<Machine>::Base::Emitter = { \ | 3225 template <> \ |
| 3239 &InstX86Base<Machine>::Traits::Assembler::Or, \ | 3226 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
| 3240 &InstX86Base<Machine>::Traits::Assembler::Or}; \ | 3227 InstImpl<TraitsType>::InstX86Or::Base::Emitter = { \ |
| 3241 template <> \ | 3228 &InstImpl<TraitsType>::Assembler::Or, \ |
| 3242 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3229 &InstImpl<TraitsType>::Assembler::Or, \ |
| 3243 InstX86Sbb<Machine>::Base::Emitter = { \ | 3230 &InstImpl<TraitsType>::Assembler::Or}; \ |
| 3244 &InstX86Base<Machine>::Traits::Assembler::sbb, \ | 3231 template <> \ |
| 3245 &InstX86Base<Machine>::Traits::Assembler::sbb, \ | 3232 template <> \ |
| 3246 &InstX86Base<Machine>::Traits::Assembler::sbb}; \ | 3233 const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ |
| 3247 template <> \ | 3234 InstImpl<TraitsType>::InstX86OrRMW::Base::Emitter = { \ |
| 3248 const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 3235 &InstImpl<TraitsType>::Assembler::Or, \ |
| 3249 InstX86SbbRMW<Machine>::Base::Emitter = { \ | 3236 &InstImpl<TraitsType>::Assembler::Or}; \ |
| 3250 &InstX86Base<Machine>::Traits::Assembler::sbb, \ | 3237 template <> \ |
| 3251 &InstX86Base<Machine>::Traits::Assembler::sbb}; \ | 3238 template <> \ |
| 3252 template <> \ | 3239 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
| 3253 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3240 InstImpl<TraitsType>::InstX86Sbb::Base::Emitter = { \ |
| 3254 InstX86Sub<Machine>::Base::Emitter = { \ | 3241 &InstImpl<TraitsType>::Assembler::sbb, \ |
| 3255 &InstX86Base<Machine>::Traits::Assembler::sub, \ | 3242 &InstImpl<TraitsType>::Assembler::sbb, \ |
| 3256 &InstX86Base<Machine>::Traits::Assembler::sub, \ | 3243 &InstImpl<TraitsType>::Assembler::sbb}; \ |
| 3257 &InstX86Base<Machine>::Traits::Assembler::sub}; \ | 3244 template <> \ |
| 3258 template <> \ | 3245 template <> \ |
| 3259 const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 3246 const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ |
| 3260 InstX86SubRMW<Machine>::Base::Emitter = { \ | 3247 InstImpl<TraitsType>::InstX86SbbRMW::Base::Emitter = { \ |
| 3261 &InstX86Base<Machine>::Traits::Assembler::sub, \ | 3248 &InstImpl<TraitsType>::Assembler::sbb, \ |
| 3262 &InstX86Base<Machine>::Traits::Assembler::sub}; \ | 3249 &InstImpl<TraitsType>::Assembler::sbb}; \ |
| 3263 template <> \ | 3250 template <> \ |
| 3264 const InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp \ | 3251 template <> \ |
| 3265 InstX86Xor<Machine>::Base::Emitter = { \ | 3252 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ |
| 3266 &InstX86Base<Machine>::Traits::Assembler::Xor, \ | 3253 InstImpl<TraitsType>::InstX86Sub::Base::Emitter = { \ |
| 3267 &InstX86Base<Machine>::Traits::Assembler::Xor, \ | 3254 &InstImpl<TraitsType>::Assembler::sub, \ |
| 3268 &InstX86Base<Machine>::Traits::Assembler::Xor}; \ | 3255 &InstImpl<TraitsType>::Assembler::sub, \ |
| 3269 template <> \ | 3256 &InstImpl<TraitsType>::Assembler::sub}; \ |
| 3270 const InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp \ | 3257 template <> \ |
| 3271 InstX86XorRMW<Machine>::Base::Emitter = { \ | 3258 template <> \ |
| 3272 &InstX86Base<Machine>::Traits::Assembler::Xor, \ | 3259 const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ |
| 3273 &InstX86Base<Machine>::Traits::Assembler::Xor}; \ | 3260 InstImpl<TraitsType>::InstX86SubRMW::Base::Emitter = { \ |
| 3261 &InstImpl<TraitsType>::Assembler::sub, \ | |
| 3262 &InstImpl<TraitsType>::Assembler::sub}; \ | |
| 3263 template <> \ | |
| 3264 template <> \ | |
| 3265 const InstImpl<TraitsType>::Assembler::GPREmitterRegOp \ | |
| 3266 InstImpl<TraitsType>::InstX86Xor::Base::Emitter = { \ | |
| 3267 &InstImpl<TraitsType>::Assembler::Xor, \ | |
| 3268 &InstImpl<TraitsType>::Assembler::Xor, \ | |
| 3269 &InstImpl<TraitsType>::Assembler::Xor}; \ | |
| 3270 template <> \ | |
| 3271 template <> \ | |
| 3272 const InstImpl<TraitsType>::Assembler::GPREmitterAddrOp \ | |
| 3273 InstImpl<TraitsType>::InstX86XorRMW::Base::Emitter = { \ | |
| 3274 &InstImpl<TraitsType>::Assembler::Xor, \ | |
| 3275 &InstImpl<TraitsType>::Assembler::Xor}; \ | |
| 3274 \ | 3276 \ |
| 3275 /* Binary Shift GPR ops */ \ | 3277 /* Binary Shift GPR ops */ \ |
| 3276 template <> \ | 3278 template <> \ |
| 3277 const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ | 3279 template <> \ |
| 3278 InstX86Rol<Machine>::Base::Emitter = { \ | 3280 const InstImpl<TraitsType>::Assembler::GPREmitterShiftOp \ |
| 3279 &InstX86Base<Machine>::Traits::Assembler::rol, \ | 3281 InstImpl<TraitsType>::InstX86Rol::Base::Emitter = { \ |
| 3280 &InstX86Base<Machine>::Traits::Assembler::rol}; \ | 3282 &InstImpl<TraitsType>::Assembler::rol, \ |
| 3281 template <> \ | 3283 &InstImpl<TraitsType>::Assembler::rol}; \ |
| 3282 const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ | 3284 template <> \ |
| 3283 InstX86Sar<Machine>::Base::Emitter = { \ | 3285 template <> \ |
| 3284 &InstX86Base<Machine>::Traits::Assembler::sar, \ | 3286 const InstImpl<TraitsType>::Assembler::GPREmitterShiftOp \ |
| 3285 &InstX86Base<Machine>::Traits::Assembler::sar}; \ | 3287 InstImpl<TraitsType>::InstX86Sar::Base::Emitter = { \ |
| 3286 template <> \ | 3288 &InstImpl<TraitsType>::Assembler::sar, \ |
| 3287 const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ | 3289 &InstImpl<TraitsType>::Assembler::sar}; \ |
| 3288 InstX86Shl<Machine>::Base::Emitter = { \ | 3290 template <> \ |
| 3289 &InstX86Base<Machine>::Traits::Assembler::shl, \ | 3291 template <> \ |
| 3290 &InstX86Base<Machine>::Traits::Assembler::shl}; \ | 3292 const InstImpl<TraitsType>::Assembler::GPREmitterShiftOp \ |
| 3291 template <> \ | 3293 InstImpl<TraitsType>::InstX86Shl::Base::Emitter = { \ |
| 3292 const InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp \ | 3294 &InstImpl<TraitsType>::Assembler::shl, \ |
| 3293 InstX86Shr<Machine>::Base::Emitter = { \ | 3295 &InstImpl<TraitsType>::Assembler::shl}; \ |
| 3294 &InstX86Base<Machine>::Traits::Assembler::shr, \ | 3296 template <> \ |
| 3295 &InstX86Base<Machine>::Traits::Assembler::shr}; \ | 3297 template <> \ |
| 3298 const InstImpl<TraitsType>::Assembler::GPREmitterShiftOp \ | |
| 3299 InstImpl<TraitsType>::InstX86Shr::Base::Emitter = { \ | |
| 3300 &InstImpl<TraitsType>::Assembler::shr, \ | |
| 3301 &InstImpl<TraitsType>::Assembler::shr}; \ | |
| 3296 \ | 3302 \ |
| 3297 /* Binary XMM ops */ \ | 3303 /* Binary XMM ops */ \ |
| 3304 template <> \ | |
| 3298 template <> /* uses specialized emitter. */ \ | 3305 template <> /* uses specialized emitter. */ \ |
| 3299 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3306 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3300 InstX86MovssRegs<Machine>::Base::Emitter = {nullptr, nullptr}; \ | 3307 InstImpl<TraitsType>::InstX86MovssRegs::Base::Emitter = {nullptr, \ |
| 3301 template <> \ | 3308 nullptr}; \ |
| 3302 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3309 template <> \ |
| 3303 InstX86Addss<Machine>::Base::Emitter = { \ | 3310 template <> \ |
| 3304 &InstX86Base<Machine>::Traits::Assembler::addss, \ | 3311 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3305 &InstX86Base<Machine>::Traits::Assembler::addss}; \ | 3312 InstImpl<TraitsType>::InstX86Addss::Base::Emitter = { \ |
| 3306 template <> \ | 3313 &InstImpl<TraitsType>::Assembler::addss, \ |
| 3307 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3314 &InstImpl<TraitsType>::Assembler::addss}; \ |
| 3308 InstX86Addps<Machine>::Base::Emitter = { \ | 3315 template <> \ |
| 3309 &InstX86Base<Machine>::Traits::Assembler::addps, \ | 3316 template <> \ |
| 3310 &InstX86Base<Machine>::Traits::Assembler::addps}; \ | 3317 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3311 template <> \ | 3318 InstImpl<TraitsType>::InstX86Addps::Base::Emitter = { \ |
| 3312 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3319 &InstImpl<TraitsType>::Assembler::addps, \ |
| 3313 InstX86Divss<Machine>::Base::Emitter = { \ | 3320 &InstImpl<TraitsType>::Assembler::addps}; \ |
| 3314 &InstX86Base<Machine>::Traits::Assembler::divss, \ | 3321 template <> \ |
| 3315 &InstX86Base<Machine>::Traits::Assembler::divss}; \ | 3322 template <> \ |
| 3316 template <> \ | 3323 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3317 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3324 InstImpl<TraitsType>::InstX86Divss::Base::Emitter = { \ |
| 3318 InstX86Divps<Machine>::Base::Emitter = { \ | 3325 &InstImpl<TraitsType>::Assembler::divss, \ |
| 3319 &InstX86Base<Machine>::Traits::Assembler::divps, \ | 3326 &InstImpl<TraitsType>::Assembler::divss}; \ |
| 3320 &InstX86Base<Machine>::Traits::Assembler::divps}; \ | 3327 template <> \ |
| 3321 template <> \ | 3328 template <> \ |
| 3322 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3329 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3323 InstX86Mulss<Machine>::Base::Emitter = { \ | 3330 InstImpl<TraitsType>::InstX86Divps::Base::Emitter = { \ |
| 3324 &InstX86Base<Machine>::Traits::Assembler::mulss, \ | 3331 &InstImpl<TraitsType>::Assembler::divps, \ |
| 3325 &InstX86Base<Machine>::Traits::Assembler::mulss}; \ | 3332 &InstImpl<TraitsType>::Assembler::divps}; \ |
| 3326 template <> \ | 3333 template <> \ |
| 3327 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3334 template <> \ |
| 3328 InstX86Mulps<Machine>::Base::Emitter = { \ | 3335 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3329 &InstX86Base<Machine>::Traits::Assembler::mulps, \ | 3336 InstImpl<TraitsType>::InstX86Mulss::Base::Emitter = { \ |
| 3330 &InstX86Base<Machine>::Traits::Assembler::mulps}; \ | 3337 &InstImpl<TraitsType>::Assembler::mulss, \ |
| 3331 template <> \ | 3338 &InstImpl<TraitsType>::Assembler::mulss}; \ |
| 3332 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3339 template <> \ |
| 3333 InstX86Padd<Machine>::Base::Emitter = { \ | 3340 template <> \ |
| 3334 &InstX86Base<Machine>::Traits::Assembler::padd, \ | 3341 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3335 &InstX86Base<Machine>::Traits::Assembler::padd}; \ | 3342 InstImpl<TraitsType>::InstX86Mulps::Base::Emitter = { \ |
| 3336 template <> \ | 3343 &InstImpl<TraitsType>::Assembler::mulps, \ |
| 3337 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3344 &InstImpl<TraitsType>::Assembler::mulps}; \ |
| 3338 InstX86Pand<Machine>::Base::Emitter = { \ | 3345 template <> \ |
| 3339 &InstX86Base<Machine>::Traits::Assembler::pand, \ | 3346 template <> \ |
| 3340 &InstX86Base<Machine>::Traits::Assembler::pand}; \ | 3347 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3341 template <> \ | 3348 InstImpl<TraitsType>::InstX86Padd::Base::Emitter = { \ |
| 3342 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3349 &InstImpl<TraitsType>::Assembler::padd, \ |
| 3343 InstX86Pandn<Machine>::Base::Emitter = { \ | 3350 &InstImpl<TraitsType>::Assembler::padd}; \ |
| 3344 &InstX86Base<Machine>::Traits::Assembler::pandn, \ | 3351 template <> \ |
| 3345 &InstX86Base<Machine>::Traits::Assembler::pandn}; \ | 3352 template <> \ |
| 3346 template <> \ | 3353 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3347 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3354 InstImpl<TraitsType>::InstX86Pand::Base::Emitter = { \ |
| 3348 InstX86Pcmpeq<Machine>::Base::Emitter = { \ | 3355 &InstImpl<TraitsType>::Assembler::pand, \ |
| 3349 &InstX86Base<Machine>::Traits::Assembler::pcmpeq, \ | 3356 &InstImpl<TraitsType>::Assembler::pand}; \ |
| 3350 &InstX86Base<Machine>::Traits::Assembler::pcmpeq}; \ | 3357 template <> \ |
| 3351 template <> \ | 3358 template <> \ |
| 3352 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3359 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3353 InstX86Pcmpgt<Machine>::Base::Emitter = { \ | 3360 InstImpl<TraitsType>::InstX86Pandn::Base::Emitter = { \ |
| 3354 &InstX86Base<Machine>::Traits::Assembler::pcmpgt, \ | 3361 &InstImpl<TraitsType>::Assembler::pandn, \ |
| 3355 &InstX86Base<Machine>::Traits::Assembler::pcmpgt}; \ | 3362 &InstImpl<TraitsType>::Assembler::pandn}; \ |
| 3356 template <> \ | 3363 template <> \ |
| 3357 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3364 template <> \ |
| 3358 InstX86Pmull<Machine>::Base::Emitter = { \ | 3365 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3359 &InstX86Base<Machine>::Traits::Assembler::pmull, \ | 3366 InstImpl<TraitsType>::InstX86Pcmpeq::Base::Emitter = { \ |
| 3360 &InstX86Base<Machine>::Traits::Assembler::pmull}; \ | 3367 &InstImpl<TraitsType>::Assembler::pcmpeq, \ |
| 3361 template <> \ | 3368 &InstImpl<TraitsType>::Assembler::pcmpeq}; \ |
| 3362 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3369 template <> \ |
| 3363 InstX86Pmuludq<Machine>::Base::Emitter = { \ | 3370 template <> \ |
| 3364 &InstX86Base<Machine>::Traits::Assembler::pmuludq, \ | 3371 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3365 &InstX86Base<Machine>::Traits::Assembler::pmuludq}; \ | 3372 InstImpl<TraitsType>::InstX86Pcmpgt::Base::Emitter = { \ |
| 3366 template <> \ | 3373 &InstImpl<TraitsType>::Assembler::pcmpgt, \ |
| 3367 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3374 &InstImpl<TraitsType>::Assembler::pcmpgt}; \ |
| 3368 InstX86Por<Machine>::Base::Emitter = { \ | 3375 template <> \ |
| 3369 &InstX86Base<Machine>::Traits::Assembler::por, \ | 3376 template <> \ |
| 3370 &InstX86Base<Machine>::Traits::Assembler::por}; \ | 3377 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3371 template <> \ | 3378 InstImpl<TraitsType>::InstX86Pmull::Base::Emitter = { \ |
| 3372 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3379 &InstImpl<TraitsType>::Assembler::pmull, \ |
| 3373 InstX86Psub<Machine>::Base::Emitter = { \ | 3380 &InstImpl<TraitsType>::Assembler::pmull}; \ |
| 3374 &InstX86Base<Machine>::Traits::Assembler::psub, \ | 3381 template <> \ |
| 3375 &InstX86Base<Machine>::Traits::Assembler::psub}; \ | 3382 template <> \ |
| 3376 template <> \ | 3383 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3377 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3384 InstImpl<TraitsType>::InstX86Pmuludq::Base::Emitter = { \ |
| 3378 InstX86Pxor<Machine>::Base::Emitter = { \ | 3385 &InstImpl<TraitsType>::Assembler::pmuludq, \ |
| 3379 &InstX86Base<Machine>::Traits::Assembler::pxor, \ | 3386 &InstImpl<TraitsType>::Assembler::pmuludq}; \ |
| 3380 &InstX86Base<Machine>::Traits::Assembler::pxor}; \ | 3387 template <> \ |
| 3381 template <> \ | 3388 template <> \ |
| 3382 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3389 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3383 InstX86Subss<Machine>::Base::Emitter = { \ | 3390 InstImpl<TraitsType>::InstX86Por::Base::Emitter = { \ |
| 3384 &InstX86Base<Machine>::Traits::Assembler::subss, \ | 3391 &InstImpl<TraitsType>::Assembler::por, \ |
| 3385 &InstX86Base<Machine>::Traits::Assembler::subss}; \ | 3392 &InstImpl<TraitsType>::Assembler::por}; \ |
| 3386 template <> \ | 3393 template <> \ |
| 3387 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3394 template <> \ |
| 3388 InstX86Subps<Machine>::Base::Emitter = { \ | 3395 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3389 &InstX86Base<Machine>::Traits::Assembler::subps, \ | 3396 InstImpl<TraitsType>::InstX86Psub::Base::Emitter = { \ |
| 3390 &InstX86Base<Machine>::Traits::Assembler::subps}; \ | 3397 &InstImpl<TraitsType>::Assembler::psub, \ |
| 3391 template <> \ | 3398 &InstImpl<TraitsType>::Assembler::psub}; \ |
| 3392 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3399 template <> \ |
| 3393 InstX86Andnps<Machine>::Base::Emitter = { \ | 3400 template <> \ |
| 3394 &InstX86Base<Machine>::Traits::Assembler::andnps, \ | 3401 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3395 &InstX86Base<Machine>::Traits::Assembler::andnps}; \ | 3402 InstImpl<TraitsType>::InstX86Pxor::Base::Emitter = { \ |
| 3396 template <> \ | 3403 &InstImpl<TraitsType>::Assembler::pxor, \ |
| 3397 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3404 &InstImpl<TraitsType>::Assembler::pxor}; \ |
| 3398 InstX86Andps<Machine>::Base::Emitter = { \ | 3405 template <> \ |
| 3399 &InstX86Base<Machine>::Traits::Assembler::andps, \ | 3406 template <> \ |
| 3400 &InstX86Base<Machine>::Traits::Assembler::andps}; \ | 3407 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3401 template <> \ | 3408 InstImpl<TraitsType>::InstX86Subss::Base::Emitter = { \ |
| 3402 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3409 &InstImpl<TraitsType>::Assembler::subss, \ |
| 3403 InstX86Maxss<Machine>::Base::Emitter = { \ | 3410 &InstImpl<TraitsType>::Assembler::subss}; \ |
| 3404 &InstX86Base<Machine>::Traits::Assembler::maxss, \ | 3411 template <> \ |
| 3405 &InstX86Base<Machine>::Traits::Assembler::maxss}; \ | 3412 template <> \ |
| 3406 template <> \ | 3413 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3407 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3414 InstImpl<TraitsType>::InstX86Subps::Base::Emitter = { \ |
| 3408 InstX86Minss<Machine>::Base::Emitter = { \ | 3415 &InstImpl<TraitsType>::Assembler::subps, \ |
| 3409 &InstX86Base<Machine>::Traits::Assembler::minss, \ | 3416 &InstImpl<TraitsType>::Assembler::subps}; \ |
| 3410 &InstX86Base<Machine>::Traits::Assembler::minss}; \ | 3417 template <> \ |
| 3411 template <> \ | 3418 template <> \ |
| 3412 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3419 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3413 InstX86Orps<Machine>::Base::Emitter = { \ | 3420 InstImpl<TraitsType>::InstX86Andnps::Base::Emitter = { \ |
| 3414 &InstX86Base<Machine>::Traits::Assembler::orps, \ | 3421 &InstImpl<TraitsType>::Assembler::andnps, \ |
| 3415 &InstX86Base<Machine>::Traits::Assembler::orps}; \ | 3422 &InstImpl<TraitsType>::Assembler::andnps}; \ |
| 3416 template <> \ | 3423 template <> \ |
| 3417 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp \ | 3424 template <> \ |
| 3418 InstX86Xorps<Machine>::Base::Emitter = { \ | 3425 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ |
| 3419 &InstX86Base<Machine>::Traits::Assembler::xorps, \ | 3426 InstImpl<TraitsType>::InstX86Andps::Base::Emitter = { \ |
| 3420 &InstX86Base<Machine>::Traits::Assembler::xorps}; \ | 3427 &InstImpl<TraitsType>::Assembler::andps, \ |
| 3428 &InstImpl<TraitsType>::Assembler::andps}; \ | |
| 3429 template <> \ | |
| 3430 template <> \ | |
| 3431 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | |
| 3432 InstImpl<TraitsType>::InstX86Maxss::Base::Emitter = { \ | |
| 3433 &InstImpl<TraitsType>::Assembler::maxss, \ | |
| 3434 &InstImpl<TraitsType>::Assembler::maxss}; \ | |
| 3435 template <> \ | |
| 3436 template <> \ | |
| 3437 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | |
| 3438 InstImpl<TraitsType>::InstX86Minss::Base::Emitter = { \ | |
| 3439 &InstImpl<TraitsType>::Assembler::minss, \ | |
| 3440 &InstImpl<TraitsType>::Assembler::minss}; \ | |
| 3441 template <> \ | |
| 3442 template <> \ | |
| 3443 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | |
| 3444 InstImpl<TraitsType>::InstX86Orps::Base::Emitter = { \ | |
| 3445 &InstImpl<TraitsType>::Assembler::orps, \ | |
| 3446 &InstImpl<TraitsType>::Assembler::orps}; \ | |
| 3447 template <> \ | |
| 3448 template <> \ | |
| 3449 const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \ | |
| 3450 InstImpl<TraitsType>::InstX86Xorps::Base::Emitter = { \ | |
| 3451 &InstImpl<TraitsType>::Assembler::xorps, \ | |
| 3452 &InstImpl<TraitsType>::Assembler::xorps}; \ | |
| 3421 \ | 3453 \ |
| 3422 /* Binary XMM Shift ops */ \ | 3454 /* Binary XMM Shift ops */ \ |
| 3423 template <> \ | 3455 template <> \ |
| 3424 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp \ | 3456 template <> \ |
| 3425 InstX86Psll<Machine>::Base::Emitter = { \ | 3457 const InstImpl<TraitsType>::Assembler::XmmEmitterShiftOp \ |
| 3426 &InstX86Base<Machine>::Traits::Assembler::psll, \ | 3458 InstImpl<TraitsType>::InstX86Psll::Base::Emitter = { \ |
| 3427 &InstX86Base<Machine>::Traits::Assembler::psll, \ | 3459 &InstImpl<TraitsType>::Assembler::psll, \ |
| 3428 &InstX86Base<Machine>::Traits::Assembler::psll}; \ | 3460 &InstImpl<TraitsType>::Assembler::psll, \ |
| 3429 template <> \ | 3461 &InstImpl<TraitsType>::Assembler::psll}; \ |
| 3430 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp \ | 3462 template <> \ |
| 3431 InstX86Psra<Machine>::Base::Emitter = { \ | 3463 template <> \ |
| 3432 &InstX86Base<Machine>::Traits::Assembler::psra, \ | 3464 const InstImpl<TraitsType>::Assembler::XmmEmitterShiftOp \ |
| 3433 &InstX86Base<Machine>::Traits::Assembler::psra, \ | 3465 InstImpl<TraitsType>::InstX86Psra::Base::Emitter = { \ |
| 3434 &InstX86Base<Machine>::Traits::Assembler::psra}; \ | 3466 &InstImpl<TraitsType>::Assembler::psra, \ |
| 3435 template <> \ | 3467 &InstImpl<TraitsType>::Assembler::psra, \ |
| 3436 const InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp \ | 3468 &InstImpl<TraitsType>::Assembler::psra}; \ |
| 3437 InstX86Psrl<Machine>::Base::Emitter = { \ | 3469 template <> \ |
| 3438 &InstX86Base<Machine>::Traits::Assembler::psrl, \ | 3470 template <> \ |
| 3439 &InstX86Base<Machine>::Traits::Assembler::psrl, \ | 3471 const InstImpl<TraitsType>::Assembler::XmmEmitterShiftOp \ |
| 3440 &InstX86Base<Machine>::Traits::Assembler::psrl}; \ | 3472 InstImpl<TraitsType>::InstX86Psrl::Base::Emitter = { \ |
| 3473 &InstImpl<TraitsType>::Assembler::psrl, \ | |
| 3474 &InstImpl<TraitsType>::Assembler::psrl, \ | |
| 3475 &InstImpl<TraitsType>::Assembler::psrl}; \ | |
| 3441 } \ | 3476 } \ |
| 3442 } | 3477 } |
| 3443 | 3478 |
| 3444 } // end of namespace X86Internal | 3479 } // end of namespace X86NAMESPACE |
| 3445 } // end of namespace Ice | 3480 } // end of namespace Ice |
| 3446 | 3481 |
| 3447 #include "IceInstX86BaseImpl.h" | 3482 #include "IceInstX86BaseImpl.h" |
| 3448 | 3483 |
| 3449 #endif // SUBZERO_SRC_ICEINSTX86BASE_H | 3484 #endif // SUBZERO_SRC_ICEINSTX86BASE_H |
| OLD | NEW |