1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions
6 // are met:
7 //
8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // - Redistribution in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the
14 // distribution.
15 //
16 // - Neither the name of Sun Microsystems or the names of contributors may
17 // be used to endorse or promote products derived from this software without
18 // specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 // OF THE POSSIBILITY OF SUCH DAMAGE.
32
33 // The original source code covered by the above license above has been modified
34 // significantly by Google Inc.
35 // Copyright 2012 the V8 project authors. All rights reserved.
36
37 #include "src/ia32/assembler-ia32.h"
38
39 #include <cstring>
40
41 #if V8_TARGET_ARCH_IA32
42
43 #if V8_LIBC_MSVCRT
44 #include <intrin.h> // _xgetbv()
45 #endif
46 #if V8_OS_MACOSX
47 #include <sys/sysctl.h>
48 #endif
49
50 #include "src/base/bits.h"
51 #include "src/base/cpu.h"
52 #include "src/disassembler.h"
53 #include "src/macro-assembler.h"
54 #include "src/v8.h"
55
56 namespace v8 {
57 namespace internal {
58
59 // -----------------------------------------------------------------------------
60 // Implementation of CpuFeatures
61
62 namespace {
63
64 #if !V8_LIBC_MSVCRT
65
_xgetbv(unsigned int xcr)66 V8_INLINE uint64_t _xgetbv(unsigned int xcr) {
67 unsigned eax, edx;
68 // Check xgetbv; this uses a .byte sequence instead of the instruction
69 // directly because older assemblers do not include support for xgetbv and
70 // there is no easy way to conditionally compile based on the assembler
71 // used.
72 __asm__ volatile(".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(xcr));
73 return static_cast<uint64_t>(eax) | (static_cast<uint64_t>(edx) << 32);
74 }
75
76 #define _XCR_XFEATURE_ENABLED_MASK 0
77
78 #endif // !V8_LIBC_MSVCRT
79
80
OSHasAVXSupport()81 bool OSHasAVXSupport() {
82 #if V8_OS_MACOSX
83 // Mac OS X up to 10.9 has a bug where AVX transitions were indeed being
84 // caused by ISRs, so we detect that here and disable AVX in that case.
85 char buffer[128];
86 size_t buffer_size = arraysize(buffer);
87 int ctl_name[] = {CTL_KERN, KERN_OSRELEASE};
88 if (sysctl(ctl_name, 2, buffer, &buffer_size, nullptr, 0) != 0) {
89 V8_Fatal(__FILE__, __LINE__, "V8 failed to get kernel version");
90 }
91 // The buffer now contains a string of the form XX.YY.ZZ, where
92 // XX is the major kernel version component.
93 char* period_pos = strchr(buffer, '.');
94 DCHECK_NOT_NULL(period_pos);
95 *period_pos = '\0';
96 long kernel_version_major = strtol(buffer, nullptr, 10); // NOLINT
97 if (kernel_version_major <= 13) return false;
98 #endif // V8_OS_MACOSX
99 // Check whether OS claims to support AVX.
100 uint64_t feature_mask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
101 return (feature_mask & 0x6) == 0x6;
102 }
103
104 } // namespace
105
106
ProbeImpl(bool cross_compile)107 void CpuFeatures::ProbeImpl(bool cross_compile) {
108 base::CPU cpu;
109 CHECK(cpu.has_sse2()); // SSE2 support is mandatory.
110 CHECK(cpu.has_cmov()); // CMOV support is mandatory.
111
112 // Only use statically determined features for cross compile (snapshot).
113 if (cross_compile) return;
114
115 if (cpu.has_sse41() && FLAG_enable_sse4_1) supported_ |= 1u << SSE4_1;
116 if (cpu.has_sse3() && FLAG_enable_sse3) supported_ |= 1u << SSE3;
117 if (cpu.has_avx() && FLAG_enable_avx && cpu.has_osxsave() &&
118 OSHasAVXSupport()) {
119 supported_ |= 1u << AVX;
120 }
121 if (cpu.has_fma3() && FLAG_enable_fma3 && cpu.has_osxsave() &&
122 OSHasAVXSupport()) {
123 supported_ |= 1u << FMA3;
124 }
125 if (cpu.has_bmi1() && FLAG_enable_bmi1) supported_ |= 1u << BMI1;
126 if (cpu.has_bmi2() && FLAG_enable_bmi2) supported_ |= 1u << BMI2;
127 if (cpu.has_lzcnt() && FLAG_enable_lzcnt) supported_ |= 1u << LZCNT;
128 if (cpu.has_popcnt() && FLAG_enable_popcnt) supported_ |= 1u << POPCNT;
129 if (strcmp(FLAG_mcpu, "auto") == 0) {
130 if (cpu.is_atom()) supported_ |= 1u << ATOM;
131 } else if (strcmp(FLAG_mcpu, "atom") == 0) {
132 supported_ |= 1u << ATOM;
133 }
134 }
135
136
PrintTarget()137 void CpuFeatures::PrintTarget() { }
PrintFeatures()138 void CpuFeatures::PrintFeatures() {
139 printf(
140 "SSE3=%d SSE4_1=%d AVX=%d FMA3=%d BMI1=%d BMI2=%d LZCNT=%d POPCNT=%d "
141 "ATOM=%d\n",
142 CpuFeatures::IsSupported(SSE3), CpuFeatures::IsSupported(SSE4_1),
143 CpuFeatures::IsSupported(AVX), CpuFeatures::IsSupported(FMA3),
144 CpuFeatures::IsSupported(BMI1), CpuFeatures::IsSupported(BMI2),
145 CpuFeatures::IsSupported(LZCNT), CpuFeatures::IsSupported(POPCNT),
146 CpuFeatures::IsSupported(ATOM));
147 }
148
149
150 // -----------------------------------------------------------------------------
151 // Implementation of Displacement
152
init(Label * L,Type type)153 void Displacement::init(Label* L, Type type) {
154 DCHECK(!L->is_bound());
155 int next = 0;
156 if (L->is_linked()) {
157 next = L->pos();
158 DCHECK(next > 0); // Displacements must be at positions > 0
159 }
160 // Ensure that we _never_ overflow the next field.
161 DCHECK(NextField::is_valid(Assembler::kMaximalBufferSize));
162 data_ = NextField::encode(next) | TypeField::encode(type);
163 }
164
165
166 // -----------------------------------------------------------------------------
167 // Implementation of RelocInfo
168
169
170 const int RelocInfo::kApplyMask =
171 RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
172 1 << RelocInfo::INTERNAL_REFERENCE | 1 << RelocInfo::CODE_AGE_SEQUENCE |
173 RelocInfo::kDebugBreakSlotMask;
174
175
IsCodedSpecially()176 bool RelocInfo::IsCodedSpecially() {
177 // The deserializer needs to know whether a pointer is specially coded. Being
178 // specially coded on IA32 means that it is a relative address, as used by
179 // branch instructions. These are also the ones that need changing when a
180 // code object moves.
181 return (1 << rmode_) & kApplyMask;
182 }
183
184
IsInConstantPool()185 bool RelocInfo::IsInConstantPool() {
186 return false;
187 }
188
wasm_memory_reference()189 Address RelocInfo::wasm_memory_reference() {
190 DCHECK(IsWasmMemoryReference(rmode_));
191 return Memory::Address_at(pc_);
192 }
193
wasm_global_reference()194 Address RelocInfo::wasm_global_reference() {
195 DCHECK(IsWasmGlobalReference(rmode_));
196 return Memory::Address_at(pc_);
197 }
198
wasm_memory_size_reference()199 uint32_t RelocInfo::wasm_memory_size_reference() {
200 DCHECK(IsWasmMemorySizeReference(rmode_));
201 return Memory::uint32_at(pc_);
202 }
203
unchecked_update_wasm_memory_reference(Address address,ICacheFlushMode flush_mode)204 void RelocInfo::unchecked_update_wasm_memory_reference(
205 Address address, ICacheFlushMode flush_mode) {
206 Memory::Address_at(pc_) = address;
207 }
208
unchecked_update_wasm_memory_size(uint32_t size,ICacheFlushMode flush_mode)209 void RelocInfo::unchecked_update_wasm_memory_size(uint32_t size,
210 ICacheFlushMode flush_mode) {
211 Memory::uint32_at(pc_) = size;
212 }
213
214 // -----------------------------------------------------------------------------
215 // Implementation of Operand
216
Operand(Register base,int32_t disp,RelocInfo::Mode rmode)217 Operand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) {
218 // [base + disp/r]
219 if (disp == 0 && RelocInfo::IsNone(rmode) && !base.is(ebp)) {
220 // [base]
221 set_modrm(0, base);
222 if (base.is(esp)) set_sib(times_1, esp, base);
223 } else if (is_int8(disp) && RelocInfo::IsNone(rmode)) {
224 // [base + disp8]
225 set_modrm(1, base);
226 if (base.is(esp)) set_sib(times_1, esp, base);
227 set_disp8(disp);
228 } else {
229 // [base + disp/r]
230 set_modrm(2, base);
231 if (base.is(esp)) set_sib(times_1, esp, base);
232 set_dispr(disp, rmode);
233 }
234 }
235
236
Operand(Register base,Register index,ScaleFactor scale,int32_t disp,RelocInfo::Mode rmode)237 Operand::Operand(Register base,
238 Register index,
239 ScaleFactor scale,
240 int32_t disp,
241 RelocInfo::Mode rmode) {
242 DCHECK(!index.is(esp)); // illegal addressing mode
243 // [base + index*scale + disp/r]
244 if (disp == 0 && RelocInfo::IsNone(rmode) && !base.is(ebp)) {
245 // [base + index*scale]
246 set_modrm(0, esp);
247 set_sib(scale, index, base);
248 } else if (is_int8(disp) && RelocInfo::IsNone(rmode)) {
249 // [base + index*scale + disp8]
250 set_modrm(1, esp);
251 set_sib(scale, index, base);
252 set_disp8(disp);
253 } else {
254 // [base + index*scale + disp/r]
255 set_modrm(2, esp);
256 set_sib(scale, index, base);
257 set_dispr(disp, rmode);
258 }
259 }
260
261
Operand(Register index,ScaleFactor scale,int32_t disp,RelocInfo::Mode rmode)262 Operand::Operand(Register index,
263 ScaleFactor scale,
264 int32_t disp,
265 RelocInfo::Mode rmode) {
266 DCHECK(!index.is(esp)); // illegal addressing mode
267 // [index*scale + disp/r]
268 set_modrm(0, esp);
269 set_sib(scale, index, ebp);
270 set_dispr(disp, rmode);
271 }
272
273
is_reg(Register reg) const274 bool Operand::is_reg(Register reg) const {
275 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only.
276 && ((buf_[0] & 0x07) == reg.code()); // register codes match.
277 }
278
279
is_reg_only() const280 bool Operand::is_reg_only() const {
281 return (buf_[0] & 0xF8) == 0xC0; // Addressing mode is register only.
282 }
283
284
reg() const285 Register Operand::reg() const {
286 DCHECK(is_reg_only());
287 return Register::from_code(buf_[0] & 0x07);
288 }
289
290
291 // -----------------------------------------------------------------------------
292 // Implementation of Assembler.
293
294 // Emit a single byte. Must always be inlined.
295 #define EMIT(x) \
296 *pc_++ = (x)
297
Assembler(Isolate * isolate,void * buffer,int buffer_size)298 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
299 : AssemblerBase(isolate, buffer, buffer_size) {
300 // Clear the buffer in debug mode unless it was provided by the
301 // caller in which case we can't be sure it's okay to overwrite
302 // existing code in it; see CodePatcher::CodePatcher(...).
303 #ifdef DEBUG
304 if (own_buffer_) {
305 memset(buffer_, 0xCC, buffer_size_); // int3
306 }
307 #endif
308
309 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
310 }
311
312
GetCode(CodeDesc * desc)313 void Assembler::GetCode(CodeDesc* desc) {
314 // Finalize code (at this point overflow() may be true, but the gap ensures
315 // that we are still not overlapping instructions and relocation info).
316 DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap.
317 // Set up code descriptor.
318 desc->buffer = buffer_;
319 desc->buffer_size = buffer_size_;
320 desc->instr_size = pc_offset();
321 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
322 desc->origin = this;
323 desc->constant_pool_size = 0;
324 desc->unwinding_info_size = 0;
325 desc->unwinding_info = nullptr;
326 }
327
328
Align(int m)329 void Assembler::Align(int m) {
330 DCHECK(base::bits::IsPowerOfTwo32(m));
331 int mask = m - 1;
332 int addr = pc_offset();
333 Nop((m - (addr & mask)) & mask);
334 }
335
336
IsNop(Address addr)337 bool Assembler::IsNop(Address addr) {
338 Address a = addr;
339 while (*a == 0x66) a++;
340 if (*a == 0x90) return true;
341 if (a[0] == 0xf && a[1] == 0x1f) return true;
342 return false;
343 }
344
345
Nop(int bytes)346 void Assembler::Nop(int bytes) {
347 EnsureSpace ensure_space(this);
348
349 // Multi byte nops from http://support.amd.com/us/Processor_TechDocs/40546.pdf
350 while (bytes > 0) {
351 switch (bytes) {
352 case 2:
353 EMIT(0x66);
354 case 1:
355 EMIT(0x90);
356 return;
357 case 3:
358 EMIT(0xf);
359 EMIT(0x1f);
360 EMIT(0);
361 return;
362 case 4:
363 EMIT(0xf);
364 EMIT(0x1f);
365 EMIT(0x40);
366 EMIT(0);
367 return;
368 case 6:
369 EMIT(0x66);
370 case 5:
371 EMIT(0xf);
372 EMIT(0x1f);
373 EMIT(0x44);
374 EMIT(0);
375 EMIT(0);
376 return;
377 case 7:
378 EMIT(0xf);
379 EMIT(0x1f);
380 EMIT(0x80);
381 EMIT(0);
382 EMIT(0);
383 EMIT(0);
384 EMIT(0);
385 return;
386 default:
387 case 11:
388 EMIT(0x66);
389 bytes--;
390 case 10:
391 EMIT(0x66);
392 bytes--;
393 case 9:
394 EMIT(0x66);
395 bytes--;
396 case 8:
397 EMIT(0xf);
398 EMIT(0x1f);
399 EMIT(0x84);
400 EMIT(0);
401 EMIT(0);
402 EMIT(0);
403 EMIT(0);
404 EMIT(0);
405 bytes -= 8;
406 }
407 }
408 }
409
410
CodeTargetAlign()411 void Assembler::CodeTargetAlign() {
412 Align(16); // Preferred alignment of jump targets on ia32.
413 }
414
415
cpuid()416 void Assembler::cpuid() {
417 EnsureSpace ensure_space(this);
418 EMIT(0x0F);
419 EMIT(0xA2);
420 }
421
422
pushad()423 void Assembler::pushad() {
424 EnsureSpace ensure_space(this);
425 EMIT(0x60);
426 }
427
428
popad()429 void Assembler::popad() {
430 EnsureSpace ensure_space(this);
431 EMIT(0x61);
432 }
433
434
pushfd()435 void Assembler::pushfd() {
436 EnsureSpace ensure_space(this);
437 EMIT(0x9C);
438 }
439
440
popfd()441 void Assembler::popfd() {
442 EnsureSpace ensure_space(this);
443 EMIT(0x9D);
444 }
445
446
push(const Immediate & x)447 void Assembler::push(const Immediate& x) {
448 EnsureSpace ensure_space(this);
449 if (x.is_int8()) {
450 EMIT(0x6a);
451 EMIT(x.x_);
452 } else {
453 EMIT(0x68);
454 emit(x);
455 }
456 }
457
458
push_imm32(int32_t imm32)459 void Assembler::push_imm32(int32_t imm32) {
460 EnsureSpace ensure_space(this);
461 EMIT(0x68);
462 emit(imm32);
463 }
464
465
push(Register src)466 void Assembler::push(Register src) {
467 EnsureSpace ensure_space(this);
468 EMIT(0x50 | src.code());
469 }
470
471
push(const Operand & src)472 void Assembler::push(const Operand& src) {
473 EnsureSpace ensure_space(this);
474 EMIT(0xFF);
475 emit_operand(esi, src);
476 }
477
478
pop(Register dst)479 void Assembler::pop(Register dst) {
480 DCHECK(reloc_info_writer.last_pc() != NULL);
481 EnsureSpace ensure_space(this);
482 EMIT(0x58 | dst.code());
483 }
484
485
pop(const Operand & dst)486 void Assembler::pop(const Operand& dst) {
487 EnsureSpace ensure_space(this);
488 EMIT(0x8F);
489 emit_operand(eax, dst);
490 }
491
492
enter(const Immediate & size)493 void Assembler::enter(const Immediate& size) {
494 EnsureSpace ensure_space(this);
495 EMIT(0xC8);
496 emit_w(size);
497 EMIT(0);
498 }
499
500
leave()501 void Assembler::leave() {
502 EnsureSpace ensure_space(this);
503 EMIT(0xC9);
504 }
505
506
mov_b(Register dst,const Operand & src)507 void Assembler::mov_b(Register dst, const Operand& src) {
508 CHECK(dst.is_byte_register());
509 EnsureSpace ensure_space(this);
510 EMIT(0x8A);
511 emit_operand(dst, src);
512 }
513
514
mov_b(const Operand & dst,const Immediate & src)515 void Assembler::mov_b(const Operand& dst, const Immediate& src) {
516 EnsureSpace ensure_space(this);
517 EMIT(0xC6);
518 emit_operand(eax, dst);
519 EMIT(static_cast<int8_t>(src.x_));
520 }
521
522
mov_b(const Operand & dst,Register src)523 void Assembler::mov_b(const Operand& dst, Register src) {
524 CHECK(src.is_byte_register());
525 EnsureSpace ensure_space(this);
526 EMIT(0x88);
527 emit_operand(src, dst);
528 }
529
530
mov_w(Register dst,const Operand & src)531 void Assembler::mov_w(Register dst, const Operand& src) {
532 EnsureSpace ensure_space(this);
533 EMIT(0x66);
534 EMIT(0x8B);
535 emit_operand(dst, src);
536 }
537
538
mov_w(const Operand & dst,Register src)539 void Assembler::mov_w(const Operand& dst, Register src) {
540 EnsureSpace ensure_space(this);
541 EMIT(0x66);
542 EMIT(0x89);
543 emit_operand(src, dst);
544 }
545
546
mov_w(const Operand & dst,const Immediate & src)547 void Assembler::mov_w(const Operand& dst, const Immediate& src) {
548 EnsureSpace ensure_space(this);
549 EMIT(0x66);
550 EMIT(0xC7);
551 emit_operand(eax, dst);
552 EMIT(static_cast<int8_t>(src.x_ & 0xff));
553 EMIT(static_cast<int8_t>(src.x_ >> 8));
554 }
555
556
mov(Register dst,int32_t imm32)557 void Assembler::mov(Register dst, int32_t imm32) {
558 EnsureSpace ensure_space(this);
559 EMIT(0xB8 | dst.code());
560 emit(imm32);
561 }
562
563
mov(Register dst,const Immediate & x)564 void Assembler::mov(Register dst, const Immediate& x) {
565 EnsureSpace ensure_space(this);
566 EMIT(0xB8 | dst.code());
567 emit(x);
568 }
569
570
mov(Register dst,Handle<Object> handle)571 void Assembler::mov(Register dst, Handle<Object> handle) {
572 EnsureSpace ensure_space(this);
573 EMIT(0xB8 | dst.code());
574 emit(handle);
575 }
576
577
mov(Register dst,const Operand & src)578 void Assembler::mov(Register dst, const Operand& src) {
579 EnsureSpace ensure_space(this);
580 EMIT(0x8B);
581 emit_operand(dst, src);
582 }
583
584
mov(Register dst,Register src)585 void Assembler::mov(Register dst, Register src) {
586 EnsureSpace ensure_space(this);
587 EMIT(0x89);
588 EMIT(0xC0 | src.code() << 3 | dst.code());
589 }
590
591
mov(const Operand & dst,const Immediate & x)592 void Assembler::mov(const Operand& dst, const Immediate& x) {
593 EnsureSpace ensure_space(this);
594 EMIT(0xC7);
595 emit_operand(eax, dst);
596 emit(x);
597 }
598
599
mov(const Operand & dst,Handle<Object> handle)600 void Assembler::mov(const Operand& dst, Handle<Object> handle) {
601 EnsureSpace ensure_space(this);
602 EMIT(0xC7);
603 emit_operand(eax, dst);
604 emit(handle);
605 }
606
607
mov(const Operand & dst,Register src)608 void Assembler::mov(const Operand& dst, Register src) {
609 EnsureSpace ensure_space(this);
610 EMIT(0x89);
611 emit_operand(src, dst);
612 }
613
614
movsx_b(Register dst,const Operand & src)615 void Assembler::movsx_b(Register dst, const Operand& src) {
616 EnsureSpace ensure_space(this);
617 EMIT(0x0F);
618 EMIT(0xBE);
619 emit_operand(dst, src);
620 }
621
622
movsx_w(Register dst,const Operand & src)623 void Assembler::movsx_w(Register dst, const Operand& src) {
624 EnsureSpace ensure_space(this);
625 EMIT(0x0F);
626 EMIT(0xBF);
627 emit_operand(dst, src);
628 }
629
630
movzx_b(Register dst,const Operand & src)631 void Assembler::movzx_b(Register dst, const Operand& src) {
632 EnsureSpace ensure_space(this);
633 EMIT(0x0F);
634 EMIT(0xB6);
635 emit_operand(dst, src);
636 }
637
638
movzx_w(Register dst,const Operand & src)639 void Assembler::movzx_w(Register dst, const Operand& src) {
640 EnsureSpace ensure_space(this);
641 EMIT(0x0F);
642 EMIT(0xB7);
643 emit_operand(dst, src);
644 }
645
646
cmov(Condition cc,Register dst,const Operand & src)647 void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
648 EnsureSpace ensure_space(this);
649 // Opcode: 0f 40 + cc /r.
650 EMIT(0x0F);
651 EMIT(0x40 + cc);
652 emit_operand(dst, src);
653 }
654
655
cld()656 void Assembler::cld() {
657 EnsureSpace ensure_space(this);
658 EMIT(0xFC);
659 }
660
661
rep_movs()662 void Assembler::rep_movs() {
663 EnsureSpace ensure_space(this);
664 EMIT(0xF3);
665 EMIT(0xA5);
666 }
667
668
rep_stos()669 void Assembler::rep_stos() {
670 EnsureSpace ensure_space(this);
671 EMIT(0xF3);
672 EMIT(0xAB);
673 }
674
675
stos()676 void Assembler::stos() {
677 EnsureSpace ensure_space(this);
678 EMIT(0xAB);
679 }
680
681
xchg(Register dst,Register src)682 void Assembler::xchg(Register dst, Register src) {
683 EnsureSpace ensure_space(this);
684 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding.
685 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code()));
686 } else {
687 EMIT(0x87);
688 EMIT(0xC0 | src.code() << 3 | dst.code());
689 }
690 }
691
692
xchg(Register dst,const Operand & src)693 void Assembler::xchg(Register dst, const Operand& src) {
694 EnsureSpace ensure_space(this);
695 EMIT(0x87);
696 emit_operand(dst, src);
697 }
698
xchg_b(Register reg,const Operand & op)699 void Assembler::xchg_b(Register reg, const Operand& op) {
700 EnsureSpace ensure_space(this);
701 EMIT(0x86);
702 emit_operand(reg, op);
703 }
704
xchg_w(Register reg,const Operand & op)705 void Assembler::xchg_w(Register reg, const Operand& op) {
706 EnsureSpace ensure_space(this);
707 EMIT(0x66);
708 EMIT(0x87);
709 emit_operand(reg, op);
710 }
711
lock()712 void Assembler::lock() {
713 EnsureSpace ensure_space(this);
714 EMIT(0xF0);
715 }
716
cmpxchg(const Operand & dst,Register src)717 void Assembler::cmpxchg(const Operand& dst, Register src) {
718 EnsureSpace ensure_space(this);
719 EMIT(0x0F);
720 EMIT(0xB1);
721 emit_operand(src, dst);
722 }
723
cmpxchg_b(const Operand & dst,Register src)724 void Assembler::cmpxchg_b(const Operand& dst, Register src) {
725 EnsureSpace ensure_space(this);
726 EMIT(0x0F);
727 EMIT(0xB0);
728 emit_operand(src, dst);
729 }
730
cmpxchg_w(const Operand & dst,Register src)731 void Assembler::cmpxchg_w(const Operand& dst, Register src) {
732 EnsureSpace ensure_space(this);
733 EMIT(0x66);
734 EMIT(0x0F);
735 EMIT(0xB1);
736 emit_operand(src, dst);
737 }
738
adc(Register dst,int32_t imm32)739 void Assembler::adc(Register dst, int32_t imm32) {
740 EnsureSpace ensure_space(this);
741 emit_arith(2, Operand(dst), Immediate(imm32));
742 }
743
744
adc(Register dst,const Operand & src)745 void Assembler::adc(Register dst, const Operand& src) {
746 EnsureSpace ensure_space(this);
747 EMIT(0x13);
748 emit_operand(dst, src);
749 }
750
751
add(Register dst,const Operand & src)752 void Assembler::add(Register dst, const Operand& src) {
753 EnsureSpace ensure_space(this);
754 EMIT(0x03);
755 emit_operand(dst, src);
756 }
757
758
add(const Operand & dst,Register src)759 void Assembler::add(const Operand& dst, Register src) {
760 EnsureSpace ensure_space(this);
761 EMIT(0x01);
762 emit_operand(src, dst);
763 }
764
765
add(const Operand & dst,const Immediate & x)766 void Assembler::add(const Operand& dst, const Immediate& x) {
767 DCHECK(reloc_info_writer.last_pc() != NULL);
768 EnsureSpace ensure_space(this);
769 emit_arith(0, dst, x);
770 }
771
772
and_(Register dst,int32_t imm32)773 void Assembler::and_(Register dst, int32_t imm32) {
774 and_(dst, Immediate(imm32));
775 }
776
777
and_(Register dst,const Immediate & x)778 void Assembler::and_(Register dst, const Immediate& x) {
779 EnsureSpace ensure_space(this);
780 emit_arith(4, Operand(dst), x);
781 }
782
783
and_(Register dst,const Operand & src)784 void Assembler::and_(Register dst, const Operand& src) {
785 EnsureSpace ensure_space(this);
786 EMIT(0x23);
787 emit_operand(dst, src);
788 }
789
790
and_(const Operand & dst,const Immediate & x)791 void Assembler::and_(const Operand& dst, const Immediate& x) {
792 EnsureSpace ensure_space(this);
793 emit_arith(4, dst, x);
794 }
795
796
and_(const Operand & dst,Register src)797 void Assembler::and_(const Operand& dst, Register src) {
798 EnsureSpace ensure_space(this);
799 EMIT(0x21);
800 emit_operand(src, dst);
801 }
802
cmpb(const Operand & op,Immediate imm8)803 void Assembler::cmpb(const Operand& op, Immediate imm8) {
804 DCHECK(imm8.is_int8() || imm8.is_uint8());
805 EnsureSpace ensure_space(this);
806 if (op.is_reg(eax)) {
807 EMIT(0x3C);
808 } else {
809 EMIT(0x80);
810 emit_operand(edi, op); // edi == 7
811 }
812 emit_b(imm8);
813 }
814
815
cmpb(const Operand & op,Register reg)816 void Assembler::cmpb(const Operand& op, Register reg) {
817 CHECK(reg.is_byte_register());
818 EnsureSpace ensure_space(this);
819 EMIT(0x38);
820 emit_operand(reg, op);
821 }
822
823
cmpb(Register reg,const Operand & op)824 void Assembler::cmpb(Register reg, const Operand& op) {
825 CHECK(reg.is_byte_register());
826 EnsureSpace ensure_space(this);
827 EMIT(0x3A);
828 emit_operand(reg, op);
829 }
830
831
cmpw(const Operand & op,Immediate imm16)832 void Assembler::cmpw(const Operand& op, Immediate imm16) {
833 DCHECK(imm16.is_int16());
834 EnsureSpace ensure_space(this);
835 EMIT(0x66);
836 EMIT(0x81);
837 emit_operand(edi, op);
838 emit_w(imm16);
839 }
840
cmpw(Register reg,const Operand & op)841 void Assembler::cmpw(Register reg, const Operand& op) {
842 EnsureSpace ensure_space(this);
843 EMIT(0x66);
844 EMIT(0x3B);
845 emit_operand(reg, op);
846 }
847
cmpw(const Operand & op,Register reg)848 void Assembler::cmpw(const Operand& op, Register reg) {
849 EnsureSpace ensure_space(this);
850 EMIT(0x66);
851 EMIT(0x39);
852 emit_operand(reg, op);
853 }
854
cmp(Register reg,int32_t imm32)855 void Assembler::cmp(Register reg, int32_t imm32) {
856 EnsureSpace ensure_space(this);
857 emit_arith(7, Operand(reg), Immediate(imm32));
858 }
859
860
cmp(Register reg,Handle<Object> handle)861 void Assembler::cmp(Register reg, Handle<Object> handle) {
862 EnsureSpace ensure_space(this);
863 emit_arith(7, Operand(reg), Immediate(handle));
864 }
865
866
cmp(Register reg,const Operand & op)867 void Assembler::cmp(Register reg, const Operand& op) {
868 EnsureSpace ensure_space(this);
869 EMIT(0x3B);
870 emit_operand(reg, op);
871 }
872
cmp(const Operand & op,Register reg)873 void Assembler::cmp(const Operand& op, Register reg) {
874 EnsureSpace ensure_space(this);
875 EMIT(0x39);
876 emit_operand(reg, op);
877 }
878
cmp(const Operand & op,const Immediate & imm)879 void Assembler::cmp(const Operand& op, const Immediate& imm) {
880 EnsureSpace ensure_space(this);
881 emit_arith(7, op, imm);
882 }
883
884
cmp(const Operand & op,Handle<Object> handle)885 void Assembler::cmp(const Operand& op, Handle<Object> handle) {
886 EnsureSpace ensure_space(this);
887 emit_arith(7, op, Immediate(handle));
888 }
889
890
cmpb_al(const Operand & op)891 void Assembler::cmpb_al(const Operand& op) {
892 EnsureSpace ensure_space(this);
893 EMIT(0x38); // CMP r/m8, r8
894 emit_operand(eax, op); // eax has same code as register al.
895 }
896
897
cmpw_ax(const Operand & op)898 void Assembler::cmpw_ax(const Operand& op) {
899 EnsureSpace ensure_space(this);
900 EMIT(0x66);
901 EMIT(0x39); // CMP r/m16, r16
902 emit_operand(eax, op); // eax has same code as register ax.
903 }
904
905
dec_b(Register dst)906 void Assembler::dec_b(Register dst) {
907 CHECK(dst.is_byte_register());
908 EnsureSpace ensure_space(this);
909 EMIT(0xFE);
910 EMIT(0xC8 | dst.code());
911 }
912
913
dec_b(const Operand & dst)914 void Assembler::dec_b(const Operand& dst) {
915 EnsureSpace ensure_space(this);
916 EMIT(0xFE);
917 emit_operand(ecx, dst);
918 }
919
920
dec(Register dst)921 void Assembler::dec(Register dst) {
922 EnsureSpace ensure_space(this);
923 EMIT(0x48 | dst.code());
924 }
925
926
dec(const Operand & dst)927 void Assembler::dec(const Operand& dst) {
928 EnsureSpace ensure_space(this);
929 EMIT(0xFF);
930 emit_operand(ecx, dst);
931 }
932
933
cdq()934 void Assembler::cdq() {
935 EnsureSpace ensure_space(this);
936 EMIT(0x99);
937 }
938
939
idiv(const Operand & src)940 void Assembler::idiv(const Operand& src) {
941 EnsureSpace ensure_space(this);
942 EMIT(0xF7);
943 emit_operand(edi, src);
944 }
945
946
div(const Operand & src)947 void Assembler::div(const Operand& src) {
948 EnsureSpace ensure_space(this);
949 EMIT(0xF7);
950 emit_operand(esi, src);
951 }
952
953
imul(Register reg)954 void Assembler::imul(Register reg) {
955 EnsureSpace ensure_space(this);
956 EMIT(0xF7);
957 EMIT(0xE8 | reg.code());
958 }
959
960
imul(Register dst,const Operand & src)961 void Assembler::imul(Register dst, const Operand& src) {
962 EnsureSpace ensure_space(this);
963 EMIT(0x0F);
964 EMIT(0xAF);
965 emit_operand(dst, src);
966 }
967
968
imul(Register dst,Register src,int32_t imm32)969 void Assembler::imul(Register dst, Register src, int32_t imm32) {
970 imul(dst, Operand(src), imm32);
971 }
972
973
imul(Register dst,const Operand & src,int32_t imm32)974 void Assembler::imul(Register dst, const Operand& src, int32_t imm32) {
975 EnsureSpace ensure_space(this);
976 if (is_int8(imm32)) {
977 EMIT(0x6B);
978 emit_operand(dst, src);
979 EMIT(imm32);
980 } else {
981 EMIT(0x69);
982 emit_operand(dst, src);
983 emit(imm32);
984 }
985 }
986
987
inc(Register dst)988 void Assembler::inc(Register dst) {
989 EnsureSpace ensure_space(this);
990 EMIT(0x40 | dst.code());
991 }
992
993
inc(const Operand & dst)994 void Assembler::inc(const Operand& dst) {
995 EnsureSpace ensure_space(this);
996 EMIT(0xFF);
997 emit_operand(eax, dst);
998 }
999
1000
lea(Register dst,const Operand & src)1001 void Assembler::lea(Register dst, const Operand& src) {
1002 EnsureSpace ensure_space(this);
1003 EMIT(0x8D);
1004 emit_operand(dst, src);
1005 }
1006
1007
mul(Register src)1008 void Assembler::mul(Register src) {
1009 EnsureSpace ensure_space(this);
1010 EMIT(0xF7);
1011 EMIT(0xE0 | src.code());
1012 }
1013
1014
neg(Register dst)1015 void Assembler::neg(Register dst) {
1016 EnsureSpace ensure_space(this);
1017 EMIT(0xF7);
1018 EMIT(0xD8 | dst.code());
1019 }
1020
1021
neg(const Operand & dst)1022 void Assembler::neg(const Operand& dst) {
1023 EnsureSpace ensure_space(this);
1024 EMIT(0xF7);
1025 emit_operand(ebx, dst);
1026 }
1027
1028
not_(Register dst)1029 void Assembler::not_(Register dst) {
1030 EnsureSpace ensure_space(this);
1031 EMIT(0xF7);
1032 EMIT(0xD0 | dst.code());
1033 }
1034
1035
not_(const Operand & dst)1036 void Assembler::not_(const Operand& dst) {
1037 EnsureSpace ensure_space(this);
1038 EMIT(0xF7);
1039 emit_operand(edx, dst);
1040 }
1041
1042
or_(Register dst,int32_t imm32)1043 void Assembler::or_(Register dst, int32_t imm32) {
1044 EnsureSpace ensure_space(this);
1045 emit_arith(1, Operand(dst), Immediate(imm32));
1046 }
1047
1048
or_(Register dst,const Operand & src)1049 void Assembler::or_(Register dst, const Operand& src) {
1050 EnsureSpace ensure_space(this);
1051 EMIT(0x0B);
1052 emit_operand(dst, src);
1053 }
1054
1055
or_(const Operand & dst,const Immediate & x)1056 void Assembler::or_(const Operand& dst, const Immediate& x) {
1057 EnsureSpace ensure_space(this);
1058 emit_arith(1, dst, x);
1059 }
1060
1061
or_(const Operand & dst,Register src)1062 void Assembler::or_(const Operand& dst, Register src) {
1063 EnsureSpace ensure_space(this);
1064 EMIT(0x09);
1065 emit_operand(src, dst);
1066 }
1067
1068
rcl(Register dst,uint8_t imm8)1069 void Assembler::rcl(Register dst, uint8_t imm8) {
1070 EnsureSpace ensure_space(this);
1071 DCHECK(is_uint5(imm8)); // illegal shift count
1072 if (imm8 == 1) {
1073 EMIT(0xD1);
1074 EMIT(0xD0 | dst.code());
1075 } else {
1076 EMIT(0xC1);
1077 EMIT(0xD0 | dst.code());
1078 EMIT(imm8);
1079 }
1080 }
1081
1082
rcr(Register dst,uint8_t imm8)1083 void Assembler::rcr(Register dst, uint8_t imm8) {
1084 EnsureSpace ensure_space(this);
1085 DCHECK(is_uint5(imm8)); // illegal shift count
1086 if (imm8 == 1) {
1087 EMIT(0xD1);
1088 EMIT(0xD8 | dst.code());
1089 } else {
1090 EMIT(0xC1);
1091 EMIT(0xD8 | dst.code());
1092 EMIT(imm8);
1093 }
1094 }
1095
1096
ror(const Operand & dst,uint8_t imm8)1097 void Assembler::ror(const Operand& dst, uint8_t imm8) {
1098 EnsureSpace ensure_space(this);
1099 DCHECK(is_uint5(imm8)); // illegal shift count
1100 if (imm8 == 1) {
1101 EMIT(0xD1);
1102 emit_operand(ecx, dst);
1103 } else {
1104 EMIT(0xC1);
1105 emit_operand(ecx, dst);
1106 EMIT(imm8);
1107 }
1108 }
1109
1110
ror_cl(const Operand & dst)1111 void Assembler::ror_cl(const Operand& dst) {
1112 EnsureSpace ensure_space(this);
1113 EMIT(0xD3);
1114 emit_operand(ecx, dst);
1115 }
1116
1117
sar(const Operand & dst,uint8_t imm8)1118 void Assembler::sar(const Operand& dst, uint8_t imm8) {
1119 EnsureSpace ensure_space(this);
1120 DCHECK(is_uint5(imm8)); // illegal shift count
1121 if (imm8 == 1) {
1122 EMIT(0xD1);
1123 emit_operand(edi, dst);
1124 } else {
1125 EMIT(0xC1);
1126 emit_operand(edi, dst);
1127 EMIT(imm8);
1128 }
1129 }
1130
1131
sar_cl(const Operand & dst)1132 void Assembler::sar_cl(const Operand& dst) {
1133 EnsureSpace ensure_space(this);
1134 EMIT(0xD3);
1135 emit_operand(edi, dst);
1136 }
1137
sbb(Register dst,const Operand & src)1138 void Assembler::sbb(Register dst, const Operand& src) {
1139 EnsureSpace ensure_space(this);
1140 EMIT(0x1B);
1141 emit_operand(dst, src);
1142 }
1143
shld(Register dst,Register src,uint8_t shift)1144 void Assembler::shld(Register dst, Register src, uint8_t shift) {
1145 DCHECK(is_uint5(shift));
1146 EnsureSpace ensure_space(this);
1147 EMIT(0x0F);
1148 EMIT(0xA4);
1149 emit_operand(src, Operand(dst));
1150 EMIT(shift);
1151 }
1152
shld_cl(Register dst,Register src)1153 void Assembler::shld_cl(Register dst, Register src) {
1154 EnsureSpace ensure_space(this);
1155 EMIT(0x0F);
1156 EMIT(0xA5);
1157 emit_operand(src, Operand(dst));
1158 }
1159
1160
shl(const Operand & dst,uint8_t imm8)1161 void Assembler::shl(const Operand& dst, uint8_t imm8) {
1162 EnsureSpace ensure_space(this);
1163 DCHECK(is_uint5(imm8)); // illegal shift count
1164 if (imm8 == 1) {
1165 EMIT(0xD1);
1166 emit_operand(esp, dst);
1167 } else {
1168 EMIT(0xC1);
1169 emit_operand(esp, dst);
1170 EMIT(imm8);
1171 }
1172 }
1173
1174
shl_cl(const Operand & dst)1175 void Assembler::shl_cl(const Operand& dst) {
1176 EnsureSpace ensure_space(this);
1177 EMIT(0xD3);
1178 emit_operand(esp, dst);
1179 }
1180
shr(const Operand & dst,uint8_t imm8)1181 void Assembler::shr(const Operand& dst, uint8_t imm8) {
1182 EnsureSpace ensure_space(this);
1183 DCHECK(is_uint5(imm8)); // illegal shift count
1184 if (imm8 == 1) {
1185 EMIT(0xD1);
1186 emit_operand(ebp, dst);
1187 } else {
1188 EMIT(0xC1);
1189 emit_operand(ebp, dst);
1190 EMIT(imm8);
1191 }
1192 }
1193
1194
shr_cl(const Operand & dst)1195 void Assembler::shr_cl(const Operand& dst) {
1196 EnsureSpace ensure_space(this);
1197 EMIT(0xD3);
1198 emit_operand(ebp, dst);
1199 }
1200
shrd(Register dst,Register src,uint8_t shift)1201 void Assembler::shrd(Register dst, Register src, uint8_t shift) {
1202 DCHECK(is_uint5(shift));
1203 EnsureSpace ensure_space(this);
1204 EMIT(0x0F);
1205 EMIT(0xAC);
1206 emit_operand(dst, Operand(src));
1207 EMIT(shift);
1208 }
1209
shrd_cl(const Operand & dst,Register src)1210 void Assembler::shrd_cl(const Operand& dst, Register src) {
1211 EnsureSpace ensure_space(this);
1212 EMIT(0x0F);
1213 EMIT(0xAD);
1214 emit_operand(src, dst);
1215 }
1216
sub(const Operand & dst,const Immediate & x)1217 void Assembler::sub(const Operand& dst, const Immediate& x) {
1218 EnsureSpace ensure_space(this);
1219 emit_arith(5, dst, x);
1220 }
1221
1222
sub(Register dst,const Operand & src)1223 void Assembler::sub(Register dst, const Operand& src) {
1224 EnsureSpace ensure_space(this);
1225 EMIT(0x2B);
1226 emit_operand(dst, src);
1227 }
1228
1229
sub(const Operand & dst,Register src)1230 void Assembler::sub(const Operand& dst, Register src) {
1231 EnsureSpace ensure_space(this);
1232 EMIT(0x29);
1233 emit_operand(src, dst);
1234 }
1235
1236
test(Register reg,const Immediate & imm)1237 void Assembler::test(Register reg, const Immediate& imm) {
1238 if (imm.is_uint8()) {
1239 test_b(reg, imm);
1240 return;
1241 }
1242
1243 EnsureSpace ensure_space(this);
1244 // This is not using emit_arith because test doesn't support
1245 // sign-extension of 8-bit operands.
1246 if (reg.is(eax)) {
1247 EMIT(0xA9);
1248 } else {
1249 EMIT(0xF7);
1250 EMIT(0xC0 | reg.code());
1251 }
1252 emit(imm);
1253 }
1254
1255
test(Register reg,const Operand & op)1256 void Assembler::test(Register reg, const Operand& op) {
1257 EnsureSpace ensure_space(this);
1258 EMIT(0x85);
1259 emit_operand(reg, op);
1260 }
1261
1262
test_b(Register reg,const Operand & op)1263 void Assembler::test_b(Register reg, const Operand& op) {
1264 CHECK(reg.is_byte_register());
1265 EnsureSpace ensure_space(this);
1266 EMIT(0x84);
1267 emit_operand(reg, op);
1268 }
1269
1270
test(const Operand & op,const Immediate & imm)1271 void Assembler::test(const Operand& op, const Immediate& imm) {
1272 if (op.is_reg_only()) {
1273 test(op.reg(), imm);
1274 return;
1275 }
1276 if (imm.is_uint8()) {
1277 return test_b(op, imm);
1278 }
1279 EnsureSpace ensure_space(this);
1280 EMIT(0xF7);
1281 emit_operand(eax, op);
1282 emit(imm);
1283 }
1284
test_b(Register reg,Immediate imm8)1285 void Assembler::test_b(Register reg, Immediate imm8) {
1286 DCHECK(imm8.is_uint8());
1287 EnsureSpace ensure_space(this);
1288 // Only use test against byte for registers that have a byte
1289 // variant: eax, ebx, ecx, and edx.
1290 if (reg.is(eax)) {
1291 EMIT(0xA8);
1292 emit_b(imm8);
1293 } else if (reg.is_byte_register()) {
1294 emit_arith_b(0xF6, 0xC0, reg, static_cast<uint8_t>(imm8.x_));
1295 } else {
1296 EMIT(0x66);
1297 EMIT(0xF7);
1298 EMIT(0xC0 | reg.code());
1299 emit_w(imm8);
1300 }
1301 }
1302
test_b(const Operand & op,Immediate imm8)1303 void Assembler::test_b(const Operand& op, Immediate imm8) {
1304 if (op.is_reg_only()) {
1305 test_b(op.reg(), imm8);
1306 return;
1307 }
1308 EnsureSpace ensure_space(this);
1309 EMIT(0xF6);
1310 emit_operand(eax, op);
1311 emit_b(imm8);
1312 }
1313
test_w(Register reg,Immediate imm16)1314 void Assembler::test_w(Register reg, Immediate imm16) {
1315 DCHECK(imm16.is_int16() || imm16.is_uint16());
1316 EnsureSpace ensure_space(this);
1317 if (reg.is(eax)) {
1318 EMIT(0xA9);
1319 emit_w(imm16);
1320 } else {
1321 EMIT(0x66);
1322 EMIT(0xF7);
1323 EMIT(0xc0 | reg.code());
1324 emit_w(imm16);
1325 }
1326 }
1327
test_w(Register reg,const Operand & op)1328 void Assembler::test_w(Register reg, const Operand& op) {
1329 EnsureSpace ensure_space(this);
1330 EMIT(0x66);
1331 EMIT(0x85);
1332 emit_operand(reg, op);
1333 }
1334
test_w(const Operand & op,Immediate imm16)1335 void Assembler::test_w(const Operand& op, Immediate imm16) {
1336 DCHECK(imm16.is_int16() || imm16.is_uint16());
1337 if (op.is_reg_only()) {
1338 test_w(op.reg(), imm16);
1339 return;
1340 }
1341 EnsureSpace ensure_space(this);
1342 EMIT(0x66);
1343 EMIT(0xF7);
1344 emit_operand(eax, op);
1345 emit_w(imm16);
1346 }
1347
xor_(Register dst,int32_t imm32)1348 void Assembler::xor_(Register dst, int32_t imm32) {
1349 EnsureSpace ensure_space(this);
1350 emit_arith(6, Operand(dst), Immediate(imm32));
1351 }
1352
1353
xor_(Register dst,const Operand & src)1354 void Assembler::xor_(Register dst, const Operand& src) {
1355 EnsureSpace ensure_space(this);
1356 EMIT(0x33);
1357 emit_operand(dst, src);
1358 }
1359
1360
xor_(const Operand & dst,Register src)1361 void Assembler::xor_(const Operand& dst, Register src) {
1362 EnsureSpace ensure_space(this);
1363 EMIT(0x31);
1364 emit_operand(src, dst);
1365 }
1366
1367
xor_(const Operand & dst,const Immediate & x)1368 void Assembler::xor_(const Operand& dst, const Immediate& x) {
1369 EnsureSpace ensure_space(this);
1370 emit_arith(6, dst, x);
1371 }
1372
1373
bt(const Operand & dst,Register src)1374 void Assembler::bt(const Operand& dst, Register src) {
1375 EnsureSpace ensure_space(this);
1376 EMIT(0x0F);
1377 EMIT(0xA3);
1378 emit_operand(src, dst);
1379 }
1380
1381
bts(const Operand & dst,Register src)1382 void Assembler::bts(const Operand& dst, Register src) {
1383 EnsureSpace ensure_space(this);
1384 EMIT(0x0F);
1385 EMIT(0xAB);
1386 emit_operand(src, dst);
1387 }
1388
1389
bsr(Register dst,const Operand & src)1390 void Assembler::bsr(Register dst, const Operand& src) {
1391 EnsureSpace ensure_space(this);
1392 EMIT(0x0F);
1393 EMIT(0xBD);
1394 emit_operand(dst, src);
1395 }
1396
1397
bsf(Register dst,const Operand & src)1398 void Assembler::bsf(Register dst, const Operand& src) {
1399 EnsureSpace ensure_space(this);
1400 EMIT(0x0F);
1401 EMIT(0xBC);
1402 emit_operand(dst, src);
1403 }
1404
1405
hlt()1406 void Assembler::hlt() {
1407 EnsureSpace ensure_space(this);
1408 EMIT(0xF4);
1409 }
1410
1411
int3()1412 void Assembler::int3() {
1413 EnsureSpace ensure_space(this);
1414 EMIT(0xCC);
1415 }
1416
1417
nop()1418 void Assembler::nop() {
1419 EnsureSpace ensure_space(this);
1420 EMIT(0x90);
1421 }
1422
1423
ret(int imm16)1424 void Assembler::ret(int imm16) {
1425 EnsureSpace ensure_space(this);
1426 DCHECK(is_uint16(imm16));
1427 if (imm16 == 0) {
1428 EMIT(0xC3);
1429 } else {
1430 EMIT(0xC2);
1431 EMIT(imm16 & 0xFF);
1432 EMIT((imm16 >> 8) & 0xFF);
1433 }
1434 }
1435
1436
ud2()1437 void Assembler::ud2() {
1438 EnsureSpace ensure_space(this);
1439 EMIT(0x0F);
1440 EMIT(0x0B);
1441 }
1442
1443
1444 // Labels refer to positions in the (to be) generated code.
1445 // There are bound, linked, and unused labels.
1446 //
1447 // Bound labels refer to known positions in the already
1448 // generated code. pos() is the position the label refers to.
1449 //
1450 // Linked labels refer to unknown positions in the code
1451 // to be generated; pos() is the position of the 32bit
1452 // Displacement of the last instruction using the label.
1453
1454
print(Label * L)1455 void Assembler::print(Label* L) {
1456 if (L->is_unused()) {
1457 PrintF("unused label\n");
1458 } else if (L->is_bound()) {
1459 PrintF("bound label to %d\n", L->pos());
1460 } else if (L->is_linked()) {
1461 Label l = *L;
1462 PrintF("unbound label");
1463 while (l.is_linked()) {
1464 Displacement disp = disp_at(&l);
1465 PrintF("@ %d ", l.pos());
1466 disp.print();
1467 PrintF("\n");
1468 disp.next(&l);
1469 }
1470 } else {
1471 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
1472 }
1473 }
1474
1475
bind_to(Label * L,int pos)1476 void Assembler::bind_to(Label* L, int pos) {
1477 EnsureSpace ensure_space(this);
1478 DCHECK(0 <= pos && pos <= pc_offset()); // must have a valid binding position
1479 while (L->is_linked()) {
1480 Displacement disp = disp_at(L);
1481 int fixup_pos = L->pos();
1482 if (disp.type() == Displacement::CODE_ABSOLUTE) {
1483 long_at_put(fixup_pos, reinterpret_cast<int>(buffer_ + pos));
1484 internal_reference_positions_.push_back(fixup_pos);
1485 } else if (disp.type() == Displacement::CODE_RELATIVE) {
1486 // Relative to Code* heap object pointer.
1487 long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
1488 } else {
1489 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
1490 DCHECK(byte_at(fixup_pos - 1) == 0xE9); // jmp expected
1491 }
1492 // Relative address, relative to point after address.
1493 int imm32 = pos - (fixup_pos + sizeof(int32_t));
1494 long_at_put(fixup_pos, imm32);
1495 }
1496 disp.next(L);
1497 }
1498 while (L->is_near_linked()) {
1499 int fixup_pos = L->near_link_pos();
1500 int offset_to_next =
1501 static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
1502 DCHECK(offset_to_next <= 0);
1503 // Relative address, relative to point after address.
1504 int disp = pos - fixup_pos - sizeof(int8_t);
1505 CHECK(0 <= disp && disp <= 127);
1506 set_byte_at(fixup_pos, disp);
1507 if (offset_to_next < 0) {
1508 L->link_to(fixup_pos + offset_to_next, Label::kNear);
1509 } else {
1510 L->UnuseNear();
1511 }
1512 }
1513 L->bind_to(pos);
1514 }
1515
1516
bind(Label * L)1517 void Assembler::bind(Label* L) {
1518 EnsureSpace ensure_space(this);
1519 DCHECK(!L->is_bound()); // label can only be bound once
1520 bind_to(L, pc_offset());
1521 }
1522
1523
call(Label * L)1524 void Assembler::call(Label* L) {
1525 EnsureSpace ensure_space(this);
1526 if (L->is_bound()) {
1527 const int long_size = 5;
1528 int offs = L->pos() - pc_offset();
1529 DCHECK(offs <= 0);
1530 // 1110 1000 #32-bit disp.
1531 EMIT(0xE8);
1532 emit(offs - long_size);
1533 } else {
1534 // 1110 1000 #32-bit disp.
1535 EMIT(0xE8);
1536 emit_disp(L, Displacement::OTHER);
1537 }
1538 }
1539
1540
call(byte * entry,RelocInfo::Mode rmode)1541 void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
1542 EnsureSpace ensure_space(this);
1543 DCHECK(!RelocInfo::IsCodeTarget(rmode));
1544 EMIT(0xE8);
1545 if (RelocInfo::IsRuntimeEntry(rmode)) {
1546 emit(reinterpret_cast<uint32_t>(entry), rmode);
1547 } else {
1548 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1549 }
1550 }
1551
1552
CallSize(const Operand & adr)1553 int Assembler::CallSize(const Operand& adr) {
1554 // Call size is 1 (opcode) + adr.len_ (operand).
1555 return 1 + adr.len_;
1556 }
1557
1558
call(const Operand & adr)1559 void Assembler::call(const Operand& adr) {
1560 EnsureSpace ensure_space(this);
1561 EMIT(0xFF);
1562 emit_operand(edx, adr);
1563 }
1564
1565
CallSize(Handle<Code> code,RelocInfo::Mode rmode)1566 int Assembler::CallSize(Handle<Code> code, RelocInfo::Mode rmode) {
1567 return 1 /* EMIT */ + sizeof(uint32_t) /* emit */;
1568 }
1569
1570
call(Handle<Code> code,RelocInfo::Mode rmode,TypeFeedbackId ast_id)1571 void Assembler::call(Handle<Code> code,
1572 RelocInfo::Mode rmode,
1573 TypeFeedbackId ast_id) {
1574 EnsureSpace ensure_space(this);
1575 DCHECK(RelocInfo::IsCodeTarget(rmode)
1576 || rmode == RelocInfo::CODE_AGE_SEQUENCE);
1577 EMIT(0xE8);
1578 emit(code, rmode, ast_id);
1579 }
1580
1581
jmp(Label * L,Label::Distance distance)1582 void Assembler::jmp(Label* L, Label::Distance distance) {
1583 EnsureSpace ensure_space(this);
1584 if (L->is_bound()) {
1585 const int short_size = 2;
1586 const int long_size = 5;
1587 int offs = L->pos() - pc_offset();
1588 DCHECK(offs <= 0);
1589 if (is_int8(offs - short_size)) {
1590 // 1110 1011 #8-bit disp.
1591 EMIT(0xEB);
1592 EMIT((offs - short_size) & 0xFF);
1593 } else {
1594 // 1110 1001 #32-bit disp.
1595 EMIT(0xE9);
1596 emit(offs - long_size);
1597 }
1598 } else if (distance == Label::kNear) {
1599 EMIT(0xEB);
1600 emit_near_disp(L);
1601 } else {
1602 // 1110 1001 #32-bit disp.
1603 EMIT(0xE9);
1604 emit_disp(L, Displacement::UNCONDITIONAL_JUMP);
1605 }
1606 }
1607
1608
jmp(byte * entry,RelocInfo::Mode rmode)1609 void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
1610 EnsureSpace ensure_space(this);
1611 DCHECK(!RelocInfo::IsCodeTarget(rmode));
1612 EMIT(0xE9);
1613 if (RelocInfo::IsRuntimeEntry(rmode)) {
1614 emit(reinterpret_cast<uint32_t>(entry), rmode);
1615 } else {
1616 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1617 }
1618 }
1619
1620
jmp(const Operand & adr)1621 void Assembler::jmp(const Operand& adr) {
1622 EnsureSpace ensure_space(this);
1623 EMIT(0xFF);
1624 emit_operand(esp, adr);
1625 }
1626
1627
jmp(Handle<Code> code,RelocInfo::Mode rmode)1628 void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
1629 EnsureSpace ensure_space(this);
1630 DCHECK(RelocInfo::IsCodeTarget(rmode));
1631 EMIT(0xE9);
1632 emit(code, rmode);
1633 }
1634
1635
j(Condition cc,Label * L,Label::Distance distance)1636 void Assembler::j(Condition cc, Label* L, Label::Distance distance) {
1637 EnsureSpace ensure_space(this);
1638 DCHECK(0 <= cc && static_cast<int>(cc) < 16);
1639 if (L->is_bound()) {
1640 const int short_size = 2;
1641 const int long_size = 6;
1642 int offs = L->pos() - pc_offset();
1643 DCHECK(offs <= 0);
1644 if (is_int8(offs - short_size)) {
1645 // 0111 tttn #8-bit disp
1646 EMIT(0x70 | cc);
1647 EMIT((offs - short_size) & 0xFF);
1648 } else {
1649 // 0000 1111 1000 tttn #32-bit disp
1650 EMIT(0x0F);
1651 EMIT(0x80 | cc);
1652 emit(offs - long_size);
1653 }
1654 } else if (distance == Label::kNear) {
1655 EMIT(0x70 | cc);
1656 emit_near_disp(L);
1657 } else {
1658 // 0000 1111 1000 tttn #32-bit disp
1659 // Note: could eliminate cond. jumps to this jump if condition
1660 // is the same however, seems to be rather unlikely case.
1661 EMIT(0x0F);
1662 EMIT(0x80 | cc);
1663 emit_disp(L, Displacement::OTHER);
1664 }
1665 }
1666
1667
j(Condition cc,byte * entry,RelocInfo::Mode rmode)1668 void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode) {
1669 EnsureSpace ensure_space(this);
1670 DCHECK((0 <= cc) && (static_cast<int>(cc) < 16));
1671 // 0000 1111 1000 tttn #32-bit disp.
1672 EMIT(0x0F);
1673 EMIT(0x80 | cc);
1674 if (RelocInfo::IsRuntimeEntry(rmode)) {
1675 emit(reinterpret_cast<uint32_t>(entry), rmode);
1676 } else {
1677 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1678 }
1679 }
1680
1681
j(Condition cc,Handle<Code> code,RelocInfo::Mode rmode)1682 void Assembler::j(Condition cc, Handle<Code> code, RelocInfo::Mode rmode) {
1683 EnsureSpace ensure_space(this);
1684 // 0000 1111 1000 tttn #32-bit disp
1685 EMIT(0x0F);
1686 EMIT(0x80 | cc);
1687 emit(code, rmode);
1688 }
1689
1690
1691 // FPU instructions.
1692
fld(int i)1693 void Assembler::fld(int i) {
1694 EnsureSpace ensure_space(this);
1695 emit_farith(0xD9, 0xC0, i);
1696 }
1697
1698
fstp(int i)1699 void Assembler::fstp(int i) {
1700 EnsureSpace ensure_space(this);
1701 emit_farith(0xDD, 0xD8, i);
1702 }
1703
1704
fld1()1705 void Assembler::fld1() {
1706 EnsureSpace ensure_space(this);
1707 EMIT(0xD9);
1708 EMIT(0xE8);
1709 }
1710
1711
fldpi()1712 void Assembler::fldpi() {
1713 EnsureSpace ensure_space(this);
1714 EMIT(0xD9);
1715 EMIT(0xEB);
1716 }
1717
1718
fldz()1719 void Assembler::fldz() {
1720 EnsureSpace ensure_space(this);
1721 EMIT(0xD9);
1722 EMIT(0xEE);
1723 }
1724
1725
fldln2()1726 void Assembler::fldln2() {
1727 EnsureSpace ensure_space(this);
1728 EMIT(0xD9);
1729 EMIT(0xED);
1730 }
1731
1732
fld_s(const Operand & adr)1733 void Assembler::fld_s(const Operand& adr) {
1734 EnsureSpace ensure_space(this);
1735 EMIT(0xD9);
1736 emit_operand(eax, adr);
1737 }
1738
1739
fld_d(const Operand & adr)1740 void Assembler::fld_d(const Operand& adr) {
1741 EnsureSpace ensure_space(this);
1742 EMIT(0xDD);
1743 emit_operand(eax, adr);
1744 }
1745
1746
fstp_s(const Operand & adr)1747 void Assembler::fstp_s(const Operand& adr) {
1748 EnsureSpace ensure_space(this);
1749 EMIT(0xD9);
1750 emit_operand(ebx, adr);
1751 }
1752
1753
fst_s(const Operand & adr)1754 void Assembler::fst_s(const Operand& adr) {
1755 EnsureSpace ensure_space(this);
1756 EMIT(0xD9);
1757 emit_operand(edx, adr);
1758 }
1759
1760
fstp_d(const Operand & adr)1761 void Assembler::fstp_d(const Operand& adr) {
1762 EnsureSpace ensure_space(this);
1763 EMIT(0xDD);
1764 emit_operand(ebx, adr);
1765 }
1766
1767
fst_d(const Operand & adr)1768 void Assembler::fst_d(const Operand& adr) {
1769 EnsureSpace ensure_space(this);
1770 EMIT(0xDD);
1771 emit_operand(edx, adr);
1772 }
1773
1774
fild_s(const Operand & adr)1775 void Assembler::fild_s(const Operand& adr) {
1776 EnsureSpace ensure_space(this);
1777 EMIT(0xDB);
1778 emit_operand(eax, adr);
1779 }
1780
1781
fild_d(const Operand & adr)1782 void Assembler::fild_d(const Operand& adr) {
1783 EnsureSpace ensure_space(this);
1784 EMIT(0xDF);
1785 emit_operand(ebp, adr);
1786 }
1787
1788
fistp_s(const Operand & adr)1789 void Assembler::fistp_s(const Operand& adr) {
1790 EnsureSpace ensure_space(this);
1791 EMIT(0xDB);
1792 emit_operand(ebx, adr);
1793 }
1794
1795
fisttp_s(const Operand & adr)1796 void Assembler::fisttp_s(const Operand& adr) {
1797 DCHECK(IsEnabled(SSE3));
1798 EnsureSpace ensure_space(this);
1799 EMIT(0xDB);
1800 emit_operand(ecx, adr);
1801 }
1802
1803
fisttp_d(const Operand & adr)1804 void Assembler::fisttp_d(const Operand& adr) {
1805 DCHECK(IsEnabled(SSE3));
1806 EnsureSpace ensure_space(this);
1807 EMIT(0xDD);
1808 emit_operand(ecx, adr);
1809 }
1810
1811
fist_s(const Operand & adr)1812 void Assembler::fist_s(const Operand& adr) {
1813 EnsureSpace ensure_space(this);
1814 EMIT(0xDB);
1815 emit_operand(edx, adr);
1816 }
1817
1818
fistp_d(const Operand & adr)1819 void Assembler::fistp_d(const Operand& adr) {
1820 EnsureSpace ensure_space(this);
1821 EMIT(0xDF);
1822 emit_operand(edi, adr);
1823 }
1824
1825
fabs()1826 void Assembler::fabs() {
1827 EnsureSpace ensure_space(this);
1828 EMIT(0xD9);
1829 EMIT(0xE1);
1830 }
1831
1832
fchs()1833 void Assembler::fchs() {
1834 EnsureSpace ensure_space(this);
1835 EMIT(0xD9);
1836 EMIT(0xE0);
1837 }
1838
1839
fcos()1840 void Assembler::fcos() {
1841 EnsureSpace ensure_space(this);
1842 EMIT(0xD9);
1843 EMIT(0xFF);
1844 }
1845
1846
fsin()1847 void Assembler::fsin() {
1848 EnsureSpace ensure_space(this);
1849 EMIT(0xD9);
1850 EMIT(0xFE);
1851 }
1852
1853
fptan()1854 void Assembler::fptan() {
1855 EnsureSpace ensure_space(this);
1856 EMIT(0xD9);
1857 EMIT(0xF2);
1858 }
1859
1860
fyl2x()1861 void Assembler::fyl2x() {
1862 EnsureSpace ensure_space(this);
1863 EMIT(0xD9);
1864 EMIT(0xF1);
1865 }
1866
1867
f2xm1()1868 void Assembler::f2xm1() {
1869 EnsureSpace ensure_space(this);
1870 EMIT(0xD9);
1871 EMIT(0xF0);
1872 }
1873
1874
fscale()1875 void Assembler::fscale() {
1876 EnsureSpace ensure_space(this);
1877 EMIT(0xD9);
1878 EMIT(0xFD);
1879 }
1880
1881
fninit()1882 void Assembler::fninit() {
1883 EnsureSpace ensure_space(this);
1884 EMIT(0xDB);
1885 EMIT(0xE3);
1886 }
1887
1888
fadd(int i)1889 void Assembler::fadd(int i) {
1890 EnsureSpace ensure_space(this);
1891 emit_farith(0xDC, 0xC0, i);
1892 }
1893
1894
fadd_i(int i)1895 void Assembler::fadd_i(int i) {
1896 EnsureSpace ensure_space(this);
1897 emit_farith(0xD8, 0xC0, i);
1898 }
1899
1900
fsub(int i)1901 void Assembler::fsub(int i) {
1902 EnsureSpace ensure_space(this);
1903 emit_farith(0xDC, 0xE8, i);
1904 }
1905
1906
fsub_i(int i)1907 void Assembler::fsub_i(int i) {
1908 EnsureSpace ensure_space(this);
1909 emit_farith(0xD8, 0xE0, i);
1910 }
1911
1912
fisub_s(const Operand & adr)1913 void Assembler::fisub_s(const Operand& adr) {
1914 EnsureSpace ensure_space(this);
1915 EMIT(0xDA);
1916 emit_operand(esp, adr);
1917 }
1918
1919
fmul_i(int i)1920 void Assembler::fmul_i(int i) {
1921 EnsureSpace ensure_space(this);
1922 emit_farith(0xD8, 0xC8, i);
1923 }
1924
1925
fmul(int i)1926 void Assembler::fmul(int i) {
1927 EnsureSpace ensure_space(this);
1928 emit_farith(0xDC, 0xC8, i);
1929 }
1930
1931
fdiv(int i)1932 void Assembler::fdiv(int i) {
1933 EnsureSpace ensure_space(this);
1934 emit_farith(0xDC, 0xF8, i);
1935 }
1936
1937
fdiv_i(int i)1938 void Assembler::fdiv_i(int i) {
1939 EnsureSpace ensure_space(this);
1940 emit_farith(0xD8, 0xF0, i);
1941 }
1942
1943
faddp(int i)1944 void Assembler::faddp(int i) {
1945 EnsureSpace ensure_space(this);
1946 emit_farith(0xDE, 0xC0, i);
1947 }
1948
1949
fsubp(int i)1950 void Assembler::fsubp(int i) {
1951 EnsureSpace ensure_space(this);
1952 emit_farith(0xDE, 0xE8, i);
1953 }
1954
1955
fsubrp(int i)1956 void Assembler::fsubrp(int i) {
1957 EnsureSpace ensure_space(this);
1958 emit_farith(0xDE, 0xE0, i);
1959 }
1960
1961
fmulp(int i)1962 void Assembler::fmulp(int i) {
1963 EnsureSpace ensure_space(this);
1964 emit_farith(0xDE, 0xC8, i);
1965 }
1966
1967
fdivp(int i)1968 void Assembler::fdivp(int i) {
1969 EnsureSpace ensure_space(this);
1970 emit_farith(0xDE, 0xF8, i);
1971 }
1972
1973
fprem()1974 void Assembler::fprem() {
1975 EnsureSpace ensure_space(this);
1976 EMIT(0xD9);
1977 EMIT(0xF8);
1978 }
1979
1980
fprem1()1981 void Assembler::fprem1() {
1982 EnsureSpace ensure_space(this);
1983 EMIT(0xD9);
1984 EMIT(0xF5);
1985 }
1986
1987
fxch(int i)1988 void Assembler::fxch(int i) {
1989 EnsureSpace ensure_space(this);
1990 emit_farith(0xD9, 0xC8, i);
1991 }
1992
1993
fincstp()1994 void Assembler::fincstp() {
1995 EnsureSpace ensure_space(this);
1996 EMIT(0xD9);
1997 EMIT(0xF7);
1998 }
1999
2000
ffree(int i)2001 void Assembler::ffree(int i) {
2002 EnsureSpace ensure_space(this);
2003 emit_farith(0xDD, 0xC0, i);
2004 }
2005
2006
ftst()2007 void Assembler::ftst() {
2008 EnsureSpace ensure_space(this);
2009 EMIT(0xD9);
2010 EMIT(0xE4);
2011 }
2012
2013
fucomp(int i)2014 void Assembler::fucomp(int i) {
2015 EnsureSpace ensure_space(this);
2016 emit_farith(0xDD, 0xE8, i);
2017 }
2018
2019
fucompp()2020 void Assembler::fucompp() {
2021 EnsureSpace ensure_space(this);
2022 EMIT(0xDA);
2023 EMIT(0xE9);
2024 }
2025
2026
fucomi(int i)2027 void Assembler::fucomi(int i) {
2028 EnsureSpace ensure_space(this);
2029 EMIT(0xDB);
2030 EMIT(0xE8 + i);
2031 }
2032
2033
fucomip()2034 void Assembler::fucomip() {
2035 EnsureSpace ensure_space(this);
2036 EMIT(0xDF);
2037 EMIT(0xE9);
2038 }
2039
2040
fcompp()2041 void Assembler::fcompp() {
2042 EnsureSpace ensure_space(this);
2043 EMIT(0xDE);
2044 EMIT(0xD9);
2045 }
2046
2047
fnstsw_ax()2048 void Assembler::fnstsw_ax() {
2049 EnsureSpace ensure_space(this);
2050 EMIT(0xDF);
2051 EMIT(0xE0);
2052 }
2053
2054
fwait()2055 void Assembler::fwait() {
2056 EnsureSpace ensure_space(this);
2057 EMIT(0x9B);
2058 }
2059
2060
frndint()2061 void Assembler::frndint() {
2062 EnsureSpace ensure_space(this);
2063 EMIT(0xD9);
2064 EMIT(0xFC);
2065 }
2066
2067
fnclex()2068 void Assembler::fnclex() {
2069 EnsureSpace ensure_space(this);
2070 EMIT(0xDB);
2071 EMIT(0xE2);
2072 }
2073
2074
sahf()2075 void Assembler::sahf() {
2076 EnsureSpace ensure_space(this);
2077 EMIT(0x9E);
2078 }
2079
2080
setcc(Condition cc,Register reg)2081 void Assembler::setcc(Condition cc, Register reg) {
2082 DCHECK(reg.is_byte_register());
2083 EnsureSpace ensure_space(this);
2084 EMIT(0x0F);
2085 EMIT(0x90 | cc);
2086 EMIT(0xC0 | reg.code());
2087 }
2088
2089
cvttss2si(Register dst,const Operand & src)2090 void Assembler::cvttss2si(Register dst, const Operand& src) {
2091 EnsureSpace ensure_space(this);
2092 EMIT(0xF3);
2093 EMIT(0x0F);
2094 EMIT(0x2C);
2095 emit_operand(dst, src);
2096 }
2097
2098
cvttsd2si(Register dst,const Operand & src)2099 void Assembler::cvttsd2si(Register dst, const Operand& src) {
2100 EnsureSpace ensure_space(this);
2101 EMIT(0xF2);
2102 EMIT(0x0F);
2103 EMIT(0x2C);
2104 emit_operand(dst, src);
2105 }
2106
2107
cvtsd2si(Register dst,XMMRegister src)2108 void Assembler::cvtsd2si(Register dst, XMMRegister src) {
2109 EnsureSpace ensure_space(this);
2110 EMIT(0xF2);
2111 EMIT(0x0F);
2112 EMIT(0x2D);
2113 emit_sse_operand(dst, src);
2114 }
2115
2116
cvtsi2ss(XMMRegister dst,const Operand & src)2117 void Assembler::cvtsi2ss(XMMRegister dst, const Operand& src) {
2118 EnsureSpace ensure_space(this);
2119 EMIT(0xF3);
2120 EMIT(0x0F);
2121 EMIT(0x2A);
2122 emit_sse_operand(dst, src);
2123 }
2124
2125
cvtsi2sd(XMMRegister dst,const Operand & src)2126 void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
2127 EnsureSpace ensure_space(this);
2128 EMIT(0xF2);
2129 EMIT(0x0F);
2130 EMIT(0x2A);
2131 emit_sse_operand(dst, src);
2132 }
2133
2134
cvtss2sd(XMMRegister dst,const Operand & src)2135 void Assembler::cvtss2sd(XMMRegister dst, const Operand& src) {
2136 EnsureSpace ensure_space(this);
2137 EMIT(0xF3);
2138 EMIT(0x0F);
2139 EMIT(0x5A);
2140 emit_sse_operand(dst, src);
2141 }
2142
2143
cvtsd2ss(XMMRegister dst,const Operand & src)2144 void Assembler::cvtsd2ss(XMMRegister dst, const Operand& src) {
2145 EnsureSpace ensure_space(this);
2146 EMIT(0xF2);
2147 EMIT(0x0F);
2148 EMIT(0x5A);
2149 emit_sse_operand(dst, src);
2150 }
2151
2152
addsd(XMMRegister dst,const Operand & src)2153 void Assembler::addsd(XMMRegister dst, const Operand& src) {
2154 EnsureSpace ensure_space(this);
2155 EMIT(0xF2);
2156 EMIT(0x0F);
2157 EMIT(0x58);
2158 emit_sse_operand(dst, src);
2159 }
2160
2161
mulsd(XMMRegister dst,const Operand & src)2162 void Assembler::mulsd(XMMRegister dst, const Operand& src) {
2163 EnsureSpace ensure_space(this);
2164 EMIT(0xF2);
2165 EMIT(0x0F);
2166 EMIT(0x59);
2167 emit_sse_operand(dst, src);
2168 }
2169
2170
subsd(XMMRegister dst,const Operand & src)2171 void Assembler::subsd(XMMRegister dst, const Operand& src) {
2172 EnsureSpace ensure_space(this);
2173 EMIT(0xF2);
2174 EMIT(0x0F);
2175 EMIT(0x5C);
2176 emit_sse_operand(dst, src);
2177 }
2178
2179
divsd(XMMRegister dst,const Operand & src)2180 void Assembler::divsd(XMMRegister dst, const Operand& src) {
2181 EnsureSpace ensure_space(this);
2182 EMIT(0xF2);
2183 EMIT(0x0F);
2184 EMIT(0x5E);
2185 emit_sse_operand(dst, src);
2186 }
2187
2188
xorpd(XMMRegister dst,XMMRegister src)2189 void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
2190 EnsureSpace ensure_space(this);
2191 EMIT(0x66);
2192 EMIT(0x0F);
2193 EMIT(0x57);
2194 emit_sse_operand(dst, src);
2195 }
2196
2197
andps(XMMRegister dst,const Operand & src)2198 void Assembler::andps(XMMRegister dst, const Operand& src) {
2199 EnsureSpace ensure_space(this);
2200 EMIT(0x0F);
2201 EMIT(0x54);
2202 emit_sse_operand(dst, src);
2203 }
2204
2205
orps(XMMRegister dst,const Operand & src)2206 void Assembler::orps(XMMRegister dst, const Operand& src) {
2207 EnsureSpace ensure_space(this);
2208 EMIT(0x0F);
2209 EMIT(0x56);
2210 emit_sse_operand(dst, src);
2211 }
2212
2213
xorps(XMMRegister dst,const Operand & src)2214 void Assembler::xorps(XMMRegister dst, const Operand& src) {
2215 EnsureSpace ensure_space(this);
2216 EMIT(0x0F);
2217 EMIT(0x57);
2218 emit_sse_operand(dst, src);
2219 }
2220
2221
addps(XMMRegister dst,const Operand & src)2222 void Assembler::addps(XMMRegister dst, const Operand& src) {
2223 EnsureSpace ensure_space(this);
2224 EMIT(0x0F);
2225 EMIT(0x58);
2226 emit_sse_operand(dst, src);
2227 }
2228
2229
subps(XMMRegister dst,const Operand & src)2230 void Assembler::subps(XMMRegister dst, const Operand& src) {
2231 EnsureSpace ensure_space(this);
2232 EMIT(0x0F);
2233 EMIT(0x5C);
2234 emit_sse_operand(dst, src);
2235 }
2236
2237
mulps(XMMRegister dst,const Operand & src)2238 void Assembler::mulps(XMMRegister dst, const Operand& src) {
2239 EnsureSpace ensure_space(this);
2240 EMIT(0x0F);
2241 EMIT(0x59);
2242 emit_sse_operand(dst, src);
2243 }
2244
2245
divps(XMMRegister dst,const Operand & src)2246 void Assembler::divps(XMMRegister dst, const Operand& src) {
2247 EnsureSpace ensure_space(this);
2248 EMIT(0x0F);
2249 EMIT(0x5E);
2250 emit_sse_operand(dst, src);
2251 }
2252
2253
sqrtsd(XMMRegister dst,const Operand & src)2254 void Assembler::sqrtsd(XMMRegister dst, const Operand& src) {
2255 EnsureSpace ensure_space(this);
2256 EMIT(0xF2);
2257 EMIT(0x0F);
2258 EMIT(0x51);
2259 emit_sse_operand(dst, src);
2260 }
2261
2262
andpd(XMMRegister dst,XMMRegister src)2263 void Assembler::andpd(XMMRegister dst, XMMRegister src) {
2264 EnsureSpace ensure_space(this);
2265 EMIT(0x66);
2266 EMIT(0x0F);
2267 EMIT(0x54);
2268 emit_sse_operand(dst, src);
2269 }
2270
2271
orpd(XMMRegister dst,XMMRegister src)2272 void Assembler::orpd(XMMRegister dst, XMMRegister src) {
2273 EnsureSpace ensure_space(this);
2274 EMIT(0x66);
2275 EMIT(0x0F);
2276 EMIT(0x56);
2277 emit_sse_operand(dst, src);
2278 }
2279
2280
ucomisd(XMMRegister dst,const Operand & src)2281 void Assembler::ucomisd(XMMRegister dst, const Operand& src) {
2282 EnsureSpace ensure_space(this);
2283 EMIT(0x66);
2284 EMIT(0x0F);
2285 EMIT(0x2E);
2286 emit_sse_operand(dst, src);
2287 }
2288
2289
roundss(XMMRegister dst,XMMRegister src,RoundingMode mode)2290 void Assembler::roundss(XMMRegister dst, XMMRegister src, RoundingMode mode) {
2291 DCHECK(IsEnabled(SSE4_1));
2292 EnsureSpace ensure_space(this);
2293 EMIT(0x66);
2294 EMIT(0x0F);
2295 EMIT(0x3A);
2296 EMIT(0x0A);
2297 emit_sse_operand(dst, src);
2298 // Mask precision exeption.
2299 EMIT(static_cast<byte>(mode) | 0x8);
2300 }
2301
2302
roundsd(XMMRegister dst,XMMRegister src,RoundingMode mode)2303 void Assembler::roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode) {
2304 DCHECK(IsEnabled(SSE4_1));
2305 EnsureSpace ensure_space(this);
2306 EMIT(0x66);
2307 EMIT(0x0F);
2308 EMIT(0x3A);
2309 EMIT(0x0B);
2310 emit_sse_operand(dst, src);
2311 // Mask precision exeption.
2312 EMIT(static_cast<byte>(mode) | 0x8);
2313 }
2314
2315
movmskpd(Register dst,XMMRegister src)2316 void Assembler::movmskpd(Register dst, XMMRegister src) {
2317 EnsureSpace ensure_space(this);
2318 EMIT(0x66);
2319 EMIT(0x0F);
2320 EMIT(0x50);
2321 emit_sse_operand(dst, src);
2322 }
2323
2324
movmskps(Register dst,XMMRegister src)2325 void Assembler::movmskps(Register dst, XMMRegister src) {
2326 EnsureSpace ensure_space(this);
2327 EMIT(0x0F);
2328 EMIT(0x50);
2329 emit_sse_operand(dst, src);
2330 }
2331
2332
pcmpeqd(XMMRegister dst,XMMRegister src)2333 void Assembler::pcmpeqd(XMMRegister dst, XMMRegister src) {
2334 EnsureSpace ensure_space(this);
2335 EMIT(0x66);
2336 EMIT(0x0F);
2337 EMIT(0x76);
2338 emit_sse_operand(dst, src);
2339 }
2340
2341
punpckldq(XMMRegister dst,XMMRegister src)2342 void Assembler::punpckldq(XMMRegister dst, XMMRegister src) {
2343 EnsureSpace ensure_space(this);
2344 EMIT(0x66);
2345 EMIT(0x0F);
2346 EMIT(0x62);
2347 emit_sse_operand(dst, src);
2348 }
2349
2350
punpckhdq(XMMRegister dst,XMMRegister src)2351 void Assembler::punpckhdq(XMMRegister dst, XMMRegister src) {
2352 EnsureSpace ensure_space(this);
2353 EMIT(0x66);
2354 EMIT(0x0F);
2355 EMIT(0x6A);
2356 emit_sse_operand(dst, src);
2357 }
2358
2359
maxsd(XMMRegister dst,const Operand & src)2360 void Assembler::maxsd(XMMRegister dst, const Operand& src) {
2361 EnsureSpace ensure_space(this);
2362 EMIT(0xF2);
2363 EMIT(0x0F);
2364 EMIT(0x5F);
2365 emit_sse_operand(dst, src);
2366 }
2367
2368
minsd(XMMRegister dst,const Operand & src)2369 void Assembler::minsd(XMMRegister dst, const Operand& src) {
2370 EnsureSpace ensure_space(this);
2371 EMIT(0xF2);
2372 EMIT(0x0F);
2373 EMIT(0x5D);
2374 emit_sse_operand(dst, src);
2375 }
2376
2377
cmpltsd(XMMRegister dst,XMMRegister src)2378 void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
2379 EnsureSpace ensure_space(this);
2380 EMIT(0xF2);
2381 EMIT(0x0F);
2382 EMIT(0xC2);
2383 emit_sse_operand(dst, src);
2384 EMIT(1); // LT == 1
2385 }
2386
2387
movaps(XMMRegister dst,XMMRegister src)2388 void Assembler::movaps(XMMRegister dst, XMMRegister src) {
2389 EnsureSpace ensure_space(this);
2390 EMIT(0x0F);
2391 EMIT(0x28);
2392 emit_sse_operand(dst, src);
2393 }
2394
movups(XMMRegister dst,XMMRegister src)2395 void Assembler::movups(XMMRegister dst, XMMRegister src) {
2396 EnsureSpace ensure_space(this);
2397 EMIT(0x0F);
2398 EMIT(0x11);
2399 emit_sse_operand(dst, src);
2400 }
2401
movups(XMMRegister dst,const Operand & src)2402 void Assembler::movups(XMMRegister dst, const Operand& src) {
2403 EnsureSpace ensure_space(this);
2404 EMIT(0x0F);
2405 EMIT(0x10);
2406 emit_sse_operand(dst, src);
2407 }
2408
movups(const Operand & dst,XMMRegister src)2409 void Assembler::movups(const Operand& dst, XMMRegister src) {
2410 EnsureSpace ensure_space(this);
2411 EMIT(0x0F);
2412 EMIT(0x11);
2413 emit_sse_operand(src, dst);
2414 }
2415
shufps(XMMRegister dst,XMMRegister src,byte imm8)2416 void Assembler::shufps(XMMRegister dst, XMMRegister src, byte imm8) {
2417 DCHECK(is_uint8(imm8));
2418 EnsureSpace ensure_space(this);
2419 EMIT(0x0F);
2420 EMIT(0xC6);
2421 emit_sse_operand(dst, src);
2422 EMIT(imm8);
2423 }
2424
2425
movdqa(const Operand & dst,XMMRegister src)2426 void Assembler::movdqa(const Operand& dst, XMMRegister src) {
2427 EnsureSpace ensure_space(this);
2428 EMIT(0x66);
2429 EMIT(0x0F);
2430 EMIT(0x7F);
2431 emit_sse_operand(src, dst);
2432 }
2433
2434
movdqa(XMMRegister dst,const Operand & src)2435 void Assembler::movdqa(XMMRegister dst, const Operand& src) {
2436 EnsureSpace ensure_space(this);
2437 EMIT(0x66);
2438 EMIT(0x0F);
2439 EMIT(0x6F);
2440 emit_sse_operand(dst, src);
2441 }
2442
2443
movdqu(const Operand & dst,XMMRegister src)2444 void Assembler::movdqu(const Operand& dst, XMMRegister src ) {
2445 EnsureSpace ensure_space(this);
2446 EMIT(0xF3);
2447 EMIT(0x0F);
2448 EMIT(0x7F);
2449 emit_sse_operand(src, dst);
2450 }
2451
2452
movdqu(XMMRegister dst,const Operand & src)2453 void Assembler::movdqu(XMMRegister dst, const Operand& src) {
2454 EnsureSpace ensure_space(this);
2455 EMIT(0xF3);
2456 EMIT(0x0F);
2457 EMIT(0x6F);
2458 emit_sse_operand(dst, src);
2459 }
2460
2461
prefetch(const Operand & src,int level)2462 void Assembler::prefetch(const Operand& src, int level) {
2463 DCHECK(is_uint2(level));
2464 EnsureSpace ensure_space(this);
2465 EMIT(0x0F);
2466 EMIT(0x18);
2467 // Emit hint number in Reg position of RegR/M.
2468 XMMRegister code = XMMRegister::from_code(level);
2469 emit_sse_operand(code, src);
2470 }
2471
2472
movsd(const Operand & dst,XMMRegister src)2473 void Assembler::movsd(const Operand& dst, XMMRegister src ) {
2474 EnsureSpace ensure_space(this);
2475 EMIT(0xF2); // double
2476 EMIT(0x0F);
2477 EMIT(0x11); // store
2478 emit_sse_operand(src, dst);
2479 }
2480
2481
movsd(XMMRegister dst,const Operand & src)2482 void Assembler::movsd(XMMRegister dst, const Operand& src) {
2483 EnsureSpace ensure_space(this);
2484 EMIT(0xF2); // double
2485 EMIT(0x0F);
2486 EMIT(0x10); // load
2487 emit_sse_operand(dst, src);
2488 }
2489
2490
movss(const Operand & dst,XMMRegister src)2491 void Assembler::movss(const Operand& dst, XMMRegister src ) {
2492 EnsureSpace ensure_space(this);
2493 EMIT(0xF3); // float
2494 EMIT(0x0F);
2495 EMIT(0x11); // store
2496 emit_sse_operand(src, dst);
2497 }
2498
2499
movss(XMMRegister dst,const Operand & src)2500 void Assembler::movss(XMMRegister dst, const Operand& src) {
2501 EnsureSpace ensure_space(this);
2502 EMIT(0xF3); // float
2503 EMIT(0x0F);
2504 EMIT(0x10); // load
2505 emit_sse_operand(dst, src);
2506 }
2507
2508
movd(XMMRegister dst,const Operand & src)2509 void Assembler::movd(XMMRegister dst, const Operand& src) {
2510 EnsureSpace ensure_space(this);
2511 EMIT(0x66);
2512 EMIT(0x0F);
2513 EMIT(0x6E);
2514 emit_sse_operand(dst, src);
2515 }
2516
2517
movd(const Operand & dst,XMMRegister src)2518 void Assembler::movd(const Operand& dst, XMMRegister src) {
2519 EnsureSpace ensure_space(this);
2520 EMIT(0x66);
2521 EMIT(0x0F);
2522 EMIT(0x7E);
2523 emit_sse_operand(src, dst);
2524 }
2525
2526
extractps(Register dst,XMMRegister src,byte imm8)2527 void Assembler::extractps(Register dst, XMMRegister src, byte imm8) {
2528 DCHECK(IsEnabled(SSE4_1));
2529 DCHECK(is_uint8(imm8));
2530 EnsureSpace ensure_space(this);
2531 EMIT(0x66);
2532 EMIT(0x0F);
2533 EMIT(0x3A);
2534 EMIT(0x17);
2535 emit_sse_operand(src, dst);
2536 EMIT(imm8);
2537 }
2538
2539
pand(XMMRegister dst,XMMRegister src)2540 void Assembler::pand(XMMRegister dst, XMMRegister src) {
2541 EnsureSpace ensure_space(this);
2542 EMIT(0x66);
2543 EMIT(0x0F);
2544 EMIT(0xDB);
2545 emit_sse_operand(dst, src);
2546 }
2547
2548
pxor(XMMRegister dst,XMMRegister src)2549 void Assembler::pxor(XMMRegister dst, XMMRegister src) {
2550 EnsureSpace ensure_space(this);
2551 EMIT(0x66);
2552 EMIT(0x0F);
2553 EMIT(0xEF);
2554 emit_sse_operand(dst, src);
2555 }
2556
2557
por(XMMRegister dst,XMMRegister src)2558 void Assembler::por(XMMRegister dst, XMMRegister src) {
2559 EnsureSpace ensure_space(this);
2560 EMIT(0x66);
2561 EMIT(0x0F);
2562 EMIT(0xEB);
2563 emit_sse_operand(dst, src);
2564 }
2565
2566
ptest(XMMRegister dst,XMMRegister src)2567 void Assembler::ptest(XMMRegister dst, XMMRegister src) {
2568 DCHECK(IsEnabled(SSE4_1));
2569 EnsureSpace ensure_space(this);
2570 EMIT(0x66);
2571 EMIT(0x0F);
2572 EMIT(0x38);
2573 EMIT(0x17);
2574 emit_sse_operand(dst, src);
2575 }
2576
2577
pslld(XMMRegister reg,int8_t shift)2578 void Assembler::pslld(XMMRegister reg, int8_t shift) {
2579 EnsureSpace ensure_space(this);
2580 EMIT(0x66);
2581 EMIT(0x0F);
2582 EMIT(0x72);
2583 emit_sse_operand(esi, reg); // esi == 6
2584 EMIT(shift);
2585 }
2586
2587
psrld(XMMRegister reg,int8_t shift)2588 void Assembler::psrld(XMMRegister reg, int8_t shift) {
2589 EnsureSpace ensure_space(this);
2590 EMIT(0x66);
2591 EMIT(0x0F);
2592 EMIT(0x72);
2593 emit_sse_operand(edx, reg); // edx == 2
2594 EMIT(shift);
2595 }
2596
2597
psllq(XMMRegister reg,int8_t shift)2598 void Assembler::psllq(XMMRegister reg, int8_t shift) {
2599 EnsureSpace ensure_space(this);
2600 EMIT(0x66);
2601 EMIT(0x0F);
2602 EMIT(0x73);
2603 emit_sse_operand(esi, reg); // esi == 6
2604 EMIT(shift);
2605 }
2606
2607
psllq(XMMRegister dst,XMMRegister src)2608 void Assembler::psllq(XMMRegister dst, XMMRegister src) {
2609 EnsureSpace ensure_space(this);
2610 EMIT(0x66);
2611 EMIT(0x0F);
2612 EMIT(0xF3);
2613 emit_sse_operand(dst, src);
2614 }
2615
2616
psrlq(XMMRegister reg,int8_t shift)2617 void Assembler::psrlq(XMMRegister reg, int8_t shift) {
2618 EnsureSpace ensure_space(this);
2619 EMIT(0x66);
2620 EMIT(0x0F);
2621 EMIT(0x73);
2622 emit_sse_operand(edx, reg); // edx == 2
2623 EMIT(shift);
2624 }
2625
2626
psrlq(XMMRegister dst,XMMRegister src)2627 void Assembler::psrlq(XMMRegister dst, XMMRegister src) {
2628 EnsureSpace ensure_space(this);
2629 EMIT(0x66);
2630 EMIT(0x0F);
2631 EMIT(0xD3);
2632 emit_sse_operand(dst, src);
2633 }
2634
2635
pshufd(XMMRegister dst,XMMRegister src,uint8_t shuffle)2636 void Assembler::pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle) {
2637 EnsureSpace ensure_space(this);
2638 EMIT(0x66);
2639 EMIT(0x0F);
2640 EMIT(0x70);
2641 emit_sse_operand(dst, src);
2642 EMIT(shuffle);
2643 }
2644
2645
pextrd(const Operand & dst,XMMRegister src,int8_t offset)2646 void Assembler::pextrd(const Operand& dst, XMMRegister src, int8_t offset) {
2647 DCHECK(IsEnabled(SSE4_1));
2648 EnsureSpace ensure_space(this);
2649 EMIT(0x66);
2650 EMIT(0x0F);
2651 EMIT(0x3A);
2652 EMIT(0x16);
2653 emit_sse_operand(src, dst);
2654 EMIT(offset);
2655 }
2656
2657
pinsrd(XMMRegister dst,const Operand & src,int8_t offset)2658 void Assembler::pinsrd(XMMRegister dst, const Operand& src, int8_t offset) {
2659 DCHECK(IsEnabled(SSE4_1));
2660 EnsureSpace ensure_space(this);
2661 EMIT(0x66);
2662 EMIT(0x0F);
2663 EMIT(0x3A);
2664 EMIT(0x22);
2665 emit_sse_operand(dst, src);
2666 EMIT(offset);
2667 }
2668
2669
addss(XMMRegister dst,const Operand & src)2670 void Assembler::addss(XMMRegister dst, const Operand& src) {
2671 EnsureSpace ensure_space(this);
2672 EMIT(0xF3);
2673 EMIT(0x0F);
2674 EMIT(0x58);
2675 emit_sse_operand(dst, src);
2676 }
2677
2678
subss(XMMRegister dst,const Operand & src)2679 void Assembler::subss(XMMRegister dst, const Operand& src) {
2680 EnsureSpace ensure_space(this);
2681 EMIT(0xF3);
2682 EMIT(0x0F);
2683 EMIT(0x5C);
2684 emit_sse_operand(dst, src);
2685 }
2686
2687
mulss(XMMRegister dst,const Operand & src)2688 void Assembler::mulss(XMMRegister dst, const Operand& src) {
2689 EnsureSpace ensure_space(this);
2690 EMIT(0xF3);
2691 EMIT(0x0F);
2692 EMIT(0x59);
2693 emit_sse_operand(dst, src);
2694 }
2695
2696
divss(XMMRegister dst,const Operand & src)2697 void Assembler::divss(XMMRegister dst, const Operand& src) {
2698 EnsureSpace ensure_space(this);
2699 EMIT(0xF3);
2700 EMIT(0x0F);
2701 EMIT(0x5E);
2702 emit_sse_operand(dst, src);
2703 }
2704
2705
sqrtss(XMMRegister dst,const Operand & src)2706 void Assembler::sqrtss(XMMRegister dst, const Operand& src) {
2707 EnsureSpace ensure_space(this);
2708 EMIT(0xF3);
2709 EMIT(0x0F);
2710 EMIT(0x51);
2711 emit_sse_operand(dst, src);
2712 }
2713
2714
ucomiss(XMMRegister dst,const Operand & src)2715 void Assembler::ucomiss(XMMRegister dst, const Operand& src) {
2716 EnsureSpace ensure_space(this);
2717 EMIT(0x0f);
2718 EMIT(0x2e);
2719 emit_sse_operand(dst, src);
2720 }
2721
2722
maxss(XMMRegister dst,const Operand & src)2723 void Assembler::maxss(XMMRegister dst, const Operand& src) {
2724 EnsureSpace ensure_space(this);
2725 EMIT(0xF3);
2726 EMIT(0x0F);
2727 EMIT(0x5F);
2728 emit_sse_operand(dst, src);
2729 }
2730
2731
minss(XMMRegister dst,const Operand & src)2732 void Assembler::minss(XMMRegister dst, const Operand& src) {
2733 EnsureSpace ensure_space(this);
2734 EMIT(0xF3);
2735 EMIT(0x0F);
2736 EMIT(0x5D);
2737 emit_sse_operand(dst, src);
2738 }
2739
2740
2741 // AVX instructions
vfmasd(byte op,XMMRegister dst,XMMRegister src1,const Operand & src2)2742 void Assembler::vfmasd(byte op, XMMRegister dst, XMMRegister src1,
2743 const Operand& src2) {
2744 DCHECK(IsEnabled(FMA3));
2745 EnsureSpace ensure_space(this);
2746 emit_vex_prefix(src1, kLIG, k66, k0F38, kW1);
2747 EMIT(op);
2748 emit_sse_operand(dst, src2);
2749 }
2750
2751
vfmass(byte op,XMMRegister dst,XMMRegister src1,const Operand & src2)2752 void Assembler::vfmass(byte op, XMMRegister dst, XMMRegister src1,
2753 const Operand& src2) {
2754 DCHECK(IsEnabled(FMA3));
2755 EnsureSpace ensure_space(this);
2756 emit_vex_prefix(src1, kLIG, k66, k0F38, kW0);
2757 EMIT(op);
2758 emit_sse_operand(dst, src2);
2759 }
2760
2761
vsd(byte op,XMMRegister dst,XMMRegister src1,const Operand & src2)2762 void Assembler::vsd(byte op, XMMRegister dst, XMMRegister src1,
2763 const Operand& src2) {
2764 DCHECK(IsEnabled(AVX));
2765 EnsureSpace ensure_space(this);
2766 emit_vex_prefix(src1, kLIG, kF2, k0F, kWIG);
2767 EMIT(op);
2768 emit_sse_operand(dst, src2);
2769 }
2770
2771
vss(byte op,XMMRegister dst,XMMRegister src1,const Operand & src2)2772 void Assembler::vss(byte op, XMMRegister dst, XMMRegister src1,
2773 const Operand& src2) {
2774 DCHECK(IsEnabled(AVX));
2775 EnsureSpace ensure_space(this);
2776 emit_vex_prefix(src1, kLIG, kF3, k0F, kWIG);
2777 EMIT(op);
2778 emit_sse_operand(dst, src2);
2779 }
2780
2781
vps(byte op,XMMRegister dst,XMMRegister src1,const Operand & src2)2782 void Assembler::vps(byte op, XMMRegister dst, XMMRegister src1,
2783 const Operand& src2) {
2784 DCHECK(IsEnabled(AVX));
2785 EnsureSpace ensure_space(this);
2786 emit_vex_prefix(src1, kL128, kNone, k0F, kWIG);
2787 EMIT(op);
2788 emit_sse_operand(dst, src2);
2789 }
2790
2791
vpd(byte op,XMMRegister dst,XMMRegister src1,const Operand & src2)2792 void Assembler::vpd(byte op, XMMRegister dst, XMMRegister src1,
2793 const Operand& src2) {
2794 DCHECK(IsEnabled(AVX));
2795 EnsureSpace ensure_space(this);
2796 emit_vex_prefix(src1, kL128, k66, k0F, kWIG);
2797 EMIT(op);
2798 emit_sse_operand(dst, src2);
2799 }
2800
2801
bmi1(byte op,Register reg,Register vreg,const Operand & rm)2802 void Assembler::bmi1(byte op, Register reg, Register vreg, const Operand& rm) {
2803 DCHECK(IsEnabled(BMI1));
2804 EnsureSpace ensure_space(this);
2805 emit_vex_prefix(vreg, kLZ, kNone, k0F38, kW0);
2806 EMIT(op);
2807 emit_operand(reg, rm);
2808 }
2809
2810
tzcnt(Register dst,const Operand & src)2811 void Assembler::tzcnt(Register dst, const Operand& src) {
2812 DCHECK(IsEnabled(BMI1));
2813 EnsureSpace ensure_space(this);
2814 EMIT(0xF3);
2815 EMIT(0x0F);
2816 EMIT(0xBC);
2817 emit_operand(dst, src);
2818 }
2819
2820
lzcnt(Register dst,const Operand & src)2821 void Assembler::lzcnt(Register dst, const Operand& src) {
2822 DCHECK(IsEnabled(LZCNT));
2823 EnsureSpace ensure_space(this);
2824 EMIT(0xF3);
2825 EMIT(0x0F);
2826 EMIT(0xBD);
2827 emit_operand(dst, src);
2828 }
2829
2830
popcnt(Register dst,const Operand & src)2831 void Assembler::popcnt(Register dst, const Operand& src) {
2832 DCHECK(IsEnabled(POPCNT));
2833 EnsureSpace ensure_space(this);
2834 EMIT(0xF3);
2835 EMIT(0x0F);
2836 EMIT(0xB8);
2837 emit_operand(dst, src);
2838 }
2839
2840
bmi2(SIMDPrefix pp,byte op,Register reg,Register vreg,const Operand & rm)2841 void Assembler::bmi2(SIMDPrefix pp, byte op, Register reg, Register vreg,
2842 const Operand& rm) {
2843 DCHECK(IsEnabled(BMI2));
2844 EnsureSpace ensure_space(this);
2845 emit_vex_prefix(vreg, kLZ, pp, k0F38, kW0);
2846 EMIT(op);
2847 emit_operand(reg, rm);
2848 }
2849
2850
rorx(Register dst,const Operand & src,byte imm8)2851 void Assembler::rorx(Register dst, const Operand& src, byte imm8) {
2852 DCHECK(IsEnabled(BMI2));
2853 DCHECK(is_uint8(imm8));
2854 Register vreg = {0}; // VEX.vvvv unused
2855 EnsureSpace ensure_space(this);
2856 emit_vex_prefix(vreg, kLZ, kF2, k0F3A, kW0);
2857 EMIT(0xF0);
2858 emit_operand(dst, src);
2859 EMIT(imm8);
2860 }
2861
2862
emit_sse_operand(XMMRegister reg,const Operand & adr)2863 void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
2864 Register ireg = { reg.code() };
2865 emit_operand(ireg, adr);
2866 }
2867
2868
emit_sse_operand(XMMRegister dst,XMMRegister src)2869 void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
2870 EMIT(0xC0 | dst.code() << 3 | src.code());
2871 }
2872
2873
emit_sse_operand(Register dst,XMMRegister src)2874 void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
2875 EMIT(0xC0 | dst.code() << 3 | src.code());
2876 }
2877
2878
emit_sse_operand(XMMRegister dst,Register src)2879 void Assembler::emit_sse_operand(XMMRegister dst, Register src) {
2880 EMIT(0xC0 | (dst.code() << 3) | src.code());
2881 }
2882
2883
emit_vex_prefix(XMMRegister vreg,VectorLength l,SIMDPrefix pp,LeadingOpcode mm,VexW w)2884 void Assembler::emit_vex_prefix(XMMRegister vreg, VectorLength l, SIMDPrefix pp,
2885 LeadingOpcode mm, VexW w) {
2886 if (mm != k0F || w != kW0) {
2887 EMIT(0xc4);
2888 // Change RXB from "110" to "111" to align with gdb disassembler.
2889 EMIT(0xe0 | mm);
2890 EMIT(w | ((~vreg.code() & 0xf) << 3) | l | pp);
2891 } else {
2892 EMIT(0xc5);
2893 EMIT(((~vreg.code()) << 3) | l | pp);
2894 }
2895 }
2896
2897
emit_vex_prefix(Register vreg,VectorLength l,SIMDPrefix pp,LeadingOpcode mm,VexW w)2898 void Assembler::emit_vex_prefix(Register vreg, VectorLength l, SIMDPrefix pp,
2899 LeadingOpcode mm, VexW w) {
2900 XMMRegister ivreg = {vreg.code()};
2901 emit_vex_prefix(ivreg, l, pp, mm, w);
2902 }
2903
2904
GrowBuffer()2905 void Assembler::GrowBuffer() {
2906 DCHECK(buffer_overflow());
2907 if (!own_buffer_) FATAL("external code buffer is too small");
2908
2909 // Compute new buffer size.
2910 CodeDesc desc; // the new buffer
2911 desc.buffer_size = 2 * buffer_size_;
2912
2913 // Some internal data structures overflow for very large buffers,
2914 // they must ensure that kMaximalBufferSize is not too large.
2915 if (desc.buffer_size > kMaximalBufferSize ||
2916 static_cast<size_t>(desc.buffer_size) >
2917 isolate()->heap()->MaxOldGenerationSize()) {
2918 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
2919 }
2920
2921 // Set up new buffer.
2922 desc.buffer = NewArray<byte>(desc.buffer_size);
2923 desc.origin = this;
2924 desc.instr_size = pc_offset();
2925 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
2926
2927 // Clear the buffer in debug mode. Use 'int3' instructions to make
2928 // sure to get into problems if we ever run uninitialized code.
2929 #ifdef DEBUG
2930 memset(desc.buffer, 0xCC, desc.buffer_size);
2931 #endif
2932
2933 // Copy the data.
2934 int pc_delta = desc.buffer - buffer_;
2935 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
2936 MemMove(desc.buffer, buffer_, desc.instr_size);
2937 MemMove(rc_delta + reloc_info_writer.pos(), reloc_info_writer.pos(),
2938 desc.reloc_size);
2939
2940 // Switch buffers.
2941 DeleteArray(buffer_);
2942 buffer_ = desc.buffer;
2943 buffer_size_ = desc.buffer_size;
2944 pc_ += pc_delta;
2945 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2946 reloc_info_writer.last_pc() + pc_delta);
2947
2948 // Relocate internal references.
2949 for (auto pos : internal_reference_positions_) {
2950 int32_t* p = reinterpret_cast<int32_t*>(buffer_ + pos);
2951 *p += pc_delta;
2952 }
2953
2954 DCHECK(!buffer_overflow());
2955 }
2956
2957
emit_arith_b(int op1,int op2,Register dst,int imm8)2958 void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
2959 DCHECK(is_uint8(op1) && is_uint8(op2)); // wrong opcode
2960 DCHECK(is_uint8(imm8));
2961 DCHECK((op1 & 0x01) == 0); // should be 8bit operation
2962 EMIT(op1);
2963 EMIT(op2 | dst.code());
2964 EMIT(imm8);
2965 }
2966
2967
emit_arith(int sel,Operand dst,const Immediate & x)2968 void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
2969 DCHECK((0 <= sel) && (sel <= 7));
2970 Register ireg = { sel };
2971 if (x.is_int8()) {
2972 EMIT(0x83); // using a sign-extended 8-bit immediate.
2973 emit_operand(ireg, dst);
2974 EMIT(x.x_ & 0xFF);
2975 } else if (dst.is_reg(eax)) {
2976 EMIT((sel << 3) | 0x05); // short form if the destination is eax.
2977 emit(x);
2978 } else {
2979 EMIT(0x81); // using a literal 32-bit immediate.
2980 emit_operand(ireg, dst);
2981 emit(x);
2982 }
2983 }
2984
2985
emit_operand(Register reg,const Operand & adr)2986 void Assembler::emit_operand(Register reg, const Operand& adr) {
2987 const unsigned length = adr.len_;
2988 DCHECK(length > 0);
2989
2990 // Emit updated ModRM byte containing the given register.
2991 pc_[0] = (adr.buf_[0] & ~0x38) | (reg.code() << 3);
2992
2993 // Emit the rest of the encoded operand.
2994 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
2995 pc_ += length;
2996
2997 // Emit relocation information if necessary.
2998 if (length >= sizeof(int32_t) && !RelocInfo::IsNone(adr.rmode_)) {
2999 pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
3000 RecordRelocInfo(adr.rmode_);
3001 if (adr.rmode_ == RelocInfo::INTERNAL_REFERENCE) { // Fixup for labels
3002 emit_label(*reinterpret_cast<Label**>(pc_));
3003 } else {
3004 pc_ += sizeof(int32_t);
3005 }
3006 }
3007 }
3008
3009
emit_label(Label * label)3010 void Assembler::emit_label(Label* label) {
3011 if (label->is_bound()) {
3012 internal_reference_positions_.push_back(pc_offset());
3013 emit(reinterpret_cast<uint32_t>(buffer_ + label->pos()));
3014 } else {
3015 emit_disp(label, Displacement::CODE_ABSOLUTE);
3016 }
3017 }
3018
3019
emit_farith(int b1,int b2,int i)3020 void Assembler::emit_farith(int b1, int b2, int i) {
3021 DCHECK(is_uint8(b1) && is_uint8(b2)); // wrong opcode
3022 DCHECK(0 <= i && i < 8); // illegal stack offset
3023 EMIT(b1);
3024 EMIT(b2 + i);
3025 }
3026
3027
db(uint8_t data)3028 void Assembler::db(uint8_t data) {
3029 EnsureSpace ensure_space(this);
3030 EMIT(data);
3031 }
3032
3033
dd(uint32_t data)3034 void Assembler::dd(uint32_t data) {
3035 EnsureSpace ensure_space(this);
3036 emit(data);
3037 }
3038
3039
dq(uint64_t data)3040 void Assembler::dq(uint64_t data) {
3041 EnsureSpace ensure_space(this);
3042 emit_q(data);
3043 }
3044
3045
dd(Label * label)3046 void Assembler::dd(Label* label) {
3047 EnsureSpace ensure_space(this);
3048 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
3049 emit_label(label);
3050 }
3051
3052
RecordRelocInfo(RelocInfo::Mode rmode,intptr_t data)3053 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
3054 DCHECK(!RelocInfo::IsNone(rmode));
3055 // Don't record external references unless the heap will be serialized.
3056 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
3057 !serializer_enabled() && !emit_debug_code()) {
3058 return;
3059 }
3060 RelocInfo rinfo(isolate(), pc_, rmode, data, NULL);
3061 reloc_info_writer.Write(&rinfo);
3062 }
3063
3064
3065 } // namespace internal
3066 } // namespace v8
3067
3068 #endif // V8_TARGET_ARCH_IA32
3069