OLD | NEW |
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 |
OLD | NEW |