blob: 5f8fb6818eb89cf8dd8e79be4beaf051e1f57bbb [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005#include "src/x64/assembler-x64.h"
6
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include <cstring>
8
9#if V8_TARGET_ARCH_X64
10
11#if V8_LIBC_MSVCRT
12#include <intrin.h> // _xgetbv()
13#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -040014#if V8_OS_MACOSX
15#include <sys/sysctl.h>
16#endif
Steve Blocka7e24c12009-10-30 11:49:00 +000017
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018#include "src/base/bits.h"
19#include "src/macro-assembler.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020#include "src/v8.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000021
22namespace v8 {
23namespace internal {
24
25// -----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +000026// Implementation of CpuFeatures
27
Emily Bernierd0a1eb72015-03-24 16:35:39 -040028namespace {
29
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030#if !V8_LIBC_MSVCRT
31
32V8_INLINE uint64_t _xgetbv(unsigned int xcr) {
33 unsigned eax, edx;
34 // Check xgetbv; this uses a .byte sequence instead of the instruction
35 // directly because older assemblers do not include support for xgetbv and
36 // there is no easy way to conditionally compile based on the assembler
37 // used.
38 __asm__ volatile(".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(xcr));
39 return static_cast<uint64_t>(eax) | (static_cast<uint64_t>(edx) << 32);
40}
41
42#define _XCR_XFEATURE_ENABLED_MASK 0
43
44#endif // !V8_LIBC_MSVCRT
45
46
47bool OSHasAVXSupport() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040048#if V8_OS_MACOSX
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049 // Mac OS X up to 10.9 has a bug where AVX transitions were indeed being
50 // caused by ISRs, so we detect that here and disable AVX in that case.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040051 char buffer[128];
52 size_t buffer_size = arraysize(buffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053 int ctl_name[] = {CTL_KERN, KERN_OSRELEASE};
Emily Bernierd0a1eb72015-03-24 16:35:39 -040054 if (sysctl(ctl_name, 2, buffer, &buffer_size, nullptr, 0) != 0) {
55 V8_Fatal(__FILE__, __LINE__, "V8 failed to get kernel version");
56 }
57 // The buffer now contains a string of the form XX.YY.ZZ, where
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058 // XX is the major kernel version component.
59 char* period_pos = strchr(buffer, '.');
60 DCHECK_NOT_NULL(period_pos);
61 *period_pos = '\0';
62 long kernel_version_major = strtol(buffer, nullptr, 10); // NOLINT
63 if (kernel_version_major <= 13) return false;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040064#endif // V8_OS_MACOSX
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000065 // Check whether OS claims to support AVX.
66 uint64_t feature_mask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
67 return (feature_mask & 0x6) == 0x6;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040068}
69
70} // namespace
71
72
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073void CpuFeatures::ProbeImpl(bool cross_compile) {
74 base::CPU cpu;
75 CHECK(cpu.has_sse2()); // SSE2 support is mandatory.
76 CHECK(cpu.has_cmov()); // CMOV support is mandatory.
Ben Murdoch8b112d22011-06-08 16:22:53 +010077
Ben Murdochb8a8cc12014-11-26 15:28:44 +000078 // Only use statically determined features for cross compile (snapshot).
79 if (cross_compile) return;
Steve Block44f0eee2011-05-26 01:26:41 +010080
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081 if (cpu.has_sse41() && FLAG_enable_sse4_1) supported_ |= 1u << SSE4_1;
82 if (cpu.has_sse3() && FLAG_enable_sse3) supported_ |= 1u << SSE3;
83 // SAHF is not generally available in long mode.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040084 if (cpu.has_sahf() && FLAG_enable_sahf) supported_ |= 1u << SAHF;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000085 if (cpu.has_avx() && FLAG_enable_avx && cpu.has_osxsave() &&
86 OSHasAVXSupport()) {
87 supported_ |= 1u << AVX;
88 }
89 if (cpu.has_fma3() && FLAG_enable_fma3 && cpu.has_osxsave() &&
90 OSHasAVXSupport()) {
91 supported_ |= 1u << FMA3;
92 }
93 if (cpu.has_bmi1() && FLAG_enable_bmi1) supported_ |= 1u << BMI1;
94 if (cpu.has_bmi2() && FLAG_enable_bmi2) supported_ |= 1u << BMI2;
95 if (cpu.has_lzcnt() && FLAG_enable_lzcnt) supported_ |= 1u << LZCNT;
96 if (cpu.has_popcnt() && FLAG_enable_popcnt) supported_ |= 1u << POPCNT;
97 if (strcmp(FLAG_mcpu, "auto") == 0) {
98 if (cpu.is_atom()) supported_ |= 1u << ATOM;
99 } else if (strcmp(FLAG_mcpu, "atom") == 0) {
100 supported_ |= 1u << ATOM;
101 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000102}
103
104
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105void CpuFeatures::PrintTarget() { }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400106void CpuFeatures::PrintFeatures() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000107 printf(
108 "SSE3=%d SSE4_1=%d SAHF=%d AVX=%d FMA3=%d BMI1=%d BMI2=%d LZCNT=%d "
109 "POPCNT=%d ATOM=%d\n",
110 CpuFeatures::IsSupported(SSE3), CpuFeatures::IsSupported(SSE4_1),
111 CpuFeatures::IsSupported(SAHF), CpuFeatures::IsSupported(AVX),
112 CpuFeatures::IsSupported(FMA3), CpuFeatures::IsSupported(BMI1),
113 CpuFeatures::IsSupported(BMI2), CpuFeatures::IsSupported(LZCNT),
114 CpuFeatures::IsSupported(POPCNT), CpuFeatures::IsSupported(ATOM));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400115}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000116
Ben Murdochc5610432016-08-08 18:44:38 +0100117// -----------------------------------------------------------------------------
118// Implementation of RelocInfo
119
120Address RelocInfo::wasm_memory_reference() {
121 DCHECK(IsWasmMemoryReference(rmode_));
122 return Memory::Address_at(pc_);
123}
124
125uint32_t RelocInfo::wasm_memory_size_reference() {
126 DCHECK(IsWasmMemorySizeReference(rmode_));
127 return Memory::uint32_at(pc_);
128}
129
130void RelocInfo::update_wasm_memory_reference(
131 Address old_base, Address new_base, uint32_t old_size, uint32_t new_size,
132 ICacheFlushMode icache_flush_mode) {
133 DCHECK(IsWasmMemoryReference(rmode_) || IsWasmMemorySizeReference(rmode_));
134 if (IsWasmMemoryReference(rmode_)) {
135 Address updated_reference;
136 DCHECK(old_base <= wasm_memory_reference() &&
137 wasm_memory_reference() < old_base + old_size);
138 updated_reference = new_base + (wasm_memory_reference() - old_base);
139 DCHECK(new_base <= updated_reference &&
140 updated_reference < new_base + new_size);
141 Memory::Address_at(pc_) = updated_reference;
142 } else if (IsWasmMemorySizeReference(rmode_)) {
143 uint32_t updated_size_reference;
144 DCHECK(wasm_memory_size_reference() <= old_size);
145 updated_size_reference =
146 new_size + (wasm_memory_size_reference() - old_size);
147 DCHECK(updated_size_reference <= new_size);
148 Memory::uint32_at(pc_) = updated_size_reference;
149 } else {
150 UNREACHABLE();
151 }
152 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
153 Assembler::FlushICache(isolate_, pc_, sizeof(int64_t));
154 }
155}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000156
Steve Blocka7e24c12009-10-30 11:49:00 +0000157// -----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000158// Implementation of Operand
159
Andrei Popescu402d9372010-02-26 13:31:12 +0000160Operand::Operand(Register base, int32_t disp) : rex_(0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000161 len_ = 1;
162 if (base.is(rsp) || base.is(r12)) {
163 // SIB byte is needed to encode (rsp + offset) or (r12 + offset).
164 set_sib(times_1, rsp, base);
165 }
166
167 if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
168 set_modrm(0, base);
169 } else if (is_int8(disp)) {
170 set_modrm(1, base);
171 set_disp8(disp);
172 } else {
173 set_modrm(2, base);
174 set_disp32(disp);
175 }
176}
177
178
179Operand::Operand(Register base,
180 Register index,
181 ScaleFactor scale,
Andrei Popescu402d9372010-02-26 13:31:12 +0000182 int32_t disp) : rex_(0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183 DCHECK(!index.is(rsp));
Steve Blocka7e24c12009-10-30 11:49:00 +0000184 len_ = 1;
185 set_sib(scale, index, base);
186 if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
187 // This call to set_modrm doesn't overwrite the REX.B (or REX.X) bits
188 // possibly set by set_sib.
189 set_modrm(0, rsp);
190 } else if (is_int8(disp)) {
191 set_modrm(1, rsp);
192 set_disp8(disp);
193 } else {
194 set_modrm(2, rsp);
195 set_disp32(disp);
196 }
197}
198
199
Andrei Popescu402d9372010-02-26 13:31:12 +0000200Operand::Operand(Register index,
201 ScaleFactor scale,
202 int32_t disp) : rex_(0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000203 DCHECK(!index.is(rsp));
Andrei Popescu402d9372010-02-26 13:31:12 +0000204 len_ = 1;
205 set_modrm(0, rsp);
206 set_sib(scale, index, rbp);
207 set_disp32(disp);
208}
209
210
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211Operand::Operand(Label* label) : rex_(0), len_(1) {
212 DCHECK_NOT_NULL(label);
213 set_modrm(0, rbp);
214 set_disp64(reinterpret_cast<intptr_t>(label));
215}
216
217
Leon Clarkef7060e22010-06-03 12:02:55 +0100218Operand::Operand(const Operand& operand, int32_t offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000219 DCHECK(operand.len_ >= 1);
Leon Clarkef7060e22010-06-03 12:02:55 +0100220 // Operand encodes REX ModR/M [SIB] [Disp].
221 byte modrm = operand.buf_[0];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222 DCHECK(modrm < 0xC0); // Disallow mode 3 (register target).
Leon Clarkef7060e22010-06-03 12:02:55 +0100223 bool has_sib = ((modrm & 0x07) == 0x04);
224 byte mode = modrm & 0xC0;
225 int disp_offset = has_sib ? 2 : 1;
226 int base_reg = (has_sib ? operand.buf_[1] : modrm) & 0x07;
227 // Mode 0 with rbp/r13 as ModR/M or SIB base register always has a 32-bit
228 // displacement.
229 bool is_baseless = (mode == 0) && (base_reg == 0x05); // No base or RIP base.
230 int32_t disp_value = 0;
231 if (mode == 0x80 || is_baseless) {
232 // Mode 2 or mode 0 with rbp/r13 as base: Word displacement.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233 disp_value = *bit_cast<const int32_t*>(&operand.buf_[disp_offset]);
Leon Clarkef7060e22010-06-03 12:02:55 +0100234 } else if (mode == 0x40) {
235 // Mode 1: Byte displacement.
236 disp_value = static_cast<signed char>(operand.buf_[disp_offset]);
237 }
238
239 // Write new operand with same registers, but with modified displacement.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000240 DCHECK(offset >= 0 ? disp_value + offset > disp_value
Leon Clarkef7060e22010-06-03 12:02:55 +0100241 : disp_value + offset < disp_value); // No overflow.
242 disp_value += offset;
243 rex_ = operand.rex_;
244 if (!is_int8(disp_value) || is_baseless) {
245 // Need 32 bits of displacement, mode 2 or mode 1 with register rbp/r13.
246 buf_[0] = (modrm & 0x3f) | (is_baseless ? 0x00 : 0x80);
247 len_ = disp_offset + 4;
248 Memory::int32_at(&buf_[disp_offset]) = disp_value;
249 } else if (disp_value != 0 || (base_reg == 0x05)) {
250 // Need 8 bits of displacement.
251 buf_[0] = (modrm & 0x3f) | 0x40; // Mode 1.
252 len_ = disp_offset + 1;
253 buf_[disp_offset] = static_cast<byte>(disp_value);
254 } else {
255 // Need no displacement.
256 buf_[0] = (modrm & 0x3f); // Mode 0.
257 len_ = disp_offset;
258 }
259 if (has_sib) {
260 buf_[1] = operand.buf_[1];
261 }
262}
263
Steve Block1e0659c2011-05-24 12:43:12 +0100264
265bool Operand::AddressUsesRegister(Register reg) const {
266 int code = reg.code();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267 DCHECK((buf_[0] & 0xC0) != 0xC0); // Always a memory operand.
Steve Block1e0659c2011-05-24 12:43:12 +0100268 // Start with only low three bits of base register. Initial decoding doesn't
269 // distinguish on the REX.B bit.
270 int base_code = buf_[0] & 0x07;
271 if (base_code == rsp.code()) {
272 // SIB byte present in buf_[1].
273 // Check the index register from the SIB byte + REX.X prefix.
274 int index_code = ((buf_[1] >> 3) & 0x07) | ((rex_ & 0x02) << 2);
275 // Index code (including REX.X) of 0x04 (rsp) means no index register.
276 if (index_code != rsp.code() && index_code == code) return true;
277 // Add REX.B to get the full base register code.
278 base_code = (buf_[1] & 0x07) | ((rex_ & 0x01) << 3);
279 // A base register of 0x05 (rbp) with mod = 0 means no base register.
280 if (base_code == rbp.code() && ((buf_[0] & 0xC0) == 0)) return false;
281 return code == base_code;
282 } else {
283 // A base register with low bits of 0x05 (rbp or r13) and mod = 0 means
284 // no base register.
285 if (base_code == rbp.code() && ((buf_[0] & 0xC0) == 0)) return false;
286 base_code |= ((rex_ & 0x01) << 3);
287 return code == base_code;
288 }
289}
290
291
Steve Blocka7e24c12009-10-30 11:49:00 +0000292// -----------------------------------------------------------------------------
Andrei Popescu31002712010-02-23 13:46:05 +0000293// Implementation of Assembler.
Steve Blocka7e24c12009-10-30 11:49:00 +0000294
295#ifdef GENERATED_CODE_COVERAGE
296static void InitCoverageLog();
297#endif
298
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000299Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
300 : AssemblerBase(isolate, buffer, buffer_size),
Steve Block44f0eee2011-05-26 01:26:41 +0100301 code_targets_(100),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302 positions_recorder_(this) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000303 // Clear the buffer in debug mode unless it was provided by the
304 // caller in which case we can't be sure it's okay to overwrite
305 // existing code in it.
306#ifdef DEBUG
307 if (own_buffer_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000308 memset(buffer_, 0xCC, buffer_size_); // int3
Steve Blocka7e24c12009-10-30 11:49:00 +0000309 }
310#endif
311
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000312 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000313
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800314
Steve Blocka7e24c12009-10-30 11:49:00 +0000315#ifdef GENERATED_CODE_COVERAGE
316 InitCoverageLog();
317#endif
318}
319
320
Steve Blocka7e24c12009-10-30 11:49:00 +0000321void Assembler::GetCode(CodeDesc* desc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000322 // Finalize code (at this point overflow() may be true, but the gap ensures
323 // that we are still not overlapping instructions and relocation info).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000324 reloc_info_writer.Finish();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000325 DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100326 // Set up code descriptor.
Steve Blocka7e24c12009-10-30 11:49:00 +0000327 desc->buffer = buffer_;
328 desc->buffer_size = buffer_size_;
329 desc->instr_size = pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000330 DCHECK(desc->instr_size > 0); // Zero-size code objects upset the system.
Steve Blockd0582a62009-12-15 09:54:21 +0000331 desc->reloc_size =
332 static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos());
Steve Blocka7e24c12009-10-30 11:49:00 +0000333 desc->origin = this;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000334 desc->constant_pool_size = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000335}
336
337
338void Assembler::Align(int m) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000339 DCHECK(base::bits::IsPowerOfTwo32(m));
Steve Block8defd9f2010-07-08 12:39:36 +0100340 int delta = (m - (pc_offset() & (m - 1))) & (m - 1);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100341 Nop(delta);
Steve Blocka7e24c12009-10-30 11:49:00 +0000342}
343
344
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100345void Assembler::CodeTargetAlign() {
346 Align(16); // Preferred alignment of jump targets on x64.
347}
348
349
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100350bool Assembler::IsNop(Address addr) {
351 Address a = addr;
352 while (*a == 0x66) a++;
353 if (*a == 0x90) return true;
354 if (a[0] == 0xf && a[1] == 0x1f) return true;
355 return false;
356}
357
358
Steve Blocka7e24c12009-10-30 11:49:00 +0000359void Assembler::bind_to(Label* L, int pos) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000360 DCHECK(!L->is_bound()); // Label may only be bound once.
361 DCHECK(0 <= pos && pos <= pc_offset()); // Position must be valid.
Steve Blocka7e24c12009-10-30 11:49:00 +0000362 if (L->is_linked()) {
363 int current = L->pos();
364 int next = long_at(current);
365 while (next != current) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000366 if (current >= 4 && long_at(current - 4) == 0) {
367 // Absolute address.
368 intptr_t imm64 = reinterpret_cast<intptr_t>(buffer_ + pos);
369 *reinterpret_cast<intptr_t*>(addr_at(current - 4)) = imm64;
370 internal_reference_positions_.push_back(current - 4);
371 } else {
372 // Relative address, relative to point after address.
373 int imm32 = pos - (current + sizeof(int32_t));
374 long_at_put(current, imm32);
375 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000376 current = next;
377 next = long_at(next);
378 }
379 // Fix up last fixup on linked list.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000380 if (current >= 4 && long_at(current - 4) == 0) {
381 // Absolute address.
382 intptr_t imm64 = reinterpret_cast<intptr_t>(buffer_ + pos);
383 *reinterpret_cast<intptr_t*>(addr_at(current - 4)) = imm64;
384 internal_reference_positions_.push_back(current - 4);
385 } else {
386 // Relative address, relative to point after address.
387 int imm32 = pos - (current + sizeof(int32_t));
388 long_at_put(current, imm32);
389 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000390 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000391 while (L->is_near_linked()) {
392 int fixup_pos = L->near_link_pos();
393 int offset_to_next =
394 static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000395 DCHECK(offset_to_next <= 0);
Ben Murdoch257744e2011-11-30 15:57:28 +0000396 int disp = pos - (fixup_pos + sizeof(int8_t));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000397 CHECK(is_int8(disp));
Ben Murdoch257744e2011-11-30 15:57:28 +0000398 set_byte_at(fixup_pos, disp);
399 if (offset_to_next < 0) {
400 L->link_to(fixup_pos + offset_to_next, Label::kNear);
401 } else {
402 L->UnuseNear();
403 }
404 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000405 L->bind_to(pos);
406}
407
408
409void Assembler::bind(Label* L) {
410 bind_to(L, pc_offset());
411}
412
413
414void Assembler::GrowBuffer() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000415 DCHECK(buffer_overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +0000416 if (!own_buffer_) FATAL("external code buffer is too small");
417
Andrei Popescu31002712010-02-23 13:46:05 +0000418 // Compute new buffer size.
Steve Blocka7e24c12009-10-30 11:49:00 +0000419 CodeDesc desc; // the new buffer
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000420 desc.buffer_size = 2 * buffer_size_;
421
Steve Blocka7e24c12009-10-30 11:49:00 +0000422 // Some internal data structures overflow for very large buffers,
423 // they must ensure that kMaximalBufferSize is not too large.
424 if ((desc.buffer_size > kMaximalBufferSize) ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000425 (desc.buffer_size > isolate()->heap()->MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000426 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
427 }
428
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100429 // Set up new buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +0000430 desc.buffer = NewArray<byte>(desc.buffer_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000431 desc.origin = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000432 desc.instr_size = pc_offset();
Steve Blockd0582a62009-12-15 09:54:21 +0000433 desc.reloc_size =
434 static_cast<int>((buffer_ + buffer_size_) - (reloc_info_writer.pos()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000435
436 // Clear the buffer in debug mode. Use 'int3' instructions to make
437 // sure to get into problems if we ever run uninitialized code.
438#ifdef DEBUG
439 memset(desc.buffer, 0xCC, desc.buffer_size);
440#endif
441
Andrei Popescu31002712010-02-23 13:46:05 +0000442 // Copy the data.
Steve Blocka7e24c12009-10-30 11:49:00 +0000443 intptr_t pc_delta = desc.buffer - buffer_;
444 intptr_t rc_delta = (desc.buffer + desc.buffer_size) -
445 (buffer_ + buffer_size_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000446 MemMove(desc.buffer, buffer_, desc.instr_size);
447 MemMove(rc_delta + reloc_info_writer.pos(), reloc_info_writer.pos(),
448 desc.reloc_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000449
Andrei Popescu31002712010-02-23 13:46:05 +0000450 // Switch buffers.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000451 DeleteArray(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000452 buffer_ = desc.buffer;
453 buffer_size_ = desc.buffer_size;
454 pc_ += pc_delta;
Steve Blocka7e24c12009-10-30 11:49:00 +0000455 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
456 reloc_info_writer.last_pc() + pc_delta);
457
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000458 // Relocate internal references.
459 for (auto pos : internal_reference_positions_) {
460 intptr_t* p = reinterpret_cast<intptr_t*>(buffer_ + pos);
461 *p += pc_delta;
Steve Blocka7e24c12009-10-30 11:49:00 +0000462 }
463
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000464 DCHECK(!buffer_overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +0000465}
466
467
468void Assembler::emit_operand(int code, const Operand& adr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000469 DCHECK(is_uint3(code));
Steve Blocka7e24c12009-10-30 11:49:00 +0000470 const unsigned length = adr.len_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000471 DCHECK(length > 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000472
473 // Emit updated ModR/M byte containing the given register.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000474 DCHECK((adr.buf_[0] & 0x38) == 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000475 *pc_++ = adr.buf_[0] | code << 3;
Steve Blocka7e24c12009-10-30 11:49:00 +0000476
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000477 // Recognize RIP relative addressing.
478 if (adr.buf_[0] == 5) {
479 DCHECK_EQ(9u, length);
480 Label* label = *bit_cast<Label* const*>(&adr.buf_[1]);
481 if (label->is_bound()) {
482 int offset = label->pos() - pc_offset() - sizeof(int32_t);
483 DCHECK_GE(0, offset);
484 emitl(offset);
485 } else if (label->is_linked()) {
486 emitl(label->pos());
487 label->link_to(pc_offset() - sizeof(int32_t));
488 } else {
489 DCHECK(label->is_unused());
490 int32_t current = pc_offset();
491 emitl(current);
492 label->link_to(current);
493 }
494 } else {
495 // Emit the rest of the encoded operand.
496 for (unsigned i = 1; i < length; i++) *pc_++ = adr.buf_[i];
497 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000498}
499
500
Andrei Popescu31002712010-02-23 13:46:05 +0000501// Assembler Instruction implementations.
Steve Blocka7e24c12009-10-30 11:49:00 +0000502
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000503void Assembler::arithmetic_op(byte opcode,
504 Register reg,
505 const Operand& op,
506 int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000507 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000508 emit_rex(reg, op, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000509 emit(opcode);
510 emit_operand(reg, op);
511}
512
513
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000514void Assembler::arithmetic_op(byte opcode,
515 Register reg,
516 Register rm_reg,
517 int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000518 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000519 DCHECK((opcode & 0xC6) == 2);
Leon Clarkef7060e22010-06-03 12:02:55 +0100520 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
521 // Swap reg and rm_reg and change opcode operand order.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000522 emit_rex(rm_reg, reg, size);
Leon Clarkef7060e22010-06-03 12:02:55 +0100523 emit(opcode ^ 0x02);
524 emit_modrm(rm_reg, reg);
525 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000526 emit_rex(reg, rm_reg, size);
Leon Clarkef7060e22010-06-03 12:02:55 +0100527 emit(opcode);
528 emit_modrm(reg, rm_reg);
529 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000530}
531
532
533void Assembler::arithmetic_op_16(byte opcode, Register reg, Register rm_reg) {
534 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535 DCHECK((opcode & 0xC6) == 2);
Leon Clarkef7060e22010-06-03 12:02:55 +0100536 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
537 // Swap reg and rm_reg and change opcode operand order.
538 emit(0x66);
539 emit_optional_rex_32(rm_reg, reg);
540 emit(opcode ^ 0x02);
541 emit_modrm(rm_reg, reg);
542 } else {
543 emit(0x66);
544 emit_optional_rex_32(reg, rm_reg);
545 emit(opcode);
546 emit_modrm(reg, rm_reg);
547 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000548}
549
550
551void Assembler::arithmetic_op_16(byte opcode,
552 Register reg,
553 const Operand& rm_reg) {
554 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000555 emit(0x66);
556 emit_optional_rex_32(reg, rm_reg);
557 emit(opcode);
558 emit_operand(reg, rm_reg);
559}
560
561
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000562void Assembler::arithmetic_op_8(byte opcode, Register reg, const Operand& op) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000563 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000564 if (!reg.is_byte_register()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100565 emit_rex_32(reg, op);
566 } else {
567 emit_optional_rex_32(reg, op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000568 }
569 emit(opcode);
570 emit_operand(reg, op);
571}
572
573
574void Assembler::arithmetic_op_8(byte opcode, Register reg, Register rm_reg) {
575 EnsureSpace ensure_space(this);
576 DCHECK((opcode & 0xC6) == 2);
577 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
Leon Clarkef7060e22010-06-03 12:02:55 +0100578 // Swap reg and rm_reg and change opcode operand order.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000579 if (!rm_reg.is_byte_register() || !reg.is_byte_register()) {
580 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
581 emit_rex_32(rm_reg, reg);
582 }
583 emit(opcode ^ 0x02);
Leon Clarkef7060e22010-06-03 12:02:55 +0100584 emit_modrm(rm_reg, reg);
585 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000586 if (!reg.is_byte_register() || !rm_reg.is_byte_register()) {
587 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
588 emit_rex_32(reg, rm_reg);
589 }
Leon Clarkef7060e22010-06-03 12:02:55 +0100590 emit(opcode);
591 emit_modrm(reg, rm_reg);
592 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000593}
594
595
Steve Blocka7e24c12009-10-30 11:49:00 +0000596void Assembler::immediate_arithmetic_op(byte subcode,
597 Register dst,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000598 Immediate src,
599 int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000600 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000601 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000602 if (is_int8(src.value_)) {
603 emit(0x83);
604 emit_modrm(subcode, dst);
Ben Murdochc5610432016-08-08 18:44:38 +0100605 if (!RelocInfo::IsNone(src.rmode_)) {
606 RecordRelocInfo(src.rmode_);
607 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000608 emit(src.value_);
609 } else if (dst.is(rax)) {
610 emit(0x05 | (subcode << 3));
Ben Murdochc5610432016-08-08 18:44:38 +0100611 emit(src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000612 } else {
613 emit(0x81);
614 emit_modrm(subcode, dst);
Ben Murdochc5610432016-08-08 18:44:38 +0100615 emit(src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000616 }
617}
618
619void Assembler::immediate_arithmetic_op(byte subcode,
620 const Operand& dst,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000621 Immediate src,
622 int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000623 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000624 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000625 if (is_int8(src.value_)) {
626 emit(0x83);
627 emit_operand(subcode, dst);
Ben Murdochc5610432016-08-08 18:44:38 +0100628 if (!RelocInfo::IsNone(src.rmode_)) {
629 RecordRelocInfo(src.rmode_);
630 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000631 emit(src.value_);
632 } else {
633 emit(0x81);
634 emit_operand(subcode, dst);
Ben Murdochc5610432016-08-08 18:44:38 +0100635 emit(src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000636 }
637}
638
639
640void Assembler::immediate_arithmetic_op_16(byte subcode,
641 Register dst,
642 Immediate src) {
643 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000644 emit(0x66); // Operand size override prefix.
645 emit_optional_rex_32(dst);
646 if (is_int8(src.value_)) {
647 emit(0x83);
648 emit_modrm(subcode, dst);
649 emit(src.value_);
650 } else if (dst.is(rax)) {
651 emit(0x05 | (subcode << 3));
Steve Block3ce2e202009-11-05 08:53:23 +0000652 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000653 } else {
654 emit(0x81);
655 emit_modrm(subcode, dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000656 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000657 }
658}
659
660
661void Assembler::immediate_arithmetic_op_16(byte subcode,
662 const Operand& dst,
663 Immediate src) {
664 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000665 emit(0x66); // Operand size override prefix.
666 emit_optional_rex_32(dst);
667 if (is_int8(src.value_)) {
668 emit(0x83);
669 emit_operand(subcode, dst);
670 emit(src.value_);
671 } else {
672 emit(0x81);
673 emit_operand(subcode, dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000674 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000675 }
676}
677
678
Steve Blocka7e24c12009-10-30 11:49:00 +0000679void Assembler::immediate_arithmetic_op_8(byte subcode,
680 const Operand& dst,
681 Immediate src) {
682 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000683 emit_optional_rex_32(dst);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000684 DCHECK(is_int8(src.value_) || is_uint8(src.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000685 emit(0x80);
686 emit_operand(subcode, dst);
687 emit(src.value_);
688}
689
690
691void Assembler::immediate_arithmetic_op_8(byte subcode,
692 Register dst,
693 Immediate src) {
694 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100695 if (!dst.is_byte_register()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000696 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
697 emit_rex_32(dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000698 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000699 DCHECK(is_int8(src.value_) || is_uint8(src.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000700 emit(0x80);
701 emit_modrm(subcode, dst);
702 emit(src.value_);
703}
704
705
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000706void Assembler::shift(Register dst,
707 Immediate shift_amount,
708 int subcode,
709 int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000710 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000711 DCHECK(size == kInt64Size ? is_uint6(shift_amount.value_)
712 : is_uint5(shift_amount.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000713 if (shift_amount.value_ == 1) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000714 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000715 emit(0xD1);
716 emit_modrm(subcode, dst);
717 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000718 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000719 emit(0xC1);
720 emit_modrm(subcode, dst);
721 emit(shift_amount.value_);
722 }
723}
724
725
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400726void Assembler::shift(Operand dst, Immediate shift_amount, int subcode,
727 int size) {
728 EnsureSpace ensure_space(this);
729 DCHECK(size == kInt64Size ? is_uint6(shift_amount.value_)
730 : is_uint5(shift_amount.value_));
731 if (shift_amount.value_ == 1) {
732 emit_rex(dst, size);
733 emit(0xD1);
734 emit_operand(subcode, dst);
735 } else {
736 emit_rex(dst, size);
737 emit(0xC1);
738 emit_operand(subcode, dst);
739 emit(shift_amount.value_);
740 }
741}
742
743
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000744void Assembler::shift(Register dst, int subcode, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000745 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000746 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000747 emit(0xD3);
748 emit_modrm(subcode, dst);
749}
750
751
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400752void Assembler::shift(Operand dst, int subcode, int size) {
753 EnsureSpace ensure_space(this);
754 emit_rex(dst, size);
755 emit(0xD3);
756 emit_operand(subcode, dst);
757}
758
759
Steve Blocka7e24c12009-10-30 11:49:00 +0000760void Assembler::bt(const Operand& dst, Register src) {
761 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000762 emit_rex_64(src, dst);
763 emit(0x0F);
764 emit(0xA3);
765 emit_operand(src, dst);
766}
767
768
769void Assembler::bts(const Operand& dst, Register src) {
770 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000771 emit_rex_64(src, dst);
772 emit(0x0F);
773 emit(0xAB);
774 emit_operand(src, dst);
775}
776
777
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000778void Assembler::bsrl(Register dst, Register src) {
779 EnsureSpace ensure_space(this);
780 emit_optional_rex_32(dst, src);
781 emit(0x0F);
782 emit(0xBD);
783 emit_modrm(dst, src);
784}
785
786
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000787void Assembler::bsrl(Register dst, const Operand& src) {
788 EnsureSpace ensure_space(this);
789 emit_optional_rex_32(dst, src);
790 emit(0x0F);
791 emit(0xBD);
792 emit_operand(dst, src);
793}
794
795
796void Assembler::bsrq(Register dst, Register src) {
797 EnsureSpace ensure_space(this);
798 emit_rex_64(dst, src);
799 emit(0x0F);
800 emit(0xBD);
801 emit_modrm(dst, src);
802}
803
804
805void Assembler::bsrq(Register dst, const Operand& src) {
806 EnsureSpace ensure_space(this);
807 emit_rex_64(dst, src);
808 emit(0x0F);
809 emit(0xBD);
810 emit_operand(dst, src);
811}
812
813
814void Assembler::bsfl(Register dst, Register src) {
815 EnsureSpace ensure_space(this);
816 emit_optional_rex_32(dst, src);
817 emit(0x0F);
818 emit(0xBC);
819 emit_modrm(dst, src);
820}
821
822
823void Assembler::bsfl(Register dst, const Operand& src) {
824 EnsureSpace ensure_space(this);
825 emit_optional_rex_32(dst, src);
826 emit(0x0F);
827 emit(0xBC);
828 emit_operand(dst, src);
829}
830
831
832void Assembler::bsfq(Register dst, Register src) {
833 EnsureSpace ensure_space(this);
834 emit_rex_64(dst, src);
835 emit(0x0F);
836 emit(0xBC);
837 emit_modrm(dst, src);
838}
839
840
841void Assembler::bsfq(Register dst, const Operand& src) {
842 EnsureSpace ensure_space(this);
843 emit_rex_64(dst, src);
844 emit(0x0F);
845 emit(0xBC);
846 emit_operand(dst, src);
847}
848
849
Steve Blocka7e24c12009-10-30 11:49:00 +0000850void Assembler::call(Label* L) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100851 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000852 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000853 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +0000854 emit(0xE8);
855 if (L->is_bound()) {
856 int offset = L->pos() - pc_offset() - sizeof(int32_t);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000857 DCHECK(offset <= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000858 emitl(offset);
859 } else if (L->is_linked()) {
860 emitl(L->pos());
861 L->link_to(pc_offset() - sizeof(int32_t));
862 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000863 DCHECK(L->is_unused());
Steve Blocka7e24c12009-10-30 11:49:00 +0000864 int32_t current = pc_offset();
865 emitl(current);
866 L->link_to(current);
867 }
868}
869
870
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000871void Assembler::call(Address entry, RelocInfo::Mode rmode) {
872 DCHECK(RelocInfo::IsRuntimeEntry(rmode));
873 positions_recorder()->WriteRecordedPositions();
874 EnsureSpace ensure_space(this);
875 // 1110 1000 #32-bit disp.
876 emit(0xE8);
877 emit_runtime_entry(entry, rmode);
878}
879
880
Ben Murdoch257744e2011-11-30 15:57:28 +0000881void Assembler::call(Handle<Code> target,
882 RelocInfo::Mode rmode,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000883 TypeFeedbackId ast_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800884 positions_recorder()->WriteRecordedPositions();
Steve Block3ce2e202009-11-05 08:53:23 +0000885 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000886 // 1110 1000 #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +0000887 emit(0xE8);
Ben Murdoch257744e2011-11-30 15:57:28 +0000888 emit_code_target(target, rmode, ast_id);
Steve Block3ce2e202009-11-05 08:53:23 +0000889}
890
891
Steve Blocka7e24c12009-10-30 11:49:00 +0000892void Assembler::call(Register adr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100893 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000894 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000895 // Opcode: FF /2 r64.
Steve Block8defd9f2010-07-08 12:39:36 +0100896 emit_optional_rex_32(adr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000897 emit(0xFF);
898 emit_modrm(0x2, adr);
899}
900
901
902void Assembler::call(const Operand& op) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100903 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000904 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000905 // Opcode: FF /2 m64.
Steve Block8defd9f2010-07-08 12:39:36 +0100906 emit_optional_rex_32(op);
Steve Blocka7e24c12009-10-30 11:49:00 +0000907 emit(0xFF);
Steve Block8defd9f2010-07-08 12:39:36 +0100908 emit_operand(0x2, op);
Steve Blocka7e24c12009-10-30 11:49:00 +0000909}
910
911
Steve Block1e0659c2011-05-24 12:43:12 +0100912// Calls directly to the given address using a relative offset.
913// Should only ever be used in Code objects for calls within the
914// same Code object. Should not be used when generating new code (use labels),
915// but only when patching existing code.
916void Assembler::call(Address target) {
917 positions_recorder()->WriteRecordedPositions();
918 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +0100919 // 1110 1000 #32-bit disp.
920 emit(0xE8);
921 Address source = pc_ + 4;
922 intptr_t displacement = target - source;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000923 DCHECK(is_int32(displacement));
Steve Block1e0659c2011-05-24 12:43:12 +0100924 emitl(static_cast<int32_t>(displacement));
925}
926
927
Steve Block3ce2e202009-11-05 08:53:23 +0000928void Assembler::clc() {
929 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +0000930 emit(0xF8);
931}
932
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000933
Steve Block44f0eee2011-05-26 01:26:41 +0100934void Assembler::cld() {
935 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +0100936 emit(0xFC);
937}
938
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000939
Steve Blocka7e24c12009-10-30 11:49:00 +0000940void Assembler::cdq() {
941 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000942 emit(0x99);
943}
944
945
946void Assembler::cmovq(Condition cc, Register dst, Register src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000947 if (cc == always) {
948 movq(dst, src);
949 } else if (cc == never) {
950 return;
951 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000952 // No need to check CpuInfo for CMOV support, it's a required part of the
953 // 64-bit architecture.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000954 DCHECK(cc >= 0); // Use mov for unconditional moves.
Steve Blocka7e24c12009-10-30 11:49:00 +0000955 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000956 // Opcode: REX.W 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000957 emit_rex_64(dst, src);
958 emit(0x0f);
959 emit(0x40 + cc);
960 emit_modrm(dst, src);
961}
962
963
964void Assembler::cmovq(Condition cc, Register dst, const Operand& src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000965 if (cc == always) {
966 movq(dst, src);
967 } else if (cc == never) {
968 return;
969 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000970 DCHECK(cc >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000971 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000972 // Opcode: REX.W 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000973 emit_rex_64(dst, src);
974 emit(0x0f);
975 emit(0x40 + cc);
976 emit_operand(dst, src);
977}
978
979
980void Assembler::cmovl(Condition cc, Register dst, Register src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000981 if (cc == always) {
982 movl(dst, src);
983 } else if (cc == never) {
984 return;
985 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000986 DCHECK(cc >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000987 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000988 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000989 emit_optional_rex_32(dst, src);
990 emit(0x0f);
991 emit(0x40 + cc);
992 emit_modrm(dst, src);
993}
994
995
996void Assembler::cmovl(Condition cc, Register dst, const Operand& src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000997 if (cc == always) {
998 movl(dst, src);
999 } else if (cc == never) {
1000 return;
1001 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001002 DCHECK(cc >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001003 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +00001004 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +00001005 emit_optional_rex_32(dst, src);
1006 emit(0x0f);
1007 emit(0x40 + cc);
1008 emit_operand(dst, src);
1009}
1010
1011
1012void Assembler::cmpb_al(Immediate imm8) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001013 DCHECK(is_int8(imm8.value_) || is_uint8(imm8.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +00001014 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001015 emit(0x3c);
1016 emit(imm8.value_);
1017}
1018
1019
1020void Assembler::cpuid() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001021 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001022 emit(0x0F);
1023 emit(0xA2);
1024}
1025
1026
1027void Assembler::cqo() {
1028 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001029 emit_rex_64();
1030 emit(0x99);
1031}
1032
1033
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001034void Assembler::emit_dec(Register dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001035 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001036 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001037 emit(0xFF);
1038 emit_modrm(0x1, dst);
1039}
1040
1041
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001042void Assembler::emit_dec(const Operand& dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001043 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001044 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001045 emit(0xFF);
1046 emit_operand(1, dst);
1047}
1048
1049
Steve Block3ce2e202009-11-05 08:53:23 +00001050void Assembler::decb(Register dst) {
1051 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001052 if (!dst.is_byte_register()) {
Steve Block3ce2e202009-11-05 08:53:23 +00001053 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1054 emit_rex_32(dst);
1055 }
1056 emit(0xFE);
1057 emit_modrm(0x1, dst);
1058}
1059
1060
1061void Assembler::decb(const Operand& dst) {
1062 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001063 emit_optional_rex_32(dst);
1064 emit(0xFE);
1065 emit_operand(1, dst);
1066}
1067
1068
Steve Blocka7e24c12009-10-30 11:49:00 +00001069void Assembler::enter(Immediate size) {
1070 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001071 emit(0xC8);
1072 emitw(size.value_); // 16 bit operand, always.
1073 emit(0);
1074}
1075
1076
1077void Assembler::hlt() {
1078 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001079 emit(0xF4);
1080}
1081
1082
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001083void Assembler::emit_idiv(Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001084 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001085 emit_rex(src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001086 emit(0xF7);
1087 emit_modrm(0x7, src);
1088}
1089
1090
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001091void Assembler::emit_div(Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001092 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001093 emit_rex(src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001094 emit(0xF7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001095 emit_modrm(0x6, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001096}
1097
1098
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001099void Assembler::emit_imul(Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001100 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001101 emit_rex(src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001102 emit(0xF7);
1103 emit_modrm(0x5, src);
1104}
1105
1106
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001107void Assembler::emit_imul(const Operand& src, int size) {
1108 EnsureSpace ensure_space(this);
1109 emit_rex(src, size);
1110 emit(0xF7);
1111 emit_operand(0x5, src);
1112}
1113
1114
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001115void Assembler::emit_imul(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001116 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001117 emit_rex(dst, src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001118 emit(0x0F);
1119 emit(0xAF);
1120 emit_modrm(dst, src);
1121}
1122
1123
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001124void Assembler::emit_imul(Register dst, const Operand& src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001125 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001126 emit_rex(dst, src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001127 emit(0x0F);
1128 emit(0xAF);
1129 emit_operand(dst, src);
1130}
1131
1132
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001133void Assembler::emit_imul(Register dst, Register src, Immediate imm, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001134 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001135 emit_rex(dst, src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001136 if (is_int8(imm.value_)) {
1137 emit(0x6B);
1138 emit_modrm(dst, src);
1139 emit(imm.value_);
1140 } else {
1141 emit(0x69);
1142 emit_modrm(dst, src);
1143 emitl(imm.value_);
1144 }
1145}
1146
1147
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001148void Assembler::emit_imul(Register dst, const Operand& src, Immediate imm,
1149 int size) {
1150 EnsureSpace ensure_space(this);
1151 emit_rex(dst, src, size);
1152 if (is_int8(imm.value_)) {
1153 emit(0x6B);
1154 emit_operand(dst, src);
1155 emit(imm.value_);
1156 } else {
1157 emit(0x69);
1158 emit_operand(dst, src);
1159 emitl(imm.value_);
1160 }
1161}
1162
1163
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001164void Assembler::emit_inc(Register dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001165 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001166 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001167 emit(0xFF);
1168 emit_modrm(0x0, dst);
1169}
1170
1171
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001172void Assembler::emit_inc(const Operand& dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001173 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001174 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001175 emit(0xFF);
1176 emit_operand(0, dst);
1177}
1178
1179
Steve Blocka7e24c12009-10-30 11:49:00 +00001180void Assembler::int3() {
1181 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001182 emit(0xCC);
1183}
1184
1185
Ben Murdoch257744e2011-11-30 15:57:28 +00001186void Assembler::j(Condition cc, Label* L, Label::Distance distance) {
Steve Block3ce2e202009-11-05 08:53:23 +00001187 if (cc == always) {
1188 jmp(L);
1189 return;
1190 } else if (cc == never) {
1191 return;
1192 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001193 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001194 DCHECK(is_uint4(cc));
Steve Blocka7e24c12009-10-30 11:49:00 +00001195 if (L->is_bound()) {
1196 const int short_size = 2;
1197 const int long_size = 6;
1198 int offs = L->pos() - pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001199 DCHECK(offs <= 0);
1200 // Determine whether we can use 1-byte offsets for backwards branches,
1201 // which have a max range of 128 bytes.
1202
1203 // We also need to check predictable_code_size() flag here, because on x64,
1204 // when the full code generator recompiles code for debugging, some places
1205 // need to be padded out to a certain size. The debugger is keeping track of
1206 // how often it did this so that it can adjust return addresses on the
1207 // stack, but if the size of jump instructions can also change, that's not
1208 // enough and the calculated offsets would be incorrect.
1209 if (is_int8(offs - short_size) && !predictable_code_size()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001210 // 0111 tttn #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001211 emit(0x70 | cc);
1212 emit((offs - short_size) & 0xFF);
1213 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001214 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001215 emit(0x0F);
1216 emit(0x80 | cc);
1217 emitl(offs - long_size);
1218 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001219 } else if (distance == Label::kNear) {
1220 // 0111 tttn #8-bit disp
1221 emit(0x70 | cc);
1222 byte disp = 0x00;
1223 if (L->is_near_linked()) {
1224 int offset = L->near_link_pos() - pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001225 DCHECK(is_int8(offset));
Ben Murdoch257744e2011-11-30 15:57:28 +00001226 disp = static_cast<byte>(offset & 0xFF);
1227 }
1228 L->link_to(pc_offset(), Label::kNear);
1229 emit(disp);
Steve Blocka7e24c12009-10-30 11:49:00 +00001230 } else if (L->is_linked()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001231 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001232 emit(0x0F);
1233 emit(0x80 | cc);
1234 emitl(L->pos());
1235 L->link_to(pc_offset() - sizeof(int32_t));
1236 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001237 DCHECK(L->is_unused());
Steve Blocka7e24c12009-10-30 11:49:00 +00001238 emit(0x0F);
1239 emit(0x80 | cc);
1240 int32_t current = pc_offset();
1241 emitl(current);
1242 L->link_to(current);
1243 }
1244}
1245
1246
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001247void Assembler::j(Condition cc, Address entry, RelocInfo::Mode rmode) {
1248 DCHECK(RelocInfo::IsRuntimeEntry(rmode));
1249 EnsureSpace ensure_space(this);
1250 DCHECK(is_uint4(cc));
1251 emit(0x0F);
1252 emit(0x80 | cc);
1253 emit_runtime_entry(entry, rmode);
1254}
1255
1256
Steve Block3ce2e202009-11-05 08:53:23 +00001257void Assembler::j(Condition cc,
1258 Handle<Code> target,
1259 RelocInfo::Mode rmode) {
1260 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001261 DCHECK(is_uint4(cc));
Andrei Popescu31002712010-02-23 13:46:05 +00001262 // 0000 1111 1000 tttn #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +00001263 emit(0x0F);
1264 emit(0x80 | cc);
1265 emit_code_target(target, rmode);
1266}
1267
1268
Ben Murdoch257744e2011-11-30 15:57:28 +00001269void Assembler::jmp(Label* L, Label::Distance distance) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001270 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01001271 const int short_size = sizeof(int8_t);
1272 const int long_size = sizeof(int32_t);
Steve Blocka7e24c12009-10-30 11:49:00 +00001273 if (L->is_bound()) {
1274 int offs = L->pos() - pc_offset() - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001275 DCHECK(offs <= 0);
1276 if (is_int8(offs - short_size) && !predictable_code_size()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001277 // 1110 1011 #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001278 emit(0xEB);
Steve Block6ded16b2010-05-10 14:33:55 +01001279 emit((offs - short_size) & 0xFF);
Steve Blocka7e24c12009-10-30 11:49:00 +00001280 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001281 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001282 emit(0xE9);
Steve Block6ded16b2010-05-10 14:33:55 +01001283 emitl(offs - long_size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001284 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001285 } else if (distance == Label::kNear) {
1286 emit(0xEB);
1287 byte disp = 0x00;
1288 if (L->is_near_linked()) {
1289 int offset = L->near_link_pos() - pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001290 DCHECK(is_int8(offset));
Ben Murdoch257744e2011-11-30 15:57:28 +00001291 disp = static_cast<byte>(offset & 0xFF);
1292 }
1293 L->link_to(pc_offset(), Label::kNear);
1294 emit(disp);
1295 } else if (L->is_linked()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001296 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001297 emit(0xE9);
1298 emitl(L->pos());
Steve Block6ded16b2010-05-10 14:33:55 +01001299 L->link_to(pc_offset() - long_size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001300 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001301 // 1110 1001 #32-bit disp.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001302 DCHECK(L->is_unused());
Steve Blocka7e24c12009-10-30 11:49:00 +00001303 emit(0xE9);
1304 int32_t current = pc_offset();
1305 emitl(current);
1306 L->link_to(current);
1307 }
1308}
1309
1310
Steve Block3ce2e202009-11-05 08:53:23 +00001311void Assembler::jmp(Handle<Code> target, RelocInfo::Mode rmode) {
1312 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +00001313 // 1110 1001 #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +00001314 emit(0xE9);
1315 emit_code_target(target, rmode);
1316}
1317
1318
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001319void Assembler::jmp(Address entry, RelocInfo::Mode rmode) {
1320 DCHECK(RelocInfo::IsRuntimeEntry(rmode));
1321 EnsureSpace ensure_space(this);
1322 DCHECK(RelocInfo::IsRuntimeEntry(rmode));
1323 emit(0xE9);
1324 emit_runtime_entry(entry, rmode);
1325}
1326
1327
Steve Blocka7e24c12009-10-30 11:49:00 +00001328void Assembler::jmp(Register target) {
1329 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +00001330 // Opcode FF/4 r64.
Steve Block8defd9f2010-07-08 12:39:36 +01001331 emit_optional_rex_32(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001332 emit(0xFF);
1333 emit_modrm(0x4, target);
1334}
1335
1336
1337void Assembler::jmp(const Operand& src) {
1338 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +00001339 // Opcode FF/4 m64.
Steve Blocka7e24c12009-10-30 11:49:00 +00001340 emit_optional_rex_32(src);
1341 emit(0xFF);
1342 emit_operand(0x4, src);
1343}
1344
1345
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001346void Assembler::emit_lea(Register dst, const Operand& src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001347 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001348 emit_rex(dst, src, size);
Steve Block6ded16b2010-05-10 14:33:55 +01001349 emit(0x8D);
1350 emit_operand(dst, src);
1351}
1352
1353
Steve Blocka7e24c12009-10-30 11:49:00 +00001354void Assembler::load_rax(void* value, RelocInfo::Mode mode) {
1355 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001356 if (kPointerSize == kInt64Size) {
1357 emit(0x48); // REX.W
1358 emit(0xA1);
1359 emitp(value, mode);
1360 } else {
1361 DCHECK(kPointerSize == kInt32Size);
1362 emit(0xA1);
1363 emitp(value, mode);
1364 // In 64-bit mode, need to zero extend the operand to 8 bytes.
1365 // See 2.2.1.4 in Intel64 and IA32 Architectures Software
1366 // Developer's Manual Volume 2.
1367 emitl(0);
1368 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001369}
1370
1371
1372void Assembler::load_rax(ExternalReference ref) {
1373 load_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
1374}
1375
1376
1377void Assembler::leave() {
1378 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001379 emit(0xC9);
1380}
1381
1382
1383void Assembler::movb(Register dst, const Operand& src) {
1384 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001385 if (!dst.is_byte_register()) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001386 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1387 emit_rex_32(dst, src);
1388 } else {
1389 emit_optional_rex_32(dst, src);
1390 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001391 emit(0x8A);
1392 emit_operand(dst, src);
1393}
1394
Steve Block6ded16b2010-05-10 14:33:55 +01001395
Steve Blocka7e24c12009-10-30 11:49:00 +00001396void Assembler::movb(Register dst, Immediate imm) {
1397 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001398 if (!dst.is_byte_register()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001399 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001400 emit_rex_32(dst);
1401 }
1402 emit(0xB0 + dst.low_bits());
Steve Blocka7e24c12009-10-30 11:49:00 +00001403 emit(imm.value_);
1404}
1405
Steve Block6ded16b2010-05-10 14:33:55 +01001406
Steve Blocka7e24c12009-10-30 11:49:00 +00001407void Assembler::movb(const Operand& dst, Register src) {
1408 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001409 if (!src.is_byte_register()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001410 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001411 emit_rex_32(src, dst);
1412 } else {
1413 emit_optional_rex_32(src, dst);
1414 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001415 emit(0x88);
1416 emit_operand(src, dst);
1417}
1418
Steve Block6ded16b2010-05-10 14:33:55 +01001419
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001420void Assembler::movb(const Operand& dst, Immediate imm) {
1421 EnsureSpace ensure_space(this);
1422 emit_optional_rex_32(dst);
1423 emit(0xC6);
1424 emit_operand(0x0, dst);
1425 emit(static_cast<byte>(imm.value_));
1426}
1427
1428
1429void Assembler::movw(Register dst, const Operand& src) {
1430 EnsureSpace ensure_space(this);
1431 emit(0x66);
1432 emit_optional_rex_32(dst, src);
1433 emit(0x8B);
1434 emit_operand(dst, src);
1435}
1436
1437
Steve Block3ce2e202009-11-05 08:53:23 +00001438void Assembler::movw(const Operand& dst, Register src) {
1439 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001440 emit(0x66);
1441 emit_optional_rex_32(src, dst);
1442 emit(0x89);
1443 emit_operand(src, dst);
1444}
1445
Steve Block6ded16b2010-05-10 14:33:55 +01001446
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001447void Assembler::movw(const Operand& dst, Immediate imm) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001448 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001449 emit(0x66);
1450 emit_optional_rex_32(dst);
1451 emit(0xC7);
1452 emit_operand(0x0, dst);
1453 emit(static_cast<byte>(imm.value_ & 0xff));
1454 emit(static_cast<byte>(imm.value_ >> 8));
1455}
1456
1457
1458void Assembler::emit_mov(Register dst, const Operand& src, int size) {
1459 EnsureSpace ensure_space(this);
1460 emit_rex(dst, src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001461 emit(0x8B);
1462 emit_operand(dst, src);
1463}
1464
1465
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001466void Assembler::emit_mov(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001467 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +01001468 if (src.low_bits() == 4) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001469 emit_rex(src, dst, size);
Leon Clarkef7060e22010-06-03 12:02:55 +01001470 emit(0x89);
1471 emit_modrm(src, dst);
1472 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001473 emit_rex(dst, src, size);
Leon Clarkef7060e22010-06-03 12:02:55 +01001474 emit(0x8B);
1475 emit_modrm(dst, src);
1476 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001477}
1478
1479
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001480void Assembler::emit_mov(const Operand& dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001481 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001482 emit_rex(src, dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001483 emit(0x89);
1484 emit_operand(src, dst);
1485}
1486
1487
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001488void Assembler::emit_mov(Register dst, Immediate value, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001489 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001490 emit_rex(dst, size);
1491 if (size == kInt64Size) {
1492 emit(0xC7);
1493 emit_modrm(0x0, dst);
1494 } else {
1495 DCHECK(size == kInt32Size);
1496 emit(0xB8 + dst.low_bits());
1497 }
1498 emit(value);
1499}
1500
1501
1502void Assembler::emit_mov(const Operand& dst, Immediate value, int size) {
1503 EnsureSpace ensure_space(this);
1504 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001505 emit(0xC7);
1506 emit_operand(0x0, dst);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001507 emit(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001508}
1509
1510
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001511void Assembler::movp(Register dst, void* value, RelocInfo::Mode rmode) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001512 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001513 emit_rex(dst, kPointerSize);
1514 emit(0xB8 | dst.low_bits());
1515 emitp(value, rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001516}
1517
Ben Murdochda12d292016-06-02 14:46:10 +01001518void Assembler::movq(Register dst, int64_t value, RelocInfo::Mode rmode) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001519 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001520 emit_rex_64(dst);
1521 emit(0xB8 | dst.low_bits());
Ben Murdochda12d292016-06-02 14:46:10 +01001522 if (!RelocInfo::IsNone(rmode)) {
1523 RecordRelocInfo(rmode, value);
1524 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001525 emitq(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001526}
1527
Ben Murdochda12d292016-06-02 14:46:10 +01001528void Assembler::movq(Register dst, uint64_t value, RelocInfo::Mode rmode) {
1529 movq(dst, static_cast<int64_t>(value), rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001530}
1531
Andrei Popescu31002712010-02-23 13:46:05 +00001532// Loads the ip-relative location of the src label into the target location
1533// (as a 32-bit offset sign extended to 64-bit).
Steve Blocka7e24c12009-10-30 11:49:00 +00001534void Assembler::movl(const Operand& dst, Label* src) {
1535 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001536 emit_optional_rex_32(dst);
1537 emit(0xC7);
1538 emit_operand(0, dst);
1539 if (src->is_bound()) {
1540 int offset = src->pos() - pc_offset() - sizeof(int32_t);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001541 DCHECK(offset <= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001542 emitl(offset);
1543 } else if (src->is_linked()) {
1544 emitl(src->pos());
1545 src->link_to(pc_offset() - sizeof(int32_t));
1546 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001547 DCHECK(src->is_unused());
Steve Blocka7e24c12009-10-30 11:49:00 +00001548 int32_t current = pc_offset();
1549 emitl(current);
1550 src->link_to(current);
1551 }
1552}
1553
1554
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001555void Assembler::movsxbl(Register dst, Register src) {
1556 EnsureSpace ensure_space(this);
1557 if (!src.is_byte_register()) {
1558 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1559 emit_rex_32(dst, src);
1560 } else {
1561 emit_optional_rex_32(dst, src);
1562 }
1563 emit(0x0F);
1564 emit(0xBE);
1565 emit_modrm(dst, src);
1566}
1567
1568
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001569void Assembler::movsxbl(Register dst, const Operand& src) {
1570 EnsureSpace ensure_space(this);
1571 emit_optional_rex_32(dst, src);
1572 emit(0x0F);
1573 emit(0xBE);
1574 emit_operand(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001575}
1576
1577
Steve Block3ce2e202009-11-05 08:53:23 +00001578void Assembler::movsxbq(Register dst, const Operand& src) {
1579 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001580 emit_rex_64(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00001581 emit(0x0F);
1582 emit(0xBE);
1583 emit_operand(dst, src);
1584}
1585
1586
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001587void Assembler::movsxwl(Register dst, Register src) {
1588 EnsureSpace ensure_space(this);
1589 emit_optional_rex_32(dst, src);
1590 emit(0x0F);
1591 emit(0xBF);
1592 emit_modrm(dst, src);
1593}
1594
1595
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001596void Assembler::movsxwl(Register dst, const Operand& src) {
1597 EnsureSpace ensure_space(this);
1598 emit_optional_rex_32(dst, src);
1599 emit(0x0F);
1600 emit(0xBF);
1601 emit_operand(dst, src);
1602}
1603
1604
Steve Block3ce2e202009-11-05 08:53:23 +00001605void Assembler::movsxwq(Register dst, const Operand& src) {
1606 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001607 emit_rex_64(dst, src);
1608 emit(0x0F);
1609 emit(0xBF);
1610 emit_operand(dst, src);
1611}
1612
1613
Steve Blocka7e24c12009-10-30 11:49:00 +00001614void Assembler::movsxlq(Register dst, Register src) {
1615 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001616 emit_rex_64(dst, src);
1617 emit(0x63);
1618 emit_modrm(dst, src);
1619}
1620
1621
1622void Assembler::movsxlq(Register dst, const Operand& src) {
1623 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001624 emit_rex_64(dst, src);
1625 emit(0x63);
1626 emit_operand(dst, src);
1627}
1628
1629
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001630void Assembler::emit_movzxb(Register dst, const Operand& src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001631 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001632 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
1633 // there is no need to make this a 64 bit operation.
Steve Block8defd9f2010-07-08 12:39:36 +01001634 emit_optional_rex_32(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001635 emit(0x0F);
1636 emit(0xB6);
1637 emit_operand(dst, src);
1638}
1639
1640
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001641void Assembler::emit_movzxb(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001642 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001643 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
1644 // there is no need to make this a 64 bit operation.
1645 if (!src.is_byte_register()) {
1646 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1647 emit_rex_32(dst, src);
1648 } else {
1649 emit_optional_rex_32(dst, src);
1650 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001651 emit(0x0F);
1652 emit(0xB6);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001653 emit_modrm(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001654}
1655
1656
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001657void Assembler::emit_movzxw(Register dst, const Operand& src, int size) {
Steve Block3ce2e202009-11-05 08:53:23 +00001658 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001659 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
1660 // there is no need to make this a 64 bit operation.
Steve Block8defd9f2010-07-08 12:39:36 +01001661 emit_optional_rex_32(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00001662 emit(0x0F);
1663 emit(0xB7);
1664 emit_operand(dst, src);
1665}
1666
1667
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001668void Assembler::emit_movzxw(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001669 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001670 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
1671 // there is no need to make this a 64 bit operation.
Steve Blocka7e24c12009-10-30 11:49:00 +00001672 emit_optional_rex_32(dst, src);
1673 emit(0x0F);
1674 emit(0xB7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001675 emit_modrm(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001676}
1677
1678
Leon Clarked91b9f72010-01-27 17:25:45 +00001679void Assembler::repmovsb() {
1680 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001681 emit(0xF3);
1682 emit(0xA4);
1683}
1684
1685
1686void Assembler::repmovsw() {
1687 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001688 emit(0x66); // Operand size override.
1689 emit(0xF3);
1690 emit(0xA4);
1691}
1692
1693
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001694void Assembler::emit_repmovs(int size) {
Leon Clarked91b9f72010-01-27 17:25:45 +00001695 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001696 emit(0xF3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001697 emit_rex(size);
Leon Clarked91b9f72010-01-27 17:25:45 +00001698 emit(0xA5);
1699}
1700
1701
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001702void Assembler::mull(Register src) {
1703 EnsureSpace ensure_space(this);
1704 emit_optional_rex_32(src);
1705 emit(0xF7);
1706 emit_modrm(0x4, src);
1707}
1708
1709
1710void Assembler::mull(const Operand& src) {
1711 EnsureSpace ensure_space(this);
1712 emit_optional_rex_32(src);
1713 emit(0xF7);
1714 emit_operand(0x4, src);
1715}
1716
1717
1718void Assembler::mulq(Register src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001719 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001720 emit_rex_64(src);
1721 emit(0xF7);
1722 emit_modrm(0x4, src);
1723}
1724
1725
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001726void Assembler::emit_neg(Register dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001727 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001728 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001729 emit(0xF7);
1730 emit_modrm(0x3, dst);
1731}
1732
1733
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001734void Assembler::emit_neg(const Operand& dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001735 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001736 emit_rex_64(dst);
1737 emit(0xF7);
1738 emit_operand(3, dst);
1739}
1740
1741
1742void Assembler::nop() {
1743 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001744 emit(0x90);
1745}
1746
1747
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001748void Assembler::emit_not(Register dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001749 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001750 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001751 emit(0xF7);
1752 emit_modrm(0x2, dst);
1753}
1754
1755
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001756void Assembler::emit_not(const Operand& dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001757 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001758 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001759 emit(0xF7);
1760 emit_operand(2, dst);
1761}
1762
1763
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001764void Assembler::Nop(int n) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001765 // The recommended muti-byte sequences of NOP instructions from the Intel 64
1766 // and IA-32 Architectures Software Developer's Manual.
1767 //
1768 // Length Assembly Byte Sequence
1769 // 2 bytes 66 NOP 66 90H
1770 // 3 bytes NOP DWORD ptr [EAX] 0F 1F 00H
1771 // 4 bytes NOP DWORD ptr [EAX + 00H] 0F 1F 40 00H
1772 // 5 bytes NOP DWORD ptr [EAX + EAX*1 + 00H] 0F 1F 44 00 00H
1773 // 6 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00H] 66 0F 1F 44 00 00H
1774 // 7 bytes NOP DWORD ptr [EAX + 00000000H] 0F 1F 80 00 00 00 00H
1775 // 8 bytes NOP DWORD ptr [EAX + EAX*1 + 00000000H] 0F 1F 84 00 00 00 00 00H
1776 // 9 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 66 0F 1F 84 00 00 00 00
1777 // 00000000H] 00H
1778
Steve Blocka7e24c12009-10-30 11:49:00 +00001779 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001780 while (n > 0) {
1781 switch (n) {
1782 case 2:
1783 emit(0x66);
1784 case 1:
1785 emit(0x90);
1786 return;
1787 case 3:
1788 emit(0x0f);
1789 emit(0x1f);
1790 emit(0x00);
1791 return;
1792 case 4:
1793 emit(0x0f);
1794 emit(0x1f);
1795 emit(0x40);
1796 emit(0x00);
1797 return;
1798 case 6:
1799 emit(0x66);
1800 case 5:
1801 emit(0x0f);
1802 emit(0x1f);
1803 emit(0x44);
1804 emit(0x00);
1805 emit(0x00);
1806 return;
1807 case 7:
1808 emit(0x0f);
1809 emit(0x1f);
1810 emit(0x80);
1811 emit(0x00);
1812 emit(0x00);
1813 emit(0x00);
1814 emit(0x00);
1815 return;
1816 default:
1817 case 11:
1818 emit(0x66);
1819 n--;
1820 case 10:
1821 emit(0x66);
1822 n--;
1823 case 9:
1824 emit(0x66);
1825 n--;
1826 case 8:
1827 emit(0x0f);
1828 emit(0x1f);
1829 emit(0x84);
1830 emit(0x00);
1831 emit(0x00);
1832 emit(0x00);
1833 emit(0x00);
1834 emit(0x00);
1835 n -= 8;
1836 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001837 }
1838}
1839
1840
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001841void Assembler::popq(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001842 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001843 emit_optional_rex_32(dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001844 emit(0x58 | dst.low_bits());
1845}
1846
1847
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001848void Assembler::popq(const Operand& dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001849 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001850 emit_optional_rex_32(dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001851 emit(0x8F);
1852 emit_operand(0, dst);
1853}
1854
1855
1856void Assembler::popfq() {
1857 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001858 emit(0x9D);
1859}
1860
1861
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001862void Assembler::pushq(Register src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001863 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001864 emit_optional_rex_32(src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001865 emit(0x50 | src.low_bits());
1866}
1867
1868
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001869void Assembler::pushq(const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001870 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001871 emit_optional_rex_32(src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001872 emit(0xFF);
1873 emit_operand(6, src);
1874}
1875
1876
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001877void Assembler::pushq(Immediate value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001878 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001879 if (is_int8(value.value_)) {
1880 emit(0x6A);
1881 emit(value.value_); // Emit low byte of value.
1882 } else {
1883 emit(0x68);
1884 emitl(value.value_);
1885 }
1886}
1887
1888
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001889void Assembler::pushq_imm32(int32_t imm32) {
Steve Block1e0659c2011-05-24 12:43:12 +01001890 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01001891 emit(0x68);
1892 emitl(imm32);
1893}
1894
1895
Steve Blocka7e24c12009-10-30 11:49:00 +00001896void Assembler::pushfq() {
1897 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001898 emit(0x9C);
1899}
1900
1901
Steve Blocka7e24c12009-10-30 11:49:00 +00001902void Assembler::ret(int imm16) {
1903 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001904 DCHECK(is_uint16(imm16));
Steve Blocka7e24c12009-10-30 11:49:00 +00001905 if (imm16 == 0) {
1906 emit(0xC3);
1907 } else {
1908 emit(0xC2);
1909 emit(imm16 & 0xFF);
1910 emit((imm16 >> 8) & 0xFF);
1911 }
1912}
1913
1914
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001915void Assembler::ud2() {
1916 EnsureSpace ensure_space(this);
1917 emit(0x0F);
1918 emit(0x0B);
1919}
1920
1921
Steve Blocka7e24c12009-10-30 11:49:00 +00001922void Assembler::setcc(Condition cc, Register reg) {
Steve Block3ce2e202009-11-05 08:53:23 +00001923 if (cc > last_condition) {
1924 movb(reg, Immediate(cc == always ? 1 : 0));
1925 return;
1926 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001927 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001928 DCHECK(is_uint4(cc));
1929 if (!reg.is_byte_register()) {
1930 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
Steve Blocka7e24c12009-10-30 11:49:00 +00001931 emit_rex_32(reg);
1932 }
1933 emit(0x0F);
1934 emit(0x90 | cc);
1935 emit_modrm(0x0, reg);
1936}
1937
1938
1939void Assembler::shld(Register dst, Register src) {
1940 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001941 emit_rex_64(src, dst);
1942 emit(0x0F);
1943 emit(0xA5);
1944 emit_modrm(src, dst);
1945}
1946
1947
1948void Assembler::shrd(Register dst, Register src) {
1949 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001950 emit_rex_64(src, dst);
1951 emit(0x0F);
1952 emit(0xAD);
1953 emit_modrm(src, dst);
1954}
1955
Ben Murdochc5610432016-08-08 18:44:38 +01001956void Assembler::xchgb(Register reg, const Operand& op) {
1957 EnsureSpace ensure_space(this);
1958 if (!reg.is_byte_register()) {
1959 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1960 emit_rex_32(reg, op);
1961 } else {
1962 emit_optional_rex_32(reg, op);
1963 }
1964 emit(0x86);
1965 emit_operand(reg, op);
1966}
1967
1968void Assembler::xchgw(Register reg, const Operand& op) {
1969 EnsureSpace ensure_space(this);
1970 emit(0x66);
1971 emit_optional_rex_32(reg, op);
1972 emit(0x87);
1973 emit_operand(reg, op);
1974}
Steve Blocka7e24c12009-10-30 11:49:00 +00001975
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001976void Assembler::emit_xchg(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001977 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001978 if (src.is(rax) || dst.is(rax)) { // Single-byte encoding
1979 Register other = src.is(rax) ? dst : src;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001980 emit_rex(other, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001981 emit(0x90 | other.low_bits());
Leon Clarkef7060e22010-06-03 12:02:55 +01001982 } else if (dst.low_bits() == 4) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001983 emit_rex(dst, src, size);
Leon Clarkef7060e22010-06-03 12:02:55 +01001984 emit(0x87);
1985 emit_modrm(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001986 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001987 emit_rex(src, dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001988 emit(0x87);
1989 emit_modrm(src, dst);
1990 }
1991}
1992
1993
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001994void Assembler::emit_xchg(Register dst, const Operand& src, int size) {
1995 EnsureSpace ensure_space(this);
1996 emit_rex(dst, src, size);
1997 emit(0x87);
1998 emit_operand(dst, src);
1999}
2000
2001
Steve Blocka7e24c12009-10-30 11:49:00 +00002002void Assembler::store_rax(void* dst, RelocInfo::Mode mode) {
2003 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002004 if (kPointerSize == kInt64Size) {
2005 emit(0x48); // REX.W
2006 emit(0xA3);
2007 emitp(dst, mode);
2008 } else {
2009 DCHECK(kPointerSize == kInt32Size);
2010 emit(0xA3);
2011 emitp(dst, mode);
2012 // In 64-bit mode, need to zero extend the operand to 8 bytes.
2013 // See 2.2.1.4 in Intel64 and IA32 Architectures Software
2014 // Developer's Manual Volume 2.
2015 emitl(0);
2016 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002017}
2018
2019
2020void Assembler::store_rax(ExternalReference ref) {
2021 store_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
2022}
2023
2024
Steve Block3ce2e202009-11-05 08:53:23 +00002025void Assembler::testb(Register dst, Register src) {
2026 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +01002027 if (src.low_bits() == 4) {
2028 emit_rex_32(src, dst);
2029 emit(0x84);
2030 emit_modrm(src, dst);
2031 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002032 if (!dst.is_byte_register() || !src.is_byte_register()) {
Leon Clarkef7060e22010-06-03 12:02:55 +01002033 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2034 emit_rex_32(dst, src);
2035 }
2036 emit(0x84);
2037 emit_modrm(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00002038 }
Steve Block3ce2e202009-11-05 08:53:23 +00002039}
2040
2041
Steve Blocka7e24c12009-10-30 11:49:00 +00002042void Assembler::testb(Register reg, Immediate mask) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002043 DCHECK(is_int8(mask.value_) || is_uint8(mask.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +00002044 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002045 if (reg.is(rax)) {
2046 emit(0xA8);
2047 emit(mask.value_); // Low byte emitted.
2048 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002049 if (!reg.is_byte_register()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002050 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2051 emit_rex_32(reg);
2052 }
2053 emit(0xF6);
2054 emit_modrm(0x0, reg);
2055 emit(mask.value_); // Low byte emitted.
2056 }
2057}
2058
2059
2060void Assembler::testb(const Operand& op, Immediate mask) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002061 DCHECK(is_int8(mask.value_) || is_uint8(mask.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +00002062 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002063 emit_optional_rex_32(rax, op);
2064 emit(0xF6);
2065 emit_operand(rax, op); // Operation code 0
2066 emit(mask.value_); // Low byte emitted.
2067}
2068
2069
Leon Clarkee46be812010-01-19 14:06:41 +00002070void Assembler::testb(const Operand& op, Register reg) {
2071 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002072 if (!reg.is_byte_register()) {
Leon Clarkee46be812010-01-19 14:06:41 +00002073 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2074 emit_rex_32(reg, op);
2075 } else {
2076 emit_optional_rex_32(reg, op);
2077 }
2078 emit(0x84);
2079 emit_operand(reg, op);
2080}
2081
Ben Murdochda12d292016-06-02 14:46:10 +01002082void Assembler::testw(Register dst, Register src) {
2083 EnsureSpace ensure_space(this);
2084 emit(0x66);
2085 if (src.low_bits() == 4) {
2086 emit_rex_32(src, dst);
2087 }
2088 emit(0x85);
2089 emit_modrm(src, dst);
2090}
2091
2092void Assembler::testw(Register reg, Immediate mask) {
2093 DCHECK(is_int16(mask.value_) || is_uint16(mask.value_));
2094 EnsureSpace ensure_space(this);
2095 emit(0x66);
2096 if (reg.is(rax)) {
2097 emit(0xA9);
Ben Murdochc5610432016-08-08 18:44:38 +01002098 emitw(mask.value_);
Ben Murdochda12d292016-06-02 14:46:10 +01002099 } else {
2100 if (reg.low_bits() == 4) {
2101 emit_rex_32(reg);
2102 }
2103 emit(0xF7);
2104 emit_modrm(0x0, reg);
Ben Murdochc5610432016-08-08 18:44:38 +01002105 emitw(mask.value_);
Ben Murdochda12d292016-06-02 14:46:10 +01002106 }
2107}
2108
2109void Assembler::testw(const Operand& op, Immediate mask) {
2110 DCHECK(is_int16(mask.value_) || is_uint16(mask.value_));
2111 EnsureSpace ensure_space(this);
2112 emit(0x66);
2113 emit_optional_rex_32(rax, op);
2114 emit(0xF7);
2115 emit_operand(rax, op);
Ben Murdochc5610432016-08-08 18:44:38 +01002116 emitw(mask.value_);
Ben Murdochda12d292016-06-02 14:46:10 +01002117}
2118
2119void Assembler::testw(const Operand& op, Register reg) {
2120 EnsureSpace ensure_space(this);
2121 emit(0x66);
2122 emit_optional_rex_32(reg, op);
2123 emit(0x85);
2124 emit_operand(rax, op);
2125}
Leon Clarkee46be812010-01-19 14:06:41 +00002126
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002127void Assembler::emit_test(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002128 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +01002129 if (src.low_bits() == 4) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002130 emit_rex(src, dst, size);
Leon Clarkef7060e22010-06-03 12:02:55 +01002131 emit(0x85);
2132 emit_modrm(src, dst);
2133 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002134 emit_rex(dst, src, size);
Leon Clarkef7060e22010-06-03 12:02:55 +01002135 emit(0x85);
2136 emit_modrm(dst, src);
2137 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002138}
2139
2140
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002141void Assembler::emit_test(Register reg, Immediate mask, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002142 // testl with a mask that fits in the low byte is exactly testb.
2143 if (is_uint8(mask.value_)) {
2144 testb(reg, mask);
2145 return;
2146 }
2147 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002148 if (reg.is(rax)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002149 emit_rex(rax, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00002150 emit(0xA9);
2151 emit(mask);
2152 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002153 emit_rex(reg, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00002154 emit(0xF7);
2155 emit_modrm(0x0, reg);
2156 emit(mask);
2157 }
2158}
2159
2160
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002161void Assembler::emit_test(const Operand& op, Immediate mask, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002162 // testl with a mask that fits in the low byte is exactly testb.
2163 if (is_uint8(mask.value_)) {
2164 testb(op, mask);
2165 return;
2166 }
2167 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002168 emit_rex(rax, op, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00002169 emit(0xF7);
2170 emit_operand(rax, op); // Operation code 0
2171 emit(mask);
2172}
2173
2174
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002175void Assembler::emit_test(const Operand& op, Register reg, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002176 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002177 emit_rex(reg, op, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00002178 emit(0x85);
2179 emit_operand(reg, op);
2180}
2181
2182
Andrei Popescu31002712010-02-23 13:46:05 +00002183// FPU instructions.
Steve Blocka7e24c12009-10-30 11:49:00 +00002184
2185
2186void Assembler::fld(int i) {
2187 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002188 emit_farith(0xD9, 0xC0, i);
2189}
2190
2191
2192void Assembler::fld1() {
2193 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002194 emit(0xD9);
2195 emit(0xE8);
2196}
2197
2198
2199void Assembler::fldz() {
2200 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002201 emit(0xD9);
2202 emit(0xEE);
2203}
2204
2205
Steve Block6ded16b2010-05-10 14:33:55 +01002206void Assembler::fldpi() {
2207 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002208 emit(0xD9);
2209 emit(0xEB);
2210}
2211
2212
Ben Murdochb0fe1622011-05-05 13:52:32 +01002213void Assembler::fldln2() {
2214 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002215 emit(0xD9);
2216 emit(0xED);
2217}
2218
2219
Steve Blocka7e24c12009-10-30 11:49:00 +00002220void Assembler::fld_s(const Operand& adr) {
2221 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002222 emit_optional_rex_32(adr);
2223 emit(0xD9);
2224 emit_operand(0, adr);
2225}
2226
2227
2228void Assembler::fld_d(const Operand& adr) {
2229 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002230 emit_optional_rex_32(adr);
2231 emit(0xDD);
2232 emit_operand(0, adr);
2233}
2234
2235
2236void Assembler::fstp_s(const Operand& adr) {
2237 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002238 emit_optional_rex_32(adr);
2239 emit(0xD9);
2240 emit_operand(3, adr);
2241}
2242
2243
2244void Assembler::fstp_d(const Operand& adr) {
2245 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002246 emit_optional_rex_32(adr);
2247 emit(0xDD);
2248 emit_operand(3, adr);
2249}
2250
2251
Steve Block3ce2e202009-11-05 08:53:23 +00002252void Assembler::fstp(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002253 DCHECK(is_uint3(index));
Steve Block3ce2e202009-11-05 08:53:23 +00002254 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00002255 emit_farith(0xDD, 0xD8, index);
2256}
2257
2258
Steve Blocka7e24c12009-10-30 11:49:00 +00002259void Assembler::fild_s(const Operand& adr) {
2260 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002261 emit_optional_rex_32(adr);
2262 emit(0xDB);
2263 emit_operand(0, adr);
2264}
2265
2266
2267void Assembler::fild_d(const Operand& adr) {
2268 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002269 emit_optional_rex_32(adr);
2270 emit(0xDF);
2271 emit_operand(5, adr);
2272}
2273
2274
2275void Assembler::fistp_s(const Operand& adr) {
2276 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002277 emit_optional_rex_32(adr);
2278 emit(0xDB);
2279 emit_operand(3, adr);
2280}
2281
2282
2283void Assembler::fisttp_s(const Operand& adr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002284 DCHECK(IsEnabled(SSE3));
Steve Blocka7e24c12009-10-30 11:49:00 +00002285 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002286 emit_optional_rex_32(adr);
2287 emit(0xDB);
2288 emit_operand(1, adr);
2289}
2290
2291
Leon Clarked91b9f72010-01-27 17:25:45 +00002292void Assembler::fisttp_d(const Operand& adr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002293 DCHECK(IsEnabled(SSE3));
Leon Clarked91b9f72010-01-27 17:25:45 +00002294 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00002295 emit_optional_rex_32(adr);
2296 emit(0xDD);
2297 emit_operand(1, adr);
2298}
2299
2300
Steve Blocka7e24c12009-10-30 11:49:00 +00002301void Assembler::fist_s(const Operand& adr) {
2302 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002303 emit_optional_rex_32(adr);
2304 emit(0xDB);
2305 emit_operand(2, adr);
2306}
2307
2308
2309void Assembler::fistp_d(const Operand& adr) {
2310 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002311 emit_optional_rex_32(adr);
2312 emit(0xDF);
Steve Block3ce2e202009-11-05 08:53:23 +00002313 emit_operand(7, adr);
Steve Blocka7e24c12009-10-30 11:49:00 +00002314}
2315
2316
2317void Assembler::fabs() {
2318 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002319 emit(0xD9);
2320 emit(0xE1);
2321}
2322
2323
2324void Assembler::fchs() {
2325 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002326 emit(0xD9);
2327 emit(0xE0);
2328}
2329
2330
2331void Assembler::fcos() {
2332 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002333 emit(0xD9);
2334 emit(0xFF);
2335}
2336
2337
2338void Assembler::fsin() {
2339 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002340 emit(0xD9);
2341 emit(0xFE);
2342}
2343
2344
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002345void Assembler::fptan() {
2346 EnsureSpace ensure_space(this);
2347 emit(0xD9);
2348 emit(0xF2);
2349}
2350
2351
Ben Murdochb0fe1622011-05-05 13:52:32 +01002352void Assembler::fyl2x() {
2353 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002354 emit(0xD9);
2355 emit(0xF1);
2356}
2357
2358
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002359void Assembler::f2xm1() {
2360 EnsureSpace ensure_space(this);
2361 emit(0xD9);
2362 emit(0xF0);
2363}
2364
2365
2366void Assembler::fscale() {
2367 EnsureSpace ensure_space(this);
2368 emit(0xD9);
2369 emit(0xFD);
2370}
2371
2372
2373void Assembler::fninit() {
2374 EnsureSpace ensure_space(this);
2375 emit(0xDB);
2376 emit(0xE3);
2377}
2378
2379
Steve Blocka7e24c12009-10-30 11:49:00 +00002380void Assembler::fadd(int i) {
2381 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002382 emit_farith(0xDC, 0xC0, i);
2383}
2384
2385
2386void Assembler::fsub(int i) {
2387 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002388 emit_farith(0xDC, 0xE8, i);
2389}
2390
2391
2392void Assembler::fisub_s(const Operand& adr) {
2393 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002394 emit_optional_rex_32(adr);
2395 emit(0xDA);
2396 emit_operand(4, adr);
2397}
2398
2399
2400void Assembler::fmul(int i) {
2401 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002402 emit_farith(0xDC, 0xC8, i);
2403}
2404
2405
2406void Assembler::fdiv(int i) {
2407 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002408 emit_farith(0xDC, 0xF8, i);
2409}
2410
2411
2412void Assembler::faddp(int i) {
2413 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002414 emit_farith(0xDE, 0xC0, i);
2415}
2416
2417
2418void Assembler::fsubp(int i) {
2419 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002420 emit_farith(0xDE, 0xE8, i);
2421}
2422
2423
2424void Assembler::fsubrp(int i) {
2425 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002426 emit_farith(0xDE, 0xE0, i);
2427}
2428
2429
2430void Assembler::fmulp(int i) {
2431 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002432 emit_farith(0xDE, 0xC8, i);
2433}
2434
2435
2436void Assembler::fdivp(int i) {
2437 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002438 emit_farith(0xDE, 0xF8, i);
2439}
2440
2441
2442void Assembler::fprem() {
2443 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002444 emit(0xD9);
2445 emit(0xF8);
2446}
2447
2448
2449void Assembler::fprem1() {
2450 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002451 emit(0xD9);
2452 emit(0xF5);
2453}
2454
2455
2456void Assembler::fxch(int i) {
2457 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002458 emit_farith(0xD9, 0xC8, i);
2459}
2460
2461
2462void Assembler::fincstp() {
2463 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002464 emit(0xD9);
2465 emit(0xF7);
2466}
2467
2468
2469void Assembler::ffree(int i) {
2470 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002471 emit_farith(0xDD, 0xC0, i);
2472}
2473
2474
2475void Assembler::ftst() {
2476 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002477 emit(0xD9);
2478 emit(0xE4);
2479}
2480
2481
2482void Assembler::fucomp(int i) {
2483 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002484 emit_farith(0xDD, 0xE8, i);
2485}
2486
2487
2488void Assembler::fucompp() {
2489 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002490 emit(0xDA);
2491 emit(0xE9);
2492}
2493
2494
Steve Block3ce2e202009-11-05 08:53:23 +00002495void Assembler::fucomi(int i) {
2496 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00002497 emit(0xDB);
2498 emit(0xE8 + i);
2499}
2500
2501
2502void Assembler::fucomip() {
2503 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00002504 emit(0xDF);
2505 emit(0xE9);
2506}
2507
2508
Steve Blocka7e24c12009-10-30 11:49:00 +00002509void Assembler::fcompp() {
2510 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002511 emit(0xDE);
2512 emit(0xD9);
2513}
2514
2515
2516void Assembler::fnstsw_ax() {
2517 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002518 emit(0xDF);
2519 emit(0xE0);
2520}
2521
2522
2523void Assembler::fwait() {
2524 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002525 emit(0x9B);
2526}
2527
2528
2529void Assembler::frndint() {
2530 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002531 emit(0xD9);
2532 emit(0xFC);
2533}
2534
2535
2536void Assembler::fnclex() {
2537 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002538 emit(0xDB);
2539 emit(0xE2);
2540}
2541
2542
2543void Assembler::sahf() {
2544 // TODO(X64): Test for presence. Not all 64-bit intel CPU's have sahf
2545 // in 64-bit mode. Test CpuID.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002546 DCHECK(IsEnabled(SAHF));
Steve Blocka7e24c12009-10-30 11:49:00 +00002547 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002548 emit(0x9E);
2549}
2550
2551
2552void Assembler::emit_farith(int b1, int b2, int i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002553 DCHECK(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2554 DCHECK(is_uint3(i)); // illegal stack offset
Steve Blocka7e24c12009-10-30 11:49:00 +00002555 emit(b1);
2556 emit(b2 + i);
2557}
2558
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002559
2560// SSE operations.
2561
2562void Assembler::andps(XMMRegister dst, XMMRegister src) {
2563 EnsureSpace ensure_space(this);
2564 emit_optional_rex_32(dst, src);
2565 emit(0x0F);
2566 emit(0x54);
2567 emit_sse_operand(dst, src);
2568}
2569
2570
2571void Assembler::andps(XMMRegister dst, const Operand& src) {
2572 EnsureSpace ensure_space(this);
2573 emit_optional_rex_32(dst, src);
2574 emit(0x0F);
2575 emit(0x54);
2576 emit_sse_operand(dst, src);
2577}
2578
2579
2580void Assembler::orps(XMMRegister dst, XMMRegister src) {
2581 EnsureSpace ensure_space(this);
2582 emit_optional_rex_32(dst, src);
2583 emit(0x0F);
2584 emit(0x56);
2585 emit_sse_operand(dst, src);
2586}
2587
2588
2589void Assembler::orps(XMMRegister dst, const Operand& src) {
2590 EnsureSpace ensure_space(this);
2591 emit_optional_rex_32(dst, src);
2592 emit(0x0F);
2593 emit(0x56);
2594 emit_sse_operand(dst, src);
2595}
2596
2597
2598void Assembler::xorps(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002599 DCHECK(!IsEnabled(AVX));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002600 EnsureSpace ensure_space(this);
2601 emit_optional_rex_32(dst, src);
2602 emit(0x0F);
2603 emit(0x57);
2604 emit_sse_operand(dst, src);
2605}
2606
2607
2608void Assembler::xorps(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002609 DCHECK(!IsEnabled(AVX));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002610 EnsureSpace ensure_space(this);
2611 emit_optional_rex_32(dst, src);
2612 emit(0x0F);
2613 emit(0x57);
2614 emit_sse_operand(dst, src);
2615}
2616
2617
2618void Assembler::addps(XMMRegister dst, XMMRegister src) {
2619 EnsureSpace ensure_space(this);
2620 emit_optional_rex_32(dst, src);
2621 emit(0x0F);
2622 emit(0x58);
2623 emit_sse_operand(dst, src);
2624}
2625
2626
2627void Assembler::addps(XMMRegister dst, const Operand& src) {
2628 EnsureSpace ensure_space(this);
2629 emit_optional_rex_32(dst, src);
2630 emit(0x0F);
2631 emit(0x58);
2632 emit_sse_operand(dst, src);
2633}
2634
2635
2636void Assembler::subps(XMMRegister dst, XMMRegister src) {
2637 EnsureSpace ensure_space(this);
2638 emit_optional_rex_32(dst, src);
2639 emit(0x0F);
2640 emit(0x5C);
2641 emit_sse_operand(dst, src);
2642}
2643
2644
2645void Assembler::subps(XMMRegister dst, const Operand& src) {
2646 EnsureSpace ensure_space(this);
2647 emit_optional_rex_32(dst, src);
2648 emit(0x0F);
2649 emit(0x5C);
2650 emit_sse_operand(dst, src);
2651}
2652
2653
2654void Assembler::mulps(XMMRegister dst, XMMRegister src) {
2655 EnsureSpace ensure_space(this);
2656 emit_optional_rex_32(dst, src);
2657 emit(0x0F);
2658 emit(0x59);
2659 emit_sse_operand(dst, src);
2660}
2661
2662
2663void Assembler::mulps(XMMRegister dst, const Operand& src) {
2664 EnsureSpace ensure_space(this);
2665 emit_optional_rex_32(dst, src);
2666 emit(0x0F);
2667 emit(0x59);
2668 emit_sse_operand(dst, src);
2669}
2670
2671
2672void Assembler::divps(XMMRegister dst, XMMRegister src) {
2673 EnsureSpace ensure_space(this);
2674 emit_optional_rex_32(dst, src);
2675 emit(0x0F);
2676 emit(0x5E);
2677 emit_sse_operand(dst, src);
2678}
2679
2680
2681void Assembler::divps(XMMRegister dst, const Operand& src) {
2682 EnsureSpace ensure_space(this);
2683 emit_optional_rex_32(dst, src);
2684 emit(0x0F);
2685 emit(0x5E);
2686 emit_sse_operand(dst, src);
2687}
2688
2689
Andrei Popescu31002712010-02-23 13:46:05 +00002690// SSE 2 operations.
Steve Blocka7e24c12009-10-30 11:49:00 +00002691
Steve Block6ded16b2010-05-10 14:33:55 +01002692void Assembler::movd(XMMRegister dst, Register src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002693 DCHECK(!IsEnabled(AVX));
2694 EnsureSpace ensure_space(this);
2695 emit(0x66);
2696 emit_optional_rex_32(dst, src);
2697 emit(0x0F);
2698 emit(0x6E);
2699 emit_sse_operand(dst, src);
2700}
2701
2702
2703void Assembler::movd(XMMRegister dst, const Operand& src) {
2704 DCHECK(!IsEnabled(AVX));
Steve Block6ded16b2010-05-10 14:33:55 +01002705 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002706 emit(0x66);
2707 emit_optional_rex_32(dst, src);
2708 emit(0x0F);
2709 emit(0x6E);
2710 emit_sse_operand(dst, src);
2711}
2712
2713
2714void Assembler::movd(Register dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002715 DCHECK(!IsEnabled(AVX));
Steve Block6ded16b2010-05-10 14:33:55 +01002716 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002717 emit(0x66);
Ben Murdochbb769b22010-08-11 14:56:33 +01002718 emit_optional_rex_32(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002719 emit(0x0F);
2720 emit(0x7E);
Ben Murdochbb769b22010-08-11 14:56:33 +01002721 emit_sse_operand(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002722}
2723
2724
2725void Assembler::movq(XMMRegister dst, Register src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002726 DCHECK(!IsEnabled(AVX));
Steve Block6ded16b2010-05-10 14:33:55 +01002727 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002728 emit(0x66);
2729 emit_rex_64(dst, src);
2730 emit(0x0F);
2731 emit(0x6E);
2732 emit_sse_operand(dst, src);
2733}
2734
2735
2736void Assembler::movq(Register dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002737 DCHECK(!IsEnabled(AVX));
Steve Block6ded16b2010-05-10 14:33:55 +01002738 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002739 emit(0x66);
Ben Murdochbb769b22010-08-11 14:56:33 +01002740 emit_rex_64(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002741 emit(0x0F);
2742 emit(0x7E);
Ben Murdochbb769b22010-08-11 14:56:33 +01002743 emit_sse_operand(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002744}
2745
2746
Ben Murdoch257744e2011-11-30 15:57:28 +00002747void Assembler::movq(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002748 DCHECK(!IsEnabled(AVX));
Ben Murdoch257744e2011-11-30 15:57:28 +00002749 EnsureSpace ensure_space(this);
2750 if (dst.low_bits() == 4) {
2751 // Avoid unnecessary SIB byte.
2752 emit(0xf3);
2753 emit_optional_rex_32(dst, src);
2754 emit(0x0F);
2755 emit(0x7e);
2756 emit_sse_operand(dst, src);
2757 } else {
2758 emit(0x66);
2759 emit_optional_rex_32(src, dst);
2760 emit(0x0F);
2761 emit(0xD6);
2762 emit_sse_operand(src, dst);
2763 }
2764}
2765
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002766
Ben Murdoch8b112d22011-06-08 16:22:53 +01002767void Assembler::movdqa(const Operand& dst, XMMRegister src) {
2768 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002769 emit(0x66);
2770 emit_rex_64(src, dst);
2771 emit(0x0F);
2772 emit(0x7F);
2773 emit_sse_operand(src, dst);
2774}
2775
2776
2777void Assembler::movdqa(XMMRegister dst, const Operand& src) {
Steve Block1e0659c2011-05-24 12:43:12 +01002778 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002779 emit(0x66);
2780 emit_rex_64(dst, src);
2781 emit(0x0F);
2782 emit(0x6F);
2783 emit_sse_operand(dst, src);
2784}
2785
2786
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002787void Assembler::movdqu(const Operand& dst, XMMRegister src) {
2788 EnsureSpace ensure_space(this);
2789 emit(0xF3);
2790 emit_rex_64(src, dst);
2791 emit(0x0F);
2792 emit(0x7F);
2793 emit_sse_operand(src, dst);
2794}
2795
2796
2797void Assembler::movdqu(XMMRegister dst, const Operand& src) {
2798 EnsureSpace ensure_space(this);
2799 emit(0xF3);
2800 emit_rex_64(dst, src);
2801 emit(0x0F);
2802 emit(0x6F);
2803 emit_sse_operand(dst, src);
2804}
2805
2806
Steve Block6ded16b2010-05-10 14:33:55 +01002807void Assembler::extractps(Register dst, XMMRegister src, byte imm8) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002808 DCHECK(IsEnabled(SSE4_1));
2809 DCHECK(is_uint8(imm8));
Steve Block6ded16b2010-05-10 14:33:55 +01002810 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002811 emit(0x66);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002812 emit_optional_rex_32(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002813 emit(0x0F);
2814 emit(0x3A);
2815 emit(0x17);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002816 emit_sse_operand(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002817 emit(imm8);
2818}
2819
2820
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002821void Assembler::pextrd(Register dst, XMMRegister src, int8_t imm8) {
2822 DCHECK(IsEnabled(SSE4_1));
2823 EnsureSpace ensure_space(this);
2824 emit(0x66);
2825 emit_optional_rex_32(src, dst);
2826 emit(0x0F);
2827 emit(0x3A);
2828 emit(0x16);
2829 emit_sse_operand(src, dst);
2830 emit(imm8);
2831}
2832
2833
2834void Assembler::pinsrd(XMMRegister dst, Register src, int8_t imm8) {
2835 DCHECK(IsEnabled(SSE4_1));
2836 EnsureSpace ensure_space(this);
2837 emit(0x66);
2838 emit_optional_rex_32(dst, src);
2839 emit(0x0F);
2840 emit(0x3A);
2841 emit(0x22);
2842 emit_sse_operand(dst, src);
2843 emit(imm8);
2844}
2845
2846
2847void Assembler::pinsrd(XMMRegister dst, const Operand& src, int8_t imm8) {
2848 DCHECK(IsEnabled(SSE4_1));
2849 EnsureSpace ensure_space(this);
2850 emit(0x66);
2851 emit_optional_rex_32(dst, src);
2852 emit(0x0F);
2853 emit(0x3A);
2854 emit(0x22);
2855 emit_sse_operand(dst, src);
2856 emit(imm8);
2857}
2858
2859
Steve Blocka7e24c12009-10-30 11:49:00 +00002860void Assembler::movsd(const Operand& dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002861 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00002862 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002863 emit(0xF2); // double
2864 emit_optional_rex_32(src, dst);
2865 emit(0x0F);
2866 emit(0x11); // store
2867 emit_sse_operand(src, dst);
2868}
2869
2870
Steve Block3ce2e202009-11-05 08:53:23 +00002871void Assembler::movsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002872 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00002873 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002874 emit(0xF2); // double
2875 emit_optional_rex_32(dst, src);
2876 emit(0x0F);
2877 emit(0x10); // load
2878 emit_sse_operand(dst, src);
2879}
2880
2881
2882void Assembler::movsd(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002883 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00002884 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002885 emit(0xF2); // double
2886 emit_optional_rex_32(dst, src);
2887 emit(0x0F);
2888 emit(0x10); // load
2889 emit_sse_operand(dst, src);
2890}
2891
2892
Ben Murdoch257744e2011-11-30 15:57:28 +00002893void Assembler::movaps(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002894 DCHECK(!IsEnabled(AVX));
Ben Murdoch257744e2011-11-30 15:57:28 +00002895 EnsureSpace ensure_space(this);
2896 if (src.low_bits() == 4) {
2897 // Try to avoid an unnecessary SIB byte.
2898 emit_optional_rex_32(src, dst);
2899 emit(0x0F);
2900 emit(0x29);
2901 emit_sse_operand(src, dst);
2902 } else {
2903 emit_optional_rex_32(dst, src);
2904 emit(0x0F);
2905 emit(0x28);
2906 emit_sse_operand(dst, src);
2907 }
2908}
2909
2910
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002911void Assembler::shufps(XMMRegister dst, XMMRegister src, byte imm8) {
2912 DCHECK(is_uint8(imm8));
2913 EnsureSpace ensure_space(this);
2914 emit_optional_rex_32(src, dst);
2915 emit(0x0F);
2916 emit(0xC6);
2917 emit_sse_operand(dst, src);
2918 emit(imm8);
2919}
2920
2921
Ben Murdoch257744e2011-11-30 15:57:28 +00002922void Assembler::movapd(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002923 DCHECK(!IsEnabled(AVX));
Ben Murdoch257744e2011-11-30 15:57:28 +00002924 EnsureSpace ensure_space(this);
2925 if (src.low_bits() == 4) {
2926 // Try to avoid an unnecessary SIB byte.
2927 emit(0x66);
2928 emit_optional_rex_32(src, dst);
2929 emit(0x0F);
2930 emit(0x29);
2931 emit_sse_operand(src, dst);
2932 } else {
2933 emit(0x66);
2934 emit_optional_rex_32(dst, src);
2935 emit(0x0F);
2936 emit(0x28);
2937 emit_sse_operand(dst, src);
2938 }
2939}
2940
2941
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002942void Assembler::addss(XMMRegister dst, XMMRegister src) {
2943 EnsureSpace ensure_space(this);
2944 emit(0xF3);
2945 emit_optional_rex_32(dst, src);
2946 emit(0x0F);
2947 emit(0x58);
2948 emit_sse_operand(dst, src);
2949}
2950
2951
2952void Assembler::addss(XMMRegister dst, const Operand& src) {
2953 EnsureSpace ensure_space(this);
2954 emit(0xF3);
2955 emit_optional_rex_32(dst, src);
2956 emit(0x0F);
2957 emit(0x58);
2958 emit_sse_operand(dst, src);
2959}
2960
2961
2962void Assembler::subss(XMMRegister dst, XMMRegister src) {
2963 EnsureSpace ensure_space(this);
2964 emit(0xF3);
2965 emit_optional_rex_32(dst, src);
2966 emit(0x0F);
2967 emit(0x5C);
2968 emit_sse_operand(dst, src);
2969}
2970
2971
2972void Assembler::subss(XMMRegister dst, const Operand& src) {
2973 EnsureSpace ensure_space(this);
2974 emit(0xF3);
2975 emit_optional_rex_32(dst, src);
2976 emit(0x0F);
2977 emit(0x5C);
2978 emit_sse_operand(dst, src);
2979}
2980
2981
2982void Assembler::mulss(XMMRegister dst, XMMRegister src) {
2983 EnsureSpace ensure_space(this);
2984 emit(0xF3);
2985 emit_optional_rex_32(dst, src);
2986 emit(0x0F);
2987 emit(0x59);
2988 emit_sse_operand(dst, src);
2989}
2990
2991
2992void Assembler::mulss(XMMRegister dst, const Operand& src) {
2993 EnsureSpace ensure_space(this);
2994 emit(0xF3);
2995 emit_optional_rex_32(dst, src);
2996 emit(0x0F);
2997 emit(0x59);
2998 emit_sse_operand(dst, src);
2999}
3000
3001
3002void Assembler::divss(XMMRegister dst, XMMRegister src) {
3003 EnsureSpace ensure_space(this);
3004 emit(0xF3);
3005 emit_optional_rex_32(dst, src);
3006 emit(0x0F);
3007 emit(0x5E);
3008 emit_sse_operand(dst, src);
3009}
3010
3011
3012void Assembler::divss(XMMRegister dst, const Operand& src) {
3013 EnsureSpace ensure_space(this);
3014 emit(0xF3);
3015 emit_optional_rex_32(dst, src);
3016 emit(0x0F);
3017 emit(0x5E);
3018 emit_sse_operand(dst, src);
3019}
3020
3021
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003022void Assembler::maxss(XMMRegister dst, XMMRegister src) {
3023 EnsureSpace ensure_space(this);
3024 emit(0xF3);
3025 emit_optional_rex_32(dst, src);
3026 emit(0x0F);
3027 emit(0x5F);
3028 emit_sse_operand(dst, src);
3029}
3030
3031
3032void Assembler::maxss(XMMRegister dst, const Operand& src) {
3033 EnsureSpace ensure_space(this);
3034 emit(0xF3);
3035 emit_optional_rex_32(dst, src);
3036 emit(0x0F);
3037 emit(0x5F);
3038 emit_sse_operand(dst, src);
3039}
3040
3041
3042void Assembler::minss(XMMRegister dst, XMMRegister src) {
3043 EnsureSpace ensure_space(this);
3044 emit(0xF3);
3045 emit_optional_rex_32(dst, src);
3046 emit(0x0F);
3047 emit(0x5D);
3048 emit_sse_operand(dst, src);
3049}
3050
3051
3052void Assembler::minss(XMMRegister dst, const Operand& src) {
3053 EnsureSpace ensure_space(this);
3054 emit(0xF3);
3055 emit_optional_rex_32(dst, src);
3056 emit(0x0F);
3057 emit(0x5D);
3058 emit_sse_operand(dst, src);
3059}
3060
3061
3062void Assembler::sqrtss(XMMRegister dst, XMMRegister src) {
3063 EnsureSpace ensure_space(this);
3064 emit(0xF3);
3065 emit_optional_rex_32(dst, src);
3066 emit(0x0F);
3067 emit(0x51);
3068 emit_sse_operand(dst, src);
3069}
3070
3071
3072void Assembler::sqrtss(XMMRegister dst, const Operand& src) {
3073 EnsureSpace ensure_space(this);
3074 emit(0xF3);
3075 emit_optional_rex_32(dst, src);
3076 emit(0x0F);
3077 emit(0x51);
3078 emit_sse_operand(dst, src);
3079}
3080
3081
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003082void Assembler::ucomiss(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003083 DCHECK(!IsEnabled(AVX));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003084 EnsureSpace ensure_space(this);
3085 emit_optional_rex_32(dst, src);
3086 emit(0x0f);
3087 emit(0x2e);
3088 emit_sse_operand(dst, src);
3089}
3090
3091
3092void Assembler::ucomiss(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003093 DCHECK(!IsEnabled(AVX));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003094 EnsureSpace ensure_space(this);
3095 emit_optional_rex_32(dst, src);
3096 emit(0x0f);
3097 emit(0x2e);
3098 emit_sse_operand(dst, src);
3099}
3100
3101
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003102void Assembler::movss(XMMRegister dst, XMMRegister src) {
3103 DCHECK(!IsEnabled(AVX));
3104 EnsureSpace ensure_space(this);
3105 emit(0xF3); // single
3106 emit_optional_rex_32(dst, src);
3107 emit(0x0F);
3108 emit(0x10); // load
3109 emit_sse_operand(dst, src);
3110}
3111
3112
Steve Block8defd9f2010-07-08 12:39:36 +01003113void Assembler::movss(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003114 DCHECK(!IsEnabled(AVX));
Steve Block8defd9f2010-07-08 12:39:36 +01003115 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003116 emit(0xF3); // single
3117 emit_optional_rex_32(dst, src);
3118 emit(0x0F);
3119 emit(0x10); // load
3120 emit_sse_operand(dst, src);
3121}
3122
3123
3124void Assembler::movss(const Operand& src, XMMRegister dst) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003125 DCHECK(!IsEnabled(AVX));
Steve Block8defd9f2010-07-08 12:39:36 +01003126 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003127 emit(0xF3); // single
3128 emit_optional_rex_32(dst, src);
3129 emit(0x0F);
3130 emit(0x11); // store
3131 emit_sse_operand(dst, src);
3132}
3133
3134
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003135void Assembler::psllq(XMMRegister reg, byte imm8) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003136 DCHECK(!IsEnabled(AVX));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003137 EnsureSpace ensure_space(this);
3138 emit(0x66);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003139 emit_optional_rex_32(reg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003140 emit(0x0F);
3141 emit(0x73);
3142 emit_sse_operand(rsi, reg); // rsi == 6
3143 emit(imm8);
3144}
3145
3146
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003147void Assembler::psrlq(XMMRegister reg, byte imm8) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003148 DCHECK(!IsEnabled(AVX));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003149 EnsureSpace ensure_space(this);
3150 emit(0x66);
3151 emit_optional_rex_32(reg);
3152 emit(0x0F);
3153 emit(0x73);
3154 emit_sse_operand(rdx, reg); // rdx == 2
3155 emit(imm8);
3156}
3157
3158
3159void Assembler::pslld(XMMRegister reg, byte imm8) {
3160 EnsureSpace ensure_space(this);
3161 emit(0x66);
3162 emit_optional_rex_32(reg);
3163 emit(0x0F);
3164 emit(0x72);
3165 emit_sse_operand(rsi, reg); // rsi == 6
3166 emit(imm8);
3167}
3168
3169
3170void Assembler::psrld(XMMRegister reg, byte imm8) {
3171 EnsureSpace ensure_space(this);
3172 emit(0x66);
3173 emit_optional_rex_32(reg);
3174 emit(0x0F);
3175 emit(0x72);
3176 emit_sse_operand(rdx, reg); // rdx == 2
3177 emit(imm8);
3178}
3179
3180
Steve Blocka7e24c12009-10-30 11:49:00 +00003181void Assembler::cvttss2si(Register dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003182 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00003183 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003184 emit(0xF3);
3185 emit_optional_rex_32(dst, src);
3186 emit(0x0F);
3187 emit(0x2C);
3188 emit_operand(dst, src);
3189}
3190
3191
Steve Block1e0659c2011-05-24 12:43:12 +01003192void Assembler::cvttss2si(Register dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003193 DCHECK(!IsEnabled(AVX));
Steve Block1e0659c2011-05-24 12:43:12 +01003194 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01003195 emit(0xF3);
3196 emit_optional_rex_32(dst, src);
3197 emit(0x0F);
3198 emit(0x2C);
3199 emit_sse_operand(dst, src);
3200}
3201
3202
Steve Blocka7e24c12009-10-30 11:49:00 +00003203void Assembler::cvttsd2si(Register dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003204 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00003205 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003206 emit(0xF2);
3207 emit_optional_rex_32(dst, src);
3208 emit(0x0F);
3209 emit(0x2C);
3210 emit_operand(dst, src);
3211}
3212
3213
Steve Block1e0659c2011-05-24 12:43:12 +01003214void Assembler::cvttsd2si(Register dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003215 DCHECK(!IsEnabled(AVX));
Steve Block1e0659c2011-05-24 12:43:12 +01003216 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01003217 emit(0xF2);
3218 emit_optional_rex_32(dst, src);
3219 emit(0x0F);
3220 emit(0x2C);
3221 emit_sse_operand(dst, src);
3222}
3223
3224
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003225void Assembler::cvttss2siq(Register dst, XMMRegister src) {
3226 DCHECK(!IsEnabled(AVX));
3227 EnsureSpace ensure_space(this);
3228 emit(0xF3);
3229 emit_rex_64(dst, src);
3230 emit(0x0F);
3231 emit(0x2C);
3232 emit_sse_operand(dst, src);
3233}
3234
3235
3236void Assembler::cvttss2siq(Register dst, const Operand& src) {
3237 DCHECK(!IsEnabled(AVX));
3238 EnsureSpace ensure_space(this);
3239 emit(0xF3);
3240 emit_rex_64(dst, src);
3241 emit(0x0F);
3242 emit(0x2C);
3243 emit_sse_operand(dst, src);
3244}
3245
3246
Kristian Monsen25f61362010-05-21 11:50:48 +01003247void Assembler::cvttsd2siq(Register dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003248 DCHECK(!IsEnabled(AVX));
Kristian Monsen25f61362010-05-21 11:50:48 +01003249 EnsureSpace ensure_space(this);
Kristian Monsen25f61362010-05-21 11:50:48 +01003250 emit(0xF2);
3251 emit_rex_64(dst, src);
3252 emit(0x0F);
3253 emit(0x2C);
3254 emit_sse_operand(dst, src);
3255}
3256
3257
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003258void Assembler::cvttsd2siq(Register dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003259 DCHECK(!IsEnabled(AVX));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003260 EnsureSpace ensure_space(this);
3261 emit(0xF2);
3262 emit_rex_64(dst, src);
3263 emit(0x0F);
3264 emit(0x2C);
3265 emit_sse_operand(dst, src);
3266}
3267
3268
Steve Blocka7e24c12009-10-30 11:49:00 +00003269void Assembler::cvtlsi2sd(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003270 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00003271 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003272 emit(0xF2);
3273 emit_optional_rex_32(dst, src);
3274 emit(0x0F);
3275 emit(0x2A);
3276 emit_sse_operand(dst, src);
3277}
3278
3279
3280void Assembler::cvtlsi2sd(XMMRegister dst, Register src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003281 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00003282 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003283 emit(0xF2);
3284 emit_optional_rex_32(dst, src);
3285 emit(0x0F);
3286 emit(0x2A);
3287 emit_sse_operand(dst, src);
3288}
3289
3290
Ben Murdoch097c5b22016-05-18 11:27:45 +01003291void Assembler::cvtlsi2ss(XMMRegister dst, const Operand& src) {
3292 DCHECK(!IsEnabled(AVX));
3293 EnsureSpace ensure_space(this);
3294 emit(0xF3);
3295 emit_optional_rex_32(dst, src);
3296 emit(0x0F);
3297 emit(0x2A);
3298 emit_sse_operand(dst, src);
3299}
3300
3301
Steve Block8defd9f2010-07-08 12:39:36 +01003302void Assembler::cvtlsi2ss(XMMRegister dst, Register src) {
3303 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003304 emit(0xF3);
3305 emit_optional_rex_32(dst, src);
3306 emit(0x0F);
3307 emit(0x2A);
3308 emit_sse_operand(dst, src);
3309}
3310
3311
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003312void Assembler::cvtqsi2ss(XMMRegister dst, const Operand& src) {
3313 DCHECK(!IsEnabled(AVX));
3314 EnsureSpace ensure_space(this);
3315 emit(0xF3);
3316 emit_rex_64(dst, src);
3317 emit(0x0F);
3318 emit(0x2A);
3319 emit_sse_operand(dst, src);
3320}
3321
3322
3323void Assembler::cvtqsi2ss(XMMRegister dst, Register src) {
3324 DCHECK(!IsEnabled(AVX));
3325 EnsureSpace ensure_space(this);
3326 emit(0xF3);
3327 emit_rex_64(dst, src);
3328 emit(0x0F);
3329 emit(0x2A);
3330 emit_sse_operand(dst, src);
3331}
3332
3333
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003334void Assembler::cvtqsi2sd(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003335 DCHECK(!IsEnabled(AVX));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003336 EnsureSpace ensure_space(this);
3337 emit(0xF2);
3338 emit_rex_64(dst, src);
3339 emit(0x0F);
3340 emit(0x2A);
3341 emit_sse_operand(dst, src);
3342}
3343
3344
Steve Blocka7e24c12009-10-30 11:49:00 +00003345void Assembler::cvtqsi2sd(XMMRegister dst, Register src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003346 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00003347 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003348 emit(0xF2);
3349 emit_rex_64(dst, src);
3350 emit(0x0F);
3351 emit(0x2A);
3352 emit_sse_operand(dst, src);
3353}
3354
3355
Steve Block6ded16b2010-05-10 14:33:55 +01003356void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003357 DCHECK(!IsEnabled(AVX));
Steve Block6ded16b2010-05-10 14:33:55 +01003358 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01003359 emit(0xF3);
3360 emit_optional_rex_32(dst, src);
3361 emit(0x0F);
3362 emit(0x5A);
3363 emit_sse_operand(dst, src);
3364}
3365
3366
Steve Block8defd9f2010-07-08 12:39:36 +01003367void Assembler::cvtss2sd(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003368 DCHECK(!IsEnabled(AVX));
Steve Block8defd9f2010-07-08 12:39:36 +01003369 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003370 emit(0xF3);
3371 emit_optional_rex_32(dst, src);
3372 emit(0x0F);
3373 emit(0x5A);
3374 emit_sse_operand(dst, src);
3375}
3376
3377
3378void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003379 DCHECK(!IsEnabled(AVX));
Steve Block8defd9f2010-07-08 12:39:36 +01003380 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003381 emit(0xF2);
3382 emit_optional_rex_32(dst, src);
3383 emit(0x0F);
3384 emit(0x5A);
3385 emit_sse_operand(dst, src);
3386}
3387
3388
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003389void Assembler::cvtsd2ss(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003390 DCHECK(!IsEnabled(AVX));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003391 EnsureSpace ensure_space(this);
3392 emit(0xF2);
3393 emit_optional_rex_32(dst, src);
3394 emit(0x0F);
3395 emit(0x5A);
3396 emit_sse_operand(dst, src);
3397}
3398
3399
Steve Block8defd9f2010-07-08 12:39:36 +01003400void Assembler::cvtsd2si(Register dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003401 DCHECK(!IsEnabled(AVX));
Steve Block8defd9f2010-07-08 12:39:36 +01003402 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003403 emit(0xF2);
3404 emit_optional_rex_32(dst, src);
3405 emit(0x0F);
3406 emit(0x2D);
3407 emit_sse_operand(dst, src);
3408}
3409
3410
3411void Assembler::cvtsd2siq(Register dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003412 DCHECK(!IsEnabled(AVX));
Steve Block8defd9f2010-07-08 12:39:36 +01003413 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003414 emit(0xF2);
3415 emit_rex_64(dst, src);
3416 emit(0x0F);
3417 emit(0x2D);
3418 emit_sse_operand(dst, src);
3419}
3420
3421
Steve Blocka7e24c12009-10-30 11:49:00 +00003422void Assembler::addsd(XMMRegister dst, XMMRegister src) {
3423 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003424 emit(0xF2);
3425 emit_optional_rex_32(dst, src);
3426 emit(0x0F);
3427 emit(0x58);
3428 emit_sse_operand(dst, src);
3429}
3430
3431
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003432void Assembler::addsd(XMMRegister dst, const Operand& src) {
3433 EnsureSpace ensure_space(this);
3434 emit(0xF2);
3435 emit_optional_rex_32(dst, src);
3436 emit(0x0F);
3437 emit(0x58);
3438 emit_sse_operand(dst, src);
3439}
3440
3441
Steve Blocka7e24c12009-10-30 11:49:00 +00003442void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
3443 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003444 emit(0xF2);
3445 emit_optional_rex_32(dst, src);
3446 emit(0x0F);
3447 emit(0x59);
3448 emit_sse_operand(dst, src);
3449}
3450
3451
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003452void Assembler::mulsd(XMMRegister dst, const Operand& src) {
3453 EnsureSpace ensure_space(this);
3454 emit(0xF2);
3455 emit_optional_rex_32(dst, src);
3456 emit(0x0F);
3457 emit(0x59);
3458 emit_sse_operand(dst, src);
3459}
3460
3461
Steve Blocka7e24c12009-10-30 11:49:00 +00003462void Assembler::subsd(XMMRegister dst, XMMRegister src) {
3463 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003464 emit(0xF2);
3465 emit_optional_rex_32(dst, src);
3466 emit(0x0F);
3467 emit(0x5C);
3468 emit_sse_operand(dst, src);
3469}
3470
3471
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003472void Assembler::subsd(XMMRegister dst, const Operand& src) {
3473 EnsureSpace ensure_space(this);
3474 emit(0xF2);
3475 emit_optional_rex_32(dst, src);
3476 emit(0x0F);
3477 emit(0x5C);
3478 emit_sse_operand(dst, src);
3479}
3480
3481
Steve Blocka7e24c12009-10-30 11:49:00 +00003482void Assembler::divsd(XMMRegister dst, XMMRegister src) {
3483 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003484 emit(0xF2);
3485 emit_optional_rex_32(dst, src);
3486 emit(0x0F);
3487 emit(0x5E);
3488 emit_sse_operand(dst, src);
3489}
3490
3491
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003492void Assembler::divsd(XMMRegister dst, const Operand& src) {
3493 EnsureSpace ensure_space(this);
3494 emit(0xF2);
3495 emit_optional_rex_32(dst, src);
3496 emit(0x0F);
3497 emit(0x5E);
3498 emit_sse_operand(dst, src);
3499}
3500
3501
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003502void Assembler::maxsd(XMMRegister dst, XMMRegister src) {
3503 EnsureSpace ensure_space(this);
3504 emit(0xF2);
3505 emit_optional_rex_32(dst, src);
3506 emit(0x0F);
3507 emit(0x5F);
3508 emit_sse_operand(dst, src);
3509}
3510
3511
3512void Assembler::maxsd(XMMRegister dst, const Operand& src) {
3513 EnsureSpace ensure_space(this);
3514 emit(0xF2);
3515 emit_optional_rex_32(dst, src);
3516 emit(0x0F);
3517 emit(0x5F);
3518 emit_sse_operand(dst, src);
3519}
3520
3521
3522void Assembler::minsd(XMMRegister dst, XMMRegister src) {
3523 EnsureSpace ensure_space(this);
3524 emit(0xF2);
3525 emit_optional_rex_32(dst, src);
3526 emit(0x0F);
3527 emit(0x5D);
3528 emit_sse_operand(dst, src);
3529}
3530
3531
3532void Assembler::minsd(XMMRegister dst, const Operand& src) {
3533 EnsureSpace ensure_space(this);
3534 emit(0xF2);
3535 emit_optional_rex_32(dst, src);
3536 emit(0x0F);
3537 emit(0x5D);
3538 emit_sse_operand(dst, src);
3539}
3540
3541
Ben Murdoche0cee9b2011-05-25 10:26:03 +01003542void Assembler::andpd(XMMRegister dst, XMMRegister src) {
3543 EnsureSpace ensure_space(this);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01003544 emit(0x66);
3545 emit_optional_rex_32(dst, src);
3546 emit(0x0F);
3547 emit(0x54);
3548 emit_sse_operand(dst, src);
3549}
3550
3551
3552void Assembler::orpd(XMMRegister dst, XMMRegister src) {
3553 EnsureSpace ensure_space(this);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01003554 emit(0x66);
3555 emit_optional_rex_32(dst, src);
3556 emit(0x0F);
3557 emit(0x56);
3558 emit_sse_operand(dst, src);
3559}
3560
3561
Andrei Popescu402d9372010-02-26 13:31:12 +00003562void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003563 DCHECK(!IsEnabled(AVX));
Andrei Popescu402d9372010-02-26 13:31:12 +00003564 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003565 emit(0x66);
3566 emit_optional_rex_32(dst, src);
Steve Block6ded16b2010-05-10 14:33:55 +01003567 emit(0x0F);
Andrei Popescu402d9372010-02-26 13:31:12 +00003568 emit(0x57);
3569 emit_sse_operand(dst, src);
3570}
3571
3572
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003573void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003574 DCHECK(!IsEnabled(AVX));
Ben Murdoch257744e2011-11-30 15:57:28 +00003575 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003576 emit(0xF2);
Ben Murdoch257744e2011-11-30 15:57:28 +00003577 emit_optional_rex_32(dst, src);
3578 emit(0x0F);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003579 emit(0x51);
Ben Murdoch257744e2011-11-30 15:57:28 +00003580 emit_sse_operand(dst, src);
3581}
3582
3583
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003584void Assembler::sqrtsd(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003585 DCHECK(!IsEnabled(AVX));
Steve Block6ded16b2010-05-10 14:33:55 +01003586 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01003587 emit(0xF2);
3588 emit_optional_rex_32(dst, src);
3589 emit(0x0F);
3590 emit(0x51);
3591 emit_sse_operand(dst, src);
3592}
3593
3594
Andrei Popescu402d9372010-02-26 13:31:12 +00003595void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003596 DCHECK(!IsEnabled(AVX));
Andrei Popescu402d9372010-02-26 13:31:12 +00003597 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003598 emit(0x66);
3599 emit_optional_rex_32(dst, src);
3600 emit(0x0f);
3601 emit(0x2e);
3602 emit_sse_operand(dst, src);
3603}
3604
Steve Blocka7e24c12009-10-30 11:49:00 +00003605
Steve Block8defd9f2010-07-08 12:39:36 +01003606void Assembler::ucomisd(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003607 DCHECK(!IsEnabled(AVX));
Steve Block8defd9f2010-07-08 12:39:36 +01003608 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003609 emit(0x66);
3610 emit_optional_rex_32(dst, src);
3611 emit(0x0f);
3612 emit(0x2e);
3613 emit_sse_operand(dst, src);
3614}
3615
3616
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003617void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
3618 EnsureSpace ensure_space(this);
3619 emit(0xF2);
3620 emit_optional_rex_32(dst, src);
3621 emit(0x0F);
3622 emit(0xC2);
3623 emit_sse_operand(dst, src);
3624 emit(0x01); // LT == 1
3625}
3626
3627
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003628void Assembler::roundss(XMMRegister dst, XMMRegister src, RoundingMode mode) {
3629 DCHECK(!IsEnabled(AVX));
3630 DCHECK(IsEnabled(SSE4_1));
3631 EnsureSpace ensure_space(this);
3632 emit(0x66);
3633 emit_optional_rex_32(dst, src);
3634 emit(0x0f);
3635 emit(0x3a);
3636 emit(0x0a);
3637 emit_sse_operand(dst, src);
3638 // Mask precision exception.
3639 emit(static_cast<byte>(mode) | 0x8);
3640}
3641
3642
3643void Assembler::roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode) {
3644 DCHECK(!IsEnabled(AVX));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003645 DCHECK(IsEnabled(SSE4_1));
Ben Murdoch257744e2011-11-30 15:57:28 +00003646 EnsureSpace ensure_space(this);
3647 emit(0x66);
3648 emit_optional_rex_32(dst, src);
3649 emit(0x0f);
3650 emit(0x3a);
3651 emit(0x0b);
3652 emit_sse_operand(dst, src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003653 // Mask precision exception.
Ben Murdoch257744e2011-11-30 15:57:28 +00003654 emit(static_cast<byte>(mode) | 0x8);
3655}
3656
3657
Steve Block1e0659c2011-05-24 12:43:12 +01003658void Assembler::movmskpd(Register dst, XMMRegister src) {
3659 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01003660 emit(0x66);
3661 emit_optional_rex_32(dst, src);
3662 emit(0x0f);
3663 emit(0x50);
3664 emit_sse_operand(dst, src);
3665}
3666
Steve Block8defd9f2010-07-08 12:39:36 +01003667
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003668void Assembler::movmskps(Register dst, XMMRegister src) {
3669 EnsureSpace ensure_space(this);
3670 emit_optional_rex_32(dst, src);
3671 emit(0x0f);
3672 emit(0x50);
3673 emit_sse_operand(dst, src);
3674}
3675
3676
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003677void Assembler::pcmpeqd(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003678 DCHECK(!IsEnabled(AVX));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003679 EnsureSpace ensure_space(this);
3680 emit(0x66);
3681 emit_optional_rex_32(dst, src);
3682 emit(0x0F);
3683 emit(0x76);
3684 emit_sse_operand(dst, src);
3685}
3686
3687
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003688void Assembler::punpckldq(XMMRegister dst, XMMRegister src) {
3689 EnsureSpace ensure_space(this);
3690 emit(0x66);
3691 emit_optional_rex_32(dst, src);
3692 emit(0x0F);
3693 emit(0x62);
3694 emit_sse_operand(dst, src);
3695}
3696
3697
3698void Assembler::punpckhdq(XMMRegister dst, XMMRegister src) {
3699 EnsureSpace ensure_space(this);
3700 emit(0x66);
3701 emit_optional_rex_32(dst, src);
3702 emit(0x0F);
3703 emit(0x6A);
3704 emit_sse_operand(dst, src);
3705}
3706
3707
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003708// AVX instructions
3709void Assembler::vfmasd(byte op, XMMRegister dst, XMMRegister src1,
3710 XMMRegister src2) {
3711 DCHECK(IsEnabled(FMA3));
3712 EnsureSpace ensure_space(this);
3713 emit_vex_prefix(dst, src1, src2, kLIG, k66, k0F38, kW1);
3714 emit(op);
3715 emit_sse_operand(dst, src2);
3716}
3717
3718
3719void Assembler::vfmasd(byte op, XMMRegister dst, XMMRegister src1,
3720 const Operand& src2) {
3721 DCHECK(IsEnabled(FMA3));
3722 EnsureSpace ensure_space(this);
3723 emit_vex_prefix(dst, src1, src2, kLIG, k66, k0F38, kW1);
3724 emit(op);
3725 emit_sse_operand(dst, src2);
3726}
3727
3728
3729void Assembler::vfmass(byte op, XMMRegister dst, XMMRegister src1,
3730 XMMRegister src2) {
3731 DCHECK(IsEnabled(FMA3));
3732 EnsureSpace ensure_space(this);
3733 emit_vex_prefix(dst, src1, src2, kLIG, k66, k0F38, kW0);
3734 emit(op);
3735 emit_sse_operand(dst, src2);
3736}
3737
3738
3739void Assembler::vfmass(byte op, XMMRegister dst, XMMRegister src1,
3740 const Operand& src2) {
3741 DCHECK(IsEnabled(FMA3));
3742 EnsureSpace ensure_space(this);
3743 emit_vex_prefix(dst, src1, src2, kLIG, k66, k0F38, kW0);
3744 emit(op);
3745 emit_sse_operand(dst, src2);
3746}
3747
3748
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003749void Assembler::vmovd(XMMRegister dst, Register src) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003750 DCHECK(IsEnabled(AVX));
3751 EnsureSpace ensure_space(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003752 XMMRegister isrc = {src.code()};
3753 emit_vex_prefix(dst, xmm0, isrc, kL128, k66, k0F, kW0);
3754 emit(0x6e);
3755 emit_sse_operand(dst, src);
3756}
3757
3758
3759void Assembler::vmovd(XMMRegister dst, const Operand& src) {
3760 DCHECK(IsEnabled(AVX));
3761 EnsureSpace ensure_space(this);
3762 emit_vex_prefix(dst, xmm0, src, kL128, k66, k0F, kW0);
3763 emit(0x6e);
3764 emit_sse_operand(dst, src);
3765}
3766
3767
3768void Assembler::vmovd(Register dst, XMMRegister src) {
3769 DCHECK(IsEnabled(AVX));
3770 EnsureSpace ensure_space(this);
3771 XMMRegister idst = {dst.code()};
3772 emit_vex_prefix(src, xmm0, idst, kL128, k66, k0F, kW0);
3773 emit(0x7e);
3774 emit_sse_operand(src, dst);
3775}
3776
3777
3778void Assembler::vmovq(XMMRegister dst, Register src) {
3779 DCHECK(IsEnabled(AVX));
3780 EnsureSpace ensure_space(this);
3781 XMMRegister isrc = {src.code()};
3782 emit_vex_prefix(dst, xmm0, isrc, kL128, k66, k0F, kW1);
3783 emit(0x6e);
3784 emit_sse_operand(dst, src);
3785}
3786
3787
3788void Assembler::vmovq(XMMRegister dst, const Operand& src) {
3789 DCHECK(IsEnabled(AVX));
3790 EnsureSpace ensure_space(this);
3791 emit_vex_prefix(dst, xmm0, src, kL128, k66, k0F, kW1);
3792 emit(0x6e);
3793 emit_sse_operand(dst, src);
3794}
3795
3796
3797void Assembler::vmovq(Register dst, XMMRegister src) {
3798 DCHECK(IsEnabled(AVX));
3799 EnsureSpace ensure_space(this);
3800 XMMRegister idst = {dst.code()};
3801 emit_vex_prefix(src, xmm0, idst, kL128, k66, k0F, kW1);
3802 emit(0x7e);
3803 emit_sse_operand(src, dst);
3804}
3805
3806
3807void Assembler::vsd(byte op, XMMRegister dst, XMMRegister src1,
3808 XMMRegister src2, SIMDPrefix pp, LeadingOpcode m, VexW w) {
3809 DCHECK(IsEnabled(AVX));
3810 EnsureSpace ensure_space(this);
3811 emit_vex_prefix(dst, src1, src2, kLIG, pp, m, w);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003812 emit(op);
3813 emit_sse_operand(dst, src2);
3814}
3815
3816
3817void Assembler::vsd(byte op, XMMRegister dst, XMMRegister src1,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003818 const Operand& src2, SIMDPrefix pp, LeadingOpcode m,
3819 VexW w) {
3820 DCHECK(IsEnabled(AVX));
3821 EnsureSpace ensure_space(this);
3822 emit_vex_prefix(dst, src1, src2, kLIG, pp, m, w);
3823 emit(op);
3824 emit_sse_operand(dst, src2);
3825}
3826
3827
3828void Assembler::vps(byte op, XMMRegister dst, XMMRegister src1,
3829 XMMRegister src2) {
3830 DCHECK(IsEnabled(AVX));
3831 EnsureSpace ensure_space(this);
3832 emit_vex_prefix(dst, src1, src2, kL128, kNone, k0F, kWIG);
3833 emit(op);
3834 emit_sse_operand(dst, src2);
3835}
3836
3837
3838void Assembler::vps(byte op, XMMRegister dst, XMMRegister src1,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003839 const Operand& src2) {
3840 DCHECK(IsEnabled(AVX));
3841 EnsureSpace ensure_space(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003842 emit_vex_prefix(dst, src1, src2, kL128, kNone, k0F, kWIG);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003843 emit(op);
3844 emit_sse_operand(dst, src2);
3845}
3846
3847
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003848void Assembler::vpd(byte op, XMMRegister dst, XMMRegister src1,
3849 XMMRegister src2) {
3850 DCHECK(IsEnabled(AVX));
3851 EnsureSpace ensure_space(this);
3852 emit_vex_prefix(dst, src1, src2, kL128, k66, k0F, kWIG);
3853 emit(op);
3854 emit_sse_operand(dst, src2);
3855}
3856
3857
3858void Assembler::vpd(byte op, XMMRegister dst, XMMRegister src1,
3859 const Operand& src2) {
3860 DCHECK(IsEnabled(AVX));
3861 EnsureSpace ensure_space(this);
3862 emit_vex_prefix(dst, src1, src2, kL128, k66, k0F, kWIG);
3863 emit(op);
3864 emit_sse_operand(dst, src2);
3865}
3866
3867
3868void Assembler::vucomiss(XMMRegister dst, XMMRegister src) {
3869 DCHECK(IsEnabled(AVX));
3870 EnsureSpace ensure_space(this);
3871 emit_vex_prefix(dst, xmm0, src, kLIG, kNone, k0F, kWIG);
3872 emit(0x2e);
3873 emit_sse_operand(dst, src);
3874}
3875
3876
3877void Assembler::vucomiss(XMMRegister dst, const Operand& src) {
3878 DCHECK(IsEnabled(AVX));
3879 EnsureSpace ensure_space(this);
3880 emit_vex_prefix(dst, xmm0, src, kLIG, kNone, k0F, kWIG);
3881 emit(0x2e);
3882 emit_sse_operand(dst, src);
3883}
3884
3885
3886void Assembler::vss(byte op, XMMRegister dst, XMMRegister src1,
3887 XMMRegister src2) {
3888 DCHECK(IsEnabled(AVX));
3889 EnsureSpace ensure_space(this);
3890 emit_vex_prefix(dst, src1, src2, kLIG, kF3, k0F, kWIG);
3891 emit(op);
3892 emit_sse_operand(dst, src2);
3893}
3894
3895
3896void Assembler::vss(byte op, XMMRegister dst, XMMRegister src1,
3897 const Operand& src2) {
3898 DCHECK(IsEnabled(AVX));
3899 EnsureSpace ensure_space(this);
3900 emit_vex_prefix(dst, src1, src2, kLIG, kF3, k0F, kWIG);
3901 emit(op);
3902 emit_sse_operand(dst, src2);
3903}
3904
3905
3906void Assembler::bmi1q(byte op, Register reg, Register vreg, Register rm) {
3907 DCHECK(IsEnabled(BMI1));
3908 EnsureSpace ensure_space(this);
3909 emit_vex_prefix(reg, vreg, rm, kLZ, kNone, k0F38, kW1);
3910 emit(op);
3911 emit_modrm(reg, rm);
3912}
3913
3914
3915void Assembler::bmi1q(byte op, Register reg, Register vreg, const Operand& rm) {
3916 DCHECK(IsEnabled(BMI1));
3917 EnsureSpace ensure_space(this);
3918 emit_vex_prefix(reg, vreg, rm, kLZ, kNone, k0F38, kW1);
3919 emit(op);
3920 emit_operand(reg, rm);
3921}
3922
3923
3924void Assembler::bmi1l(byte op, Register reg, Register vreg, Register rm) {
3925 DCHECK(IsEnabled(BMI1));
3926 EnsureSpace ensure_space(this);
3927 emit_vex_prefix(reg, vreg, rm, kLZ, kNone, k0F38, kW0);
3928 emit(op);
3929 emit_modrm(reg, rm);
3930}
3931
3932
3933void Assembler::bmi1l(byte op, Register reg, Register vreg, const Operand& rm) {
3934 DCHECK(IsEnabled(BMI1));
3935 EnsureSpace ensure_space(this);
3936 emit_vex_prefix(reg, vreg, rm, kLZ, kNone, k0F38, kW0);
3937 emit(op);
3938 emit_operand(reg, rm);
3939}
3940
3941
3942void Assembler::tzcntq(Register dst, Register src) {
3943 DCHECK(IsEnabled(BMI1));
3944 EnsureSpace ensure_space(this);
3945 emit(0xF3);
3946 emit_rex_64(dst, src);
3947 emit(0x0F);
3948 emit(0xBC);
3949 emit_modrm(dst, src);
3950}
3951
3952
3953void Assembler::tzcntq(Register dst, const Operand& src) {
3954 DCHECK(IsEnabled(BMI1));
3955 EnsureSpace ensure_space(this);
3956 emit(0xF3);
3957 emit_rex_64(dst, src);
3958 emit(0x0F);
3959 emit(0xBC);
3960 emit_operand(dst, src);
3961}
3962
3963
3964void Assembler::tzcntl(Register dst, Register src) {
3965 DCHECK(IsEnabled(BMI1));
3966 EnsureSpace ensure_space(this);
3967 emit(0xF3);
3968 emit_optional_rex_32(dst, src);
3969 emit(0x0F);
3970 emit(0xBC);
3971 emit_modrm(dst, src);
3972}
3973
3974
3975void Assembler::tzcntl(Register dst, const Operand& src) {
3976 DCHECK(IsEnabled(BMI1));
3977 EnsureSpace ensure_space(this);
3978 emit(0xF3);
3979 emit_optional_rex_32(dst, src);
3980 emit(0x0F);
3981 emit(0xBC);
3982 emit_operand(dst, src);
3983}
3984
3985
3986void Assembler::lzcntq(Register dst, Register src) {
3987 DCHECK(IsEnabled(LZCNT));
3988 EnsureSpace ensure_space(this);
3989 emit(0xF3);
3990 emit_rex_64(dst, src);
3991 emit(0x0F);
3992 emit(0xBD);
3993 emit_modrm(dst, src);
3994}
3995
3996
3997void Assembler::lzcntq(Register dst, const Operand& src) {
3998 DCHECK(IsEnabled(LZCNT));
3999 EnsureSpace ensure_space(this);
4000 emit(0xF3);
4001 emit_rex_64(dst, src);
4002 emit(0x0F);
4003 emit(0xBD);
4004 emit_operand(dst, src);
4005}
4006
4007
4008void Assembler::lzcntl(Register dst, Register src) {
4009 DCHECK(IsEnabled(LZCNT));
4010 EnsureSpace ensure_space(this);
4011 emit(0xF3);
4012 emit_optional_rex_32(dst, src);
4013 emit(0x0F);
4014 emit(0xBD);
4015 emit_modrm(dst, src);
4016}
4017
4018
4019void Assembler::lzcntl(Register dst, const Operand& src) {
4020 DCHECK(IsEnabled(LZCNT));
4021 EnsureSpace ensure_space(this);
4022 emit(0xF3);
4023 emit_optional_rex_32(dst, src);
4024 emit(0x0F);
4025 emit(0xBD);
4026 emit_operand(dst, src);
4027}
4028
4029
4030void Assembler::popcntq(Register dst, Register src) {
4031 DCHECK(IsEnabled(POPCNT));
4032 EnsureSpace ensure_space(this);
4033 emit(0xF3);
4034 emit_rex_64(dst, src);
4035 emit(0x0F);
4036 emit(0xB8);
4037 emit_modrm(dst, src);
4038}
4039
4040
4041void Assembler::popcntq(Register dst, const Operand& src) {
4042 DCHECK(IsEnabled(POPCNT));
4043 EnsureSpace ensure_space(this);
4044 emit(0xF3);
4045 emit_rex_64(dst, src);
4046 emit(0x0F);
4047 emit(0xB8);
4048 emit_operand(dst, src);
4049}
4050
4051
4052void Assembler::popcntl(Register dst, Register src) {
4053 DCHECK(IsEnabled(POPCNT));
4054 EnsureSpace ensure_space(this);
4055 emit(0xF3);
4056 emit_optional_rex_32(dst, src);
4057 emit(0x0F);
4058 emit(0xB8);
4059 emit_modrm(dst, src);
4060}
4061
4062
4063void Assembler::popcntl(Register dst, const Operand& src) {
4064 DCHECK(IsEnabled(POPCNT));
4065 EnsureSpace ensure_space(this);
4066 emit(0xF3);
4067 emit_optional_rex_32(dst, src);
4068 emit(0x0F);
4069 emit(0xB8);
4070 emit_operand(dst, src);
4071}
4072
4073
4074void Assembler::bmi2q(SIMDPrefix pp, byte op, Register reg, Register vreg,
4075 Register rm) {
4076 DCHECK(IsEnabled(BMI2));
4077 EnsureSpace ensure_space(this);
4078 emit_vex_prefix(reg, vreg, rm, kLZ, pp, k0F38, kW1);
4079 emit(op);
4080 emit_modrm(reg, rm);
4081}
4082
4083
4084void Assembler::bmi2q(SIMDPrefix pp, byte op, Register reg, Register vreg,
4085 const Operand& rm) {
4086 DCHECK(IsEnabled(BMI2));
4087 EnsureSpace ensure_space(this);
4088 emit_vex_prefix(reg, vreg, rm, kLZ, pp, k0F38, kW1);
4089 emit(op);
4090 emit_operand(reg, rm);
4091}
4092
4093
4094void Assembler::bmi2l(SIMDPrefix pp, byte op, Register reg, Register vreg,
4095 Register rm) {
4096 DCHECK(IsEnabled(BMI2));
4097 EnsureSpace ensure_space(this);
4098 emit_vex_prefix(reg, vreg, rm, kLZ, pp, k0F38, kW0);
4099 emit(op);
4100 emit_modrm(reg, rm);
4101}
4102
4103
4104void Assembler::bmi2l(SIMDPrefix pp, byte op, Register reg, Register vreg,
4105 const Operand& rm) {
4106 DCHECK(IsEnabled(BMI2));
4107 EnsureSpace ensure_space(this);
4108 emit_vex_prefix(reg, vreg, rm, kLZ, pp, k0F38, kW0);
4109 emit(op);
4110 emit_operand(reg, rm);
4111}
4112
4113
4114void Assembler::rorxq(Register dst, Register src, byte imm8) {
4115 DCHECK(IsEnabled(BMI2));
4116 DCHECK(is_uint8(imm8));
4117 Register vreg = {0}; // VEX.vvvv unused
4118 EnsureSpace ensure_space(this);
4119 emit_vex_prefix(dst, vreg, src, kLZ, kF2, k0F3A, kW1);
4120 emit(0xF0);
4121 emit_modrm(dst, src);
4122 emit(imm8);
4123}
4124
4125
4126void Assembler::rorxq(Register dst, const Operand& src, byte imm8) {
4127 DCHECK(IsEnabled(BMI2));
4128 DCHECK(is_uint8(imm8));
4129 Register vreg = {0}; // VEX.vvvv unused
4130 EnsureSpace ensure_space(this);
4131 emit_vex_prefix(dst, vreg, src, kLZ, kF2, k0F3A, kW1);
4132 emit(0xF0);
4133 emit_operand(dst, src);
4134 emit(imm8);
4135}
4136
4137
4138void Assembler::rorxl(Register dst, Register src, byte imm8) {
4139 DCHECK(IsEnabled(BMI2));
4140 DCHECK(is_uint8(imm8));
4141 Register vreg = {0}; // VEX.vvvv unused
4142 EnsureSpace ensure_space(this);
4143 emit_vex_prefix(dst, vreg, src, kLZ, kF2, k0F3A, kW0);
4144 emit(0xF0);
4145 emit_modrm(dst, src);
4146 emit(imm8);
4147}
4148
4149
4150void Assembler::rorxl(Register dst, const Operand& src, byte imm8) {
4151 DCHECK(IsEnabled(BMI2));
4152 DCHECK(is_uint8(imm8));
4153 Register vreg = {0}; // VEX.vvvv unused
4154 EnsureSpace ensure_space(this);
4155 emit_vex_prefix(dst, vreg, src, kLZ, kF2, k0F3A, kW0);
4156 emit(0xF0);
4157 emit_operand(dst, src);
4158 emit(imm8);
4159}
4160
4161
Steve Blocka7e24c12009-10-30 11:49:00 +00004162void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
4163 Register ireg = { reg.code() };
4164 emit_operand(ireg, adr);
4165}
4166
4167
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004168void Assembler::emit_sse_operand(Register reg, const Operand& adr) {
4169 Register ireg = {reg.code()};
4170 emit_operand(ireg, adr);
4171}
4172
4173
Steve Blocka7e24c12009-10-30 11:49:00 +00004174void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
4175 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
4176}
4177
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004178
Steve Blocka7e24c12009-10-30 11:49:00 +00004179void Assembler::emit_sse_operand(XMMRegister dst, Register src) {
4180 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
4181}
4182
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004183
Steve Block6ded16b2010-05-10 14:33:55 +01004184void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
4185 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
4186}
4187
Steve Blocka7e24c12009-10-30 11:49:00 +00004188
Ben Murdochb8e0da22011-05-16 14:20:40 +01004189void Assembler::db(uint8_t data) {
4190 EnsureSpace ensure_space(this);
4191 emit(data);
4192}
4193
4194
Ben Murdochb0fe1622011-05-05 13:52:32 +01004195void Assembler::dd(uint32_t data) {
4196 EnsureSpace ensure_space(this);
4197 emitl(data);
4198}
4199
4200
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004201void Assembler::dq(uint64_t data) {
4202 EnsureSpace ensure_space(this);
4203 emitq(data);
4204}
4205
4206
4207void Assembler::dq(Label* label) {
4208 EnsureSpace ensure_space(this);
4209 if (label->is_bound()) {
4210 internal_reference_positions_.push_back(pc_offset());
4211 emitp(buffer_ + label->pos(), RelocInfo::INTERNAL_REFERENCE);
4212 } else {
4213 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
4214 emitl(0); // Zero for the first 32bit marks it as 64bit absolute address.
4215 if (label->is_linked()) {
4216 emitl(label->pos());
4217 label->link_to(pc_offset() - sizeof(int32_t));
4218 } else {
4219 DCHECK(label->is_unused());
4220 int32_t current = pc_offset();
4221 emitl(current);
4222 label->link_to(current);
4223 }
4224 }
4225}
4226
4227
Andrei Popescu31002712010-02-23 13:46:05 +00004228// Relocation information implementations.
Steve Blocka7e24c12009-10-30 11:49:00 +00004229
4230void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004231 DCHECK(!RelocInfo::IsNone(rmode));
Steve Blocka7e24c12009-10-30 11:49:00 +00004232 // Don't record external references unless the heap will be serialized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004233 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
4234 !serializer_enabled() && !emit_debug_code()) {
4235 return;
4236 } else if (rmode == RelocInfo::CODE_AGE_SEQUENCE) {
4237 // Don't record psuedo relocation info for code age sequence mode.
4238 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00004239 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004240 RelocInfo rinfo(isolate(), pc_, rmode, data, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00004241 reloc_info_writer.Write(&rinfo);
4242}
4243
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004244
Steve Block3ce2e202009-11-05 08:53:23 +00004245const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004246 1 << RelocInfo::RUNTIME_ENTRY |
4247 1 << RelocInfo::INTERNAL_REFERENCE |
4248 1 << RelocInfo::CODE_AGE_SEQUENCE;
Steve Blocka7e24c12009-10-30 11:49:00 +00004249
Leon Clarkef7060e22010-06-03 12:02:55 +01004250
4251bool RelocInfo::IsCodedSpecially() {
4252 // The deserializer needs to know whether a pointer is specially coded. Being
4253 // specially coded on x64 means that it is a relative 32 bit address, as used
4254 // by branch instructions.
4255 return (1 << rmode_) & kApplyMask;
4256}
4257
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004258
4259bool RelocInfo::IsInConstantPool() {
4260 return false;
4261}
4262
4263
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004264} // namespace internal
4265} // namespace v8
Leon Clarkef7060e22010-06-03 12:02:55 +01004266
4267#endif // V8_TARGET_ARCH_X64