OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 // | |
5 // Modified by the Subzero authors. | |
6 // | |
7 //===- subzero/src/assembler_ia32.cpp - Assembler for x86-32 -------------===// | |
8 // | |
9 // The Subzero Code Generator | |
10 // | |
11 // This file is distributed under the University of Illinois Open Source | |
12 // License. See LICENSE.TXT for details. | |
13 // | |
14 //===----------------------------------------------------------------------===// | |
15 // | |
16 // This file implements the Assembler class for x86-32. | |
17 // | |
18 //===----------------------------------------------------------------------===// | |
19 | |
20 #include "assembler_ia32.h" | |
21 #include "IceCfg.h" | |
22 #include "IceMemoryRegion.h" | |
23 #include "IceOperand.h" | |
24 | |
25 namespace Ice { | |
26 namespace x86 { | |
27 | |
28 class DirectCallRelocation : public AssemblerFixup { | |
29 public: | |
30 static DirectCallRelocation *create(Assembler *Asm, FixupKind Kind, | |
31 const ConstantRelocatable *Sym) { | |
32 return new (Asm->Allocate<DirectCallRelocation>()) | |
33 DirectCallRelocation(Kind, Sym); | |
34 } | |
35 | |
36 void Process(const MemoryRegion ®ion, intptr_t position) { | |
37 // Direct calls are relative to the following instruction on x86. | |
38 int32_t pointer = region.Load<int32_t>(position); | |
39 int32_t delta = region.start() + position + sizeof(int32_t); | |
40 region.Store<int32_t>(position, pointer - delta); | |
41 } | |
42 | |
43 private: | |
44 DirectCallRelocation(FixupKind Kind, const ConstantRelocatable *Sym) | |
45 : AssemblerFixup(Kind, Sym) {} | |
46 }; | |
47 | |
48 Address Address::ofConstPool(GlobalContext *Ctx, Assembler *Asm, | |
49 const Constant *Imm) { | |
50 // We should make this much lighter-weight. E.g., just record the const pool | |
51 // entry ID. | |
52 std::string Buffer; | |
53 llvm::raw_string_ostream StrBuf(Buffer); | |
54 Type Ty = Imm->getType(); | |
55 assert(llvm::isa<ConstantFloat>(Imm) || llvm::isa<ConstantDouble>(Imm)); | |
56 StrBuf << "L$" << Ty << "$" << Imm->getPoolEntryID(); | |
57 const int64_t Offset = 0; | |
58 const bool SuppressMangling = true; | |
59 Constant *Sym = | |
60 Ctx->getConstantSym(Ty, Offset, StrBuf.str(), SuppressMangling); | |
61 AssemblerFixup *Fixup = x86::DisplacementRelocation::create( | |
62 Asm, FK_Abs_4, llvm::cast<ConstantRelocatable>(Sym)); | |
63 return x86::Address::Absolute(Offset, Fixup); | |
64 } | |
65 | |
66 void AssemblerX86::call(GPRRegister reg) { | |
67 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
68 EmitUint8(0xFF); | |
69 EmitRegisterOperand(2, reg); | |
70 } | |
71 | |
72 void AssemblerX86::call(const Address &address) { | |
73 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
74 EmitUint8(0xFF); | |
75 EmitOperand(2, address); | |
76 } | |
77 | |
78 void AssemblerX86::call(Label *label) { | |
79 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
80 EmitUint8(0xE8); | |
81 static const int kSize = 5; | |
82 EmitLabel(label, kSize); | |
83 } | |
84 | |
85 void AssemblerX86::call(const ConstantRelocatable *label) { | |
86 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
87 intptr_t call_start = buffer_.GetPosition(); | |
88 EmitUint8(0xE8); | |
89 EmitFixup(DirectCallRelocation::create(this, FK_PcRel_4, label)); | |
90 EmitInt32(-4); | |
91 assert((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); | |
92 } | |
93 | |
94 void AssemblerX86::pushl(GPRRegister reg) { | |
95 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
96 EmitUint8(0x50 + reg); | |
97 } | |
98 | |
99 void AssemblerX86::pushl(const Address &address) { | |
100 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
101 EmitUint8(0xFF); | |
102 EmitOperand(6, address); | |
103 } | |
104 | |
105 void AssemblerX86::pushl(const Immediate &imm) { | |
106 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
107 EmitUint8(0x68); | |
108 EmitImmediate(imm); | |
109 } | |
110 | |
111 void AssemblerX86::popl(GPRRegister reg) { | |
112 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
113 EmitUint8(0x58 + reg); | |
114 } | |
115 | |
116 void AssemblerX86::popl(const Address &address) { | |
117 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
118 EmitUint8(0x8F); | |
119 EmitOperand(0, address); | |
120 } | |
121 | |
122 void AssemblerX86::pushal() { | |
123 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
124 EmitUint8(0x60); | |
125 } | |
126 | |
127 void AssemblerX86::popal() { | |
128 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
129 EmitUint8(0x61); | |
130 } | |
131 | |
132 void AssemblerX86::setcc(CondX86::BrCond condition, ByteRegister dst) { | |
133 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
134 EmitUint8(0x0F); | |
135 EmitUint8(0x90 + condition); | |
136 EmitUint8(0xC0 + dst); | |
137 } | |
138 | |
139 void AssemblerX86::movl(GPRRegister dst, const Immediate &imm) { | |
140 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
141 EmitUint8(0xB8 + dst); | |
142 EmitImmediate(imm); | |
143 } | |
144 | |
145 void AssemblerX86::movl(GPRRegister dst, GPRRegister src) { | |
146 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
147 EmitUint8(0x89); | |
148 EmitRegisterOperand(src, dst); | |
149 } | |
150 | |
151 void AssemblerX86::movl(GPRRegister dst, const Address &src) { | |
152 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
153 EmitUint8(0x8B); | |
154 EmitOperand(dst, src); | |
155 } | |
156 | |
157 void AssemblerX86::movl(const Address &dst, GPRRegister src) { | |
158 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
159 EmitUint8(0x89); | |
160 EmitOperand(src, dst); | |
161 } | |
162 | |
163 void AssemblerX86::movl(const Address &dst, const Immediate &imm) { | |
164 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
165 EmitUint8(0xC7); | |
166 EmitOperand(0, dst); | |
167 EmitImmediate(imm); | |
168 } | |
169 | |
170 void AssemblerX86::movzxb(GPRRegister dst, ByteRegister src) { | |
171 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
172 EmitUint8(0x0F); | |
173 EmitUint8(0xB6); | |
174 EmitRegisterOperand(dst, src); | |
175 } | |
176 | |
177 void AssemblerX86::movzxb(GPRRegister dst, const Address &src) { | |
178 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
179 EmitUint8(0x0F); | |
180 EmitUint8(0xB6); | |
181 EmitOperand(dst, src); | |
182 } | |
183 | |
184 void AssemblerX86::movsxb(GPRRegister dst, ByteRegister src) { | |
185 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
186 EmitUint8(0x0F); | |
187 EmitUint8(0xBE); | |
188 EmitRegisterOperand(dst, src); | |
189 } | |
190 | |
191 void AssemblerX86::movsxb(GPRRegister dst, const Address &src) { | |
192 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
193 EmitUint8(0x0F); | |
194 EmitUint8(0xBE); | |
195 EmitOperand(dst, src); | |
196 } | |
197 | |
198 void AssemblerX86::movb(ByteRegister dst, const Address &src) { | |
199 (void)dst; | |
200 (void)src; | |
201 // FATAL | |
202 llvm_unreachable("Use movzxb or movsxb instead."); | |
203 } | |
204 | |
205 void AssemblerX86::movb(const Address &dst, ByteRegister src) { | |
206 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
207 EmitUint8(0x88); | |
208 EmitOperand(src, dst); | |
209 } | |
210 | |
211 void AssemblerX86::movb(const Address &dst, const Immediate &imm) { | |
212 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
213 EmitUint8(0xC6); | |
214 EmitOperand(RegX8632::Encoded_Reg_eax, dst); | |
215 assert(imm.is_int8()); | |
216 EmitUint8(imm.value() & 0xFF); | |
217 } | |
218 | |
219 void AssemblerX86::movzxw(GPRRegister dst, GPRRegister src) { | |
220 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
221 EmitUint8(0x0F); | |
222 EmitUint8(0xB7); | |
223 EmitRegisterOperand(dst, src); | |
224 } | |
225 | |
226 void AssemblerX86::movzxw(GPRRegister dst, const Address &src) { | |
227 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
228 EmitUint8(0x0F); | |
229 EmitUint8(0xB7); | |
230 EmitOperand(dst, src); | |
231 } | |
232 | |
233 void AssemblerX86::movsxw(GPRRegister dst, GPRRegister src) { | |
234 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
235 EmitUint8(0x0F); | |
236 EmitUint8(0xBF); | |
237 EmitRegisterOperand(dst, src); | |
238 } | |
239 | |
240 void AssemblerX86::movsxw(GPRRegister dst, const Address &src) { | |
241 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
242 EmitUint8(0x0F); | |
243 EmitUint8(0xBF); | |
244 EmitOperand(dst, src); | |
245 } | |
246 | |
247 void AssemblerX86::movw(GPRRegister dst, const Address &src) { | |
248 (void)dst; | |
249 (void)src; | |
250 // FATAL | |
251 llvm_unreachable("Use movzxw or movsxw instead."); | |
252 } | |
253 | |
254 void AssemblerX86::movw(const Address &dst, GPRRegister src) { | |
255 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
256 EmitOperandSizeOverride(); | |
257 EmitUint8(0x89); | |
258 EmitOperand(src, dst); | |
259 } | |
260 | |
261 void AssemblerX86::leal(GPRRegister dst, const Address &src) { | |
262 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
263 EmitUint8(0x8D); | |
264 EmitOperand(dst, src); | |
265 } | |
266 | |
267 void AssemblerX86::cmov(CondX86::BrCond cond, GPRRegister dst, | |
268 GPRRegister src) { | |
269 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
270 EmitUint8(0x0F); | |
271 EmitUint8(0x40 + cond); | |
272 EmitRegisterOperand(dst, src); | |
273 } | |
274 | |
275 void AssemblerX86::rep_movsb() { | |
276 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
277 EmitUint8(0xF3); | |
278 EmitUint8(0xA4); | |
279 } | |
280 | |
281 void AssemblerX86::movss(XmmRegister dst, const Address &src) { | |
282 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
283 EmitUint8(0xF3); | |
284 EmitUint8(0x0F); | |
285 EmitUint8(0x10); | |
286 EmitOperand(dst, src); | |
287 } | |
288 | |
289 void AssemblerX86::movss(const Address &dst, XmmRegister src) { | |
290 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
291 EmitUint8(0xF3); | |
292 EmitUint8(0x0F); | |
293 EmitUint8(0x11); | |
294 EmitOperand(src, dst); | |
295 } | |
296 | |
297 void AssemblerX86::movss(XmmRegister dst, XmmRegister src) { | |
298 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
299 EmitUint8(0xF3); | |
300 EmitUint8(0x0F); | |
301 EmitUint8(0x11); | |
302 EmitXmmRegisterOperand(src, dst); | |
303 } | |
304 | |
305 void AssemblerX86::movd(XmmRegister dst, GPRRegister src) { | |
306 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
307 EmitUint8(0x66); | |
308 EmitUint8(0x0F); | |
309 EmitUint8(0x6E); | |
310 EmitOperand(dst, Operand(src)); | |
311 } | |
312 | |
313 void AssemblerX86::movd(GPRRegister dst, XmmRegister src) { | |
314 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
315 EmitUint8(0x66); | |
316 EmitUint8(0x0F); | |
317 EmitUint8(0x7E); | |
318 EmitOperand(src, Operand(dst)); | |
319 } | |
320 | |
321 void AssemblerX86::movq(const Address &dst, XmmRegister src) { | |
322 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
323 EmitUint8(0x66); | |
324 EmitUint8(0x0F); | |
325 EmitUint8(0xD6); | |
326 EmitOperand(src, Operand(dst)); | |
327 } | |
328 | |
329 void AssemblerX86::movq(XmmRegister dst, const Address &src) { | |
330 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
331 EmitUint8(0xF3); | |
332 EmitUint8(0x0F); | |
333 EmitUint8(0x7E); | |
334 EmitOperand(dst, Operand(src)); | |
335 } | |
336 | |
337 void AssemblerX86::addss(Type Ty, XmmRegister dst, XmmRegister src) { | |
338 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
339 EmitUint8(Ty == IceType_f32 ? 0xF3 : 0xF2); | |
jvoung (off chromium)
2014/09/20 18:13:34
I debated a bunch where to put the Type check. Thi
| |
340 EmitUint8(0x0F); | |
341 EmitUint8(0x58); | |
342 EmitXmmRegisterOperand(dst, src); | |
343 } | |
344 | |
345 void AssemblerX86::addss(Type Ty, XmmRegister dst, const Address &src) { | |
346 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
347 EmitUint8(Ty == IceType_f32 ? 0xF3 : 0xF2); | |
348 EmitUint8(0x0F); | |
349 EmitUint8(0x58); | |
350 EmitOperand(dst, src); | |
351 } | |
352 | |
353 void AssemblerX86::subss(Type Ty, XmmRegister dst, XmmRegister src) { | |
354 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
355 EmitUint8(Ty == IceType_f32 ? 0xF3 : 0xF2); | |
356 EmitUint8(0x0F); | |
357 EmitUint8(0x5C); | |
358 EmitXmmRegisterOperand(dst, src); | |
359 } | |
360 | |
361 void AssemblerX86::subss(Type Ty, XmmRegister dst, const Address &src) { | |
362 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
363 EmitUint8(Ty == IceType_f32 ? 0xF3 : 0xF2); | |
364 EmitUint8(0x0F); | |
365 EmitUint8(0x5C); | |
366 EmitOperand(dst, src); | |
367 } | |
368 | |
369 void AssemblerX86::mulss(Type Ty, XmmRegister dst, XmmRegister src) { | |
370 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
371 EmitUint8(Ty == IceType_f32 ? 0xF3 : 0xF2); | |
372 EmitUint8(0x0F); | |
373 EmitUint8(0x59); | |
374 EmitXmmRegisterOperand(dst, src); | |
375 } | |
376 | |
377 void AssemblerX86::mulss(Type Ty, XmmRegister dst, const Address &src) { | |
378 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
379 EmitUint8(Ty == IceType_f32 ? 0xF3 : 0xF2); | |
380 EmitUint8(0x0F); | |
381 EmitUint8(0x59); | |
382 EmitOperand(dst, src); | |
383 } | |
384 | |
385 void AssemblerX86::divss(Type Ty, XmmRegister dst, XmmRegister src) { | |
386 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
387 EmitUint8(Ty == IceType_f32 ? 0xF3 : 0xF2); | |
388 EmitUint8(0x0F); | |
389 EmitUint8(0x5E); | |
390 EmitXmmRegisterOperand(dst, src); | |
391 } | |
392 | |
393 void AssemblerX86::divss(Type Ty, XmmRegister dst, const Address &src) { | |
394 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
395 EmitUint8(Ty == IceType_f32 ? 0xF3 : 0xF2); | |
396 EmitUint8(0x0F); | |
397 EmitUint8(0x5E); | |
398 EmitOperand(dst, src); | |
399 } | |
400 | |
401 void AssemblerX86::flds(const Address &src) { | |
402 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
403 EmitUint8(0xD9); | |
404 EmitOperand(0, src); | |
405 } | |
406 | |
407 void AssemblerX86::fstps(const Address &dst) { | |
408 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
409 EmitUint8(0xD9); | |
410 EmitOperand(3, dst); | |
411 } | |
412 | |
413 void AssemblerX86::movsd(XmmRegister dst, const Address &src) { | |
414 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
415 EmitUint8(0xF2); | |
416 EmitUint8(0x0F); | |
417 EmitUint8(0x10); | |
418 EmitOperand(dst, src); | |
419 } | |
420 | |
421 void AssemblerX86::movsd(const Address &dst, XmmRegister src) { | |
422 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
423 EmitUint8(0xF2); | |
424 EmitUint8(0x0F); | |
425 EmitUint8(0x11); | |
426 EmitOperand(src, dst); | |
427 } | |
428 | |
429 void AssemblerX86::movsd(XmmRegister dst, XmmRegister src) { | |
430 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
431 EmitUint8(0xF2); | |
432 EmitUint8(0x0F); | |
433 EmitUint8(0x11); | |
434 EmitXmmRegisterOperand(src, dst); | |
435 } | |
436 | |
437 void AssemblerX86::movaps(XmmRegister dst, XmmRegister src) { | |
438 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
439 EmitUint8(0x0F); | |
440 EmitUint8(0x28); | |
441 EmitXmmRegisterOperand(dst, src); | |
442 } | |
443 | |
444 void AssemblerX86::movups(XmmRegister dst, const Address &src) { | |
445 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
446 EmitUint8(0x0F); | |
447 EmitUint8(0x10); | |
448 EmitOperand(dst, src); | |
449 } | |
450 | |
451 void AssemblerX86::movups(const Address &dst, XmmRegister src) { | |
452 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
453 EmitUint8(0x0F); | |
454 EmitUint8(0x11); | |
455 EmitOperand(src, dst); | |
456 } | |
457 | |
458 void AssemblerX86::padd(Type Ty, XmmRegister dst, XmmRegister src) { | |
459 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
460 EmitUint8(0x66); | |
461 EmitUint8(0x0F); | |
462 if (Ty == IceType_i8 || Ty == IceType_i1) { | |
463 EmitUint8(0xFC); | |
464 } else if (Ty == IceType_i16) { | |
465 EmitUint8(0xFD); | |
466 } else { | |
467 EmitUint8(0xFE); | |
468 } | |
469 EmitXmmRegisterOperand(dst, src); | |
470 } | |
471 | |
472 void AssemblerX86::padd(Type Ty, XmmRegister dst, const Address &src) { | |
473 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
474 EmitUint8(0x66); | |
475 EmitUint8(0x0F); | |
476 if (Ty == IceType_i8 || Ty == IceType_i1) { | |
477 EmitUint8(0xFC); | |
478 } else if (Ty == IceType_i16) { | |
479 EmitUint8(0xFD); | |
480 } else { | |
481 EmitUint8(0xFE); | |
482 } | |
483 EmitOperand(dst, src); | |
484 } | |
485 | |
486 void AssemblerX86::pand(Type /* Ty */, XmmRegister dst, XmmRegister src) { | |
487 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
488 EmitUint8(0x66); | |
489 EmitUint8(0x0F); | |
490 EmitUint8(0xDB); | |
491 EmitXmmRegisterOperand(dst, src); | |
492 } | |
493 | |
494 void AssemblerX86::pand(Type /* Ty */, XmmRegister dst, const Address &src) { | |
495 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
496 EmitUint8(0x66); | |
497 EmitUint8(0x0F); | |
498 EmitUint8(0xDB); | |
499 EmitOperand(dst, src); | |
500 } | |
501 | |
502 void AssemblerX86::pandn(Type /* Ty */, XmmRegister dst, XmmRegister src) { | |
503 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
504 EmitUint8(0x66); | |
505 EmitUint8(0x0F); | |
506 EmitUint8(0xDF); | |
507 EmitXmmRegisterOperand(dst, src); | |
508 } | |
509 | |
510 void AssemblerX86::pandn(Type /* Ty */, XmmRegister dst, const Address &src) { | |
511 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
512 EmitUint8(0x66); | |
513 EmitUint8(0x0F); | |
514 EmitUint8(0xDF); | |
515 EmitOperand(dst, src); | |
516 } | |
517 | |
518 void AssemblerX86::pmuludq(Type /* Ty */, XmmRegister dst, XmmRegister src) { | |
519 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
520 EmitUint8(0x66); | |
521 EmitUint8(0x0F); | |
522 EmitUint8(0xF4); | |
523 EmitXmmRegisterOperand(dst, src); | |
524 } | |
525 | |
526 void AssemblerX86::pmuludq(Type /* Ty */, XmmRegister dst, const Address &src) { | |
527 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
528 EmitUint8(0x66); | |
529 EmitUint8(0x0F); | |
530 EmitUint8(0xF4); | |
531 EmitOperand(dst, src); | |
532 } | |
533 | |
534 void AssemblerX86::por(Type /* Ty */, XmmRegister dst, XmmRegister src) { | |
535 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
536 EmitUint8(0x66); | |
537 EmitUint8(0x0F); | |
538 EmitUint8(0xEB); | |
539 EmitXmmRegisterOperand(dst, src); | |
540 } | |
541 | |
542 void AssemblerX86::por(Type /* Ty */, XmmRegister dst, const Address &src) { | |
543 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
544 EmitUint8(0x66); | |
545 EmitUint8(0x0F); | |
546 EmitUint8(0xEB); | |
547 EmitOperand(dst, src); | |
548 } | |
549 | |
550 void AssemblerX86::psub(Type Ty, XmmRegister dst, XmmRegister src) { | |
551 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
552 EmitUint8(0x66); | |
553 EmitUint8(0x0F); | |
554 if (Ty == IceType_i8 || Ty == IceType_i1) { | |
555 EmitUint8(0xF8); | |
556 } else if (Ty == IceType_i16) { | |
557 EmitUint8(0xF9); | |
558 } else { | |
559 EmitUint8(0xFA); | |
560 } | |
561 EmitXmmRegisterOperand(dst, src); | |
562 } | |
563 | |
564 void AssemblerX86::psub(Type Ty, XmmRegister dst, const Address &src) { | |
565 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
566 EmitUint8(0x66); | |
567 EmitUint8(0x0F); | |
568 if (Ty == IceType_i8 || Ty == IceType_i1) { | |
569 EmitUint8(0xF8); | |
570 } else if (Ty == IceType_i16) { | |
571 EmitUint8(0xF9); | |
572 } else { | |
573 EmitUint8(0xFA); | |
574 } | |
575 EmitOperand(dst, src); | |
576 } | |
577 | |
578 void AssemblerX86::pxor(Type /* Ty */, XmmRegister dst, XmmRegister src) { | |
579 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
580 EmitUint8(0x66); | |
581 EmitUint8(0x0F); | |
582 EmitUint8(0xEF); | |
583 EmitXmmRegisterOperand(dst, src); | |
584 } | |
585 | |
586 void AssemblerX86::pxor(Type /* Ty */, XmmRegister dst, const Address &src) { | |
587 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
588 EmitUint8(0x66); | |
589 EmitUint8(0x0F); | |
590 EmitUint8(0xEF); | |
591 EmitOperand(dst, src); | |
592 } | |
593 | |
594 // {add,sub,mul,div}ps are given a Ty parameter for consistency with | |
595 // {add,sub,mul,div}ss. In the future, when the PNaCl ABI allows | |
596 // addpd, etc., we can use the Ty parameter to decide on adding | |
597 // a 0x66 prefix. | |
598 void AssemblerX86::addps(Type /* Ty */, XmmRegister dst, XmmRegister src) { | |
599 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
600 EmitUint8(0x0F); | |
601 EmitUint8(0x58); | |
602 EmitXmmRegisterOperand(dst, src); | |
603 } | |
604 | |
605 void AssemblerX86::addps(Type /* Ty */, XmmRegister dst, const Address &src) { | |
606 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
607 EmitUint8(0x0F); | |
608 EmitUint8(0x58); | |
609 EmitOperand(dst, src); | |
610 } | |
611 | |
612 void AssemblerX86::subps(Type /* Ty */, XmmRegister dst, XmmRegister src) { | |
613 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
614 EmitUint8(0x0F); | |
615 EmitUint8(0x5C); | |
616 EmitXmmRegisterOperand(dst, src); | |
617 } | |
618 | |
619 void AssemblerX86::subps(Type /* Ty */, XmmRegister dst, const Address &src) { | |
620 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
621 EmitUint8(0x0F); | |
622 EmitUint8(0x5C); | |
623 EmitOperand(dst, src); | |
624 } | |
625 | |
626 void AssemblerX86::divps(Type /* Ty */, XmmRegister dst, XmmRegister src) { | |
627 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
628 EmitUint8(0x0F); | |
629 EmitUint8(0x5E); | |
630 EmitXmmRegisterOperand(dst, src); | |
631 } | |
632 | |
633 void AssemblerX86::divps(Type /* Ty */, XmmRegister dst, const Address &src) { | |
634 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
635 EmitUint8(0x0F); | |
636 EmitUint8(0x5E); | |
637 EmitOperand(dst, src); | |
638 } | |
639 | |
640 void AssemblerX86::mulps(Type /* Ty */, XmmRegister dst, XmmRegister src) { | |
641 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
642 EmitUint8(0x0F); | |
643 EmitUint8(0x59); | |
644 EmitXmmRegisterOperand(dst, src); | |
645 } | |
646 | |
647 void AssemblerX86::mulps(Type /* Ty */, XmmRegister dst, const Address &src) { | |
648 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
649 EmitUint8(0x0F); | |
650 EmitUint8(0x59); | |
651 EmitOperand(dst, src); | |
652 } | |
653 | |
654 void AssemblerX86::minps(XmmRegister dst, XmmRegister src) { | |
655 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
656 EmitUint8(0x0F); | |
657 EmitUint8(0x5D); | |
658 EmitXmmRegisterOperand(dst, src); | |
659 } | |
660 | |
661 void AssemblerX86::maxps(XmmRegister dst, XmmRegister src) { | |
662 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
663 EmitUint8(0x0F); | |
664 EmitUint8(0x5F); | |
665 EmitXmmRegisterOperand(dst, src); | |
666 } | |
667 | |
668 void AssemblerX86::andps(XmmRegister dst, XmmRegister src) { | |
669 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
670 EmitUint8(0x0F); | |
671 EmitUint8(0x54); | |
672 EmitXmmRegisterOperand(dst, src); | |
673 } | |
674 | |
675 void AssemblerX86::andps(XmmRegister dst, const Address &src) { | |
676 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
677 EmitUint8(0x0F); | |
678 EmitUint8(0x54); | |
679 EmitOperand(dst, src); | |
680 } | |
681 | |
682 void AssemblerX86::orps(XmmRegister dst, XmmRegister src) { | |
683 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
684 EmitUint8(0x0F); | |
685 EmitUint8(0x56); | |
686 EmitXmmRegisterOperand(dst, src); | |
687 } | |
688 | |
689 void AssemblerX86::cmpps(XmmRegister dst, XmmRegister src, | |
690 uint8_t CmpCondition) { | |
691 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
692 EmitUint8(0x0F); | |
693 EmitUint8(0xC2); | |
694 EmitXmmRegisterOperand(dst, src); | |
695 EmitUint8(CmpCondition); | |
696 } | |
697 | |
698 void AssemblerX86::cmpps(XmmRegister dst, const Address &src, | |
699 uint8_t CmpCondition) { | |
700 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
701 EmitUint8(0x0F); | |
702 EmitUint8(0xC2); | |
703 EmitOperand(dst, src); | |
704 EmitUint8(CmpCondition); | |
705 } | |
706 | |
707 void AssemblerX86::sqrtps(XmmRegister dst) { | |
708 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
709 EmitUint8(0x0F); | |
710 EmitUint8(0x51); | |
711 EmitXmmRegisterOperand(dst, dst); | |
712 } | |
713 | |
714 void AssemblerX86::rsqrtps(XmmRegister dst) { | |
715 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
716 EmitUint8(0x0F); | |
717 EmitUint8(0x52); | |
718 EmitXmmRegisterOperand(dst, dst); | |
719 } | |
720 | |
721 void AssemblerX86::reciprocalps(XmmRegister dst) { | |
722 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
723 EmitUint8(0x0F); | |
724 EmitUint8(0x53); | |
725 EmitXmmRegisterOperand(dst, dst); | |
726 } | |
727 | |
728 void AssemblerX86::movhlps(XmmRegister dst, XmmRegister src) { | |
729 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
730 EmitUint8(0x0F); | |
731 EmitUint8(0x12); | |
732 EmitXmmRegisterOperand(dst, src); | |
733 } | |
734 | |
735 void AssemblerX86::movlhps(XmmRegister dst, XmmRegister src) { | |
736 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
737 EmitUint8(0x0F); | |
738 EmitUint8(0x16); | |
739 EmitXmmRegisterOperand(dst, src); | |
740 } | |
741 | |
742 void AssemblerX86::unpcklps(XmmRegister dst, XmmRegister src) { | |
743 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
744 EmitUint8(0x0F); | |
745 EmitUint8(0x14); | |
746 EmitXmmRegisterOperand(dst, src); | |
747 } | |
748 | |
749 void AssemblerX86::unpckhps(XmmRegister dst, XmmRegister src) { | |
750 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
751 EmitUint8(0x0F); | |
752 EmitUint8(0x15); | |
753 EmitXmmRegisterOperand(dst, src); | |
754 } | |
755 | |
756 void AssemblerX86::unpcklpd(XmmRegister dst, XmmRegister src) { | |
757 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
758 EmitUint8(0x66); | |
759 EmitUint8(0x0F); | |
760 EmitUint8(0x14); | |
761 EmitXmmRegisterOperand(dst, src); | |
762 } | |
763 | |
764 void AssemblerX86::unpckhpd(XmmRegister dst, XmmRegister src) { | |
765 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
766 EmitUint8(0x66); | |
767 EmitUint8(0x0F); | |
768 EmitUint8(0x15); | |
769 EmitXmmRegisterOperand(dst, src); | |
770 } | |
771 | |
772 void AssemblerX86::set1ps(XmmRegister dst, GPRRegister tmp1, | |
773 const Immediate &imm) { | |
774 // Load 32-bit immediate value into tmp1. | |
775 movl(tmp1, imm); | |
776 // Move value from tmp1 into dst. | |
777 movd(dst, tmp1); | |
778 // Broadcast low lane into other three lanes. | |
779 shufps(dst, dst, Immediate(0x0)); | |
780 } | |
781 | |
782 void AssemblerX86::shufps(XmmRegister dst, XmmRegister src, | |
783 const Immediate &imm) { | |
784 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
785 EmitUint8(0x0F); | |
786 EmitUint8(0xC6); | |
787 EmitXmmRegisterOperand(dst, src); | |
788 assert(imm.is_uint8()); | |
789 EmitUint8(imm.value()); | |
790 } | |
791 | |
792 void AssemblerX86::minpd(XmmRegister dst, XmmRegister src) { | |
793 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
794 EmitUint8(0x66); | |
795 EmitUint8(0x0F); | |
796 EmitUint8(0x5D); | |
797 EmitXmmRegisterOperand(dst, src); | |
798 } | |
799 | |
800 void AssemblerX86::maxpd(XmmRegister dst, XmmRegister src) { | |
801 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
802 EmitUint8(0x66); | |
803 EmitUint8(0x0F); | |
804 EmitUint8(0x5F); | |
805 EmitXmmRegisterOperand(dst, src); | |
806 } | |
807 | |
808 void AssemblerX86::sqrtpd(XmmRegister dst) { | |
809 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
810 EmitUint8(0x66); | |
811 EmitUint8(0x0F); | |
812 EmitUint8(0x51); | |
813 EmitXmmRegisterOperand(dst, dst); | |
814 } | |
815 | |
816 void AssemblerX86::cvtps2pd(XmmRegister dst, XmmRegister src) { | |
817 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
818 EmitUint8(0x0F); | |
819 EmitUint8(0x5A); | |
820 EmitXmmRegisterOperand(dst, src); | |
821 } | |
822 | |
823 void AssemblerX86::cvtpd2ps(XmmRegister dst, XmmRegister src) { | |
824 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
825 EmitUint8(0x66); | |
826 EmitUint8(0x0F); | |
827 EmitUint8(0x5A); | |
828 EmitXmmRegisterOperand(dst, src); | |
829 } | |
830 | |
831 void AssemblerX86::shufpd(XmmRegister dst, XmmRegister src, | |
832 const Immediate &imm) { | |
833 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
834 EmitUint8(0x66); | |
835 EmitUint8(0x0F); | |
836 EmitUint8(0xC6); | |
837 EmitXmmRegisterOperand(dst, src); | |
838 assert(imm.is_uint8()); | |
839 EmitUint8(imm.value()); | |
840 } | |
841 | |
842 void AssemblerX86::cvtsi2ss(XmmRegister dst, GPRRegister src) { | |
843 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
844 EmitUint8(0xF3); | |
845 EmitUint8(0x0F); | |
846 EmitUint8(0x2A); | |
847 EmitOperand(dst, Operand(src)); | |
848 } | |
849 | |
850 void AssemblerX86::cvtsi2sd(XmmRegister dst, GPRRegister src) { | |
851 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
852 EmitUint8(0xF2); | |
853 EmitUint8(0x0F); | |
854 EmitUint8(0x2A); | |
855 EmitOperand(dst, Operand(src)); | |
856 } | |
857 | |
858 void AssemblerX86::cvtss2si(GPRRegister dst, XmmRegister src) { | |
859 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
860 EmitUint8(0xF3); | |
861 EmitUint8(0x0F); | |
862 EmitUint8(0x2D); | |
863 EmitXmmRegisterOperand(dst, src); | |
864 } | |
865 | |
866 void AssemblerX86::cvtss2sd(XmmRegister dst, XmmRegister src) { | |
867 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
868 EmitUint8(0xF3); | |
869 EmitUint8(0x0F); | |
870 EmitUint8(0x5A); | |
871 EmitXmmRegisterOperand(dst, src); | |
872 } | |
873 | |
874 void AssemblerX86::cvtsd2si(GPRRegister dst, XmmRegister src) { | |
875 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
876 EmitUint8(0xF2); | |
877 EmitUint8(0x0F); | |
878 EmitUint8(0x2D); | |
879 EmitXmmRegisterOperand(dst, src); | |
880 } | |
881 | |
882 void AssemblerX86::cvttss2si(GPRRegister dst, XmmRegister src) { | |
883 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
884 EmitUint8(0xF3); | |
885 EmitUint8(0x0F); | |
886 EmitUint8(0x2C); | |
887 EmitXmmRegisterOperand(dst, src); | |
888 } | |
889 | |
890 void AssemblerX86::cvttsd2si(GPRRegister dst, XmmRegister src) { | |
891 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
892 EmitUint8(0xF2); | |
893 EmitUint8(0x0F); | |
894 EmitUint8(0x2C); | |
895 EmitXmmRegisterOperand(dst, src); | |
896 } | |
897 | |
898 void AssemblerX86::cvtsd2ss(XmmRegister dst, XmmRegister src) { | |
899 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
900 EmitUint8(0xF2); | |
901 EmitUint8(0x0F); | |
902 EmitUint8(0x5A); | |
903 EmitXmmRegisterOperand(dst, src); | |
904 } | |
905 | |
906 void AssemblerX86::cvtdq2pd(XmmRegister dst, XmmRegister src) { | |
907 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
908 EmitUint8(0xF3); | |
909 EmitUint8(0x0F); | |
910 EmitUint8(0xE6); | |
911 EmitXmmRegisterOperand(dst, src); | |
912 } | |
913 | |
914 void AssemblerX86::ucomiss(Type Ty, XmmRegister a, XmmRegister b) { | |
915 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
916 if (Ty == IceType_f64) | |
917 EmitUint8(0x66); | |
918 EmitUint8(0x0F); | |
919 EmitUint8(0x2E); | |
920 EmitXmmRegisterOperand(a, b); | |
921 } | |
922 | |
923 void AssemblerX86::ucomiss(Type Ty, XmmRegister a, const Address &b) { | |
924 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
925 if (Ty == IceType_f64) | |
926 EmitUint8(0x66); | |
927 EmitUint8(0x0F); | |
928 EmitUint8(0x2E); | |
929 EmitOperand(a, b); | |
930 } | |
931 | |
932 void AssemblerX86::movmskpd(GPRRegister dst, XmmRegister src) { | |
933 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
934 EmitUint8(0x66); | |
935 EmitUint8(0x0F); | |
936 EmitUint8(0x50); | |
937 EmitXmmRegisterOperand(dst, src); | |
938 } | |
939 | |
940 void AssemblerX86::movmskps(GPRRegister dst, XmmRegister src) { | |
941 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
942 EmitUint8(0x0F); | |
943 EmitUint8(0x50); | |
944 EmitXmmRegisterOperand(dst, src); | |
945 } | |
946 | |
947 void AssemblerX86::sqrtss(Type Ty, XmmRegister dst, const Address &src) { | |
948 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
949 EmitUint8(Ty == IceType_f32 ? 0xF3 : 0xF2); | |
950 EmitUint8(0x0F); | |
951 EmitUint8(0x51); | |
952 EmitOperand(dst, src); | |
953 } | |
954 | |
955 void AssemblerX86::sqrtss(Type Ty, XmmRegister dst, XmmRegister src) { | |
956 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
957 EmitUint8(Ty == IceType_f32 ? 0xF3 : 0xF2); | |
958 EmitUint8(0x0F); | |
959 EmitUint8(0x51); | |
960 EmitXmmRegisterOperand(dst, src); | |
961 } | |
962 | |
963 void AssemblerX86::xorpd(XmmRegister dst, const Address &src) { | |
964 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
965 EmitUint8(0x66); | |
966 EmitUint8(0x0F); | |
967 EmitUint8(0x57); | |
968 EmitOperand(dst, src); | |
969 } | |
970 | |
971 void AssemblerX86::xorpd(XmmRegister dst, XmmRegister src) { | |
972 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
973 EmitUint8(0x66); | |
974 EmitUint8(0x0F); | |
975 EmitUint8(0x57); | |
976 EmitXmmRegisterOperand(dst, src); | |
977 } | |
978 | |
979 void AssemblerX86::orpd(XmmRegister dst, XmmRegister src) { | |
980 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
981 EmitUint8(0x66); | |
982 EmitUint8(0x0F); | |
983 EmitUint8(0x56); | |
984 EmitXmmRegisterOperand(dst, src); | |
985 } | |
986 | |
987 void AssemblerX86::xorps(XmmRegister dst, const Address &src) { | |
988 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
989 EmitUint8(0x0F); | |
990 EmitUint8(0x57); | |
991 EmitOperand(dst, src); | |
992 } | |
993 | |
994 void AssemblerX86::xorps(XmmRegister dst, XmmRegister src) { | |
995 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
996 EmitUint8(0x0F); | |
997 EmitUint8(0x57); | |
998 EmitXmmRegisterOperand(dst, src); | |
999 } | |
1000 | |
1001 void AssemblerX86::andpd(XmmRegister dst, const Address &src) { | |
1002 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1003 EmitUint8(0x66); | |
1004 EmitUint8(0x0F); | |
1005 EmitUint8(0x54); | |
1006 EmitOperand(dst, src); | |
1007 } | |
1008 | |
1009 void AssemblerX86::andpd(XmmRegister dst, XmmRegister src) { | |
1010 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1011 EmitUint8(0x66); | |
1012 EmitUint8(0x0F); | |
1013 EmitUint8(0x54); | |
1014 EmitXmmRegisterOperand(dst, src); | |
1015 } | |
1016 | |
1017 void AssemblerX86::pextrd(GPRRegister dst, XmmRegister src, | |
1018 const Immediate &imm) { | |
1019 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1020 EmitUint8(0x66); | |
1021 EmitUint8(0x0F); | |
1022 EmitUint8(0x3A); | |
1023 EmitUint8(0x16); | |
1024 EmitOperand(src, Operand(dst)); | |
1025 assert(imm.is_uint8()); | |
1026 EmitUint8(imm.value()); | |
1027 } | |
1028 | |
1029 void AssemblerX86::pmovsxdq(XmmRegister dst, XmmRegister src) { | |
1030 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1031 EmitUint8(0x66); | |
1032 EmitUint8(0x0F); | |
1033 EmitUint8(0x38); | |
1034 EmitUint8(0x25); | |
1035 EmitXmmRegisterOperand(dst, src); | |
1036 } | |
1037 | |
1038 void AssemblerX86::pcmpeqq(XmmRegister dst, XmmRegister src) { | |
1039 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1040 EmitUint8(0x66); | |
1041 EmitUint8(0x0F); | |
1042 EmitUint8(0x38); | |
1043 EmitUint8(0x29); | |
1044 EmitXmmRegisterOperand(dst, src); | |
1045 } | |
1046 | |
1047 void AssemblerX86::pxor(XmmRegister dst, XmmRegister src) { | |
1048 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1049 EmitUint8(0x66); | |
1050 EmitUint8(0x0F); | |
1051 EmitUint8(0xEF); | |
1052 EmitXmmRegisterOperand(dst, src); | |
1053 } | |
1054 | |
1055 void AssemblerX86::roundsd(XmmRegister dst, XmmRegister src, | |
1056 RoundingMode mode) { | |
1057 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1058 EmitUint8(0x66); | |
1059 EmitUint8(0x0F); | |
1060 EmitUint8(0x3A); | |
1061 EmitUint8(0x0B); | |
1062 EmitXmmRegisterOperand(dst, src); | |
1063 // Mask precision exeption. | |
1064 EmitUint8(static_cast<uint8_t>(mode) | 0x8); | |
1065 } | |
1066 | |
1067 void AssemblerX86::fldl(const Address &src) { | |
1068 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1069 EmitUint8(0xDD); | |
1070 EmitOperand(0, src); | |
1071 } | |
1072 | |
1073 void AssemblerX86::fstpl(const Address &dst) { | |
1074 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1075 EmitUint8(0xDD); | |
1076 EmitOperand(3, dst); | |
1077 } | |
1078 | |
1079 void AssemblerX86::fnstcw(const Address &dst) { | |
1080 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1081 EmitUint8(0xD9); | |
1082 EmitOperand(7, dst); | |
1083 } | |
1084 | |
1085 void AssemblerX86::fldcw(const Address &src) { | |
1086 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1087 EmitUint8(0xD9); | |
1088 EmitOperand(5, src); | |
1089 } | |
1090 | |
1091 void AssemblerX86::fistpl(const Address &dst) { | |
1092 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1093 EmitUint8(0xDF); | |
1094 EmitOperand(7, dst); | |
1095 } | |
1096 | |
1097 void AssemblerX86::fistps(const Address &dst) { | |
1098 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1099 EmitUint8(0xDB); | |
1100 EmitOperand(3, dst); | |
1101 } | |
1102 | |
1103 void AssemblerX86::fildl(const Address &src) { | |
1104 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1105 EmitUint8(0xDF); | |
1106 EmitOperand(5, src); | |
1107 } | |
1108 | |
1109 void AssemblerX86::filds(const Address &src) { | |
1110 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1111 EmitUint8(0xDB); | |
1112 EmitOperand(0, src); | |
1113 } | |
1114 | |
1115 void AssemblerX86::fincstp() { | |
1116 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1117 EmitUint8(0xD9); | |
1118 EmitUint8(0xF7); | |
1119 } | |
1120 | |
1121 void AssemblerX86::xchgl(GPRRegister dst, GPRRegister src) { | |
1122 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1123 EmitUint8(0x87); | |
1124 EmitRegisterOperand(dst, src); | |
1125 } | |
1126 | |
1127 void AssemblerX86::cmpl(GPRRegister reg, const Immediate &imm) { | |
1128 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1129 EmitComplex(7, Operand(reg), imm); | |
1130 } | |
1131 | |
1132 void AssemblerX86::cmpl(GPRRegister reg0, GPRRegister reg1) { | |
1133 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1134 EmitUint8(0x3B); | |
1135 EmitOperand(reg0, Operand(reg1)); | |
1136 } | |
1137 | |
1138 void AssemblerX86::cmpl(GPRRegister reg, const Address &address) { | |
1139 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1140 EmitUint8(0x3B); | |
1141 EmitOperand(reg, address); | |
1142 } | |
1143 | |
1144 void AssemblerX86::addl(GPRRegister dst, GPRRegister src) { | |
1145 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1146 EmitUint8(0x03); | |
1147 EmitRegisterOperand(dst, src); | |
1148 } | |
1149 | |
1150 void AssemblerX86::addl(GPRRegister reg, const Address &address) { | |
1151 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1152 EmitUint8(0x03); | |
1153 EmitOperand(reg, address); | |
1154 } | |
1155 | |
1156 void AssemblerX86::cmpl(const Address &address, GPRRegister reg) { | |
1157 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1158 EmitUint8(0x39); | |
1159 EmitOperand(reg, address); | |
1160 } | |
1161 | |
1162 void AssemblerX86::cmpl(const Address &address, const Immediate &imm) { | |
1163 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1164 EmitComplex(7, address, imm); | |
1165 } | |
1166 | |
1167 void AssemblerX86::cmpb(const Address &address, const Immediate &imm) { | |
1168 assert(imm.is_int8()); | |
1169 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1170 EmitUint8(0x80); | |
1171 EmitOperand(7, address); | |
1172 EmitUint8(imm.value() & 0xFF); | |
1173 } | |
1174 | |
1175 void AssemblerX86::testl(GPRRegister reg1, GPRRegister reg2) { | |
1176 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1177 EmitUint8(0x85); | |
1178 EmitRegisterOperand(reg1, reg2); | |
1179 } | |
1180 | |
1181 void AssemblerX86::testl(GPRRegister reg, const Immediate &immediate) { | |
1182 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1183 // For registers that have a byte variant (EAX, EBX, ECX, and EDX) | |
1184 // we only test the byte register to keep the encoding short. | |
1185 if (immediate.is_uint8() && reg < 4) { | |
1186 // Use zero-extended 8-bit immediate. | |
1187 if (reg == RegX8632::Encoded_Reg_eax) { | |
1188 EmitUint8(0xA8); | |
1189 } else { | |
1190 EmitUint8(0xF6); | |
1191 EmitUint8(0xC0 + reg); | |
1192 } | |
1193 EmitUint8(immediate.value() & 0xFF); | |
1194 } else if (reg == RegX8632::Encoded_Reg_eax) { | |
1195 // Use short form if the destination is EAX. | |
1196 EmitUint8(0xA9); | |
1197 EmitImmediate(immediate); | |
1198 } else { | |
1199 EmitUint8(0xF7); | |
1200 EmitOperand(0, Operand(reg)); | |
1201 EmitImmediate(immediate); | |
1202 } | |
1203 } | |
1204 | |
1205 void AssemblerX86::andl(GPRRegister dst, GPRRegister src) { | |
1206 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1207 EmitUint8(0x23); | |
1208 EmitOperand(dst, Operand(src)); | |
1209 } | |
1210 | |
1211 void AssemblerX86::andl(GPRRegister dst, const Immediate &imm) { | |
1212 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1213 EmitComplex(4, Operand(dst), imm); | |
1214 } | |
1215 | |
1216 void AssemblerX86::andl(GPRRegister dst, const Address &address) { | |
1217 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1218 EmitUint8(0x23); | |
1219 EmitOperand(dst, address); | |
1220 } | |
1221 | |
1222 void AssemblerX86::orl(GPRRegister dst, GPRRegister src) { | |
1223 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1224 EmitUint8(0x0B); | |
1225 EmitOperand(dst, Operand(src)); | |
1226 } | |
1227 | |
1228 void AssemblerX86::orl(GPRRegister dst, const Immediate &imm) { | |
1229 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1230 EmitComplex(1, Operand(dst), imm); | |
1231 } | |
1232 | |
1233 void AssemblerX86::orl(GPRRegister dst, const Address &address) { | |
1234 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1235 EmitUint8(0x0B); | |
1236 EmitOperand(dst, address); | |
1237 } | |
1238 | |
1239 void AssemblerX86::xorl(GPRRegister dst, GPRRegister src) { | |
1240 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1241 EmitUint8(0x33); | |
1242 EmitOperand(dst, Operand(src)); | |
1243 } | |
1244 | |
1245 void AssemblerX86::xorl(GPRRegister dst, const Immediate &imm) { | |
1246 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1247 EmitComplex(6, Operand(dst), imm); | |
1248 } | |
1249 | |
1250 void AssemblerX86::xorl(GPRRegister dst, const Address &address) { | |
1251 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1252 EmitUint8(0x33); | |
1253 EmitOperand(dst, address); | |
1254 } | |
1255 | |
1256 void AssemblerX86::addl(GPRRegister reg, const Immediate &imm) { | |
1257 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1258 EmitComplex(0, Operand(reg), imm); | |
1259 } | |
1260 | |
1261 void AssemblerX86::addl(const Address &address, GPRRegister reg) { | |
1262 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1263 EmitUint8(0x01); | |
1264 EmitOperand(reg, address); | |
1265 } | |
1266 | |
1267 void AssemblerX86::addl(const Address &address, const Immediate &imm) { | |
1268 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1269 EmitComplex(0, address, imm); | |
1270 } | |
1271 | |
1272 void AssemblerX86::adcl(GPRRegister reg, const Immediate &imm) { | |
1273 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1274 EmitComplex(2, Operand(reg), imm); | |
1275 } | |
1276 | |
1277 void AssemblerX86::adcl(GPRRegister dst, GPRRegister src) { | |
1278 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1279 EmitUint8(0x13); | |
1280 EmitOperand(dst, Operand(src)); | |
1281 } | |
1282 | |
1283 void AssemblerX86::adcl(GPRRegister dst, const Address &address) { | |
1284 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1285 EmitUint8(0x13); | |
1286 EmitOperand(dst, address); | |
1287 } | |
1288 | |
1289 void AssemblerX86::adcl(const Address &address, GPRRegister reg) { | |
1290 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1291 EmitUint8(0x11); | |
1292 EmitOperand(reg, address); | |
1293 } | |
1294 | |
1295 void AssemblerX86::subl(GPRRegister dst, GPRRegister src) { | |
1296 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1297 EmitUint8(0x2B); | |
1298 EmitOperand(dst, Operand(src)); | |
1299 } | |
1300 | |
1301 void AssemblerX86::subl(GPRRegister reg, const Immediate &imm) { | |
1302 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1303 EmitComplex(5, Operand(reg), imm); | |
1304 } | |
1305 | |
1306 void AssemblerX86::subl(GPRRegister reg, const Address &address) { | |
1307 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1308 EmitUint8(0x2B); | |
1309 EmitOperand(reg, address); | |
1310 } | |
1311 | |
1312 void AssemblerX86::subl(const Address &address, GPRRegister reg) { | |
1313 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1314 EmitUint8(0x29); | |
1315 EmitOperand(reg, address); | |
1316 } | |
1317 | |
1318 void AssemblerX86::cdq() { | |
1319 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1320 EmitUint8(0x99); | |
1321 } | |
1322 | |
1323 void AssemblerX86::idivl(GPRRegister reg) { | |
1324 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1325 EmitUint8(0xF7); | |
1326 EmitUint8(0xF8 | reg); | |
1327 } | |
1328 | |
1329 void AssemblerX86::imull(GPRRegister dst, GPRRegister src) { | |
1330 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1331 EmitUint8(0x0F); | |
1332 EmitUint8(0xAF); | |
1333 EmitOperand(dst, Operand(src)); | |
1334 } | |
1335 | |
1336 void AssemblerX86::imull(GPRRegister reg, const Immediate &imm) { | |
1337 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1338 EmitUint8(0x69); | |
1339 EmitOperand(reg, Operand(reg)); | |
1340 EmitImmediate(imm); | |
1341 } | |
1342 | |
1343 void AssemblerX86::imull(GPRRegister reg, const Address &address) { | |
1344 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1345 EmitUint8(0x0F); | |
1346 EmitUint8(0xAF); | |
1347 EmitOperand(reg, address); | |
1348 } | |
1349 | |
1350 void AssemblerX86::imull(GPRRegister reg) { | |
1351 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1352 EmitUint8(0xF7); | |
1353 EmitOperand(5, Operand(reg)); | |
1354 } | |
1355 | |
1356 void AssemblerX86::imull(const Address &address) { | |
1357 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1358 EmitUint8(0xF7); | |
1359 EmitOperand(5, address); | |
1360 } | |
1361 | |
1362 void AssemblerX86::mull(GPRRegister reg) { | |
1363 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1364 EmitUint8(0xF7); | |
1365 EmitOperand(4, Operand(reg)); | |
1366 } | |
1367 | |
1368 void AssemblerX86::mull(const Address &address) { | |
1369 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1370 EmitUint8(0xF7); | |
1371 EmitOperand(4, address); | |
1372 } | |
1373 | |
1374 void AssemblerX86::sbbl(GPRRegister dst, GPRRegister src) { | |
1375 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1376 EmitUint8(0x1B); | |
1377 EmitOperand(dst, Operand(src)); | |
1378 } | |
1379 | |
1380 void AssemblerX86::sbbl(GPRRegister reg, const Immediate &imm) { | |
1381 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1382 EmitComplex(3, Operand(reg), imm); | |
1383 } | |
1384 | |
1385 void AssemblerX86::sbbl(GPRRegister dst, const Address &address) { | |
1386 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1387 EmitUint8(0x1B); | |
1388 EmitOperand(dst, address); | |
1389 } | |
1390 | |
1391 void AssemblerX86::sbbl(const Address &address, GPRRegister dst) { | |
1392 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1393 EmitUint8(0x19); | |
1394 EmitOperand(dst, address); | |
1395 } | |
1396 | |
1397 void AssemblerX86::incl(GPRRegister reg) { | |
1398 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1399 EmitUint8(0x40 + reg); | |
1400 } | |
1401 | |
1402 void AssemblerX86::incl(const Address &address) { | |
1403 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1404 EmitUint8(0xFF); | |
1405 EmitOperand(0, address); | |
1406 } | |
1407 | |
1408 void AssemblerX86::decl(GPRRegister reg) { | |
1409 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1410 EmitUint8(0x48 + reg); | |
1411 } | |
1412 | |
1413 void AssemblerX86::decl(const Address &address) { | |
1414 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1415 EmitUint8(0xFF); | |
1416 EmitOperand(1, address); | |
1417 } | |
1418 | |
1419 void AssemblerX86::shll(GPRRegister reg, const Immediate &imm) { | |
1420 EmitGenericShift(4, reg, imm); | |
1421 } | |
1422 | |
1423 void AssemblerX86::shll(GPRRegister operand, GPRRegister shifter) { | |
1424 EmitGenericShift(4, Operand(operand), shifter); | |
1425 } | |
1426 | |
1427 void AssemblerX86::shll(const Address &operand, GPRRegister shifter) { | |
1428 EmitGenericShift(4, Operand(operand), shifter); | |
1429 } | |
1430 | |
1431 void AssemblerX86::shrl(GPRRegister reg, const Immediate &imm) { | |
1432 EmitGenericShift(5, reg, imm); | |
1433 } | |
1434 | |
1435 void AssemblerX86::shrl(GPRRegister operand, GPRRegister shifter) { | |
1436 EmitGenericShift(5, Operand(operand), shifter); | |
1437 } | |
1438 | |
1439 void AssemblerX86::sarl(GPRRegister reg, const Immediate &imm) { | |
1440 EmitGenericShift(7, reg, imm); | |
1441 } | |
1442 | |
1443 void AssemblerX86::sarl(GPRRegister operand, GPRRegister shifter) { | |
1444 EmitGenericShift(7, Operand(operand), shifter); | |
1445 } | |
1446 | |
1447 void AssemblerX86::sarl(const Address &address, GPRRegister shifter) { | |
1448 EmitGenericShift(7, Operand(address), shifter); | |
1449 } | |
1450 | |
1451 void AssemblerX86::shld(GPRRegister dst, GPRRegister src) { | |
1452 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1453 EmitUint8(0x0F); | |
1454 EmitUint8(0xA5); | |
1455 EmitRegisterOperand(src, dst); | |
1456 } | |
1457 | |
1458 void AssemblerX86::shld(GPRRegister dst, GPRRegister src, | |
1459 const Immediate &imm) { | |
1460 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1461 assert(imm.is_int8()); | |
1462 EmitUint8(0x0F); | |
1463 EmitUint8(0xA4); | |
1464 EmitRegisterOperand(src, dst); | |
1465 EmitUint8(imm.value() & 0xFF); | |
1466 } | |
1467 | |
1468 void AssemblerX86::shld(const Address &operand, GPRRegister src) { | |
1469 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1470 EmitUint8(0x0F); | |
1471 EmitUint8(0xA5); | |
1472 EmitOperand(src, Operand(operand)); | |
1473 } | |
1474 | |
1475 void AssemblerX86::shrd(GPRRegister dst, GPRRegister src) { | |
1476 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1477 EmitUint8(0x0F); | |
1478 EmitUint8(0xAD); | |
1479 EmitRegisterOperand(src, dst); | |
1480 } | |
1481 | |
1482 void AssemblerX86::shrd(GPRRegister dst, GPRRegister src, | |
1483 const Immediate &imm) { | |
1484 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1485 assert(imm.is_int8()); | |
1486 EmitUint8(0x0F); | |
1487 EmitUint8(0xAC); | |
1488 EmitRegisterOperand(src, dst); | |
1489 EmitUint8(imm.value() & 0xFF); | |
1490 } | |
1491 | |
1492 void AssemblerX86::shrd(const Address &dst, GPRRegister src) { | |
1493 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1494 EmitUint8(0x0F); | |
1495 EmitUint8(0xAD); | |
1496 EmitOperand(src, Operand(dst)); | |
1497 } | |
1498 | |
1499 void AssemblerX86::negl(GPRRegister reg) { | |
1500 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1501 EmitUint8(0xF7); | |
1502 EmitOperand(3, Operand(reg)); | |
1503 } | |
1504 | |
1505 void AssemblerX86::notl(GPRRegister reg) { | |
1506 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1507 EmitUint8(0xF7); | |
1508 EmitUint8(0xD0 | reg); | |
1509 } | |
1510 | |
1511 void AssemblerX86::bsrl(GPRRegister dst, GPRRegister src) { | |
1512 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1513 EmitUint8(0x0F); | |
1514 EmitUint8(0xBD); | |
1515 EmitRegisterOperand(dst, src); | |
1516 } | |
1517 | |
1518 void AssemblerX86::bt(GPRRegister base, GPRRegister offset) { | |
1519 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1520 EmitUint8(0x0F); | |
1521 EmitUint8(0xA3); | |
1522 EmitRegisterOperand(offset, base); | |
1523 } | |
1524 | |
1525 void AssemblerX86::ret() { | |
1526 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1527 EmitUint8(0xC3); | |
1528 } | |
1529 | |
1530 void AssemblerX86::ret(const Immediate &imm) { | |
1531 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1532 EmitUint8(0xC2); | |
1533 assert(imm.is_uint16()); | |
1534 EmitUint8(imm.value() & 0xFF); | |
1535 EmitUint8((imm.value() >> 8) & 0xFF); | |
1536 } | |
1537 | |
1538 void AssemblerX86::nop(int size) { | |
1539 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1540 // There are nops up to size 15, but for now just provide up to size 8. | |
1541 assert(0 < size && size <= MAX_NOP_SIZE); | |
1542 switch (size) { | |
1543 case 1: | |
1544 EmitUint8(0x90); | |
1545 break; | |
1546 case 2: | |
1547 EmitUint8(0x66); | |
1548 EmitUint8(0x90); | |
1549 break; | |
1550 case 3: | |
1551 EmitUint8(0x0F); | |
1552 EmitUint8(0x1F); | |
1553 EmitUint8(0x00); | |
1554 break; | |
1555 case 4: | |
1556 EmitUint8(0x0F); | |
1557 EmitUint8(0x1F); | |
1558 EmitUint8(0x40); | |
1559 EmitUint8(0x00); | |
1560 break; | |
1561 case 5: | |
1562 EmitUint8(0x0F); | |
1563 EmitUint8(0x1F); | |
1564 EmitUint8(0x44); | |
1565 EmitUint8(0x00); | |
1566 EmitUint8(0x00); | |
1567 break; | |
1568 case 6: | |
1569 EmitUint8(0x66); | |
1570 EmitUint8(0x0F); | |
1571 EmitUint8(0x1F); | |
1572 EmitUint8(0x44); | |
1573 EmitUint8(0x00); | |
1574 EmitUint8(0x00); | |
1575 break; | |
1576 case 7: | |
1577 EmitUint8(0x0F); | |
1578 EmitUint8(0x1F); | |
1579 EmitUint8(0x80); | |
1580 EmitUint8(0x00); | |
1581 EmitUint8(0x00); | |
1582 EmitUint8(0x00); | |
1583 EmitUint8(0x00); | |
1584 break; | |
1585 case 8: | |
1586 EmitUint8(0x0F); | |
1587 EmitUint8(0x1F); | |
1588 EmitUint8(0x84); | |
1589 EmitUint8(0x00); | |
1590 EmitUint8(0x00); | |
1591 EmitUint8(0x00); | |
1592 EmitUint8(0x00); | |
1593 EmitUint8(0x00); | |
1594 break; | |
1595 default: | |
1596 llvm_unreachable("Unimplemented"); | |
1597 } | |
1598 } | |
1599 | |
1600 void AssemblerX86::int3() { | |
1601 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1602 EmitUint8(0xCC); | |
1603 } | |
1604 | |
1605 void AssemblerX86::hlt() { | |
1606 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1607 EmitUint8(0xF4); | |
1608 } | |
1609 | |
1610 void AssemblerX86::j(CondX86::BrCond condition, Label *label, bool near) { | |
1611 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1612 if (label->IsBound()) { | |
1613 static const int kShortSize = 2; | |
1614 static const int kLongSize = 6; | |
1615 intptr_t offset = label->Position() - buffer_.Size(); | |
1616 assert(offset <= 0); | |
1617 if (Utils::IsInt(8, offset - kShortSize)) { | |
1618 EmitUint8(0x70 + condition); | |
1619 EmitUint8((offset - kShortSize) & 0xFF); | |
1620 } else { | |
1621 EmitUint8(0x0F); | |
1622 EmitUint8(0x80 + condition); | |
1623 EmitInt32(offset - kLongSize); | |
1624 } | |
1625 } else if (near) { | |
1626 EmitUint8(0x70 + condition); | |
1627 EmitNearLabelLink(label); | |
1628 } else { | |
1629 EmitUint8(0x0F); | |
1630 EmitUint8(0x80 + condition); | |
1631 EmitLabelLink(label); | |
1632 } | |
1633 } | |
1634 | |
1635 void AssemblerX86::j(CondX86::BrCond condition, | |
1636 const ConstantRelocatable *label) { | |
1637 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1638 EmitUint8(0x0F); | |
1639 EmitUint8(0x80 + condition); | |
1640 EmitFixup(DirectCallRelocation::create(this, FK_PcRel_4, label)); | |
1641 EmitInt32(-4); | |
1642 } | |
1643 | |
1644 void AssemblerX86::jmp(GPRRegister reg) { | |
1645 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1646 EmitUint8(0xFF); | |
1647 EmitRegisterOperand(4, reg); | |
1648 } | |
1649 | |
1650 void AssemblerX86::jmp(Label *label, bool near) { | |
1651 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1652 if (label->IsBound()) { | |
1653 static const int kShortSize = 2; | |
1654 static const int kLongSize = 5; | |
1655 intptr_t offset = label->Position() - buffer_.Size(); | |
1656 assert(offset <= 0); | |
1657 if (Utils::IsInt(8, offset - kShortSize)) { | |
1658 EmitUint8(0xEB); | |
1659 EmitUint8((offset - kShortSize) & 0xFF); | |
1660 } else { | |
1661 EmitUint8(0xE9); | |
1662 EmitInt32(offset - kLongSize); | |
1663 } | |
1664 } else if (near) { | |
1665 EmitUint8(0xEB); | |
1666 EmitNearLabelLink(label); | |
1667 } else { | |
1668 EmitUint8(0xE9); | |
1669 EmitLabelLink(label); | |
1670 } | |
1671 } | |
1672 | |
1673 void AssemblerX86::jmp(const ConstantRelocatable *label) { | |
1674 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1675 EmitUint8(0xE9); | |
1676 EmitFixup(DirectCallRelocation::create(this, FK_PcRel_4, label)); | |
1677 EmitInt32(-4); | |
1678 } | |
1679 | |
1680 void AssemblerX86::lock() { | |
1681 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1682 EmitUint8(0xF0); | |
1683 } | |
1684 | |
1685 void AssemblerX86::cmpxchgl(const Address &address, GPRRegister reg) { | |
1686 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1687 EmitUint8(0x0F); | |
1688 EmitUint8(0xB1); | |
1689 EmitOperand(reg, address); | |
1690 } | |
1691 | |
1692 void AssemblerX86::Align(intptr_t alignment, intptr_t offset) { | |
1693 assert(llvm::isPowerOf2_32(alignment)); | |
1694 intptr_t pos = offset + buffer_.GetPosition(); | |
1695 intptr_t mod = pos & (alignment - 1); | |
1696 if (mod == 0) { | |
1697 return; | |
1698 } | |
1699 intptr_t bytes_needed = alignment - mod; | |
1700 while (bytes_needed > MAX_NOP_SIZE) { | |
1701 nop(MAX_NOP_SIZE); | |
1702 bytes_needed -= MAX_NOP_SIZE; | |
1703 } | |
1704 if (bytes_needed) { | |
1705 nop(bytes_needed); | |
1706 } | |
1707 assert(((offset + buffer_.GetPosition()) & (alignment - 1)) == 0); | |
1708 } | |
1709 | |
1710 void AssemblerX86::Bind(Label *label) { | |
1711 intptr_t bound = buffer_.Size(); | |
1712 assert(!label->IsBound()); // Labels can only be bound once. | |
1713 while (label->IsLinked()) { | |
1714 intptr_t position = label->LinkPosition(); | |
1715 intptr_t next = buffer_.Load<int32_t>(position); | |
1716 buffer_.Store<int32_t>(position, bound - (position + 4)); | |
1717 label->position_ = next; | |
1718 } | |
1719 while (label->HasNear()) { | |
1720 intptr_t position = label->NearPosition(); | |
1721 intptr_t offset = bound - (position + 1); | |
1722 assert(Utils::IsInt(8, offset)); | |
1723 buffer_.Store<int8_t>(position, offset); | |
1724 } | |
1725 label->BindTo(bound); | |
1726 } | |
1727 | |
1728 void AssemblerX86::EmitOperand(int rm, const Operand &operand) { | |
1729 assert(rm >= 0 && rm < 8); | |
1730 const intptr_t length = operand.length_; | |
1731 assert(length > 0); | |
1732 // Emit the ModRM byte updated with the given RM value. | |
1733 assert((operand.encoding_[0] & 0x38) == 0); | |
1734 EmitUint8(operand.encoding_[0] + (rm << 3)); | |
1735 if (operand.fixup()) { | |
1736 EmitFixup(operand.fixup()); | |
1737 } | |
1738 // Emit the rest of the encoded operand. | |
1739 for (intptr_t i = 1; i < length; i++) { | |
1740 EmitUint8(operand.encoding_[i]); | |
1741 } | |
1742 } | |
1743 | |
1744 void AssemblerX86::EmitImmediate(const Immediate &imm) { | |
1745 EmitInt32(imm.value()); | |
1746 } | |
1747 | |
1748 void AssemblerX86::EmitComplexI8(int rm, const Operand &operand, | |
1749 const Immediate &immediate) { | |
1750 assert(rm >= 0 && rm < 8); | |
1751 assert(immediate.is_int8()); | |
1752 if (operand.IsRegister(RegX8632::Encoded_Reg_eax)) { | |
1753 // Use short form if the destination is al. | |
1754 EmitUint8(0x04 + (rm << 3)); | |
1755 EmitUint8(immediate.value() & 0xFF); | |
1756 } else { | |
1757 // Use sign-extended 8-bit immediate. | |
1758 EmitUint8(0x80); | |
1759 EmitOperand(rm, operand); | |
1760 EmitUint8(immediate.value() & 0xFF); | |
1761 } | |
1762 } | |
1763 | |
1764 void AssemblerX86::EmitComplex(int rm, const Operand &operand, | |
1765 const Immediate &immediate) { | |
1766 assert(rm >= 0 && rm < 8); | |
1767 if (immediate.is_int8()) { | |
1768 // Use sign-extended 8-bit immediate. | |
1769 EmitUint8(0x83); | |
1770 EmitOperand(rm, operand); | |
1771 EmitUint8(immediate.value() & 0xFF); | |
1772 } else if (operand.IsRegister(RegX8632::Encoded_Reg_eax)) { | |
1773 // Use short form if the destination is eax. | |
1774 EmitUint8(0x05 + (rm << 3)); | |
1775 EmitImmediate(immediate); | |
1776 } else { | |
1777 EmitUint8(0x81); | |
1778 EmitOperand(rm, operand); | |
1779 EmitImmediate(immediate); | |
1780 } | |
1781 } | |
1782 | |
1783 void AssemblerX86::EmitLabel(Label *label, intptr_t instruction_size) { | |
1784 if (label->IsBound()) { | |
1785 intptr_t offset = label->Position() - buffer_.Size(); | |
1786 assert(offset <= 0); | |
1787 EmitInt32(offset - instruction_size); | |
1788 } else { | |
1789 EmitLabelLink(label); | |
1790 } | |
1791 } | |
1792 | |
1793 void AssemblerX86::EmitLabelLink(Label *label) { | |
1794 assert(!label->IsBound()); | |
1795 intptr_t position = buffer_.Size(); | |
1796 EmitInt32(label->position_); | |
1797 label->LinkTo(position); | |
1798 } | |
1799 | |
1800 void AssemblerX86::EmitNearLabelLink(Label *label) { | |
1801 assert(!label->IsBound()); | |
1802 intptr_t position = buffer_.Size(); | |
1803 EmitUint8(0); | |
1804 label->NearLinkTo(position); | |
1805 } | |
1806 | |
1807 void AssemblerX86::EmitGenericShift(int rm, GPRRegister reg, | |
1808 const Immediate &imm) { | |
1809 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1810 assert(imm.is_int8()); | |
1811 if (imm.value() == 1) { | |
1812 EmitUint8(0xD1); | |
1813 EmitOperand(rm, Operand(reg)); | |
1814 } else { | |
1815 EmitUint8(0xC1); | |
1816 EmitOperand(rm, Operand(reg)); | |
1817 EmitUint8(imm.value() & 0xFF); | |
1818 } | |
1819 } | |
1820 | |
1821 void AssemblerX86::EmitGenericShift(int rm, const Operand &operand, | |
1822 GPRRegister shifter) { | |
1823 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1824 assert(shifter == RegX8632::Encoded_Reg_ecx); | |
1825 EmitUint8(0xD3); | |
1826 EmitOperand(rm, Operand(operand)); | |
1827 } | |
1828 | |
1829 } // end of namespace x86 | |
1830 } // end of namespace Ice | |
OLD | NEW |