Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(279)

Side by Side Diff: src/IceInstX86BaseImpl.h

Issue 1548363002: Subzero. Code organization. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- subzero/src/IceInstX86BaseImpl.h - Generic X86 instructions -*- C++ -*=// 1 //===- subzero/src/IceInstX86BaseImpl.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 Implements the InstX86Base class and its descendants. 11 /// \brief Implements the InstX86Base class and its descendants.
12 /// 12 ///
13 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
14 14
15 #ifndef SUBZERO_SRC_ICEINSTX86BASEIMPL_H 15 #ifndef SUBZERO_SRC_ICEINSTX86BASEIMPL_H
16 #define SUBZERO_SRC_ICEINSTX86BASEIMPL_H 16 #define SUBZERO_SRC_ICEINSTX86BASEIMPL_H
17 17
18 #include "IceInstX86Base.h" 18 #include "IceInstX86Base.h"
19 19
20 #include "IceAssemblerX86Base.h" 20 #include "IceAssemblerX86Base.h"
21 #include "IceCfg.h" 21 #include "IceCfg.h"
22 #include "IceCfgNode.h" 22 #include "IceCfgNode.h"
23 #include "IceDefs.h" 23 #include "IceDefs.h"
24 #include "IceInst.h" 24 #include "IceInst.h"
25 #include "IceOperand.h" 25 #include "IceOperand.h"
26 #include "IceTargetLowering.h" 26 #include "IceTargetLowering.h"
27 27
28 namespace Ice { 28 namespace Ice {
29 29
30 namespace X86Internal { 30 namespace X86NAMESPACE {
31 31
32 template <class Machine> 32 template <typename TraitsType>
33 const char *InstX86Base<Machine>::getWidthString(Type Ty) { 33 const char *InstImpl<TraitsType>::InstX86Base::getWidthString(Type Ty) {
34 return Traits::TypeAttributes[Ty].WidthString; 34 return Traits::TypeAttributes[Ty].WidthString;
35 } 35 }
36 36
37 template <class Machine> 37 template <typename TraitsType>
38 const char *InstX86Base<Machine>::getFldString(Type Ty) { 38 const char *InstImpl<TraitsType>::InstX86Base::getFldString(Type Ty) {
39 return Traits::TypeAttributes[Ty].FldString; 39 return Traits::TypeAttributes[Ty].FldString;
40 } 40 }
41 41
42 template <class Machine> 42 template <typename TraitsType>
43 typename InstX86Base<Machine>::Traits::Cond::BrCond 43 typename InstImpl<TraitsType>::Cond::BrCond
44 InstX86Base<Machine>::getOppositeCondition(typename Traits::Cond::BrCond Cond) { 44 InstImpl<TraitsType>::InstX86Base::getOppositeCondition(BrCond Cond) {
45 return Traits::InstBrAttributes[Cond].Opposite; 45 return Traits::InstBrAttributes[Cond].Opposite;
46 } 46 }
47 47
48 template <class Machine> 48 template <typename TraitsType>
49 InstX86FakeRMW<Machine>::InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr, 49 InstImpl<TraitsType>::InstX86FakeRMW::InstX86FakeRMW(Cfg *Func, Operand *Data,
50 InstArithmetic::OpKind Op, 50 Operand *Addr,
51 Variable *Beacon) 51 InstArithmetic::OpKind Op,
52 : InstX86Base<Machine>(Func, InstX86Base<Machine>::FakeRMW, 3, nullptr), 52 Variable *Beacon)
53 Op(Op) { 53 : InstX86Base(Func, InstX86Base::FakeRMW, 3, nullptr), Op(Op) {
54 this->addSource(Data); 54 this->addSource(Data);
55 this->addSource(Addr); 55 this->addSource(Addr);
56 this->addSource(Beacon); 56 this->addSource(Beacon);
57 } 57 }
58 58
59 template <class Machine> 59 template <typename TraitsType>
60 InstX86Mul<Machine>::InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1, 60 InstImpl<TraitsType>::InstX86Mul::InstX86Mul(Cfg *Func, Variable *Dest,
61 Operand *Source2) 61 Variable *Source1,
62 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Mul, 2, Dest) { 62 Operand *Source2)
63 : InstX86Base(Func, InstX86Base::Mul, 2, Dest) {
63 this->addSource(Source1); 64 this->addSource(Source1);
64 this->addSource(Source2); 65 this->addSource(Source2);
65 } 66 }
66 67
67 template <class Machine> 68 template <typename TraitsType>
68 InstX86Shld<Machine>::InstX86Shld(Cfg *Func, Variable *Dest, Variable *Source1, 69 InstImpl<TraitsType>::InstX86Shld::InstX86Shld(Cfg *Func, Variable *Dest,
69 Operand *Source2) 70 Variable *Source1,
70 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Shld, 3, Dest) { 71 Operand *Source2)
72 : InstX86Base(Func, InstX86Base::Shld, 3, Dest) {
71 this->addSource(Dest); 73 this->addSource(Dest);
72 this->addSource(Source1); 74 this->addSource(Source1);
73 this->addSource(Source2); 75 this->addSource(Source2);
74 } 76 }
75 77
76 template <class Machine> 78 template <typename TraitsType>
77 InstX86Shrd<Machine>::InstX86Shrd(Cfg *Func, Variable *Dest, Variable *Source1, 79 InstImpl<TraitsType>::InstX86Shrd::InstX86Shrd(Cfg *Func, Variable *Dest,
78 Operand *Source2) 80 Variable *Source1,
79 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Shrd, 3, Dest) { 81 Operand *Source2)
82 : InstX86Base(Func, InstX86Base::Shrd, 3, Dest) {
80 this->addSource(Dest); 83 this->addSource(Dest);
81 this->addSource(Source1); 84 this->addSource(Source1);
82 this->addSource(Source2); 85 this->addSource(Source2);
83 } 86 }
84 87
85 template <class Machine> 88 template <typename TraitsType>
86 InstX86Label<Machine>::InstX86Label( 89 InstImpl<TraitsType>::InstX86Label::InstX86Label(Cfg *Func,
87 Cfg *Func, typename InstX86Base<Machine>::Traits::TargetLowering *Target) 90 TargetLowering *Target)
88 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Label, 0, nullptr), 91 : InstX86Base(Func, InstX86Base::Label, 0, nullptr),
89 Number(Target->makeNextLabelNumber()) {} 92 Number(Target->makeNextLabelNumber()) {}
90 93
91 template <class Machine> 94 template <typename TraitsType>
92 IceString InstX86Label<Machine>::getName(const Cfg *Func) const { 95 IceString InstImpl<TraitsType>::InstX86Label::getName(const Cfg *Func) const {
93 return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number); 96 return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number);
94 } 97 }
95 98
96 template <class Machine> 99 template <typename TraitsType>
97 InstX86Br<Machine>::InstX86Br( 100 InstImpl<TraitsType>::InstX86Br::InstX86Br(
98 Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, 101 Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
99 const InstX86Label<Machine> *Label, 102 const InstImpl<TraitsType>::InstX86Label *Label, BrCond Condition,
100 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, Mode Kind) 103 Mode Kind)
101 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Br, 0, nullptr), 104 : InstX86Base(Func, InstX86Base::Br, 0, nullptr), Condition(Condition),
102 Condition(Condition), TargetTrue(TargetTrue), TargetFalse(TargetFalse), 105 TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label),
103 Label(Label), Kind(Kind) {} 106 Kind(Kind) {}
104 107
105 template <class Machine> 108 template <typename TraitsType>
106 bool InstX86Br<Machine>::optimizeBranch(const CfgNode *NextNode) { 109 bool InstImpl<TraitsType>::InstX86Br::optimizeBranch(const CfgNode *NextNode) {
107 // If there is no next block, then there can be no fallthrough to optimize. 110 // If there is no next block, then there can be no fallthrough to optimize.
108 if (NextNode == nullptr) 111 if (NextNode == nullptr)
109 return false; 112 return false;
110 // Intra-block conditional branches can't be optimized. 113 // Intra-block conditional branches can't be optimized.
111 if (Label) 114 if (Label)
112 return false; 115 return false;
113 // If there is no fallthrough node, such as a non-default case label for a 116 // If there is no fallthrough node, such as a non-default case label for a
114 // switch instruction, then there is no opportunity to optimize. 117 // switch instruction, then there is no opportunity to optimize.
115 if (getTargetFalse() == nullptr) 118 if (getTargetFalse() == nullptr)
116 return false; 119 return false;
117 120
118 // Unconditional branch to the next node can be removed. 121 // Unconditional branch to the next node can be removed.
119 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None && 122 if (Condition == Cond::Br_None && getTargetFalse() == NextNode) {
120 getTargetFalse() == NextNode) {
121 assert(getTargetTrue() == nullptr); 123 assert(getTargetTrue() == nullptr);
122 this->setDeleted(); 124 this->setDeleted();
123 return true; 125 return true;
124 } 126 }
125 // If the fallthrough is to the next node, set fallthrough to nullptr to 127 // If the fallthrough is to the next node, set fallthrough to nullptr to
126 // indicate. 128 // indicate.
127 if (getTargetFalse() == NextNode) { 129 if (getTargetFalse() == NextNode) {
128 TargetFalse = nullptr; 130 TargetFalse = nullptr;
129 return true; 131 return true;
130 } 132 }
131 // If TargetTrue is the next node, and TargetFalse is not nullptr (which was 133 // If TargetTrue is the next node, and TargetFalse is not nullptr (which was
132 // already tested above), then invert the branch condition, swap the targets, 134 // already tested above), then invert the branch condition, swap the targets,
133 // and set new fallthrough to nullptr. 135 // and set new fallthrough to nullptr.
134 if (getTargetTrue() == NextNode) { 136 if (getTargetTrue() == NextNode) {
135 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None); 137 assert(Condition != Cond::Br_None);
136 Condition = this->getOppositeCondition(Condition); 138 Condition = this->getOppositeCondition(Condition);
137 TargetTrue = getTargetFalse(); 139 TargetTrue = getTargetFalse();
138 TargetFalse = nullptr; 140 TargetFalse = nullptr;
139 return true; 141 return true;
140 } 142 }
141 return false; 143 return false;
142 } 144 }
143 145
144 template <class Machine> 146 template <typename TraitsType>
145 bool InstX86Br<Machine>::repointEdges(CfgNode *OldNode, CfgNode *NewNode) { 147 bool InstImpl<TraitsType>::InstX86Br::repointEdges(CfgNode *OldNode,
148 CfgNode *NewNode) {
146 bool Found = false; 149 bool Found = false;
147 if (TargetFalse == OldNode) { 150 if (TargetFalse == OldNode) {
148 TargetFalse = NewNode; 151 TargetFalse = NewNode;
149 Found = true; 152 Found = true;
150 } 153 }
151 if (TargetTrue == OldNode) { 154 if (TargetTrue == OldNode) {
152 TargetTrue = NewNode; 155 TargetTrue = NewNode;
153 Found = true; 156 Found = true;
154 } 157 }
155 return Found; 158 return Found;
156 } 159 }
157 160
158 template <class Machine> 161 template <typename TraitsType>
159 InstX86Jmp<Machine>::InstX86Jmp(Cfg *Func, Operand *Target) 162 InstImpl<TraitsType>::InstX86Jmp::InstX86Jmp(Cfg *Func, Operand *Target)
160 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Jmp, 1, nullptr) { 163 : InstX86Base(Func, InstX86Base::Jmp, 1, nullptr) {
161 this->addSource(Target); 164 this->addSource(Target);
162 } 165 }
163 166
164 template <class Machine> 167 template <typename TraitsType>
165 InstX86Call<Machine>::InstX86Call(Cfg *Func, Variable *Dest, 168 InstImpl<TraitsType>::InstX86Call::InstX86Call(Cfg *Func, Variable *Dest,
166 Operand *CallTarget) 169 Operand *CallTarget)
167 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Call, 1, Dest) { 170 : InstX86Base(Func, InstX86Base::Call, 1, Dest) {
168 this->HasSideEffects = true; 171 this->HasSideEffects = true;
169 this->addSource(CallTarget); 172 this->addSource(CallTarget);
170 } 173 }
171 174
172 template <class Machine> 175 template <typename TraitsType>
173 InstX86Cmov<Machine>::InstX86Cmov( 176 InstImpl<TraitsType>::InstX86Cmov::InstX86Cmov(Cfg *Func, Variable *Dest,
174 Cfg *Func, Variable *Dest, Operand *Source, 177 Operand *Source,
175 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition) 178 BrCond Condition)
176 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cmov, 2, Dest), 179 : InstX86Base(Func, InstX86Base::Cmov, 2, Dest), Condition(Condition) {
177 Condition(Condition) {
178 // The final result is either the original Dest, or Source, so mark both as 180 // The final result is either the original Dest, or Source, so mark both as
179 // sources. 181 // sources.
180 this->addSource(Dest); 182 this->addSource(Dest);
181 this->addSource(Source); 183 this->addSource(Source);
182 } 184 }
183 185
184 template <class Machine> 186 template <typename TraitsType>
185 InstX86Cmpps<Machine>::InstX86Cmpps( 187 InstImpl<TraitsType>::InstX86Cmpps::InstX86Cmpps(Cfg *Func, Variable *Dest,
186 Cfg *Func, Variable *Dest, Operand *Source, 188 Operand *Source,
187 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition) 189 CmppsCond Condition)
188 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cmpps, 2, Dest), 190 : InstX86Base(Func, InstX86Base::Cmpps, 2, Dest), Condition(Condition) {
189 Condition(Condition) {
190 this->addSource(Dest); 191 this->addSource(Dest);
191 this->addSource(Source); 192 this->addSource(Source);
192 } 193 }
193 194
194 template <class Machine> 195 template <typename TraitsType>
195 InstX86Cmpxchg<Machine>::InstX86Cmpxchg(Cfg *Func, Operand *DestOrAddr, 196 InstImpl<TraitsType>::InstX86Cmpxchg::InstX86Cmpxchg(Cfg *Func,
196 Variable *Eax, Variable *Desired, 197 Operand *DestOrAddr,
197 bool Locked) 198 Variable *Eax,
198 : InstX86BaseLockable<Machine>(Func, InstX86Base<Machine>::Cmpxchg, 3, 199 Variable *Desired,
199 llvm::dyn_cast<Variable>(DestOrAddr), 200 bool Locked)
200 Locked) { 201 : InstImpl<TraitsType>::InstX86BaseLockable(
202 Func, InstX86Base::Cmpxchg, 3, llvm::dyn_cast<Variable>(DestOrAddr),
203 Locked) {
201 constexpr uint16_t Encoded_rAX = 0; 204 constexpr uint16_t Encoded_rAX = 0;
202 (void)Encoded_rAX; 205 (void)Encoded_rAX;
203 assert(InstX86Base<Machine>::Traits::getEncodedGPR(Eax->getRegNum()) == 206 assert(Traits::getEncodedGPR(Eax->getRegNum()) == Encoded_rAX);
204 Encoded_rAX);
205 this->addSource(DestOrAddr); 207 this->addSource(DestOrAddr);
206 this->addSource(Eax); 208 this->addSource(Eax);
207 this->addSource(Desired); 209 this->addSource(Desired);
208 } 210 }
209 211
210 template <class Machine> 212 template <typename TraitsType>
211 InstX86Cmpxchg8b<Machine>::InstX86Cmpxchg8b( 213 InstImpl<TraitsType>::InstX86Cmpxchg8b::InstX86Cmpxchg8b(
212 Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *Addr, 214 Cfg *Func, X86OperandMem *Addr, Variable *Edx, Variable *Eax, Variable *Ecx,
213 Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked) 215 Variable *Ebx, bool Locked)
214 : InstX86BaseLockable<Machine>(Func, InstX86Base<Machine>::Cmpxchg, 5, 216 : InstImpl<TraitsType>::InstX86BaseLockable(Func, InstX86Base::Cmpxchg, 5,
215 nullptr, Locked) { 217 nullptr, Locked) {
216 assert(Edx->getRegNum() == 218 assert(Edx->getRegNum() == RegisterSet::Reg_edx);
217 InstX86Base<Machine>::Traits::RegisterSet::Reg_edx); 219 assert(Eax->getRegNum() == RegisterSet::Reg_eax);
218 assert(Eax->getRegNum() == 220 assert(Ecx->getRegNum() == RegisterSet::Reg_ecx);
219 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); 221 assert(Ebx->getRegNum() == RegisterSet::Reg_ebx);
220 assert(Ecx->getRegNum() ==
221 InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx);
222 assert(Ebx->getRegNum() ==
223 InstX86Base<Machine>::Traits::RegisterSet::Reg_ebx);
224 this->addSource(Addr); 222 this->addSource(Addr);
225 this->addSource(Edx); 223 this->addSource(Edx);
226 this->addSource(Eax); 224 this->addSource(Eax);
227 this->addSource(Ecx); 225 this->addSource(Ecx);
228 this->addSource(Ebx); 226 this->addSource(Ebx);
229 } 227 }
230 228
231 template <class Machine> 229 template <typename TraitsType>
232 InstX86Cvt<Machine>::InstX86Cvt(Cfg *Func, Variable *Dest, Operand *Source, 230 InstImpl<TraitsType>::InstX86Cvt::InstX86Cvt(Cfg *Func, Variable *Dest,
233 CvtVariant Variant) 231 Operand *Source,
234 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cvt, 1, Dest), 232 CvtVariant Variant)
235 Variant(Variant) { 233 : InstX86Base(Func, InstX86Base::Cvt, 1, Dest), Variant(Variant) {
236 this->addSource(Source); 234 this->addSource(Source);
237 } 235 }
238 236
239 template <class Machine> 237 template <typename TraitsType>
240 InstX86Icmp<Machine>::InstX86Icmp(Cfg *Func, Operand *Src0, Operand *Src1) 238 InstImpl<TraitsType>::InstX86Icmp::InstX86Icmp(Cfg *Func, Operand *Src0,
241 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Icmp, 2, nullptr) { 239 Operand *Src1)
240 : InstX86Base(Func, InstX86Base::Icmp, 2, nullptr) {
242 this->addSource(Src0); 241 this->addSource(Src0);
243 this->addSource(Src1); 242 this->addSource(Src1);
244 } 243 }
245 244
246 template <class Machine> 245 template <typename TraitsType>
247 InstX86Ucomiss<Machine>::InstX86Ucomiss(Cfg *Func, Operand *Src0, Operand *Src1) 246 InstImpl<TraitsType>::InstX86Ucomiss::InstX86Ucomiss(Cfg *Func, Operand *Src0,
248 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Ucomiss, 2, nullptr) { 247 Operand *Src1)
248 : InstX86Base(Func, InstX86Base::Ucomiss, 2, nullptr) {
249 this->addSource(Src0); 249 this->addSource(Src0);
250 this->addSource(Src1); 250 this->addSource(Src1);
251 } 251 }
252 252
253 template <class Machine> 253 template <typename TraitsType>
254 InstX86UD2<Machine>::InstX86UD2(Cfg *Func) 254 InstImpl<TraitsType>::InstX86UD2::InstX86UD2(Cfg *Func)
255 : InstX86Base<Machine>(Func, InstX86Base<Machine>::UD2, 0, nullptr) {} 255 : InstX86Base(Func, InstX86Base::UD2, 0, nullptr) {}
256 256
257 template <class Machine> 257 template <typename TraitsType>
258 InstX86Test<Machine>::InstX86Test(Cfg *Func, Operand *Src1, Operand *Src2) 258 InstImpl<TraitsType>::InstX86Test::InstX86Test(Cfg *Func, Operand *Src1,
259 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Test, 2, nullptr) { 259 Operand *Src2)
260 : InstX86Base(Func, InstX86Base::Test, 2, nullptr) {
260 this->addSource(Src1); 261 this->addSource(Src1);
261 this->addSource(Src2); 262 this->addSource(Src2);
262 } 263 }
263 264
264 template <class Machine> 265 template <typename TraitsType>
265 InstX86Mfence<Machine>::InstX86Mfence(Cfg *Func) 266 InstImpl<TraitsType>::InstX86Mfence::InstX86Mfence(Cfg *Func)
266 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Mfence, 0, nullptr) { 267 : InstX86Base(Func, InstX86Base::Mfence, 0, nullptr) {
267 this->HasSideEffects = true; 268 this->HasSideEffects = true;
268 } 269 }
269 270
270 template <class Machine> 271 template <typename TraitsType>
271 InstX86Store<Machine>::InstX86Store( 272 InstImpl<TraitsType>::InstX86Store::InstX86Store(Cfg *Func, Operand *Value,
272 Cfg *Func, Operand *Value, 273 X86Operand *Mem)
273 typename InstX86Base<Machine>::Traits::X86Operand *Mem) 274 : InstX86Base(Func, InstX86Base::Store, 2, nullptr) {
274 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Store, 2, nullptr) {
275 this->addSource(Value); 275 this->addSource(Value);
276 this->addSource(Mem); 276 this->addSource(Mem);
277 } 277 }
278 278
279 template <class Machine> 279 template <typename TraitsType>
280 InstX86StoreP<Machine>::InstX86StoreP( 280 InstImpl<TraitsType>::InstX86StoreP::InstX86StoreP(Cfg *Func, Variable *Value,
281 Cfg *Func, Variable *Value, 281 X86OperandMem *Mem)
282 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem) 282 : InstX86Base(Func, InstX86Base::StoreP, 2, nullptr) {
283 : InstX86Base<Machine>(Func, InstX86Base<Machine>::StoreP, 2, nullptr) {
284 this->addSource(Value); 283 this->addSource(Value);
285 this->addSource(Mem); 284 this->addSource(Mem);
286 } 285 }
287 286
288 template <class Machine> 287 template <typename TraitsType>
289 InstX86StoreQ<Machine>::InstX86StoreQ( 288 InstImpl<TraitsType>::InstX86StoreQ::InstX86StoreQ(Cfg *Func, Variable *Value,
290 Cfg *Func, Variable *Value, 289 X86OperandMem *Mem)
291 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem) 290 : InstX86Base(Func, InstX86Base::StoreQ, 2, nullptr) {
292 : InstX86Base<Machine>(Func, InstX86Base<Machine>::StoreQ, 2, nullptr) {
293 this->addSource(Value); 291 this->addSource(Value);
294 this->addSource(Mem); 292 this->addSource(Mem);
295 } 293 }
296 294
297 template <class Machine> 295 template <typename TraitsType>
298 InstX86Nop<Machine>::InstX86Nop(Cfg *Func, InstX86Nop::NopVariant Variant) 296 InstImpl<TraitsType>::InstX86Nop::InstX86Nop(Cfg *Func,
299 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Nop, 0, nullptr), 297 InstX86Nop::NopVariant Variant)
300 Variant(Variant) {} 298 : InstX86Base(Func, InstX86Base::Nop, 0, nullptr), Variant(Variant) {}
301 299
302 template <class Machine> 300 template <typename TraitsType>
303 InstX86Fld<Machine>::InstX86Fld(Cfg *Func, Operand *Src) 301 InstImpl<TraitsType>::InstX86Fld::InstX86Fld(Cfg *Func, Operand *Src)
304 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Fld, 1, nullptr) { 302 : InstX86Base(Func, InstX86Base::Fld, 1, nullptr) {
305 this->addSource(Src); 303 this->addSource(Src);
306 } 304 }
307 305
308 template <class Machine> 306 template <typename TraitsType>
309 InstX86Fstp<Machine>::InstX86Fstp(Cfg *Func, Variable *Dest) 307 InstImpl<TraitsType>::InstX86Fstp::InstX86Fstp(Cfg *Func, Variable *Dest)
310 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Fstp, 0, Dest) {} 308 : InstX86Base(Func, InstX86Base::Fstp, 0, Dest) {}
311 309
312 template <class Machine> 310 template <typename TraitsType>
313 InstX86Pop<Machine>::InstX86Pop(Cfg *Func, Variable *Dest) 311 InstImpl<TraitsType>::InstX86Pop::InstX86Pop(Cfg *Func, Variable *Dest)
314 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Pop, 0, Dest) { 312 : InstX86Base(Func, InstX86Base::Pop, 0, Dest) {
315 // A pop instruction affects the stack pointer and so it should not be 313 // A pop instruction affects the stack pointer and so it should not be
316 // allowed to be automatically dead-code eliminated. (The corresponding push 314 // allowed to be automatically dead-code eliminated. (The corresponding push
317 // instruction doesn't need this treatment because it has no dest variable 315 // instruction doesn't need this treatment because it has no dest variable
318 // and therefore won't be dead-code eliminated.) This is needed for 316 // and therefore won't be dead-code eliminated.) This is needed for
319 // late-stage liveness analysis (e.g. asm-verbose mode). 317 // late-stage liveness analysis (e.g. asm-verbose mode).
320 this->HasSideEffects = true; 318 this->HasSideEffects = true;
321 } 319 }
322 320
323 template <class Machine> 321 template <typename TraitsType>
324 InstX86Push<Machine>::InstX86Push(Cfg *Func, Variable *Source) 322 InstImpl<TraitsType>::InstX86Push::InstX86Push(Cfg *Func, Variable *Source)
325 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Push, 1, nullptr) { 323 : InstX86Base(Func, InstX86Base::Push, 1, nullptr) {
326 this->addSource(Source); 324 this->addSource(Source);
327 } 325 }
328 326
329 template <class Machine> 327 template <typename TraitsType>
330 InstX86Ret<Machine>::InstX86Ret(Cfg *Func, Variable *Source) 328 InstImpl<TraitsType>::InstX86Ret::InstX86Ret(Cfg *Func, Variable *Source)
331 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Ret, Source ? 1 : 0, 329 : InstX86Base(Func, InstX86Base::Ret, Source ? 1 : 0, nullptr) {
332 nullptr) {
333 if (Source) 330 if (Source)
334 this->addSource(Source); 331 this->addSource(Source);
335 } 332 }
336 333
337 template <class Machine> 334 template <typename TraitsType>
338 InstX86Setcc<Machine>::InstX86Setcc( 335 InstImpl<TraitsType>::InstX86Setcc::InstX86Setcc(Cfg *Func, Variable *Dest,
339 Cfg *Func, Variable *Dest, 336 BrCond Cond)
340 typename InstX86Base<Machine>::Traits::Cond::BrCond Cond) 337 : InstX86Base(Func, InstX86Base::Setcc, 0, Dest), Condition(Cond) {}
341 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Setcc, 0, Dest),
342 Condition(Cond) {}
343 338
344 template <class Machine> 339 template <typename TraitsType>
345 InstX86Xadd<Machine>::InstX86Xadd(Cfg *Func, Operand *Dest, Variable *Source, 340 InstImpl<TraitsType>::InstX86Xadd::InstX86Xadd(Cfg *Func, Operand *Dest,
346 bool Locked) 341 Variable *Source, bool Locked)
347 : InstX86BaseLockable<Machine>(Func, InstX86Base<Machine>::Xadd, 2, 342 : InstImpl<TraitsType>::InstX86BaseLockable(
348 llvm::dyn_cast<Variable>(Dest), Locked) { 343 Func, InstX86Base::Xadd, 2, llvm::dyn_cast<Variable>(Dest), Locked) {
349 this->addSource(Dest); 344 this->addSource(Dest);
350 this->addSource(Source); 345 this->addSource(Source);
351 } 346 }
352 347
353 template <class Machine> 348 template <typename TraitsType>
354 InstX86Xchg<Machine>::InstX86Xchg(Cfg *Func, Operand *Dest, Variable *Source) 349 InstImpl<TraitsType>::InstX86Xchg::InstX86Xchg(Cfg *Func, Operand *Dest,
355 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Xchg, 2, 350 Variable *Source)
356 llvm::dyn_cast<Variable>(Dest)) { 351 : InstX86Base(Func, InstX86Base::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) {
357 this->addSource(Dest); 352 this->addSource(Dest);
358 this->addSource(Source); 353 this->addSource(Source);
359 } 354 }
360 355
361 template <class Machine> 356 template <typename TraitsType>
362 InstX86IacaStart<Machine>::InstX86IacaStart(Cfg *Func) 357 InstImpl<TraitsType>::InstX86IacaStart::InstX86IacaStart(Cfg *Func)
363 : InstX86Base<Machine>(Func, InstX86Base<Machine>::IacaStart, 0, nullptr) { 358 : InstX86Base(Func, InstX86Base::IacaStart, 0, nullptr) {
364 assert(Func->getContext()->getFlags().getAllowIacaMarks()); 359 assert(Func->getContext()->getFlags().getAllowIacaMarks());
365 } 360 }
366 361
367 template <class Machine> 362 template <typename TraitsType>
368 InstX86IacaEnd<Machine>::InstX86IacaEnd(Cfg *Func) 363 InstImpl<TraitsType>::InstX86IacaEnd::InstX86IacaEnd(Cfg *Func)
369 : InstX86Base<Machine>(Func, InstX86Base<Machine>::IacaEnd, 0, nullptr) { 364 : InstX86Base(Func, InstX86Base::IacaEnd, 0, nullptr) {
370 assert(Func->getContext()->getFlags().getAllowIacaMarks()); 365 assert(Func->getContext()->getFlags().getAllowIacaMarks());
371 } 366 }
372 367
373 // ======================== Dump routines ======================== // 368 // ======================== Dump routines ======================== //
374 369
375 template <class Machine> 370 template <typename TraitsType>
376 void InstX86Base<Machine>::dump(const Cfg *Func) const { 371 void InstImpl<TraitsType>::InstX86Base::dump(const Cfg *Func) const {
377 if (!BuildDefs::dump()) 372 if (!BuildDefs::dump())
378 return; 373 return;
379 Ostream &Str = Func->getContext()->getStrDump(); 374 Ostream &Str = Func->getContext()->getStrDump();
380 Str << "[" << Traits::TargetName << "] "; 375 Str << "[" << Traits::TargetName << "] ";
381 Inst::dump(Func); 376 Inst::dump(Func);
382 } 377 }
383 378
384 template <class Machine> 379 template <typename TraitsType>
385 void InstX86FakeRMW<Machine>::dump(const Cfg *Func) const { 380 void InstImpl<TraitsType>::InstX86FakeRMW::dump(const Cfg *Func) const {
386 if (!BuildDefs::dump()) 381 if (!BuildDefs::dump())
387 return; 382 return;
388 Ostream &Str = Func->getContext()->getStrDump(); 383 Ostream &Str = Func->getContext()->getStrDump();
389 Type Ty = getData()->getType(); 384 Type Ty = getData()->getType();
390 Str << "rmw " << InstArithmetic::getOpName(getOp()) << " " << Ty << " *"; 385 Str << "rmw " << InstArithmetic::getOpName(getOp()) << " " << Ty << " *";
391 getAddr()->dump(Func); 386 getAddr()->dump(Func);
392 Str << ", "; 387 Str << ", ";
393 getData()->dump(Func); 388 getData()->dump(Func);
394 Str << ", beacon="; 389 Str << ", beacon=";
395 getBeacon()->dump(Func); 390 getBeacon()->dump(Func);
396 } 391 }
397 392
398 template <class Machine> 393 template <typename TraitsType>
399 void InstX86Label<Machine>::emit(const Cfg *Func) const { 394 void InstImpl<TraitsType>::InstX86Label::emit(const Cfg *Func) const {
400 if (!BuildDefs::dump()) 395 if (!BuildDefs::dump())
401 return; 396 return;
402 Ostream &Str = Func->getContext()->getStrEmit(); 397 Ostream &Str = Func->getContext()->getStrEmit();
403 Str << getName(Func) << ":"; 398 Str << getName(Func) << ":";
404 } 399 }
405 400
406 template <class Machine> 401 template <typename TraitsType>
407 void InstX86Label<Machine>::emitIAS(const Cfg *Func) const { 402 void InstImpl<TraitsType>::InstX86Label::emitIAS(const Cfg *Func) const {
408 typename InstX86Base<Machine>::Traits::Assembler *Asm = 403 Assembler *Asm = Func->getAssembler<Assembler>();
409 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
410 Asm->bindLocalLabel(Number); 404 Asm->bindLocalLabel(Number);
411 } 405 }
412 406
413 template <class Machine> 407 template <typename TraitsType>
414 void InstX86Label<Machine>::dump(const Cfg *Func) const { 408 void InstImpl<TraitsType>::InstX86Label::dump(const Cfg *Func) const {
415 if (!BuildDefs::dump()) 409 if (!BuildDefs::dump())
416 return; 410 return;
417 Ostream &Str = Func->getContext()->getStrDump(); 411 Ostream &Str = Func->getContext()->getStrDump();
418 Str << getName(Func) << ":"; 412 Str << getName(Func) << ":";
419 } 413 }
420 414
421 template <class Machine> void InstX86Br<Machine>::emit(const Cfg *Func) const { 415 template <typename TraitsType>
416 void InstImpl<TraitsType>::InstX86Br::emit(const Cfg *Func) const {
422 if (!BuildDefs::dump()) 417 if (!BuildDefs::dump())
423 return; 418 return;
424 Ostream &Str = Func->getContext()->getStrEmit(); 419 Ostream &Str = Func->getContext()->getStrEmit();
425 Str << "\t"; 420 Str << "\t";
426 421
427 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) { 422 if (Condition == Cond::Br_None) {
428 Str << "jmp"; 423 Str << "jmp";
429 } else { 424 } else {
430 Str << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].EmitString; 425 Str << Traits::InstBrAttributes[Condition].EmitString;
431 } 426 }
432 427
433 if (Label) { 428 if (Label) {
434 Str << "\t" << Label->getName(Func); 429 Str << "\t" << Label->getName(Func);
435 } else { 430 } else {
436 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) { 431 if (Condition == Cond::Br_None) {
437 Str << "\t" << getTargetFalse()->getAsmName(); 432 Str << "\t" << getTargetFalse()->getAsmName();
438 } else { 433 } else {
439 Str << "\t" << getTargetTrue()->getAsmName(); 434 Str << "\t" << getTargetTrue()->getAsmName();
440 if (getTargetFalse()) { 435 if (getTargetFalse()) {
441 Str << "\n\t" 436 Str << "\n\t"
442 "jmp\t" << getTargetFalse()->getAsmName(); 437 "jmp\t" << getTargetFalse()->getAsmName();
443 } 438 }
444 } 439 }
445 } 440 }
446 } 441 }
447 442
448 template <class Machine> 443 template <typename TraitsType>
449 void InstX86Br<Machine>::emitIAS(const Cfg *Func) const { 444 void InstImpl<TraitsType>::InstX86Br::emitIAS(const Cfg *Func) const {
450 typename InstX86Base<Machine>::Traits::Assembler *Asm = 445 Assembler *Asm = Func->getAssembler<Assembler>();
451 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
452 if (Label) { 446 if (Label) {
453 class Label *L = Asm->getOrCreateLocalLabel(Label->getNumber()); 447 auto *L = Asm->getOrCreateLocalLabel(Label->getNumber());
454 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) { 448 if (Condition == Cond::Br_None) {
455 Asm->jmp(L, isNear()); 449 Asm->jmp(L, isNear());
456 } else { 450 } else {
457 Asm->j(Condition, L, isNear()); 451 Asm->j(Condition, L, isNear());
458 } 452 }
459 } else { 453 } else {
460 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) { 454 if (Condition == Cond::Br_None) {
461 class Label *L = 455 auto *L = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
462 Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
463 assert(!getTargetTrue()); 456 assert(!getTargetTrue());
464 Asm->jmp(L, isNear()); 457 Asm->jmp(L, isNear());
465 } else { 458 } else {
466 class Label *L = 459 auto *L = Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex());
467 Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex());
468 Asm->j(Condition, L, isNear()); 460 Asm->j(Condition, L, isNear());
469 if (getTargetFalse()) { 461 if (getTargetFalse()) {
470 class Label *L2 = 462 auto *L2 = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
471 Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
472 Asm->jmp(L2, isNear()); 463 Asm->jmp(L2, isNear());
473 } 464 }
474 } 465 }
475 } 466 }
476 } 467 }
477 468
478 template <class Machine> void InstX86Br<Machine>::dump(const Cfg *Func) const { 469 template <typename TraitsType>
470 void InstImpl<TraitsType>::InstX86Br::dump(const Cfg *Func) const {
479 if (!BuildDefs::dump()) 471 if (!BuildDefs::dump())
480 return; 472 return;
481 Ostream &Str = Func->getContext()->getStrDump(); 473 Ostream &Str = Func->getContext()->getStrDump();
482 Str << "br "; 474 Str << "br ";
483 475
484 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) { 476 if (Condition == Cond::Br_None) {
485 Str << "label %" 477 Str << "label %"
486 << (Label ? Label->getName(Func) : getTargetFalse()->getName()); 478 << (Label ? Label->getName(Func) : getTargetFalse()->getName());
487 return; 479 return;
488 } 480 }
489 481
490 Str << InstX86Base<Machine>::Traits::InstBrAttributes[Condition] 482 Str << Traits::InstBrAttributes[Condition].DisplayString;
491 .DisplayString;
492 if (Label) { 483 if (Label) {
493 Str << ", label %" << Label->getName(Func); 484 Str << ", label %" << Label->getName(Func);
494 } else { 485 } else {
495 Str << ", label %" << getTargetTrue()->getName(); 486 Str << ", label %" << getTargetTrue()->getName();
496 if (getTargetFalse()) { 487 if (getTargetFalse()) {
497 Str << ", label %" << getTargetFalse()->getName(); 488 Str << ", label %" << getTargetFalse()->getName();
498 } 489 }
499 } 490 }
500 491
501 Str << " // (" << (isNear() ? "near" : "far") << " jump)"; 492 Str << " // (" << (isNear() ? "near" : "far") << " jump)";
502 } 493 }
503 494
504 template <class Machine> void InstX86Jmp<Machine>::emit(const Cfg *Func) const { 495 template <typename TraitsType>
496 void InstImpl<TraitsType>::InstX86Jmp::emit(const Cfg *Func) const {
505 if (!BuildDefs::dump()) 497 if (!BuildDefs::dump())
506 return; 498 return;
507 Ostream &Str = Func->getContext()->getStrEmit(); 499 Ostream &Str = Func->getContext()->getStrEmit();
508 assert(this->getSrcSize() == 1); 500 assert(this->getSrcSize() == 1);
509 Str << "\t" 501 Str << "\t"
510 "jmp\t*"; 502 "jmp\t*";
511 getJmpTarget()->emit(Func); 503 getJmpTarget()->emit(Func);
512 } 504 }
513 505
514 template <class Machine> 506 template <typename TraitsType>
515 void InstX86Jmp<Machine>::emitIAS(const Cfg *Func) const { 507 void InstImpl<TraitsType>::InstX86Jmp::emitIAS(const Cfg *Func) const {
516 // Note: Adapted (mostly copied) from InstX86Call<Machine>::emitIAS(). 508 // Note: Adapted (mostly copied) from
517 typename InstX86Base<Machine>::Traits::Assembler *Asm = 509 // InstImpl<TraitsType>::InstX86Call::emitIAS().
518 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); 510 Assembler *Asm = Func->getAssembler<Assembler>();
519 Operand *Target = getJmpTarget(); 511 Operand *Target = getJmpTarget();
520 if (const auto *Var = llvm::dyn_cast<Variable>(Target)) { 512 if (const auto *Var = llvm::dyn_cast<Variable>(Target)) {
521 if (Var->hasReg()) { 513 if (Var->hasReg()) {
522 Asm->jmp(InstX86Base<Machine>::Traits::getEncodedGPR(Var->getRegNum())); 514 Asm->jmp(Traits::getEncodedGPR(Var->getRegNum()));
523 } else { 515 } else {
524 // The jmp instruction with a memory operand should be possible to 516 // The jmp instruction with a memory operand should be possible to
525 // encode, but it isn't a valid sandboxed instruction, and there 517 // encode, but it isn't a valid sandboxed instruction, and there
526 // shouldn't be a register allocation issue to jump through a scratch 518 // shouldn't be a register allocation issue to jump through a scratch
527 // register, so we don't really need to bother implementing it. 519 // register, so we don't really need to bother implementing it.
528 llvm::report_fatal_error("Assembler can't jmp to memory operand"); 520 llvm::report_fatal_error("Assembler can't jmp to memory operand");
529 } 521 }
530 } else if (const auto *Mem = llvm::dyn_cast< 522 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Target)) {
531 typename InstX86Base<Machine>::Traits::X86OperandMem>(
532 Target)) {
533 (void)Mem; 523 (void)Mem;
534 assert(Mem->getSegmentRegister() == 524 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
535 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
536 llvm::report_fatal_error("Assembler can't jmp to memory operand"); 525 llvm::report_fatal_error("Assembler can't jmp to memory operand");
537 } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Target)) { 526 } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
538 assert(CR->getOffset() == 0 && "We only support jumping to a function"); 527 assert(CR->getOffset() == 0 && "We only support jumping to a function");
539 Asm->jmp(CR); 528 Asm->jmp(CR);
540 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { 529 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
541 // NaCl trampoline calls refer to an address within the sandbox directly. 530 // NaCl trampoline calls refer to an address within the sandbox directly.
542 // This is usually only needed for non-IRT builds and otherwise not very 531 // This is usually only needed for non-IRT builds and otherwise not very
543 // portable or stable. Usually this is only done for "calls" and not jumps. 532 // portable or stable. Usually this is only done for "calls" and not jumps.
544 // TODO(jvoung): Support this when there is a lowering that actually 533 // TODO(jvoung): Support this when there is a lowering that actually
545 // triggers this case. 534 // triggers this case.
546 (void)Imm; 535 (void)Imm;
547 llvm::report_fatal_error("Unexpected jmp to absolute address"); 536 llvm::report_fatal_error("Unexpected jmp to absolute address");
548 } else { 537 } else {
549 llvm::report_fatal_error("Unexpected operand type"); 538 llvm::report_fatal_error("Unexpected operand type");
550 } 539 }
551 } 540 }
552 541
553 template <class Machine> void InstX86Jmp<Machine>::dump(const Cfg *Func) const { 542 template <typename TraitsType>
543 void InstImpl<TraitsType>::InstX86Jmp::dump(const Cfg *Func) const {
554 if (!BuildDefs::dump()) 544 if (!BuildDefs::dump())
555 return; 545 return;
556 Ostream &Str = Func->getContext()->getStrDump(); 546 Ostream &Str = Func->getContext()->getStrDump();
557 Str << "jmp "; 547 Str << "jmp ";
558 getJmpTarget()->dump(Func); 548 getJmpTarget()->dump(Func);
559 } 549 }
560 550
561 template <class Machine> 551 template <typename TraitsType>
562 void InstX86Call<Machine>::emit(const Cfg *Func) const { 552 void InstImpl<TraitsType>::InstX86Call::emit(const Cfg *Func) const {
563 if (!BuildDefs::dump()) 553 if (!BuildDefs::dump())
564 return; 554 return;
565 Ostream &Str = Func->getContext()->getStrEmit(); 555 Ostream &Str = Func->getContext()->getStrEmit();
566 assert(this->getSrcSize() == 1); 556 assert(this->getSrcSize() == 1);
567 Str << "\t" 557 Str << "\t"
568 "call\t"; 558 "call\t";
569 Operand *CallTarget = getCallTarget(); 559 Operand *CallTarget = getCallTarget();
570 auto *Target = InstX86Base<Machine>::getTarget(Func); 560 auto *Target = InstX86Base::getTarget(Func);
571 if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(CallTarget)) { 561 if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(CallTarget)) {
572 // Emit without a leading '$'. 562 // Emit without a leading '$'.
573 Str << CI->getValue(); 563 Str << CI->getValue();
574 } else if (const auto DirectCallTarget = 564 } else if (const auto DirectCallTarget =
575 llvm::dyn_cast<ConstantRelocatable>(CallTarget)) { 565 llvm::dyn_cast<ConstantRelocatable>(CallTarget)) {
576 DirectCallTarget->emitWithoutPrefix(Target); 566 DirectCallTarget->emitWithoutPrefix(Target);
577 } else { 567 } else {
578 Str << "*"; 568 Str << "*";
579 CallTarget->emit(Func); 569 CallTarget->emit(Func);
580 } 570 }
581 } 571 }
582 572
583 template <class Machine> 573 template <typename TraitsType>
584 void InstX86Call<Machine>::emitIAS(const Cfg *Func) const { 574 void InstImpl<TraitsType>::InstX86Call::emitIAS(const Cfg *Func) const {
585 typename InstX86Base<Machine>::Traits::Assembler *Asm = 575 Assembler *Asm = Func->getAssembler<Assembler>();
586 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
587 Operand *CallTarget = getCallTarget(); 576 Operand *CallTarget = getCallTarget();
588 auto *Target = InstX86Base<Machine>::getTarget(Func); 577 auto *Target = InstX86Base::getTarget(Func);
589 if (const auto *Var = llvm::dyn_cast<Variable>(CallTarget)) { 578 if (const auto *Var = llvm::dyn_cast<Variable>(CallTarget)) {
590 if (Var->hasReg()) { 579 if (Var->hasReg()) {
591 Asm->call(InstX86Base<Machine>::Traits::getEncodedGPR(Var->getRegNum())); 580 Asm->call(Traits::getEncodedGPR(Var->getRegNum()));
592 } else { 581 } else {
593 Asm->call(Target->stackVarToAsmOperand(Var)); 582 Asm->call(Target->stackVarToAsmOperand(Var));
594 } 583 }
595 } else if (const auto *Mem = llvm::dyn_cast< 584 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(CallTarget)) {
596 typename InstX86Base<Machine>::Traits::X86OperandMem>( 585 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
597 CallTarget)) {
598 assert(Mem->getSegmentRegister() ==
599 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
600 Asm->call(Mem->toAsmAddress(Asm, Target)); 586 Asm->call(Mem->toAsmAddress(Asm, Target));
601 } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(CallTarget)) { 587 } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(CallTarget)) {
602 assert(CR->getOffset() == 0 && "We only support calling a function"); 588 assert(CR->getOffset() == 0 && "We only support calling a function");
603 Asm->call(CR); 589 Asm->call(CR);
604 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(CallTarget)) { 590 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(CallTarget)) {
605 Asm->call(Immediate(Imm->getValue())); 591 Asm->call(AssemblerImmediate(Imm->getValue()));
606 } else { 592 } else {
607 llvm_unreachable("Unexpected operand type"); 593 llvm_unreachable("Unexpected operand type");
608 } 594 }
609 } 595 }
610 596
611 template <class Machine> 597 template <typename TraitsType>
612 void InstX86Call<Machine>::dump(const Cfg *Func) const { 598 void InstImpl<TraitsType>::InstX86Call::dump(const Cfg *Func) const {
613 if (!BuildDefs::dump()) 599 if (!BuildDefs::dump())
614 return; 600 return;
615 Ostream &Str = Func->getContext()->getStrDump(); 601 Ostream &Str = Func->getContext()->getStrDump();
616 if (this->getDest()) { 602 if (this->getDest()) {
617 this->dumpDest(Func); 603 this->dumpDest(Func);
618 Str << " = "; 604 Str << " = ";
619 } 605 }
620 Str << "call "; 606 Str << "call ";
621 getCallTarget()->dump(Func); 607 getCallTarget()->dump(Func);
622 } 608 }
623 609
624 // The this->Opcode parameter needs to be char* and not IceString because of 610 // The this->Opcode parameter needs to be char* and not IceString because of
625 // template issues. 611 // template issues.
626 template <class Machine> 612 template <typename TraitsType>
627 void InstX86Base<Machine>::emitTwoAddress(const Cfg *Func, const char *Opcode, 613 void InstImpl<TraitsType>::InstX86Base::emitTwoAddress(
628 const char *Suffix) const { 614 const Cfg *Func, const char *Opcode, const char *Suffix) const {
629 if (!BuildDefs::dump()) 615 if (!BuildDefs::dump())
630 return; 616 return;
631 Ostream &Str = Func->getContext()->getStrEmit(); 617 Ostream &Str = Func->getContext()->getStrEmit();
632 assert(getSrcSize() == 2); 618 assert(getSrcSize() == 2);
633 Operand *Dest = getDest(); 619 Operand *Dest = getDest();
634 if (Dest == nullptr) 620 if (Dest == nullptr)
635 Dest = getSrc(0); 621 Dest = getSrc(0);
636 assert(Dest == getSrc(0)); 622 assert(Dest == getSrc(0));
637 Operand *Src1 = getSrc(1); 623 Operand *Src1 = getSrc(1);
638 Str << "\t" << Opcode << Suffix 624 Str << "\t" << Opcode << Suffix
639 << InstX86Base<Machine>::getWidthString(Dest->getType()) << "\t"; 625 << InstX86Base::getWidthString(Dest->getType()) << "\t";
640 Src1->emit(Func); 626 Src1->emit(Func);
641 Str << ", "; 627 Str << ", ";
642 Dest->emit(Func); 628 Dest->emit(Func);
643 } 629 }
644 630
645 template <class Machine> 631 template <typename TraitsType>
646 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op, 632 void InstImpl<TraitsType>::emitIASOpTyGPR(const Cfg *Func, Type Ty,
647 const typename InstX86Base< 633 const Operand *Op,
648 Machine>::Traits::Assembler::GPREmitterOneOp &Emitter) { 634 const GPREmitterOneOp &Emitter) {
649 auto *Target = InstX86Base<Machine>::getTarget(Func); 635 auto *Target = InstX86Base::getTarget(Func);
650 typename InstX86Base<Machine>::Traits::Assembler *Asm = 636 Assembler *Asm = Func->getAssembler<Assembler>();
651 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
652 if (const auto *Var = llvm::dyn_cast<Variable>(Op)) { 637 if (const auto *Var = llvm::dyn_cast<Variable>(Op)) {
653 if (Var->hasReg()) { 638 if (Var->hasReg()) {
654 // We cheat a little and use GPRRegister even for byte operations. 639 // We cheat a little and use GPRRegister even for byte operations.
655 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg = 640 GPRRegister VarReg = Traits::getEncodedGPR(Var->getRegNum());
656 InstX86Base<Machine>::Traits::getEncodedGPR(Var->getRegNum());
657 (Asm->*(Emitter.Reg))(Ty, VarReg); 641 (Asm->*(Emitter.Reg))(Ty, VarReg);
658 } else { 642 } else {
659 typename InstX86Base<Machine>::Traits::Address StackAddr( 643 Address StackAddr(Target->stackVarToAsmOperand(Var));
660 Target->stackVarToAsmOperand(Var));
661 (Asm->*(Emitter.Addr))(Ty, StackAddr); 644 (Asm->*(Emitter.Addr))(Ty, StackAddr);
662 } 645 }
663 } else if (const auto *Mem = llvm::dyn_cast< 646 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Op)) {
664 typename InstX86Base<Machine>::Traits::X86OperandMem>(Op)) {
665 Mem->emitSegmentOverride(Asm); 647 Mem->emitSegmentOverride(Asm);
666 (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm, Target)); 648 (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm, Target));
667 } else { 649 } else {
668 llvm_unreachable("Unexpected operand type"); 650 llvm_unreachable("Unexpected operand type");
669 } 651 }
670 } 652 }
671 653
672 template <class Machine, bool VarCanBeByte, bool SrcCanBeByte> 654 template <typename TraitsType>
673 void emitIASRegOpTyGPR( 655 template <bool VarCanBeByte, bool SrcCanBeByte>
674 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src, 656 void InstImpl<TraitsType>::emitIASRegOpTyGPR(const Cfg *Func, Type Ty,
675 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp 657 const Variable *Var,
676 &Emitter) { 658 const Operand *Src,
677 auto *Target = InstX86Base<Machine>::getTarget(Func); 659 const GPREmitterRegOp &Emitter) {
678 typename InstX86Base<Machine>::Traits::Assembler *Asm = 660 auto *Target = InstX86Base::getTarget(Func);
679 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); 661 Assembler *Asm = Func->getAssembler<Assembler>();
680 assert(Var->hasReg()); 662 assert(Var->hasReg());
681 // We cheat a little and use GPRRegister even for byte operations. 663 // We cheat a little and use GPRRegister even for byte operations.
682 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg = 664 GPRRegister VarReg = VarCanBeByte ? Traits::getEncodedGPR(Var->getRegNum())
683 VarCanBeByte 665 : Traits::getEncodedGPR(Var->getRegNum());
684 ? InstX86Base<Machine>::Traits::getEncodedGPR(Var->getRegNum())
685 : InstX86Base<Machine>::Traits::getEncodedGPR(Var->getRegNum());
686 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { 666 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
687 if (SrcVar->hasReg()) { 667 if (SrcVar->hasReg()) {
688 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg = 668 GPRRegister SrcReg = SrcCanBeByte
689 SrcCanBeByte 669 ? Traits::getEncodedGPR(SrcVar->getRegNum())
690 ? InstX86Base<Machine>::Traits::getEncodedGPR(SrcVar->getRegNum()) 670 : Traits::getEncodedGPR(SrcVar->getRegNum());
691 : InstX86Base<Machine>::Traits::getEncodedGPR(
692 SrcVar->getRegNum());
693 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); 671 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
694 } else { 672 } else {
695 typename InstX86Base<Machine>::Traits::Address SrcStackAddr = 673 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
696 Target->stackVarToAsmOperand(SrcVar);
697 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr); 674 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr);
698 } 675 }
699 } else if (const auto *Mem = llvm::dyn_cast< 676 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
700 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
701 Mem->emitSegmentOverride(Asm); 677 Mem->emitSegmentOverride(Asm);
702 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target)); 678 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target));
703 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { 679 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
704 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Imm->getValue())); 680 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
705 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { 681 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
706 AssemblerFixup *Fixup = 682 AssemblerFixup *Fixup = Asm->createFixup(Traits::RelFixup, Reloc);
707 Asm->createFixup(InstX86Base<Machine>::Traits::RelFixup, Reloc); 683 (Asm->*(Emitter.GPRImm))(Ty, VarReg,
708 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Reloc->getOffset(), Fixup)); 684 AssemblerImmediate(Reloc->getOffset(), Fixup));
709 } else if (const auto *Split = llvm::dyn_cast< 685 } else if (const auto *Split = llvm::dyn_cast<VariableSplit>(Src)) {
710 typename InstX86Base<Machine>::Traits::VariableSplit>(Src)) {
711 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func)); 686 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func));
712 } else { 687 } else {
713 llvm_unreachable("Unexpected operand type"); 688 llvm_unreachable("Unexpected operand type");
714 } 689 }
715 } 690 }
716 691
717 template <class Machine> 692 template <typename TraitsType>
718 void emitIASAddrOpTyGPR( 693 void InstImpl<TraitsType>::emitIASAddrOpTyGPR(const Cfg *Func, Type Ty,
719 const Cfg *Func, Type Ty, 694 const Address &Addr,
720 const typename InstX86Base<Machine>::Traits::Address &Addr, 695 const Operand *Src,
721 const Operand *Src, 696 const GPREmitterAddrOp &Emitter) {
722 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp 697 Assembler *Asm = Func->getAssembler<Assembler>();
723 &Emitter) { 698 // Src can only be Reg or AssemblerImmediate.
724 typename InstX86Base<Machine>::Traits::Assembler *Asm =
725 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
726 // Src can only be Reg or Immediate.
727 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { 699 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
728 assert(SrcVar->hasReg()); 700 assert(SrcVar->hasReg());
729 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg = 701 GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar->getRegNum());
730 InstX86Base<Machine>::Traits::getEncodedGPR(SrcVar->getRegNum());
731 (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg); 702 (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
732 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { 703 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
733 (Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Imm->getValue())); 704 (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
734 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { 705 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
735 AssemblerFixup *Fixup = 706 AssemblerFixup *Fixup = Asm->createFixup(Traits::RelFixup, Reloc);
736 Asm->createFixup(InstX86Base<Machine>::Traits::RelFixup, Reloc); 707 (Asm->*(Emitter.AddrImm))(Ty, Addr,
737 (Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Reloc->getOffset(), Fixup)); 708 AssemblerImmediate(Reloc->getOffset(), Fixup));
738 } else { 709 } else {
739 llvm_unreachable("Unexpected operand type"); 710 llvm_unreachable("Unexpected operand type");
740 } 711 }
741 } 712 }
742 713
743 template <class Machine> 714 template <typename TraitsType>
744 void emitIASAsAddrOpTyGPR( 715 void InstImpl<TraitsType>::emitIASAsAddrOpTyGPR(
745 const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1, 716 const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1,
746 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp 717 const GPREmitterAddrOp &Emitter) {
747 &Emitter) { 718 auto *Target = InstX86Base::getTarget(Func);
748 auto *Target = InstX86Base<Machine>::getTarget(Func);
749 if (const auto *Op0Var = llvm::dyn_cast<Variable>(Op0)) { 719 if (const auto *Op0Var = llvm::dyn_cast<Variable>(Op0)) {
750 assert(!Op0Var->hasReg()); 720 assert(!Op0Var->hasReg());
751 typename InstX86Base<Machine>::Traits::Address StackAddr( 721 Address StackAddr(Target->stackVarToAsmOperand(Op0Var));
752 Target->stackVarToAsmOperand(Op0Var)); 722 emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter);
753 emitIASAddrOpTyGPR<Machine>(Func, Ty, StackAddr, Op1, Emitter); 723 } else if (const auto *Op0Mem = llvm::dyn_cast<X86OperandMem>(Op0)) {
754 } else if (const auto *Op0Mem = llvm::dyn_cast< 724 Assembler *Asm = Func->getAssembler<Assembler>();
755 typename InstX86Base<Machine>::Traits::X86OperandMem>(Op0)) {
756 typename InstX86Base<Machine>::Traits::Assembler *Asm =
757 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
758 Op0Mem->emitSegmentOverride(Asm); 725 Op0Mem->emitSegmentOverride(Asm);
759 emitIASAddrOpTyGPR<Machine>(Func, Ty, Op0Mem->toAsmAddress(Asm, Target), 726 emitIASAddrOpTyGPR(Func, Ty, Op0Mem->toAsmAddress(Asm, Target), Op1,
760 Op1, Emitter); 727 Emitter);
761 } else if (const auto *Split = llvm::dyn_cast< 728 } else if (const auto *Split = llvm::dyn_cast<VariableSplit>(Op0)) {
762 typename InstX86Base<Machine>::Traits::VariableSplit>(Op0)) { 729 emitIASAddrOpTyGPR(Func, Ty, Split->toAsmAddress(Func), Op1, Emitter);
763 emitIASAddrOpTyGPR<Machine>(Func, Ty, Split->toAsmAddress(Func), Op1,
764 Emitter);
765 } else { 730 } else {
766 llvm_unreachable("Unexpected operand type"); 731 llvm_unreachable("Unexpected operand type");
767 } 732 }
768 } 733 }
769 734
770 template <class Machine> 735 template <typename TraitsType>
771 void InstX86Base<Machine>::emitIASGPRShift( 736 void InstImpl<TraitsType>::emitIASGPRShift(const Cfg *Func, Type Ty,
772 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src, 737 const Variable *Var,
773 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp 738 const Operand *Src,
774 &Emitter) { 739 const GPREmitterShiftOp &Emitter) {
775 typename InstX86Base<Machine>::Traits::Assembler *Asm = 740 Assembler *Asm = Func->getAssembler<Assembler>();
776 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
777 // Technically, the Dest Var can be mem as well, but we only use Reg. We can 741 // Technically, the Dest Var can be mem as well, but we only use Reg. We can
778 // extend this to check Dest if we decide to use that form. 742 // extend this to check Dest if we decide to use that form.
779 assert(Var->hasReg()); 743 assert(Var->hasReg());
780 // We cheat a little and use GPRRegister even for byte operations. 744 // We cheat a little and use GPRRegister even for byte operations.
781 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg = 745 GPRRegister VarReg = Traits::getEncodedGPR(Var->getRegNum());
782 InstX86Base<Machine>::Traits::getEncodedGPR(Var->getRegNum());
783 // Src must be reg == ECX or an Imm8. This is asserted by the assembler. 746 // Src must be reg == ECX or an Imm8. This is asserted by the assembler.
784 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { 747 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
785 assert(SrcVar->hasReg()); 748 assert(SrcVar->hasReg());
786 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg = 749 GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar->getRegNum());
787 InstX86Base<Machine>::Traits::getEncodedGPR(SrcVar->getRegNum());
788 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); 750 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
789 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { 751 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
790 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Imm->getValue())); 752 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
791 } else { 753 } else {
792 llvm_unreachable("Unexpected operand type"); 754 llvm_unreachable("Unexpected operand type");
793 } 755 }
794 } 756 }
795 757
796 template <class Machine> 758 template <typename TraitsType>
797 void emitIASGPRShiftDouble( 759 void InstImpl<TraitsType>::emitIASGPRShiftDouble(
798 const Cfg *Func, const Variable *Dest, const Operand *Src1Op, 760 const Cfg *Func, const Variable *Dest, const Operand *Src1Op,
799 const Operand *Src2Op, 761 const Operand *Src2Op, const GPREmitterShiftD &Emitter) {
800 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftD 762 Assembler *Asm = Func->getAssembler<Assembler>();
801 &Emitter) {
802 typename InstX86Base<Machine>::Traits::Assembler *Asm =
803 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
804 // Dest can be reg or mem, but we only use the reg variant. 763 // Dest can be reg or mem, but we only use the reg variant.
805 assert(Dest->hasReg()); 764 assert(Dest->hasReg());
806 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister DestReg = 765 GPRRegister DestReg = Traits::getEncodedGPR(Dest->getRegNum());
807 InstX86Base<Machine>::Traits::getEncodedGPR(Dest->getRegNum());
808 // SrcVar1 must be reg. 766 // SrcVar1 must be reg.
809 const auto *SrcVar1 = llvm::cast<Variable>(Src1Op); 767 const auto *SrcVar1 = llvm::cast<Variable>(Src1Op);
810 assert(SrcVar1->hasReg()); 768 assert(SrcVar1->hasReg());
811 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg = 769 GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar1->getRegNum());
812 InstX86Base<Machine>::Traits::getEncodedGPR(SrcVar1->getRegNum());
813 Type Ty = SrcVar1->getType(); 770 Type Ty = SrcVar1->getType();
814 // Src2 can be the implicit CL register or an immediate. 771 // Src2 can be the implicit CL register or an immediate.
815 if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) { 772 if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) {
816 (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg, 773 (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg,
817 Immediate(Imm->getValue())); 774 AssemblerImmediate(Imm->getValue()));
818 } else { 775 } else {
819 assert(llvm::cast<Variable>(Src2Op)->getRegNum() == 776 assert(llvm::cast<Variable>(Src2Op)->getRegNum() == RegisterSet::Reg_cl);
820 InstX86Base<Machine>::Traits::RegisterSet::Reg_cl);
821 (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg); 777 (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg);
822 } 778 }
823 } 779 }
824 780
825 template <class Machine> 781 template <typename TraitsType>
826 void emitIASXmmShift( 782 void InstImpl<TraitsType>::emitIASXmmShift(const Cfg *Func, Type Ty,
827 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src, 783 const Variable *Var,
828 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp 784 const Operand *Src,
829 &Emitter) { 785 const XmmEmitterShiftOp &Emitter) {
830 auto *Target = InstX86Base<Machine>::getTarget(Func); 786 auto *Target = InstX86Base::getTarget(Func);
831 typename InstX86Base<Machine>::Traits::Assembler *Asm = 787 Assembler *Asm = Func->getAssembler<Assembler>();
832 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
833 assert(Var->hasReg()); 788 assert(Var->hasReg());
834 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister VarReg = 789 XmmRegister VarReg = Traits::getEncodedXmm(Var->getRegNum());
835 InstX86Base<Machine>::Traits::getEncodedXmm(Var->getRegNum());
836 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { 790 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
837 if (SrcVar->hasReg()) { 791 if (SrcVar->hasReg()) {
838 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg = 792 XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
839 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum());
840 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg); 793 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
841 } else { 794 } else {
842 typename InstX86Base<Machine>::Traits::Address SrcStackAddr = 795 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
843 Target->stackVarToAsmOperand(SrcVar);
844 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr); 796 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
845 } 797 }
846 } else if (const auto *Mem = llvm::dyn_cast< 798 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
847 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) { 799 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
848 assert(Mem->getSegmentRegister() ==
849 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
850 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target)); 800 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target));
851 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { 801 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
852 (Asm->*(Emitter.XmmImm))(Ty, VarReg, Immediate(Imm->getValue())); 802 (Asm->*(Emitter.XmmImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
853 } else { 803 } else {
854 llvm_unreachable("Unexpected operand type"); 804 llvm_unreachable("Unexpected operand type");
855 } 805 }
856 } 806 }
857 807
858 template <class Machine> 808 template <typename TraitsType>
859 void emitIASRegOpTyXMM( 809 void InstImpl<TraitsType>::emitIASRegOpTyXMM(const Cfg *Func, Type Ty,
860 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src, 810 const Variable *Var,
861 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp 811 const Operand *Src,
862 &Emitter) { 812 const XmmEmitterRegOp &Emitter) {
863 auto *Target = InstX86Base<Machine>::getTarget(Func); 813 auto *Target = InstX86Base::getTarget(Func);
864 typename InstX86Base<Machine>::Traits::Assembler *Asm = 814 Assembler *Asm = Func->getAssembler<Assembler>();
865 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
866 assert(Var->hasReg()); 815 assert(Var->hasReg());
867 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister VarReg = 816 XmmRegister VarReg = Traits::getEncodedXmm(Var->getRegNum());
868 InstX86Base<Machine>::Traits::getEncodedXmm(Var->getRegNum());
869 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { 817 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
870 if (SrcVar->hasReg()) { 818 if (SrcVar->hasReg()) {
871 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg = 819 XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
872 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum());
873 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg); 820 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
874 } else { 821 } else {
875 typename InstX86Base<Machine>::Traits::Address SrcStackAddr = 822 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
876 Target->stackVarToAsmOperand(SrcVar);
877 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr); 823 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
878 } 824 }
879 } else if (const auto *Mem = llvm::dyn_cast< 825 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
880 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) { 826 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
881 assert(Mem->getSegmentRegister() ==
882 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
883 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target)); 827 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target));
884 } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) { 828 } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) {
885 (Asm->*(Emitter.XmmAddr))( 829 (Asm->*(Emitter.XmmAddr))(Ty, VarReg,
886 Ty, VarReg, 830 Traits::Address::ofConstPool(Asm, Imm));
887 InstX86Base<Machine>::Traits::Address::ofConstPool(Asm, Imm));
888 } else { 831 } else {
889 llvm_unreachable("Unexpected operand type"); 832 llvm_unreachable("Unexpected operand type");
890 } 833 }
891 } 834 }
892 835
893 template <class Machine, typename DReg_t, typename SReg_t, 836 template <typename TraitsType>
894 DReg_t (*destEnc)(int32_t), SReg_t (*srcEnc)(int32_t)> 837 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t),
895 void emitIASCastRegOp(const Cfg *Func, Type DestTy, const Variable *Dest, 838 SReg_t (*srcEnc)(int32_t)>
896 Type SrcTy, const Operand *Src, 839 void InstImpl<TraitsType>::emitIASCastRegOp(
897 const typename InstX86Base<Machine>::Traits::Assembler:: 840 const Cfg *Func, Type DestTy, const Variable *Dest, Type SrcTy,
898 template CastEmitterRegOp<DReg_t, SReg_t> &Emitter) { 841 const Operand *Src, const CastEmitterRegOp<DReg_t, SReg_t> &Emitter) {
899 auto *Target = InstX86Base<Machine>::getTarget(Func); 842 auto *Target = InstX86Base::getTarget(Func);
900 typename InstX86Base<Machine>::Traits::Assembler *Asm = 843 Assembler *Asm = Func->getAssembler<Assembler>();
901 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
902 assert(Dest->hasReg()); 844 assert(Dest->hasReg());
903 DReg_t DestReg = destEnc(Dest->getRegNum()); 845 DReg_t DestReg = destEnc(Dest->getRegNum());
904 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { 846 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
905 if (SrcVar->hasReg()) { 847 if (SrcVar->hasReg()) {
906 SReg_t SrcReg = srcEnc(SrcVar->getRegNum()); 848 SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
907 (Asm->*(Emitter.RegReg))(DestTy, DestReg, SrcTy, SrcReg); 849 (Asm->*(Emitter.RegReg))(DestTy, DestReg, SrcTy, SrcReg);
908 } else { 850 } else {
909 typename InstX86Base<Machine>::Traits::Address SrcStackAddr = 851 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
910 Target->stackVarToAsmOperand(SrcVar);
911 (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy, SrcStackAddr); 852 (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy, SrcStackAddr);
912 } 853 }
913 } else if (const auto *Mem = llvm::dyn_cast< 854 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
914 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
915 Mem->emitSegmentOverride(Asm); 855 Mem->emitSegmentOverride(Asm);
916 (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy, 856 (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy,
917 Mem->toAsmAddress(Asm, Target)); 857 Mem->toAsmAddress(Asm, Target));
918 } else { 858 } else {
919 llvm_unreachable("Unexpected operand type"); 859 llvm_unreachable("Unexpected operand type");
920 } 860 }
921 } 861 }
922 862
923 template <class Machine, typename DReg_t, typename SReg_t, 863 template <typename TraitsType>
924 DReg_t (*destEnc)(int32_t), SReg_t (*srcEnc)(int32_t)> 864 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t),
925 void emitIASThreeOpImmOps( 865 SReg_t (*srcEnc)(int32_t)>
866 void InstImpl<TraitsType>::emitIASThreeOpImmOps(
926 const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0, 867 const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0,
927 const Operand *Src1, 868 const Operand *Src1, const ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) {
928 const typename InstX86Base<Machine>::Traits::Assembler:: 869 auto *Target = InstX86Base::getTarget(Func);
929 template ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) { 870 Assembler *Asm = Func->getAssembler<Assembler>();
930 auto *Target = InstX86Base<Machine>::getTarget(Func);
931 typename InstX86Base<Machine>::Traits::Assembler *Asm =
932 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
933 // This only handles Dest being a register, and Src1 being an immediate. 871 // This only handles Dest being a register, and Src1 being an immediate.
934 assert(Dest->hasReg()); 872 assert(Dest->hasReg());
935 DReg_t DestReg = destEnc(Dest->getRegNum()); 873 DReg_t DestReg = destEnc(Dest->getRegNum());
936 Immediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue()); 874 AssemblerImmediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue());
937 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src0)) { 875 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src0)) {
938 if (SrcVar->hasReg()) { 876 if (SrcVar->hasReg()) {
939 SReg_t SrcReg = srcEnc(SrcVar->getRegNum()); 877 SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
940 (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm); 878 (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm);
941 } else { 879 } else {
942 typename InstX86Base<Machine>::Traits::Address SrcStackAddr = 880 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
943 Target->stackVarToAsmOperand(SrcVar);
944 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm); 881 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm);
945 } 882 }
946 } else if (const auto *Mem = llvm::dyn_cast< 883 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src0)) {
947 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src0)) {
948 Mem->emitSegmentOverride(Asm); 884 Mem->emitSegmentOverride(Asm);
949 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, 885 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg,
950 Mem->toAsmAddress(Asm, Target), Imm); 886 Mem->toAsmAddress(Asm, Target), Imm);
951 } else { 887 } else {
952 llvm_unreachable("Unexpected operand type"); 888 llvm_unreachable("Unexpected operand type");
953 } 889 }
954 } 890 }
955 891
956 template <class Machine> 892 template <typename TraitsType>
957 void emitIASMovlikeXMM( 893 void InstImpl<TraitsType>::emitIASMovlikeXMM(const Cfg *Func,
958 const Cfg *Func, const Variable *Dest, const Operand *Src, 894 const Variable *Dest,
959 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterMovOps 895 const Operand *Src,
960 Emitter) { 896 const XmmEmitterMovOps Emitter) {
961 auto *Target = InstX86Base<Machine>::getTarget(Func); 897 auto *Target = InstX86Base::getTarget(Func);
962 typename InstX86Base<Machine>::Traits::Assembler *Asm = 898 Assembler *Asm = Func->getAssembler<Assembler>();
963 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
964 if (Dest->hasReg()) { 899 if (Dest->hasReg()) {
965 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister DestReg = 900 XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
966 InstX86Base<Machine>::Traits::getEncodedXmm(Dest->getRegNum());
967 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { 901 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
968 if (SrcVar->hasReg()) { 902 if (SrcVar->hasReg()) {
969 (Asm->*(Emitter.XmmXmm))( 903 (Asm->*(Emitter.XmmXmm))(DestReg,
970 DestReg, 904 Traits::getEncodedXmm(SrcVar->getRegNum()));
971 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum()));
972 } else { 905 } else {
973 typename InstX86Base<Machine>::Traits::Address StackAddr( 906 Address StackAddr(Target->stackVarToAsmOperand(SrcVar));
974 Target->stackVarToAsmOperand(SrcVar));
975 (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr); 907 (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
976 } 908 }
977 } else if (const auto *SrcMem = llvm::dyn_cast< 909 } else if (const auto *SrcMem = llvm::dyn_cast<X86OperandMem>(Src)) {
978 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) { 910 assert(SrcMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
979 assert(SrcMem->getSegmentRegister() ==
980 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
981 (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm, Target)); 911 (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm, Target));
982 } else { 912 } else {
983 llvm_unreachable("Unexpected operand type"); 913 llvm_unreachable("Unexpected operand type");
984 } 914 }
985 } else { 915 } else {
986 typename InstX86Base<Machine>::Traits::Address StackAddr( 916 Address StackAddr(Target->stackVarToAsmOperand(Dest));
987 Target->stackVarToAsmOperand(Dest));
988 // Src must be a register in this case. 917 // Src must be a register in this case.
989 const auto *SrcVar = llvm::cast<Variable>(Src); 918 const auto *SrcVar = llvm::cast<Variable>(Src);
990 assert(SrcVar->hasReg()); 919 assert(SrcVar->hasReg());
991 (Asm->*(Emitter.AddrXmm))( 920 (Asm->*(Emitter.AddrXmm))(StackAddr,
992 StackAddr, 921 Traits::getEncodedXmm(SrcVar->getRegNum()));
993 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum()));
994 } 922 }
995 } 923 }
996 924
997 template <class Machine> 925 template <typename TraitsType>
998 void InstX86Sqrtss<Machine>::emit(const Cfg *Func) const { 926 void InstImpl<TraitsType>::InstX86Sqrtss::emit(const Cfg *Func) const {
999 if (!BuildDefs::dump()) 927 if (!BuildDefs::dump())
1000 return; 928 return;
1001 Ostream &Str = Func->getContext()->getStrEmit(); 929 Ostream &Str = Func->getContext()->getStrEmit();
1002 assert(this->getSrcSize() == 1); 930 assert(this->getSrcSize() == 1);
1003 Type Ty = this->getSrc(0)->getType(); 931 Type Ty = this->getSrc(0)->getType();
1004 assert(isScalarFloatingType(Ty)); 932 assert(isScalarFloatingType(Ty));
1005 Str << "\t" 933 Str << "\t"
1006 "sqrt" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString 934 "sqrt" << Traits::TypeAttributes[Ty].SdSsString << "\t";
1007 << "\t";
1008 this->getSrc(0)->emit(Func); 935 this->getSrc(0)->emit(Func);
1009 Str << ", "; 936 Str << ", ";
1010 this->getDest()->emit(Func); 937 this->getDest()->emit(Func);
1011 } 938 }
1012 939
1013 template <class Machine> void InstX86Div<Machine>::emit(const Cfg *Func) const { 940 template <typename TraitsType>
941 void InstImpl<TraitsType>::InstX86Div::emit(const Cfg *Func) const {
1014 if (!BuildDefs::dump()) 942 if (!BuildDefs::dump())
1015 return; 943 return;
1016 Ostream &Str = Func->getContext()->getStrEmit(); 944 Ostream &Str = Func->getContext()->getStrEmit();
1017 assert(this->getSrcSize() == 3); 945 assert(this->getSrcSize() == 3);
1018 Operand *Src1 = this->getSrc(1); 946 Operand *Src1 = this->getSrc(1);
1019 Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t"; 947 Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1020 Src1->emit(Func); 948 Src1->emit(Func);
1021 } 949 }
1022 950
1023 template <class Machine> 951 template <typename TraitsType>
1024 void InstX86Div<Machine>::emitIAS(const Cfg *Func) const { 952 void InstImpl<TraitsType>::InstX86Div::emitIAS(const Cfg *Func) const {
1025 assert(this->getSrcSize() == 3); 953 assert(this->getSrcSize() == 3);
1026 const Operand *Src = this->getSrc(1); 954 const Operand *Src = this->getSrc(1);
1027 Type Ty = Src->getType(); 955 Type Ty = Src->getType();
1028 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp 956 static GPREmitterOneOp Emitter = {&Assembler::div, &Assembler::div};
1029 Emitter = {&InstX86Base<Machine>::Traits::Assembler::div, 957 emitIASOpTyGPR(Func, Ty, Src, Emitter);
1030 &InstX86Base<Machine>::Traits::Assembler::div};
1031 emitIASOpTyGPR<Machine>(Func, Ty, Src, Emitter);
1032 } 958 }
1033 959
1034 template <class Machine> 960 template <typename TraitsType>
1035 void InstX86Idiv<Machine>::emit(const Cfg *Func) const { 961 void InstImpl<TraitsType>::InstX86Idiv::emit(const Cfg *Func) const {
1036 if (!BuildDefs::dump()) 962 if (!BuildDefs::dump())
1037 return; 963 return;
1038 Ostream &Str = Func->getContext()->getStrEmit(); 964 Ostream &Str = Func->getContext()->getStrEmit();
1039 assert(this->getSrcSize() == 3); 965 assert(this->getSrcSize() == 3);
1040 Operand *Src1 = this->getSrc(1); 966 Operand *Src1 = this->getSrc(1);
1041 Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t"; 967 Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1042 Src1->emit(Func); 968 Src1->emit(Func);
1043 } 969 }
1044 970
1045 template <class Machine> 971 template <typename TraitsType>
1046 void InstX86Idiv<Machine>::emitIAS(const Cfg *Func) const { 972 void InstImpl<TraitsType>::InstX86Idiv::emitIAS(const Cfg *Func) const {
1047 assert(this->getSrcSize() == 3); 973 assert(this->getSrcSize() == 3);
1048 const Operand *Src = this->getSrc(1); 974 const Operand *Src = this->getSrc(1);
1049 Type Ty = Src->getType(); 975 Type Ty = Src->getType();
1050 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp 976 static const GPREmitterOneOp Emitter = {&Assembler::idiv, &Assembler::idiv};
1051 Emitter = {&InstX86Base<Machine>::Traits::Assembler::idiv, 977 emitIASOpTyGPR(Func, Ty, Src, Emitter);
1052 &InstX86Base<Machine>::Traits::Assembler::idiv};
1053 emitIASOpTyGPR<Machine>(Func, Ty, Src, Emitter);
1054 } 978 }
1055 979
1056 // pblendvb and blendvps take xmm0 as a final implicit argument. 980 // pblendvb and blendvps take xmm0 as a final implicit argument.
1057 template <class Machine> 981 template <typename TraitsType>
1058 void emitVariableBlendInst(const char *Opcode, const Inst *Inst, 982 void InstImpl<TraitsType>::emitVariableBlendInst(const char *Opcode,
1059 const Cfg *Func) { 983 const Inst *Inst,
984 const Cfg *Func) {
1060 if (!BuildDefs::dump()) 985 if (!BuildDefs::dump())
1061 return; 986 return;
1062 Ostream &Str = Func->getContext()->getStrEmit(); 987 Ostream &Str = Func->getContext()->getStrEmit();
1063 assert(Inst->getSrcSize() == 3); 988 assert(Inst->getSrcSize() == 3);
1064 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == 989 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() ==
1065 InstX86Base<Machine>::Traits::RegisterSet::Reg_xmm0); 990 RegisterSet::Reg_xmm0);
1066 Str << "\t" << Opcode << "\t"; 991 Str << "\t" << Opcode << "\t";
1067 Inst->getSrc(1)->emit(Func); 992 Inst->getSrc(1)->emit(Func);
1068 Str << ", "; 993 Str << ", ";
1069 Inst->getDest()->emit(Func); 994 Inst->getDest()->emit(Func);
1070 } 995 }
1071 996
1072 template <class Machine> 997 template <typename TraitsType>
1073 void emitIASVariableBlendInst( 998 void InstImpl<TraitsType>::emitIASVariableBlendInst(
1074 const Inst *Inst, const Cfg *Func, 999 const Inst *Inst, const Cfg *Func, const XmmEmitterRegOp &Emitter) {
1075 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1076 &Emitter) {
1077 assert(Inst->getSrcSize() == 3); 1000 assert(Inst->getSrcSize() == 3);
1078 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == 1001 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() ==
1079 InstX86Base<Machine>::Traits::RegisterSet::Reg_xmm0); 1002 RegisterSet::Reg_xmm0);
1080 const Variable *Dest = Inst->getDest(); 1003 const Variable *Dest = Inst->getDest();
1081 const Operand *Src = Inst->getSrc(1); 1004 const Operand *Src = Inst->getSrc(1);
1082 emitIASRegOpTyXMM<Machine>(Func, Dest->getType(), Dest, Src, Emitter); 1005 emitIASRegOpTyXMM(Func, Dest->getType(), Dest, Src, Emitter);
1083 } 1006 }
1084 1007
1085 template <class Machine> 1008 template <typename TraitsType>
1086 void InstX86Blendvps<Machine>::emit(const Cfg *Func) const { 1009 void InstImpl<TraitsType>::InstX86Blendvps::emit(const Cfg *Func) const {
1087 if (!BuildDefs::dump()) 1010 if (!BuildDefs::dump())
1088 return; 1011 return;
1089 emitVariableBlendInst<Machine>(this->Opcode, this, Func); 1012 emitVariableBlendInst(this->Opcode, this, Func);
1090 } 1013 }
1091 1014
1092 template <class Machine> 1015 template <typename TraitsType>
1093 void InstX86Blendvps<Machine>::emitIAS(const Cfg *Func) const { 1016 void InstImpl<TraitsType>::InstX86Blendvps::emitIAS(const Cfg *Func) const {
1094 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp 1017 static const XmmEmitterRegOp Emitter = {&Assembler::blendvps,
1095 Emitter = {&InstX86Base<Machine>::Traits::Assembler::blendvps, 1018 &Assembler::blendvps};
1096 &InstX86Base<Machine>::Traits::Assembler::blendvps}; 1019 emitIASVariableBlendInst(this, Func, Emitter);
1097 emitIASVariableBlendInst<Machine>(this, Func, Emitter);
1098 } 1020 }
1099 1021
1100 template <class Machine> 1022 template <typename TraitsType>
1101 void InstX86Pblendvb<Machine>::emit(const Cfg *Func) const { 1023 void InstImpl<TraitsType>::InstX86Pblendvb::emit(const Cfg *Func) const {
1102 if (!BuildDefs::dump()) 1024 if (!BuildDefs::dump())
1103 return; 1025 return;
1104 emitVariableBlendInst<Machine>(this->Opcode, this, Func); 1026 emitVariableBlendInst(this->Opcode, this, Func);
1105 } 1027 }
1106 1028
1107 template <class Machine> 1029 template <typename TraitsType>
1108 void InstX86Pblendvb<Machine>::emitIAS(const Cfg *Func) const { 1030 void InstImpl<TraitsType>::InstX86Pblendvb::emitIAS(const Cfg *Func) const {
1109 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp 1031 static const XmmEmitterRegOp Emitter = {&Assembler::pblendvb,
1110 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pblendvb, 1032 &Assembler::pblendvb};
1111 &InstX86Base<Machine>::Traits::Assembler::pblendvb}; 1033 emitIASVariableBlendInst(this, Func, Emitter);
1112 emitIASVariableBlendInst<Machine>(this, Func, Emitter);
1113 } 1034 }
1114 1035
1115 template <class Machine> 1036 template <typename TraitsType>
1116 void InstX86Imul<Machine>::emit(const Cfg *Func) const { 1037 void InstImpl<TraitsType>::InstX86Imul::emit(const Cfg *Func) const {
1117 if (!BuildDefs::dump()) 1038 if (!BuildDefs::dump())
1118 return; 1039 return;
1119 Ostream &Str = Func->getContext()->getStrEmit(); 1040 Ostream &Str = Func->getContext()->getStrEmit();
1120 assert(this->getSrcSize() == 2); 1041 assert(this->getSrcSize() == 2);
1121 Variable *Dest = this->getDest(); 1042 Variable *Dest = this->getDest();
1122 if (isByteSizedArithType(Dest->getType())) { 1043 if (isByteSizedArithType(Dest->getType())) {
1123 // The 8-bit version of imul only allows the form "imul r/m8". 1044 // The 8-bit version of imul only allows the form "imul r/m8".
1124 const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0)); 1045 const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
1125 (void)Src0Var; 1046 (void)Src0Var;
1126 assert(Src0Var->getRegNum() == 1047 assert(Src0Var->getRegNum() == RegisterSet::Reg_al);
1127 InstX86Base<Machine>::Traits::RegisterSet::Reg_al);
1128 Str << "\t" 1048 Str << "\t"
1129 "imulb\t"; 1049 "imulb\t";
1130 this->getSrc(1)->emit(Func); 1050 this->getSrc(1)->emit(Func);
1131 } else if (llvm::isa<Constant>(this->getSrc(1))) { 1051 } else if (llvm::isa<Constant>(this->getSrc(1))) {
1132 Str << "\t" 1052 Str << "\t"
1133 "imul" << this->getWidthString(Dest->getType()) << "\t"; 1053 "imul" << this->getWidthString(Dest->getType()) << "\t";
1134 this->getSrc(1)->emit(Func); 1054 this->getSrc(1)->emit(Func);
1135 Str << ", "; 1055 Str << ", ";
1136 this->getSrc(0)->emit(Func); 1056 this->getSrc(0)->emit(Func);
1137 Str << ", "; 1057 Str << ", ";
1138 Dest->emit(Func); 1058 Dest->emit(Func);
1139 } else { 1059 } else {
1140 this->emitTwoAddress(Func, this->Opcode); 1060 this->emitTwoAddress(Func, this->Opcode);
1141 } 1061 }
1142 } 1062 }
1143 1063
1144 template <class Machine> 1064 template <typename TraitsType>
1145 void InstX86Imul<Machine>::emitIAS(const Cfg *Func) const { 1065 void InstImpl<TraitsType>::InstX86Imul::emitIAS(const Cfg *Func) const {
1146 assert(this->getSrcSize() == 2); 1066 assert(this->getSrcSize() == 2);
1147 const Variable *Var = this->getDest(); 1067 const Variable *Var = this->getDest();
1148 Type Ty = Var->getType(); 1068 Type Ty = Var->getType();
1149 const Operand *Src = this->getSrc(1); 1069 const Operand *Src = this->getSrc(1);
1150 if (isByteSizedArithType(Ty)) { 1070 if (isByteSizedArithType(Ty)) {
1151 // The 8-bit version of imul only allows the form "imul r/m8". 1071 // The 8-bit version of imul only allows the form "imul r/m8".
1152 const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0)); 1072 const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
1153 (void)Src0Var; 1073 (void)Src0Var;
1154 assert(Src0Var->getRegNum() == 1074 assert(Src0Var->getRegNum() == RegisterSet::Reg_al);
1155 InstX86Base<Machine>::Traits::RegisterSet::Reg_al); 1075 static const GPREmitterOneOp Emitter = {&Assembler::imul, &Assembler::imul};
1156 static const typename InstX86Base< 1076 emitIASOpTyGPR(Func, Ty, this->getSrc(1), Emitter);
1157 Machine>::Traits::Assembler::GPREmitterOneOp Emitter = {
1158 &InstX86Base<Machine>::Traits::Assembler::imul,
1159 &InstX86Base<Machine>::Traits::Assembler::imul};
1160 emitIASOpTyGPR<Machine>(Func, Ty, this->getSrc(1), Emitter);
1161 } else { 1077 } else {
1162 // The two-address version is used when multiplying by a non-constant 1078 // The two-address version is used when multiplying by a non-constant
1163 // or doing an 8-bit multiply. 1079 // or doing an 8-bit multiply.
1164 assert(Var == this->getSrc(0)); 1080 assert(Var == this->getSrc(0));
1165 static const typename InstX86Base< 1081 static const GPREmitterRegOp Emitter = {&Assembler::imul, &Assembler::imul,
1166 Machine>::Traits::Assembler::GPREmitterRegOp Emitter = { 1082 &Assembler::imul};
1167 &InstX86Base<Machine>::Traits::Assembler::imul, 1083 emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter);
1168 &InstX86Base<Machine>::Traits::Assembler::imul,
1169 &InstX86Base<Machine>::Traits::Assembler::imul};
1170 emitIASRegOpTyGPR<Machine>(Func, Ty, Var, Src, Emitter);
1171 } 1084 }
1172 } 1085 }
1173 1086
1174 template <class Machine> 1087 template <typename TraitsType>
1175 void InstX86ImulImm<Machine>::emit(const Cfg *Func) const { 1088 void InstImpl<TraitsType>::InstX86ImulImm::emit(const Cfg *Func) const {
1176 if (!BuildDefs::dump()) 1089 if (!BuildDefs::dump())
1177 return; 1090 return;
1178 Ostream &Str = Func->getContext()->getStrEmit(); 1091 Ostream &Str = Func->getContext()->getStrEmit();
1179 assert(this->getSrcSize() == 2); 1092 assert(this->getSrcSize() == 2);
1180 Variable *Dest = this->getDest(); 1093 Variable *Dest = this->getDest();
1181 assert(Dest->getType() == IceType_i16 || Dest->getType() == IceType_i32); 1094 assert(Dest->getType() == IceType_i16 || Dest->getType() == IceType_i32);
1182 assert(llvm::isa<Constant>(this->getSrc(1))); 1095 assert(llvm::isa<Constant>(this->getSrc(1)));
1183 Str << "\t" 1096 Str << "\t"
1184 "imul" << this->getWidthString(Dest->getType()) << "\t"; 1097 "imul" << this->getWidthString(Dest->getType()) << "\t";
1185 this->getSrc(1)->emit(Func); 1098 this->getSrc(1)->emit(Func);
1186 Str << ", "; 1099 Str << ", ";
1187 this->getSrc(0)->emit(Func); 1100 this->getSrc(0)->emit(Func);
1188 Str << ", "; 1101 Str << ", ";
1189 Dest->emit(Func); 1102 Dest->emit(Func);
1190 } 1103 }
1191 1104
1192 template <class Machine> 1105 template <typename TraitsType>
1193 void InstX86ImulImm<Machine>::emitIAS(const Cfg *Func) const { 1106 void InstImpl<TraitsType>::InstX86ImulImm::emitIAS(const Cfg *Func) const {
1194 assert(this->getSrcSize() == 2); 1107 assert(this->getSrcSize() == 2);
1195 const Variable *Dest = this->getDest(); 1108 const Variable *Dest = this->getDest();
1196 Type Ty = Dest->getType(); 1109 Type Ty = Dest->getType();
1197 assert(llvm::isa<Constant>(this->getSrc(1))); 1110 assert(llvm::isa<Constant>(this->getSrc(1)));
1198 static const typename InstX86Base<Machine>::Traits::Assembler:: 1111 static const ThreeOpImmEmitter<GPRRegister, GPRRegister> Emitter = {
1199 template ThreeOpImmEmitter< 1112 &Assembler::imul, &Assembler::imul};
1200 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister, 1113 emitIASThreeOpImmOps<GPRRegister, GPRRegister, Traits::getEncodedGPR,
1201 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister> 1114 Traits::getEncodedGPR>(Func, Ty, Dest, this->getSrc(0),
1202 Emitter = {&InstX86Base<Machine>::Traits::Assembler::imul, 1115 this->getSrc(1), Emitter);
1203 &InstX86Base<Machine>::Traits::Assembler::imul};
1204 emitIASThreeOpImmOps<
1205 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1206 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1207 InstX86Base<Machine>::Traits::getEncodedGPR,
1208 InstX86Base<Machine>::Traits::getEncodedGPR>(
1209 Func, Ty, Dest, this->getSrc(0), this->getSrc(1), Emitter);
1210 } 1116 }
1211 1117
1212 template <class Machine> 1118 template <typename TraitsType>
1213 void InstX86Insertps<Machine>::emitIAS(const Cfg *Func) const { 1119 void InstImpl<TraitsType>::InstX86Insertps::emitIAS(const Cfg *Func) const {
1214 assert(this->getSrcSize() == 3); 1120 assert(this->getSrcSize() == 3);
1215 assert(InstX86Base<Machine>::getTarget(Func)->getInstructionSet() >= 1121 assert(InstX86Base::getTarget(Func)->getInstructionSet() >= Traits::SSE4_1);
1216 InstX86Base<Machine>::Traits::SSE4_1);
1217 const Variable *Dest = this->getDest(); 1122 const Variable *Dest = this->getDest();
1218 assert(Dest == this->getSrc(0)); 1123 assert(Dest == this->getSrc(0));
1219 Type Ty = Dest->getType(); 1124 Type Ty = Dest->getType();
1220 static const typename InstX86Base<Machine>::Traits::Assembler:: 1125 static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
1221 template ThreeOpImmEmitter< 1126 &Assembler::insertps, &Assembler::insertps};
1222 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister, 1127 emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
1223 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister> 1128 Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
1224 Emitter = {&InstX86Base<Machine>::Traits::Assembler::insertps, 1129 this->getSrc(2), Emitter);
1225 &InstX86Base<Machine>::Traits::Assembler::insertps};
1226 emitIASThreeOpImmOps<
1227 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1228 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1229 InstX86Base<Machine>::Traits::getEncodedXmm,
1230 InstX86Base<Machine>::Traits::getEncodedXmm>(
1231 Func, Ty, Dest, this->getSrc(1), this->getSrc(2), Emitter);
1232 } 1130 }
1233 1131
1234 template <class Machine> 1132 template <typename TraitsType>
1235 void InstX86Cbwdq<Machine>::emit(const Cfg *Func) const { 1133 void InstImpl<TraitsType>::InstX86Cbwdq::emit(const Cfg *Func) const {
1236 if (!BuildDefs::dump()) 1134 if (!BuildDefs::dump())
1237 return; 1135 return;
1238 Ostream &Str = Func->getContext()->getStrEmit(); 1136 Ostream &Str = Func->getContext()->getStrEmit();
1239 assert(this->getSrcSize() == 1); 1137 assert(this->getSrcSize() == 1);
1240 Operand *Src0 = this->getSrc(0); 1138 Operand *Src0 = this->getSrc(0);
1241 int32_t DestReg = this->getDest()->getRegNum(); 1139 int32_t DestReg = this->getDest()->getRegNum();
1242 int32_t SrcReg = llvm::cast<Variable>(Src0)->getRegNum(); 1140 int32_t SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
1243 (void)DestReg; 1141 (void)DestReg;
1244 (void)SrcReg; 1142 (void)SrcReg;
1245 switch (Src0->getType()) { 1143 switch (Src0->getType()) {
1246 default: 1144 default:
1247 llvm_unreachable("unexpected source type!"); 1145 llvm_unreachable("unexpected source type!");
1248 break; 1146 break;
1249 case IceType_i8: 1147 case IceType_i8:
1250 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_al); 1148 assert(SrcReg == RegisterSet::Reg_al);
1251 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ax || 1149 assert(DestReg == RegisterSet::Reg_ax || DestReg == RegisterSet::Reg_ah);
1252 DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ah);
1253 Str << "\t" 1150 Str << "\t"
1254 "cbtw"; 1151 "cbtw";
1255 break; 1152 break;
1256 case IceType_i16: 1153 case IceType_i16:
1257 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ax); 1154 assert(SrcReg == RegisterSet::Reg_ax);
1258 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_dx); 1155 assert(DestReg == RegisterSet::Reg_dx);
1259 Str << "\t" 1156 Str << "\t"
1260 "cwtd"; 1157 "cwtd";
1261 break; 1158 break;
1262 case IceType_i32: 1159 case IceType_i32:
1263 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); 1160 assert(SrcReg == RegisterSet::Reg_eax);
1264 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_edx); 1161 assert(DestReg == RegisterSet::Reg_edx);
1265 Str << "\t" 1162 Str << "\t"
1266 "cltd"; 1163 "cltd";
1267 break; 1164 break;
1268 case IceType_i64: 1165 case IceType_i64:
1269 assert(InstX86Base<Machine>::Traits::Is64Bit); 1166 assert(Traits::Is64Bit);
1270 assert(SrcReg == InstX86Base<Machine>::Traits::getRaxOrDie()); 1167 assert(SrcReg == Traits::getRaxOrDie());
1271 assert(DestReg == InstX86Base<Machine>::Traits::getRdxOrDie()); 1168 assert(DestReg == Traits::getRdxOrDie());
1272 Str << "\t" 1169 Str << "\t"
1273 "cqo"; 1170 "cqo";
1274 break; 1171 break;
1275 } 1172 }
1276 } 1173 }
1277 1174
1278 template <class Machine> 1175 template <typename TraitsType>
1279 void InstX86Cbwdq<Machine>::emitIAS(const Cfg *Func) const { 1176 void InstImpl<TraitsType>::InstX86Cbwdq::emitIAS(const Cfg *Func) const {
1280 typename InstX86Base<Machine>::Traits::Assembler *Asm = 1177 Assembler *Asm = Func->getAssembler<Assembler>();
1281 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1282 assert(this->getSrcSize() == 1); 1178 assert(this->getSrcSize() == 1);
1283 Operand *Src0 = this->getSrc(0); 1179 Operand *Src0 = this->getSrc(0);
1284 int32_t DestReg = this->getDest()->getRegNum(); 1180 int32_t DestReg = this->getDest()->getRegNum();
1285 int32_t SrcReg = llvm::cast<Variable>(Src0)->getRegNum(); 1181 int32_t SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
1286 (void)DestReg; 1182 (void)DestReg;
1287 (void)SrcReg; 1183 (void)SrcReg;
1288 switch (Src0->getType()) { 1184 switch (Src0->getType()) {
1289 default: 1185 default:
1290 llvm_unreachable("unexpected source type!"); 1186 llvm_unreachable("unexpected source type!");
1291 break; 1187 break;
1292 case IceType_i8: 1188 case IceType_i8:
1293 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_al); 1189 assert(SrcReg == RegisterSet::Reg_al);
1294 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ax || 1190 assert(DestReg == RegisterSet::Reg_ax || DestReg == RegisterSet::Reg_ah);
1295 DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ah);
1296 Asm->cbw(); 1191 Asm->cbw();
1297 break; 1192 break;
1298 case IceType_i16: 1193 case IceType_i16:
1299 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ax); 1194 assert(SrcReg == RegisterSet::Reg_ax);
1300 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_dx); 1195 assert(DestReg == RegisterSet::Reg_dx);
1301 Asm->cwd(); 1196 Asm->cwd();
1302 break; 1197 break;
1303 case IceType_i32: 1198 case IceType_i32:
1304 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); 1199 assert(SrcReg == RegisterSet::Reg_eax);
1305 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_edx); 1200 assert(DestReg == RegisterSet::Reg_edx);
1306 Asm->cdq(); 1201 Asm->cdq();
1307 break; 1202 break;
1308 case IceType_i64: 1203 case IceType_i64:
1309 assert(InstX86Base<Machine>::Traits::Is64Bit); 1204 assert(Traits::Is64Bit);
1310 assert(SrcReg == InstX86Base<Machine>::Traits::getRaxOrDie()); 1205 assert(SrcReg == Traits::getRaxOrDie());
1311 assert(DestReg == InstX86Base<Machine>::Traits::getRdxOrDie()); 1206 assert(DestReg == Traits::getRdxOrDie());
1312 Asm->cqo(); 1207 Asm->cqo();
1313 break; 1208 break;
1314 } 1209 }
1315 } 1210 }
1316 1211
1317 template <class Machine> void InstX86Mul<Machine>::emit(const Cfg *Func) const { 1212 template <typename TraitsType>
1213 void InstImpl<TraitsType>::InstX86Mul::emit(const Cfg *Func) const {
1318 if (!BuildDefs::dump()) 1214 if (!BuildDefs::dump())
1319 return; 1215 return;
1320 Ostream &Str = Func->getContext()->getStrEmit(); 1216 Ostream &Str = Func->getContext()->getStrEmit();
1321 assert(this->getSrcSize() == 2); 1217 assert(this->getSrcSize() == 2);
1322 assert(llvm::isa<Variable>(this->getSrc(0))); 1218 assert(llvm::isa<Variable>(this->getSrc(0)));
1323 assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() == 1219 assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1324 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); 1220 RegisterSet::Reg_eax);
1325 assert( 1221 assert(this->getDest()->getRegNum() == RegisterSet::Reg_eax); // TODO:
1326 this->getDest()->getRegNum() == 1222 // allow
1327 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); // TODO: allow edx? 1223 // edx?
1328 Str << "\t" 1224 Str << "\t"
1329 "mul" << this->getWidthString(this->getDest()->getType()) << "\t"; 1225 "mul" << this->getWidthString(this->getDest()->getType()) << "\t";
1330 this->getSrc(1)->emit(Func); 1226 this->getSrc(1)->emit(Func);
1331 } 1227 }
1332 1228
1333 template <class Machine> 1229 template <typename TraitsType>
1334 void InstX86Mul<Machine>::emitIAS(const Cfg *Func) const { 1230 void InstImpl<TraitsType>::InstX86Mul::emitIAS(const Cfg *Func) const {
1335 assert(this->getSrcSize() == 2); 1231 assert(this->getSrcSize() == 2);
1336 assert(llvm::isa<Variable>(this->getSrc(0))); 1232 assert(llvm::isa<Variable>(this->getSrc(0)));
1337 assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() == 1233 assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1338 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); 1234 RegisterSet::Reg_eax);
1339 assert( 1235 assert(this->getDest()->getRegNum() == RegisterSet::Reg_eax); // TODO:
1340 this->getDest()->getRegNum() == 1236 // allow
1341 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); // TODO: allow edx? 1237 // edx?
1342 const Operand *Src = this->getSrc(1); 1238 const Operand *Src = this->getSrc(1);
1343 Type Ty = Src->getType(); 1239 Type Ty = Src->getType();
1344 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp 1240 static const GPREmitterOneOp Emitter = {&Assembler::mul, &Assembler::mul};
1345 Emitter = {&InstX86Base<Machine>::Traits::Assembler::mul, 1241 emitIASOpTyGPR(Func, Ty, Src, Emitter);
1346 &InstX86Base<Machine>::Traits::Assembler::mul};
1347 emitIASOpTyGPR<Machine>(Func, Ty, Src, Emitter);
1348 } 1242 }
1349 1243
1350 template <class Machine> void InstX86Mul<Machine>::dump(const Cfg *Func) const { 1244 template <typename TraitsType>
1245 void InstImpl<TraitsType>::InstX86Mul::dump(const Cfg *Func) const {
1351 if (!BuildDefs::dump()) 1246 if (!BuildDefs::dump())
1352 return; 1247 return;
1353 Ostream &Str = Func->getContext()->getStrDump(); 1248 Ostream &Str = Func->getContext()->getStrDump();
1354 this->dumpDest(Func); 1249 this->dumpDest(Func);
1355 Str << " = mul." << this->getDest()->getType() << " "; 1250 Str << " = mul." << this->getDest()->getType() << " ";
1356 this->dumpSources(Func); 1251 this->dumpSources(Func);
1357 } 1252 }
1358 1253
1359 template <class Machine> 1254 template <typename TraitsType>
1360 void InstX86Shld<Machine>::emit(const Cfg *Func) const { 1255 void InstImpl<TraitsType>::InstX86Shld::emit(const Cfg *Func) const {
1361 if (!BuildDefs::dump()) 1256 if (!BuildDefs::dump())
1362 return; 1257 return;
1363 Ostream &Str = Func->getContext()->getStrEmit(); 1258 Ostream &Str = Func->getContext()->getStrEmit();
1364 Variable *Dest = this->getDest(); 1259 Variable *Dest = this->getDest();
1365 assert(this->getSrcSize() == 3); 1260 assert(this->getSrcSize() == 3);
1366 assert(Dest == this->getSrc(0)); 1261 assert(Dest == this->getSrc(0));
1367 Str << "\t" 1262 Str << "\t"
1368 "shld" << this->getWidthString(Dest->getType()) << "\t"; 1263 "shld" << this->getWidthString(Dest->getType()) << "\t";
1369 this->getSrc(2)->emit(Func); 1264 this->getSrc(2)->emit(Func);
1370 Str << ", "; 1265 Str << ", ";
1371 this->getSrc(1)->emit(Func); 1266 this->getSrc(1)->emit(Func);
1372 Str << ", "; 1267 Str << ", ";
1373 Dest->emit(Func); 1268 Dest->emit(Func);
1374 } 1269 }
1375 1270
1376 template <class Machine> 1271 template <typename TraitsType>
1377 void InstX86Shld<Machine>::emitIAS(const Cfg *Func) const { 1272 void InstImpl<TraitsType>::InstX86Shld::emitIAS(const Cfg *Func) const {
1378 assert(this->getSrcSize() == 3); 1273 assert(this->getSrcSize() == 3);
1379 assert(this->getDest() == this->getSrc(0)); 1274 assert(this->getDest() == this->getSrc(0));
1380 const Variable *Dest = this->getDest(); 1275 const Variable *Dest = this->getDest();
1381 const Operand *Src1 = this->getSrc(1); 1276 const Operand *Src1 = this->getSrc(1);
1382 const Operand *Src2 = this->getSrc(2); 1277 const Operand *Src2 = this->getSrc(2);
1383 static const typename InstX86Base< 1278 static const GPREmitterShiftD Emitter = {&Assembler::shld, &Assembler::shld};
1384 Machine>::Traits::Assembler::GPREmitterShiftD Emitter = { 1279 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
1385 &InstX86Base<Machine>::Traits::Assembler::shld,
1386 &InstX86Base<Machine>::Traits::Assembler::shld};
1387 emitIASGPRShiftDouble<Machine>(Func, Dest, Src1, Src2, Emitter);
1388 } 1280 }
1389 1281
1390 template <class Machine> 1282 template <typename TraitsType>
1391 void InstX86Shld<Machine>::dump(const Cfg *Func) const { 1283 void InstImpl<TraitsType>::InstX86Shld::dump(const Cfg *Func) const {
1392 if (!BuildDefs::dump()) 1284 if (!BuildDefs::dump())
1393 return; 1285 return;
1394 Ostream &Str = Func->getContext()->getStrDump(); 1286 Ostream &Str = Func->getContext()->getStrDump();
1395 this->dumpDest(Func); 1287 this->dumpDest(Func);
1396 Str << " = shld." << this->getDest()->getType() << " "; 1288 Str << " = shld." << this->getDest()->getType() << " ";
1397 this->dumpSources(Func); 1289 this->dumpSources(Func);
1398 } 1290 }
1399 1291
1400 template <class Machine> 1292 template <typename TraitsType>
1401 void InstX86Shrd<Machine>::emit(const Cfg *Func) const { 1293 void InstImpl<TraitsType>::InstX86Shrd::emit(const Cfg *Func) const {
1402 if (!BuildDefs::dump()) 1294 if (!BuildDefs::dump())
1403 return; 1295 return;
1404 Ostream &Str = Func->getContext()->getStrEmit(); 1296 Ostream &Str = Func->getContext()->getStrEmit();
1405 Variable *Dest = this->getDest(); 1297 Variable *Dest = this->getDest();
1406 assert(this->getSrcSize() == 3); 1298 assert(this->getSrcSize() == 3);
1407 assert(Dest == this->getSrc(0)); 1299 assert(Dest == this->getSrc(0));
1408 Str << "\t" 1300 Str << "\t"
1409 "shrd" << this->getWidthString(Dest->getType()) << "\t"; 1301 "shrd" << this->getWidthString(Dest->getType()) << "\t";
1410 this->getSrc(2)->emit(Func); 1302 this->getSrc(2)->emit(Func);
1411 Str << ", "; 1303 Str << ", ";
1412 this->getSrc(1)->emit(Func); 1304 this->getSrc(1)->emit(Func);
1413 Str << ", "; 1305 Str << ", ";
1414 Dest->emit(Func); 1306 Dest->emit(Func);
1415 } 1307 }
1416 1308
1417 template <class Machine> 1309 template <typename TraitsType>
1418 void InstX86Shrd<Machine>::emitIAS(const Cfg *Func) const { 1310 void InstImpl<TraitsType>::InstX86Shrd::emitIAS(const Cfg *Func) const {
1419 assert(this->getSrcSize() == 3); 1311 assert(this->getSrcSize() == 3);
1420 assert(this->getDest() == this->getSrc(0)); 1312 assert(this->getDest() == this->getSrc(0));
1421 const Variable *Dest = this->getDest(); 1313 const Variable *Dest = this->getDest();
1422 const Operand *Src1 = this->getSrc(1); 1314 const Operand *Src1 = this->getSrc(1);
1423 const Operand *Src2 = this->getSrc(2); 1315 const Operand *Src2 = this->getSrc(2);
1424 static const typename InstX86Base< 1316 static const GPREmitterShiftD Emitter = {&Assembler::shrd, &Assembler::shrd};
1425 Machine>::Traits::Assembler::GPREmitterShiftD Emitter = { 1317 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
1426 &InstX86Base<Machine>::Traits::Assembler::shrd,
1427 &InstX86Base<Machine>::Traits::Assembler::shrd};
1428 emitIASGPRShiftDouble<Machine>(Func, Dest, Src1, Src2, Emitter);
1429 } 1318 }
1430 1319
1431 template <class Machine> 1320 template <typename TraitsType>
1432 void InstX86Shrd<Machine>::dump(const Cfg *Func) const { 1321 void InstImpl<TraitsType>::InstX86Shrd::dump(const Cfg *Func) const {
1433 if (!BuildDefs::dump()) 1322 if (!BuildDefs::dump())
1434 return; 1323 return;
1435 Ostream &Str = Func->getContext()->getStrDump(); 1324 Ostream &Str = Func->getContext()->getStrDump();
1436 this->dumpDest(Func); 1325 this->dumpDest(Func);
1437 Str << " = shrd." << this->getDest()->getType() << " "; 1326 Str << " = shrd." << this->getDest()->getType() << " ";
1438 this->dumpSources(Func); 1327 this->dumpSources(Func);
1439 } 1328 }
1440 1329
1441 template <class Machine> 1330 template <typename TraitsType>
1442 void InstX86Cmov<Machine>::emit(const Cfg *Func) const { 1331 void InstImpl<TraitsType>::InstX86Cmov::emit(const Cfg *Func) const {
1443 if (!BuildDefs::dump()) 1332 if (!BuildDefs::dump())
1444 return; 1333 return;
1445 Ostream &Str = Func->getContext()->getStrEmit(); 1334 Ostream &Str = Func->getContext()->getStrEmit();
1446 Variable *Dest = this->getDest(); 1335 Variable *Dest = this->getDest();
1447 Str << "\t"; 1336 Str << "\t";
1448 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None); 1337 assert(Condition != Cond::Br_None);
1449 assert(this->getDest()->hasReg()); 1338 assert(this->getDest()->hasReg());
1450 Str << "cmov" 1339 Str << "cmov" << Traits::InstBrAttributes[Condition].DisplayString
1451 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
1452 << this->getWidthString(Dest->getType()) << "\t"; 1340 << this->getWidthString(Dest->getType()) << "\t";
1453 this->getSrc(1)->emit(Func); 1341 this->getSrc(1)->emit(Func);
1454 Str << ", "; 1342 Str << ", ";
1455 Dest->emit(Func); 1343 Dest->emit(Func);
1456 } 1344 }
1457 1345
1458 template <class Machine> 1346 template <typename TraitsType>
1459 void InstX86Cmov<Machine>::emitIAS(const Cfg *Func) const { 1347 void InstImpl<TraitsType>::InstX86Cmov::emitIAS(const Cfg *Func) const {
1460 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None); 1348 assert(Condition != Cond::Br_None);
1461 assert(this->getDest()->hasReg()); 1349 assert(this->getDest()->hasReg());
1462 assert(this->getSrcSize() == 2); 1350 assert(this->getSrcSize() == 2);
1463 Operand *Src = this->getSrc(1); 1351 Operand *Src = this->getSrc(1);
1464 Type SrcTy = Src->getType(); 1352 Type SrcTy = Src->getType();
1465 assert(SrcTy == IceType_i16 || SrcTy == IceType_i32 || 1353 assert(SrcTy == IceType_i16 || SrcTy == IceType_i32 || (Traits::Is64Bit));
1466 (InstX86Base<Machine>::Traits::Is64Bit)); 1354 Assembler *Asm = Func->getAssembler<Assembler>();
1467 typename InstX86Base<Machine>::Traits::Assembler *Asm = 1355 auto *Target = InstX86Base::getTarget(Func);
1468 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1469 auto *Target = InstX86Base<Machine>::getTarget(Func);
1470 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { 1356 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
1471 if (SrcVar->hasReg()) { 1357 if (SrcVar->hasReg()) {
1472 Asm->cmov( 1358 Asm->cmov(SrcTy, Condition,
1473 SrcTy, Condition, InstX86Base<Machine>::Traits::getEncodedGPR( 1359 Traits::getEncodedGPR(this->getDest()->getRegNum()),
1474 this->getDest()->getRegNum()), 1360 Traits::getEncodedGPR(SrcVar->getRegNum()));
1475 InstX86Base<Machine>::Traits::getEncodedGPR(SrcVar->getRegNum()));
1476 } else { 1361 } else {
1477 Asm->cmov(SrcTy, Condition, InstX86Base<Machine>::Traits::getEncodedGPR( 1362 Asm->cmov(SrcTy, Condition,
1478 this->getDest()->getRegNum()), 1363 Traits::getEncodedGPR(this->getDest()->getRegNum()),
1479 Target->stackVarToAsmOperand(SrcVar)); 1364 Target->stackVarToAsmOperand(SrcVar));
1480 } 1365 }
1481 } else if (const auto *Mem = llvm::dyn_cast< 1366 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
1482 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) { 1367 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1483 assert(Mem->getSegmentRegister() == 1368 Asm->cmov(SrcTy, Condition,
1484 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment); 1369 Traits::getEncodedGPR(this->getDest()->getRegNum()),
1485 Asm->cmov(SrcTy, Condition, InstX86Base<Machine>::Traits::getEncodedGPR(
1486 this->getDest()->getRegNum()),
1487 Mem->toAsmAddress(Asm, Target)); 1370 Mem->toAsmAddress(Asm, Target));
1488 } else { 1371 } else {
1489 llvm_unreachable("Unexpected operand type"); 1372 llvm_unreachable("Unexpected operand type");
1490 } 1373 }
1491 } 1374 }
1492 1375
1493 template <class Machine> 1376 template <typename TraitsType>
1494 void InstX86Cmov<Machine>::dump(const Cfg *Func) const { 1377 void InstImpl<TraitsType>::InstX86Cmov::dump(const Cfg *Func) const {
1495 if (!BuildDefs::dump()) 1378 if (!BuildDefs::dump())
1496 return; 1379 return;
1497 Ostream &Str = Func->getContext()->getStrDump(); 1380 Ostream &Str = Func->getContext()->getStrDump();
1498 Str << "cmov" 1381 Str << "cmov" << Traits::InstBrAttributes[Condition].DisplayString << ".";
1499 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
1500 << ".";
1501 Str << this->getDest()->getType() << " "; 1382 Str << this->getDest()->getType() << " ";
1502 this->dumpDest(Func); 1383 this->dumpDest(Func);
1503 Str << ", "; 1384 Str << ", ";
1504 this->dumpSources(Func); 1385 this->dumpSources(Func);
1505 } 1386 }
1506 1387
1507 template <class Machine> 1388 template <typename TraitsType>
1508 void InstX86Cmpps<Machine>::emit(const Cfg *Func) const { 1389 void InstImpl<TraitsType>::InstX86Cmpps::emit(const Cfg *Func) const {
1509 if (!BuildDefs::dump()) 1390 if (!BuildDefs::dump())
1510 return; 1391 return;
1511 Ostream &Str = Func->getContext()->getStrEmit(); 1392 Ostream &Str = Func->getContext()->getStrEmit();
1512 assert(this->getSrcSize() == 2); 1393 assert(this->getSrcSize() == 2);
1513 assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid); 1394 assert(Condition < Cond::Cmpps_Invalid);
1514 Type DestTy = this->Dest->getType(); 1395 Type DestTy = this->Dest->getType();
1515 Str << "\t" 1396 Str << "\t"
1516 "cmp" 1397 "cmp" << Traits::InstCmppsAttributes[Condition].EmitString
1517 << InstX86Base<Machine>::Traits::InstCmppsAttributes[Condition].EmitString 1398 << Traits::TypeAttributes[DestTy].PdPsString << "\t";
1518 << InstX86Base<Machine>::Traits::TypeAttributes[DestTy].PdPsString
1519 << "\t";
1520 this->getSrc(1)->emit(Func); 1399 this->getSrc(1)->emit(Func);
1521 Str << ", "; 1400 Str << ", ";
1522 this->getDest()->emit(Func); 1401 this->getDest()->emit(Func);
1523 } 1402 }
1524 1403
1525 template <class Machine> 1404 template <typename TraitsType>
1526 void InstX86Cmpps<Machine>::emitIAS(const Cfg *Func) const { 1405 void InstImpl<TraitsType>::InstX86Cmpps::emitIAS(const Cfg *Func) const {
1527 typename InstX86Base<Machine>::Traits::Assembler *Asm = 1406 Assembler *Asm = Func->getAssembler<Assembler>();
1528 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1529 assert(this->getSrcSize() == 2); 1407 assert(this->getSrcSize() == 2);
1530 assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid); 1408 assert(Condition < Cond::Cmpps_Invalid);
1531 // Assuming there isn't any load folding for cmpps, and vector constants are 1409 // Assuming there isn't any load folding for cmpps, and vector constants are
1532 // not allowed in PNaCl. 1410 // not allowed in PNaCl.
1533 assert(llvm::isa<Variable>(this->getSrc(1))); 1411 assert(llvm::isa<Variable>(this->getSrc(1)));
1534 auto *Target = InstX86Base<Machine>::getTarget(Func); 1412 auto *Target = InstX86Base::getTarget(Func);
1535 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1)); 1413 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
1536 if (SrcVar->hasReg()) { 1414 if (SrcVar->hasReg()) {
1537 Asm->cmpps(this->getDest()->getType(), 1415 Asm->cmpps(this->getDest()->getType(),
1538 InstX86Base<Machine>::Traits::getEncodedXmm( 1416 Traits::getEncodedXmm(this->getDest()->getRegNum()),
1539 this->getDest()->getRegNum()), 1417 Traits::getEncodedXmm(SrcVar->getRegNum()), Condition);
1540 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum()),
1541 Condition);
1542 } else { 1418 } else {
1543 typename InstX86Base<Machine>::Traits::Address SrcStackAddr = 1419 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
1544 Target->stackVarToAsmOperand(SrcVar);
1545 Asm->cmpps(this->getDest()->getType(), 1420 Asm->cmpps(this->getDest()->getType(),
1546 InstX86Base<Machine>::Traits::getEncodedXmm( 1421 Traits::getEncodedXmm(this->getDest()->getRegNum()),
1547 this->getDest()->getRegNum()),
1548 SrcStackAddr, Condition); 1422 SrcStackAddr, Condition);
1549 } 1423 }
1550 } 1424 }
1551 1425
1552 template <class Machine> 1426 template <typename TraitsType>
1553 void InstX86Cmpps<Machine>::dump(const Cfg *Func) const { 1427 void InstImpl<TraitsType>::InstX86Cmpps::dump(const Cfg *Func) const {
1554 if (!BuildDefs::dump()) 1428 if (!BuildDefs::dump())
1555 return; 1429 return;
1556 Ostream &Str = Func->getContext()->getStrDump(); 1430 Ostream &Str = Func->getContext()->getStrDump();
1557 assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid); 1431 assert(Condition < Cond::Cmpps_Invalid);
1558 this->dumpDest(Func); 1432 this->dumpDest(Func);
1559 Str << " = cmp" 1433 Str << " = cmp" << Traits::InstCmppsAttributes[Condition].EmitString << "ps"
1560 << InstX86Base<Machine>::Traits::InstCmppsAttributes[Condition].EmitString 1434 "\t";
1561 << "ps"
1562 "\t";
1563 this->dumpSources(Func); 1435 this->dumpSources(Func);
1564 } 1436 }
1565 1437
1566 template <class Machine> 1438 template <typename TraitsType>
1567 void InstX86Cmpxchg<Machine>::emit(const Cfg *Func) const { 1439 void InstImpl<TraitsType>::InstX86Cmpxchg::emit(const Cfg *Func) const {
1568 if (!BuildDefs::dump()) 1440 if (!BuildDefs::dump())
1569 return; 1441 return;
1570 Ostream &Str = Func->getContext()->getStrEmit(); 1442 Ostream &Str = Func->getContext()->getStrEmit();
1571 assert(this->getSrcSize() == 3); 1443 assert(this->getSrcSize() == 3);
1572 if (this->Locked) { 1444 if (this->Locked) {
1573 Str << "\t" 1445 Str << "\t"
1574 "lock"; 1446 "lock";
1575 } 1447 }
1576 Str << "\t" 1448 Str << "\t"
1577 "cmpxchg" << this->getWidthString(this->getSrc(0)->getType()) << "\t"; 1449 "cmpxchg" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
1578 this->getSrc(2)->emit(Func); 1450 this->getSrc(2)->emit(Func);
1579 Str << ", "; 1451 Str << ", ";
1580 this->getSrc(0)->emit(Func); 1452 this->getSrc(0)->emit(Func);
1581 } 1453 }
1582 1454
1583 template <class Machine> 1455 template <typename TraitsType>
1584 void InstX86Cmpxchg<Machine>::emitIAS(const Cfg *Func) const { 1456 void InstImpl<TraitsType>::InstX86Cmpxchg::emitIAS(const Cfg *Func) const {
1585 assert(this->getSrcSize() == 3); 1457 assert(this->getSrcSize() == 3);
1586 typename InstX86Base<Machine>::Traits::Assembler *Asm = 1458 Assembler *Asm = Func->getAssembler<Assembler>();
1587 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1588 Type Ty = this->getSrc(0)->getType(); 1459 Type Ty = this->getSrc(0)->getType();
1589 auto *Target = InstX86Base<Machine>::getTarget(Func); 1460 auto *Target = InstX86Base::getTarget(Func);
1590 const auto Mem = 1461 const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
1591 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>( 1462 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1592 this->getSrc(0)); 1463 const Address Addr = Mem->toAsmAddress(Asm, Target);
1593 assert(Mem->getSegmentRegister() ==
1594 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
1595 const typename InstX86Base<Machine>::Traits::Address Addr =
1596 Mem->toAsmAddress(Asm, Target);
1597 const auto *VarReg = llvm::cast<Variable>(this->getSrc(2)); 1464 const auto *VarReg = llvm::cast<Variable>(this->getSrc(2));
1598 assert(VarReg->hasReg()); 1465 assert(VarReg->hasReg());
1599 const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg = 1466 const GPRRegister Reg = Traits::getEncodedGPR(VarReg->getRegNum());
1600 InstX86Base<Machine>::Traits::getEncodedGPR(VarReg->getRegNum());
1601 Asm->cmpxchg(Ty, Addr, Reg, this->Locked); 1467 Asm->cmpxchg(Ty, Addr, Reg, this->Locked);
1602 } 1468 }
1603 1469
1604 template <class Machine> 1470 template <typename TraitsType>
1605 void InstX86Cmpxchg<Machine>::dump(const Cfg *Func) const { 1471 void InstImpl<TraitsType>::InstX86Cmpxchg::dump(const Cfg *Func) const {
1606 if (!BuildDefs::dump()) 1472 if (!BuildDefs::dump())
1607 return; 1473 return;
1608 Ostream &Str = Func->getContext()->getStrDump(); 1474 Ostream &Str = Func->getContext()->getStrDump();
1609 if (this->Locked) { 1475 if (this->Locked) {
1610 Str << "lock "; 1476 Str << "lock ";
1611 } 1477 }
1612 Str << "cmpxchg." << this->getSrc(0)->getType() << " "; 1478 Str << "cmpxchg." << this->getSrc(0)->getType() << " ";
1613 this->dumpSources(Func); 1479 this->dumpSources(Func);
1614 } 1480 }
1615 1481
1616 template <class Machine> 1482 template <typename TraitsType>
1617 void InstX86Cmpxchg8b<Machine>::emit(const Cfg *Func) const { 1483 void InstImpl<TraitsType>::InstX86Cmpxchg8b::emit(const Cfg *Func) const {
1618 if (!BuildDefs::dump()) 1484 if (!BuildDefs::dump())
1619 return; 1485 return;
1620 Ostream &Str = Func->getContext()->getStrEmit(); 1486 Ostream &Str = Func->getContext()->getStrEmit();
1621 assert(this->getSrcSize() == 5); 1487 assert(this->getSrcSize() == 5);
1622 if (this->Locked) { 1488 if (this->Locked) {
1623 Str << "\t" 1489 Str << "\t"
1624 "lock"; 1490 "lock";
1625 } 1491 }
1626 Str << "\t" 1492 Str << "\t"
1627 "cmpxchg8b\t"; 1493 "cmpxchg8b\t";
1628 this->getSrc(0)->emit(Func); 1494 this->getSrc(0)->emit(Func);
1629 } 1495 }
1630 1496
1631 template <class Machine> 1497 template <typename TraitsType>
1632 void InstX86Cmpxchg8b<Machine>::emitIAS(const Cfg *Func) const { 1498 void InstImpl<TraitsType>::InstX86Cmpxchg8b::emitIAS(const Cfg *Func) const {
1633 assert(this->getSrcSize() == 5); 1499 assert(this->getSrcSize() == 5);
1634 typename InstX86Base<Machine>::Traits::Assembler *Asm = 1500 Assembler *Asm = Func->getAssembler<Assembler>();
1635 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); 1501 const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
1636 const auto Mem = 1502 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1637 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>( 1503 auto *Target = InstX86Base::getTarget(Func);
1638 this->getSrc(0)); 1504 const Address Addr = Mem->toAsmAddress(Asm, Target);
1639 assert(Mem->getSegmentRegister() ==
1640 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
1641 auto *Target = InstX86Base<Machine>::getTarget(Func);
1642 const typename InstX86Base<Machine>::Traits::Address Addr =
1643 Mem->toAsmAddress(Asm, Target);
1644 Asm->cmpxchg8b(Addr, this->Locked); 1505 Asm->cmpxchg8b(Addr, this->Locked);
1645 } 1506 }
1646 1507
1647 template <class Machine> 1508 template <typename TraitsType>
1648 void InstX86Cmpxchg8b<Machine>::dump(const Cfg *Func) const { 1509 void InstImpl<TraitsType>::InstX86Cmpxchg8b::dump(const Cfg *Func) const {
1649 if (!BuildDefs::dump()) 1510 if (!BuildDefs::dump())
1650 return; 1511 return;
1651 Ostream &Str = Func->getContext()->getStrDump(); 1512 Ostream &Str = Func->getContext()->getStrDump();
1652 if (this->Locked) { 1513 if (this->Locked) {
1653 Str << "lock "; 1514 Str << "lock ";
1654 } 1515 }
1655 Str << "cmpxchg8b "; 1516 Str << "cmpxchg8b ";
1656 this->dumpSources(Func); 1517 this->dumpSources(Func);
1657 } 1518 }
1658 1519
1659 template <class Machine> void InstX86Cvt<Machine>::emit(const Cfg *Func) const { 1520 template <typename TraitsType>
1521 void InstImpl<TraitsType>::InstX86Cvt::emit(const Cfg *Func) const {
1660 if (!BuildDefs::dump()) 1522 if (!BuildDefs::dump())
1661 return; 1523 return;
1662 Ostream &Str = Func->getContext()->getStrEmit(); 1524 Ostream &Str = Func->getContext()->getStrEmit();
1663 assert(this->getSrcSize() == 1); 1525 assert(this->getSrcSize() == 1);
1664 Str << "\t" 1526 Str << "\t"
1665 "cvt"; 1527 "cvt";
1666 if (isTruncating()) 1528 if (isTruncating())
1667 Str << "t"; 1529 Str << "t";
1668 Str << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0) 1530 Str << Traits::TypeAttributes[this->getSrc(0)->getType()].CvtString << "2"
1669 ->getType()] 1531 << Traits::TypeAttributes[this->getDest()->getType()].CvtString << "\t";
1670 .CvtString << "2"
1671 << InstX86Base<
1672 Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1673 .CvtString << "\t";
1674 this->getSrc(0)->emit(Func); 1532 this->getSrc(0)->emit(Func);
1675 Str << ", "; 1533 Str << ", ";
1676 this->getDest()->emit(Func); 1534 this->getDest()->emit(Func);
1677 } 1535 }
1678 1536
1679 template <class Machine> 1537 template <typename TraitsType>
1680 void InstX86Cvt<Machine>::emitIAS(const Cfg *Func) const { 1538 void InstImpl<TraitsType>::InstX86Cvt::emitIAS(const Cfg *Func) const {
1681 assert(this->getSrcSize() == 1); 1539 assert(this->getSrcSize() == 1);
1682 const Variable *Dest = this->getDest(); 1540 const Variable *Dest = this->getDest();
1683 const Operand *Src = this->getSrc(0); 1541 const Operand *Src = this->getSrc(0);
1684 Type DestTy = Dest->getType(); 1542 Type DestTy = Dest->getType();
1685 Type SrcTy = Src->getType(); 1543 Type SrcTy = Src->getType();
1686 switch (Variant) { 1544 switch (Variant) {
1687 case Si2ss: { 1545 case Si2ss: {
1688 assert(isScalarIntegerType(SrcTy)); 1546 assert(isScalarIntegerType(SrcTy));
1689 if (!InstX86Base<Machine>::Traits::Is64Bit) { 1547 if (!Traits::Is64Bit) {
1690 assert(typeWidthInBytes(SrcTy) <= 4); 1548 assert(typeWidthInBytes(SrcTy) <= 4);
1691 } else { 1549 } else {
1692 assert(SrcTy == IceType_i32 || SrcTy == IceType_i64); 1550 assert(SrcTy == IceType_i32 || SrcTy == IceType_i64);
1693 } 1551 }
1694 assert(isScalarFloatingType(DestTy)); 1552 assert(isScalarFloatingType(DestTy));
1695 static const typename InstX86Base<Machine>::Traits::Assembler:: 1553 static const CastEmitterRegOp<XmmRegister, GPRRegister> Emitter = {
1696 template CastEmitterRegOp< 1554 &Assembler::cvtsi2ss, &Assembler::cvtsi2ss};
1697 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister, 1555 emitIASCastRegOp<XmmRegister, GPRRegister, Traits::getEncodedXmm,
1698 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister> 1556 Traits::getEncodedGPR>(Func, DestTy, Dest, SrcTy, Src,
1699 Emitter = {&InstX86Base<Machine>::Traits::Assembler::cvtsi2ss, 1557 Emitter);
1700 &InstX86Base<Machine>::Traits::Assembler::cvtsi2ss};
1701 emitIASCastRegOp<
1702 Machine,
1703 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1704 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1705 InstX86Base<Machine>::Traits::getEncodedXmm,
1706 InstX86Base<Machine>::Traits::getEncodedGPR>(Func, DestTy, Dest, SrcTy,
1707 Src, Emitter);
1708 return; 1558 return;
1709 } 1559 }
1710 case Tss2si: { 1560 case Tss2si: {
1711 assert(isScalarFloatingType(SrcTy)); 1561 assert(isScalarFloatingType(SrcTy));
1712 assert(isScalarIntegerType(DestTy)); 1562 assert(isScalarIntegerType(DestTy));
1713 if (!InstX86Base<Machine>::Traits::Is64Bit) { 1563 if (!Traits::Is64Bit) {
1714 assert(typeWidthInBytes(DestTy) <= 4); 1564 assert(typeWidthInBytes(DestTy) <= 4);
1715 } else { 1565 } else {
1716 assert(DestTy == IceType_i32 || DestTy == IceType_i64); 1566 assert(DestTy == IceType_i32 || DestTy == IceType_i64);
1717 } 1567 }
1718 static const typename InstX86Base<Machine>::Traits::Assembler:: 1568 static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
1719 template CastEmitterRegOp< 1569 &Assembler::cvttss2si, &Assembler::cvttss2si};
1720 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister, 1570 emitIASCastRegOp<GPRRegister, XmmRegister, Traits::getEncodedGPR,
1721 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister> 1571 Traits::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
1722 Emitter = {&InstX86Base<Machine>::Traits::Assembler::cvttss2si, 1572 Emitter);
1723 &InstX86Base<Machine>::Traits::Assembler::cvttss2si};
1724 emitIASCastRegOp<
1725 Machine,
1726 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1727 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1728 InstX86Base<Machine>::Traits::getEncodedGPR,
1729 InstX86Base<Machine>::Traits::getEncodedXmm>(Func, DestTy, Dest, SrcTy,
1730 Src, Emitter);
1731 return; 1573 return;
1732 } 1574 }
1733 case Float2float: { 1575 case Float2float: {
1734 assert(isScalarFloatingType(SrcTy)); 1576 assert(isScalarFloatingType(SrcTy));
1735 assert(isScalarFloatingType(DestTy)); 1577 assert(isScalarFloatingType(DestTy));
1736 assert(DestTy != SrcTy); 1578 assert(DestTy != SrcTy);
1737 static const typename InstX86Base< 1579 static const XmmEmitterRegOp Emitter = {&Assembler::cvtfloat2float,
1738 Machine>::Traits::Assembler::XmmEmitterRegOp Emitter = { 1580 &Assembler::cvtfloat2float};
1739 &InstX86Base<Machine>::Traits::Assembler::cvtfloat2float, 1581 emitIASRegOpTyXMM(Func, SrcTy, Dest, Src, Emitter);
1740 &InstX86Base<Machine>::Traits::Assembler::cvtfloat2float};
1741 emitIASRegOpTyXMM<Machine>(Func, SrcTy, Dest, Src, Emitter);
1742 return; 1582 return;
1743 } 1583 }
1744 case Dq2ps: { 1584 case Dq2ps: {
1745 assert(isVectorIntegerType(SrcTy)); 1585 assert(isVectorIntegerType(SrcTy));
1746 assert(isVectorFloatingType(DestTy)); 1586 assert(isVectorFloatingType(DestTy));
1747 static const typename InstX86Base< 1587 static const XmmEmitterRegOp Emitter = {&Assembler::cvtdq2ps,
1748 Machine>::Traits::Assembler::XmmEmitterRegOp Emitter = { 1588 &Assembler::cvtdq2ps};
1749 &InstX86Base<Machine>::Traits::Assembler::cvtdq2ps, 1589 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
1750 &InstX86Base<Machine>::Traits::Assembler::cvtdq2ps};
1751 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, Emitter);
1752 return; 1590 return;
1753 } 1591 }
1754 case Tps2dq: { 1592 case Tps2dq: {
1755 assert(isVectorFloatingType(SrcTy)); 1593 assert(isVectorFloatingType(SrcTy));
1756 assert(isVectorIntegerType(DestTy)); 1594 assert(isVectorIntegerType(DestTy));
1757 static const typename InstX86Base< 1595 static const XmmEmitterRegOp Emitter = {&Assembler::cvttps2dq,
1758 Machine>::Traits::Assembler::XmmEmitterRegOp Emitter = { 1596 &Assembler::cvttps2dq};
1759 &InstX86Base<Machine>::Traits::Assembler::cvttps2dq, 1597 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
1760 &InstX86Base<Machine>::Traits::Assembler::cvttps2dq};
1761 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, Emitter);
1762 return; 1598 return;
1763 } 1599 }
1764 } 1600 }
1765 } 1601 }
1766 1602
1767 template <class Machine> void InstX86Cvt<Machine>::dump(const Cfg *Func) const { 1603 template <typename TraitsType>
1604 void InstImpl<TraitsType>::InstX86Cvt::dump(const Cfg *Func) const {
1768 if (!BuildDefs::dump()) 1605 if (!BuildDefs::dump())
1769 return; 1606 return;
1770 Ostream &Str = Func->getContext()->getStrDump(); 1607 Ostream &Str = Func->getContext()->getStrDump();
1771 this->dumpDest(Func); 1608 this->dumpDest(Func);
1772 Str << " = cvt"; 1609 Str << " = cvt";
1773 if (isTruncating()) 1610 if (isTruncating())
1774 Str << "t"; 1611 Str << "t";
1775 Str << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0) 1612 Str << Traits::TypeAttributes[this->getSrc(0)->getType()].CvtString << "2"
1776 ->getType()] 1613 << Traits::TypeAttributes[this->getDest()->getType()].CvtString << " ";
1777 .CvtString << "2"
1778 << InstX86Base<
1779 Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1780 .CvtString << " ";
1781 this->dumpSources(Func); 1614 this->dumpSources(Func);
1782 } 1615 }
1783 1616
1784 template <class Machine> 1617 template <typename TraitsType>
1785 void InstX86Icmp<Machine>::emit(const Cfg *Func) const { 1618 void InstImpl<TraitsType>::InstX86Icmp::emit(const Cfg *Func) const {
1786 if (!BuildDefs::dump()) 1619 if (!BuildDefs::dump())
1787 return; 1620 return;
1788 Ostream &Str = Func->getContext()->getStrEmit(); 1621 Ostream &Str = Func->getContext()->getStrEmit();
1789 assert(this->getSrcSize() == 2); 1622 assert(this->getSrcSize() == 2);
1790 Str << "\t" 1623 Str << "\t"
1791 "cmp" << this->getWidthString(this->getSrc(0)->getType()) << "\t"; 1624 "cmp" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
1792 this->getSrc(1)->emit(Func); 1625 this->getSrc(1)->emit(Func);
1793 Str << ", "; 1626 Str << ", ";
1794 this->getSrc(0)->emit(Func); 1627 this->getSrc(0)->emit(Func);
1795 } 1628 }
1796 1629
1797 template <class Machine> 1630 template <typename TraitsType>
1798 void InstX86Icmp<Machine>::emitIAS(const Cfg *Func) const { 1631 void InstImpl<TraitsType>::InstX86Icmp::emitIAS(const Cfg *Func) const {
1799 assert(this->getSrcSize() == 2); 1632 assert(this->getSrcSize() == 2);
1800 const Operand *Src0 = this->getSrc(0); 1633 const Operand *Src0 = this->getSrc(0);
1801 const Operand *Src1 = this->getSrc(1); 1634 const Operand *Src1 = this->getSrc(1);
1802 Type Ty = Src0->getType(); 1635 Type Ty = Src0->getType();
1803 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp 1636 static const GPREmitterRegOp RegEmitter = {&Assembler::cmp, &Assembler::cmp,
1804 RegEmitter = {&InstX86Base<Machine>::Traits::Assembler::cmp, 1637 &Assembler::cmp};
1805 &InstX86Base<Machine>::Traits::Assembler::cmp, 1638 static const GPREmitterAddrOp AddrEmitter = {&Assembler::cmp,
1806 &InstX86Base<Machine>::Traits::Assembler::cmp}; 1639 &Assembler::cmp};
1807 static const typename InstX86Base<
1808 Machine>::Traits::Assembler::GPREmitterAddrOp AddrEmitter = {
1809 &InstX86Base<Machine>::Traits::Assembler::cmp,
1810 &InstX86Base<Machine>::Traits::Assembler::cmp};
1811 if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { 1640 if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
1812 if (SrcVar0->hasReg()) { 1641 if (SrcVar0->hasReg()) {
1813 emitIASRegOpTyGPR<Machine>(Func, Ty, SrcVar0, Src1, RegEmitter); 1642 emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter);
1814 return; 1643 return;
1815 } 1644 }
1816 } 1645 }
1817 emitIASAsAddrOpTyGPR<Machine>(Func, Ty, Src0, Src1, AddrEmitter); 1646 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
1818 } 1647 }
1819 1648
1820 template <class Machine> 1649 template <typename TraitsType>
1821 void InstX86Icmp<Machine>::dump(const Cfg *Func) const { 1650 void InstImpl<TraitsType>::InstX86Icmp::dump(const Cfg *Func) const {
1822 if (!BuildDefs::dump()) 1651 if (!BuildDefs::dump())
1823 return; 1652 return;
1824 Ostream &Str = Func->getContext()->getStrDump(); 1653 Ostream &Str = Func->getContext()->getStrDump();
1825 Str << "cmp." << this->getSrc(0)->getType() << " "; 1654 Str << "cmp." << this->getSrc(0)->getType() << " ";
1826 this->dumpSources(Func); 1655 this->dumpSources(Func);
1827 } 1656 }
1828 1657
1829 template <class Machine> 1658 template <typename TraitsType>
1830 void InstX86Ucomiss<Machine>::emit(const Cfg *Func) const { 1659 void InstImpl<TraitsType>::InstX86Ucomiss::emit(const Cfg *Func) const {
1831 if (!BuildDefs::dump()) 1660 if (!BuildDefs::dump())
1832 return; 1661 return;
1833 Ostream &Str = Func->getContext()->getStrEmit(); 1662 Ostream &Str = Func->getContext()->getStrEmit();
1834 assert(this->getSrcSize() == 2); 1663 assert(this->getSrcSize() == 2);
1835 Str << "\t" 1664 Str << "\t"
1836 "ucomi" 1665 "ucomi"
1837 << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0) 1666 << Traits::TypeAttributes[this->getSrc(0)->getType()].SdSsString << "\t";
1838 ->getType()]
1839 .SdSsString << "\t";
1840 this->getSrc(1)->emit(Func); 1667 this->getSrc(1)->emit(Func);
1841 Str << ", "; 1668 Str << ", ";
1842 this->getSrc(0)->emit(Func); 1669 this->getSrc(0)->emit(Func);
1843 } 1670 }
1844 1671
1845 template <class Machine> 1672 template <typename TraitsType>
1846 void InstX86Ucomiss<Machine>::emitIAS(const Cfg *Func) const { 1673 void InstImpl<TraitsType>::InstX86Ucomiss::emitIAS(const Cfg *Func) const {
1847 assert(this->getSrcSize() == 2); 1674 assert(this->getSrcSize() == 2);
1848 // Currently src0 is always a variable by convention, to avoid having two 1675 // Currently src0 is always a variable by convention, to avoid having two
1849 // memory operands. 1676 // memory operands.
1850 assert(llvm::isa<Variable>(this->getSrc(0))); 1677 assert(llvm::isa<Variable>(this->getSrc(0)));
1851 const auto *Src0Var = llvm::cast<Variable>(this->getSrc(0)); 1678 const auto *Src0Var = llvm::cast<Variable>(this->getSrc(0));
1852 Type Ty = Src0Var->getType(); 1679 Type Ty = Src0Var->getType();
1853 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp 1680 static const XmmEmitterRegOp Emitter = {&Assembler::ucomiss,
1854 Emitter = {&InstX86Base<Machine>::Traits::Assembler::ucomiss, 1681 &Assembler::ucomiss};
1855 &InstX86Base<Machine>::Traits::Assembler::ucomiss}; 1682 emitIASRegOpTyXMM(Func, Ty, Src0Var, this->getSrc(1), Emitter);
1856 emitIASRegOpTyXMM<Machine>(Func, Ty, Src0Var, this->getSrc(1), Emitter);
1857 } 1683 }
1858 1684
1859 template <class Machine> 1685 template <typename TraitsType>
1860 void InstX86Ucomiss<Machine>::dump(const Cfg *Func) const { 1686 void InstImpl<TraitsType>::InstX86Ucomiss::dump(const Cfg *Func) const {
1861 if (!BuildDefs::dump()) 1687 if (!BuildDefs::dump())
1862 return; 1688 return;
1863 Ostream &Str = Func->getContext()->getStrDump(); 1689 Ostream &Str = Func->getContext()->getStrDump();
1864 Str << "ucomiss." << this->getSrc(0)->getType() << " "; 1690 Str << "ucomiss." << this->getSrc(0)->getType() << " ";
1865 this->dumpSources(Func); 1691 this->dumpSources(Func);
1866 } 1692 }
1867 1693
1868 template <class Machine> void InstX86UD2<Machine>::emit(const Cfg *Func) const { 1694 template <typename TraitsType>
1695 void InstImpl<TraitsType>::InstX86UD2::emit(const Cfg *Func) const {
1869 if (!BuildDefs::dump()) 1696 if (!BuildDefs::dump())
1870 return; 1697 return;
1871 Ostream &Str = Func->getContext()->getStrEmit(); 1698 Ostream &Str = Func->getContext()->getStrEmit();
1872 assert(this->getSrcSize() == 0); 1699 assert(this->getSrcSize() == 0);
1873 Str << "\t" 1700 Str << "\t"
1874 "ud2"; 1701 "ud2";
1875 } 1702 }
1876 1703
1877 template <class Machine> 1704 template <typename TraitsType>
1878 void InstX86UD2<Machine>::emitIAS(const Cfg *Func) const { 1705 void InstImpl<TraitsType>::InstX86UD2::emitIAS(const Cfg *Func) const {
1879 typename InstX86Base<Machine>::Traits::Assembler *Asm = 1706 Assembler *Asm = Func->getAssembler<Assembler>();
1880 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1881 Asm->ud2(); 1707 Asm->ud2();
1882 } 1708 }
1883 1709
1884 template <class Machine> void InstX86UD2<Machine>::dump(const Cfg *Func) const { 1710 template <typename TraitsType>
1711 void InstImpl<TraitsType>::InstX86UD2::dump(const Cfg *Func) const {
1885 if (!BuildDefs::dump()) 1712 if (!BuildDefs::dump())
1886 return; 1713 return;
1887 Ostream &Str = Func->getContext()->getStrDump(); 1714 Ostream &Str = Func->getContext()->getStrDump();
1888 Str << "ud2"; 1715 Str << "ud2";
1889 } 1716 }
1890 1717
1891 template <class Machine> 1718 template <typename TraitsType>
1892 void InstX86Test<Machine>::emit(const Cfg *Func) const { 1719 void InstImpl<TraitsType>::InstX86Test::emit(const Cfg *Func) const {
1893 if (!BuildDefs::dump()) 1720 if (!BuildDefs::dump())
1894 return; 1721 return;
1895 Ostream &Str = Func->getContext()->getStrEmit(); 1722 Ostream &Str = Func->getContext()->getStrEmit();
1896 assert(this->getSrcSize() == 2); 1723 assert(this->getSrcSize() == 2);
1897 Str << "\t" 1724 Str << "\t"
1898 "test" << this->getWidthString(this->getSrc(0)->getType()) << "\t"; 1725 "test" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
1899 this->getSrc(1)->emit(Func); 1726 this->getSrc(1)->emit(Func);
1900 Str << ", "; 1727 Str << ", ";
1901 this->getSrc(0)->emit(Func); 1728 this->getSrc(0)->emit(Func);
1902 } 1729 }
1903 1730
1904 template <class Machine> 1731 template <typename TraitsType>
1905 void InstX86Test<Machine>::emitIAS(const Cfg *Func) const { 1732 void InstImpl<TraitsType>::InstX86Test::emitIAS(const Cfg *Func) const {
1906 assert(this->getSrcSize() == 2); 1733 assert(this->getSrcSize() == 2);
1907 const Operand *Src0 = this->getSrc(0); 1734 const Operand *Src0 = this->getSrc(0);
1908 const Operand *Src1 = this->getSrc(1); 1735 const Operand *Src1 = this->getSrc(1);
1909 Type Ty = Src0->getType(); 1736 Type Ty = Src0->getType();
1910 // The Reg/Addr form of test is not encodeable. 1737 // The Reg/Addr form of test is not encodeable.
1911 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp 1738 static const GPREmitterRegOp RegEmitter = {&Assembler::test, nullptr,
1912 RegEmitter = {&InstX86Base<Machine>::Traits::Assembler::test, nullptr, 1739 &Assembler::test};
1913 &InstX86Base<Machine>::Traits::Assembler::test}; 1740 static const GPREmitterAddrOp AddrEmitter = {&Assembler::test,
1914 static const typename InstX86Base< 1741 &Assembler::test};
1915 Machine>::Traits::Assembler::GPREmitterAddrOp AddrEmitter = {
1916 &InstX86Base<Machine>::Traits::Assembler::test,
1917 &InstX86Base<Machine>::Traits::Assembler::test};
1918 if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { 1742 if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
1919 if (SrcVar0->hasReg()) { 1743 if (SrcVar0->hasReg()) {
1920 emitIASRegOpTyGPR<Machine>(Func, Ty, SrcVar0, Src1, RegEmitter); 1744 emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter);
1921 return; 1745 return;
1922 } 1746 }
1923 } 1747 }
1924 emitIASAsAddrOpTyGPR<Machine>(Func, Ty, Src0, Src1, AddrEmitter); 1748 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
1925 } 1749 }
1926 1750
1927 template <class Machine> 1751 template <typename TraitsType>
1928 void InstX86Test<Machine>::dump(const Cfg *Func) const { 1752 void InstImpl<TraitsType>::InstX86Test::dump(const Cfg *Func) const {
1929 if (!BuildDefs::dump()) 1753 if (!BuildDefs::dump())
1930 return; 1754 return;
1931 Ostream &Str = Func->getContext()->getStrDump(); 1755 Ostream &Str = Func->getContext()->getStrDump();
1932 Str << "test." << this->getSrc(0)->getType() << " "; 1756 Str << "test." << this->getSrc(0)->getType() << " ";
1933 this->dumpSources(Func); 1757 this->dumpSources(Func);
1934 } 1758 }
1935 1759
1936 template <class Machine> 1760 template <typename TraitsType>
1937 void InstX86Mfence<Machine>::emit(const Cfg *Func) const { 1761 void InstImpl<TraitsType>::InstX86Mfence::emit(const Cfg *Func) const {
1938 if (!BuildDefs::dump()) 1762 if (!BuildDefs::dump())
1939 return; 1763 return;
1940 Ostream &Str = Func->getContext()->getStrEmit(); 1764 Ostream &Str = Func->getContext()->getStrEmit();
1941 assert(this->getSrcSize() == 0); 1765 assert(this->getSrcSize() == 0);
1942 Str << "\t" 1766 Str << "\t"
1943 "mfence"; 1767 "mfence";
1944 } 1768 }
1945 1769
1946 template <class Machine> 1770 template <typename TraitsType>
1947 void InstX86Mfence<Machine>::emitIAS(const Cfg *Func) const { 1771 void InstImpl<TraitsType>::InstX86Mfence::emitIAS(const Cfg *Func) const {
1948 typename InstX86Base<Machine>::Traits::Assembler *Asm = 1772 Assembler *Asm = Func->getAssembler<Assembler>();
1949 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1950 Asm->mfence(); 1773 Asm->mfence();
1951 } 1774 }
1952 1775
1953 template <class Machine> 1776 template <typename TraitsType>
1954 void InstX86Mfence<Machine>::dump(const Cfg *Func) const { 1777 void InstImpl<TraitsType>::InstX86Mfence::dump(const Cfg *Func) const {
1955 if (!BuildDefs::dump()) 1778 if (!BuildDefs::dump())
1956 return; 1779 return;
1957 Ostream &Str = Func->getContext()->getStrDump(); 1780 Ostream &Str = Func->getContext()->getStrDump();
1958 Str << "mfence"; 1781 Str << "mfence";
1959 } 1782 }
1960 1783
1961 template <class Machine> 1784 template <typename TraitsType>
1962 void InstX86Store<Machine>::emit(const Cfg *Func) const { 1785 void InstImpl<TraitsType>::InstX86Store::emit(const Cfg *Func) const {
1963 if (!BuildDefs::dump()) 1786 if (!BuildDefs::dump())
1964 return; 1787 return;
1965 Ostream &Str = Func->getContext()->getStrEmit(); 1788 Ostream &Str = Func->getContext()->getStrEmit();
1966 assert(this->getSrcSize() == 2); 1789 assert(this->getSrcSize() == 2);
1967 Type Ty = this->getSrc(0)->getType(); 1790 Type Ty = this->getSrc(0)->getType();
1968 Str << "\t" 1791 Str << "\t"
1969 "mov" << this->getWidthString(Ty) 1792 "mov" << this->getWidthString(Ty)
1970 << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString << "\t"; 1793 << Traits::TypeAttributes[Ty].SdSsString << "\t";
1971 this->getSrc(0)->emit(Func); 1794 this->getSrc(0)->emit(Func);
1972 Str << ", "; 1795 Str << ", ";
1973 this->getSrc(1)->emit(Func); 1796 this->getSrc(1)->emit(Func);
1974 } 1797 }
1975 1798
1976 template <class Machine> 1799 template <typename TraitsType>
1977 void InstX86Store<Machine>::emitIAS(const Cfg *Func) const { 1800 void InstImpl<TraitsType>::InstX86Store::emitIAS(const Cfg *Func) const {
1978 assert(this->getSrcSize() == 2); 1801 assert(this->getSrcSize() == 2);
1979 const Operand *Dest = this->getSrc(1); 1802 const Operand *Dest = this->getSrc(1);
1980 const Operand *Src = this->getSrc(0); 1803 const Operand *Src = this->getSrc(0);
1981 Type DestTy = Dest->getType(); 1804 Type DestTy = Dest->getType();
1982 if (isScalarFloatingType(DestTy)) { 1805 if (isScalarFloatingType(DestTy)) {
1983 // Src must be a register, since Dest is a Mem operand of some kind. 1806 // Src must be a register, since Dest is a Mem operand of some kind.
1984 const auto *SrcVar = llvm::cast<Variable>(Src); 1807 const auto *SrcVar = llvm::cast<Variable>(Src);
1985 assert(SrcVar->hasReg()); 1808 assert(SrcVar->hasReg());
1986 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg = 1809 XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
1987 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum()); 1810 Assembler *Asm = Func->getAssembler<Assembler>();
1988 typename InstX86Base<Machine>::Traits::Assembler *Asm = 1811 auto *Target = InstX86Base::getTarget(Func);
1989 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1990 auto *Target = InstX86Base<Machine>::getTarget(Func);
1991 if (const auto *DestVar = llvm::dyn_cast<Variable>(Dest)) { 1812 if (const auto *DestVar = llvm::dyn_cast<Variable>(Dest)) {
1992 assert(!DestVar->hasReg()); 1813 assert(!DestVar->hasReg());
1993 typename InstX86Base<Machine>::Traits::Address StackAddr( 1814 Address StackAddr(Target->stackVarToAsmOperand(DestVar));
1994 Target->stackVarToAsmOperand(DestVar));
1995 Asm->movss(DestTy, StackAddr, SrcReg); 1815 Asm->movss(DestTy, StackAddr, SrcReg);
1996 } else { 1816 } else {
1997 const auto DestMem = 1817 const auto DestMem = llvm::cast<X86OperandMem>(Dest);
1998 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>( 1818 assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1999 Dest);
2000 assert(DestMem->getSegmentRegister() ==
2001 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2002 Asm->movss(DestTy, DestMem->toAsmAddress(Asm, Target), SrcReg); 1819 Asm->movss(DestTy, DestMem->toAsmAddress(Asm, Target), SrcReg);
2003 } 1820 }
2004 return; 1821 return;
2005 } else { 1822 } else {
2006 assert(isScalarIntegerType(DestTy)); 1823 assert(isScalarIntegerType(DestTy));
2007 static const typename InstX86Base< 1824 static const GPREmitterAddrOp GPRAddrEmitter = {&Assembler::mov,
2008 Machine>::Traits::Assembler::GPREmitterAddrOp GPRAddrEmitter = { 1825 &Assembler::mov};
2009 &InstX86Base<Machine>::Traits::Assembler::mov, 1826 emitIASAsAddrOpTyGPR(Func, DestTy, Dest, Src, GPRAddrEmitter);
2010 &InstX86Base<Machine>::Traits::Assembler::mov};
2011 emitIASAsAddrOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRAddrEmitter);
2012 } 1827 }
2013 } 1828 }
2014 1829
2015 template <class Machine> 1830 template <typename TraitsType>
2016 void InstX86Store<Machine>::dump(const Cfg *Func) const { 1831 void InstImpl<TraitsType>::InstX86Store::dump(const Cfg *Func) const {
2017 if (!BuildDefs::dump()) 1832 if (!BuildDefs::dump())
2018 return; 1833 return;
2019 Ostream &Str = Func->getContext()->getStrDump(); 1834 Ostream &Str = Func->getContext()->getStrDump();
2020 Str << "mov." << this->getSrc(0)->getType() << " "; 1835 Str << "mov." << this->getSrc(0)->getType() << " ";
2021 this->getSrc(1)->dump(Func); 1836 this->getSrc(1)->dump(Func);
2022 Str << ", "; 1837 Str << ", ";
2023 this->getSrc(0)->dump(Func); 1838 this->getSrc(0)->dump(Func);
2024 } 1839 }
2025 1840
2026 template <class Machine> 1841 template <typename TraitsType>
2027 void InstX86StoreP<Machine>::emit(const Cfg *Func) const { 1842 void InstImpl<TraitsType>::InstX86StoreP::emit(const Cfg *Func) const {
2028 if (!BuildDefs::dump()) 1843 if (!BuildDefs::dump())
2029 return; 1844 return;
2030 Ostream &Str = Func->getContext()->getStrEmit(); 1845 Ostream &Str = Func->getContext()->getStrEmit();
2031 assert(this->getSrcSize() == 2); 1846 assert(this->getSrcSize() == 2);
2032 assert(isVectorType(this->getSrc(1)->getType())); 1847 assert(isVectorType(this->getSrc(1)->getType()));
2033 Str << "\t" 1848 Str << "\t"
2034 "movups\t"; 1849 "movups\t";
2035 this->getSrc(0)->emit(Func); 1850 this->getSrc(0)->emit(Func);
2036 Str << ", "; 1851 Str << ", ";
2037 this->getSrc(1)->emit(Func); 1852 this->getSrc(1)->emit(Func);
2038 } 1853 }
2039 1854
2040 template <class Machine> 1855 template <typename TraitsType>
2041 void InstX86StoreP<Machine>::emitIAS(const Cfg *Func) const { 1856 void InstImpl<TraitsType>::InstX86StoreP::emitIAS(const Cfg *Func) const {
2042 typename InstX86Base<Machine>::Traits::Assembler *Asm = 1857 Assembler *Asm = Func->getAssembler<Assembler>();
2043 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2044 assert(this->getSrcSize() == 2); 1858 assert(this->getSrcSize() == 2);
2045 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0)); 1859 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
2046 const auto DestMem = 1860 const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
2047 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>( 1861 assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
2048 this->getSrc(1));
2049 assert(DestMem->getSegmentRegister() ==
2050 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2051 assert(SrcVar->hasReg()); 1862 assert(SrcVar->hasReg());
2052 auto *Target = InstX86Base<Machine>::getTarget(Func); 1863 auto *Target = InstX86Base::getTarget(Func);
2053 Asm->movups(DestMem->toAsmAddress(Asm, Target), 1864 Asm->movups(DestMem->toAsmAddress(Asm, Target),
2054 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum())); 1865 Traits::getEncodedXmm(SrcVar->getRegNum()));
2055 } 1866 }
2056 1867
2057 template <class Machine> 1868 template <typename TraitsType>
2058 void InstX86StoreP<Machine>::dump(const Cfg *Func) const { 1869 void InstImpl<TraitsType>::InstX86StoreP::dump(const Cfg *Func) const {
2059 if (!BuildDefs::dump()) 1870 if (!BuildDefs::dump())
2060 return; 1871 return;
2061 Ostream &Str = Func->getContext()->getStrDump(); 1872 Ostream &Str = Func->getContext()->getStrDump();
2062 Str << "storep." << this->getSrc(0)->getType() << " "; 1873 Str << "storep." << this->getSrc(0)->getType() << " ";
2063 this->getSrc(1)->dump(Func); 1874 this->getSrc(1)->dump(Func);
2064 Str << ", "; 1875 Str << ", ";
2065 this->getSrc(0)->dump(Func); 1876 this->getSrc(0)->dump(Func);
2066 } 1877 }
2067 1878
2068 template <class Machine> 1879 template <typename TraitsType>
2069 void InstX86StoreQ<Machine>::emit(const Cfg *Func) const { 1880 void InstImpl<TraitsType>::InstX86StoreQ::emit(const Cfg *Func) const {
2070 if (!BuildDefs::dump()) 1881 if (!BuildDefs::dump())
2071 return; 1882 return;
2072 Ostream &Str = Func->getContext()->getStrEmit(); 1883 Ostream &Str = Func->getContext()->getStrEmit();
2073 assert(this->getSrcSize() == 2); 1884 assert(this->getSrcSize() == 2);
2074 assert(this->getSrc(1)->getType() == IceType_i64 || 1885 assert(this->getSrc(1)->getType() == IceType_i64 ||
2075 this->getSrc(1)->getType() == IceType_f64 || 1886 this->getSrc(1)->getType() == IceType_f64 ||
2076 isVectorType(this->getSrc(1)->getType())); 1887 isVectorType(this->getSrc(1)->getType()));
2077 Str << "\t" 1888 Str << "\t"
2078 "movq\t"; 1889 "movq\t";
2079 this->getSrc(0)->emit(Func); 1890 this->getSrc(0)->emit(Func);
2080 Str << ", "; 1891 Str << ", ";
2081 this->getSrc(1)->emit(Func); 1892 this->getSrc(1)->emit(Func);
2082 } 1893 }
2083 1894
2084 template <class Machine> 1895 template <typename TraitsType>
2085 void InstX86StoreQ<Machine>::emitIAS(const Cfg *Func) const { 1896 void InstImpl<TraitsType>::InstX86StoreQ::emitIAS(const Cfg *Func) const {
2086 typename InstX86Base<Machine>::Traits::Assembler *Asm = 1897 Assembler *Asm = Func->getAssembler<Assembler>();
2087 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2088 assert(this->getSrcSize() == 2); 1898 assert(this->getSrcSize() == 2);
2089 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0)); 1899 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
2090 const auto DestMem = 1900 const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
2091 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>( 1901 assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
2092 this->getSrc(1));
2093 assert(DestMem->getSegmentRegister() ==
2094 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2095 assert(SrcVar->hasReg()); 1902 assert(SrcVar->hasReg());
2096 auto *Target = InstX86Base<Machine>::getTarget(Func); 1903 auto *Target = InstX86Base::getTarget(Func);
2097 Asm->movq(DestMem->toAsmAddress(Asm, Target), 1904 Asm->movq(DestMem->toAsmAddress(Asm, Target),
2098 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum())); 1905 Traits::getEncodedXmm(SrcVar->getRegNum()));
2099 } 1906 }
2100 1907
2101 template <class Machine> 1908 template <typename TraitsType>
2102 void InstX86StoreQ<Machine>::dump(const Cfg *Func) const { 1909 void InstImpl<TraitsType>::InstX86StoreQ::dump(const Cfg *Func) const {
2103 if (!BuildDefs::dump()) 1910 if (!BuildDefs::dump())
2104 return; 1911 return;
2105 Ostream &Str = Func->getContext()->getStrDump(); 1912 Ostream &Str = Func->getContext()->getStrDump();
2106 Str << "storeq." << this->getSrc(0)->getType() << " "; 1913 Str << "storeq." << this->getSrc(0)->getType() << " ";
2107 this->getSrc(1)->dump(Func); 1914 this->getSrc(1)->dump(Func);
2108 Str << ", "; 1915 Str << ", ";
2109 this->getSrc(0)->dump(Func); 1916 this->getSrc(0)->dump(Func);
2110 } 1917 }
2111 1918
2112 template <class Machine> void InstX86Lea<Machine>::emit(const Cfg *Func) const { 1919 template <typename TraitsType>
1920 void InstImpl<TraitsType>::InstX86Lea::emit(const Cfg *Func) const {
2113 if (!BuildDefs::dump()) 1921 if (!BuildDefs::dump())
2114 return; 1922 return;
2115 Ostream &Str = Func->getContext()->getStrEmit(); 1923 Ostream &Str = Func->getContext()->getStrEmit();
2116 assert(this->getSrcSize() == 1); 1924 assert(this->getSrcSize() == 1);
2117 assert(this->getDest()->hasReg()); 1925 assert(this->getDest()->hasReg());
2118 Str << "\t" 1926 Str << "\t"
2119 "leal\t"; 1927 "leal\t";
2120 Operand *Src0 = this->getSrc(0); 1928 Operand *Src0 = this->getSrc(0);
2121 if (const auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) { 1929 if (const auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
2122 Type Ty = Src0Var->getType(); 1930 Type Ty = Src0Var->getType();
2123 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an 1931 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
2124 // acceptable type. 1932 // acceptable type.
2125 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty, Variable::NoRegister) 1933 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty, Variable::NoRegister)
2126 ->emit(Func); 1934 ->emit(Func);
2127 } else { 1935 } else {
2128 Src0->emit(Func); 1936 Src0->emit(Func);
2129 } 1937 }
2130 Str << ", "; 1938 Str << ", ";
2131 this->getDest()->emit(Func); 1939 this->getDest()->emit(Func);
2132 } 1940 }
2133 1941
2134 template <class Machine> void InstX86Mov<Machine>::emit(const Cfg *Func) const { 1942 template <typename TraitsType>
1943 void InstImpl<TraitsType>::InstX86Mov::emit(const Cfg *Func) const {
2135 if (!BuildDefs::dump()) 1944 if (!BuildDefs::dump())
2136 return; 1945 return;
2137 Ostream &Str = Func->getContext()->getStrEmit(); 1946 Ostream &Str = Func->getContext()->getStrEmit();
2138 assert(this->getSrcSize() == 1); 1947 assert(this->getSrcSize() == 1);
2139 Operand *Src = this->getSrc(0); 1948 Operand *Src = this->getSrc(0);
2140 Type SrcTy = Src->getType(); 1949 Type SrcTy = Src->getType();
2141 Type DestTy = this->getDest()->getType(); 1950 Type DestTy = this->getDest()->getType();
2142 if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64 && 1951 if (Traits::Is64Bit && DestTy == IceType_i64 &&
2143 llvm::isa<ConstantInteger64>(Src)) { 1952 llvm::isa<ConstantInteger64>(Src)) {
2144 Str << "\t" 1953 Str << "\t"
2145 "movabs" 1954 "movabs"
2146 "\t"; 1955 "\t";
2147 } else { 1956 } else {
2148 Str << "\t" 1957 Str << "\t"
2149 "mov" << (!isScalarFloatingType(DestTy) 1958 "mov" << (!isScalarFloatingType(DestTy)
2150 ? this->getWidthString(DestTy) 1959 ? this->getWidthString(DestTy)
2151 : InstX86Base<Machine>::Traits::TypeAttributes[DestTy] 1960 : Traits::TypeAttributes[DestTy].SdSsString) << "\t";
2152 .SdSsString) << "\t";
2153 } 1961 }
2154 // For an integer truncation operation, src is wider than dest. In this case, 1962 // For an integer truncation operation, src is wider than dest. In this case,
2155 // we use a mov instruction whose data width matches the narrower dest. 1963 // we use a mov instruction whose data width matches the narrower dest.
2156 // TODO: This assert disallows usages such as copying a floating 1964 // TODO: This assert disallows usages such as copying a floating
2157 // point value between a vector and a scalar (which movss is used for). Clean 1965 // point value between a vector and a scalar (which movss is used for). Clean
2158 // this up. 1966 // this up.
2159 assert( 1967 assert(InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(DestTy) ==
2160 InstX86Base<Machine>::getTarget(Func)->typeWidthInBytesOnStack(DestTy) == 1968 InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(SrcTy));
2161 InstX86Base<Machine>::getTarget(Func)->typeWidthInBytesOnStack(SrcTy));
2162 const Operand *NewSrc = Src; 1969 const Operand *NewSrc = Src;
2163 if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { 1970 if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
2164 int32_t NewRegNum = Variable::NoRegister; 1971 int32_t NewRegNum = Variable::NoRegister;
2165 if (SrcVar->hasReg()) 1972 if (SrcVar->hasReg())
2166 NewRegNum = InstX86Base<Machine>::Traits::getGprForType( 1973 NewRegNum = Traits::getGprForType(DestTy, SrcVar->getRegNum());
2167 DestTy, SrcVar->getRegNum());
2168 if (SrcTy != DestTy) 1974 if (SrcTy != DestTy)
2169 NewSrc = SrcVar->asType(DestTy, NewRegNum); 1975 NewSrc = SrcVar->asType(DestTy, NewRegNum);
2170 } 1976 }
2171 NewSrc->emit(Func); 1977 NewSrc->emit(Func);
2172 Str << ", "; 1978 Str << ", ";
2173 this->getDest()->emit(Func); 1979 this->getDest()->emit(Func);
2174 } 1980 }
2175 1981
2176 template <class Machine> 1982 template <typename TraitsType>
2177 void InstX86Mov<Machine>::emitIAS(const Cfg *Func) const { 1983 void InstImpl<TraitsType>::InstX86Mov::emitIAS(const Cfg *Func) const {
2178 assert(this->getSrcSize() == 1); 1984 assert(this->getSrcSize() == 1);
2179 const Variable *Dest = this->getDest(); 1985 const Variable *Dest = this->getDest();
2180 const Operand *Src = this->getSrc(0); 1986 const Operand *Src = this->getSrc(0);
2181 Type DestTy = Dest->getType(); 1987 Type DestTy = Dest->getType();
2182 Type SrcTy = Src->getType(); 1988 Type SrcTy = Src->getType();
2183 // Mov can be used for GPRs or XMM registers. Also, the type does not 1989 // Mov can be used for GPRs or XMM registers. Also, the type does not
2184 // necessarily match (Mov can be used for bitcasts). However, when the type 1990 // necessarily match (Mov can be used for bitcasts). However, when the type
2185 // does not match, one of the operands must be a register. Thus, the strategy 1991 // does not match, one of the operands must be a register. Thus, the strategy
2186 // is to find out if Src or Dest are a register, then use that register's 1992 // is to find out if Src or Dest are a register, then use that register's
2187 // type to decide on which emitter set to use. The emitter set will include 1993 // type to decide on which emitter set to use. The emitter set will include
2188 // reg-reg movs, but that case should be unused when the types don't match. 1994 // reg-reg movs, but that case should be unused when the types don't match.
2189 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp 1995 static const XmmEmitterRegOp XmmRegEmitter = {&Assembler::movss,
2190 XmmRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::movss, 1996 &Assembler::movss};
2191 &InstX86Base<Machine>::Traits::Assembler::movss}; 1997 static const GPREmitterRegOp GPRRegEmitter = {
2192 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp 1998 &Assembler::mov, &Assembler::mov, &Assembler::mov};
2193 GPRRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::mov, 1999 static const GPREmitterAddrOp GPRAddrEmitter = {&Assembler::mov,
2194 &InstX86Base<Machine>::Traits::Assembler::mov, 2000 &Assembler::mov};
2195 &InstX86Base<Machine>::Traits::Assembler::mov};
2196 static const typename InstX86Base<
2197 Machine>::Traits::Assembler::GPREmitterAddrOp GPRAddrEmitter = {
2198 &InstX86Base<Machine>::Traits::Assembler::mov,
2199 &InstX86Base<Machine>::Traits::Assembler::mov};
2200 // For an integer truncation operation, src is wider than dest. In this case, 2001 // For an integer truncation operation, src is wider than dest. In this case,
2201 // we use a mov instruction whose data width matches the narrower dest. 2002 // we use a mov instruction whose data width matches the narrower dest.
2202 // TODO: This assert disallows usages such as copying a floating 2003 // TODO: This assert disallows usages such as copying a floating
2203 // point value between a vector and a scalar (which movss is used for). Clean 2004 // point value between a vector and a scalar (which movss is used for). Clean
2204 // this up. 2005 // this up.
2205 auto *Target = InstX86Base<Machine>::getTarget(Func); 2006 auto *Target = InstX86Base::getTarget(Func);
2206 assert(Target->typeWidthInBytesOnStack(this->getDest()->getType()) == 2007 assert(Target->typeWidthInBytesOnStack(this->getDest()->getType()) ==
2207 Target->typeWidthInBytesOnStack(Src->getType())); 2008 Target->typeWidthInBytesOnStack(Src->getType()));
2208 if (Dest->hasReg()) { 2009 if (Dest->hasReg()) {
2209 if (isScalarFloatingType(DestTy)) { 2010 if (isScalarFloatingType(DestTy)) {
2210 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, XmmRegEmitter); 2011 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, XmmRegEmitter);
2211 return; 2012 return;
2212 } else { 2013 } else {
2213 assert(isScalarIntegerType(DestTy)); 2014 assert(isScalarIntegerType(DestTy));
2214 // Widen DestTy for truncation (see above note). We should only do this 2015 // Widen DestTy for truncation (see above note). We should only do this
2215 // when both Src and Dest are integer types. 2016 // when both Src and Dest are integer types.
2216 if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64) { 2017 if (Traits::Is64Bit && DestTy == IceType_i64) {
2217 if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) { 2018 if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) {
2218 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>() 2019 Func->getAssembler<Assembler>()->movabs(
2219 ->movabs(InstX86Base<Machine>::Traits::getEncodedGPR( 2020 Traits::getEncodedGPR(Dest->getRegNum()), C64->getValue());
2220 Dest->getRegNum()),
2221 C64->getValue());
2222 return; 2021 return;
2223 } 2022 }
2224 } 2023 }
2225 if (isScalarIntegerType(SrcTy)) { 2024 if (isScalarIntegerType(SrcTy)) {
2226 SrcTy = DestTy; 2025 SrcTy = DestTy;
2227 } 2026 }
2228 emitIASRegOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRRegEmitter); 2027 emitIASRegOpTyGPR(Func, DestTy, Dest, Src, GPRRegEmitter);
2229 return; 2028 return;
2230 } 2029 }
2231 } else { 2030 } else {
2232 // Dest must be Stack and Src *could* be a register. Use Src's type to 2031 // Dest must be Stack and Src *could* be a register. Use Src's type to
2233 // decide on the emitters. 2032 // decide on the emitters.
2234 typename InstX86Base<Machine>::Traits::Address StackAddr( 2033 Address StackAddr(Target->stackVarToAsmOperand(Dest));
2235 Target->stackVarToAsmOperand(Dest));
2236 if (isScalarFloatingType(SrcTy)) { 2034 if (isScalarFloatingType(SrcTy)) {
2237 // Src must be a register. 2035 // Src must be a register.
2238 const auto *SrcVar = llvm::cast<Variable>(Src); 2036 const auto *SrcVar = llvm::cast<Variable>(Src);
2239 assert(SrcVar->hasReg()); 2037 assert(SrcVar->hasReg());
2240 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2038 Assembler *Asm = Func->getAssembler<Assembler>();
2241 Func->getAssembler< 2039 Asm->movss(SrcTy, StackAddr, Traits::getEncodedXmm(SrcVar->getRegNum()));
2242 typename InstX86Base<Machine>::Traits::Assembler>();
2243 Asm->movss(SrcTy, StackAddr, InstX86Base<Machine>::Traits::getEncodedXmm(
2244 SrcVar->getRegNum()));
2245 return; 2040 return;
2246 } else { 2041 } else {
2247 // Src can be a register or immediate. 2042 // Src can be a register or immediate.
2248 assert(isScalarIntegerType(SrcTy)); 2043 assert(isScalarIntegerType(SrcTy));
2249 emitIASAddrOpTyGPR<Machine>(Func, SrcTy, StackAddr, Src, GPRAddrEmitter); 2044 emitIASAddrOpTyGPR(Func, SrcTy, StackAddr, Src, GPRAddrEmitter);
2250 return; 2045 return;
2251 } 2046 }
2252 return; 2047 return;
2253 } 2048 }
2254 } 2049 }
2255 2050
2256 template <class Machine> 2051 template <typename TraitsType>
2257 void InstX86Movd<Machine>::emit(const Cfg *Func) const { 2052 void InstImpl<TraitsType>::InstX86Movd::emit(const Cfg *Func) const {
2258 if (!BuildDefs::dump()) 2053 if (!BuildDefs::dump())
2259 return; 2054 return;
2260 assert(this->getSrcSize() == 1); 2055 assert(this->getSrcSize() == 1);
2261 Variable *Dest = this->getDest(); 2056 Variable *Dest = this->getDest();
2262 Operand *Src = this->getSrc(0); 2057 Operand *Src = this->getSrc(0);
2263 2058
2264 if (Dest->getType() == IceType_i64 || Src->getType() == IceType_i64) { 2059 if (Dest->getType() == IceType_i64 || Src->getType() == IceType_i64) {
2265 assert(Dest->getType() == IceType_f64 || Src->getType() == IceType_f64); 2060 assert(Dest->getType() == IceType_f64 || Src->getType() == IceType_f64);
2266 assert(Dest->getType() != Src->getType()); 2061 assert(Dest->getType() != Src->getType());
2267 Ostream &Str = Func->getContext()->getStrEmit(); 2062 Ostream &Str = Func->getContext()->getStrEmit();
2268 Str << "\t" 2063 Str << "\t"
2269 "movq" 2064 "movq"
2270 "\t"; 2065 "\t";
2271 Src->emit(Func); 2066 Src->emit(Func);
2272 Str << ", "; 2067 Str << ", ";
2273 Dest->emit(Func); 2068 Dest->emit(Func);
2274 return; 2069 return;
2275 } 2070 }
2276 2071
2277 InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Movd>::emit(Func); 2072 InstX86BaseUnaryopXmm<InstX86Base::Movd>::emit(Func);
2278 } 2073 }
2279 2074
2280 template <class Machine> 2075 template <typename TraitsType>
2281 void InstX86Movd<Machine>::emitIAS(const Cfg *Func) const { 2076 void InstImpl<TraitsType>::InstX86Movd::emitIAS(const Cfg *Func) const {
2282 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2077 Assembler *Asm = Func->getAssembler<Assembler>();
2283 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2284 assert(this->getSrcSize() == 1); 2078 assert(this->getSrcSize() == 1);
2285 const Variable *Dest = this->getDest(); 2079 const Variable *Dest = this->getDest();
2286 auto *Target = InstX86Base<Machine>::getTarget(Func); 2080 auto *Target = InstX86Base::getTarget(Func);
2287 // For insert/extract element (one of Src/Dest is an Xmm vector and the other 2081 // For insert/extract element (one of Src/Dest is an Xmm vector and the other
2288 // is an int type). 2082 // is an int type).
2289 if (const auto *SrcVar = llvm::dyn_cast<Variable>(this->getSrc(0))) { 2083 if (const auto *SrcVar = llvm::dyn_cast<Variable>(this->getSrc(0))) {
2290 if (SrcVar->getType() == IceType_i32 || 2084 if (SrcVar->getType() == IceType_i32 ||
2291 (InstX86Base<Machine>::Traits::Is64Bit && 2085 (Traits::Is64Bit && SrcVar->getType() == IceType_i64)) {
2292 SrcVar->getType() == IceType_i64)) {
2293 assert(isVectorType(Dest->getType()) || 2086 assert(isVectorType(Dest->getType()) ||
2294 (isScalarFloatingType(Dest->getType()) && 2087 (isScalarFloatingType(Dest->getType()) &&
2295 typeWidthInBytes(SrcVar->getType()) == 2088 typeWidthInBytes(SrcVar->getType()) ==
2296 typeWidthInBytes(Dest->getType()))); 2089 typeWidthInBytes(Dest->getType())));
2297 assert(Dest->hasReg()); 2090 assert(Dest->hasReg());
2298 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister DestReg = 2091 XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
2299 InstX86Base<Machine>::Traits::getEncodedXmm(Dest->getRegNum());
2300 if (SrcVar->hasReg()) { 2092 if (SrcVar->hasReg()) {
2301 Asm->movd( 2093 Asm->movd(SrcVar->getType(), DestReg,
2302 SrcVar->getType(), DestReg, 2094 Traits::getEncodedGPR(SrcVar->getRegNum()));
2303 InstX86Base<Machine>::Traits::getEncodedGPR(SrcVar->getRegNum()));
2304 } else { 2095 } else {
2305 typename InstX86Base<Machine>::Traits::Address StackAddr( 2096 Address StackAddr(Target->stackVarToAsmOperand(SrcVar));
2306 Target->stackVarToAsmOperand(SrcVar));
2307 Asm->movd(SrcVar->getType(), DestReg, StackAddr); 2097 Asm->movd(SrcVar->getType(), DestReg, StackAddr);
2308 } 2098 }
2309 } else { 2099 } else {
2310 assert(isVectorType(SrcVar->getType()) || 2100 assert(isVectorType(SrcVar->getType()) ||
2311 (isScalarFloatingType(SrcVar->getType()) && 2101 (isScalarFloatingType(SrcVar->getType()) &&
2312 typeWidthInBytes(SrcVar->getType()) == 2102 typeWidthInBytes(SrcVar->getType()) ==
2313 typeWidthInBytes(Dest->getType()))); 2103 typeWidthInBytes(Dest->getType())));
2314 assert(SrcVar->hasReg()); 2104 assert(SrcVar->hasReg());
2315 assert(Dest->getType() == IceType_i32 || 2105 assert(Dest->getType() == IceType_i32 ||
2316 (InstX86Base<Machine>::Traits::Is64Bit && 2106 (Traits::Is64Bit && Dest->getType() == IceType_i64));
2317 Dest->getType() == IceType_i64)); 2107 XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
2318 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
2319 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum());
2320 if (Dest->hasReg()) { 2108 if (Dest->hasReg()) {
2321 Asm->movd(Dest->getType(), InstX86Base<Machine>::Traits::getEncodedGPR( 2109 Asm->movd(Dest->getType(), Traits::getEncodedGPR(Dest->getRegNum()),
2322 Dest->getRegNum()),
2323 SrcReg); 2110 SrcReg);
2324 } else { 2111 } else {
2325 typename InstX86Base<Machine>::Traits::Address StackAddr( 2112 Address StackAddr(Target->stackVarToAsmOperand(Dest));
2326 Target->stackVarToAsmOperand(Dest));
2327 Asm->movd(Dest->getType(), StackAddr, SrcReg); 2113 Asm->movd(Dest->getType(), StackAddr, SrcReg);
2328 } 2114 }
2329 } 2115 }
2330 } else { 2116 } else {
2331 assert(Dest->hasReg()); 2117 assert(Dest->hasReg());
2332 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister DestReg = 2118 XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
2333 InstX86Base<Machine>::Traits::getEncodedXmm(Dest->getRegNum()); 2119 auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
2334 auto *Mem =
2335 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
2336 this->getSrc(0));
2337 Asm->movd(Mem->getType(), DestReg, Mem->toAsmAddress(Asm, Target)); 2120 Asm->movd(Mem->getType(), DestReg, Mem->toAsmAddress(Asm, Target));
2338 } 2121 }
2339 } 2122 }
2340 2123
2341 template <class Machine> 2124 template <typename TraitsType>
2342 void InstX86Movp<Machine>::emit(const Cfg *Func) const { 2125 void InstImpl<TraitsType>::InstX86Movp::emit(const Cfg *Func) const {
2343 if (!BuildDefs::dump()) 2126 if (!BuildDefs::dump())
2344 return; 2127 return;
2345 // TODO(wala,stichnot): movups works with all vector operands, but there 2128 // TODO(wala,stichnot): movups works with all vector operands, but there
2346 // exist other instructions (movaps, movdqa, movdqu) that may perform better, 2129 // exist other instructions (movaps, movdqa, movdqu) that may perform better,
2347 // depending on the data type and alignment of the operands. 2130 // depending on the data type and alignment of the operands.
2348 Ostream &Str = Func->getContext()->getStrEmit(); 2131 Ostream &Str = Func->getContext()->getStrEmit();
2349 assert(this->getSrcSize() == 1); 2132 assert(this->getSrcSize() == 1);
2350 Str << "\t" 2133 Str << "\t"
2351 "movups\t"; 2134 "movups\t";
2352 this->getSrc(0)->emit(Func); 2135 this->getSrc(0)->emit(Func);
2353 Str << ", "; 2136 Str << ", ";
2354 this->getDest()->emit(Func); 2137 this->getDest()->emit(Func);
2355 } 2138 }
2356 2139
2357 template <class Machine> 2140 template <typename TraitsType>
2358 void InstX86Movp<Machine>::emitIAS(const Cfg *Func) const { 2141 void InstImpl<TraitsType>::InstX86Movp::emitIAS(const Cfg *Func) const {
2359 assert(this->getSrcSize() == 1); 2142 assert(this->getSrcSize() == 1);
2360 assert(isVectorType(this->getDest()->getType())); 2143 assert(isVectorType(this->getDest()->getType()));
2361 const Variable *Dest = this->getDest(); 2144 const Variable *Dest = this->getDest();
2362 const Operand *Src = this->getSrc(0); 2145 const Operand *Src = this->getSrc(0);
2363 static const typename InstX86Base< 2146 static const XmmEmitterMovOps Emitter = {
2364 Machine>::Traits::Assembler::XmmEmitterMovOps Emitter = { 2147 &Assembler::movups, &Assembler::movups, &Assembler::movups};
2365 &InstX86Base<Machine>::Traits::Assembler::movups, 2148 emitIASMovlikeXMM(Func, Dest, Src, Emitter);
2366 &InstX86Base<Machine>::Traits::Assembler::movups,
2367 &InstX86Base<Machine>::Traits::Assembler::movups};
2368 emitIASMovlikeXMM<Machine>(Func, Dest, Src, Emitter);
2369 } 2149 }
2370 2150
2371 template <class Machine> 2151 template <typename TraitsType>
2372 void InstX86Movq<Machine>::emit(const Cfg *Func) const { 2152 void InstImpl<TraitsType>::InstX86Movq::emit(const Cfg *Func) const {
2373 if (!BuildDefs::dump()) 2153 if (!BuildDefs::dump())
2374 return; 2154 return;
2375 Ostream &Str = Func->getContext()->getStrEmit(); 2155 Ostream &Str = Func->getContext()->getStrEmit();
2376 assert(this->getSrcSize() == 1); 2156 assert(this->getSrcSize() == 1);
2377 assert(this->getDest()->getType() == IceType_i64 || 2157 assert(this->getDest()->getType() == IceType_i64 ||
2378 this->getDest()->getType() == IceType_f64); 2158 this->getDest()->getType() == IceType_f64);
2379 Str << "\t" 2159 Str << "\t"
2380 "movq" 2160 "movq"
2381 "\t"; 2161 "\t";
2382 this->getSrc(0)->emit(Func); 2162 this->getSrc(0)->emit(Func);
2383 Str << ", "; 2163 Str << ", ";
2384 this->getDest()->emit(Func); 2164 this->getDest()->emit(Func);
2385 } 2165 }
2386 2166
2387 template <class Machine> 2167 template <typename TraitsType>
2388 void InstX86Movq<Machine>::emitIAS(const Cfg *Func) const { 2168 void InstImpl<TraitsType>::InstX86Movq::emitIAS(const Cfg *Func) const {
2389 assert(this->getSrcSize() == 1); 2169 assert(this->getSrcSize() == 1);
2390 assert(this->getDest()->getType() == IceType_i64 || 2170 assert(this->getDest()->getType() == IceType_i64 ||
2391 this->getDest()->getType() == IceType_f64); 2171 this->getDest()->getType() == IceType_f64);
2392 const Variable *Dest = this->getDest(); 2172 const Variable *Dest = this->getDest();
2393 const Operand *Src = this->getSrc(0); 2173 const Operand *Src = this->getSrc(0);
2394 static const typename InstX86Base< 2174 static const XmmEmitterMovOps Emitter = {&Assembler::movq, &Assembler::movq,
2395 Machine>::Traits::Assembler::XmmEmitterMovOps Emitter = { 2175 &Assembler::movq};
2396 &InstX86Base<Machine>::Traits::Assembler::movq, 2176 emitIASMovlikeXMM(Func, Dest, Src, Emitter);
2397 &InstX86Base<Machine>::Traits::Assembler::movq,
2398 &InstX86Base<Machine>::Traits::Assembler::movq};
2399 emitIASMovlikeXMM<Machine>(Func, Dest, Src, Emitter);
2400 } 2177 }
2401 2178
2402 template <class Machine> 2179 template <typename TraitsType>
2403 void InstX86MovssRegs<Machine>::emitIAS(const Cfg *Func) const { 2180 void InstImpl<TraitsType>::InstX86MovssRegs::emitIAS(const Cfg *Func) const {
2404 // This is Binop variant is only intended to be used for reg-reg moves where 2181 // This is Binop variant is only intended to be used for reg-reg moves where
2405 // part of the Dest register is untouched. 2182 // part of the Dest register is untouched.
2406 assert(this->getSrcSize() == 2); 2183 assert(this->getSrcSize() == 2);
2407 const Variable *Dest = this->getDest(); 2184 const Variable *Dest = this->getDest();
2408 assert(Dest == this->getSrc(0)); 2185 assert(Dest == this->getSrc(0));
2409 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1)); 2186 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
2410 assert(Dest->hasReg() && SrcVar->hasReg()); 2187 assert(Dest->hasReg() && SrcVar->hasReg());
2411 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2188 Assembler *Asm = Func->getAssembler<Assembler>();
2412 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); 2189 Asm->movss(IceType_f32, Traits::getEncodedXmm(Dest->getRegNum()),
2413 Asm->movss(IceType_f32, 2190 Traits::getEncodedXmm(SrcVar->getRegNum()));
2414 InstX86Base<Machine>::Traits::getEncodedXmm(Dest->getRegNum()),
2415 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum()));
2416 } 2191 }
2417 2192
2418 template <class Machine> 2193 template <typename TraitsType>
2419 void InstX86Movsx<Machine>::emitIAS(const Cfg *Func) const { 2194 void InstImpl<TraitsType>::InstX86Movsx::emitIAS(const Cfg *Func) const {
2420 assert(this->getSrcSize() == 1); 2195 assert(this->getSrcSize() == 1);
2421 const Variable *Dest = this->getDest(); 2196 const Variable *Dest = this->getDest();
2422 const Operand *Src = this->getSrc(0); 2197 const Operand *Src = this->getSrc(0);
2423 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice we just 2198 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice we just
2424 // use the full register for Dest to avoid having an OperandSizeOverride 2199 // use the full register for Dest to avoid having an OperandSizeOverride
2425 // prefix. It also allows us to only dispatch on SrcTy. 2200 // prefix. It also allows us to only dispatch on SrcTy.
2426 Type SrcTy = Src->getType(); 2201 Type SrcTy = Src->getType();
2427 assert(typeWidthInBytes(Dest->getType()) > 1); 2202 assert(typeWidthInBytes(Dest->getType()) > 1);
2428 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); 2203 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2429 emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src, 2204 emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, this->Emitter);
2430 this->Emitter);
2431 } 2205 }
2432 2206
2433 template <class Machine> 2207 template <typename TraitsType>
2434 void InstX86Movzx<Machine>::emit(const Cfg *Func) const { 2208 void InstImpl<TraitsType>::InstX86Movzx::emit(const Cfg *Func) const {
2435 if (!BuildDefs::dump()) 2209 if (!BuildDefs::dump())
2436 return; 2210 return;
2437 if (InstX86Base<Machine>::Traits::Is64Bit) { 2211 if (Traits::Is64Bit) {
2438 // There's no movzx %eXX, %rXX. To zero extend 32- to 64-bits, we emit a 2212 // There's no movzx %eXX, %rXX. To zero extend 32- to 64-bits, we emit a
2439 // mov %eXX, %eXX. The processor will still do a movzx[bw]q. 2213 // mov %eXX, %eXX. The processor will still do a movzx[bw]q.
2440 assert(this->getSrcSize() == 1); 2214 assert(this->getSrcSize() == 1);
2441 const Operand *Src = this->getSrc(0); 2215 const Operand *Src = this->getSrc(0);
2442 const Variable *Dest = this->Dest; 2216 const Variable *Dest = this->Dest;
2443 if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64) { 2217 if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64) {
2444 Ostream &Str = Func->getContext()->getStrEmit(); 2218 Ostream &Str = Func->getContext()->getStrEmit();
2445 Str << "\t" 2219 Str << "\t"
2446 "mov" 2220 "mov"
2447 "\t"; 2221 "\t";
2448 Src->emit(Func); 2222 Src->emit(Func);
2449 Str << ", "; 2223 Str << ", ";
2450 Dest->asType(IceType_i32, InstX86Base<Machine>::Traits::getGprForType( 2224 Dest->asType(IceType_i32,
2451 IceType_i32, Dest->getRegNum())) 2225 Traits::getGprForType(IceType_i32, Dest->getRegNum()))
2452 ->emit(Func); 2226 ->emit(Func);
2453 Str << " /* movzx */"; 2227 Str << " /* movzx */";
2454 return; 2228 return;
2455 } 2229 }
2456 } 2230 }
2457 InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movzx>::emit(Func); 2231 InstX86BaseUnaryopGPR<InstX86Base::Movzx>::emit(Func);
2458 } 2232 }
2459 2233
2460 template <class Machine> 2234 template <typename TraitsType>
2461 void InstX86Movzx<Machine>::emitIAS(const Cfg *Func) const { 2235 void InstImpl<TraitsType>::InstX86Movzx::emitIAS(const Cfg *Func) const {
2462 assert(this->getSrcSize() == 1); 2236 assert(this->getSrcSize() == 1);
2463 const Variable *Dest = this->getDest(); 2237 const Variable *Dest = this->getDest();
2464 const Operand *Src = this->getSrc(0); 2238 const Operand *Src = this->getSrc(0);
2465 Type SrcTy = Src->getType(); 2239 Type SrcTy = Src->getType();
2466 assert(typeWidthInBytes(Dest->getType()) > 1); 2240 assert(typeWidthInBytes(Dest->getType()) > 1);
2467 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); 2241 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2468 emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src, 2242 emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, this->Emitter);
2469 this->Emitter);
2470 } 2243 }
2471 2244
2472 template <class Machine> void InstX86Nop<Machine>::emit(const Cfg *Func) const { 2245 template <typename TraitsType>
2246 void InstImpl<TraitsType>::InstX86Nop::emit(const Cfg *Func) const {
2473 if (!BuildDefs::dump()) 2247 if (!BuildDefs::dump())
2474 return; 2248 return;
2475 Ostream &Str = Func->getContext()->getStrEmit(); 2249 Ostream &Str = Func->getContext()->getStrEmit();
2476 // TODO: Emit the right code for each variant. 2250 // TODO: Emit the right code for each variant.
2477 Str << "\t" 2251 Str << "\t"
2478 "nop\t/* variant = " << Variant << " */"; 2252 "nop\t/* variant = " << Variant << " */";
2479 } 2253 }
2480 2254
2481 template <class Machine> 2255 template <typename TraitsType>
2482 void InstX86Nop<Machine>::emitIAS(const Cfg *Func) const { 2256 void InstImpl<TraitsType>::InstX86Nop::emitIAS(const Cfg *Func) const {
2483 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2257 Assembler *Asm = Func->getAssembler<Assembler>();
2484 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2485 // TODO: Emit the right code for the variant. 2258 // TODO: Emit the right code for the variant.
2486 Asm->nop(); 2259 Asm->nop();
2487 } 2260 }
2488 2261
2489 template <class Machine> void InstX86Nop<Machine>::dump(const Cfg *Func) const { 2262 template <typename TraitsType>
2263 void InstImpl<TraitsType>::InstX86Nop::dump(const Cfg *Func) const {
2490 if (!BuildDefs::dump()) 2264 if (!BuildDefs::dump())
2491 return; 2265 return;
2492 Ostream &Str = Func->getContext()->getStrDump(); 2266 Ostream &Str = Func->getContext()->getStrDump();
2493 Str << "nop (variant = " << Variant << ")"; 2267 Str << "nop (variant = " << Variant << ")";
2494 } 2268 }
2495 2269
2496 template <class Machine> void InstX86Fld<Machine>::emit(const Cfg *Func) const { 2270 template <typename TraitsType>
2271 void InstImpl<TraitsType>::InstX86Fld::emit(const Cfg *Func) const {
2497 if (!BuildDefs::dump()) 2272 if (!BuildDefs::dump())
2498 return; 2273 return;
2499 Ostream &Str = Func->getContext()->getStrEmit(); 2274 Ostream &Str = Func->getContext()->getStrEmit();
2500 assert(this->getSrcSize() == 1); 2275 assert(this->getSrcSize() == 1);
2501 Type Ty = this->getSrc(0)->getType(); 2276 Type Ty = this->getSrc(0)->getType();
2502 const auto *Var = llvm::dyn_cast<Variable>(this->getSrc(0)); 2277 const auto *Var = llvm::dyn_cast<Variable>(this->getSrc(0));
2503 if (Var && Var->hasReg()) { 2278 if (Var && Var->hasReg()) {
2504 // This is a physical xmm register, so we need to spill it to a temporary 2279 // This is a physical xmm register, so we need to spill it to a temporary
2505 // stack slot. Function prolog emission guarantees that there is sufficient 2280 // stack slot. Function prolog emission guarantees that there is sufficient
2506 // space to do this. 2281 // space to do this.
2507 Str << "\t" 2282 Str << "\t"
2508 "mov" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString 2283 "mov" << Traits::TypeAttributes[Ty].SdSsString << "\t";
2509 << "\t";
2510 Var->emit(Func); 2284 Var->emit(Func);
2511 Str << ", (%esp)\n" 2285 Str << ", (%esp)\n"
2512 "\t" 2286 "\t"
2513 "fld" << this->getFldString(Ty) << "\t" 2287 "fld" << this->getFldString(Ty) << "\t"
2514 "(%esp)"; 2288 "(%esp)";
2515 return; 2289 return;
2516 } 2290 }
2517 Str << "\t" 2291 Str << "\t"
2518 "fld" << this->getFldString(Ty) << "\t"; 2292 "fld" << this->getFldString(Ty) << "\t";
2519 this->getSrc(0)->emit(Func); 2293 this->getSrc(0)->emit(Func);
2520 } 2294 }
2521 2295
2522 template <class Machine> 2296 template <typename TraitsType>
2523 void InstX86Fld<Machine>::emitIAS(const Cfg *Func) const { 2297 void InstImpl<TraitsType>::InstX86Fld::emitIAS(const Cfg *Func) const {
2524 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2298 Assembler *Asm = Func->getAssembler<Assembler>();
2525 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2526 assert(this->getSrcSize() == 1); 2299 assert(this->getSrcSize() == 1);
2527 const Operand *Src = this->getSrc(0); 2300 const Operand *Src = this->getSrc(0);
2528 auto *Target = InstX86Base<Machine>::getTarget(Func); 2301 auto *Target = InstX86Base::getTarget(Func);
2529 Type Ty = Src->getType(); 2302 Type Ty = Src->getType();
2530 if (const auto *Var = llvm::dyn_cast<Variable>(Src)) { 2303 if (const auto *Var = llvm::dyn_cast<Variable>(Src)) {
2531 if (Var->hasReg()) { 2304 if (Var->hasReg()) {
2532 // This is a physical xmm register, so we need to spill it to a temporary 2305 // This is a physical xmm register, so we need to spill it to a temporary
2533 // stack slot. Function prolog emission guarantees that there is 2306 // stack slot. Function prolog emission guarantees that there is
2534 // sufficient space to do this. 2307 // sufficient space to do this.
2535 typename InstX86Base<Machine>::Traits::Address StackSlot = 2308 Address StackSlot =
2536 typename InstX86Base<Machine>::Traits::Address( 2309 Address(RegisterSet::Encoded_Reg_esp, 0, AssemblerFixup::NoFixup);
2537 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0, 2310 Asm->movss(Ty, StackSlot, Traits::getEncodedXmm(Var->getRegNum()));
2538 AssemblerFixup::NoFixup);
2539 Asm->movss(Ty, StackSlot,
2540 InstX86Base<Machine>::Traits::getEncodedXmm(Var->getRegNum()));
2541 Asm->fld(Ty, StackSlot); 2311 Asm->fld(Ty, StackSlot);
2542 } else { 2312 } else {
2543 typename InstX86Base<Machine>::Traits::Address StackAddr( 2313 Address StackAddr(Target->stackVarToAsmOperand(Var));
2544 Target->stackVarToAsmOperand(Var));
2545 Asm->fld(Ty, StackAddr); 2314 Asm->fld(Ty, StackAddr);
2546 } 2315 }
2547 } else if (const auto *Mem = llvm::dyn_cast< 2316 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
2548 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) { 2317 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
2549 assert(Mem->getSegmentRegister() ==
2550 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2551 Asm->fld(Ty, Mem->toAsmAddress(Asm, Target)); 2318 Asm->fld(Ty, Mem->toAsmAddress(Asm, Target));
2552 } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) { 2319 } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) {
2553 Asm->fld(Ty, InstX86Base<Machine>::Traits::Address::ofConstPool(Asm, Imm)); 2320 Asm->fld(Ty, Traits::Address::ofConstPool(Asm, Imm));
2554 } else { 2321 } else {
2555 llvm_unreachable("Unexpected operand type"); 2322 llvm_unreachable("Unexpected operand type");
2556 } 2323 }
2557 } 2324 }
2558 2325
2559 template <class Machine> void InstX86Fld<Machine>::dump(const Cfg *Func) const { 2326 template <typename TraitsType>
2327 void InstImpl<TraitsType>::InstX86Fld::dump(const Cfg *Func) const {
2560 if (!BuildDefs::dump()) 2328 if (!BuildDefs::dump())
2561 return; 2329 return;
2562 Ostream &Str = Func->getContext()->getStrDump(); 2330 Ostream &Str = Func->getContext()->getStrDump();
2563 Str << "fld." << this->getSrc(0)->getType() << " "; 2331 Str << "fld." << this->getSrc(0)->getType() << " ";
2564 this->dumpSources(Func); 2332 this->dumpSources(Func);
2565 } 2333 }
2566 2334
2567 template <class Machine> 2335 template <typename TraitsType>
2568 void InstX86Fstp<Machine>::emit(const Cfg *Func) const { 2336 void InstImpl<TraitsType>::InstX86Fstp::emit(const Cfg *Func) const {
2569 if (!BuildDefs::dump()) 2337 if (!BuildDefs::dump())
2570 return; 2338 return;
2571 Ostream &Str = Func->getContext()->getStrEmit(); 2339 Ostream &Str = Func->getContext()->getStrEmit();
2572 assert(this->getSrcSize() == 0); 2340 assert(this->getSrcSize() == 0);
2573 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to 2341 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
2574 // "partially" delete the fstp if the Dest is unused. Even if Dest is unused, 2342 // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
2575 // the fstp should be kept for the SideEffects of popping the stack. 2343 // the fstp should be kept for the SideEffects of popping the stack.
2576 if (!this->getDest()) { 2344 if (!this->getDest()) {
2577 Str << "\t" 2345 Str << "\t"
2578 "fstp\t" 2346 "fstp\t"
2579 "st(0)"; 2347 "st(0)";
2580 return; 2348 return;
2581 } 2349 }
2582 Type Ty = this->getDest()->getType(); 2350 Type Ty = this->getDest()->getType();
2583 if (!this->getDest()->hasReg()) { 2351 if (!this->getDest()->hasReg()) {
2584 Str << "\t" 2352 Str << "\t"
2585 "fstp" << this->getFldString(Ty) << "\t"; 2353 "fstp" << this->getFldString(Ty) << "\t";
2586 this->getDest()->emit(Func); 2354 this->getDest()->emit(Func);
2587 return; 2355 return;
2588 } 2356 }
2589 // Dest is a physical (xmm) register, so st(0) needs to go through memory. 2357 // Dest is a physical (xmm) register, so st(0) needs to go through memory.
2590 // Hack this by using caller-reserved memory at the top of stack, spilling 2358 // Hack this by using caller-reserved memory at the top of stack, spilling
2591 // st(0) there, and loading it into the xmm register. 2359 // st(0) there, and loading it into the xmm register.
2592 Str << "\t" 2360 Str << "\t"
2593 "fstp" << this->getFldString(Ty) << "\t" 2361 "fstp" << this->getFldString(Ty) << "\t"
2594 "(%esp)\n"; 2362 "(%esp)\n";
2595 Str << "\t" 2363 Str << "\t"
2596 "mov" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString 2364 "mov" << Traits::TypeAttributes[Ty].SdSsString << "\t"
2597 << "\t" 2365 "(%esp), ";
2598 "(%esp), ";
2599 this->getDest()->emit(Func); 2366 this->getDest()->emit(Func);
2600 } 2367 }
2601 2368
2602 template <class Machine> 2369 template <typename TraitsType>
2603 void InstX86Fstp<Machine>::emitIAS(const Cfg *Func) const { 2370 void InstImpl<TraitsType>::InstX86Fstp::emitIAS(const Cfg *Func) const {
2604 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2371 Assembler *Asm = Func->getAssembler<Assembler>();
2605 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2606 assert(this->getSrcSize() == 0); 2372 assert(this->getSrcSize() == 0);
2607 const Variable *Dest = this->getDest(); 2373 const Variable *Dest = this->getDest();
2608 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to 2374 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
2609 // "partially" delete the fstp if the Dest is unused. Even if Dest is unused, 2375 // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
2610 // the fstp should be kept for the SideEffects of popping the stack. 2376 // the fstp should be kept for the SideEffects of popping the stack.
2611 if (!Dest) { 2377 if (!Dest) {
2612 Asm->fstp(InstX86Base<Machine>::Traits::RegisterSet::getEncodedSTReg(0)); 2378 Asm->fstp(RegisterSet::getEncodedSTReg(0));
2613 return; 2379 return;
2614 } 2380 }
2615 auto *Target = InstX86Base<Machine>::getTarget(Func); 2381 auto *Target = InstX86Base::getTarget(Func);
2616 Type Ty = Dest->getType(); 2382 Type Ty = Dest->getType();
2617 if (!Dest->hasReg()) { 2383 if (!Dest->hasReg()) {
2618 typename InstX86Base<Machine>::Traits::Address StackAddr( 2384 Address StackAddr(Target->stackVarToAsmOperand(Dest));
2619 Target->stackVarToAsmOperand(Dest));
2620 Asm->fstp(Ty, StackAddr); 2385 Asm->fstp(Ty, StackAddr);
2621 } else { 2386 } else {
2622 // Dest is a physical (xmm) register, so st(0) needs to go through memory. 2387 // Dest is a physical (xmm) register, so st(0) needs to go through memory.
2623 // Hack this by using caller-reserved memory at the top of stack, spilling 2388 // Hack this by using caller-reserved memory at the top of stack, spilling
2624 // st(0) there, and loading it into the xmm register. 2389 // st(0) there, and loading it into the xmm register.
2625 typename InstX86Base<Machine>::Traits::Address StackSlot = 2390 Address StackSlot =
2626 typename InstX86Base<Machine>::Traits::Address( 2391 Address(RegisterSet::Encoded_Reg_esp, 0, AssemblerFixup::NoFixup);
2627 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0,
2628 AssemblerFixup::NoFixup);
2629 Asm->fstp(Ty, StackSlot); 2392 Asm->fstp(Ty, StackSlot);
2630 Asm->movss(Ty, 2393 Asm->movss(Ty, Traits::getEncodedXmm(Dest->getRegNum()), StackSlot);
2631 InstX86Base<Machine>::Traits::getEncodedXmm(Dest->getRegNum()),
2632 StackSlot);
2633 } 2394 }
2634 } 2395 }
2635 2396
2636 template <class Machine> 2397 template <typename TraitsType>
2637 void InstX86Fstp<Machine>::dump(const Cfg *Func) const { 2398 void InstImpl<TraitsType>::InstX86Fstp::dump(const Cfg *Func) const {
2638 if (!BuildDefs::dump()) 2399 if (!BuildDefs::dump())
2639 return; 2400 return;
2640 Ostream &Str = Func->getContext()->getStrDump(); 2401 Ostream &Str = Func->getContext()->getStrDump();
2641 this->dumpDest(Func); 2402 this->dumpDest(Func);
2642 Str << " = fstp." << this->getDest()->getType() << ", st(0)"; 2403 Str << " = fstp." << this->getDest()->getType() << ", st(0)";
2643 } 2404 }
2644 2405
2645 template <class Machine> 2406 template <typename TraitsType>
2646 void InstX86Pextr<Machine>::emit(const Cfg *Func) const { 2407 void InstImpl<TraitsType>::InstX86Pextr::emit(const Cfg *Func) const {
2647 if (!BuildDefs::dump()) 2408 if (!BuildDefs::dump())
2648 return; 2409 return;
2649 Ostream &Str = Func->getContext()->getStrEmit(); 2410 Ostream &Str = Func->getContext()->getStrEmit();
2650 assert(this->getSrcSize() == 2); 2411 assert(this->getSrcSize() == 2);
2651 // pextrb and pextrd are SSE4.1 instructions. 2412 // pextrb and pextrd are SSE4.1 instructions.
2652 Str << "\t" << this->Opcode 2413 Str << "\t" << this->Opcode
2653 << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0) 2414 << Traits::TypeAttributes[this->getSrc(0)->getType()].PackString << "\t";
2654 ->getType()]
2655 .PackString << "\t";
2656 this->getSrc(1)->emit(Func); 2415 this->getSrc(1)->emit(Func);
2657 Str << ", "; 2416 Str << ", ";
2658 this->getSrc(0)->emit(Func); 2417 this->getSrc(0)->emit(Func);
2659 Str << ", "; 2418 Str << ", ";
2660 Variable *Dest = this->getDest(); 2419 Variable *Dest = this->getDest();
2661 // pextrw must take a register dest. There is an SSE4.1 version that takes a 2420 // pextrw must take a register dest. There is an SSE4.1 version that takes a
2662 // memory dest, but we aren't using it. For uniformity, just restrict them 2421 // memory dest, but we aren't using it. For uniformity, just restrict them
2663 // all to have a register dest for now. 2422 // all to have a register dest for now.
2664 assert(Dest->hasReg()); 2423 assert(Dest->hasReg());
2665 Dest->asType(IceType_i32, Dest->getRegNum())->emit(Func); 2424 Dest->asType(IceType_i32, Dest->getRegNum())->emit(Func);
2666 } 2425 }
2667 2426
2668 template <class Machine> 2427 template <typename TraitsType>
2669 void InstX86Pextr<Machine>::emitIAS(const Cfg *Func) const { 2428 void InstImpl<TraitsType>::InstX86Pextr::emitIAS(const Cfg *Func) const {
2670 assert(this->getSrcSize() == 2); 2429 assert(this->getSrcSize() == 2);
2671 // pextrb and pextrd are SSE4.1 instructions. 2430 // pextrb and pextrd are SSE4.1 instructions.
2672 const Variable *Dest = this->getDest(); 2431 const Variable *Dest = this->getDest();
2673 Type DispatchTy = InstX86Base<Machine>::Traits::getInVectorElementType( 2432 Type DispatchTy = Traits::getInVectorElementType(this->getSrc(0)->getType());
2674 this->getSrc(0)->getType());
2675 // pextrw must take a register dest. There is an SSE4.1 version that takes a 2433 // pextrw must take a register dest. There is an SSE4.1 version that takes a
2676 // memory dest, but we aren't using it. For uniformity, just restrict them 2434 // memory dest, but we aren't using it. For uniformity, just restrict them
2677 // all to have a register dest for now. 2435 // all to have a register dest for now.
2678 assert(Dest->hasReg()); 2436 assert(Dest->hasReg());
2679 // pextrw's Src(0) must be a register (both SSE4.1 and SSE2). 2437 // pextrw's Src(0) must be a register (both SSE4.1 and SSE2).
2680 assert(llvm::cast<Variable>(this->getSrc(0))->hasReg()); 2438 assert(llvm::cast<Variable>(this->getSrc(0))->hasReg());
2681 static const typename InstX86Base<Machine>::Traits::Assembler:: 2439 static const ThreeOpImmEmitter<GPRRegister, XmmRegister> Emitter = {
2682 template ThreeOpImmEmitter< 2440 &Assembler::pextr, nullptr};
2683 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister, 2441 emitIASThreeOpImmOps<GPRRegister, XmmRegister, Traits::getEncodedGPR,
2684 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister> 2442 Traits::getEncodedXmm>(
2685 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pextr, nullptr};
2686 emitIASThreeOpImmOps<
2687 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
2688 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2689 InstX86Base<Machine>::Traits::getEncodedGPR,
2690 InstX86Base<Machine>::Traits::getEncodedXmm>(
2691 Func, DispatchTy, Dest, this->getSrc(0), this->getSrc(1), Emitter); 2443 Func, DispatchTy, Dest, this->getSrc(0), this->getSrc(1), Emitter);
2692 } 2444 }
2693 2445
2694 template <class Machine> 2446 template <typename TraitsType>
2695 void InstX86Pinsr<Machine>::emit(const Cfg *Func) const { 2447 void InstImpl<TraitsType>::InstX86Pinsr::emit(const Cfg *Func) const {
2696 if (!BuildDefs::dump()) 2448 if (!BuildDefs::dump())
2697 return; 2449 return;
2698 Ostream &Str = Func->getContext()->getStrEmit(); 2450 Ostream &Str = Func->getContext()->getStrEmit();
2699 assert(this->getSrcSize() == 3); 2451 assert(this->getSrcSize() == 3);
2700 Str << "\t" << this->Opcode 2452 Str << "\t" << this->Opcode
2701 << InstX86Base< 2453 << Traits::TypeAttributes[this->getDest()->getType()].PackString << "\t";
2702 Machine>::Traits::TypeAttributes[this->getDest()->getType()]
2703 .PackString << "\t";
2704 this->getSrc(2)->emit(Func); 2454 this->getSrc(2)->emit(Func);
2705 Str << ", "; 2455 Str << ", ";
2706 Operand *Src1 = this->getSrc(1); 2456 Operand *Src1 = this->getSrc(1);
2707 if (const auto *Src1Var = llvm::dyn_cast<Variable>(Src1)) { 2457 if (const auto *Src1Var = llvm::dyn_cast<Variable>(Src1)) {
2708 // If src1 is a register, it should always be r32. 2458 // If src1 is a register, it should always be r32.
2709 if (Src1Var->hasReg()) { 2459 if (Src1Var->hasReg()) {
2710 int32_t NewRegNum = 2460 int32_t NewRegNum = Traits::getBaseReg(Src1Var->getRegNum());
2711 InstX86Base<Machine>::Traits::getBaseReg(Src1Var->getRegNum());
2712 const Variable *NewSrc = Src1Var->asType(IceType_i32, NewRegNum); 2461 const Variable *NewSrc = Src1Var->asType(IceType_i32, NewRegNum);
2713 NewSrc->emit(Func); 2462 NewSrc->emit(Func);
2714 } else { 2463 } else {
2715 Src1Var->emit(Func); 2464 Src1Var->emit(Func);
2716 } 2465 }
2717 } else { 2466 } else {
2718 Src1->emit(Func); 2467 Src1->emit(Func);
2719 } 2468 }
2720 Str << ", "; 2469 Str << ", ";
2721 this->getDest()->emit(Func); 2470 this->getDest()->emit(Func);
2722 } 2471 }
2723 2472
2724 template <class Machine> 2473 template <typename TraitsType>
2725 void InstX86Pinsr<Machine>::emitIAS(const Cfg *Func) const { 2474 void InstImpl<TraitsType>::InstX86Pinsr::emitIAS(const Cfg *Func) const {
2726 assert(this->getSrcSize() == 3); 2475 assert(this->getSrcSize() == 3);
2727 assert(this->getDest() == this->getSrc(0)); 2476 assert(this->getDest() == this->getSrc(0));
2728 // pinsrb and pinsrd are SSE4.1 instructions. 2477 // pinsrb and pinsrd are SSE4.1 instructions.
2729 const Operand *Src0 = this->getSrc(1); 2478 const Operand *Src0 = this->getSrc(1);
2730 Type DispatchTy = Src0->getType(); 2479 Type DispatchTy = Src0->getType();
2731 // If src1 is a register, it should always be r32 (this should fall out from 2480 // If src1 is a register, it should always be r32 (this should fall out from
2732 // the encodings for ByteRegs overlapping the encodings for r32), but we have 2481 // the encodings for ByteRegs overlapping the encodings for r32), but we have
2733 // to make sure the register allocator didn't choose an 8-bit high register 2482 // to make sure the register allocator didn't choose an 8-bit high register
2734 // like "ah". 2483 // like "ah".
2735 if (BuildDefs::asserts()) { 2484 if (BuildDefs::asserts()) {
2736 if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) { 2485 if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
2737 if (Src0Var->hasReg()) { 2486 if (Src0Var->hasReg()) {
2738 int32_t RegNum = Src0Var->getRegNum(); 2487 int32_t RegNum = Src0Var->getRegNum();
2739 int32_t BaseRegNum = InstX86Base<Machine>::Traits::getBaseReg(RegNum); 2488 int32_t BaseRegNum = Traits::getBaseReg(RegNum);
2740 (void)BaseRegNum; 2489 (void)BaseRegNum;
2741 assert(InstX86Base<Machine>::Traits::getEncodedGPR(RegNum) == 2490 assert(Traits::getEncodedGPR(RegNum) ==
2742 InstX86Base<Machine>::Traits::getEncodedGPR(BaseRegNum)); 2491 Traits::getEncodedGPR(BaseRegNum));
2743 } 2492 }
2744 } 2493 }
2745 } 2494 }
2746 static const typename InstX86Base<Machine>::Traits::Assembler:: 2495 static const ThreeOpImmEmitter<XmmRegister, GPRRegister> Emitter = {
2747 template ThreeOpImmEmitter< 2496 &Assembler::pinsr, &Assembler::pinsr};
2748 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister, 2497 emitIASThreeOpImmOps<XmmRegister, GPRRegister, Traits::getEncodedXmm,
2749 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister> 2498 Traits::getEncodedGPR>(Func, DispatchTy, this->getDest(),
2750 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pinsr, 2499 Src0, this->getSrc(2), Emitter);
2751 &InstX86Base<Machine>::Traits::Assembler::pinsr};
2752 emitIASThreeOpImmOps<
2753 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2754 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
2755 InstX86Base<Machine>::Traits::getEncodedXmm,
2756 InstX86Base<Machine>::Traits::getEncodedGPR>(
2757 Func, DispatchTy, this->getDest(), Src0, this->getSrc(2), Emitter);
2758 } 2500 }
2759 2501
2760 template <class Machine> 2502 template <typename TraitsType>
2761 void InstX86Pshufd<Machine>::emitIAS(const Cfg *Func) const { 2503 void InstImpl<TraitsType>::InstX86Pshufd::emitIAS(const Cfg *Func) const {
2762 assert(this->getSrcSize() == 2); 2504 assert(this->getSrcSize() == 2);
2763 const Variable *Dest = this->getDest(); 2505 const Variable *Dest = this->getDest();
2764 Type Ty = Dest->getType(); 2506 Type Ty = Dest->getType();
2765 static const typename InstX86Base<Machine>::Traits::Assembler:: 2507 static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
2766 template ThreeOpImmEmitter< 2508 &Assembler::pshufd, &Assembler::pshufd};
2767 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister, 2509 emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
2768 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister> 2510 Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
2769 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pshufd, 2511 this->getSrc(1), Emitter);
2770 &InstX86Base<Machine>::Traits::Assembler::pshufd};
2771 emitIASThreeOpImmOps<
2772 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2773 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2774 InstX86Base<Machine>::Traits::getEncodedXmm,
2775 InstX86Base<Machine>::Traits::getEncodedXmm>(
2776 Func, Ty, Dest, this->getSrc(0), this->getSrc(1), Emitter);
2777 } 2512 }
2778 2513
2779 template <class Machine> 2514 template <typename TraitsType>
2780 void InstX86Shufps<Machine>::emitIAS(const Cfg *Func) const { 2515 void InstImpl<TraitsType>::InstX86Shufps::emitIAS(const Cfg *Func) const {
2781 assert(this->getSrcSize() == 3); 2516 assert(this->getSrcSize() == 3);
2782 const Variable *Dest = this->getDest(); 2517 const Variable *Dest = this->getDest();
2783 assert(Dest == this->getSrc(0)); 2518 assert(Dest == this->getSrc(0));
2784 Type Ty = Dest->getType(); 2519 Type Ty = Dest->getType();
2785 static const typename InstX86Base<Machine>::Traits::Assembler:: 2520 static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
2786 template ThreeOpImmEmitter< 2521 &Assembler::shufps, &Assembler::shufps};
2787 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister, 2522 emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
2788 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister> 2523 Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
2789 Emitter = {&InstX86Base<Machine>::Traits::Assembler::shufps, 2524 this->getSrc(2), Emitter);
2790 &InstX86Base<Machine>::Traits::Assembler::shufps};
2791 emitIASThreeOpImmOps<
2792 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2793 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2794 InstX86Base<Machine>::Traits::getEncodedXmm,
2795 InstX86Base<Machine>::Traits::getEncodedXmm>(
2796 Func, Ty, Dest, this->getSrc(1), this->getSrc(2), Emitter);
2797 } 2525 }
2798 2526
2799 template <class Machine> void InstX86Pop<Machine>::emit(const Cfg *Func) const { 2527 template <typename TraitsType>
2528 void InstImpl<TraitsType>::InstX86Pop::emit(const Cfg *Func) const {
2800 if (!BuildDefs::dump()) 2529 if (!BuildDefs::dump())
2801 return; 2530 return;
2802 Ostream &Str = Func->getContext()->getStrEmit(); 2531 Ostream &Str = Func->getContext()->getStrEmit();
2803 assert(this->getSrcSize() == 0); 2532 assert(this->getSrcSize() == 0);
2804 Str << "\t" 2533 Str << "\t"
2805 "pop\t"; 2534 "pop\t";
2806 this->getDest()->emit(Func); 2535 this->getDest()->emit(Func);
2807 } 2536 }
2808 2537
2809 template <class Machine> 2538 template <typename TraitsType>
2810 void InstX86Pop<Machine>::emitIAS(const Cfg *Func) const { 2539 void InstImpl<TraitsType>::InstX86Pop::emitIAS(const Cfg *Func) const {
2811 assert(this->getSrcSize() == 0); 2540 assert(this->getSrcSize() == 0);
2812 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2541 Assembler *Asm = Func->getAssembler<Assembler>();
2813 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2814 if (this->getDest()->hasReg()) { 2542 if (this->getDest()->hasReg()) {
2815 Asm->popl(InstX86Base<Machine>::Traits::getEncodedGPR( 2543 Asm->popl(Traits::getEncodedGPR(this->getDest()->getRegNum()));
2816 this->getDest()->getRegNum()));
2817 } else { 2544 } else {
2818 auto *Target = InstX86Base<Machine>::getTarget(Func); 2545 auto *Target = InstX86Base::getTarget(Func);
2819 Asm->popl(Target->stackVarToAsmOperand(this->getDest())); 2546 Asm->popl(Target->stackVarToAsmOperand(this->getDest()));
2820 } 2547 }
2821 } 2548 }
2822 2549
2823 template <class Machine> void InstX86Pop<Machine>::dump(const Cfg *Func) const { 2550 template <typename TraitsType>
2551 void InstImpl<TraitsType>::InstX86Pop::dump(const Cfg *Func) const {
2824 if (!BuildDefs::dump()) 2552 if (!BuildDefs::dump())
2825 return; 2553 return;
2826 Ostream &Str = Func->getContext()->getStrDump(); 2554 Ostream &Str = Func->getContext()->getStrDump();
2827 this->dumpDest(Func); 2555 this->dumpDest(Func);
2828 Str << " = pop." << this->getDest()->getType() << " "; 2556 Str << " = pop." << this->getDest()->getType() << " ";
2829 } 2557 }
2830 2558
2831 template <class Machine> 2559 template <typename TraitsType>
2832 void InstX86Push<Machine>::emit(const Cfg *Func) const { 2560 void InstImpl<TraitsType>::InstX86Push::emit(const Cfg *Func) const {
2833 if (!BuildDefs::dump()) 2561 if (!BuildDefs::dump())
2834 return; 2562 return;
2835 Ostream &Str = Func->getContext()->getStrEmit(); 2563 Ostream &Str = Func->getContext()->getStrEmit();
2836 assert(this->getSrcSize() == 1); 2564 assert(this->getSrcSize() == 1);
2837 // Push is currently only used for saving GPRs. 2565 // Push is currently only used for saving GPRs.
2838 const auto *Var = llvm::cast<Variable>(this->getSrc(0)); 2566 const auto *Var = llvm::cast<Variable>(this->getSrc(0));
2839 assert(Var->hasReg()); 2567 assert(Var->hasReg());
2840 Str << "\t" 2568 Str << "\t"
2841 "push\t"; 2569 "push\t";
2842 Var->emit(Func); 2570 Var->emit(Func);
2843 } 2571 }
2844 2572
2845 template <class Machine> 2573 template <typename TraitsType>
2846 void InstX86Push<Machine>::emitIAS(const Cfg *Func) const { 2574 void InstImpl<TraitsType>::InstX86Push::emitIAS(const Cfg *Func) const {
2847 assert(this->getSrcSize() == 1); 2575 assert(this->getSrcSize() == 1);
2848 // Push is currently only used for saving GPRs. 2576 // Push is currently only used for saving GPRs.
2849 const auto *Var = llvm::cast<Variable>(this->getSrc(0)); 2577 const auto *Var = llvm::cast<Variable>(this->getSrc(0));
2850 assert(Var->hasReg()); 2578 assert(Var->hasReg());
2851 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2579 Assembler *Asm = Func->getAssembler<Assembler>();
2852 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); 2580 Asm->pushl(Traits::getEncodedGPR(Var->getRegNum()));
2853 Asm->pushl(InstX86Base<Machine>::Traits::getEncodedGPR(Var->getRegNum()));
2854 } 2581 }
2855 2582
2856 template <class Machine> 2583 template <typename TraitsType>
2857 void InstX86Push<Machine>::dump(const Cfg *Func) const { 2584 void InstImpl<TraitsType>::InstX86Push::dump(const Cfg *Func) const {
2858 if (!BuildDefs::dump()) 2585 if (!BuildDefs::dump())
2859 return; 2586 return;
2860 Ostream &Str = Func->getContext()->getStrDump(); 2587 Ostream &Str = Func->getContext()->getStrDump();
2861 Str << "push." << this->getSrc(0)->getType() << " "; 2588 Str << "push." << this->getSrc(0)->getType() << " ";
2862 this->dumpSources(Func); 2589 this->dumpSources(Func);
2863 } 2590 }
2864 2591
2865 template <class Machine> void InstX86Ret<Machine>::emit(const Cfg *Func) const { 2592 template <typename TraitsType>
2593 void InstImpl<TraitsType>::InstX86Ret::emit(const Cfg *Func) const {
2866 if (!BuildDefs::dump()) 2594 if (!BuildDefs::dump())
2867 return; 2595 return;
2868 Ostream &Str = Func->getContext()->getStrEmit(); 2596 Ostream &Str = Func->getContext()->getStrEmit();
2869 Str << "\t" 2597 Str << "\t"
2870 "ret"; 2598 "ret";
2871 } 2599 }
2872 2600
2873 template <class Machine> 2601 template <typename TraitsType>
2874 void InstX86Ret<Machine>::emitIAS(const Cfg *Func) const { 2602 void InstImpl<TraitsType>::InstX86Ret::emitIAS(const Cfg *Func) const {
2875 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2603 Assembler *Asm = Func->getAssembler<Assembler>();
2876 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2877 Asm->ret(); 2604 Asm->ret();
2878 } 2605 }
2879 2606
2880 template <class Machine> void InstX86Ret<Machine>::dump(const Cfg *Func) const { 2607 template <typename TraitsType>
2608 void InstImpl<TraitsType>::InstX86Ret::dump(const Cfg *Func) const {
2881 if (!BuildDefs::dump()) 2609 if (!BuildDefs::dump())
2882 return; 2610 return;
2883 Ostream &Str = Func->getContext()->getStrDump(); 2611 Ostream &Str = Func->getContext()->getStrDump();
2884 Type Ty = 2612 Type Ty =
2885 (this->getSrcSize() == 0 ? IceType_void : this->getSrc(0)->getType()); 2613 (this->getSrcSize() == 0 ? IceType_void : this->getSrc(0)->getType());
2886 Str << "ret." << Ty << " "; 2614 Str << "ret." << Ty << " ";
2887 this->dumpSources(Func); 2615 this->dumpSources(Func);
2888 } 2616 }
2889 2617
2890 template <class Machine> 2618 template <typename TraitsType>
2891 void InstX86Setcc<Machine>::emit(const Cfg *Func) const { 2619 void InstImpl<TraitsType>::InstX86Setcc::emit(const Cfg *Func) const {
2892 if (!BuildDefs::dump()) 2620 if (!BuildDefs::dump())
2893 return; 2621 return;
2894 Ostream &Str = Func->getContext()->getStrEmit(); 2622 Ostream &Str = Func->getContext()->getStrEmit();
2895 Str << "\t" 2623 Str << "\t"
2896 "set" 2624 "set" << Traits::InstBrAttributes[Condition].DisplayString << "\t";
2897 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
2898 << "\t";
2899 this->Dest->emit(Func); 2625 this->Dest->emit(Func);
2900 } 2626 }
2901 2627
2902 template <class Machine> 2628 template <typename TraitsType>
2903 void InstX86Setcc<Machine>::emitIAS(const Cfg *Func) const { 2629 void InstImpl<TraitsType>::InstX86Setcc::emitIAS(const Cfg *Func) const {
2904 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None); 2630 assert(Condition != Cond::Br_None);
2905 assert(this->getDest()->getType() == IceType_i1); 2631 assert(this->getDest()->getType() == IceType_i1);
2906 assert(this->getSrcSize() == 0); 2632 assert(this->getSrcSize() == 0);
2907 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2633 Assembler *Asm = Func->getAssembler<Assembler>();
2908 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); 2634 auto *Target = InstX86Base::getTarget(Func);
2909 auto *Target = InstX86Base<Machine>::getTarget(Func);
2910 if (this->getDest()->hasReg()) 2635 if (this->getDest()->hasReg())
2911 Asm->setcc(Condition, InstX86Base<Machine>::Traits::getEncodedByteReg( 2636 Asm->setcc(Condition,
2912 this->getDest()->getRegNum())); 2637 Traits::getEncodedByteReg(this->getDest()->getRegNum()));
2913 else 2638 else
2914 Asm->setcc(Condition, Target->stackVarToAsmOperand(this->getDest())); 2639 Asm->setcc(Condition, Target->stackVarToAsmOperand(this->getDest()));
2915 return; 2640 return;
2916 } 2641 }
2917 2642
2918 template <class Machine> 2643 template <typename TraitsType>
2919 void InstX86Setcc<Machine>::dump(const Cfg *Func) const { 2644 void InstImpl<TraitsType>::InstX86Setcc::dump(const Cfg *Func) const {
2920 if (!BuildDefs::dump()) 2645 if (!BuildDefs::dump())
2921 return; 2646 return;
2922 Ostream &Str = Func->getContext()->getStrDump(); 2647 Ostream &Str = Func->getContext()->getStrDump();
2923 Str << "setcc." 2648 Str << "setcc." << Traits::InstBrAttributes[Condition].DisplayString << " ";
2924 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
2925 << " ";
2926 this->dumpDest(Func); 2649 this->dumpDest(Func);
2927 } 2650 }
2928 2651
2929 template <class Machine> 2652 template <typename TraitsType>
2930 void InstX86Xadd<Machine>::emit(const Cfg *Func) const { 2653 void InstImpl<TraitsType>::InstX86Xadd::emit(const Cfg *Func) const {
2931 if (!BuildDefs::dump()) 2654 if (!BuildDefs::dump())
2932 return; 2655 return;
2933 Ostream &Str = Func->getContext()->getStrEmit(); 2656 Ostream &Str = Func->getContext()->getStrEmit();
2934 if (this->Locked) { 2657 if (this->Locked) {
2935 Str << "\t" 2658 Str << "\t"
2936 "lock"; 2659 "lock";
2937 } 2660 }
2938 Str << "\t" 2661 Str << "\t"
2939 "xadd" << this->getWidthString(this->getSrc(0)->getType()) << "\t"; 2662 "xadd" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
2940 this->getSrc(1)->emit(Func); 2663 this->getSrc(1)->emit(Func);
2941 Str << ", "; 2664 Str << ", ";
2942 this->getSrc(0)->emit(Func); 2665 this->getSrc(0)->emit(Func);
2943 } 2666 }
2944 2667
2945 template <class Machine> 2668 template <typename TraitsType>
2946 void InstX86Xadd<Machine>::emitIAS(const Cfg *Func) const { 2669 void InstImpl<TraitsType>::InstX86Xadd::emitIAS(const Cfg *Func) const {
2947 assert(this->getSrcSize() == 2); 2670 assert(this->getSrcSize() == 2);
2948 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2671 Assembler *Asm = Func->getAssembler<Assembler>();
2949 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2950 Type Ty = this->getSrc(0)->getType(); 2672 Type Ty = this->getSrc(0)->getType();
2951 const auto Mem = 2673 const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
2952 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>( 2674 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
2953 this->getSrc(0)); 2675 auto *Target = InstX86Base::getTarget(Func);
2954 assert(Mem->getSegmentRegister() == 2676 const Address Addr = Mem->toAsmAddress(Asm, Target);
2955 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2956 auto *Target = InstX86Base<Machine>::getTarget(Func);
2957 const typename InstX86Base<Machine>::Traits::Address Addr =
2958 Mem->toAsmAddress(Asm, Target);
2959 const auto *VarReg = llvm::cast<Variable>(this->getSrc(1)); 2677 const auto *VarReg = llvm::cast<Variable>(this->getSrc(1));
2960 assert(VarReg->hasReg()); 2678 assert(VarReg->hasReg());
2961 const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg = 2679 const GPRRegister Reg = Traits::getEncodedGPR(VarReg->getRegNum());
2962 InstX86Base<Machine>::Traits::getEncodedGPR(VarReg->getRegNum());
2963 Asm->xadd(Ty, Addr, Reg, this->Locked); 2680 Asm->xadd(Ty, Addr, Reg, this->Locked);
2964 } 2681 }
2965 2682
2966 template <class Machine> 2683 template <typename TraitsType>
2967 void InstX86Xadd<Machine>::dump(const Cfg *Func) const { 2684 void InstImpl<TraitsType>::InstX86Xadd::dump(const Cfg *Func) const {
2968 if (!BuildDefs::dump()) 2685 if (!BuildDefs::dump())
2969 return; 2686 return;
2970 Ostream &Str = Func->getContext()->getStrDump(); 2687 Ostream &Str = Func->getContext()->getStrDump();
2971 if (this->Locked) { 2688 if (this->Locked) {
2972 Str << "lock "; 2689 Str << "lock ";
2973 } 2690 }
2974 Type Ty = this->getSrc(0)->getType(); 2691 Type Ty = this->getSrc(0)->getType();
2975 Str << "xadd." << Ty << " "; 2692 Str << "xadd." << Ty << " ";
2976 this->dumpSources(Func); 2693 this->dumpSources(Func);
2977 } 2694 }
2978 2695
2979 template <class Machine> 2696 template <typename TraitsType>
2980 void InstX86Xchg<Machine>::emit(const Cfg *Func) const { 2697 void InstImpl<TraitsType>::InstX86Xchg::emit(const Cfg *Func) const {
2981 if (!BuildDefs::dump()) 2698 if (!BuildDefs::dump())
2982 return; 2699 return;
2983 Ostream &Str = Func->getContext()->getStrEmit(); 2700 Ostream &Str = Func->getContext()->getStrEmit();
2984 Str << "\t" 2701 Str << "\t"
2985 "xchg" << this->getWidthString(this->getSrc(0)->getType()) << "\t"; 2702 "xchg" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
2986 this->getSrc(1)->emit(Func); 2703 this->getSrc(1)->emit(Func);
2987 Str << ", "; 2704 Str << ", ";
2988 this->getSrc(0)->emit(Func); 2705 this->getSrc(0)->emit(Func);
2989 } 2706 }
2990 2707
2991 template <class Machine> 2708 template <typename TraitsType>
2992 void InstX86Xchg<Machine>::emitIAS(const Cfg *Func) const { 2709 void InstImpl<TraitsType>::InstX86Xchg::emitIAS(const Cfg *Func) const {
2993 assert(this->getSrcSize() == 2); 2710 assert(this->getSrcSize() == 2);
2994 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2711 Assembler *Asm = Func->getAssembler<Assembler>();
2995 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2996 Type Ty = this->getSrc(0)->getType(); 2712 Type Ty = this->getSrc(0)->getType();
2997 const auto *VarReg1 = llvm::cast<Variable>(this->getSrc(1)); 2713 const auto *VarReg1 = llvm::cast<Variable>(this->getSrc(1));
2998 assert(VarReg1->hasReg()); 2714 assert(VarReg1->hasReg());
2999 const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg1 = 2715 const GPRRegister Reg1 = Traits::getEncodedGPR(VarReg1->getRegNum());
3000 InstX86Base<Machine>::Traits::getEncodedGPR(VarReg1->getRegNum());
3001 2716
3002 if (const auto *VarReg0 = llvm::dyn_cast<Variable>(this->getSrc(0))) { 2717 if (const auto *VarReg0 = llvm::dyn_cast<Variable>(this->getSrc(0))) {
3003 assert(VarReg0->hasReg()); 2718 assert(VarReg0->hasReg());
3004 const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg0 = 2719 const GPRRegister Reg0 = Traits::getEncodedGPR(VarReg0->getRegNum());
3005 InstX86Base<Machine>::Traits::getEncodedGPR(VarReg0->getRegNum());
3006 Asm->xchg(Ty, Reg0, Reg1); 2720 Asm->xchg(Ty, Reg0, Reg1);
3007 return; 2721 return;
3008 } 2722 }
3009 2723
3010 const auto *Mem = 2724 const auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
3011 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>( 2725 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
3012 this->getSrc(0)); 2726 auto *Target = InstX86Base::getTarget(Func);
3013 assert(Mem->getSegmentRegister() == 2727 const Address Addr = Mem->toAsmAddress(Asm, Target);
3014 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
3015 auto *Target = InstX86Base<Machine>::getTarget(Func);
3016 const typename InstX86Base<Machine>::Traits::Address Addr =
3017 Mem->toAsmAddress(Asm, Target);
3018 Asm->xchg(Ty, Addr, Reg1); 2728 Asm->xchg(Ty, Addr, Reg1);
3019 } 2729 }
3020 2730
3021 template <class Machine> 2731 template <typename TraitsType>
3022 void InstX86Xchg<Machine>::dump(const Cfg *Func) const { 2732 void InstImpl<TraitsType>::InstX86Xchg::dump(const Cfg *Func) const {
3023 if (!BuildDefs::dump()) 2733 if (!BuildDefs::dump())
3024 return; 2734 return;
3025 Ostream &Str = Func->getContext()->getStrDump(); 2735 Ostream &Str = Func->getContext()->getStrDump();
3026 Type Ty = this->getSrc(0)->getType(); 2736 Type Ty = this->getSrc(0)->getType();
3027 Str << "xchg." << Ty << " "; 2737 Str << "xchg." << Ty << " ";
3028 this->dumpSources(Func); 2738 this->dumpSources(Func);
3029 } 2739 }
3030 2740
3031 template <class Machine> 2741 template <typename TraitsType>
3032 void InstX86IacaStart<Machine>::emit(const Cfg *Func) const { 2742 void InstImpl<TraitsType>::InstX86IacaStart::emit(const Cfg *Func) const {
3033 if (!BuildDefs::dump()) 2743 if (!BuildDefs::dump())
3034 return; 2744 return;
3035 Ostream &Str = Func->getContext()->getStrEmit(); 2745 Ostream &Str = Func->getContext()->getStrEmit();
3036 Str << "\t# IACA_START\n" 2746 Str << "\t# IACA_START\n"
3037 "\t.byte 0x0F, 0x0B\n" 2747 "\t.byte 0x0F, 0x0B\n"
3038 "\t" 2748 "\t"
3039 "movl\t$111, %ebx\n" 2749 "movl\t$111, %ebx\n"
3040 "\t.byte 0x64, 0x67, 0x90"; 2750 "\t.byte 0x64, 0x67, 0x90";
3041 } 2751 }
3042 2752
3043 template <class Machine> 2753 template <typename TraitsType>
3044 void InstX86IacaStart<Machine>::emitIAS(const Cfg *Func) const { 2754 void InstImpl<TraitsType>::InstX86IacaStart::emitIAS(const Cfg *Func) const {
3045 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2755 Assembler *Asm = Func->getAssembler<Assembler>();
3046 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3047 Asm->iaca_start(); 2756 Asm->iaca_start();
3048 } 2757 }
3049 2758
3050 template <class Machine> 2759 template <typename TraitsType>
3051 void InstX86IacaStart<Machine>::dump(const Cfg *Func) const { 2760 void InstImpl<TraitsType>::InstX86IacaStart::dump(const Cfg *Func) const {
3052 if (!BuildDefs::dump()) 2761 if (!BuildDefs::dump())
3053 return; 2762 return;
3054 Ostream &Str = Func->getContext()->getStrDump(); 2763 Ostream &Str = Func->getContext()->getStrDump();
3055 Str << "IACA_START"; 2764 Str << "IACA_START";
3056 } 2765 }
3057 2766
3058 template <class Machine> 2767 template <typename TraitsType>
3059 void InstX86IacaEnd<Machine>::emit(const Cfg *Func) const { 2768 void InstImpl<TraitsType>::InstX86IacaEnd::emit(const Cfg *Func) const {
3060 if (!BuildDefs::dump()) 2769 if (!BuildDefs::dump())
3061 return; 2770 return;
3062 Ostream &Str = Func->getContext()->getStrEmit(); 2771 Ostream &Str = Func->getContext()->getStrEmit();
3063 Str << "\t# IACA_END\n" 2772 Str << "\t# IACA_END\n"
3064 "\t" 2773 "\t"
3065 "movl\t$222, %ebx\n" 2774 "movl\t$222, %ebx\n"
3066 "\t.byte 0x64, 0x67, 0x90\n" 2775 "\t.byte 0x64, 0x67, 0x90\n"
3067 "\t.byte 0x0F, 0x0B"; 2776 "\t.byte 0x0F, 0x0B";
3068 } 2777 }
3069 2778
3070 template <class Machine> 2779 template <typename TraitsType>
3071 void InstX86IacaEnd<Machine>::emitIAS(const Cfg *Func) const { 2780 void InstImpl<TraitsType>::InstX86IacaEnd::emitIAS(const Cfg *Func) const {
3072 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2781 Assembler *Asm = Func->getAssembler<Assembler>();
3073 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3074 Asm->iaca_end(); 2782 Asm->iaca_end();
3075 } 2783 }
3076 2784
3077 template <class Machine> 2785 template <typename TraitsType>
3078 void InstX86IacaEnd<Machine>::dump(const Cfg *Func) const { 2786 void InstImpl<TraitsType>::InstX86IacaEnd::dump(const Cfg *Func) const {
3079 if (!BuildDefs::dump()) 2787 if (!BuildDefs::dump())
3080 return; 2788 return;
3081 Ostream &Str = Func->getContext()->getStrDump(); 2789 Ostream &Str = Func->getContext()->getStrDump();
3082 Str << "IACA_END"; 2790 Str << "IACA_END";
3083 } 2791 }
3084 2792
3085 } // end of namespace X86Internal 2793 } // end of namespace X86NAMESPACE
3086 2794
3087 } // end of namespace Ice 2795 } // end of namespace Ice
3088 2796
3089 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H 2797 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698