blob: cc44a1aa5763c80d54999a3090372a9fc038895d [file] [log] [blame]
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001//===- subzero/src/IceInstX8632.h - Low-level x86 instructions --*- C++ -*-===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file declares the InstX8632 and OperandX8632 classes and
11// their subclasses. This represents the machine instructions and
12// operands used for x86-32 code selection.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef SUBZERO_SRC_ICEINSTX8632_H
17#define SUBZERO_SRC_ICEINSTX8632_H
18
Jan Voung8acded02014-09-22 18:02:25 -070019#include "assembler_ia32.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070020#include "IceDefs.h"
21#include "IceInst.h"
Jan Voungbd385e42014-09-18 18:18:10 -070022#include "IceConditionCodesX8632.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070023#include "IceInstX8632.def"
24#include "IceOperand.h"
25
26namespace Ice {
27
28class TargetX8632;
29
30// OperandX8632 extends the Operand hierarchy. Its subclasses are
31// OperandX8632Mem and VariableSplit.
32class OperandX8632 : public Operand {
Jim Stichnoth7b451a92014-10-15 14:39:23 -070033 OperandX8632(const OperandX8632 &) = delete;
34 OperandX8632 &operator=(const OperandX8632 &) = delete;
35
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070036public:
37 enum OperandKindX8632 {
38 k__Start = Operand::kTarget,
39 kMem,
40 kSplit
41 };
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -070042 using Operand::dump;
Jim Stichnothb56c8f42014-09-26 09:28:46 -070043 void dump(const Cfg *, Ostream &Str) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -080044 if (ALLOW_DUMP)
45 Str << "<OperandX8632>";
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -070046 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070047
48protected:
49 OperandX8632(OperandKindX8632 Kind, Type Ty)
50 : Operand(static_cast<OperandKind>(Kind), Ty) {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -070051 ~OperandX8632() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070052};
53
54// OperandX8632Mem represents the m32 addressing mode, with optional
55// base and index registers, a constant offset, and a fixed shift
56// value for the index register.
57class OperandX8632Mem : public OperandX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -070058 OperandX8632Mem(const OperandX8632Mem &) = delete;
59 OperandX8632Mem &operator=(const OperandX8632Mem &) = delete;
60
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070061public:
Jan Voung3bd9f1a2014-06-18 10:50:57 -070062 enum SegmentRegisters {
63 DefaultSegment = -1,
Jan Voungfe14fb82014-10-13 15:56:32 -070064#define X(val, name, prefix) val,
Jan Vounga3a01a22014-07-14 10:32:41 -070065 SEG_REGX8632_TABLE
Jan Voung3bd9f1a2014-06-18 10:50:57 -070066#undef X
67 SegReg_NUM
68 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070069 static OperandX8632Mem *create(Cfg *Func, Type Ty, Variable *Base,
70 Constant *Offset, Variable *Index = NULL,
Jan Voung3bd9f1a2014-06-18 10:50:57 -070071 uint16_t Shift = 0,
72 SegmentRegisters SegmentReg = DefaultSegment) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070073 return new (Func->allocate<OperandX8632Mem>())
Jan Voung3bd9f1a2014-06-18 10:50:57 -070074 OperandX8632Mem(Func, Ty, Base, Offset, Index, Shift, SegmentReg);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070075 }
76 Variable *getBase() const { return Base; }
77 Constant *getOffset() const { return Offset; }
78 Variable *getIndex() const { return Index; }
Jan Voung3bd9f1a2014-06-18 10:50:57 -070079 uint16_t getShift() const { return Shift; }
80 SegmentRegisters getSegmentRegister() const { return SegmentReg; }
Jan Voungfe14fb82014-10-13 15:56:32 -070081 void emitSegmentOverride(x86::AssemblerX86 *Asm) const;
Jan Voung8acded02014-09-22 18:02:25 -070082 x86::Address toAsmAddress(Assembler *Asm) const;
Jim Stichnothb56c8f42014-09-26 09:28:46 -070083 void emit(const Cfg *Func) const override;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -070084 using OperandX8632::dump;
Jim Stichnothb56c8f42014-09-26 09:28:46 -070085 void dump(const Cfg *Func, Ostream &Str) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070086
87 static bool classof(const Operand *Operand) {
88 return Operand->getKind() == static_cast<OperandKind>(kMem);
89 }
90
91private:
92 OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset,
Jan Voung3bd9f1a2014-06-18 10:50:57 -070093 Variable *Index, uint16_t Shift, SegmentRegisters SegmentReg);
Jim Stichnothb56c8f42014-09-26 09:28:46 -070094 ~OperandX8632Mem() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070095 Variable *Base;
96 Constant *Offset;
97 Variable *Index;
Jan Voung3bd9f1a2014-06-18 10:50:57 -070098 uint16_t Shift;
99 SegmentRegisters SegmentReg : 16;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700100};
101
102// VariableSplit is a way to treat an f64 memory location as a pair
103// of i32 locations (Low and High). This is needed for some cases
104// of the Bitcast instruction. Since it's not possible for integer
105// registers to access the XMM registers and vice versa, the
106// lowering forces the f64 to be spilled to the stack and then
107// accesses through the VariableSplit.
108class VariableSplit : public OperandX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700109 VariableSplit(const VariableSplit &) = delete;
110 VariableSplit &operator=(const VariableSplit &) = delete;
111
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700112public:
113 enum Portion {
114 Low,
115 High
116 };
117 static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) {
118 return new (Func->allocate<VariableSplit>()) VariableSplit(Func, Var, Part);
119 }
Jan Voungfe14fb82014-10-13 15:56:32 -0700120 int32_t getOffset() const { return Part == High ? 4 : 0; }
121
122 x86::Address toAsmAddress(const Cfg *Func) const;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700123 void emit(const Cfg *Func) const override;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700124 using OperandX8632::dump;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700125 void dump(const Cfg *Func, Ostream &Str) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700126
127 static bool classof(const Operand *Operand) {
128 return Operand->getKind() == static_cast<OperandKind>(kSplit);
129 }
130
131private:
132 VariableSplit(Cfg *Func, Variable *Var, Portion Part)
133 : OperandX8632(kSplit, IceType_i32), Func(Func), Var(Var), Part(Part) {
134 assert(Var->getType() == IceType_f64);
135 Vars = Func->allocateArrayOf<Variable *>(1);
136 Vars[0] = Var;
137 NumVars = 1;
138 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700139 ~VariableSplit() override { Func->deallocateArrayOf<Variable *>(Vars); }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700140 Cfg *Func; // Held only for the destructor.
141 Variable *Var;
142 Portion Part;
143};
144
Jim Stichnoth800dab22014-09-20 12:25:02 -0700145// SpillVariable decorates a Variable by linking it to another
146// Variable. When stack frame offsets are computed, the SpillVariable
147// is given a distinct stack slot only if its linked Variable has a
148// register. If the linked Variable has a stack slot, then the
149// Variable and SpillVariable share that slot.
150class SpillVariable : public Variable {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700151 SpillVariable(const SpillVariable &) = delete;
152 SpillVariable &operator=(const SpillVariable &) = delete;
153
Jim Stichnoth800dab22014-09-20 12:25:02 -0700154public:
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800155 static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index) {
156 return new (Func->allocate<SpillVariable>()) SpillVariable(Ty, Index);
Jim Stichnoth800dab22014-09-20 12:25:02 -0700157 }
158 const static OperandKind SpillVariableKind =
159 static_cast<OperandKind>(kVariable_Target);
160 static bool classof(const Operand *Operand) {
161 return Operand->getKind() == SpillVariableKind;
162 }
163 void setLinkedTo(Variable *Var) { LinkedTo = Var; }
164 Variable *getLinkedTo() const { return LinkedTo; }
165 // Inherit dump() and emit() from Variable.
166private:
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800167 SpillVariable(Type Ty, SizeT Index)
168 : Variable(SpillVariableKind, Ty, Index), LinkedTo(NULL) {}
Jim Stichnoth800dab22014-09-20 12:25:02 -0700169 Variable *LinkedTo;
170};
171
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700172class InstX8632 : public InstTarget {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700173 InstX8632(const InstX8632 &) = delete;
174 InstX8632 &operator=(const InstX8632 &) = delete;
175
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700176public:
177 enum InstKindX8632 {
178 k__Start = Inst::Target,
179 Adc,
180 Add,
Matt Wala8d1072e2014-07-11 15:43:51 -0700181 Addps,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700182 Addss,
Matt Wala105b7042014-08-11 19:56:19 -0700183 Adjuststack,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700184 And,
Matt Wala0a450512014-07-30 12:44:39 -0700185 Blendvps,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700186 Br,
Jan Vounge4da26f2014-07-15 17:52:39 -0700187 Bsf,
188 Bsr,
Jan Voung7fa813b2014-07-18 13:01:08 -0700189 Bswap,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700190 Call,
Matt Walaafeaee42014-08-07 13:47:30 -0700191 Cbwdq,
Jan Vounge4da26f2014-07-15 17:52:39 -0700192 Cmov,
Matt Walace0ca8f2014-07-24 12:34:20 -0700193 Cmpps,
Jan Vounga3a01a22014-07-14 10:32:41 -0700194 Cmpxchg,
195 Cmpxchg8b,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700196 Cvt,
197 Div,
Matt Wala8d1072e2014-07-11 15:43:51 -0700198 Divps,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700199 Divss,
200 Fld,
201 Fstp,
202 Icmp,
203 Idiv,
204 Imul,
Matt Wala0a450512014-07-30 12:44:39 -0700205 Insertps,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700206 Label,
Matt Wala49889232014-07-18 12:45:09 -0700207 Lea,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700208 Load,
Jan Voung5cd240d2014-06-25 10:36:46 -0700209 Mfence,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700210 Mov,
Matt Wala49889232014-07-18 12:45:09 -0700211 Movd,
Matt Wala928f1292014-07-07 16:50:46 -0700212 Movp,
Jan Voung5cd240d2014-06-25 10:36:46 -0700213 Movq,
Jan Vounge4dc61b2014-10-06 08:53:52 -0700214 MovssRegs,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700215 Movsx,
216 Movzx,
217 Mul,
Matt Wala8d1072e2014-07-11 15:43:51 -0700218 Mulps,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700219 Mulss,
Jan Vounga3a01a22014-07-14 10:32:41 -0700220 Neg,
Matt Walac3302742014-08-15 16:21:56 -0700221 Nop,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700222 Or,
Matt Wala7fa22d82014-07-17 12:41:31 -0700223 Padd,
Matt Wala83b80362014-07-16 10:21:30 -0700224 Pand,
Matt Wala9cb61e22014-07-24 09:44:42 -0700225 Pandn,
Matt Wala0a450512014-07-30 12:44:39 -0700226 Pblendvb,
Matt Wala83b80362014-07-16 10:21:30 -0700227 Pcmpeq,
228 Pcmpgt,
Matt Wala0a450512014-07-30 12:44:39 -0700229 Pextr,
230 Pinsr,
231 Pmull,
Matt Wala7fa22d82014-07-17 12:41:31 -0700232 Pmuludq,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700233 Pop,
Matt Wala7fa22d82014-07-17 12:41:31 -0700234 Por,
235 Pshufd,
Matt Wala83b80362014-07-16 10:21:30 -0700236 Psll,
237 Psra,
238 Psub,
Matt Wala7fa22d82014-07-17 12:41:31 -0700239 Push,
Matt Wala928f1292014-07-07 16:50:46 -0700240 Pxor,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700241 Ret,
Jan Voung7fa813b2014-07-18 13:01:08 -0700242 Rol,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700243 Sar,
244 Sbb,
245 Shl,
246 Shld,
247 Shr,
248 Shrd,
Matt Wala7fa22d82014-07-17 12:41:31 -0700249 Shufps,
Jan Voungf37fbbe2014-07-09 16:13:13 -0700250 Sqrtss,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700251 Store,
Matt Wala105b7042014-08-11 19:56:19 -0700252 StoreP,
Jan Voung5cd240d2014-06-25 10:36:46 -0700253 StoreQ,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700254 Sub,
Matt Wala8d1072e2014-07-11 15:43:51 -0700255 Subps,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700256 Subss,
257 Test,
258 Ucomiss,
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700259 UD2,
Jan Voung5cd240d2014-06-25 10:36:46 -0700260 Xadd,
Jan Vounga3a01a22014-07-14 10:32:41 -0700261 Xchg,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700262 Xor
263 };
Jan Vounge4da26f2014-07-15 17:52:39 -0700264
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700265 static const char *getWidthString(Type Ty);
Jim Stichnothbca2f652014-11-01 10:13:54 -0700266 static const char *getFldString(Type Ty);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700267 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700268
269protected:
270 InstX8632(Cfg *Func, InstKindX8632 Kind, SizeT Maxsrcs, Variable *Dest)
271 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700272 ~InstX8632() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700273 static bool isClassof(const Inst *Inst, InstKindX8632 MyKind) {
274 return Inst->getKind() == static_cast<InstKind>(MyKind);
275 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700276};
277
Jan Voung7e1e4852014-10-24 10:29:30 -0700278// InstX8632Label represents an intra-block label that is the target
279// of an intra-block branch. The offset between the label and the
280// branch must be fit into one byte (considered "near"). These are
281// used for lowering i1 calculations, Select instructions, and 64-bit
282// compares on a 32-bit architecture, without basic block splitting.
283// Basic block splitting is not so desirable for several reasons, one
284// of which is the impact on decisions based on whether a variable's
285// live range spans multiple basic blocks.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700286//
287// Intra-block control flow must be used with caution. Consider the
288// sequence for "c = (a >= b ? x : y)".
289// cmp a, b
290// br lt, L1
291// mov c, x
292// jmp L2
293// L1:
294// mov c, y
295// L2:
296//
297// Labels L1 and L2 are intra-block labels. Without knowledge of the
298// intra-block control flow, liveness analysis will determine the "mov
299// c, x" instruction to be dead. One way to prevent this is to insert
300// a "FakeUse(c)" instruction anywhere between the two "mov c, ..."
301// instructions, e.g.:
302//
303// cmp a, b
304// br lt, L1
305// mov c, x
306// jmp L2
307// FakeUse(c)
308// L1:
309// mov c, y
310// L2:
311//
312// The down-side is that "mov c, x" can never be dead-code eliminated
313// even if there are no uses of c. As unlikely as this situation is,
314// it may be prevented by running dead code elimination before
315// lowering.
316class InstX8632Label : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700317 InstX8632Label(const InstX8632Label &) = delete;
318 InstX8632Label &operator=(const InstX8632Label &) = delete;
319
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700320public:
321 static InstX8632Label *create(Cfg *Func, TargetX8632 *Target) {
322 return new (Func->allocate<InstX8632Label>()) InstX8632Label(Func, Target);
323 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700324 uint32_t getEmitInstCount() const override { return 0; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700325 IceString getName(const Cfg *Func) const;
Jan Voung7e1e4852014-10-24 10:29:30 -0700326 SizeT getNumber() const { return Number; }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700327 void emit(const Cfg *Func) const override;
Jan Voung7e1e4852014-10-24 10:29:30 -0700328 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700329 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700330
331private:
332 InstX8632Label(Cfg *Func, TargetX8632 *Target);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700333 ~InstX8632Label() override {}
Jan Voung7e1e4852014-10-24 10:29:30 -0700334 SizeT Number; // used for unique label generation.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700335};
336
337// Conditional and unconditional branch instruction.
338class InstX8632Br : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700339 InstX8632Br(const InstX8632Br &) = delete;
340 InstX8632Br &operator=(const InstX8632Br &) = delete;
341
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700342public:
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700343 // Create a conditional branch to a node.
344 static InstX8632Br *create(Cfg *Func, CfgNode *TargetTrue,
Jan Voungbd385e42014-09-18 18:18:10 -0700345 CfgNode *TargetFalse, CondX86::BrCond Condition) {
Jim Stichnoth98712a32014-10-24 10:59:02 -0700346 assert(Condition != CondX86::Br_None);
Jim Stichnothff9c7062014-09-18 04:50:49 -0700347 const InstX8632Label *NoLabel = NULL;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700348 return new (Func->allocate<InstX8632Br>())
Jim Stichnothff9c7062014-09-18 04:50:49 -0700349 InstX8632Br(Func, TargetTrue, TargetFalse, NoLabel, Condition);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700350 }
351 // Create an unconditional branch to a node.
352 static InstX8632Br *create(Cfg *Func, CfgNode *Target) {
Jim Stichnothff9c7062014-09-18 04:50:49 -0700353 const CfgNode *NoCondTarget = NULL;
354 const InstX8632Label *NoLabel = NULL;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700355 return new (Func->allocate<InstX8632Br>())
Jan Voungbd385e42014-09-18 18:18:10 -0700356 InstX8632Br(Func, NoCondTarget, Target, NoLabel, CondX86::Br_None);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700357 }
358 // Create a non-terminator conditional branch to a node, with a
359 // fallthrough to the next instruction in the current node. This is
360 // used for switch lowering.
Jan Voungbd385e42014-09-18 18:18:10 -0700361 static InstX8632Br *create(Cfg *Func, CfgNode *Target,
362 CondX86::BrCond Condition) {
Jim Stichnoth98712a32014-10-24 10:59:02 -0700363 assert(Condition != CondX86::Br_None);
Jim Stichnothff9c7062014-09-18 04:50:49 -0700364 const CfgNode *NoUncondTarget = NULL;
365 const InstX8632Label *NoLabel = NULL;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700366 return new (Func->allocate<InstX8632Br>())
Jim Stichnothff9c7062014-09-18 04:50:49 -0700367 InstX8632Br(Func, Target, NoUncondTarget, NoLabel, Condition);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700368 }
369 // Create a conditional intra-block branch (or unconditional, if
Jim Stichnoth18735602014-09-16 19:59:35 -0700370 // Condition==Br_None) to a label in the current block.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700371 static InstX8632Br *create(Cfg *Func, InstX8632Label *Label,
Jan Voungbd385e42014-09-18 18:18:10 -0700372 CondX86::BrCond Condition) {
Jim Stichnothff9c7062014-09-18 04:50:49 -0700373 const CfgNode *NoCondTarget = NULL;
374 const CfgNode *NoUncondTarget = NULL;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700375 return new (Func->allocate<InstX8632Br>())
Jim Stichnothff9c7062014-09-18 04:50:49 -0700376 InstX8632Br(Func, NoCondTarget, NoUncondTarget, Label, Condition);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700377 }
Jim Stichnothff9c7062014-09-18 04:50:49 -0700378 const CfgNode *getTargetTrue() const { return TargetTrue; }
379 const CfgNode *getTargetFalse() const { return TargetFalse; }
380 bool optimizeBranch(const CfgNode *NextNode);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700381 uint32_t getEmitInstCount() const override {
Jim Stichnothff9c7062014-09-18 04:50:49 -0700382 uint32_t Sum = 0;
Jim Stichnoth18735602014-09-16 19:59:35 -0700383 if (Label)
Jim Stichnothff9c7062014-09-18 04:50:49 -0700384 ++Sum;
385 if (getTargetTrue())
386 ++Sum;
Jim Stichnoth18735602014-09-16 19:59:35 -0700387 if (getTargetFalse())
Jim Stichnothff9c7062014-09-18 04:50:49 -0700388 ++Sum;
389 return Sum;
Jim Stichnoth18735602014-09-16 19:59:35 -0700390 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700391 bool isUnconditionalBranch() const override {
392 return !Label && Condition == CondX86::Br_None;
393 }
394 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700395 void emit(const Cfg *Func) const override;
Jan Voung7e1e4852014-10-24 10:29:30 -0700396 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700397 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700398 static bool classof(const Inst *Inst) { return isClassof(Inst, Br); }
399
400private:
Jim Stichnothff9c7062014-09-18 04:50:49 -0700401 InstX8632Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
Jan Voungbd385e42014-09-18 18:18:10 -0700402 const InstX8632Label *Label, CondX86::BrCond Condition);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700403 ~InstX8632Br() override {}
Jan Voungbd385e42014-09-18 18:18:10 -0700404 CondX86::BrCond Condition;
Jim Stichnothff9c7062014-09-18 04:50:49 -0700405 const CfgNode *TargetTrue;
406 const CfgNode *TargetFalse;
407 const InstX8632Label *Label; // Intra-block branch target
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700408};
409
Matt Wala105b7042014-08-11 19:56:19 -0700410// AdjustStack instruction - subtracts esp by the given amount and
411// updates the stack offset during code emission.
412class InstX8632AdjustStack : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700413 InstX8632AdjustStack(const InstX8632AdjustStack &) = delete;
414 InstX8632AdjustStack &operator=(const InstX8632AdjustStack &) = delete;
415
Matt Wala105b7042014-08-11 19:56:19 -0700416public:
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700417 static InstX8632AdjustStack *create(Cfg *Func, SizeT Amount, Variable *Esp) {
Matt Wala105b7042014-08-11 19:56:19 -0700418 return new (Func->allocate<InstX8632AdjustStack>())
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700419 InstX8632AdjustStack(Func, Amount, Esp);
Matt Wala105b7042014-08-11 19:56:19 -0700420 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700421 void emit(const Cfg *Func) const override;
422 void emitIAS(const Cfg *Func) const override;
423 void dump(const Cfg *Func) const override;
Matt Wala105b7042014-08-11 19:56:19 -0700424 static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); }
425
426private:
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700427 InstX8632AdjustStack(Cfg *Func, SizeT Amount, Variable *Esp);
Matt Wala105b7042014-08-11 19:56:19 -0700428 SizeT Amount;
429};
430
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700431// Call instruction. Arguments should have already been pushed.
432class InstX8632Call : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700433 InstX8632Call(const InstX8632Call &) = delete;
434 InstX8632Call &operator=(const InstX8632Call &) = delete;
435
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700436public:
437 static InstX8632Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) {
438 return new (Func->allocate<InstX8632Call>())
439 InstX8632Call(Func, Dest, CallTarget);
440 }
441 Operand *getCallTarget() const { return getSrc(0); }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700442 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -0700443 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700444 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700445 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); }
446
447private:
448 InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700449 ~InstX8632Call() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700450};
451
Jan Voung3b43b892014-09-24 13:32:39 -0700452// Emit a one-operand (GPR) instruction.
Jan Voungaf2780c2014-09-26 11:14:30 -0700453void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Var,
454 const x86::AssemblerX86::GPREmitterOneOp &Emitter);
Jan Voung3b43b892014-09-24 13:32:39 -0700455
Jan Voung7fa813b2014-07-18 13:01:08 -0700456// Instructions of the form x := op(x).
457template <InstX8632::InstKindX8632 K>
Jan Voung3b43b892014-09-24 13:32:39 -0700458class InstX8632InplaceopGPR : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700459 InstX8632InplaceopGPR(const InstX8632InplaceopGPR &) = delete;
460 InstX8632InplaceopGPR &operator=(const InstX8632InplaceopGPR &) = delete;
461
Jan Voung7fa813b2014-07-18 13:01:08 -0700462public:
Jan Voung3b43b892014-09-24 13:32:39 -0700463 static InstX8632InplaceopGPR *create(Cfg *Func, Operand *SrcDest) {
464 return new (Func->allocate<InstX8632InplaceopGPR>())
465 InstX8632InplaceopGPR(Func, SrcDest);
Jan Voung7fa813b2014-07-18 13:01:08 -0700466 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700467 void emit(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800468 if (!ALLOW_DUMP)
469 return;
Jan Voung7fa813b2014-07-18 13:01:08 -0700470 Ostream &Str = Func->getContext()->getStrEmit();
471 assert(getSrcSize() == 1);
472 Str << "\t" << Opcode << "\t";
473 getSrc(0)->emit(Func);
Jan Voung7fa813b2014-07-18 13:01:08 -0700474 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700475 void emitIAS(const Cfg *Func) const override {
Jan Voung3b43b892014-09-24 13:32:39 -0700476 assert(getSrcSize() == 1);
477 const Variable *Var = getDest();
478 Type Ty = Var->getType();
Jan Voungaf2780c2014-09-26 11:14:30 -0700479 emitIASOpTyGPR(Func, Ty, Var, Emitter);
Jan Voung3b43b892014-09-24 13:32:39 -0700480 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700481 void dump(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800482 if (!ALLOW_DUMP)
483 return;
Jan Voung7fa813b2014-07-18 13:01:08 -0700484 Ostream &Str = Func->getContext()->getStrDump();
485 dumpDest(Func);
486 Str << " = " << Opcode << "." << getDest()->getType() << " ";
487 dumpSources(Func);
488 }
489 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
490
491private:
Jan Voung3b43b892014-09-24 13:32:39 -0700492 InstX8632InplaceopGPR(Cfg *Func, Operand *SrcDest)
Jan Voung7fa813b2014-07-18 13:01:08 -0700493 : InstX8632(Func, K, 1, llvm::dyn_cast<Variable>(SrcDest)) {
494 addSource(SrcDest);
495 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700496 ~InstX8632InplaceopGPR() override {}
Jan Voung7fa813b2014-07-18 13:01:08 -0700497 static const char *Opcode;
Jan Voung3b43b892014-09-24 13:32:39 -0700498 static const x86::AssemblerX86::GPREmitterOneOp Emitter;
Jan Voung7fa813b2014-07-18 13:01:08 -0700499};
500
Jan Voung3b43b892014-09-24 13:32:39 -0700501// Emit a two-operand (GPR) instruction, where the dest operand is a
502// Variable that's guaranteed to be a register.
Jan Voung39d4aca2014-10-15 15:16:54 -0700503template <bool VarCanBeByte = true, bool SrcCanBeByte = true>
Jan Voung3b43b892014-09-24 13:32:39 -0700504void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Dst,
505 const Operand *Src,
506 const x86::AssemblerX86::GPREmitterRegOp &Emitter);
507
Jan Voung39d4aca2014-10-15 15:16:54 -0700508// Instructions of the form x := op(y).
Jan Vounga3a01a22014-07-14 10:32:41 -0700509template <InstX8632::InstKindX8632 K>
Jan Voung3b43b892014-09-24 13:32:39 -0700510class InstX8632UnaryopGPR : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700511 InstX8632UnaryopGPR(const InstX8632UnaryopGPR &) = delete;
512 InstX8632UnaryopGPR &operator=(const InstX8632UnaryopGPR &) = delete;
513
Jan Vounga3a01a22014-07-14 10:32:41 -0700514public:
Jan Voung3b43b892014-09-24 13:32:39 -0700515 static InstX8632UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src) {
516 return new (Func->allocate<InstX8632UnaryopGPR>())
517 InstX8632UnaryopGPR(Func, Dest, Src);
Jan Vounga3a01a22014-07-14 10:32:41 -0700518 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700519 void emit(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800520 if (!ALLOW_DUMP)
521 return;
Jan Vounga3a01a22014-07-14 10:32:41 -0700522 Ostream &Str = Func->getContext()->getStrEmit();
523 assert(getSrcSize() == 1);
Jim Stichnothbca2f652014-11-01 10:13:54 -0700524 Type SrcTy = getSrc(0)->getType();
525 Type DestTy = getDest()->getType();
526 Str << "\t" << Opcode << getWidthString(SrcTy);
527 // Movsx and movzx need both the source and dest type width letter
528 // to define the operation. The other unary operations have the
529 // same source and dest type and as a result need only one letter.
530 if (SrcTy != DestTy)
531 Str << getWidthString(DestTy);
532 Str << "\t";
Jan Vounga3a01a22014-07-14 10:32:41 -0700533 getSrc(0)->emit(Func);
Jim Stichnothbca2f652014-11-01 10:13:54 -0700534 Str << ", ";
535 getDest()->emit(Func);
Jan Vounga3a01a22014-07-14 10:32:41 -0700536 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700537 void emitIAS(const Cfg *Func) const override {
Jan Voung3b43b892014-09-24 13:32:39 -0700538 assert(getSrcSize() == 1);
539 const Variable *Var = getDest();
540 Type Ty = Var->getType();
541 const Operand *Src = getSrc(0);
542 emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter);
543 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700544 void dump(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800545 if (!ALLOW_DUMP)
546 return;
Jan Vounga3a01a22014-07-14 10:32:41 -0700547 Ostream &Str = Func->getContext()->getStrDump();
548 dumpDest(Func);
Jan Voung39d4aca2014-10-15 15:16:54 -0700549 Str << " = " << Opcode << "." << getSrc(0)->getType() << " ";
Jan Vounga3a01a22014-07-14 10:32:41 -0700550 dumpSources(Func);
551 }
552 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
553
554private:
Jan Voung3b43b892014-09-24 13:32:39 -0700555 InstX8632UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src)
Jan Vounge4da26f2014-07-15 17:52:39 -0700556 : InstX8632(Func, K, 1, Dest) {
557 addSource(Src);
Jan Vounga3a01a22014-07-14 10:32:41 -0700558 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700559 ~InstX8632UnaryopGPR() override {}
Jan Vounga3a01a22014-07-14 10:32:41 -0700560 static const char *Opcode;
Jan Voung3b43b892014-09-24 13:32:39 -0700561 static const x86::AssemblerX86::GPREmitterRegOp Emitter;
Jan Vounga3a01a22014-07-14 10:32:41 -0700562};
563
Jan Vounge4dc61b2014-10-06 08:53:52 -0700564void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var,
565 const Operand *Src,
566 const x86::AssemblerX86::XmmEmitterRegOp &Emitter);
Jan Voung8acded02014-09-22 18:02:25 -0700567
568template <InstX8632::InstKindX8632 K>
569class InstX8632UnaryopXmm : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700570 InstX8632UnaryopXmm(const InstX8632UnaryopXmm &) = delete;
571 InstX8632UnaryopXmm &operator=(const InstX8632UnaryopXmm &) = delete;
572
Jan Voung8acded02014-09-22 18:02:25 -0700573public:
574 static InstX8632UnaryopXmm *create(Cfg *Func, Variable *Dest, Operand *Src) {
575 return new (Func->allocate<InstX8632UnaryopXmm>())
576 InstX8632UnaryopXmm(Func, Dest, Src);
577 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700578 void emit(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800579 if (!ALLOW_DUMP)
580 return;
Jan Voung8acded02014-09-22 18:02:25 -0700581 Ostream &Str = Func->getContext()->getStrEmit();
582 assert(getSrcSize() == 1);
583 Str << "\t" << Opcode << "\t";
Jan Voung8acded02014-09-22 18:02:25 -0700584 getSrc(0)->emit(Func);
Jim Stichnothbca2f652014-11-01 10:13:54 -0700585 Str << ", ";
586 getDest()->emit(Func);
Jan Voung8acded02014-09-22 18:02:25 -0700587 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700588 void emitIAS(const Cfg *Func) const override {
Jan Voung8acded02014-09-22 18:02:25 -0700589 Type Ty = getDest()->getType();
590 assert(getSrcSize() == 1);
Jan Vounge4dc61b2014-10-06 08:53:52 -0700591 emitIASRegOpTyXMM(Func, Ty, getDest(), getSrc(0), Emitter);
Jan Voung8acded02014-09-22 18:02:25 -0700592 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700593 void dump(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800594 if (!ALLOW_DUMP)
595 return;
Jan Voung8acded02014-09-22 18:02:25 -0700596 Ostream &Str = Func->getContext()->getStrDump();
597 dumpDest(Func);
598 Str << " = " << Opcode << "." << getDest()->getType() << " ";
599 dumpSources(Func);
600 }
601 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
602
603private:
604 InstX8632UnaryopXmm(Cfg *Func, Variable *Dest, Operand *Src)
605 : InstX8632(Func, K, 1, Dest) {
606 addSource(Src);
607 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700608 ~InstX8632UnaryopXmm() override {}
Jan Voung8acded02014-09-22 18:02:25 -0700609 static const char *Opcode;
Jan Vounge4dc61b2014-10-06 08:53:52 -0700610 static const x86::AssemblerX86::XmmEmitterRegOp Emitter;
Jan Voung8acded02014-09-22 18:02:25 -0700611};
612
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700613// See the definition of emitTwoAddress() for a description of
614// ShiftHack.
615void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func,
616 bool ShiftHack = false);
617
Jan Voung8bcca042014-10-03 21:58:02 -0700618void emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var,
619 const Operand *Src,
620 const x86::AssemblerX86::GPREmitterShiftOp &Emitter);
621
622template <InstX8632::InstKindX8632 K>
623class InstX8632BinopGPRShift : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700624 InstX8632BinopGPRShift(const InstX8632BinopGPRShift &) = delete;
625 InstX8632BinopGPRShift &operator=(const InstX8632BinopGPRShift &) = delete;
626
Jan Voung8bcca042014-10-03 21:58:02 -0700627public:
628 // Create a binary-op GPR shift instruction.
629 static InstX8632BinopGPRShift *create(Cfg *Func, Variable *Dest,
630 Operand *Source) {
631 return new (Func->allocate<InstX8632BinopGPRShift>())
632 InstX8632BinopGPRShift(Func, Dest, Source);
633 }
634 void emit(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800635 if (!ALLOW_DUMP)
636 return;
Jan Voung8bcca042014-10-03 21:58:02 -0700637 const bool ShiftHack = true;
638 emitTwoAddress(Opcode, this, Func, ShiftHack);
639 }
640 void emitIAS(const Cfg *Func) const override {
641 Type Ty = getDest()->getType();
642 assert(getSrcSize() == 2);
643 emitIASGPRShift(Func, Ty, getDest(), getSrc(1), Emitter);
644 }
645 void dump(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800646 if (!ALLOW_DUMP)
647 return;
Jan Voung8bcca042014-10-03 21:58:02 -0700648 Ostream &Str = Func->getContext()->getStrDump();
649 dumpDest(Func);
650 Str << " = " << Opcode << "." << getDest()->getType() << " ";
651 dumpSources(Func);
652 }
653 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
654
655private:
656 InstX8632BinopGPRShift(Cfg *Func, Variable *Dest, Operand *Source)
657 : InstX8632(Func, K, 2, Dest) {
658 addSource(Dest);
659 addSource(Source);
660 }
Jan Voung8bcca042014-10-03 21:58:02 -0700661 ~InstX8632BinopGPRShift() override {}
662 static const char *Opcode;
663 static const x86::AssemblerX86::GPREmitterShiftOp Emitter;
664};
665
Jan Voungaf2780c2014-09-26 11:14:30 -0700666template <InstX8632::InstKindX8632 K>
667class InstX8632BinopGPR : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700668 InstX8632BinopGPR(const InstX8632BinopGPR &) = delete;
669 InstX8632BinopGPR &operator=(const InstX8632BinopGPR &) = delete;
670
Jan Voungaf2780c2014-09-26 11:14:30 -0700671public:
672 // Create an ordinary binary-op instruction like add or sub.
673 static InstX8632BinopGPR *create(Cfg *Func, Variable *Dest, Operand *Source) {
674 return new (Func->allocate<InstX8632BinopGPR>())
675 InstX8632BinopGPR(Func, Dest, Source);
676 }
677 void emit(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800678 if (!ALLOW_DUMP)
679 return;
Jan Voungaf2780c2014-09-26 11:14:30 -0700680 const bool ShiftHack = false;
681 emitTwoAddress(Opcode, this, Func, ShiftHack);
682 }
683 void emitIAS(const Cfg *Func) const override {
684 Type Ty = getDest()->getType();
685 assert(getSrcSize() == 2);
686 emitIASRegOpTyGPR(Func, Ty, getDest(), getSrc(1), Emitter);
687 }
688 void dump(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800689 if (!ALLOW_DUMP)
690 return;
Jan Voungaf2780c2014-09-26 11:14:30 -0700691 Ostream &Str = Func->getContext()->getStrDump();
692 dumpDest(Func);
693 Str << " = " << Opcode << "." << getDest()->getType() << " ";
694 dumpSources(Func);
695 }
696 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
697
698private:
699 InstX8632BinopGPR(Cfg *Func, Variable *Dest, Operand *Source)
700 : InstX8632(Func, K, 2, Dest) {
701 addSource(Dest);
702 addSource(Source);
703 }
Jan Voungaf2780c2014-09-26 11:14:30 -0700704 ~InstX8632BinopGPR() override {}
705 static const char *Opcode;
706 static const x86::AssemblerX86::GPREmitterRegOp Emitter;
707};
708
Jan Voung8acded02014-09-22 18:02:25 -0700709template <InstX8632::InstKindX8632 K, bool NeedsElementType>
710class InstX8632BinopXmm : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700711 InstX8632BinopXmm(const InstX8632BinopXmm &) = delete;
712 InstX8632BinopXmm &operator=(const InstX8632BinopXmm &) = delete;
713
Jan Voung8acded02014-09-22 18:02:25 -0700714public:
715 // Create an XMM binary-op instruction like addss or addps.
716 static InstX8632BinopXmm *create(Cfg *Func, Variable *Dest, Operand *Source) {
717 return new (Func->allocate<InstX8632BinopXmm>())
718 InstX8632BinopXmm(Func, Dest, Source);
719 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700720 void emit(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800721 if (!ALLOW_DUMP)
722 return;
Jan Voung8acded02014-09-22 18:02:25 -0700723 const bool ShiftHack = false;
724 emitTwoAddress(Opcode, this, Func, ShiftHack);
725 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700726 void emitIAS(const Cfg *Func) const override {
Jan Voung8acded02014-09-22 18:02:25 -0700727 Type Ty = getDest()->getType();
728 if (NeedsElementType)
729 Ty = typeElementType(Ty);
730 assert(getSrcSize() == 2);
Jan Vounge4dc61b2014-10-06 08:53:52 -0700731 emitIASRegOpTyXMM(Func, Ty, getDest(), getSrc(1), Emitter);
Jan Voung8acded02014-09-22 18:02:25 -0700732 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700733 void dump(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800734 if (!ALLOW_DUMP)
735 return;
Jan Voung8acded02014-09-22 18:02:25 -0700736 Ostream &Str = Func->getContext()->getStrDump();
737 dumpDest(Func);
738 Str << " = " << Opcode << "." << getDest()->getType() << " ";
739 dumpSources(Func);
740 }
741 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
742
743private:
744 InstX8632BinopXmm(Cfg *Func, Variable *Dest, Operand *Source)
745 : InstX8632(Func, K, 2, Dest) {
746 addSource(Dest);
747 addSource(Source);
748 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700749 ~InstX8632BinopXmm() override {}
Jan Voung8acded02014-09-22 18:02:25 -0700750 static const char *Opcode;
Jan Vounge4dc61b2014-10-06 08:53:52 -0700751 static const x86::AssemblerX86::XmmEmitterRegOp Emitter;
Jan Voung8acded02014-09-22 18:02:25 -0700752};
753
Jan Voung8bcca042014-10-03 21:58:02 -0700754void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var,
755 const Operand *Src,
756 const x86::AssemblerX86::XmmEmitterShiftOp &Emitter);
757
758template <InstX8632::InstKindX8632 K>
759class InstX8632BinopXmmShift : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700760 InstX8632BinopXmmShift(const InstX8632BinopXmmShift &) = delete;
761 InstX8632BinopXmmShift &operator=(const InstX8632BinopXmmShift &) = delete;
762
Jan Voung8bcca042014-10-03 21:58:02 -0700763public:
764 // Create an XMM binary-op shift operation.
765 static InstX8632BinopXmmShift *create(Cfg *Func, Variable *Dest,
766 Operand *Source) {
767 return new (Func->allocate<InstX8632BinopXmmShift>())
768 InstX8632BinopXmmShift(Func, Dest, Source);
769 }
770 void emit(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800771 if (!ALLOW_DUMP)
772 return;
Jan Voung8bcca042014-10-03 21:58:02 -0700773 const bool ShiftHack = false;
774 emitTwoAddress(Opcode, this, Func, ShiftHack);
775 }
776 void emitIAS(const Cfg *Func) const override {
777 Type Ty = getDest()->getType();
778 assert(Ty == IceType_v8i16 || Ty == IceType_v8i1 || Ty == IceType_v4i32 ||
779 Ty == IceType_v4i1);
780 Type ElementTy = typeElementType(Ty);
781 assert(getSrcSize() == 2);
782 emitIASXmmShift(Func, ElementTy, getDest(), getSrc(1), Emitter);
783 }
784 void dump(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800785 if (!ALLOW_DUMP)
786 return;
Jan Voung8bcca042014-10-03 21:58:02 -0700787 Ostream &Str = Func->getContext()->getStrDump();
788 dumpDest(Func);
789 Str << " = " << Opcode << "." << getDest()->getType() << " ";
790 dumpSources(Func);
791 }
792 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
793
794private:
795 InstX8632BinopXmmShift(Cfg *Func, Variable *Dest, Operand *Source)
796 : InstX8632(Func, K, 2, Dest) {
797 addSource(Dest);
798 addSource(Source);
799 }
Jan Voung8bcca042014-10-03 21:58:02 -0700800 ~InstX8632BinopXmmShift() override {}
801 static const char *Opcode;
802 static const x86::AssemblerX86::XmmEmitterShiftOp Emitter;
803};
804
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700805template <InstX8632::InstKindX8632 K> class InstX8632Ternop : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700806 InstX8632Ternop(const InstX8632Ternop &) = delete;
807 InstX8632Ternop &operator=(const InstX8632Ternop &) = delete;
808
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700809public:
810 // Create a ternary-op instruction like div or idiv.
811 static InstX8632Ternop *create(Cfg *Func, Variable *Dest, Operand *Source1,
812 Operand *Source2) {
813 return new (Func->allocate<InstX8632Ternop>())
814 InstX8632Ternop(Func, Dest, Source1, Source2);
815 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700816 void emit(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800817 if (!ALLOW_DUMP)
818 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700819 Ostream &Str = Func->getContext()->getStrEmit();
820 assert(getSrcSize() == 3);
821 Str << "\t" << Opcode << "\t";
Jim Stichnothbca2f652014-11-01 10:13:54 -0700822 getSrc(2)->emit(Func);
Matt Wala49889232014-07-18 12:45:09 -0700823 Str << ", ";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700824 getSrc(1)->emit(Func);
Matt Wala49889232014-07-18 12:45:09 -0700825 Str << ", ";
Jim Stichnothbca2f652014-11-01 10:13:54 -0700826 getDest()->emit(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700827 }
Jan Voung962befa2014-10-15 09:32:58 -0700828 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700829 void dump(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800830 if (!ALLOW_DUMP)
831 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700832 Ostream &Str = Func->getContext()->getStrDump();
833 dumpDest(Func);
834 Str << " = " << Opcode << "." << getDest()->getType() << " ";
835 dumpSources(Func);
836 }
837 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
838
839private:
840 InstX8632Ternop(Cfg *Func, Variable *Dest, Operand *Source1, Operand *Source2)
841 : InstX8632(Func, K, 3, Dest) {
842 addSource(Dest);
843 addSource(Source1);
844 addSource(Source2);
845 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700846 ~InstX8632Ternop() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700847 static const char *Opcode;
848};
849
Matt Wala49889232014-07-18 12:45:09 -0700850// Instructions of the form x := y op z
851template <InstX8632::InstKindX8632 K>
852class InstX8632ThreeAddressop : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700853 InstX8632ThreeAddressop(const InstX8632ThreeAddressop &) = delete;
854 InstX8632ThreeAddressop &operator=(const InstX8632ThreeAddressop &) = delete;
855
Matt Wala49889232014-07-18 12:45:09 -0700856public:
857 static InstX8632ThreeAddressop *create(Cfg *Func, Variable *Dest,
858 Operand *Source0, Operand *Source1) {
859 return new (Func->allocate<InstX8632ThreeAddressop>())
860 InstX8632ThreeAddressop(Func, Dest, Source0, Source1);
861 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700862 void emit(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800863 if (!ALLOW_DUMP)
864 return;
Matt Wala49889232014-07-18 12:45:09 -0700865 Ostream &Str = Func->getContext()->getStrEmit();
866 assert(getSrcSize() == 2);
867 Str << "\t" << Opcode << "\t";
Jim Stichnothbca2f652014-11-01 10:13:54 -0700868 getSrc(1)->emit(Func);
Matt Wala49889232014-07-18 12:45:09 -0700869 Str << ", ";
870 getSrc(0)->emit(Func);
871 Str << ", ";
Jim Stichnothbca2f652014-11-01 10:13:54 -0700872 getDest()->emit(Func);
Matt Wala49889232014-07-18 12:45:09 -0700873 }
Jan Voung962befa2014-10-15 09:32:58 -0700874 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700875 void dump(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800876 if (!ALLOW_DUMP)
877 return;
Matt Wala49889232014-07-18 12:45:09 -0700878 Ostream &Str = Func->getContext()->getStrDump();
879 dumpDest(Func);
880 Str << " = " << Opcode << "." << getDest()->getType() << " ";
881 dumpSources(Func);
882 }
883 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
884
885private:
886 InstX8632ThreeAddressop(Cfg *Func, Variable *Dest, Operand *Source0,
887 Operand *Source1)
888 : InstX8632(Func, K, 2, Dest) {
889 addSource(Source0);
890 addSource(Source1);
891 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700892 ~InstX8632ThreeAddressop() override {}
Matt Wala49889232014-07-18 12:45:09 -0700893 static const char *Opcode;
894};
895
Matt Walae58178a2014-08-12 13:15:04 -0700896bool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
897
898// Base class for assignment instructions
899template <InstX8632::InstKindX8632 K>
900class InstX8632Movlike : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700901 InstX8632Movlike(const InstX8632Movlike &) = delete;
902 InstX8632Movlike &operator=(const InstX8632Movlike &) = delete;
903
Matt Walae58178a2014-08-12 13:15:04 -0700904public:
905 static InstX8632Movlike *create(Cfg *Func, Variable *Dest, Operand *Source) {
906 return new (Func->allocate<InstX8632Movlike>())
907 InstX8632Movlike(Func, Dest, Source);
908 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700909 bool isRedundantAssign() const override {
Matt Walae58178a2014-08-12 13:15:04 -0700910 return checkForRedundantAssign(getDest(), getSrc(0));
911 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700912 bool isSimpleAssign() const override { return true; }
913 void emit(const Cfg *Func) const override;
Jan Voungfe14fb82014-10-13 15:56:32 -0700914 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700915 void dump(const Cfg *Func) const override {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800916 if (!ALLOW_DUMP)
917 return;
Matt Walae58178a2014-08-12 13:15:04 -0700918 Ostream &Str = Func->getContext()->getStrDump();
919 Str << Opcode << "." << getDest()->getType() << " ";
920 dumpDest(Func);
921 Str << ", ";
922 dumpSources(Func);
923 }
924 static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
925
926private:
927 InstX8632Movlike(Cfg *Func, Variable *Dest, Operand *Source)
928 : InstX8632(Func, K, 1, Dest) {
929 addSource(Source);
930 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700931 ~InstX8632Movlike() override {}
Matt Walae58178a2014-08-12 13:15:04 -0700932
933 static const char *Opcode;
934};
935
Jan Voung3b43b892014-09-24 13:32:39 -0700936typedef InstX8632InplaceopGPR<InstX8632::Bswap> InstX8632Bswap;
937typedef InstX8632InplaceopGPR<InstX8632::Neg> InstX8632Neg;
938typedef InstX8632UnaryopGPR<InstX8632::Bsf> InstX8632Bsf;
939typedef InstX8632UnaryopGPR<InstX8632::Bsr> InstX8632Bsr;
940typedef InstX8632UnaryopGPR<InstX8632::Lea> InstX8632Lea;
Matt Wala51e8cfb2014-08-08 08:39:40 -0700941// Cbwdq instruction - wrapper for cbw, cwd, and cdq
Jan Voung3b43b892014-09-24 13:32:39 -0700942typedef InstX8632UnaryopGPR<InstX8632::Cbwdq> InstX8632Cbwdq;
Jan Voung39d4aca2014-10-15 15:16:54 -0700943typedef InstX8632UnaryopGPR<InstX8632::Movsx> InstX8632Movsx;
944typedef InstX8632UnaryopGPR<InstX8632::Movzx> InstX8632Movzx;
Jan Voung3b43b892014-09-24 13:32:39 -0700945typedef InstX8632UnaryopXmm<InstX8632::Movd> InstX8632Movd;
946typedef InstX8632UnaryopXmm<InstX8632::Sqrtss> InstX8632Sqrtss;
Matt Walae58178a2014-08-12 13:15:04 -0700947// Move/assignment instruction - wrapper for mov/movss/movsd.
948typedef InstX8632Movlike<InstX8632::Mov> InstX8632Mov;
949// Move packed - copy 128 bit values between XMM registers, or mem128
950// and XMM registers.
951typedef InstX8632Movlike<InstX8632::Movp> InstX8632Movp;
952// Movq - copy between XMM registers, or mem64 and XMM registers.
953typedef InstX8632Movlike<InstX8632::Movq> InstX8632Movq;
Jan Voungaf2780c2014-09-26 11:14:30 -0700954typedef InstX8632BinopGPR<InstX8632::Add> InstX8632Add;
Jan Voung8acded02014-09-22 18:02:25 -0700955typedef InstX8632BinopXmm<InstX8632::Addps, true> InstX8632Addps;
Jan Voungaf2780c2014-09-26 11:14:30 -0700956typedef InstX8632BinopGPR<InstX8632::Adc> InstX8632Adc;
Jan Voung8acded02014-09-22 18:02:25 -0700957typedef InstX8632BinopXmm<InstX8632::Addss, false> InstX8632Addss;
958typedef InstX8632BinopXmm<InstX8632::Padd, true> InstX8632Padd;
Jan Voungaf2780c2014-09-26 11:14:30 -0700959typedef InstX8632BinopGPR<InstX8632::Sub> InstX8632Sub;
Jan Voung8acded02014-09-22 18:02:25 -0700960typedef InstX8632BinopXmm<InstX8632::Subps, true> InstX8632Subps;
961typedef InstX8632BinopXmm<InstX8632::Subss, false> InstX8632Subss;
Jan Voungaf2780c2014-09-26 11:14:30 -0700962typedef InstX8632BinopGPR<InstX8632::Sbb> InstX8632Sbb;
Jan Voung8acded02014-09-22 18:02:25 -0700963typedef InstX8632BinopXmm<InstX8632::Psub, true> InstX8632Psub;
Jan Voungaf2780c2014-09-26 11:14:30 -0700964typedef InstX8632BinopGPR<InstX8632::And> InstX8632And;
Jan Voung8acded02014-09-22 18:02:25 -0700965typedef InstX8632BinopXmm<InstX8632::Pand, false> InstX8632Pand;
966typedef InstX8632BinopXmm<InstX8632::Pandn, false> InstX8632Pandn;
Jan Voungaf2780c2014-09-26 11:14:30 -0700967typedef InstX8632BinopGPR<InstX8632::Or> InstX8632Or;
Jan Voung8acded02014-09-22 18:02:25 -0700968typedef InstX8632BinopXmm<InstX8632::Por, false> InstX8632Por;
Jan Voungaf2780c2014-09-26 11:14:30 -0700969typedef InstX8632BinopGPR<InstX8632::Xor> InstX8632Xor;
Jan Voung8acded02014-09-22 18:02:25 -0700970typedef InstX8632BinopXmm<InstX8632::Pxor, false> InstX8632Pxor;
Jan Voung0ac50dc2014-09-30 08:36:06 -0700971typedef InstX8632BinopGPR<InstX8632::Imul> InstX8632Imul;
Jan Voung8acded02014-09-22 18:02:25 -0700972typedef InstX8632BinopXmm<InstX8632::Mulps, true> InstX8632Mulps;
973typedef InstX8632BinopXmm<InstX8632::Mulss, false> InstX8632Mulss;
Jan Voung8bcca042014-10-03 21:58:02 -0700974typedef InstX8632BinopXmm<InstX8632::Pmull, true> InstX8632Pmull;
Jan Voung8acded02014-09-22 18:02:25 -0700975typedef InstX8632BinopXmm<InstX8632::Pmuludq, false> InstX8632Pmuludq;
976typedef InstX8632BinopXmm<InstX8632::Divps, true> InstX8632Divps;
977typedef InstX8632BinopXmm<InstX8632::Divss, false> InstX8632Divss;
Jan Voung8bcca042014-10-03 21:58:02 -0700978typedef InstX8632BinopGPRShift<InstX8632::Rol> InstX8632Rol;
979typedef InstX8632BinopGPRShift<InstX8632::Shl> InstX8632Shl;
980typedef InstX8632BinopXmmShift<InstX8632::Psll> InstX8632Psll;
981typedef InstX8632BinopGPRShift<InstX8632::Shr> InstX8632Shr;
982typedef InstX8632BinopGPRShift<InstX8632::Sar> InstX8632Sar;
983typedef InstX8632BinopXmmShift<InstX8632::Psra> InstX8632Psra;
Jan Voung0ac50dc2014-09-30 08:36:06 -0700984typedef InstX8632BinopXmm<InstX8632::Pcmpeq, true> InstX8632Pcmpeq;
985typedef InstX8632BinopXmm<InstX8632::Pcmpgt, true> InstX8632Pcmpgt;
Jan Vounge4dc61b2014-10-06 08:53:52 -0700986// movss is only a binary operation when the source and dest
987// operands are both registers (the high bits of dest are left untouched).
988// In other cases, it behaves like a copy (mov-like) operation (and the
989// high bits of dest are cleared).
990// InstX8632Movss will assert that both its source and dest operands are
991// registers, so the lowering code should use _mov instead of _movss
992// in cases where a copy operation is intended.
993typedef InstX8632BinopXmm<InstX8632::MovssRegs, false> InstX8632MovssRegs;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700994typedef InstX8632Ternop<InstX8632::Idiv> InstX8632Idiv;
995typedef InstX8632Ternop<InstX8632::Div> InstX8632Div;
Matt Wala0a450512014-07-30 12:44:39 -0700996typedef InstX8632Ternop<InstX8632::Insertps> InstX8632Insertps;
997typedef InstX8632Ternop<InstX8632::Pinsr> InstX8632Pinsr;
Matt Wala49889232014-07-18 12:45:09 -0700998typedef InstX8632Ternop<InstX8632::Shufps> InstX8632Shufps;
Matt Wala0a450512014-07-30 12:44:39 -0700999typedef InstX8632Ternop<InstX8632::Blendvps> InstX8632Blendvps;
1000typedef InstX8632Ternop<InstX8632::Pblendvb> InstX8632Pblendvb;
1001typedef InstX8632ThreeAddressop<InstX8632::Pextr> InstX8632Pextr;
Matt Wala49889232014-07-18 12:45:09 -07001002typedef InstX8632ThreeAddressop<InstX8632::Pshufd> InstX8632Pshufd;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001003
Jan Vounga3a01a22014-07-14 10:32:41 -07001004// Base class for a lockable x86-32 instruction (emits a locked prefix).
1005class InstX8632Lockable : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001006 InstX8632Lockable(const InstX8632Lockable &) = delete;
1007 InstX8632Lockable &operator=(const InstX8632Lockable &) = delete;
1008
Jan Vounga3a01a22014-07-14 10:32:41 -07001009protected:
1010 bool Locked;
1011
1012 InstX8632Lockable(Cfg *Func, InstKindX8632 Kind, SizeT Maxsrcs,
1013 Variable *Dest, bool Locked)
1014 : InstX8632(Func, Kind, Maxsrcs, Dest), Locked(Locked) {
1015 // Assume that such instructions are used for Atomics and be careful
1016 // with optimizations.
1017 HasSideEffects = Locked;
1018 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001019 ~InstX8632Lockable() override {}
Jan Vounga3a01a22014-07-14 10:32:41 -07001020};
1021
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001022// Mul instruction - unsigned multiply.
1023class InstX8632Mul : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001024 InstX8632Mul(const InstX8632Mul &) = delete;
1025 InstX8632Mul &operator=(const InstX8632Mul &) = delete;
1026
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001027public:
1028 static InstX8632Mul *create(Cfg *Func, Variable *Dest, Variable *Source1,
1029 Operand *Source2) {
1030 return new (Func->allocate<InstX8632Mul>())
1031 InstX8632Mul(Func, Dest, Source1, Source2);
1032 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001033 void emit(const Cfg *Func) const override;
Jan Voungaf2780c2014-09-26 11:14:30 -07001034 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001035 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001036 static bool classof(const Inst *Inst) { return isClassof(Inst, Mul); }
1037
1038private:
1039 InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1, Operand *Source2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001040 ~InstX8632Mul() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001041};
1042
Jan Voung88355762014-11-01 09:40:20 -07001043// Shld instruction - shift across a pair of operands.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001044class InstX8632Shld : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001045 InstX8632Shld(const InstX8632Shld &) = delete;
1046 InstX8632Shld &operator=(const InstX8632Shld &) = delete;
1047
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001048public:
1049 static InstX8632Shld *create(Cfg *Func, Variable *Dest, Variable *Source1,
1050 Variable *Source2) {
1051 return new (Func->allocate<InstX8632Shld>())
1052 InstX8632Shld(Func, Dest, Source1, Source2);
1053 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001054 void emit(const Cfg *Func) const override;
Jan Voung962befa2014-10-15 09:32:58 -07001055 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001056 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001057 static bool classof(const Inst *Inst) { return isClassof(Inst, Shld); }
1058
1059private:
1060 InstX8632Shld(Cfg *Func, Variable *Dest, Variable *Source1,
1061 Variable *Source2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001062 ~InstX8632Shld() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001063};
1064
Jan Voung88355762014-11-01 09:40:20 -07001065// Shrd instruction - shift across a pair of operands.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001066class InstX8632Shrd : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001067 InstX8632Shrd(const InstX8632Shrd &) = delete;
1068 InstX8632Shrd &operator=(const InstX8632Shrd &) = delete;
1069
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001070public:
1071 static InstX8632Shrd *create(Cfg *Func, Variable *Dest, Variable *Source1,
1072 Variable *Source2) {
1073 return new (Func->allocate<InstX8632Shrd>())
1074 InstX8632Shrd(Func, Dest, Source1, Source2);
1075 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001076 void emit(const Cfg *Func) const override;
Jan Voung962befa2014-10-15 09:32:58 -07001077 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001078 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001079 static bool classof(const Inst *Inst) { return isClassof(Inst, Shrd); }
1080
1081private:
1082 InstX8632Shrd(Cfg *Func, Variable *Dest, Variable *Source1,
1083 Variable *Source2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001084 ~InstX8632Shrd() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001085};
1086
Jan Vounge4da26f2014-07-15 17:52:39 -07001087// Conditional move instruction.
1088class InstX8632Cmov : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001089 InstX8632Cmov(const InstX8632Cmov &) = delete;
1090 InstX8632Cmov &operator=(const InstX8632Cmov &) = delete;
1091
Jan Vounge4da26f2014-07-15 17:52:39 -07001092public:
1093 static InstX8632Cmov *create(Cfg *Func, Variable *Dest, Operand *Source,
Jan Voungbd385e42014-09-18 18:18:10 -07001094 CondX86::BrCond Cond) {
Jan Vounge4da26f2014-07-15 17:52:39 -07001095 return new (Func->allocate<InstX8632Cmov>())
1096 InstX8632Cmov(Func, Dest, Source, Cond);
1097 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001098 void emit(const Cfg *Func) const override;
1099 void emitIAS(const Cfg *Func) const override;
1100 void dump(const Cfg *Func) const override;
Jan Vounge4da26f2014-07-15 17:52:39 -07001101 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmov); }
1102
1103private:
Jan Voungbd385e42014-09-18 18:18:10 -07001104 InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source,
1105 CondX86::BrCond Cond);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001106 ~InstX8632Cmov() override {}
Jan Vounge4da26f2014-07-15 17:52:39 -07001107
Jan Voungbd385e42014-09-18 18:18:10 -07001108 CondX86::BrCond Condition;
Jan Vounge4da26f2014-07-15 17:52:39 -07001109};
1110
Matt Walace0ca8f2014-07-24 12:34:20 -07001111// Cmpps instruction - compare packed singled-precision floating point
1112// values
1113class InstX8632Cmpps : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001114 InstX8632Cmpps(const InstX8632Cmpps &) = delete;
1115 InstX8632Cmpps &operator=(const InstX8632Cmpps &) = delete;
1116
Matt Walace0ca8f2014-07-24 12:34:20 -07001117public:
Matt Walace0ca8f2014-07-24 12:34:20 -07001118 static InstX8632Cmpps *create(Cfg *Func, Variable *Dest, Operand *Source,
Jan Voungbd385e42014-09-18 18:18:10 -07001119 CondX86::CmppsCond Condition) {
Matt Walace0ca8f2014-07-24 12:34:20 -07001120 return new (Func->allocate<InstX8632Cmpps>())
1121 InstX8632Cmpps(Func, Dest, Source, Condition);
1122 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001123 void emit(const Cfg *Func) const override;
1124 void emitIAS(const Cfg *Func) const override;
1125 void dump(const Cfg *Func) const override;
Matt Walace0ca8f2014-07-24 12:34:20 -07001126 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpps); }
1127
1128private:
Jan Voungbd385e42014-09-18 18:18:10 -07001129 InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source,
1130 CondX86::CmppsCond Cond);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001131 ~InstX8632Cmpps() override {}
Matt Walace0ca8f2014-07-24 12:34:20 -07001132
Jan Voungbd385e42014-09-18 18:18:10 -07001133 CondX86::CmppsCond Condition;
Matt Walace0ca8f2014-07-24 12:34:20 -07001134};
1135
Jan Vounga3a01a22014-07-14 10:32:41 -07001136// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest>
1137// equals eax. If so, the ZF is set and <desired> is stored in <dest>.
1138// If not, ZF is cleared and <dest> is copied to eax (or subregister).
1139// <dest> can be a register or memory, while <desired> must be a register.
1140// It is the user's responsiblity to mark eax with a FakeDef.
1141class InstX8632Cmpxchg : public InstX8632Lockable {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001142 InstX8632Cmpxchg(const InstX8632Cmpxchg &) = delete;
1143 InstX8632Cmpxchg &operator=(const InstX8632Cmpxchg &) = delete;
1144
Jan Vounga3a01a22014-07-14 10:32:41 -07001145public:
1146 static InstX8632Cmpxchg *create(Cfg *Func, Operand *DestOrAddr, Variable *Eax,
1147 Variable *Desired, bool Locked) {
1148 return new (Func->allocate<InstX8632Cmpxchg>())
1149 InstX8632Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked);
1150 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001151 void emit(const Cfg *Func) const override;
1152 void emitIAS(const Cfg *Func) const override;
1153 void dump(const Cfg *Func) const override;
Jan Vounga3a01a22014-07-14 10:32:41 -07001154 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg); }
1155
1156private:
1157 InstX8632Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax,
1158 Variable *Desired, bool Locked);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001159 ~InstX8632Cmpxchg() override {}
Jan Vounga3a01a22014-07-14 10:32:41 -07001160};
1161
1162// Cmpxchg8b instruction - cmpxchg8b <m64> will compare if <m64>
1163// equals edx:eax. If so, the ZF is set and ecx:ebx is stored in <m64>.
1164// If not, ZF is cleared and <m64> is copied to edx:eax.
1165// The caller is responsible for inserting FakeDefs to mark edx
1166// and eax as modified.
1167// <m64> must be a memory operand.
1168class InstX8632Cmpxchg8b : public InstX8632Lockable {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001169 InstX8632Cmpxchg8b(const InstX8632Cmpxchg8b &) = delete;
1170 InstX8632Cmpxchg8b &operator=(const InstX8632Cmpxchg8b &) = delete;
1171
Jan Vounga3a01a22014-07-14 10:32:41 -07001172public:
Jan Voung03532e52014-09-23 13:32:18 -07001173 static InstX8632Cmpxchg8b *create(Cfg *Func, OperandX8632Mem *Dest,
Jan Vounga3a01a22014-07-14 10:32:41 -07001174 Variable *Edx, Variable *Eax, Variable *Ecx,
1175 Variable *Ebx, bool Locked) {
1176 return new (Func->allocate<InstX8632Cmpxchg8b>())
1177 InstX8632Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked);
1178 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001179 void emit(const Cfg *Func) const override;
1180 void emitIAS(const Cfg *Func) const override;
1181 void dump(const Cfg *Func) const override;
Jan Vounga3a01a22014-07-14 10:32:41 -07001182 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg8b); }
1183
1184private:
Jan Voung03532e52014-09-23 13:32:18 -07001185 InstX8632Cmpxchg8b(Cfg *Func, OperandX8632Mem *Dest, Variable *Edx,
Jan Vounga3a01a22014-07-14 10:32:41 -07001186 Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001187 ~InstX8632Cmpxchg8b() override {}
Jan Vounga3a01a22014-07-14 10:32:41 -07001188};
1189
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001190// Cvt instruction - wrapper for cvtsX2sY where X and Y are in {s,d,i}
1191// as appropriate. s=float, d=double, i=int. X and Y are determined
1192// from dest/src types. Sign and zero extension on the integer
1193// operand needs to be done separately.
1194class InstX8632Cvt : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001195 InstX8632Cvt(const InstX8632Cvt &) = delete;
1196 InstX8632Cvt &operator=(const InstX8632Cvt &) = delete;
1197
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001198public:
Jan Voung699bf022014-10-08 13:52:10 -07001199 enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq };
Jim Stichnothb63cd882014-09-08 10:47:23 -07001200 static InstX8632Cvt *create(Cfg *Func, Variable *Dest, Operand *Source,
Jan Voung699bf022014-10-08 13:52:10 -07001201 CvtVariant Variant) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001202 return new (Func->allocate<InstX8632Cvt>())
Jan Voung699bf022014-10-08 13:52:10 -07001203 InstX8632Cvt(Func, Dest, Source, Variant);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001204 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001205 void emit(const Cfg *Func) const override;
Jan Voung699bf022014-10-08 13:52:10 -07001206 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001207 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001208 static bool classof(const Inst *Inst) { return isClassof(Inst, Cvt); }
Jan Voung699bf022014-10-08 13:52:10 -07001209 bool isTruncating() const { return Variant == Tss2si || Variant == Tps2dq; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001210
1211private:
Jan Voung699bf022014-10-08 13:52:10 -07001212 CvtVariant Variant;
1213 InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source, CvtVariant Variant);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001214 ~InstX8632Cvt() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001215};
1216
1217// cmp - Integer compare instruction.
1218class InstX8632Icmp : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001219 InstX8632Icmp(const InstX8632Icmp &) = delete;
1220 InstX8632Icmp &operator=(const InstX8632Icmp &) = delete;
1221
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001222public:
1223 static InstX8632Icmp *create(Cfg *Func, Operand *Src1, Operand *Src2) {
1224 return new (Func->allocate<InstX8632Icmp>())
1225 InstX8632Icmp(Func, Src1, Src2);
1226 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001227 void emit(const Cfg *Func) const override;
Jan Vounge4dc61b2014-10-06 08:53:52 -07001228 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001229 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001230 static bool classof(const Inst *Inst) { return isClassof(Inst, Icmp); }
1231
1232private:
1233 InstX8632Icmp(Cfg *Func, Operand *Src1, Operand *Src2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001234 ~InstX8632Icmp() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001235};
1236
1237// ucomiss/ucomisd - floating-point compare instruction.
1238class InstX8632Ucomiss : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001239 InstX8632Ucomiss(const InstX8632Ucomiss &) = delete;
1240 InstX8632Ucomiss &operator=(const InstX8632Ucomiss &) = delete;
1241
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001242public:
1243 static InstX8632Ucomiss *create(Cfg *Func, Operand *Src1, Operand *Src2) {
1244 return new (Func->allocate<InstX8632Ucomiss>())
1245 InstX8632Ucomiss(Func, Src1, Src2);
1246 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001247 void emit(const Cfg *Func) const override;
1248 void emitIAS(const Cfg *Func) const override;
1249 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001250 static bool classof(const Inst *Inst) { return isClassof(Inst, Ucomiss); }
1251
1252private:
1253 InstX8632Ucomiss(Cfg *Func, Operand *Src1, Operand *Src2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001254 ~InstX8632Ucomiss() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001255};
1256
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001257// UD2 instruction.
1258class InstX8632UD2 : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001259 InstX8632UD2(const InstX8632UD2 &) = delete;
1260 InstX8632UD2 &operator=(const InstX8632UD2 &) = delete;
1261
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001262public:
1263 static InstX8632UD2 *create(Cfg *Func) {
1264 return new (Func->allocate<InstX8632UD2>()) InstX8632UD2(Func);
1265 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001266 void emit(const Cfg *Func) const override;
Jan Vounge4dc61b2014-10-06 08:53:52 -07001267 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001268 void dump(const Cfg *Func) const override;
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001269 static bool classof(const Inst *Inst) { return isClassof(Inst, UD2); }
1270
1271private:
1272 InstX8632UD2(Cfg *Func);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001273 ~InstX8632UD2() override {}
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001274};
1275
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001276// Test instruction.
1277class InstX8632Test : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001278 InstX8632Test(const InstX8632Test &) = delete;
1279 InstX8632Test &operator=(const InstX8632Test &) = delete;
1280
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001281public:
1282 static InstX8632Test *create(Cfg *Func, Operand *Source1, Operand *Source2) {
1283 return new (Func->allocate<InstX8632Test>())
1284 InstX8632Test(Func, Source1, Source2);
1285 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001286 void emit(const Cfg *Func) const override;
Jan Vounge4dc61b2014-10-06 08:53:52 -07001287 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001288 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001289 static bool classof(const Inst *Inst) { return isClassof(Inst, Test); }
1290
1291private:
1292 InstX8632Test(Cfg *Func, Operand *Source1, Operand *Source2);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001293 ~InstX8632Test() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001294};
1295
Jan Voung5cd240d2014-06-25 10:36:46 -07001296// Mfence instruction.
1297class InstX8632Mfence : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001298 InstX8632Mfence(const InstX8632Mfence &) = delete;
1299 InstX8632Mfence &operator=(const InstX8632Mfence &) = delete;
1300
Jan Voung5cd240d2014-06-25 10:36:46 -07001301public:
1302 static InstX8632Mfence *create(Cfg *Func) {
1303 return new (Func->allocate<InstX8632Mfence>()) InstX8632Mfence(Func);
1304 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001305 void emit(const Cfg *Func) const override;
Jan Voungaf2780c2014-09-26 11:14:30 -07001306 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001307 void dump(const Cfg *Func) const override;
Jan Voung5cd240d2014-06-25 10:36:46 -07001308 static bool classof(const Inst *Inst) { return isClassof(Inst, Mfence); }
1309
1310private:
1311 InstX8632Mfence(Cfg *Func);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001312 ~InstX8632Mfence() override {}
Jan Voung5cd240d2014-06-25 10:36:46 -07001313};
1314
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001315// This is essentially a "mov" instruction with an OperandX8632Mem
1316// operand instead of Variable as the destination. It's important
1317// for liveness that there is no Dest operand.
1318class InstX8632Store : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001319 InstX8632Store(const InstX8632Store &) = delete;
1320 InstX8632Store &operator=(const InstX8632Store &) = delete;
1321
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001322public:
1323 static InstX8632Store *create(Cfg *Func, Operand *Value, OperandX8632 *Mem) {
1324 return new (Func->allocate<InstX8632Store>())
1325 InstX8632Store(Func, Value, Mem);
1326 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001327 void emit(const Cfg *Func) const override;
Jan Voung198b2942014-10-16 09:40:02 -07001328 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001329 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001330 static bool classof(const Inst *Inst) { return isClassof(Inst, Store); }
1331
1332private:
1333 InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001334 ~InstX8632Store() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001335};
1336
Jan Vounge4dc61b2014-10-06 08:53:52 -07001337// This is essentially a vector "mov" instruction with an OperandX8632Mem
1338// operand instead of Variable as the destination. It's important
1339// for liveness that there is no Dest operand. The source must be an
1340// Xmm register, since Dest is mem.
Matt Wala105b7042014-08-11 19:56:19 -07001341class InstX8632StoreP : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001342 InstX8632StoreP(const InstX8632StoreP &) = delete;
1343 InstX8632StoreP &operator=(const InstX8632StoreP &) = delete;
1344
Matt Wala105b7042014-08-11 19:56:19 -07001345public:
Jan Vounge4dc61b2014-10-06 08:53:52 -07001346 static InstX8632StoreP *create(Cfg *Func, Variable *Value,
1347 OperandX8632Mem *Mem) {
Matt Wala105b7042014-08-11 19:56:19 -07001348 return new (Func->allocate<InstX8632StoreP>())
1349 InstX8632StoreP(Func, Value, Mem);
1350 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001351 void emit(const Cfg *Func) const override;
Jan Vounge4dc61b2014-10-06 08:53:52 -07001352 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001353 void dump(const Cfg *Func) const override;
Matt Wala105b7042014-08-11 19:56:19 -07001354 static bool classof(const Inst *Inst) { return isClassof(Inst, StoreP); }
1355
1356private:
Jan Vounge4dc61b2014-10-06 08:53:52 -07001357 InstX8632StoreP(Cfg *Func, Variable *Value, OperandX8632Mem *Mem);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001358 ~InstX8632StoreP() override {}
Matt Wala105b7042014-08-11 19:56:19 -07001359};
1360
Jan Voung5cd240d2014-06-25 10:36:46 -07001361class InstX8632StoreQ : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001362 InstX8632StoreQ(const InstX8632StoreQ &) = delete;
1363 InstX8632StoreQ &operator=(const InstX8632StoreQ &) = delete;
1364
Jan Voung5cd240d2014-06-25 10:36:46 -07001365public:
Jan Vounge4dc61b2014-10-06 08:53:52 -07001366 static InstX8632StoreQ *create(Cfg *Func, Variable *Value,
1367 OperandX8632Mem *Mem) {
Jan Voung5cd240d2014-06-25 10:36:46 -07001368 return new (Func->allocate<InstX8632StoreQ>())
1369 InstX8632StoreQ(Func, Value, Mem);
1370 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001371 void emit(const Cfg *Func) const override;
Jan Vounge4dc61b2014-10-06 08:53:52 -07001372 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001373 void dump(const Cfg *Func) const override;
Jan Voung5cd240d2014-06-25 10:36:46 -07001374 static bool classof(const Inst *Inst) { return isClassof(Inst, StoreQ); }
1375
1376private:
Jan Vounge4dc61b2014-10-06 08:53:52 -07001377 InstX8632StoreQ(Cfg *Func, Variable *Value, OperandX8632Mem *Mem);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001378 ~InstX8632StoreQ() override {}
Jan Voung5cd240d2014-06-25 10:36:46 -07001379};
1380
Matt Walac3302742014-08-15 16:21:56 -07001381// Nop instructions of varying length
1382class InstX8632Nop : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001383 InstX8632Nop(const InstX8632Nop &) = delete;
1384 InstX8632Nop &operator=(const InstX8632Nop &) = delete;
1385
Matt Walac3302742014-08-15 16:21:56 -07001386public:
1387 // TODO: Replace with enum.
1388 typedef unsigned NopVariant;
1389
1390 static InstX8632Nop *create(Cfg *Func, NopVariant Variant) {
1391 return new (Func->allocate<InstX8632Nop>()) InstX8632Nop(Func, Variant);
1392 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001393 void emit(const Cfg *Func) const override;
1394 void emitIAS(const Cfg *Func) const override;
1395 void dump(const Cfg *Func) const override;
Matt Walac3302742014-08-15 16:21:56 -07001396 static bool classof(const Inst *Inst) { return isClassof(Inst, Nop); }
1397
1398private:
1399 InstX8632Nop(Cfg *Func, SizeT Length);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001400 ~InstX8632Nop() override {}
Matt Walac3302742014-08-15 16:21:56 -07001401
1402 NopVariant Variant;
1403};
1404
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001405// Fld - load a value onto the x87 FP stack.
1406class InstX8632Fld : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001407 InstX8632Fld(const InstX8632Fld &) = delete;
1408 InstX8632Fld &operator=(const InstX8632Fld &) = delete;
1409
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001410public:
1411 static InstX8632Fld *create(Cfg *Func, Operand *Src) {
1412 return new (Func->allocate<InstX8632Fld>()) InstX8632Fld(Func, Src);
1413 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001414 void emit(const Cfg *Func) const override;
Jan Voung479e5632014-10-08 21:05:27 -07001415 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001416 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001417 static bool classof(const Inst *Inst) { return isClassof(Inst, Fld); }
1418
1419private:
1420 InstX8632Fld(Cfg *Func, Operand *Src);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001421 ~InstX8632Fld() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001422};
1423
1424// Fstp - store x87 st(0) into memory and pop st(0).
1425class InstX8632Fstp : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001426 InstX8632Fstp(const InstX8632Fstp &) = delete;
1427 InstX8632Fstp &operator=(const InstX8632Fstp &) = delete;
1428
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001429public:
1430 static InstX8632Fstp *create(Cfg *Func, Variable *Dest) {
1431 return new (Func->allocate<InstX8632Fstp>()) InstX8632Fstp(Func, Dest);
1432 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001433 void emit(const Cfg *Func) const override;
Jan Voung479e5632014-10-08 21:05:27 -07001434 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001435 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001436 static bool classof(const Inst *Inst) { return isClassof(Inst, Fstp); }
1437
1438private:
1439 InstX8632Fstp(Cfg *Func, Variable *Dest);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001440 ~InstX8632Fstp() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001441};
1442
1443class InstX8632Pop : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001444 InstX8632Pop(const InstX8632Pop &) = delete;
1445 InstX8632Pop &operator=(const InstX8632Pop &) = delete;
1446
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001447public:
1448 static InstX8632Pop *create(Cfg *Func, Variable *Dest) {
1449 return new (Func->allocate<InstX8632Pop>()) InstX8632Pop(Func, Dest);
1450 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001451 void emit(const Cfg *Func) const override;
1452 void emitIAS(const Cfg *Func) const override;
1453 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001454 static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); }
1455
1456private:
1457 InstX8632Pop(Cfg *Func, Variable *Dest);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001458 ~InstX8632Pop() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001459};
1460
1461class InstX8632Push : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001462 InstX8632Push(const InstX8632Push &) = delete;
1463 InstX8632Push &operator=(const InstX8632Push &) = delete;
1464
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001465public:
Jan Voung0b9eee52014-10-07 11:20:10 -07001466 static InstX8632Push *create(Cfg *Func, Variable *Source) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001467 return new (Func->allocate<InstX8632Push>())
Jan Voung0b9eee52014-10-07 11:20:10 -07001468 InstX8632Push(Func, Source);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001469 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001470 void emit(const Cfg *Func) const override;
Jan Voung0b9eee52014-10-07 11:20:10 -07001471 void emitIAS(const Cfg *Func) const override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001472 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001473 static bool classof(const Inst *Inst) { return isClassof(Inst, Push); }
1474
1475private:
Jan Voung0b9eee52014-10-07 11:20:10 -07001476 InstX8632Push(Cfg *Func, Variable *Source);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001477 ~InstX8632Push() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001478};
1479
1480// Ret instruction. Currently only supports the "ret" version that
1481// does not pop arguments. This instruction takes a Source operand
1482// (for non-void returning functions) for liveness analysis, though
1483// a FakeUse before the ret would do just as well.
1484class InstX8632Ret : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001485 InstX8632Ret(const InstX8632Ret &) = delete;
1486 InstX8632Ret &operator=(const InstX8632Ret &) = delete;
1487
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001488public:
1489 static InstX8632Ret *create(Cfg *Func, Variable *Source = NULL) {
1490 return new (Func->allocate<InstX8632Ret>()) InstX8632Ret(Func, Source);
1491 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001492 void emit(const Cfg *Func) const override;
1493 void emitIAS(const Cfg *Func) const override;
1494 void dump(const Cfg *Func) const override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001495 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); }
1496
1497private:
1498 InstX8632Ret(Cfg *Func, Variable *Source);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001499 ~InstX8632Ret() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001500};
1501
Jan Voung5cd240d2014-06-25 10:36:46 -07001502// Exchanging Add instruction. Exchanges the first operand (destination
1503// operand) with the second operand (source operand), then loads the sum
1504// of the two values into the destination operand. The destination may be
1505// a register or memory, while the source must be a register.
1506//
1507// Both the dest and source are updated. The caller should then insert a
1508// FakeDef to reflect the second udpate.
Jan Vounga3a01a22014-07-14 10:32:41 -07001509class InstX8632Xadd : public InstX8632Lockable {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001510 InstX8632Xadd(const InstX8632Xadd &) = delete;
1511 InstX8632Xadd &operator=(const InstX8632Xadd &) = delete;
1512
Jan Voung5cd240d2014-06-25 10:36:46 -07001513public:
1514 static InstX8632Xadd *create(Cfg *Func, Operand *Dest, Variable *Source,
1515 bool Locked) {
1516 return new (Func->allocate<InstX8632Xadd>())
1517 InstX8632Xadd(Func, Dest, Source, Locked);
1518 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001519 void emit(const Cfg *Func) const override;
1520 void emitIAS(const Cfg *Func) const override;
1521 void dump(const Cfg *Func) const override;
Jan Voung5cd240d2014-06-25 10:36:46 -07001522 static bool classof(const Inst *Inst) { return isClassof(Inst, Xadd); }
1523
1524private:
Jan Voung5cd240d2014-06-25 10:36:46 -07001525 InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source, bool Locked);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001526 ~InstX8632Xadd() override {}
Jan Voung5cd240d2014-06-25 10:36:46 -07001527};
1528
Jan Vounga3a01a22014-07-14 10:32:41 -07001529// Exchange instruction. Exchanges the first operand (destination
1530// operand) with the second operand (source operand). At least one of
1531// the operands must be a register (and the other can be reg or mem).
1532// Both the Dest and Source are updated. If there is a memory operand,
1533// then the instruction is automatically "locked" without the need for
1534// a lock prefix.
1535class InstX8632Xchg : public InstX8632 {
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001536 InstX8632Xchg(const InstX8632Xchg &) = delete;
1537 InstX8632Xchg &operator=(const InstX8632Xchg &) = delete;
1538
Jan Vounga3a01a22014-07-14 10:32:41 -07001539public:
1540 static InstX8632Xchg *create(Cfg *Func, Operand *Dest, Variable *Source) {
1541 return new (Func->allocate<InstX8632Xchg>())
1542 InstX8632Xchg(Func, Dest, Source);
1543 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001544 void emit(const Cfg *Func) const override;
1545 void emitIAS(const Cfg *Func) const override;
1546 void dump(const Cfg *Func) const override;
Jan Vounga3a01a22014-07-14 10:32:41 -07001547 static bool classof(const Inst *Inst) { return isClassof(Inst, Xchg); }
1548
1549private:
1550 InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source);
Jim Stichnothb56c8f42014-09-26 09:28:46 -07001551 ~InstX8632Xchg() override {}
Jan Vounga3a01a22014-07-14 10:32:41 -07001552};
1553
Jim Stichnoth6e992142014-07-30 14:45:20 -07001554// Declare partial template specializations of emit() methods that
1555// already have default implementations. Without this, there is the
1556// possibility of ODR violations and link errors.
1557template <> void InstX8632Addss::emit(const Cfg *Func) const;
1558template <> void InstX8632Blendvps::emit(const Cfg *Func) const;
Matt Wala51e8cfb2014-08-08 08:39:40 -07001559template <> void InstX8632Cbwdq::emit(const Cfg *Func) const;
Jim Stichnoth6e992142014-07-30 14:45:20 -07001560template <> void InstX8632Div::emit(const Cfg *Func) const;
1561template <> void InstX8632Divss::emit(const Cfg *Func) const;
1562template <> void InstX8632Idiv::emit(const Cfg *Func) const;
1563template <> void InstX8632Imul::emit(const Cfg *Func) const;
1564template <> void InstX8632Lea::emit(const Cfg *Func) const;
1565template <> void InstX8632Mulss::emit(const Cfg *Func) const;
1566template <> void InstX8632Padd::emit(const Cfg *Func) const;
1567template <> void InstX8632Pblendvb::emit(const Cfg *Func) const;
1568template <> void InstX8632Pcmpeq::emit(const Cfg *Func) const;
1569template <> void InstX8632Pcmpgt::emit(const Cfg *Func) const;
1570template <> void InstX8632Pextr::emit(const Cfg *Func) const;
1571template <> void InstX8632Pinsr::emit(const Cfg *Func) const;
1572template <> void InstX8632Pmull::emit(const Cfg *Func) const;
1573template <> void InstX8632Pmuludq::emit(const Cfg *Func) const;
1574template <> void InstX8632Psll::emit(const Cfg *Func) const;
1575template <> void InstX8632Psra::emit(const Cfg *Func) const;
1576template <> void InstX8632Psub::emit(const Cfg *Func) const;
1577template <> void InstX8632Sqrtss::emit(const Cfg *Func) const;
1578template <> void InstX8632Subss::emit(const Cfg *Func) const;
1579
Jan Voungd026c442014-10-13 14:06:50 -07001580template <> void InstX8632Blendvps::emitIAS(const Cfg *Func) const;
Jan Voung962befa2014-10-15 09:32:58 -07001581template <> void InstX8632Cbwdq::emitIAS(const Cfg *Func) const;
Jan Voungaf2780c2014-09-26 11:14:30 -07001582template <> void InstX8632Div::emitIAS(const Cfg *Func) const;
1583template <> void InstX8632Idiv::emitIAS(const Cfg *Func) const;
Jan Voung0ac50dc2014-09-30 08:36:06 -07001584template <> void InstX8632Imul::emitIAS(const Cfg *Func) const;
Jan Voung962befa2014-10-15 09:32:58 -07001585template <> void InstX8632Insertps::emitIAS(const Cfg *Func) const;
Jan Voung3b43b892014-09-24 13:32:39 -07001586template <> void InstX8632Movd::emitIAS(const Cfg *Func) const;
Jan Vounge4dc61b2014-10-06 08:53:52 -07001587template <> void InstX8632MovssRegs::emitIAS(const Cfg *Func) const;
Jan Voungd026c442014-10-13 14:06:50 -07001588template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const;
Jan Voung962befa2014-10-15 09:32:58 -07001589template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const;
1590template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const;
Jan Voung39d4aca2014-10-15 15:16:54 -07001591template <> void InstX8632Movsx::emitIAS(const Cfg *Func) const;
1592template <> void InstX8632Movzx::emitIAS(const Cfg *Func) const;
Jan Voung8bcca042014-10-03 21:58:02 -07001593template <> void InstX8632Pmull::emitIAS(const Cfg *Func) const;
Jan Voung962befa2014-10-15 09:32:58 -07001594template <> void InstX8632Pshufd::emitIAS(const Cfg *Func) const;
1595template <> void InstX8632Shufps::emitIAS(const Cfg *Func) const;
Jan Voung03532e52014-09-23 13:32:18 -07001596
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001597} // end of namespace Ice
1598
1599#endif // SUBZERO_SRC_ICEINSTX8632_H