blob: fdf11c1095d70d965a859f9c8a262bae7fa4f1ce [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// 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.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010035// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +000036
Emily Bernierd0a1eb72015-03-24 16:35:39 -040037#include "src/ia32/assembler-ia32.h"
38
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000039#include <cstring>
40
41#if V8_TARGET_ARCH_IA32
42
43#if V8_LIBC_MSVCRT
44#include <intrin.h> // _xgetbv()
45#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -040046#if V8_OS_MACOSX
47#include <sys/sysctl.h>
48#endif
Steve Blocka7e24c12009-10-30 11:49:00 +000049
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050#include "src/base/bits.h"
51#include "src/base/cpu.h"
52#include "src/disassembler.h"
53#include "src/macro-assembler.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040054#include "src/v8.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000055
56namespace v8 {
57namespace internal {
58
59// -----------------------------------------------------------------------------
60// Implementation of CpuFeatures
61
Emily Bernierd0a1eb72015-03-24 16:35:39 -040062namespace {
63
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064#if !V8_LIBC_MSVCRT
65
66V8_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
81bool OSHasAVXSupport() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040082#if V8_OS_MACOSX
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083 // 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.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040085 char buffer[128];
86 size_t buffer_size = arraysize(buffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087 int ctl_name[] = {CTL_KERN, KERN_OSRELEASE};
Emily Bernierd0a1eb72015-03-24 16:35:39 -040088 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000092 // 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;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040098#endif // V8_OS_MACOSX
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000099 // Check whether OS claims to support AVX.
100 uint64_t feature_mask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
101 return (feature_mask & 0x6) == 0x6;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400102}
103
104} // namespace
105
106
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107void 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.
Steve Blocka7e24c12009-10-30 11:49:00 +0000111
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112 // Only use statically determined features for cross compile (snapshot).
113 if (cross_compile) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000114
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115 if (cpu.has_sse41() && FLAG_enable_sse4_1) supported_ |= 1u << SSE4_1;
116 if (cpu.has_sse3() && FLAG_enable_sse3) supported_ |= 1u << SSE3;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117 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 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000134}
135
136
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000137void CpuFeatures::PrintTarget() { }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400138void CpuFeatures::PrintFeatures() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 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));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400147}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148
149
Steve Blocka7e24c12009-10-30 11:49:00 +0000150// -----------------------------------------------------------------------------
151// Implementation of Displacement
152
153void Displacement::init(Label* L, Type type) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154 DCHECK(!L->is_bound());
Steve Blocka7e24c12009-10-30 11:49:00 +0000155 int next = 0;
156 if (L->is_linked()) {
157 next = L->pos();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000158 DCHECK(next > 0); // Displacements must be at positions > 0
Steve Blocka7e24c12009-10-30 11:49:00 +0000159 }
160 // Ensure that we _never_ overflow the next field.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000161 DCHECK(NextField::is_valid(Assembler::kMaximalBufferSize));
Steve Blocka7e24c12009-10-30 11:49:00 +0000162 data_ = NextField::encode(next) | TypeField::encode(type);
163}
164
165
166// -----------------------------------------------------------------------------
167// Implementation of RelocInfo
168
169
170const int RelocInfo::kApplyMask =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000171 RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
172 1 << RelocInfo::INTERNAL_REFERENCE | 1 << RelocInfo::CODE_AGE_SEQUENCE |
173 RelocInfo::kDebugBreakSlotMask;
Steve Blocka7e24c12009-10-30 11:49:00 +0000174
175
Leon Clarkef7060e22010-06-03 12:02:55 +0100176bool 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185bool RelocInfo::IsInConstantPool() {
186 return false;
187}
188
Ben Murdochc5610432016-08-08 18:44:38 +0100189Address RelocInfo::wasm_memory_reference() {
190 DCHECK(IsWasmMemoryReference(rmode_));
191 return Memory::Address_at(pc_);
192}
193
194uint32_t RelocInfo::wasm_memory_size_reference() {
195 DCHECK(IsWasmMemorySizeReference(rmode_));
196 return Memory::uint32_at(pc_);
197}
198
199void RelocInfo::update_wasm_memory_reference(
200 Address old_base, Address new_base, uint32_t old_size, uint32_t new_size,
201 ICacheFlushMode icache_flush_mode) {
202 DCHECK(IsWasmMemoryReference(rmode_) || IsWasmMemorySizeReference(rmode_));
203 if (IsWasmMemoryReference(rmode_)) {
204 Address updated_reference;
205 DCHECK(old_base <= wasm_memory_reference() &&
206 wasm_memory_reference() < old_base + old_size);
207 updated_reference = new_base + (wasm_memory_reference() - old_base);
208 DCHECK(new_base <= updated_reference &&
209 updated_reference < new_base + new_size);
210 Memory::Address_at(pc_) = updated_reference;
211 } else if (IsWasmMemorySizeReference(rmode_)) {
212 uint32_t updated_size_reference;
213 DCHECK(wasm_memory_size_reference() <= old_size);
214 updated_size_reference =
215 new_size + (wasm_memory_size_reference() - old_size);
216 DCHECK(updated_size_reference <= new_size);
217 Memory::uint32_at(pc_) = updated_size_reference;
218 } else {
219 UNREACHABLE();
220 }
221 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
222 Assembler::FlushICache(isolate_, pc_, sizeof(int32_t));
223 }
224}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225
Steve Blocka7e24c12009-10-30 11:49:00 +0000226// -----------------------------------------------------------------------------
227// Implementation of Operand
228
229Operand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) {
230 // [base + disp/r]
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231 if (disp == 0 && RelocInfo::IsNone(rmode) && !base.is(ebp)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000232 // [base]
233 set_modrm(0, base);
234 if (base.is(esp)) set_sib(times_1, esp, base);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235 } else if (is_int8(disp) && RelocInfo::IsNone(rmode)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000236 // [base + disp8]
237 set_modrm(1, base);
238 if (base.is(esp)) set_sib(times_1, esp, base);
239 set_disp8(disp);
240 } else {
241 // [base + disp/r]
242 set_modrm(2, base);
243 if (base.is(esp)) set_sib(times_1, esp, base);
244 set_dispr(disp, rmode);
245 }
246}
247
248
249Operand::Operand(Register base,
250 Register index,
251 ScaleFactor scale,
252 int32_t disp,
253 RelocInfo::Mode rmode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000254 DCHECK(!index.is(esp)); // illegal addressing mode
Steve Blocka7e24c12009-10-30 11:49:00 +0000255 // [base + index*scale + disp/r]
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000256 if (disp == 0 && RelocInfo::IsNone(rmode) && !base.is(ebp)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000257 // [base + index*scale]
258 set_modrm(0, esp);
259 set_sib(scale, index, base);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000260 } else if (is_int8(disp) && RelocInfo::IsNone(rmode)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000261 // [base + index*scale + disp8]
262 set_modrm(1, esp);
263 set_sib(scale, index, base);
264 set_disp8(disp);
265 } else {
266 // [base + index*scale + disp/r]
267 set_modrm(2, esp);
268 set_sib(scale, index, base);
269 set_dispr(disp, rmode);
270 }
271}
272
273
274Operand::Operand(Register index,
275 ScaleFactor scale,
276 int32_t disp,
277 RelocInfo::Mode rmode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278 DCHECK(!index.is(esp)); // illegal addressing mode
Steve Blocka7e24c12009-10-30 11:49:00 +0000279 // [index*scale + disp/r]
280 set_modrm(0, esp);
281 set_sib(scale, index, ebp);
282 set_dispr(disp, rmode);
283}
284
285
286bool Operand::is_reg(Register reg) const {
287 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only.
288 && ((buf_[0] & 0x07) == reg.code()); // register codes match.
289}
290
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100291
292bool Operand::is_reg_only() const {
293 return (buf_[0] & 0xF8) == 0xC0; // Addressing mode is register only.
294}
295
296
297Register Operand::reg() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 DCHECK(is_reg_only());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100299 return Register::from_code(buf_[0] & 0x07);
300}
301
302
Steve Blocka7e24c12009-10-30 11:49:00 +0000303// -----------------------------------------------------------------------------
Andrei Popescu31002712010-02-23 13:46:05 +0000304// Implementation of Assembler.
Steve Blocka7e24c12009-10-30 11:49:00 +0000305
306// Emit a single byte. Must always be inlined.
307#define EMIT(x) \
308 *pc_++ = (x)
309
310
311#ifdef GENERATED_CODE_COVERAGE
312static void InitCoverageLog();
313#endif
314
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000315Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
316 : AssemblerBase(isolate, buffer, buffer_size),
317 positions_recorder_(this) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000318 // Clear the buffer in debug mode unless it was provided by the
319 // caller in which case we can't be sure it's okay to overwrite
320 // existing code in it; see CodePatcher::CodePatcher(...).
321#ifdef DEBUG
322 if (own_buffer_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323 memset(buffer_, 0xCC, buffer_size_); // int3
Steve Blocka7e24c12009-10-30 11:49:00 +0000324 }
325#endif
326
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000327 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000328
Steve Blocka7e24c12009-10-30 11:49:00 +0000329#ifdef GENERATED_CODE_COVERAGE
330 InitCoverageLog();
331#endif
332}
333
334
Steve Blocka7e24c12009-10-30 11:49:00 +0000335void Assembler::GetCode(CodeDesc* desc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000336 // Finalize code (at this point overflow() may be true, but the gap ensures
337 // that we are still not overlapping instructions and relocation info).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000338 reloc_info_writer.Finish();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000339 DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100340 // Set up code descriptor.
Steve Blocka7e24c12009-10-30 11:49:00 +0000341 desc->buffer = buffer_;
342 desc->buffer_size = buffer_size_;
343 desc->instr_size = pc_offset();
344 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
345 desc->origin = this;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000346 desc->constant_pool_size = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000347}
348
349
350void Assembler::Align(int m) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000351 DCHECK(base::bits::IsPowerOfTwo32(m));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100352 int mask = m - 1;
353 int addr = pc_offset();
354 Nop((m - (addr & mask)) & mask);
355}
356
357
358bool Assembler::IsNop(Address addr) {
359 Address a = addr;
360 while (*a == 0x66) a++;
361 if (*a == 0x90) return true;
362 if (a[0] == 0xf && a[1] == 0x1f) return true;
363 return false;
364}
365
366
367void Assembler::Nop(int bytes) {
368 EnsureSpace ensure_space(this);
369
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100370 // Multi byte nops from http://support.amd.com/us/Processor_TechDocs/40546.pdf
371 while (bytes > 0) {
372 switch (bytes) {
373 case 2:
374 EMIT(0x66);
375 case 1:
376 EMIT(0x90);
377 return;
378 case 3:
379 EMIT(0xf);
380 EMIT(0x1f);
381 EMIT(0);
382 return;
383 case 4:
384 EMIT(0xf);
385 EMIT(0x1f);
386 EMIT(0x40);
387 EMIT(0);
388 return;
389 case 6:
390 EMIT(0x66);
391 case 5:
392 EMIT(0xf);
393 EMIT(0x1f);
394 EMIT(0x44);
395 EMIT(0);
396 EMIT(0);
397 return;
398 case 7:
399 EMIT(0xf);
400 EMIT(0x1f);
401 EMIT(0x80);
402 EMIT(0);
403 EMIT(0);
404 EMIT(0);
405 EMIT(0);
406 return;
407 default:
408 case 11:
409 EMIT(0x66);
410 bytes--;
411 case 10:
412 EMIT(0x66);
413 bytes--;
414 case 9:
415 EMIT(0x66);
416 bytes--;
417 case 8:
418 EMIT(0xf);
419 EMIT(0x1f);
420 EMIT(0x84);
421 EMIT(0);
422 EMIT(0);
423 EMIT(0);
424 EMIT(0);
425 EMIT(0);
426 bytes -= 8;
427 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000428 }
429}
430
431
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100432void Assembler::CodeTargetAlign() {
433 Align(16); // Preferred alignment of jump targets on ia32.
434}
435
436
Steve Blocka7e24c12009-10-30 11:49:00 +0000437void Assembler::cpuid() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000438 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000439 EMIT(0x0F);
440 EMIT(0xA2);
441}
442
443
444void Assembler::pushad() {
445 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000446 EMIT(0x60);
447}
448
449
450void Assembler::popad() {
451 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000452 EMIT(0x61);
453}
454
455
456void Assembler::pushfd() {
457 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000458 EMIT(0x9C);
459}
460
461
462void Assembler::popfd() {
463 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000464 EMIT(0x9D);
465}
466
467
468void Assembler::push(const Immediate& x) {
469 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000470 if (x.is_int8()) {
471 EMIT(0x6a);
472 EMIT(x.x_);
473 } else {
474 EMIT(0x68);
475 emit(x);
476 }
477}
478
479
Ben Murdochb0fe1622011-05-05 13:52:32 +0100480void Assembler::push_imm32(int32_t imm32) {
481 EnsureSpace ensure_space(this);
482 EMIT(0x68);
483 emit(imm32);
484}
485
486
Steve Blocka7e24c12009-10-30 11:49:00 +0000487void Assembler::push(Register src) {
488 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000489 EMIT(0x50 | src.code());
490}
491
492
493void Assembler::push(const Operand& src) {
494 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000495 EMIT(0xFF);
496 emit_operand(esi, src);
497}
498
499
500void Assembler::pop(Register dst) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000501 DCHECK(reloc_info_writer.last_pc() != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000502 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000503 EMIT(0x58 | dst.code());
504}
505
506
507void Assembler::pop(const Operand& dst) {
508 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000509 EMIT(0x8F);
510 emit_operand(eax, dst);
511}
512
513
514void Assembler::enter(const Immediate& size) {
515 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000516 EMIT(0xC8);
517 emit_w(size);
518 EMIT(0);
519}
520
521
522void Assembler::leave() {
523 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000524 EMIT(0xC9);
525}
526
527
528void Assembler::mov_b(Register dst, const Operand& src) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100529 CHECK(dst.is_byte_register());
Steve Blocka7e24c12009-10-30 11:49:00 +0000530 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000531 EMIT(0x8A);
532 emit_operand(dst, src);
533}
534
535
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400536void Assembler::mov_b(const Operand& dst, const Immediate& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000537 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000538 EMIT(0xC6);
539 emit_operand(eax, dst);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400540 EMIT(static_cast<int8_t>(src.x_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000541}
542
543
544void Assembler::mov_b(const Operand& dst, Register src) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100545 CHECK(src.is_byte_register());
Steve Blocka7e24c12009-10-30 11:49:00 +0000546 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000547 EMIT(0x88);
548 emit_operand(src, dst);
549}
550
551
552void Assembler::mov_w(Register dst, const Operand& src) {
553 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000554 EMIT(0x66);
555 EMIT(0x8B);
556 emit_operand(dst, src);
557}
558
559
560void Assembler::mov_w(const Operand& dst, Register src) {
561 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000562 EMIT(0x66);
563 EMIT(0x89);
564 emit_operand(src, dst);
565}
566
567
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400568void Assembler::mov_w(const Operand& dst, const Immediate& src) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000569 EnsureSpace ensure_space(this);
570 EMIT(0x66);
571 EMIT(0xC7);
572 emit_operand(eax, dst);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400573 EMIT(static_cast<int8_t>(src.x_ & 0xff));
574 EMIT(static_cast<int8_t>(src.x_ >> 8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000575}
576
577
Steve Blocka7e24c12009-10-30 11:49:00 +0000578void Assembler::mov(Register dst, int32_t imm32) {
579 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000580 EMIT(0xB8 | dst.code());
581 emit(imm32);
582}
583
584
585void Assembler::mov(Register dst, const Immediate& x) {
586 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000587 EMIT(0xB8 | dst.code());
588 emit(x);
589}
590
591
592void Assembler::mov(Register dst, Handle<Object> handle) {
593 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000594 EMIT(0xB8 | dst.code());
595 emit(handle);
596}
597
598
599void Assembler::mov(Register dst, const Operand& src) {
600 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000601 EMIT(0x8B);
602 emit_operand(dst, src);
603}
604
605
606void Assembler::mov(Register dst, Register src) {
607 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000608 EMIT(0x89);
609 EMIT(0xC0 | src.code() << 3 | dst.code());
610}
611
612
613void Assembler::mov(const Operand& dst, const Immediate& x) {
614 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000615 EMIT(0xC7);
616 emit_operand(eax, dst);
617 emit(x);
618}
619
620
621void Assembler::mov(const Operand& dst, Handle<Object> handle) {
622 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000623 EMIT(0xC7);
624 emit_operand(eax, dst);
625 emit(handle);
626}
627
628
629void Assembler::mov(const Operand& dst, Register src) {
630 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000631 EMIT(0x89);
632 emit_operand(src, dst);
633}
634
635
636void Assembler::movsx_b(Register dst, const Operand& src) {
637 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000638 EMIT(0x0F);
639 EMIT(0xBE);
640 emit_operand(dst, src);
641}
642
643
644void Assembler::movsx_w(Register dst, const Operand& src) {
645 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000646 EMIT(0x0F);
647 EMIT(0xBF);
648 emit_operand(dst, src);
649}
650
651
652void Assembler::movzx_b(Register dst, const Operand& src) {
653 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000654 EMIT(0x0F);
655 EMIT(0xB6);
656 emit_operand(dst, src);
657}
658
659
660void Assembler::movzx_w(Register dst, const Operand& src) {
661 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000662 EMIT(0x0F);
663 EMIT(0xB7);
664 emit_operand(dst, src);
665}
666
667
Steve Blocka7e24c12009-10-30 11:49:00 +0000668void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000669 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000670 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000671 EMIT(0x0F);
672 EMIT(0x40 + cc);
673 emit_operand(dst, src);
674}
675
676
Steve Block6ded16b2010-05-10 14:33:55 +0100677void Assembler::cld() {
678 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +0100679 EMIT(0xFC);
680}
681
682
Leon Clarkee46be812010-01-19 14:06:41 +0000683void Assembler::rep_movs() {
684 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +0000685 EMIT(0xF3);
686 EMIT(0xA5);
687}
688
689
Steve Block6ded16b2010-05-10 14:33:55 +0100690void Assembler::rep_stos() {
691 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +0100692 EMIT(0xF3);
693 EMIT(0xAB);
694}
695
696
Leon Clarkef7060e22010-06-03 12:02:55 +0100697void Assembler::stos() {
698 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +0100699 EMIT(0xAB);
700}
701
702
Steve Blocka7e24c12009-10-30 11:49:00 +0000703void Assembler::xchg(Register dst, Register src) {
704 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000705 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding.
Steve Blocka7e24c12009-10-30 11:49:00 +0000706 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code()));
707 } else {
708 EMIT(0x87);
709 EMIT(0xC0 | src.code() << 3 | dst.code());
710 }
711}
712
713
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000714void Assembler::xchg(Register dst, const Operand& src) {
715 EnsureSpace ensure_space(this);
716 EMIT(0x87);
717 emit_operand(dst, src);
718}
719
Ben Murdochc5610432016-08-08 18:44:38 +0100720void Assembler::xchg_b(Register reg, const Operand& op) {
721 EnsureSpace ensure_space(this);
722 EMIT(0x86);
723 emit_operand(reg, op);
724}
725
726void Assembler::xchg_w(Register reg, const Operand& op) {
727 EnsureSpace ensure_space(this);
728 EMIT(0x66);
729 EMIT(0x87);
730 emit_operand(reg, op);
731}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000732
Steve Blocka7e24c12009-10-30 11:49:00 +0000733void Assembler::adc(Register dst, int32_t imm32) {
734 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000735 emit_arith(2, Operand(dst), Immediate(imm32));
736}
737
738
739void Assembler::adc(Register dst, const Operand& src) {
740 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000741 EMIT(0x13);
742 emit_operand(dst, src);
743}
744
745
746void Assembler::add(Register dst, const Operand& src) {
747 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000748 EMIT(0x03);
749 emit_operand(dst, src);
750}
751
752
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100753void Assembler::add(const Operand& dst, Register src) {
754 EnsureSpace ensure_space(this);
755 EMIT(0x01);
756 emit_operand(src, dst);
757}
758
759
Steve Blocka7e24c12009-10-30 11:49:00 +0000760void Assembler::add(const Operand& dst, const Immediate& x) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761 DCHECK(reloc_info_writer.last_pc() != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000762 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000763 emit_arith(0, dst, x);
764}
765
766
767void Assembler::and_(Register dst, int32_t imm32) {
Steve Block59151502010-09-22 15:07:15 +0100768 and_(dst, Immediate(imm32));
769}
770
771
772void Assembler::and_(Register dst, const Immediate& x) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000773 EnsureSpace ensure_space(this);
Steve Block59151502010-09-22 15:07:15 +0100774 emit_arith(4, Operand(dst), x);
Steve Blocka7e24c12009-10-30 11:49:00 +0000775}
776
777
778void Assembler::and_(Register dst, const Operand& src) {
779 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000780 EMIT(0x23);
781 emit_operand(dst, src);
782}
783
784
785void Assembler::and_(const Operand& dst, const Immediate& x) {
786 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000787 emit_arith(4, dst, x);
788}
789
790
791void Assembler::and_(const Operand& dst, Register src) {
792 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000793 EMIT(0x21);
794 emit_operand(src, dst);
795}
796
Ben Murdochda12d292016-06-02 14:46:10 +0100797void Assembler::cmpb(const Operand& op, Immediate imm8) {
798 DCHECK(imm8.is_int8() || imm8.is_uint8());
Steve Blocka7e24c12009-10-30 11:49:00 +0000799 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100800 if (op.is_reg(eax)) {
801 EMIT(0x3C);
802 } else {
803 EMIT(0x80);
804 emit_operand(edi, op); // edi == 7
805 }
Ben Murdochda12d292016-06-02 14:46:10 +0100806 emit_b(imm8);
Steve Blocka7e24c12009-10-30 11:49:00 +0000807}
808
809
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100810void Assembler::cmpb(const Operand& op, Register reg) {
811 CHECK(reg.is_byte_register());
Leon Clarked91b9f72010-01-27 17:25:45 +0000812 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +0000813 EMIT(0x38);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100814 emit_operand(reg, op);
Leon Clarked91b9f72010-01-27 17:25:45 +0000815}
816
817
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100818void Assembler::cmpb(Register reg, const Operand& op) {
819 CHECK(reg.is_byte_register());
Leon Clarked91b9f72010-01-27 17:25:45 +0000820 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +0000821 EMIT(0x3A);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100822 emit_operand(reg, op);
Leon Clarked91b9f72010-01-27 17:25:45 +0000823}
824
825
Steve Blocka7e24c12009-10-30 11:49:00 +0000826void Assembler::cmpw(const Operand& op, Immediate imm16) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000827 DCHECK(imm16.is_int16());
Steve Blocka7e24c12009-10-30 11:49:00 +0000828 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000829 EMIT(0x66);
830 EMIT(0x81);
831 emit_operand(edi, op);
832 emit_w(imm16);
833}
834
Ben Murdochda12d292016-06-02 14:46:10 +0100835void Assembler::cmpw(Register reg, const Operand& op) {
836 EnsureSpace ensure_space(this);
837 EMIT(0x66);
Ben Murdochc5610432016-08-08 18:44:38 +0100838 EMIT(0x3B);
Ben Murdochda12d292016-06-02 14:46:10 +0100839 emit_operand(reg, op);
840}
841
842void Assembler::cmpw(const Operand& op, Register reg) {
843 EnsureSpace ensure_space(this);
844 EMIT(0x66);
Ben Murdochc5610432016-08-08 18:44:38 +0100845 EMIT(0x39);
Ben Murdochda12d292016-06-02 14:46:10 +0100846 emit_operand(reg, op);
847}
Steve Blocka7e24c12009-10-30 11:49:00 +0000848
849void Assembler::cmp(Register reg, int32_t imm32) {
850 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000851 emit_arith(7, Operand(reg), Immediate(imm32));
852}
853
854
855void Assembler::cmp(Register reg, Handle<Object> handle) {
856 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000857 emit_arith(7, Operand(reg), Immediate(handle));
858}
859
860
861void Assembler::cmp(Register reg, const Operand& op) {
862 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000863 EMIT(0x3B);
864 emit_operand(reg, op);
865}
866
Ben Murdoch097c5b22016-05-18 11:27:45 +0100867void Assembler::cmp(const Operand& op, Register reg) {
868 EnsureSpace ensure_space(this);
869 EMIT(0x39);
870 emit_operand(reg, op);
871}
Steve Blocka7e24c12009-10-30 11:49:00 +0000872
873void Assembler::cmp(const Operand& op, const Immediate& imm) {
874 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000875 emit_arith(7, op, imm);
876}
877
878
879void Assembler::cmp(const Operand& op, Handle<Object> handle) {
880 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000881 emit_arith(7, op, Immediate(handle));
882}
883
884
885void Assembler::cmpb_al(const Operand& op) {
886 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000887 EMIT(0x38); // CMP r/m8, r8
888 emit_operand(eax, op); // eax has same code as register al.
889}
890
891
892void Assembler::cmpw_ax(const Operand& op) {
893 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000894 EMIT(0x66);
895 EMIT(0x39); // CMP r/m16, r16
896 emit_operand(eax, op); // eax has same code as register ax.
897}
898
899
900void Assembler::dec_b(Register dst) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100901 CHECK(dst.is_byte_register());
Steve Blocka7e24c12009-10-30 11:49:00 +0000902 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000903 EMIT(0xFE);
904 EMIT(0xC8 | dst.code());
905}
906
907
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100908void Assembler::dec_b(const Operand& dst) {
909 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100910 EMIT(0xFE);
911 emit_operand(ecx, dst);
912}
913
914
Steve Blocka7e24c12009-10-30 11:49:00 +0000915void Assembler::dec(Register dst) {
916 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000917 EMIT(0x48 | dst.code());
918}
919
920
921void Assembler::dec(const Operand& dst) {
922 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000923 EMIT(0xFF);
924 emit_operand(ecx, dst);
925}
926
927
928void Assembler::cdq() {
929 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000930 EMIT(0x99);
931}
932
933
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000934void Assembler::idiv(const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000935 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000936 EMIT(0xF7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000937 emit_operand(edi, src);
938}
939
940
941void Assembler::div(const Operand& src) {
942 EnsureSpace ensure_space(this);
943 EMIT(0xF7);
944 emit_operand(esi, src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000945}
946
947
948void Assembler::imul(Register reg) {
949 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000950 EMIT(0xF7);
951 EMIT(0xE8 | reg.code());
952}
953
954
955void Assembler::imul(Register dst, const Operand& src) {
956 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000957 EMIT(0x0F);
958 EMIT(0xAF);
959 emit_operand(dst, src);
960}
961
962
963void Assembler::imul(Register dst, Register src, int32_t imm32) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000964 imul(dst, Operand(src), imm32);
965}
966
967
968void Assembler::imul(Register dst, const Operand& src, int32_t imm32) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000969 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000970 if (is_int8(imm32)) {
971 EMIT(0x6B);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000972 emit_operand(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000973 EMIT(imm32);
974 } else {
975 EMIT(0x69);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000976 emit_operand(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000977 emit(imm32);
978 }
979}
980
981
982void Assembler::inc(Register dst) {
983 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000984 EMIT(0x40 | dst.code());
985}
986
987
988void Assembler::inc(const Operand& dst) {
989 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000990 EMIT(0xFF);
991 emit_operand(eax, dst);
992}
993
994
995void Assembler::lea(Register dst, const Operand& src) {
996 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000997 EMIT(0x8D);
998 emit_operand(dst, src);
999}
1000
1001
1002void Assembler::mul(Register src) {
1003 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001004 EMIT(0xF7);
1005 EMIT(0xE0 | src.code());
1006}
1007
1008
1009void Assembler::neg(Register dst) {
1010 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001011 EMIT(0xF7);
1012 EMIT(0xD8 | dst.code());
1013}
1014
1015
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001016void Assembler::neg(const Operand& dst) {
1017 EnsureSpace ensure_space(this);
1018 EMIT(0xF7);
1019 emit_operand(ebx, dst);
1020}
1021
1022
Steve Blocka7e24c12009-10-30 11:49:00 +00001023void Assembler::not_(Register dst) {
1024 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001025 EMIT(0xF7);
1026 EMIT(0xD0 | dst.code());
1027}
1028
1029
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001030void Assembler::not_(const Operand& dst) {
1031 EnsureSpace ensure_space(this);
1032 EMIT(0xF7);
1033 emit_operand(edx, dst);
1034}
1035
1036
Steve Blocka7e24c12009-10-30 11:49:00 +00001037void Assembler::or_(Register dst, int32_t imm32) {
1038 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001039 emit_arith(1, Operand(dst), Immediate(imm32));
1040}
1041
1042
1043void Assembler::or_(Register dst, const Operand& src) {
1044 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001045 EMIT(0x0B);
1046 emit_operand(dst, src);
1047}
1048
1049
1050void Assembler::or_(const Operand& dst, const Immediate& x) {
1051 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001052 emit_arith(1, dst, x);
1053}
1054
1055
1056void Assembler::or_(const Operand& dst, Register src) {
1057 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001058 EMIT(0x09);
1059 emit_operand(src, dst);
1060}
1061
1062
1063void Assembler::rcl(Register dst, uint8_t imm8) {
1064 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001065 DCHECK(is_uint5(imm8)); // illegal shift count
Steve Blocka7e24c12009-10-30 11:49:00 +00001066 if (imm8 == 1) {
1067 EMIT(0xD1);
1068 EMIT(0xD0 | dst.code());
1069 } else {
1070 EMIT(0xC1);
1071 EMIT(0xD0 | dst.code());
1072 EMIT(imm8);
1073 }
1074}
1075
1076
Iain Merrick75681382010-08-19 15:07:18 +01001077void Assembler::rcr(Register dst, uint8_t imm8) {
1078 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001079 DCHECK(is_uint5(imm8)); // illegal shift count
Iain Merrick75681382010-08-19 15:07:18 +01001080 if (imm8 == 1) {
1081 EMIT(0xD1);
1082 EMIT(0xD8 | dst.code());
1083 } else {
1084 EMIT(0xC1);
1085 EMIT(0xD8 | dst.code());
1086 EMIT(imm8);
1087 }
1088}
1089
1090
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001091void Assembler::ror(const Operand& dst, uint8_t imm8) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001092 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001093 DCHECK(is_uint5(imm8)); // illegal shift count
Steve Blocka7e24c12009-10-30 11:49:00 +00001094 if (imm8 == 1) {
1095 EMIT(0xD1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001096 emit_operand(ecx, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001097 } else {
1098 EMIT(0xC1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001099 emit_operand(ecx, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001100 EMIT(imm8);
1101 }
1102}
1103
1104
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001105void Assembler::ror_cl(const Operand& dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001106 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001107 EMIT(0xD3);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001108 emit_operand(ecx, dst);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001109}
1110
1111
1112void Assembler::sar(const Operand& dst, uint8_t imm8) {
1113 EnsureSpace ensure_space(this);
1114 DCHECK(is_uint5(imm8)); // illegal shift count
1115 if (imm8 == 1) {
1116 EMIT(0xD1);
1117 emit_operand(edi, dst);
1118 } else {
1119 EMIT(0xC1);
1120 emit_operand(edi, dst);
1121 EMIT(imm8);
1122 }
1123}
1124
1125
1126void Assembler::sar_cl(const Operand& dst) {
1127 EnsureSpace ensure_space(this);
1128 EMIT(0xD3);
1129 emit_operand(edi, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001130}
1131
Steve Blocka7e24c12009-10-30 11:49:00 +00001132void Assembler::sbb(Register dst, const Operand& src) {
1133 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001134 EMIT(0x1B);
1135 emit_operand(dst, src);
1136}
1137
Ben Murdochda12d292016-06-02 14:46:10 +01001138void Assembler::shld(Register dst, Register src, uint8_t shift) {
1139 DCHECK(is_uint5(shift));
1140 EnsureSpace ensure_space(this);
1141 EMIT(0x0F);
1142 EMIT(0xA4);
1143 emit_operand(src, Operand(dst));
1144 EMIT(shift);
1145}
Steve Blocka7e24c12009-10-30 11:49:00 +00001146
Ben Murdochda12d292016-06-02 14:46:10 +01001147void Assembler::shld_cl(Register dst, Register src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001148 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001149 EMIT(0x0F);
1150 EMIT(0xA5);
Ben Murdochda12d292016-06-02 14:46:10 +01001151 emit_operand(src, Operand(dst));
Steve Blocka7e24c12009-10-30 11:49:00 +00001152}
1153
1154
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001155void Assembler::shl(const Operand& dst, uint8_t imm8) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001156 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001157 DCHECK(is_uint5(imm8)); // illegal shift count
Steve Blocka7e24c12009-10-30 11:49:00 +00001158 if (imm8 == 1) {
1159 EMIT(0xD1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001160 emit_operand(esp, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001161 } else {
1162 EMIT(0xC1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001163 emit_operand(esp, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001164 EMIT(imm8);
1165 }
1166}
1167
1168
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001169void Assembler::shl_cl(const Operand& dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001170 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001171 EMIT(0xD3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001172 emit_operand(esp, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001173}
1174
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001175void Assembler::shr(const Operand& dst, uint8_t imm8) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001176 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001177 DCHECK(is_uint5(imm8)); // illegal shift count
Steve Blockd0582a62009-12-15 09:54:21 +00001178 if (imm8 == 1) {
1179 EMIT(0xD1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001180 emit_operand(ebp, dst);
Steve Blockd0582a62009-12-15 09:54:21 +00001181 } else {
1182 EMIT(0xC1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001183 emit_operand(ebp, dst);
Steve Blockd0582a62009-12-15 09:54:21 +00001184 EMIT(imm8);
1185 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001186}
1187
1188
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001189void Assembler::shr_cl(const Operand& dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001190 EnsureSpace ensure_space(this);
Steve Blockd0582a62009-12-15 09:54:21 +00001191 EMIT(0xD3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001192 emit_operand(ebp, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001193}
1194
Ben Murdochda12d292016-06-02 14:46:10 +01001195void Assembler::shrd(Register dst, Register src, uint8_t shift) {
1196 DCHECK(is_uint5(shift));
1197 EnsureSpace ensure_space(this);
1198 EMIT(0x0F);
1199 EMIT(0xAC);
1200 emit_operand(dst, Operand(src));
1201 EMIT(shift);
1202}
1203
1204void Assembler::shrd_cl(const Operand& dst, Register src) {
1205 EnsureSpace ensure_space(this);
1206 EMIT(0x0F);
1207 EMIT(0xAD);
1208 emit_operand(src, dst);
1209}
Steve Blocka7e24c12009-10-30 11:49:00 +00001210
1211void Assembler::sub(const Operand& dst, const Immediate& x) {
1212 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001213 emit_arith(5, dst, x);
1214}
1215
1216
1217void Assembler::sub(Register dst, const Operand& src) {
1218 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001219 EMIT(0x2B);
1220 emit_operand(dst, src);
1221}
1222
1223
1224void Assembler::sub(const Operand& dst, Register src) {
1225 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001226 EMIT(0x29);
1227 emit_operand(src, dst);
1228}
1229
1230
1231void Assembler::test(Register reg, const Immediate& imm) {
Ben Murdochda12d292016-06-02 14:46:10 +01001232 if (imm.is_uint8()) {
1233 test_b(reg, imm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001234 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001235 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001236
1237 EnsureSpace ensure_space(this);
1238 // This is not using emit_arith because test doesn't support
1239 // sign-extension of 8-bit operands.
1240 if (reg.is(eax)) {
1241 EMIT(0xA9);
1242 } else {
1243 EMIT(0xF7);
1244 EMIT(0xC0 | reg.code());
1245 }
1246 emit(imm);
Steve Blocka7e24c12009-10-30 11:49:00 +00001247}
1248
1249
1250void Assembler::test(Register reg, const Operand& op) {
1251 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001252 EMIT(0x85);
1253 emit_operand(reg, op);
1254}
1255
1256
Leon Clarkee46be812010-01-19 14:06:41 +00001257void Assembler::test_b(Register reg, const Operand& op) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001258 CHECK(reg.is_byte_register());
Leon Clarkee46be812010-01-19 14:06:41 +00001259 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00001260 EMIT(0x84);
1261 emit_operand(reg, op);
1262}
1263
1264
Steve Blocka7e24c12009-10-30 11:49:00 +00001265void Assembler::test(const Operand& op, const Immediate& imm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001266 if (op.is_reg_only()) {
1267 test(op.reg(), imm);
1268 return;
1269 }
Ben Murdochda12d292016-06-02 14:46:10 +01001270 if (imm.is_uint8()) {
1271 return test_b(op, imm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001272 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001273 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001274 EMIT(0xF7);
1275 emit_operand(eax, op);
1276 emit(imm);
1277}
1278
Ben Murdochda12d292016-06-02 14:46:10 +01001279void Assembler::test_b(Register reg, Immediate imm8) {
1280 DCHECK(imm8.is_uint8());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001281 EnsureSpace ensure_space(this);
1282 // Only use test against byte for registers that have a byte
1283 // variant: eax, ebx, ecx, and edx.
1284 if (reg.is(eax)) {
1285 EMIT(0xA8);
Ben Murdochda12d292016-06-02 14:46:10 +01001286 emit_b(imm8);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001287 } else if (reg.is_byte_register()) {
Ben Murdochda12d292016-06-02 14:46:10 +01001288 emit_arith_b(0xF6, 0xC0, reg, static_cast<uint8_t>(imm8.x_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001289 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01001290 EMIT(0x66);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291 EMIT(0xF7);
1292 EMIT(0xC0 | reg.code());
Ben Murdochda12d292016-06-02 14:46:10 +01001293 emit_w(imm8);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001294 }
1295}
1296
Ben Murdochda12d292016-06-02 14:46:10 +01001297void Assembler::test_b(const Operand& op, Immediate imm8) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001298 if (op.is_reg_only()) {
1299 test_b(op.reg(), imm8);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001300 return;
1301 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001302 EnsureSpace ensure_space(this);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001303 EMIT(0xF6);
1304 emit_operand(eax, op);
Ben Murdochda12d292016-06-02 14:46:10 +01001305 emit_b(imm8);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001306}
1307
Ben Murdochda12d292016-06-02 14:46:10 +01001308void Assembler::test_w(Register reg, Immediate imm16) {
1309 DCHECK(imm16.is_int16() || imm16.is_uint16());
1310 EnsureSpace ensure_space(this);
1311 if (reg.is(eax)) {
1312 EMIT(0xA9);
1313 emit_w(imm16);
1314 } else {
1315 EMIT(0x66);
1316 EMIT(0xF7);
1317 EMIT(0xc0 | reg.code());
1318 emit_w(imm16);
1319 }
1320}
1321
1322void Assembler::test_w(Register reg, const Operand& op) {
1323 EnsureSpace ensure_space(this);
1324 EMIT(0x66);
1325 EMIT(0x85);
1326 emit_operand(reg, op);
1327}
1328
1329void Assembler::test_w(const Operand& op, Immediate imm16) {
1330 DCHECK(imm16.is_int16() || imm16.is_uint16());
1331 if (op.is_reg_only()) {
1332 test_w(op.reg(), imm16);
1333 return;
1334 }
1335 EnsureSpace ensure_space(this);
1336 EMIT(0x66);
1337 EMIT(0xF7);
1338 emit_operand(eax, op);
1339 emit_w(imm16);
1340}
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001341
Steve Blocka7e24c12009-10-30 11:49:00 +00001342void Assembler::xor_(Register dst, int32_t imm32) {
1343 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001344 emit_arith(6, Operand(dst), Immediate(imm32));
1345}
1346
1347
1348void Assembler::xor_(Register dst, const Operand& src) {
1349 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001350 EMIT(0x33);
1351 emit_operand(dst, src);
1352}
1353
1354
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001355void Assembler::xor_(const Operand& dst, Register src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001356 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001357 EMIT(0x31);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001358 emit_operand(src, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001359}
1360
1361
1362void Assembler::xor_(const Operand& dst, const Immediate& x) {
1363 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001364 emit_arith(6, dst, x);
1365}
1366
1367
1368void Assembler::bt(const Operand& dst, Register src) {
1369 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001370 EMIT(0x0F);
1371 EMIT(0xA3);
1372 emit_operand(src, dst);
1373}
1374
1375
1376void Assembler::bts(const Operand& dst, Register src) {
1377 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001378 EMIT(0x0F);
1379 EMIT(0xAB);
1380 emit_operand(src, dst);
1381}
1382
1383
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001384void Assembler::bsr(Register dst, const Operand& src) {
1385 EnsureSpace ensure_space(this);
1386 EMIT(0x0F);
1387 EMIT(0xBD);
1388 emit_operand(dst, src);
1389}
1390
1391
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001392void Assembler::bsf(Register dst, const Operand& src) {
1393 EnsureSpace ensure_space(this);
1394 EMIT(0x0F);
1395 EMIT(0xBC);
1396 emit_operand(dst, src);
1397}
1398
1399
Steve Blocka7e24c12009-10-30 11:49:00 +00001400void Assembler::hlt() {
1401 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001402 EMIT(0xF4);
1403}
1404
1405
1406void Assembler::int3() {
1407 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001408 EMIT(0xCC);
1409}
1410
1411
1412void Assembler::nop() {
1413 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001414 EMIT(0x90);
1415}
1416
1417
Steve Blocka7e24c12009-10-30 11:49:00 +00001418void Assembler::ret(int imm16) {
1419 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001420 DCHECK(is_uint16(imm16));
Steve Blocka7e24c12009-10-30 11:49:00 +00001421 if (imm16 == 0) {
1422 EMIT(0xC3);
1423 } else {
1424 EMIT(0xC2);
1425 EMIT(imm16 & 0xFF);
1426 EMIT((imm16 >> 8) & 0xFF);
1427 }
1428}
1429
1430
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001431void Assembler::ud2() {
1432 EnsureSpace ensure_space(this);
1433 EMIT(0x0F);
1434 EMIT(0x0B);
1435}
1436
1437
Steve Blocka7e24c12009-10-30 11:49:00 +00001438// Labels refer to positions in the (to be) generated code.
1439// There are bound, linked, and unused labels.
1440//
1441// Bound labels refer to known positions in the already
1442// generated code. pos() is the position the label refers to.
1443//
1444// Linked labels refer to unknown positions in the code
1445// to be generated; pos() is the position of the 32bit
1446// Displacement of the last instruction using the label.
1447
1448
1449void Assembler::print(Label* L) {
1450 if (L->is_unused()) {
1451 PrintF("unused label\n");
1452 } else if (L->is_bound()) {
1453 PrintF("bound label to %d\n", L->pos());
1454 } else if (L->is_linked()) {
1455 Label l = *L;
1456 PrintF("unbound label");
1457 while (l.is_linked()) {
1458 Displacement disp = disp_at(&l);
1459 PrintF("@ %d ", l.pos());
1460 disp.print();
1461 PrintF("\n");
1462 disp.next(&l);
1463 }
1464 } else {
1465 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
1466 }
1467}
1468
1469
1470void Assembler::bind_to(Label* L, int pos) {
1471 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001472 DCHECK(0 <= pos && pos <= pc_offset()); // must have a valid binding position
Steve Blocka7e24c12009-10-30 11:49:00 +00001473 while (L->is_linked()) {
1474 Displacement disp = disp_at(L);
1475 int fixup_pos = L->pos();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001476 if (disp.type() == Displacement::CODE_ABSOLUTE) {
1477 long_at_put(fixup_pos, reinterpret_cast<int>(buffer_ + pos));
1478 internal_reference_positions_.push_back(fixup_pos);
1479 } else if (disp.type() == Displacement::CODE_RELATIVE) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001480 // Relative to Code* heap object pointer.
1481 long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
1482 } else {
1483 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001484 DCHECK(byte_at(fixup_pos - 1) == 0xE9); // jmp expected
Steve Blocka7e24c12009-10-30 11:49:00 +00001485 }
Andrei Popescu31002712010-02-23 13:46:05 +00001486 // Relative address, relative to point after address.
Steve Blocka7e24c12009-10-30 11:49:00 +00001487 int imm32 = pos - (fixup_pos + sizeof(int32_t));
1488 long_at_put(fixup_pos, imm32);
1489 }
1490 disp.next(L);
1491 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001492 while (L->is_near_linked()) {
1493 int fixup_pos = L->near_link_pos();
1494 int offset_to_next =
1495 static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001496 DCHECK(offset_to_next <= 0);
Ben Murdoch257744e2011-11-30 15:57:28 +00001497 // Relative address, relative to point after address.
1498 int disp = pos - fixup_pos - sizeof(int8_t);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001499 CHECK(0 <= disp && disp <= 127);
Ben Murdoch257744e2011-11-30 15:57:28 +00001500 set_byte_at(fixup_pos, disp);
1501 if (offset_to_next < 0) {
1502 L->link_to(fixup_pos + offset_to_next, Label::kNear);
1503 } else {
1504 L->UnuseNear();
1505 }
1506 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001507 L->bind_to(pos);
1508}
1509
1510
Steve Blocka7e24c12009-10-30 11:49:00 +00001511void Assembler::bind(Label* L) {
1512 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001513 DCHECK(!L->is_bound()); // label can only be bound once
Steve Blocka7e24c12009-10-30 11:49:00 +00001514 bind_to(L, pc_offset());
1515}
1516
1517
1518void Assembler::call(Label* L) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001519 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001520 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001521 if (L->is_bound()) {
1522 const int long_size = 5;
1523 int offs = L->pos() - pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001524 DCHECK(offs <= 0);
Andrei Popescu31002712010-02-23 13:46:05 +00001525 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001526 EMIT(0xE8);
1527 emit(offs - long_size);
1528 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001529 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001530 EMIT(0xE8);
1531 emit_disp(L, Displacement::OTHER);
1532 }
1533}
1534
1535
1536void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001537 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001538 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001539 DCHECK(!RelocInfo::IsCodeTarget(rmode));
Steve Blocka7e24c12009-10-30 11:49:00 +00001540 EMIT(0xE8);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001541 if (RelocInfo::IsRuntimeEntry(rmode)) {
1542 emit(reinterpret_cast<uint32_t>(entry), rmode);
1543 } else {
1544 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1545 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001546}
1547
1548
Ben Murdoch257744e2011-11-30 15:57:28 +00001549int Assembler::CallSize(const Operand& adr) {
1550 // Call size is 1 (opcode) + adr.len_ (operand).
1551 return 1 + adr.len_;
1552}
1553
1554
Steve Blocka7e24c12009-10-30 11:49:00 +00001555void Assembler::call(const Operand& adr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001556 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001557 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001558 EMIT(0xFF);
1559 emit_operand(edx, adr);
1560}
1561
1562
Ben Murdoch257744e2011-11-30 15:57:28 +00001563int Assembler::CallSize(Handle<Code> code, RelocInfo::Mode rmode) {
1564 return 1 /* EMIT */ + sizeof(uint32_t) /* emit */;
Steve Blocka7e24c12009-10-30 11:49:00 +00001565}
1566
1567
Ben Murdoch257744e2011-11-30 15:57:28 +00001568void Assembler::call(Handle<Code> code,
1569 RelocInfo::Mode rmode,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001570 TypeFeedbackId ast_id) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001571 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001572 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001573 DCHECK(RelocInfo::IsCodeTarget(rmode)
1574 || rmode == RelocInfo::CODE_AGE_SEQUENCE);
Ben Murdoch257744e2011-11-30 15:57:28 +00001575 EMIT(0xE8);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001576 emit(code, rmode, ast_id);
Ben Murdoch257744e2011-11-30 15:57:28 +00001577}
1578
1579
1580void Assembler::jmp(Label* L, Label::Distance distance) {
1581 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001582 if (L->is_bound()) {
1583 const int short_size = 2;
1584 const int long_size = 5;
1585 int offs = L->pos() - pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001586 DCHECK(offs <= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001587 if (is_int8(offs - short_size)) {
Andrei Popescu31002712010-02-23 13:46:05 +00001588 // 1110 1011 #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001589 EMIT(0xEB);
1590 EMIT((offs - short_size) & 0xFF);
1591 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001592 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001593 EMIT(0xE9);
1594 emit(offs - long_size);
1595 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001596 } else if (distance == Label::kNear) {
1597 EMIT(0xEB);
1598 emit_near_disp(L);
Steve Blocka7e24c12009-10-30 11:49:00 +00001599 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001600 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001601 EMIT(0xE9);
1602 emit_disp(L, Displacement::UNCONDITIONAL_JUMP);
1603 }
1604}
1605
1606
1607void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
1608 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001609 DCHECK(!RelocInfo::IsCodeTarget(rmode));
Steve Blocka7e24c12009-10-30 11:49:00 +00001610 EMIT(0xE9);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001611 if (RelocInfo::IsRuntimeEntry(rmode)) {
1612 emit(reinterpret_cast<uint32_t>(entry), rmode);
1613 } else {
1614 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1615 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001616}
1617
1618
1619void Assembler::jmp(const Operand& adr) {
1620 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001621 EMIT(0xFF);
1622 emit_operand(esp, adr);
1623}
1624
1625
1626void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
1627 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001628 DCHECK(RelocInfo::IsCodeTarget(rmode));
Steve Blocka7e24c12009-10-30 11:49:00 +00001629 EMIT(0xE9);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001630 emit(code, rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001631}
1632
1633
Ben Murdoch257744e2011-11-30 15:57:28 +00001634void Assembler::j(Condition cc, Label* L, Label::Distance distance) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001635 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001636 DCHECK(0 <= cc && static_cast<int>(cc) < 16);
Steve Blocka7e24c12009-10-30 11:49:00 +00001637 if (L->is_bound()) {
1638 const int short_size = 2;
1639 const int long_size = 6;
1640 int offs = L->pos() - pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001641 DCHECK(offs <= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001642 if (is_int8(offs - short_size)) {
1643 // 0111 tttn #8-bit disp
1644 EMIT(0x70 | cc);
1645 EMIT((offs - short_size) & 0xFF);
1646 } else {
1647 // 0000 1111 1000 tttn #32-bit disp
1648 EMIT(0x0F);
1649 EMIT(0x80 | cc);
1650 emit(offs - long_size);
1651 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001652 } else if (distance == Label::kNear) {
1653 EMIT(0x70 | cc);
1654 emit_near_disp(L);
Steve Blocka7e24c12009-10-30 11:49:00 +00001655 } else {
1656 // 0000 1111 1000 tttn #32-bit disp
1657 // Note: could eliminate cond. jumps to this jump if condition
1658 // is the same however, seems to be rather unlikely case.
1659 EMIT(0x0F);
1660 EMIT(0x80 | cc);
1661 emit_disp(L, Displacement::OTHER);
1662 }
1663}
1664
1665
Ben Murdoch257744e2011-11-30 15:57:28 +00001666void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001667 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001668 DCHECK((0 <= cc) && (static_cast<int>(cc) < 16));
Andrei Popescu31002712010-02-23 13:46:05 +00001669 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001670 EMIT(0x0F);
1671 EMIT(0x80 | cc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001672 if (RelocInfo::IsRuntimeEntry(rmode)) {
1673 emit(reinterpret_cast<uint32_t>(entry), rmode);
1674 } else {
1675 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1676 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001677}
1678
1679
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001680void Assembler::j(Condition cc, Handle<Code> code, RelocInfo::Mode rmode) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001681 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001682 // 0000 1111 1000 tttn #32-bit disp
1683 EMIT(0x0F);
1684 EMIT(0x80 | cc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001685 emit(code, rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001686}
1687
1688
Andrei Popescu31002712010-02-23 13:46:05 +00001689// FPU instructions.
Steve Blocka7e24c12009-10-30 11:49:00 +00001690
Steve Blocka7e24c12009-10-30 11:49:00 +00001691void Assembler::fld(int i) {
1692 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001693 emit_farith(0xD9, 0xC0, i);
1694}
1695
1696
Andrei Popescu402d9372010-02-26 13:31:12 +00001697void Assembler::fstp(int i) {
1698 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00001699 emit_farith(0xDD, 0xD8, i);
1700}
1701
1702
Steve Blocka7e24c12009-10-30 11:49:00 +00001703void Assembler::fld1() {
1704 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001705 EMIT(0xD9);
1706 EMIT(0xE8);
1707}
1708
1709
Andrei Popescu402d9372010-02-26 13:31:12 +00001710void Assembler::fldpi() {
1711 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00001712 EMIT(0xD9);
1713 EMIT(0xEB);
1714}
1715
1716
Steve Blocka7e24c12009-10-30 11:49:00 +00001717void Assembler::fldz() {
1718 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001719 EMIT(0xD9);
1720 EMIT(0xEE);
1721}
1722
1723
Ben Murdochb0fe1622011-05-05 13:52:32 +01001724void Assembler::fldln2() {
1725 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001726 EMIT(0xD9);
1727 EMIT(0xED);
1728}
1729
1730
Steve Blocka7e24c12009-10-30 11:49:00 +00001731void Assembler::fld_s(const Operand& adr) {
1732 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001733 EMIT(0xD9);
1734 emit_operand(eax, adr);
1735}
1736
1737
1738void Assembler::fld_d(const Operand& adr) {
1739 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001740 EMIT(0xDD);
1741 emit_operand(eax, adr);
1742}
1743
1744
1745void Assembler::fstp_s(const Operand& adr) {
1746 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001747 EMIT(0xD9);
1748 emit_operand(ebx, adr);
1749}
1750
1751
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001752void Assembler::fst_s(const Operand& adr) {
1753 EnsureSpace ensure_space(this);
1754 EMIT(0xD9);
1755 emit_operand(edx, adr);
1756}
1757
1758
Steve Blocka7e24c12009-10-30 11:49:00 +00001759void Assembler::fstp_d(const Operand& adr) {
1760 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001761 EMIT(0xDD);
1762 emit_operand(ebx, adr);
1763}
1764
1765
Andrei Popescu402d9372010-02-26 13:31:12 +00001766void Assembler::fst_d(const Operand& adr) {
1767 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00001768 EMIT(0xDD);
1769 emit_operand(edx, adr);
1770}
1771
1772
Steve Blocka7e24c12009-10-30 11:49:00 +00001773void Assembler::fild_s(const Operand& adr) {
1774 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001775 EMIT(0xDB);
1776 emit_operand(eax, adr);
1777}
1778
1779
1780void Assembler::fild_d(const Operand& adr) {
1781 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001782 EMIT(0xDF);
1783 emit_operand(ebp, adr);
1784}
1785
1786
1787void Assembler::fistp_s(const Operand& adr) {
1788 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001789 EMIT(0xDB);
1790 emit_operand(ebx, adr);
1791}
1792
1793
1794void Assembler::fisttp_s(const Operand& adr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001795 DCHECK(IsEnabled(SSE3));
Steve Blocka7e24c12009-10-30 11:49:00 +00001796 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001797 EMIT(0xDB);
1798 emit_operand(ecx, adr);
1799}
1800
1801
Leon Clarkee46be812010-01-19 14:06:41 +00001802void Assembler::fisttp_d(const Operand& adr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001803 DCHECK(IsEnabled(SSE3));
Leon Clarkee46be812010-01-19 14:06:41 +00001804 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00001805 EMIT(0xDD);
1806 emit_operand(ecx, adr);
1807}
1808
1809
Steve Blocka7e24c12009-10-30 11:49:00 +00001810void Assembler::fist_s(const Operand& adr) {
1811 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001812 EMIT(0xDB);
1813 emit_operand(edx, adr);
1814}
1815
1816
1817void Assembler::fistp_d(const Operand& adr) {
1818 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001819 EMIT(0xDF);
1820 emit_operand(edi, adr);
1821}
1822
1823
1824void Assembler::fabs() {
1825 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001826 EMIT(0xD9);
1827 EMIT(0xE1);
1828}
1829
1830
1831void Assembler::fchs() {
1832 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001833 EMIT(0xD9);
1834 EMIT(0xE0);
1835}
1836
1837
1838void Assembler::fcos() {
1839 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001840 EMIT(0xD9);
1841 EMIT(0xFF);
1842}
1843
1844
1845void Assembler::fsin() {
1846 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001847 EMIT(0xD9);
1848 EMIT(0xFE);
1849}
1850
1851
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001852void Assembler::fptan() {
1853 EnsureSpace ensure_space(this);
1854 EMIT(0xD9);
1855 EMIT(0xF2);
1856}
1857
1858
Ben Murdochb0fe1622011-05-05 13:52:32 +01001859void Assembler::fyl2x() {
1860 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001861 EMIT(0xD9);
1862 EMIT(0xF1);
1863}
1864
1865
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001866void Assembler::f2xm1() {
1867 EnsureSpace ensure_space(this);
1868 EMIT(0xD9);
1869 EMIT(0xF0);
1870}
1871
1872
1873void Assembler::fscale() {
1874 EnsureSpace ensure_space(this);
1875 EMIT(0xD9);
1876 EMIT(0xFD);
1877}
1878
1879
1880void Assembler::fninit() {
1881 EnsureSpace ensure_space(this);
1882 EMIT(0xDB);
1883 EMIT(0xE3);
1884}
1885
1886
Steve Blocka7e24c12009-10-30 11:49:00 +00001887void Assembler::fadd(int i) {
1888 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001889 emit_farith(0xDC, 0xC0, i);
1890}
1891
1892
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001893void Assembler::fadd_i(int i) {
1894 EnsureSpace ensure_space(this);
1895 emit_farith(0xD8, 0xC0, i);
1896}
1897
1898
Steve Blocka7e24c12009-10-30 11:49:00 +00001899void Assembler::fsub(int i) {
1900 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001901 emit_farith(0xDC, 0xE8, i);
1902}
1903
1904
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001905void Assembler::fsub_i(int i) {
1906 EnsureSpace ensure_space(this);
1907 emit_farith(0xD8, 0xE0, i);
1908}
1909
1910
Steve Blocka7e24c12009-10-30 11:49:00 +00001911void Assembler::fisub_s(const Operand& adr) {
1912 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001913 EMIT(0xDA);
1914 emit_operand(esp, adr);
1915}
1916
1917
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001918void Assembler::fmul_i(int i) {
1919 EnsureSpace ensure_space(this);
1920 emit_farith(0xD8, 0xC8, i);
1921}
1922
1923
Steve Blocka7e24c12009-10-30 11:49:00 +00001924void Assembler::fmul(int i) {
1925 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001926 emit_farith(0xDC, 0xC8, i);
1927}
1928
1929
1930void Assembler::fdiv(int i) {
1931 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001932 emit_farith(0xDC, 0xF8, i);
1933}
1934
1935
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001936void Assembler::fdiv_i(int i) {
1937 EnsureSpace ensure_space(this);
1938 emit_farith(0xD8, 0xF0, i);
1939}
1940
1941
Steve Blocka7e24c12009-10-30 11:49:00 +00001942void Assembler::faddp(int i) {
1943 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001944 emit_farith(0xDE, 0xC0, i);
1945}
1946
1947
1948void Assembler::fsubp(int i) {
1949 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001950 emit_farith(0xDE, 0xE8, i);
1951}
1952
1953
1954void Assembler::fsubrp(int i) {
1955 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001956 emit_farith(0xDE, 0xE0, i);
1957}
1958
1959
1960void Assembler::fmulp(int i) {
1961 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001962 emit_farith(0xDE, 0xC8, i);
1963}
1964
1965
1966void Assembler::fdivp(int i) {
1967 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001968 emit_farith(0xDE, 0xF8, i);
1969}
1970
1971
1972void Assembler::fprem() {
1973 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001974 EMIT(0xD9);
1975 EMIT(0xF8);
1976}
1977
1978
1979void Assembler::fprem1() {
1980 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001981 EMIT(0xD9);
1982 EMIT(0xF5);
1983}
1984
1985
1986void Assembler::fxch(int i) {
1987 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001988 emit_farith(0xD9, 0xC8, i);
1989}
1990
1991
1992void Assembler::fincstp() {
1993 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001994 EMIT(0xD9);
1995 EMIT(0xF7);
1996}
1997
1998
1999void Assembler::ffree(int i) {
2000 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002001 emit_farith(0xDD, 0xC0, i);
2002}
2003
2004
2005void Assembler::ftst() {
2006 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002007 EMIT(0xD9);
2008 EMIT(0xE4);
2009}
2010
2011
2012void Assembler::fucomp(int i) {
2013 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002014 emit_farith(0xDD, 0xE8, i);
2015}
2016
2017
2018void Assembler::fucompp() {
2019 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002020 EMIT(0xDA);
2021 EMIT(0xE9);
2022}
2023
2024
Steve Block3ce2e202009-11-05 08:53:23 +00002025void Assembler::fucomi(int i) {
2026 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00002027 EMIT(0xDB);
2028 EMIT(0xE8 + i);
2029}
2030
2031
2032void Assembler::fucomip() {
2033 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00002034 EMIT(0xDF);
2035 EMIT(0xE9);
2036}
2037
2038
Steve Blocka7e24c12009-10-30 11:49:00 +00002039void Assembler::fcompp() {
2040 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002041 EMIT(0xDE);
2042 EMIT(0xD9);
2043}
2044
2045
2046void Assembler::fnstsw_ax() {
2047 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002048 EMIT(0xDF);
2049 EMIT(0xE0);
2050}
2051
2052
2053void Assembler::fwait() {
2054 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002055 EMIT(0x9B);
2056}
2057
2058
2059void Assembler::frndint() {
2060 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002061 EMIT(0xD9);
2062 EMIT(0xFC);
2063}
2064
2065
2066void Assembler::fnclex() {
2067 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002068 EMIT(0xDB);
2069 EMIT(0xE2);
2070}
2071
2072
2073void Assembler::sahf() {
2074 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002075 EMIT(0x9E);
2076}
2077
2078
2079void Assembler::setcc(Condition cc, Register reg) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002080 DCHECK(reg.is_byte_register());
Steve Blocka7e24c12009-10-30 11:49:00 +00002081 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002082 EMIT(0x0F);
2083 EMIT(0x90 | cc);
2084 EMIT(0xC0 | reg.code());
2085}
2086
2087
2088void Assembler::cvttss2si(Register dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002089 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002090 EMIT(0xF3);
2091 EMIT(0x0F);
2092 EMIT(0x2C);
2093 emit_operand(dst, src);
2094}
2095
2096
2097void Assembler::cvttsd2si(Register dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002098 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002099 EMIT(0xF2);
2100 EMIT(0x0F);
2101 EMIT(0x2C);
2102 emit_operand(dst, src);
2103}
2104
2105
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002106void Assembler::cvtsd2si(Register dst, XMMRegister src) {
2107 EnsureSpace ensure_space(this);
2108 EMIT(0xF2);
2109 EMIT(0x0F);
2110 EMIT(0x2D);
2111 emit_sse_operand(dst, src);
2112}
2113
2114
Ben Murdoch097c5b22016-05-18 11:27:45 +01002115void Assembler::cvtsi2ss(XMMRegister dst, const Operand& src) {
2116 EnsureSpace ensure_space(this);
2117 EMIT(0xF3);
2118 EMIT(0x0F);
2119 EMIT(0x2A);
2120 emit_sse_operand(dst, src);
2121}
2122
2123
Steve Blocka7e24c12009-10-30 11:49:00 +00002124void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002125 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002126 EMIT(0xF2);
2127 EMIT(0x0F);
2128 EMIT(0x2A);
2129 emit_sse_operand(dst, src);
2130}
2131
2132
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002133void Assembler::cvtss2sd(XMMRegister dst, const Operand& src) {
Steve Block6ded16b2010-05-10 14:33:55 +01002134 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002135 EMIT(0xF3);
2136 EMIT(0x0F);
2137 EMIT(0x5A);
2138 emit_sse_operand(dst, src);
2139}
2140
2141
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002142void Assembler::cvtsd2ss(XMMRegister dst, const Operand& src) {
Steve Block44f0eee2011-05-26 01:26:41 +01002143 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +01002144 EMIT(0xF2);
2145 EMIT(0x0F);
2146 EMIT(0x5A);
2147 emit_sse_operand(dst, src);
2148}
2149
2150
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002151void Assembler::addsd(XMMRegister dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002152 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002153 EMIT(0xF2);
2154 EMIT(0x0F);
2155 EMIT(0x58);
2156 emit_sse_operand(dst, src);
2157}
2158
2159
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002160void Assembler::mulsd(XMMRegister dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002161 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002162 EMIT(0xF2);
2163 EMIT(0x0F);
2164 EMIT(0x59);
2165 emit_sse_operand(dst, src);
2166}
2167
2168
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002169void Assembler::subsd(XMMRegister dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002170 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002171 EMIT(0xF2);
2172 EMIT(0x0F);
2173 EMIT(0x5C);
2174 emit_sse_operand(dst, src);
2175}
2176
2177
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002178void Assembler::divsd(XMMRegister dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002179 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002180 EMIT(0xF2);
2181 EMIT(0x0F);
2182 EMIT(0x5E);
2183 emit_sse_operand(dst, src);
2184}
2185
2186
Leon Clarkee46be812010-01-19 14:06:41 +00002187void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
Leon Clarkee46be812010-01-19 14:06:41 +00002188 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002189 EMIT(0x66);
2190 EMIT(0x0F);
2191 EMIT(0x57);
2192 emit_sse_operand(dst, src);
2193}
2194
2195
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002196void Assembler::andps(XMMRegister dst, const Operand& src) {
2197 EnsureSpace ensure_space(this);
2198 EMIT(0x0F);
2199 EMIT(0x54);
2200 emit_sse_operand(dst, src);
2201}
2202
2203
2204void Assembler::orps(XMMRegister dst, const Operand& src) {
2205 EnsureSpace ensure_space(this);
2206 EMIT(0x0F);
2207 EMIT(0x56);
2208 emit_sse_operand(dst, src);
2209}
2210
2211
2212void Assembler::xorps(XMMRegister dst, const Operand& src) {
Ben Murdoch257744e2011-11-30 15:57:28 +00002213 EnsureSpace ensure_space(this);
2214 EMIT(0x0F);
2215 EMIT(0x57);
2216 emit_sse_operand(dst, src);
2217}
2218
2219
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002220void Assembler::addps(XMMRegister dst, const Operand& src) {
2221 EnsureSpace ensure_space(this);
2222 EMIT(0x0F);
2223 EMIT(0x58);
2224 emit_sse_operand(dst, src);
2225}
2226
2227
2228void Assembler::subps(XMMRegister dst, const Operand& src) {
2229 EnsureSpace ensure_space(this);
2230 EMIT(0x0F);
2231 EMIT(0x5C);
2232 emit_sse_operand(dst, src);
2233}
2234
2235
2236void Assembler::mulps(XMMRegister dst, const Operand& src) {
2237 EnsureSpace ensure_space(this);
2238 EMIT(0x0F);
2239 EMIT(0x59);
2240 emit_sse_operand(dst, src);
2241}
2242
2243
2244void Assembler::divps(XMMRegister dst, const Operand& src) {
2245 EnsureSpace ensure_space(this);
2246 EMIT(0x0F);
2247 EMIT(0x5E);
2248 emit_sse_operand(dst, src);
2249}
2250
2251
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002252void Assembler::sqrtsd(XMMRegister dst, const Operand& src) {
2253 EnsureSpace ensure_space(this);
2254 EMIT(0xF2);
2255 EMIT(0x0F);
2256 EMIT(0x51);
2257 emit_sse_operand(dst, src);
2258}
2259
2260
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002261void Assembler::andpd(XMMRegister dst, XMMRegister src) {
2262 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002263 EMIT(0x66);
2264 EMIT(0x0F);
2265 EMIT(0x54);
2266 emit_sse_operand(dst, src);
2267}
2268
2269
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002270void Assembler::orpd(XMMRegister dst, XMMRegister src) {
Steve Block6ded16b2010-05-10 14:33:55 +01002271 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002272 EMIT(0x66);
2273 EMIT(0x0F);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002274 EMIT(0x56);
Steve Block6ded16b2010-05-10 14:33:55 +01002275 emit_sse_operand(dst, src);
2276}
2277
2278
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002279void Assembler::ucomisd(XMMRegister dst, const Operand& src) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002280 EnsureSpace ensure_space(this);
2281 EMIT(0x66);
2282 EMIT(0x0F);
2283 EMIT(0x2E);
2284 emit_sse_operand(dst, src);
2285}
2286
2287
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002288void Assembler::roundss(XMMRegister dst, XMMRegister src, RoundingMode mode) {
2289 DCHECK(IsEnabled(SSE4_1));
2290 EnsureSpace ensure_space(this);
2291 EMIT(0x66);
2292 EMIT(0x0F);
2293 EMIT(0x3A);
2294 EMIT(0x0A);
2295 emit_sse_operand(dst, src);
2296 // Mask precision exeption.
2297 EMIT(static_cast<byte>(mode) | 0x8);
2298}
2299
2300
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002301void Assembler::roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002302 DCHECK(IsEnabled(SSE4_1));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002303 EnsureSpace ensure_space(this);
2304 EMIT(0x66);
2305 EMIT(0x0F);
2306 EMIT(0x3A);
2307 EMIT(0x0B);
2308 emit_sse_operand(dst, src);
2309 // Mask precision exeption.
2310 EMIT(static_cast<byte>(mode) | 0x8);
2311}
2312
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002313
Steve Block6ded16b2010-05-10 14:33:55 +01002314void Assembler::movmskpd(Register dst, XMMRegister src) {
Steve Block6ded16b2010-05-10 14:33:55 +01002315 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002316 EMIT(0x66);
2317 EMIT(0x0F);
2318 EMIT(0x50);
2319 emit_sse_operand(dst, src);
2320}
2321
2322
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002323void Assembler::movmskps(Register dst, XMMRegister src) {
2324 EnsureSpace ensure_space(this);
2325 EMIT(0x0F);
2326 EMIT(0x50);
2327 emit_sse_operand(dst, src);
2328}
2329
2330
2331void Assembler::pcmpeqd(XMMRegister dst, XMMRegister src) {
2332 EnsureSpace ensure_space(this);
2333 EMIT(0x66);
2334 EMIT(0x0F);
2335 EMIT(0x76);
2336 emit_sse_operand(dst, src);
2337}
2338
2339
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002340void Assembler::punpckldq(XMMRegister dst, XMMRegister src) {
2341 EnsureSpace ensure_space(this);
2342 EMIT(0x66);
2343 EMIT(0x0F);
2344 EMIT(0x62);
2345 emit_sse_operand(dst, src);
2346}
2347
2348
2349void Assembler::punpckhdq(XMMRegister dst, XMMRegister src) {
2350 EnsureSpace ensure_space(this);
2351 EMIT(0x66);
2352 EMIT(0x0F);
2353 EMIT(0x6A);
2354 emit_sse_operand(dst, src);
2355}
2356
2357
2358void Assembler::maxsd(XMMRegister dst, const Operand& src) {
2359 EnsureSpace ensure_space(this);
2360 EMIT(0xF2);
2361 EMIT(0x0F);
2362 EMIT(0x5F);
2363 emit_sse_operand(dst, src);
2364}
2365
2366
2367void Assembler::minsd(XMMRegister dst, const Operand& src) {
2368 EnsureSpace ensure_space(this);
2369 EMIT(0xF2);
2370 EMIT(0x0F);
2371 EMIT(0x5D);
2372 emit_sse_operand(dst, src);
2373}
2374
2375
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002376void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002377 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002378 EMIT(0xF2);
2379 EMIT(0x0F);
2380 EMIT(0xC2);
2381 emit_sse_operand(dst, src);
2382 EMIT(1); // LT == 1
2383}
2384
2385
2386void Assembler::movaps(XMMRegister dst, XMMRegister src) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002387 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002388 EMIT(0x0F);
2389 EMIT(0x28);
2390 emit_sse_operand(dst, src);
2391}
2392
2393
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002394void Assembler::shufps(XMMRegister dst, XMMRegister src, byte imm8) {
2395 DCHECK(is_uint8(imm8));
2396 EnsureSpace ensure_space(this);
2397 EMIT(0x0F);
2398 EMIT(0xC6);
2399 emit_sse_operand(dst, src);
2400 EMIT(imm8);
2401}
2402
2403
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002404void Assembler::movdqa(const Operand& dst, XMMRegister src) {
Leon Clarkee46be812010-01-19 14:06:41 +00002405 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002406 EMIT(0x66);
2407 EMIT(0x0F);
2408 EMIT(0x7F);
2409 emit_sse_operand(src, dst);
2410}
2411
2412
2413void Assembler::movdqa(XMMRegister dst, const Operand& src) {
Leon Clarkee46be812010-01-19 14:06:41 +00002414 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002415 EMIT(0x66);
2416 EMIT(0x0F);
2417 EMIT(0x6F);
2418 emit_sse_operand(dst, src);
2419}
2420
2421
2422void Assembler::movdqu(const Operand& dst, XMMRegister src ) {
Leon Clarkee46be812010-01-19 14:06:41 +00002423 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002424 EMIT(0xF3);
2425 EMIT(0x0F);
2426 EMIT(0x7F);
2427 emit_sse_operand(src, dst);
2428}
2429
2430
2431void Assembler::movdqu(XMMRegister dst, const Operand& src) {
Leon Clarkee46be812010-01-19 14:06:41 +00002432 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002433 EMIT(0xF3);
2434 EMIT(0x0F);
2435 EMIT(0x6F);
2436 emit_sse_operand(dst, src);
2437}
2438
2439
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002440void Assembler::prefetch(const Operand& src, int level) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002441 DCHECK(is_uint2(level));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002442 EnsureSpace ensure_space(this);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002443 EMIT(0x0F);
2444 EMIT(0x18);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002445 // Emit hint number in Reg position of RegR/M.
2446 XMMRegister code = XMMRegister::from_code(level);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002447 emit_sse_operand(code, src);
2448}
2449
2450
Steve Blocka7e24c12009-10-30 11:49:00 +00002451void Assembler::movsd(const Operand& dst, XMMRegister src ) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002452 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002453 EMIT(0xF2); // double
2454 EMIT(0x0F);
2455 EMIT(0x11); // store
2456 emit_sse_operand(src, dst);
2457}
2458
2459
2460void Assembler::movsd(XMMRegister dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002461 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002462 EMIT(0xF2); // double
2463 EMIT(0x0F);
2464 EMIT(0x10); // load
2465 emit_sse_operand(dst, src);
2466}
2467
Ben Murdochb0fe1622011-05-05 13:52:32 +01002468
Steve Block44f0eee2011-05-26 01:26:41 +01002469void Assembler::movss(const Operand& dst, XMMRegister src ) {
Steve Block44f0eee2011-05-26 01:26:41 +01002470 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +01002471 EMIT(0xF3); // float
2472 EMIT(0x0F);
2473 EMIT(0x11); // store
2474 emit_sse_operand(src, dst);
2475}
2476
2477
2478void Assembler::movss(XMMRegister dst, const Operand& src) {
Steve Block44f0eee2011-05-26 01:26:41 +01002479 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +01002480 EMIT(0xF3); // float
2481 EMIT(0x0F);
2482 EMIT(0x10); // load
2483 emit_sse_operand(dst, src);
2484}
2485
2486
Steve Block6ded16b2010-05-10 14:33:55 +01002487void Assembler::movd(XMMRegister dst, const Operand& src) {
Steve Block6ded16b2010-05-10 14:33:55 +01002488 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002489 EMIT(0x66);
2490 EMIT(0x0F);
2491 EMIT(0x6E);
2492 emit_sse_operand(dst, src);
2493}
2494
2495
Ben Murdochb0fe1622011-05-05 13:52:32 +01002496void Assembler::movd(const Operand& dst, XMMRegister src) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002497 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002498 EMIT(0x66);
2499 EMIT(0x0F);
2500 EMIT(0x7E);
2501 emit_sse_operand(src, dst);
2502}
2503
2504
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002505void Assembler::extractps(Register dst, XMMRegister src, byte imm8) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002506 DCHECK(IsEnabled(SSE4_1));
2507 DCHECK(is_uint8(imm8));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002508 EnsureSpace ensure_space(this);
2509 EMIT(0x66);
2510 EMIT(0x0F);
2511 EMIT(0x3A);
2512 EMIT(0x17);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002513 emit_sse_operand(src, dst);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002514 EMIT(imm8);
2515}
2516
2517
Ben Murdochb0fe1622011-05-05 13:52:32 +01002518void Assembler::pand(XMMRegister dst, XMMRegister src) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002519 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002520 EMIT(0x66);
2521 EMIT(0x0F);
2522 EMIT(0xDB);
2523 emit_sse_operand(dst, src);
2524}
2525
2526
Steve Block6ded16b2010-05-10 14:33:55 +01002527void Assembler::pxor(XMMRegister dst, XMMRegister src) {
Steve Block6ded16b2010-05-10 14:33:55 +01002528 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002529 EMIT(0x66);
2530 EMIT(0x0F);
2531 EMIT(0xEF);
2532 emit_sse_operand(dst, src);
2533}
2534
2535
Ben Murdochb8e0da22011-05-16 14:20:40 +01002536void Assembler::por(XMMRegister dst, XMMRegister src) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002537 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002538 EMIT(0x66);
2539 EMIT(0x0F);
2540 EMIT(0xEB);
2541 emit_sse_operand(dst, src);
2542}
2543
2544
Steve Block6ded16b2010-05-10 14:33:55 +01002545void Assembler::ptest(XMMRegister dst, XMMRegister src) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002546 DCHECK(IsEnabled(SSE4_1));
Steve Block6ded16b2010-05-10 14:33:55 +01002547 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002548 EMIT(0x66);
2549 EMIT(0x0F);
2550 EMIT(0x38);
2551 EMIT(0x17);
2552 emit_sse_operand(dst, src);
2553}
2554
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002555
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002556void Assembler::pslld(XMMRegister reg, int8_t shift) {
2557 EnsureSpace ensure_space(this);
2558 EMIT(0x66);
2559 EMIT(0x0F);
2560 EMIT(0x72);
2561 emit_sse_operand(esi, reg); // esi == 6
2562 EMIT(shift);
2563}
2564
2565
2566void Assembler::psrld(XMMRegister reg, int8_t shift) {
2567 EnsureSpace ensure_space(this);
2568 EMIT(0x66);
2569 EMIT(0x0F);
2570 EMIT(0x72);
2571 emit_sse_operand(edx, reg); // edx == 2
2572 EMIT(shift);
2573}
2574
2575
Ben Murdochb0fe1622011-05-05 13:52:32 +01002576void Assembler::psllq(XMMRegister reg, int8_t shift) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002577 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002578 EMIT(0x66);
2579 EMIT(0x0F);
2580 EMIT(0x73);
2581 emit_sse_operand(esi, reg); // esi == 6
Ben Murdochb0fe1622011-05-05 13:52:32 +01002582 EMIT(shift);
2583}
2584
2585
Ben Murdochb8e0da22011-05-16 14:20:40 +01002586void Assembler::psllq(XMMRegister dst, XMMRegister src) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002587 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002588 EMIT(0x66);
2589 EMIT(0x0F);
2590 EMIT(0xF3);
2591 emit_sse_operand(dst, src);
2592}
2593
2594
2595void Assembler::psrlq(XMMRegister reg, int8_t shift) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002596 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002597 EMIT(0x66);
2598 EMIT(0x0F);
2599 EMIT(0x73);
2600 emit_sse_operand(edx, reg); // edx == 2
2601 EMIT(shift);
2602}
2603
2604
2605void Assembler::psrlq(XMMRegister dst, XMMRegister src) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002606 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002607 EMIT(0x66);
2608 EMIT(0x0F);
2609 EMIT(0xD3);
2610 emit_sse_operand(dst, src);
2611}
2612
2613
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002614void Assembler::pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002615 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002616 EMIT(0x66);
2617 EMIT(0x0F);
2618 EMIT(0x70);
2619 emit_sse_operand(dst, src);
2620 EMIT(shuffle);
2621}
2622
2623
2624void Assembler::pextrd(const Operand& dst, XMMRegister src, int8_t offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002625 DCHECK(IsEnabled(SSE4_1));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002626 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002627 EMIT(0x66);
2628 EMIT(0x0F);
2629 EMIT(0x3A);
2630 EMIT(0x16);
2631 emit_sse_operand(src, dst);
2632 EMIT(offset);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002633}
2634
2635
Steve Block1e0659c2011-05-24 12:43:12 +01002636void Assembler::pinsrd(XMMRegister dst, const Operand& src, int8_t offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002637 DCHECK(IsEnabled(SSE4_1));
Steve Block1e0659c2011-05-24 12:43:12 +01002638 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002639 EMIT(0x66);
2640 EMIT(0x0F);
2641 EMIT(0x3A);
2642 EMIT(0x22);
2643 emit_sse_operand(dst, src);
2644 EMIT(offset);
2645}
2646
2647
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002648void Assembler::addss(XMMRegister dst, const Operand& src) {
2649 EnsureSpace ensure_space(this);
2650 EMIT(0xF3);
2651 EMIT(0x0F);
2652 EMIT(0x58);
2653 emit_sse_operand(dst, src);
2654}
2655
2656
2657void Assembler::subss(XMMRegister dst, const Operand& src) {
2658 EnsureSpace ensure_space(this);
2659 EMIT(0xF3);
2660 EMIT(0x0F);
2661 EMIT(0x5C);
2662 emit_sse_operand(dst, src);
2663}
2664
2665
2666void Assembler::mulss(XMMRegister dst, const Operand& src) {
2667 EnsureSpace ensure_space(this);
2668 EMIT(0xF3);
2669 EMIT(0x0F);
2670 EMIT(0x59);
2671 emit_sse_operand(dst, src);
2672}
2673
2674
2675void Assembler::divss(XMMRegister dst, const Operand& src) {
2676 EnsureSpace ensure_space(this);
2677 EMIT(0xF3);
2678 EMIT(0x0F);
2679 EMIT(0x5E);
2680 emit_sse_operand(dst, src);
2681}
2682
2683
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002684void Assembler::sqrtss(XMMRegister dst, const Operand& src) {
2685 EnsureSpace ensure_space(this);
2686 EMIT(0xF3);
2687 EMIT(0x0F);
2688 EMIT(0x51);
2689 emit_sse_operand(dst, src);
2690}
2691
2692
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002693void Assembler::ucomiss(XMMRegister dst, const Operand& src) {
2694 EnsureSpace ensure_space(this);
2695 EMIT(0x0f);
2696 EMIT(0x2e);
2697 emit_sse_operand(dst, src);
2698}
2699
2700
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002701void Assembler::maxss(XMMRegister dst, const Operand& src) {
2702 EnsureSpace ensure_space(this);
2703 EMIT(0xF3);
2704 EMIT(0x0F);
2705 EMIT(0x5F);
2706 emit_sse_operand(dst, src);
2707}
2708
2709
2710void Assembler::minss(XMMRegister dst, const Operand& src) {
2711 EnsureSpace ensure_space(this);
2712 EMIT(0xF3);
2713 EMIT(0x0F);
2714 EMIT(0x5D);
2715 emit_sse_operand(dst, src);
2716}
2717
2718
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002719// AVX instructions
2720void Assembler::vfmasd(byte op, XMMRegister dst, XMMRegister src1,
2721 const Operand& src2) {
2722 DCHECK(IsEnabled(FMA3));
2723 EnsureSpace ensure_space(this);
2724 emit_vex_prefix(src1, kLIG, k66, k0F38, kW1);
2725 EMIT(op);
2726 emit_sse_operand(dst, src2);
2727}
2728
2729
2730void Assembler::vfmass(byte op, XMMRegister dst, XMMRegister src1,
2731 const Operand& src2) {
2732 DCHECK(IsEnabled(FMA3));
2733 EnsureSpace ensure_space(this);
2734 emit_vex_prefix(src1, kLIG, k66, k0F38, kW0);
2735 EMIT(op);
2736 emit_sse_operand(dst, src2);
2737}
2738
2739
2740void Assembler::vsd(byte op, XMMRegister dst, XMMRegister src1,
2741 const Operand& src2) {
2742 DCHECK(IsEnabled(AVX));
2743 EnsureSpace ensure_space(this);
2744 emit_vex_prefix(src1, kLIG, kF2, k0F, kWIG);
2745 EMIT(op);
2746 emit_sse_operand(dst, src2);
2747}
2748
2749
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002750void Assembler::vss(byte op, XMMRegister dst, XMMRegister src1,
2751 const Operand& src2) {
2752 DCHECK(IsEnabled(AVX));
2753 EnsureSpace ensure_space(this);
2754 emit_vex_prefix(src1, kLIG, kF3, k0F, kWIG);
2755 EMIT(op);
2756 emit_sse_operand(dst, src2);
2757}
2758
2759
2760void Assembler::vps(byte op, XMMRegister dst, XMMRegister src1,
2761 const Operand& src2) {
2762 DCHECK(IsEnabled(AVX));
2763 EnsureSpace ensure_space(this);
2764 emit_vex_prefix(src1, kL128, kNone, k0F, kWIG);
2765 EMIT(op);
2766 emit_sse_operand(dst, src2);
2767}
2768
2769
2770void Assembler::vpd(byte op, XMMRegister dst, XMMRegister src1,
2771 const Operand& src2) {
2772 DCHECK(IsEnabled(AVX));
2773 EnsureSpace ensure_space(this);
2774 emit_vex_prefix(src1, kL128, k66, k0F, kWIG);
2775 EMIT(op);
2776 emit_sse_operand(dst, src2);
2777}
2778
2779
2780void Assembler::bmi1(byte op, Register reg, Register vreg, const Operand& rm) {
2781 DCHECK(IsEnabled(BMI1));
2782 EnsureSpace ensure_space(this);
2783 emit_vex_prefix(vreg, kLZ, kNone, k0F38, kW0);
2784 EMIT(op);
2785 emit_operand(reg, rm);
2786}
2787
2788
2789void Assembler::tzcnt(Register dst, const Operand& src) {
2790 DCHECK(IsEnabled(BMI1));
2791 EnsureSpace ensure_space(this);
2792 EMIT(0xF3);
2793 EMIT(0x0F);
2794 EMIT(0xBC);
2795 emit_operand(dst, src);
2796}
2797
2798
2799void Assembler::lzcnt(Register dst, const Operand& src) {
2800 DCHECK(IsEnabled(LZCNT));
2801 EnsureSpace ensure_space(this);
2802 EMIT(0xF3);
2803 EMIT(0x0F);
2804 EMIT(0xBD);
2805 emit_operand(dst, src);
2806}
2807
2808
2809void Assembler::popcnt(Register dst, const Operand& src) {
2810 DCHECK(IsEnabled(POPCNT));
2811 EnsureSpace ensure_space(this);
2812 EMIT(0xF3);
2813 EMIT(0x0F);
2814 EMIT(0xB8);
2815 emit_operand(dst, src);
2816}
2817
2818
2819void Assembler::bmi2(SIMDPrefix pp, byte op, Register reg, Register vreg,
2820 const Operand& rm) {
2821 DCHECK(IsEnabled(BMI2));
2822 EnsureSpace ensure_space(this);
2823 emit_vex_prefix(vreg, kLZ, pp, k0F38, kW0);
2824 EMIT(op);
2825 emit_operand(reg, rm);
2826}
2827
2828
2829void Assembler::rorx(Register dst, const Operand& src, byte imm8) {
2830 DCHECK(IsEnabled(BMI2));
2831 DCHECK(is_uint8(imm8));
2832 Register vreg = {0}; // VEX.vvvv unused
2833 EnsureSpace ensure_space(this);
2834 emit_vex_prefix(vreg, kLZ, kF2, k0F3A, kW0);
2835 EMIT(0xF0);
2836 emit_operand(dst, src);
2837 EMIT(imm8);
2838}
2839
2840
Steve Blocka7e24c12009-10-30 11:49:00 +00002841void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
2842 Register ireg = { reg.code() };
2843 emit_operand(ireg, adr);
2844}
2845
2846
2847void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
2848 EMIT(0xC0 | dst.code() << 3 | src.code());
2849}
2850
2851
Steve Block6ded16b2010-05-10 14:33:55 +01002852void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
2853 EMIT(0xC0 | dst.code() << 3 | src.code());
2854}
2855
2856
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002857void Assembler::emit_sse_operand(XMMRegister dst, Register src) {
2858 EMIT(0xC0 | (dst.code() << 3) | src.code());
2859}
2860
2861
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002862void Assembler::emit_vex_prefix(XMMRegister vreg, VectorLength l, SIMDPrefix pp,
2863 LeadingOpcode mm, VexW w) {
2864 if (mm != k0F || w != kW0) {
2865 EMIT(0xc4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002866 // Change RXB from "110" to "111" to align with gdb disassembler.
2867 EMIT(0xe0 | mm);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002868 EMIT(w | ((~vreg.code() & 0xf) << 3) | l | pp);
2869 } else {
2870 EMIT(0xc5);
2871 EMIT(((~vreg.code()) << 3) | l | pp);
2872 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002873}
2874
2875
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002876void Assembler::emit_vex_prefix(Register vreg, VectorLength l, SIMDPrefix pp,
2877 LeadingOpcode mm, VexW w) {
2878 XMMRegister ivreg = {vreg.code()};
2879 emit_vex_prefix(ivreg, l, pp, mm, w);
Steve Blocka7e24c12009-10-30 11:49:00 +00002880}
2881
2882
Steve Blocka7e24c12009-10-30 11:49:00 +00002883void Assembler::GrowBuffer() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002884 DCHECK(buffer_overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +00002885 if (!own_buffer_) FATAL("external code buffer is too small");
2886
Andrei Popescu31002712010-02-23 13:46:05 +00002887 // Compute new buffer size.
Steve Blocka7e24c12009-10-30 11:49:00 +00002888 CodeDesc desc; // the new buffer
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002889 desc.buffer_size = 2 * buffer_size_;
2890
Steve Blocka7e24c12009-10-30 11:49:00 +00002891 // Some internal data structures overflow for very large buffers,
2892 // they must ensure that kMaximalBufferSize is not too large.
2893 if ((desc.buffer_size > kMaximalBufferSize) ||
Steve Block44f0eee2011-05-26 01:26:41 +01002894 (desc.buffer_size > isolate()->heap()->MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002895 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
2896 }
2897
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002898 // Set up new buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +00002899 desc.buffer = NewArray<byte>(desc.buffer_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002900 desc.origin = this;
Steve Blocka7e24c12009-10-30 11:49:00 +00002901 desc.instr_size = pc_offset();
2902 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
2903
2904 // Clear the buffer in debug mode. Use 'int3' instructions to make
2905 // sure to get into problems if we ever run uninitialized code.
2906#ifdef DEBUG
2907 memset(desc.buffer, 0xCC, desc.buffer_size);
2908#endif
2909
Andrei Popescu31002712010-02-23 13:46:05 +00002910 // Copy the data.
Steve Blocka7e24c12009-10-30 11:49:00 +00002911 int pc_delta = desc.buffer - buffer_;
2912 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002913 MemMove(desc.buffer, buffer_, desc.instr_size);
2914 MemMove(rc_delta + reloc_info_writer.pos(), reloc_info_writer.pos(),
2915 desc.reloc_size);
Steve Blocka7e24c12009-10-30 11:49:00 +00002916
Andrei Popescu31002712010-02-23 13:46:05 +00002917 // Switch buffers.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002918 DeleteArray(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +00002919 buffer_ = desc.buffer;
2920 buffer_size_ = desc.buffer_size;
2921 pc_ += pc_delta;
Steve Blocka7e24c12009-10-30 11:49:00 +00002922 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2923 reloc_info_writer.last_pc() + pc_delta);
2924
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002925 // Relocate internal references.
2926 for (auto pos : internal_reference_positions_) {
2927 int32_t* p = reinterpret_cast<int32_t*>(buffer_ + pos);
2928 *p += pc_delta;
Steve Blocka7e24c12009-10-30 11:49:00 +00002929 }
2930
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002931 DCHECK(!buffer_overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +00002932}
2933
2934
2935void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002936 DCHECK(is_uint8(op1) && is_uint8(op2)); // wrong opcode
2937 DCHECK(is_uint8(imm8));
2938 DCHECK((op1 & 0x01) == 0); // should be 8bit operation
Steve Blocka7e24c12009-10-30 11:49:00 +00002939 EMIT(op1);
2940 EMIT(op2 | dst.code());
2941 EMIT(imm8);
2942}
2943
2944
2945void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002946 DCHECK((0 <= sel) && (sel <= 7));
Steve Blocka7e24c12009-10-30 11:49:00 +00002947 Register ireg = { sel };
2948 if (x.is_int8()) {
2949 EMIT(0x83); // using a sign-extended 8-bit immediate.
2950 emit_operand(ireg, dst);
2951 EMIT(x.x_ & 0xFF);
2952 } else if (dst.is_reg(eax)) {
2953 EMIT((sel << 3) | 0x05); // short form if the destination is eax.
2954 emit(x);
2955 } else {
2956 EMIT(0x81); // using a literal 32-bit immediate.
2957 emit_operand(ireg, dst);
2958 emit(x);
2959 }
2960}
2961
2962
2963void Assembler::emit_operand(Register reg, const Operand& adr) {
2964 const unsigned length = adr.len_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002965 DCHECK(length > 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002966
2967 // Emit updated ModRM byte containing the given register.
2968 pc_[0] = (adr.buf_[0] & ~0x38) | (reg.code() << 3);
2969
2970 // Emit the rest of the encoded operand.
2971 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
2972 pc_ += length;
2973
2974 // Emit relocation information if necessary.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002975 if (length >= sizeof(int32_t) && !RelocInfo::IsNone(adr.rmode_)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002976 pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
2977 RecordRelocInfo(adr.rmode_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002978 if (adr.rmode_ == RelocInfo::INTERNAL_REFERENCE) { // Fixup for labels
2979 emit_label(*reinterpret_cast<Label**>(pc_));
2980 } else {
2981 pc_ += sizeof(int32_t);
2982 }
2983 }
2984}
2985
2986
2987void Assembler::emit_label(Label* label) {
2988 if (label->is_bound()) {
2989 internal_reference_positions_.push_back(pc_offset());
2990 emit(reinterpret_cast<uint32_t>(buffer_ + label->pos()));
2991 } else {
2992 emit_disp(label, Displacement::CODE_ABSOLUTE);
Steve Blocka7e24c12009-10-30 11:49:00 +00002993 }
2994}
2995
2996
2997void Assembler::emit_farith(int b1, int b2, int i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002998 DCHECK(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2999 DCHECK(0 <= i && i < 8); // illegal stack offset
Steve Blocka7e24c12009-10-30 11:49:00 +00003000 EMIT(b1);
3001 EMIT(b2 + i);
3002}
3003
3004
Ben Murdochb0fe1622011-05-05 13:52:32 +01003005void Assembler::db(uint8_t data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003006 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003007 EMIT(data);
3008}
3009
3010
3011void Assembler::dd(uint32_t data) {
3012 EnsureSpace ensure_space(this);
3013 emit(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003014}
3015
3016
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003017void Assembler::dq(uint64_t data) {
3018 EnsureSpace ensure_space(this);
3019 emit_q(data);
3020}
3021
3022
3023void Assembler::dd(Label* label) {
3024 EnsureSpace ensure_space(this);
3025 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
3026 emit_label(label);
3027}
3028
3029
Steve Blocka7e24c12009-10-30 11:49:00 +00003030void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003031 DCHECK(!RelocInfo::IsNone(rmode));
Steve Blocka7e24c12009-10-30 11:49:00 +00003032 // Don't record external references unless the heap will be serialized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003033 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
3034 !serializer_enabled() && !emit_debug_code()) {
3035 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00003036 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003037 RelocInfo rinfo(isolate(), pc_, rmode, data, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00003038 reloc_info_writer.Write(&rinfo);
3039}
3040
3041
3042#ifdef GENERATED_CODE_COVERAGE
3043static FILE* coverage_log = NULL;
3044
3045
3046static void InitCoverageLog() {
3047 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
3048 if (file_name != NULL) {
3049 coverage_log = fopen(file_name, "aw+");
3050 }
3051}
3052
3053
3054void LogGeneratedCodeCoverage(const char* file_line) {
3055 const char* return_address = (&file_line)[-1];
3056 char* push_insn = const_cast<char*>(return_address - 12);
3057 push_insn[0] = 0xeb; // Relative branch insn.
3058 push_insn[1] = 13; // Skip over coverage insns.
3059 if (coverage_log != NULL) {
3060 fprintf(coverage_log, "%s\n", file_line);
3061 fflush(coverage_log);
3062 }
3063}
3064
3065#endif
3066
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003067} // namespace internal
3068} // namespace v8
Leon Clarkef7060e22010-06-03 12:02:55 +01003069
3070#endif // V8_TARGET_ARCH_IA32