blob: 3cf3398e876e3a51e291a2e2f60ca88355e8d87b [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
117
Steve Blocka7e24c12009-10-30 11:49:00 +0000118// -----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000119// Implementation of Operand
120
Andrei Popescu402d9372010-02-26 13:31:12 +0000121Operand::Operand(Register base, int32_t disp) : rex_(0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000122 len_ = 1;
123 if (base.is(rsp) || base.is(r12)) {
124 // SIB byte is needed to encode (rsp + offset) or (r12 + offset).
125 set_sib(times_1, rsp, base);
126 }
127
128 if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
129 set_modrm(0, base);
130 } else if (is_int8(disp)) {
131 set_modrm(1, base);
132 set_disp8(disp);
133 } else {
134 set_modrm(2, base);
135 set_disp32(disp);
136 }
137}
138
139
140Operand::Operand(Register base,
141 Register index,
142 ScaleFactor scale,
Andrei Popescu402d9372010-02-26 13:31:12 +0000143 int32_t disp) : rex_(0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144 DCHECK(!index.is(rsp));
Steve Blocka7e24c12009-10-30 11:49:00 +0000145 len_ = 1;
146 set_sib(scale, index, base);
147 if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
148 // This call to set_modrm doesn't overwrite the REX.B (or REX.X) bits
149 // possibly set by set_sib.
150 set_modrm(0, rsp);
151 } else if (is_int8(disp)) {
152 set_modrm(1, rsp);
153 set_disp8(disp);
154 } else {
155 set_modrm(2, rsp);
156 set_disp32(disp);
157 }
158}
159
160
Andrei Popescu402d9372010-02-26 13:31:12 +0000161Operand::Operand(Register index,
162 ScaleFactor scale,
163 int32_t disp) : rex_(0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164 DCHECK(!index.is(rsp));
Andrei Popescu402d9372010-02-26 13:31:12 +0000165 len_ = 1;
166 set_modrm(0, rsp);
167 set_sib(scale, index, rbp);
168 set_disp32(disp);
169}
170
171
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172Operand::Operand(Label* label) : rex_(0), len_(1) {
173 DCHECK_NOT_NULL(label);
174 set_modrm(0, rbp);
175 set_disp64(reinterpret_cast<intptr_t>(label));
176}
177
178
Leon Clarkef7060e22010-06-03 12:02:55 +0100179Operand::Operand(const Operand& operand, int32_t offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000180 DCHECK(operand.len_ >= 1);
Leon Clarkef7060e22010-06-03 12:02:55 +0100181 // Operand encodes REX ModR/M [SIB] [Disp].
182 byte modrm = operand.buf_[0];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183 DCHECK(modrm < 0xC0); // Disallow mode 3 (register target).
Leon Clarkef7060e22010-06-03 12:02:55 +0100184 bool has_sib = ((modrm & 0x07) == 0x04);
185 byte mode = modrm & 0xC0;
186 int disp_offset = has_sib ? 2 : 1;
187 int base_reg = (has_sib ? operand.buf_[1] : modrm) & 0x07;
188 // Mode 0 with rbp/r13 as ModR/M or SIB base register always has a 32-bit
189 // displacement.
190 bool is_baseless = (mode == 0) && (base_reg == 0x05); // No base or RIP base.
191 int32_t disp_value = 0;
192 if (mode == 0x80 || is_baseless) {
193 // Mode 2 or mode 0 with rbp/r13 as base: Word displacement.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194 disp_value = *bit_cast<const int32_t*>(&operand.buf_[disp_offset]);
Leon Clarkef7060e22010-06-03 12:02:55 +0100195 } else if (mode == 0x40) {
196 // Mode 1: Byte displacement.
197 disp_value = static_cast<signed char>(operand.buf_[disp_offset]);
198 }
199
200 // Write new operand with same registers, but with modified displacement.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000201 DCHECK(offset >= 0 ? disp_value + offset > disp_value
Leon Clarkef7060e22010-06-03 12:02:55 +0100202 : disp_value + offset < disp_value); // No overflow.
203 disp_value += offset;
204 rex_ = operand.rex_;
205 if (!is_int8(disp_value) || is_baseless) {
206 // Need 32 bits of displacement, mode 2 or mode 1 with register rbp/r13.
207 buf_[0] = (modrm & 0x3f) | (is_baseless ? 0x00 : 0x80);
208 len_ = disp_offset + 4;
209 Memory::int32_at(&buf_[disp_offset]) = disp_value;
210 } else if (disp_value != 0 || (base_reg == 0x05)) {
211 // Need 8 bits of displacement.
212 buf_[0] = (modrm & 0x3f) | 0x40; // Mode 1.
213 len_ = disp_offset + 1;
214 buf_[disp_offset] = static_cast<byte>(disp_value);
215 } else {
216 // Need no displacement.
217 buf_[0] = (modrm & 0x3f); // Mode 0.
218 len_ = disp_offset;
219 }
220 if (has_sib) {
221 buf_[1] = operand.buf_[1];
222 }
223}
224
Steve Block1e0659c2011-05-24 12:43:12 +0100225
226bool Operand::AddressUsesRegister(Register reg) const {
227 int code = reg.code();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228 DCHECK((buf_[0] & 0xC0) != 0xC0); // Always a memory operand.
Steve Block1e0659c2011-05-24 12:43:12 +0100229 // Start with only low three bits of base register. Initial decoding doesn't
230 // distinguish on the REX.B bit.
231 int base_code = buf_[0] & 0x07;
232 if (base_code == rsp.code()) {
233 // SIB byte present in buf_[1].
234 // Check the index register from the SIB byte + REX.X prefix.
235 int index_code = ((buf_[1] >> 3) & 0x07) | ((rex_ & 0x02) << 2);
236 // Index code (including REX.X) of 0x04 (rsp) means no index register.
237 if (index_code != rsp.code() && index_code == code) return true;
238 // Add REX.B to get the full base register code.
239 base_code = (buf_[1] & 0x07) | ((rex_ & 0x01) << 3);
240 // A base register of 0x05 (rbp) with mod = 0 means no base register.
241 if (base_code == rbp.code() && ((buf_[0] & 0xC0) == 0)) return false;
242 return code == base_code;
243 } else {
244 // A base register with low bits of 0x05 (rbp or r13) and mod = 0 means
245 // no base register.
246 if (base_code == rbp.code() && ((buf_[0] & 0xC0) == 0)) return false;
247 base_code |= ((rex_ & 0x01) << 3);
248 return code == base_code;
249 }
250}
251
252
Steve Blocka7e24c12009-10-30 11:49:00 +0000253// -----------------------------------------------------------------------------
Andrei Popescu31002712010-02-23 13:46:05 +0000254// Implementation of Assembler.
Steve Blocka7e24c12009-10-30 11:49:00 +0000255
256#ifdef GENERATED_CODE_COVERAGE
257static void InitCoverageLog();
258#endif
259
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000260Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
261 : AssemblerBase(isolate, buffer, buffer_size),
Steve Block44f0eee2011-05-26 01:26:41 +0100262 code_targets_(100),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000263 positions_recorder_(this) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000264 // Clear the buffer in debug mode unless it was provided by the
265 // caller in which case we can't be sure it's okay to overwrite
266 // existing code in it.
267#ifdef DEBUG
268 if (own_buffer_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269 memset(buffer_, 0xCC, buffer_size_); // int3
Steve Blocka7e24c12009-10-30 11:49:00 +0000270 }
271#endif
272
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000274
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800275
Steve Blocka7e24c12009-10-30 11:49:00 +0000276#ifdef GENERATED_CODE_COVERAGE
277 InitCoverageLog();
278#endif
279}
280
281
Steve Blocka7e24c12009-10-30 11:49:00 +0000282void Assembler::GetCode(CodeDesc* desc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000283 // Finalize code (at this point overflow() may be true, but the gap ensures
284 // that we are still not overlapping instructions and relocation info).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 reloc_info_writer.Finish();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286 DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100287 // Set up code descriptor.
Steve Blocka7e24c12009-10-30 11:49:00 +0000288 desc->buffer = buffer_;
289 desc->buffer_size = buffer_size_;
290 desc->instr_size = pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000291 DCHECK(desc->instr_size > 0); // Zero-size code objects upset the system.
Steve Blockd0582a62009-12-15 09:54:21 +0000292 desc->reloc_size =
293 static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos());
Steve Blocka7e24c12009-10-30 11:49:00 +0000294 desc->origin = this;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295 desc->constant_pool_size = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000296}
297
298
299void Assembler::Align(int m) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000300 DCHECK(base::bits::IsPowerOfTwo32(m));
Steve Block8defd9f2010-07-08 12:39:36 +0100301 int delta = (m - (pc_offset() & (m - 1))) & (m - 1);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100302 Nop(delta);
Steve Blocka7e24c12009-10-30 11:49:00 +0000303}
304
305
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100306void Assembler::CodeTargetAlign() {
307 Align(16); // Preferred alignment of jump targets on x64.
308}
309
310
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100311bool Assembler::IsNop(Address addr) {
312 Address a = addr;
313 while (*a == 0x66) a++;
314 if (*a == 0x90) return true;
315 if (a[0] == 0xf && a[1] == 0x1f) return true;
316 return false;
317}
318
319
Steve Blocka7e24c12009-10-30 11:49:00 +0000320void Assembler::bind_to(Label* L, int pos) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000321 DCHECK(!L->is_bound()); // Label may only be bound once.
322 DCHECK(0 <= pos && pos <= pc_offset()); // Position must be valid.
Steve Blocka7e24c12009-10-30 11:49:00 +0000323 if (L->is_linked()) {
324 int current = L->pos();
325 int next = long_at(current);
326 while (next != current) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327 if (current >= 4 && long_at(current - 4) == 0) {
328 // Absolute address.
329 intptr_t imm64 = reinterpret_cast<intptr_t>(buffer_ + pos);
330 *reinterpret_cast<intptr_t*>(addr_at(current - 4)) = imm64;
331 internal_reference_positions_.push_back(current - 4);
332 } else {
333 // Relative address, relative to point after address.
334 int imm32 = pos - (current + sizeof(int32_t));
335 long_at_put(current, imm32);
336 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000337 current = next;
338 next = long_at(next);
339 }
340 // Fix up last fixup on linked list.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341 if (current >= 4 && long_at(current - 4) == 0) {
342 // Absolute address.
343 intptr_t imm64 = reinterpret_cast<intptr_t>(buffer_ + pos);
344 *reinterpret_cast<intptr_t*>(addr_at(current - 4)) = imm64;
345 internal_reference_positions_.push_back(current - 4);
346 } else {
347 // Relative address, relative to point after address.
348 int imm32 = pos - (current + sizeof(int32_t));
349 long_at_put(current, imm32);
350 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000351 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000352 while (L->is_near_linked()) {
353 int fixup_pos = L->near_link_pos();
354 int offset_to_next =
355 static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000356 DCHECK(offset_to_next <= 0);
Ben Murdoch257744e2011-11-30 15:57:28 +0000357 int disp = pos - (fixup_pos + sizeof(int8_t));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000358 CHECK(is_int8(disp));
Ben Murdoch257744e2011-11-30 15:57:28 +0000359 set_byte_at(fixup_pos, disp);
360 if (offset_to_next < 0) {
361 L->link_to(fixup_pos + offset_to_next, Label::kNear);
362 } else {
363 L->UnuseNear();
364 }
365 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000366 L->bind_to(pos);
367}
368
369
370void Assembler::bind(Label* L) {
371 bind_to(L, pc_offset());
372}
373
374
375void Assembler::GrowBuffer() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000376 DCHECK(buffer_overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +0000377 if (!own_buffer_) FATAL("external code buffer is too small");
378
Andrei Popescu31002712010-02-23 13:46:05 +0000379 // Compute new buffer size.
Steve Blocka7e24c12009-10-30 11:49:00 +0000380 CodeDesc desc; // the new buffer
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000381 desc.buffer_size = 2 * buffer_size_;
382
Steve Blocka7e24c12009-10-30 11:49:00 +0000383 // Some internal data structures overflow for very large buffers,
384 // they must ensure that kMaximalBufferSize is not too large.
385 if ((desc.buffer_size > kMaximalBufferSize) ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000386 (desc.buffer_size > isolate()->heap()->MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000387 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
388 }
389
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100390 // Set up new buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 desc.buffer = NewArray<byte>(desc.buffer_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000392 desc.origin = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000393 desc.instr_size = pc_offset();
Steve Blockd0582a62009-12-15 09:54:21 +0000394 desc.reloc_size =
395 static_cast<int>((buffer_ + buffer_size_) - (reloc_info_writer.pos()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000396
397 // Clear the buffer in debug mode. Use 'int3' instructions to make
398 // sure to get into problems if we ever run uninitialized code.
399#ifdef DEBUG
400 memset(desc.buffer, 0xCC, desc.buffer_size);
401#endif
402
Andrei Popescu31002712010-02-23 13:46:05 +0000403 // Copy the data.
Steve Blocka7e24c12009-10-30 11:49:00 +0000404 intptr_t pc_delta = desc.buffer - buffer_;
405 intptr_t rc_delta = (desc.buffer + desc.buffer_size) -
406 (buffer_ + buffer_size_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000407 MemMove(desc.buffer, buffer_, desc.instr_size);
408 MemMove(rc_delta + reloc_info_writer.pos(), reloc_info_writer.pos(),
409 desc.reloc_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000410
Andrei Popescu31002712010-02-23 13:46:05 +0000411 // Switch buffers.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000412 DeleteArray(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 buffer_ = desc.buffer;
414 buffer_size_ = desc.buffer_size;
415 pc_ += pc_delta;
Steve Blocka7e24c12009-10-30 11:49:00 +0000416 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
417 reloc_info_writer.last_pc() + pc_delta);
418
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000419 // Relocate internal references.
420 for (auto pos : internal_reference_positions_) {
421 intptr_t* p = reinterpret_cast<intptr_t*>(buffer_ + pos);
422 *p += pc_delta;
Steve Blocka7e24c12009-10-30 11:49:00 +0000423 }
424
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000425 DCHECK(!buffer_overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +0000426}
427
428
429void Assembler::emit_operand(int code, const Operand& adr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000430 DCHECK(is_uint3(code));
Steve Blocka7e24c12009-10-30 11:49:00 +0000431 const unsigned length = adr.len_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000432 DCHECK(length > 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000433
434 // Emit updated ModR/M byte containing the given register.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000435 DCHECK((adr.buf_[0] & 0x38) == 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000436 *pc_++ = adr.buf_[0] | code << 3;
Steve Blocka7e24c12009-10-30 11:49:00 +0000437
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000438 // Recognize RIP relative addressing.
439 if (adr.buf_[0] == 5) {
440 DCHECK_EQ(9u, length);
441 Label* label = *bit_cast<Label* const*>(&adr.buf_[1]);
442 if (label->is_bound()) {
443 int offset = label->pos() - pc_offset() - sizeof(int32_t);
444 DCHECK_GE(0, offset);
445 emitl(offset);
446 } else if (label->is_linked()) {
447 emitl(label->pos());
448 label->link_to(pc_offset() - sizeof(int32_t));
449 } else {
450 DCHECK(label->is_unused());
451 int32_t current = pc_offset();
452 emitl(current);
453 label->link_to(current);
454 }
455 } else {
456 // Emit the rest of the encoded operand.
457 for (unsigned i = 1; i < length; i++) *pc_++ = adr.buf_[i];
458 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000459}
460
461
Andrei Popescu31002712010-02-23 13:46:05 +0000462// Assembler Instruction implementations.
Steve Blocka7e24c12009-10-30 11:49:00 +0000463
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000464void Assembler::arithmetic_op(byte opcode,
465 Register reg,
466 const Operand& op,
467 int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000468 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000469 emit_rex(reg, op, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000470 emit(opcode);
471 emit_operand(reg, op);
472}
473
474
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000475void Assembler::arithmetic_op(byte opcode,
476 Register reg,
477 Register rm_reg,
478 int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000479 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000480 DCHECK((opcode & 0xC6) == 2);
Leon Clarkef7060e22010-06-03 12:02:55 +0100481 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
482 // Swap reg and rm_reg and change opcode operand order.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000483 emit_rex(rm_reg, reg, size);
Leon Clarkef7060e22010-06-03 12:02:55 +0100484 emit(opcode ^ 0x02);
485 emit_modrm(rm_reg, reg);
486 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000487 emit_rex(reg, rm_reg, size);
Leon Clarkef7060e22010-06-03 12:02:55 +0100488 emit(opcode);
489 emit_modrm(reg, rm_reg);
490 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000491}
492
493
494void Assembler::arithmetic_op_16(byte opcode, Register reg, Register rm_reg) {
495 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000496 DCHECK((opcode & 0xC6) == 2);
Leon Clarkef7060e22010-06-03 12:02:55 +0100497 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
498 // Swap reg and rm_reg and change opcode operand order.
499 emit(0x66);
500 emit_optional_rex_32(rm_reg, reg);
501 emit(opcode ^ 0x02);
502 emit_modrm(rm_reg, reg);
503 } else {
504 emit(0x66);
505 emit_optional_rex_32(reg, rm_reg);
506 emit(opcode);
507 emit_modrm(reg, rm_reg);
508 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000509}
510
511
512void Assembler::arithmetic_op_16(byte opcode,
513 Register reg,
514 const Operand& rm_reg) {
515 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000516 emit(0x66);
517 emit_optional_rex_32(reg, rm_reg);
518 emit(opcode);
519 emit_operand(reg, rm_reg);
520}
521
522
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523void Assembler::arithmetic_op_8(byte opcode, Register reg, const Operand& op) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000524 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000525 if (!reg.is_byte_register()) {
526 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
527 emit_rex_32(reg);
528 }
529 emit(opcode);
530 emit_operand(reg, op);
531}
532
533
534void Assembler::arithmetic_op_8(byte opcode, Register reg, Register rm_reg) {
535 EnsureSpace ensure_space(this);
536 DCHECK((opcode & 0xC6) == 2);
537 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
Leon Clarkef7060e22010-06-03 12:02:55 +0100538 // Swap reg and rm_reg and change opcode operand order.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000539 if (!rm_reg.is_byte_register() || !reg.is_byte_register()) {
540 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
541 emit_rex_32(rm_reg, reg);
542 }
543 emit(opcode ^ 0x02);
Leon Clarkef7060e22010-06-03 12:02:55 +0100544 emit_modrm(rm_reg, reg);
545 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000546 if (!reg.is_byte_register() || !rm_reg.is_byte_register()) {
547 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
548 emit_rex_32(reg, rm_reg);
549 }
Leon Clarkef7060e22010-06-03 12:02:55 +0100550 emit(opcode);
551 emit_modrm(reg, rm_reg);
552 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000553}
554
555
Steve Blocka7e24c12009-10-30 11:49:00 +0000556void Assembler::immediate_arithmetic_op(byte subcode,
557 Register dst,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000558 Immediate src,
559 int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000560 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000561 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000562 if (is_int8(src.value_)) {
563 emit(0x83);
564 emit_modrm(subcode, dst);
565 emit(src.value_);
566 } else if (dst.is(rax)) {
567 emit(0x05 | (subcode << 3));
568 emitl(src.value_);
569 } else {
570 emit(0x81);
571 emit_modrm(subcode, dst);
572 emitl(src.value_);
573 }
574}
575
576void Assembler::immediate_arithmetic_op(byte subcode,
577 const Operand& dst,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000578 Immediate src,
579 int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000580 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000581 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000582 if (is_int8(src.value_)) {
583 emit(0x83);
584 emit_operand(subcode, dst);
585 emit(src.value_);
586 } else {
587 emit(0x81);
588 emit_operand(subcode, dst);
589 emitl(src.value_);
590 }
591}
592
593
594void Assembler::immediate_arithmetic_op_16(byte subcode,
595 Register dst,
596 Immediate src) {
597 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000598 emit(0x66); // Operand size override prefix.
599 emit_optional_rex_32(dst);
600 if (is_int8(src.value_)) {
601 emit(0x83);
602 emit_modrm(subcode, dst);
603 emit(src.value_);
604 } else if (dst.is(rax)) {
605 emit(0x05 | (subcode << 3));
Steve Block3ce2e202009-11-05 08:53:23 +0000606 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000607 } else {
608 emit(0x81);
609 emit_modrm(subcode, dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000610 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000611 }
612}
613
614
615void Assembler::immediate_arithmetic_op_16(byte subcode,
616 const Operand& dst,
617 Immediate src) {
618 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000619 emit(0x66); // Operand size override prefix.
620 emit_optional_rex_32(dst);
621 if (is_int8(src.value_)) {
622 emit(0x83);
623 emit_operand(subcode, dst);
624 emit(src.value_);
625 } else {
626 emit(0x81);
627 emit_operand(subcode, dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000628 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000629 }
630}
631
632
Steve Blocka7e24c12009-10-30 11:49:00 +0000633void Assembler::immediate_arithmetic_op_8(byte subcode,
634 const Operand& dst,
635 Immediate src) {
636 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000637 emit_optional_rex_32(dst);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000638 DCHECK(is_int8(src.value_) || is_uint8(src.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000639 emit(0x80);
640 emit_operand(subcode, dst);
641 emit(src.value_);
642}
643
644
645void Assembler::immediate_arithmetic_op_8(byte subcode,
646 Register dst,
647 Immediate src) {
648 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100649 if (!dst.is_byte_register()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000650 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
651 emit_rex_32(dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000652 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000653 DCHECK(is_int8(src.value_) || is_uint8(src.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000654 emit(0x80);
655 emit_modrm(subcode, dst);
656 emit(src.value_);
657}
658
659
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000660void Assembler::shift(Register dst,
661 Immediate shift_amount,
662 int subcode,
663 int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000664 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000665 DCHECK(size == kInt64Size ? is_uint6(shift_amount.value_)
666 : is_uint5(shift_amount.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000667 if (shift_amount.value_ == 1) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000668 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000669 emit(0xD1);
670 emit_modrm(subcode, dst);
671 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000672 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000673 emit(0xC1);
674 emit_modrm(subcode, dst);
675 emit(shift_amount.value_);
676 }
677}
678
679
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400680void Assembler::shift(Operand dst, Immediate shift_amount, int subcode,
681 int size) {
682 EnsureSpace ensure_space(this);
683 DCHECK(size == kInt64Size ? is_uint6(shift_amount.value_)
684 : is_uint5(shift_amount.value_));
685 if (shift_amount.value_ == 1) {
686 emit_rex(dst, size);
687 emit(0xD1);
688 emit_operand(subcode, dst);
689 } else {
690 emit_rex(dst, size);
691 emit(0xC1);
692 emit_operand(subcode, dst);
693 emit(shift_amount.value_);
694 }
695}
696
697
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000698void Assembler::shift(Register dst, int subcode, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000699 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000700 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000701 emit(0xD3);
702 emit_modrm(subcode, dst);
703}
704
705
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400706void Assembler::shift(Operand dst, int subcode, int size) {
707 EnsureSpace ensure_space(this);
708 emit_rex(dst, size);
709 emit(0xD3);
710 emit_operand(subcode, dst);
711}
712
713
Steve Blocka7e24c12009-10-30 11:49:00 +0000714void Assembler::bt(const Operand& dst, Register src) {
715 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000716 emit_rex_64(src, dst);
717 emit(0x0F);
718 emit(0xA3);
719 emit_operand(src, dst);
720}
721
722
723void Assembler::bts(const Operand& dst, Register src) {
724 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000725 emit_rex_64(src, dst);
726 emit(0x0F);
727 emit(0xAB);
728 emit_operand(src, dst);
729}
730
731
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000732void Assembler::bsrl(Register dst, Register src) {
733 EnsureSpace ensure_space(this);
734 emit_optional_rex_32(dst, src);
735 emit(0x0F);
736 emit(0xBD);
737 emit_modrm(dst, src);
738}
739
740
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000741void Assembler::bsrl(Register dst, const Operand& src) {
742 EnsureSpace ensure_space(this);
743 emit_optional_rex_32(dst, src);
744 emit(0x0F);
745 emit(0xBD);
746 emit_operand(dst, src);
747}
748
749
750void Assembler::bsrq(Register dst, Register src) {
751 EnsureSpace ensure_space(this);
752 emit_rex_64(dst, src);
753 emit(0x0F);
754 emit(0xBD);
755 emit_modrm(dst, src);
756}
757
758
759void Assembler::bsrq(Register dst, const Operand& src) {
760 EnsureSpace ensure_space(this);
761 emit_rex_64(dst, src);
762 emit(0x0F);
763 emit(0xBD);
764 emit_operand(dst, src);
765}
766
767
768void Assembler::bsfl(Register dst, Register src) {
769 EnsureSpace ensure_space(this);
770 emit_optional_rex_32(dst, src);
771 emit(0x0F);
772 emit(0xBC);
773 emit_modrm(dst, src);
774}
775
776
777void Assembler::bsfl(Register dst, const Operand& src) {
778 EnsureSpace ensure_space(this);
779 emit_optional_rex_32(dst, src);
780 emit(0x0F);
781 emit(0xBC);
782 emit_operand(dst, src);
783}
784
785
786void Assembler::bsfq(Register dst, Register src) {
787 EnsureSpace ensure_space(this);
788 emit_rex_64(dst, src);
789 emit(0x0F);
790 emit(0xBC);
791 emit_modrm(dst, src);
792}
793
794
795void Assembler::bsfq(Register dst, const Operand& src) {
796 EnsureSpace ensure_space(this);
797 emit_rex_64(dst, src);
798 emit(0x0F);
799 emit(0xBC);
800 emit_operand(dst, src);
801}
802
803
Steve Blocka7e24c12009-10-30 11:49:00 +0000804void Assembler::call(Label* L) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100805 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000806 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000807 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +0000808 emit(0xE8);
809 if (L->is_bound()) {
810 int offset = L->pos() - pc_offset() - sizeof(int32_t);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000811 DCHECK(offset <= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000812 emitl(offset);
813 } else if (L->is_linked()) {
814 emitl(L->pos());
815 L->link_to(pc_offset() - sizeof(int32_t));
816 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817 DCHECK(L->is_unused());
Steve Blocka7e24c12009-10-30 11:49:00 +0000818 int32_t current = pc_offset();
819 emitl(current);
820 L->link_to(current);
821 }
822}
823
824
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000825void Assembler::call(Address entry, RelocInfo::Mode rmode) {
826 DCHECK(RelocInfo::IsRuntimeEntry(rmode));
827 positions_recorder()->WriteRecordedPositions();
828 EnsureSpace ensure_space(this);
829 // 1110 1000 #32-bit disp.
830 emit(0xE8);
831 emit_runtime_entry(entry, rmode);
832}
833
834
Ben Murdoch257744e2011-11-30 15:57:28 +0000835void Assembler::call(Handle<Code> target,
836 RelocInfo::Mode rmode,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000837 TypeFeedbackId ast_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800838 positions_recorder()->WriteRecordedPositions();
Steve Block3ce2e202009-11-05 08:53:23 +0000839 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000840 // 1110 1000 #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +0000841 emit(0xE8);
Ben Murdoch257744e2011-11-30 15:57:28 +0000842 emit_code_target(target, rmode, ast_id);
Steve Block3ce2e202009-11-05 08:53:23 +0000843}
844
845
Steve Blocka7e24c12009-10-30 11:49:00 +0000846void Assembler::call(Register adr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100847 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000848 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000849 // Opcode: FF /2 r64.
Steve Block8defd9f2010-07-08 12:39:36 +0100850 emit_optional_rex_32(adr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000851 emit(0xFF);
852 emit_modrm(0x2, adr);
853}
854
855
856void Assembler::call(const Operand& op) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100857 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000858 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000859 // Opcode: FF /2 m64.
Steve Block8defd9f2010-07-08 12:39:36 +0100860 emit_optional_rex_32(op);
Steve Blocka7e24c12009-10-30 11:49:00 +0000861 emit(0xFF);
Steve Block8defd9f2010-07-08 12:39:36 +0100862 emit_operand(0x2, op);
Steve Blocka7e24c12009-10-30 11:49:00 +0000863}
864
865
Steve Block1e0659c2011-05-24 12:43:12 +0100866// Calls directly to the given address using a relative offset.
867// Should only ever be used in Code objects for calls within the
868// same Code object. Should not be used when generating new code (use labels),
869// but only when patching existing code.
870void Assembler::call(Address target) {
871 positions_recorder()->WriteRecordedPositions();
872 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +0100873 // 1110 1000 #32-bit disp.
874 emit(0xE8);
875 Address source = pc_ + 4;
876 intptr_t displacement = target - source;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000877 DCHECK(is_int32(displacement));
Steve Block1e0659c2011-05-24 12:43:12 +0100878 emitl(static_cast<int32_t>(displacement));
879}
880
881
Steve Block3ce2e202009-11-05 08:53:23 +0000882void Assembler::clc() {
883 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +0000884 emit(0xF8);
885}
886
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000887
Steve Block44f0eee2011-05-26 01:26:41 +0100888void Assembler::cld() {
889 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +0100890 emit(0xFC);
891}
892
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000893
Steve Blocka7e24c12009-10-30 11:49:00 +0000894void Assembler::cdq() {
895 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000896 emit(0x99);
897}
898
899
900void Assembler::cmovq(Condition cc, Register dst, Register src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000901 if (cc == always) {
902 movq(dst, src);
903 } else if (cc == never) {
904 return;
905 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000906 // No need to check CpuInfo for CMOV support, it's a required part of the
907 // 64-bit architecture.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000908 DCHECK(cc >= 0); // Use mov for unconditional moves.
Steve Blocka7e24c12009-10-30 11:49:00 +0000909 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000910 // Opcode: REX.W 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000911 emit_rex_64(dst, src);
912 emit(0x0f);
913 emit(0x40 + cc);
914 emit_modrm(dst, src);
915}
916
917
918void Assembler::cmovq(Condition cc, Register dst, const Operand& src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000919 if (cc == always) {
920 movq(dst, src);
921 } else if (cc == never) {
922 return;
923 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000924 DCHECK(cc >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000925 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000926 // Opcode: REX.W 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000927 emit_rex_64(dst, src);
928 emit(0x0f);
929 emit(0x40 + cc);
930 emit_operand(dst, src);
931}
932
933
934void Assembler::cmovl(Condition cc, Register dst, Register src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000935 if (cc == always) {
936 movl(dst, src);
937 } else if (cc == never) {
938 return;
939 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000940 DCHECK(cc >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000941 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000942 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000943 emit_optional_rex_32(dst, src);
944 emit(0x0f);
945 emit(0x40 + cc);
946 emit_modrm(dst, src);
947}
948
949
950void Assembler::cmovl(Condition cc, Register dst, const Operand& src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000951 if (cc == always) {
952 movl(dst, src);
953 } else if (cc == never) {
954 return;
955 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000956 DCHECK(cc >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000957 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000958 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000959 emit_optional_rex_32(dst, src);
960 emit(0x0f);
961 emit(0x40 + cc);
962 emit_operand(dst, src);
963}
964
965
966void Assembler::cmpb_al(Immediate imm8) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000967 DCHECK(is_int8(imm8.value_) || is_uint8(imm8.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000968 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000969 emit(0x3c);
970 emit(imm8.value_);
971}
972
973
974void Assembler::cpuid() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000975 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000976 emit(0x0F);
977 emit(0xA2);
978}
979
980
981void Assembler::cqo() {
982 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000983 emit_rex_64();
984 emit(0x99);
985}
986
987
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000988void Assembler::emit_dec(Register dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000989 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000990 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000991 emit(0xFF);
992 emit_modrm(0x1, dst);
993}
994
995
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000996void Assembler::emit_dec(const Operand& dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000997 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000999 emit(0xFF);
1000 emit_operand(1, dst);
1001}
1002
1003
Steve Block3ce2e202009-11-05 08:53:23 +00001004void Assembler::decb(Register dst) {
1005 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001006 if (!dst.is_byte_register()) {
Steve Block3ce2e202009-11-05 08:53:23 +00001007 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1008 emit_rex_32(dst);
1009 }
1010 emit(0xFE);
1011 emit_modrm(0x1, dst);
1012}
1013
1014
1015void Assembler::decb(const Operand& dst) {
1016 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001017 emit_optional_rex_32(dst);
1018 emit(0xFE);
1019 emit_operand(1, dst);
1020}
1021
1022
Steve Blocka7e24c12009-10-30 11:49:00 +00001023void Assembler::enter(Immediate size) {
1024 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001025 emit(0xC8);
1026 emitw(size.value_); // 16 bit operand, always.
1027 emit(0);
1028}
1029
1030
1031void Assembler::hlt() {
1032 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001033 emit(0xF4);
1034}
1035
1036
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001037void Assembler::emit_idiv(Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001038 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001039 emit_rex(src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001040 emit(0xF7);
1041 emit_modrm(0x7, src);
1042}
1043
1044
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001045void Assembler::emit_div(Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001046 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001047 emit_rex(src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001048 emit(0xF7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001049 emit_modrm(0x6, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001050}
1051
1052
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001053void Assembler::emit_imul(Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001054 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001055 emit_rex(src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001056 emit(0xF7);
1057 emit_modrm(0x5, src);
1058}
1059
1060
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001061void Assembler::emit_imul(const Operand& src, int size) {
1062 EnsureSpace ensure_space(this);
1063 emit_rex(src, size);
1064 emit(0xF7);
1065 emit_operand(0x5, src);
1066}
1067
1068
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001069void Assembler::emit_imul(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001070 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001071 emit_rex(dst, src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001072 emit(0x0F);
1073 emit(0xAF);
1074 emit_modrm(dst, src);
1075}
1076
1077
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001078void Assembler::emit_imul(Register dst, const Operand& src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001079 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001080 emit_rex(dst, src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001081 emit(0x0F);
1082 emit(0xAF);
1083 emit_operand(dst, src);
1084}
1085
1086
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001087void Assembler::emit_imul(Register dst, Register src, Immediate imm, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001088 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001089 emit_rex(dst, src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001090 if (is_int8(imm.value_)) {
1091 emit(0x6B);
1092 emit_modrm(dst, src);
1093 emit(imm.value_);
1094 } else {
1095 emit(0x69);
1096 emit_modrm(dst, src);
1097 emitl(imm.value_);
1098 }
1099}
1100
1101
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001102void Assembler::emit_imul(Register dst, const Operand& src, Immediate imm,
1103 int size) {
1104 EnsureSpace ensure_space(this);
1105 emit_rex(dst, src, size);
1106 if (is_int8(imm.value_)) {
1107 emit(0x6B);
1108 emit_operand(dst, src);
1109 emit(imm.value_);
1110 } else {
1111 emit(0x69);
1112 emit_operand(dst, src);
1113 emitl(imm.value_);
1114 }
1115}
1116
1117
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001118void Assembler::emit_inc(Register dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001119 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001120 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001121 emit(0xFF);
1122 emit_modrm(0x0, dst);
1123}
1124
1125
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001126void Assembler::emit_inc(const Operand& dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001127 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001128 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001129 emit(0xFF);
1130 emit_operand(0, dst);
1131}
1132
1133
Steve Blocka7e24c12009-10-30 11:49:00 +00001134void Assembler::int3() {
1135 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001136 emit(0xCC);
1137}
1138
1139
Ben Murdoch257744e2011-11-30 15:57:28 +00001140void Assembler::j(Condition cc, Label* L, Label::Distance distance) {
Steve Block3ce2e202009-11-05 08:53:23 +00001141 if (cc == always) {
1142 jmp(L);
1143 return;
1144 } else if (cc == never) {
1145 return;
1146 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001147 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001148 DCHECK(is_uint4(cc));
Steve Blocka7e24c12009-10-30 11:49:00 +00001149 if (L->is_bound()) {
1150 const int short_size = 2;
1151 const int long_size = 6;
1152 int offs = L->pos() - pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001153 DCHECK(offs <= 0);
1154 // Determine whether we can use 1-byte offsets for backwards branches,
1155 // which have a max range of 128 bytes.
1156
1157 // We also need to check predictable_code_size() flag here, because on x64,
1158 // when the full code generator recompiles code for debugging, some places
1159 // need to be padded out to a certain size. The debugger is keeping track of
1160 // how often it did this so that it can adjust return addresses on the
1161 // stack, but if the size of jump instructions can also change, that's not
1162 // enough and the calculated offsets would be incorrect.
1163 if (is_int8(offs - short_size) && !predictable_code_size()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001164 // 0111 tttn #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001165 emit(0x70 | cc);
1166 emit((offs - short_size) & 0xFF);
1167 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001168 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001169 emit(0x0F);
1170 emit(0x80 | cc);
1171 emitl(offs - long_size);
1172 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001173 } else if (distance == Label::kNear) {
1174 // 0111 tttn #8-bit disp
1175 emit(0x70 | cc);
1176 byte disp = 0x00;
1177 if (L->is_near_linked()) {
1178 int offset = L->near_link_pos() - pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001179 DCHECK(is_int8(offset));
Ben Murdoch257744e2011-11-30 15:57:28 +00001180 disp = static_cast<byte>(offset & 0xFF);
1181 }
1182 L->link_to(pc_offset(), Label::kNear);
1183 emit(disp);
Steve Blocka7e24c12009-10-30 11:49:00 +00001184 } else if (L->is_linked()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001185 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001186 emit(0x0F);
1187 emit(0x80 | cc);
1188 emitl(L->pos());
1189 L->link_to(pc_offset() - sizeof(int32_t));
1190 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001191 DCHECK(L->is_unused());
Steve Blocka7e24c12009-10-30 11:49:00 +00001192 emit(0x0F);
1193 emit(0x80 | cc);
1194 int32_t current = pc_offset();
1195 emitl(current);
1196 L->link_to(current);
1197 }
1198}
1199
1200
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001201void Assembler::j(Condition cc, Address entry, RelocInfo::Mode rmode) {
1202 DCHECK(RelocInfo::IsRuntimeEntry(rmode));
1203 EnsureSpace ensure_space(this);
1204 DCHECK(is_uint4(cc));
1205 emit(0x0F);
1206 emit(0x80 | cc);
1207 emit_runtime_entry(entry, rmode);
1208}
1209
1210
Steve Block3ce2e202009-11-05 08:53:23 +00001211void Assembler::j(Condition cc,
1212 Handle<Code> target,
1213 RelocInfo::Mode rmode) {
1214 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001215 DCHECK(is_uint4(cc));
Andrei Popescu31002712010-02-23 13:46:05 +00001216 // 0000 1111 1000 tttn #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +00001217 emit(0x0F);
1218 emit(0x80 | cc);
1219 emit_code_target(target, rmode);
1220}
1221
1222
Ben Murdoch257744e2011-11-30 15:57:28 +00001223void Assembler::jmp(Label* L, Label::Distance distance) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001224 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01001225 const int short_size = sizeof(int8_t);
1226 const int long_size = sizeof(int32_t);
Steve Blocka7e24c12009-10-30 11:49:00 +00001227 if (L->is_bound()) {
1228 int offs = L->pos() - pc_offset() - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001229 DCHECK(offs <= 0);
1230 if (is_int8(offs - short_size) && !predictable_code_size()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001231 // 1110 1011 #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001232 emit(0xEB);
Steve Block6ded16b2010-05-10 14:33:55 +01001233 emit((offs - short_size) & 0xFF);
Steve Blocka7e24c12009-10-30 11:49:00 +00001234 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001235 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001236 emit(0xE9);
Steve Block6ded16b2010-05-10 14:33:55 +01001237 emitl(offs - long_size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001238 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001239 } else if (distance == Label::kNear) {
1240 emit(0xEB);
1241 byte disp = 0x00;
1242 if (L->is_near_linked()) {
1243 int offset = L->near_link_pos() - pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001244 DCHECK(is_int8(offset));
Ben Murdoch257744e2011-11-30 15:57:28 +00001245 disp = static_cast<byte>(offset & 0xFF);
1246 }
1247 L->link_to(pc_offset(), Label::kNear);
1248 emit(disp);
1249 } else if (L->is_linked()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001250 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001251 emit(0xE9);
1252 emitl(L->pos());
Steve Block6ded16b2010-05-10 14:33:55 +01001253 L->link_to(pc_offset() - long_size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001254 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001255 // 1110 1001 #32-bit disp.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001256 DCHECK(L->is_unused());
Steve Blocka7e24c12009-10-30 11:49:00 +00001257 emit(0xE9);
1258 int32_t current = pc_offset();
1259 emitl(current);
1260 L->link_to(current);
1261 }
1262}
1263
1264
Steve Block3ce2e202009-11-05 08:53:23 +00001265void Assembler::jmp(Handle<Code> target, RelocInfo::Mode rmode) {
1266 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +00001267 // 1110 1001 #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +00001268 emit(0xE9);
1269 emit_code_target(target, rmode);
1270}
1271
1272
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001273void Assembler::jmp(Address entry, RelocInfo::Mode rmode) {
1274 DCHECK(RelocInfo::IsRuntimeEntry(rmode));
1275 EnsureSpace ensure_space(this);
1276 DCHECK(RelocInfo::IsRuntimeEntry(rmode));
1277 emit(0xE9);
1278 emit_runtime_entry(entry, rmode);
1279}
1280
1281
Steve Blocka7e24c12009-10-30 11:49:00 +00001282void Assembler::jmp(Register target) {
1283 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +00001284 // Opcode FF/4 r64.
Steve Block8defd9f2010-07-08 12:39:36 +01001285 emit_optional_rex_32(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001286 emit(0xFF);
1287 emit_modrm(0x4, target);
1288}
1289
1290
1291void Assembler::jmp(const Operand& src) {
1292 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +00001293 // Opcode FF/4 m64.
Steve Blocka7e24c12009-10-30 11:49:00 +00001294 emit_optional_rex_32(src);
1295 emit(0xFF);
1296 emit_operand(0x4, src);
1297}
1298
1299
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001300void Assembler::emit_lea(Register dst, const Operand& src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001301 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001302 emit_rex(dst, src, size);
Steve Block6ded16b2010-05-10 14:33:55 +01001303 emit(0x8D);
1304 emit_operand(dst, src);
1305}
1306
1307
Steve Blocka7e24c12009-10-30 11:49:00 +00001308void Assembler::load_rax(void* value, RelocInfo::Mode mode) {
1309 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001310 if (kPointerSize == kInt64Size) {
1311 emit(0x48); // REX.W
1312 emit(0xA1);
1313 emitp(value, mode);
1314 } else {
1315 DCHECK(kPointerSize == kInt32Size);
1316 emit(0xA1);
1317 emitp(value, mode);
1318 // In 64-bit mode, need to zero extend the operand to 8 bytes.
1319 // See 2.2.1.4 in Intel64 and IA32 Architectures Software
1320 // Developer's Manual Volume 2.
1321 emitl(0);
1322 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001323}
1324
1325
1326void Assembler::load_rax(ExternalReference ref) {
1327 load_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
1328}
1329
1330
1331void Assembler::leave() {
1332 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001333 emit(0xC9);
1334}
1335
1336
1337void Assembler::movb(Register dst, const Operand& src) {
1338 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001339 if (!dst.is_byte_register()) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001340 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1341 emit_rex_32(dst, src);
1342 } else {
1343 emit_optional_rex_32(dst, src);
1344 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001345 emit(0x8A);
1346 emit_operand(dst, src);
1347}
1348
Steve Block6ded16b2010-05-10 14:33:55 +01001349
Steve Blocka7e24c12009-10-30 11:49:00 +00001350void Assembler::movb(Register dst, Immediate imm) {
1351 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001352 if (!dst.is_byte_register()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001353 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001354 emit_rex_32(dst);
1355 }
1356 emit(0xB0 + dst.low_bits());
Steve Blocka7e24c12009-10-30 11:49:00 +00001357 emit(imm.value_);
1358}
1359
Steve Block6ded16b2010-05-10 14:33:55 +01001360
Steve Blocka7e24c12009-10-30 11:49:00 +00001361void Assembler::movb(const Operand& dst, Register src) {
1362 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001363 if (!src.is_byte_register()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001364 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001365 emit_rex_32(src, dst);
1366 } else {
1367 emit_optional_rex_32(src, dst);
1368 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001369 emit(0x88);
1370 emit_operand(src, dst);
1371}
1372
Steve Block6ded16b2010-05-10 14:33:55 +01001373
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001374void Assembler::movb(const Operand& dst, Immediate imm) {
1375 EnsureSpace ensure_space(this);
1376 emit_optional_rex_32(dst);
1377 emit(0xC6);
1378 emit_operand(0x0, dst);
1379 emit(static_cast<byte>(imm.value_));
1380}
1381
1382
1383void Assembler::movw(Register dst, const Operand& src) {
1384 EnsureSpace ensure_space(this);
1385 emit(0x66);
1386 emit_optional_rex_32(dst, src);
1387 emit(0x8B);
1388 emit_operand(dst, src);
1389}
1390
1391
Steve Block3ce2e202009-11-05 08:53:23 +00001392void Assembler::movw(const Operand& dst, Register src) {
1393 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001394 emit(0x66);
1395 emit_optional_rex_32(src, dst);
1396 emit(0x89);
1397 emit_operand(src, dst);
1398}
1399
Steve Block6ded16b2010-05-10 14:33:55 +01001400
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001401void Assembler::movw(const Operand& dst, Immediate imm) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001402 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001403 emit(0x66);
1404 emit_optional_rex_32(dst);
1405 emit(0xC7);
1406 emit_operand(0x0, dst);
1407 emit(static_cast<byte>(imm.value_ & 0xff));
1408 emit(static_cast<byte>(imm.value_ >> 8));
1409}
1410
1411
1412void Assembler::emit_mov(Register dst, const Operand& src, int size) {
1413 EnsureSpace ensure_space(this);
1414 emit_rex(dst, src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001415 emit(0x8B);
1416 emit_operand(dst, src);
1417}
1418
1419
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001420void Assembler::emit_mov(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001421 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +01001422 if (src.low_bits() == 4) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001423 emit_rex(src, dst, size);
Leon Clarkef7060e22010-06-03 12:02:55 +01001424 emit(0x89);
1425 emit_modrm(src, dst);
1426 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001427 emit_rex(dst, src, size);
Leon Clarkef7060e22010-06-03 12:02:55 +01001428 emit(0x8B);
1429 emit_modrm(dst, src);
1430 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001431}
1432
1433
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001434void Assembler::emit_mov(const Operand& dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001435 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001436 emit_rex(src, dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001437 emit(0x89);
1438 emit_operand(src, dst);
1439}
1440
1441
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001442void Assembler::emit_mov(Register dst, Immediate value, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001443 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001444 emit_rex(dst, size);
1445 if (size == kInt64Size) {
1446 emit(0xC7);
1447 emit_modrm(0x0, dst);
1448 } else {
1449 DCHECK(size == kInt32Size);
1450 emit(0xB8 + dst.low_bits());
1451 }
1452 emit(value);
1453}
1454
1455
1456void Assembler::emit_mov(const Operand& dst, Immediate value, int size) {
1457 EnsureSpace ensure_space(this);
1458 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001459 emit(0xC7);
1460 emit_operand(0x0, dst);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001461 emit(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001462}
1463
1464
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001465void Assembler::movp(Register dst, void* value, RelocInfo::Mode rmode) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001466 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001467 emit_rex(dst, kPointerSize);
1468 emit(0xB8 | dst.low_bits());
1469 emitp(value, rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001470}
1471
1472
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001473void Assembler::movq(Register dst, int64_t value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001474 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001475 emit_rex_64(dst);
1476 emit(0xB8 | dst.low_bits());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001477 emitq(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001478}
1479
1480
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001481void Assembler::movq(Register dst, uint64_t value) {
1482 movq(dst, static_cast<int64_t>(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001483}
1484
1485
Andrei Popescu31002712010-02-23 13:46:05 +00001486// Loads the ip-relative location of the src label into the target location
1487// (as a 32-bit offset sign extended to 64-bit).
Steve Blocka7e24c12009-10-30 11:49:00 +00001488void Assembler::movl(const Operand& dst, Label* src) {
1489 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001490 emit_optional_rex_32(dst);
1491 emit(0xC7);
1492 emit_operand(0, dst);
1493 if (src->is_bound()) {
1494 int offset = src->pos() - pc_offset() - sizeof(int32_t);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001495 DCHECK(offset <= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001496 emitl(offset);
1497 } else if (src->is_linked()) {
1498 emitl(src->pos());
1499 src->link_to(pc_offset() - sizeof(int32_t));
1500 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001501 DCHECK(src->is_unused());
Steve Blocka7e24c12009-10-30 11:49:00 +00001502 int32_t current = pc_offset();
1503 emitl(current);
1504 src->link_to(current);
1505 }
1506}
1507
1508
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001509void Assembler::movsxbl(Register dst, Register src) {
1510 EnsureSpace ensure_space(this);
1511 if (!src.is_byte_register()) {
1512 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1513 emit_rex_32(dst, src);
1514 } else {
1515 emit_optional_rex_32(dst, src);
1516 }
1517 emit(0x0F);
1518 emit(0xBE);
1519 emit_modrm(dst, src);
1520}
1521
1522
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001523void Assembler::movsxbl(Register dst, const Operand& src) {
1524 EnsureSpace ensure_space(this);
1525 emit_optional_rex_32(dst, src);
1526 emit(0x0F);
1527 emit(0xBE);
1528 emit_operand(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001529}
1530
1531
Steve Block3ce2e202009-11-05 08:53:23 +00001532void Assembler::movsxbq(Register dst, const Operand& src) {
1533 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001534 emit_rex_64(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00001535 emit(0x0F);
1536 emit(0xBE);
1537 emit_operand(dst, src);
1538}
1539
1540
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001541void Assembler::movsxwl(Register dst, Register src) {
1542 EnsureSpace ensure_space(this);
1543 emit_optional_rex_32(dst, src);
1544 emit(0x0F);
1545 emit(0xBF);
1546 emit_modrm(dst, src);
1547}
1548
1549
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001550void Assembler::movsxwl(Register dst, const Operand& src) {
1551 EnsureSpace ensure_space(this);
1552 emit_optional_rex_32(dst, src);
1553 emit(0x0F);
1554 emit(0xBF);
1555 emit_operand(dst, src);
1556}
1557
1558
Steve Block3ce2e202009-11-05 08:53:23 +00001559void Assembler::movsxwq(Register dst, const Operand& src) {
1560 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001561 emit_rex_64(dst, src);
1562 emit(0x0F);
1563 emit(0xBF);
1564 emit_operand(dst, src);
1565}
1566
1567
Steve Blocka7e24c12009-10-30 11:49:00 +00001568void Assembler::movsxlq(Register dst, Register src) {
1569 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001570 emit_rex_64(dst, src);
1571 emit(0x63);
1572 emit_modrm(dst, src);
1573}
1574
1575
1576void Assembler::movsxlq(Register dst, const Operand& src) {
1577 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001578 emit_rex_64(dst, src);
1579 emit(0x63);
1580 emit_operand(dst, src);
1581}
1582
1583
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001584void Assembler::emit_movzxb(Register dst, const Operand& src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001585 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001586 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
1587 // there is no need to make this a 64 bit operation.
Steve Block8defd9f2010-07-08 12:39:36 +01001588 emit_optional_rex_32(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001589 emit(0x0F);
1590 emit(0xB6);
1591 emit_operand(dst, src);
1592}
1593
1594
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001595void Assembler::emit_movzxb(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001596 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001597 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
1598 // there is no need to make this a 64 bit operation.
1599 if (!src.is_byte_register()) {
1600 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1601 emit_rex_32(dst, src);
1602 } else {
1603 emit_optional_rex_32(dst, src);
1604 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001605 emit(0x0F);
1606 emit(0xB6);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001607 emit_modrm(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001608}
1609
1610
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001611void Assembler::emit_movzxw(Register dst, const Operand& src, int size) {
Steve Block3ce2e202009-11-05 08:53:23 +00001612 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001613 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
1614 // there is no need to make this a 64 bit operation.
Steve Block8defd9f2010-07-08 12:39:36 +01001615 emit_optional_rex_32(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00001616 emit(0x0F);
1617 emit(0xB7);
1618 emit_operand(dst, src);
1619}
1620
1621
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001622void Assembler::emit_movzxw(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001623 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001624 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
1625 // there is no need to make this a 64 bit operation.
Steve Blocka7e24c12009-10-30 11:49:00 +00001626 emit_optional_rex_32(dst, src);
1627 emit(0x0F);
1628 emit(0xB7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001629 emit_modrm(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001630}
1631
1632
Leon Clarked91b9f72010-01-27 17:25:45 +00001633void Assembler::repmovsb() {
1634 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001635 emit(0xF3);
1636 emit(0xA4);
1637}
1638
1639
1640void Assembler::repmovsw() {
1641 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001642 emit(0x66); // Operand size override.
1643 emit(0xF3);
1644 emit(0xA4);
1645}
1646
1647
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001648void Assembler::emit_repmovs(int size) {
Leon Clarked91b9f72010-01-27 17:25:45 +00001649 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001650 emit(0xF3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001651 emit_rex(size);
Leon Clarked91b9f72010-01-27 17:25:45 +00001652 emit(0xA5);
1653}
1654
1655
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001656void Assembler::mull(Register src) {
1657 EnsureSpace ensure_space(this);
1658 emit_optional_rex_32(src);
1659 emit(0xF7);
1660 emit_modrm(0x4, src);
1661}
1662
1663
1664void Assembler::mull(const Operand& src) {
1665 EnsureSpace ensure_space(this);
1666 emit_optional_rex_32(src);
1667 emit(0xF7);
1668 emit_operand(0x4, src);
1669}
1670
1671
1672void Assembler::mulq(Register src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001673 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001674 emit_rex_64(src);
1675 emit(0xF7);
1676 emit_modrm(0x4, src);
1677}
1678
1679
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001680void Assembler::emit_neg(Register dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001681 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001682 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001683 emit(0xF7);
1684 emit_modrm(0x3, dst);
1685}
1686
1687
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001688void Assembler::emit_neg(const Operand& dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001689 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001690 emit_rex_64(dst);
1691 emit(0xF7);
1692 emit_operand(3, dst);
1693}
1694
1695
1696void Assembler::nop() {
1697 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001698 emit(0x90);
1699}
1700
1701
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001702void Assembler::emit_not(Register dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001703 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001704 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001705 emit(0xF7);
1706 emit_modrm(0x2, dst);
1707}
1708
1709
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001710void Assembler::emit_not(const Operand& dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001711 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001712 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001713 emit(0xF7);
1714 emit_operand(2, dst);
1715}
1716
1717
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001718void Assembler::Nop(int n) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001719 // The recommended muti-byte sequences of NOP instructions from the Intel 64
1720 // and IA-32 Architectures Software Developer's Manual.
1721 //
1722 // Length Assembly Byte Sequence
1723 // 2 bytes 66 NOP 66 90H
1724 // 3 bytes NOP DWORD ptr [EAX] 0F 1F 00H
1725 // 4 bytes NOP DWORD ptr [EAX + 00H] 0F 1F 40 00H
1726 // 5 bytes NOP DWORD ptr [EAX + EAX*1 + 00H] 0F 1F 44 00 00H
1727 // 6 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00H] 66 0F 1F 44 00 00H
1728 // 7 bytes NOP DWORD ptr [EAX + 00000000H] 0F 1F 80 00 00 00 00H
1729 // 8 bytes NOP DWORD ptr [EAX + EAX*1 + 00000000H] 0F 1F 84 00 00 00 00 00H
1730 // 9 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 66 0F 1F 84 00 00 00 00
1731 // 00000000H] 00H
1732
Steve Blocka7e24c12009-10-30 11:49:00 +00001733 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001734 while (n > 0) {
1735 switch (n) {
1736 case 2:
1737 emit(0x66);
1738 case 1:
1739 emit(0x90);
1740 return;
1741 case 3:
1742 emit(0x0f);
1743 emit(0x1f);
1744 emit(0x00);
1745 return;
1746 case 4:
1747 emit(0x0f);
1748 emit(0x1f);
1749 emit(0x40);
1750 emit(0x00);
1751 return;
1752 case 6:
1753 emit(0x66);
1754 case 5:
1755 emit(0x0f);
1756 emit(0x1f);
1757 emit(0x44);
1758 emit(0x00);
1759 emit(0x00);
1760 return;
1761 case 7:
1762 emit(0x0f);
1763 emit(0x1f);
1764 emit(0x80);
1765 emit(0x00);
1766 emit(0x00);
1767 emit(0x00);
1768 emit(0x00);
1769 return;
1770 default:
1771 case 11:
1772 emit(0x66);
1773 n--;
1774 case 10:
1775 emit(0x66);
1776 n--;
1777 case 9:
1778 emit(0x66);
1779 n--;
1780 case 8:
1781 emit(0x0f);
1782 emit(0x1f);
1783 emit(0x84);
1784 emit(0x00);
1785 emit(0x00);
1786 emit(0x00);
1787 emit(0x00);
1788 emit(0x00);
1789 n -= 8;
1790 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001791 }
1792}
1793
1794
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001795void Assembler::popq(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001796 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001797 emit_optional_rex_32(dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001798 emit(0x58 | dst.low_bits());
1799}
1800
1801
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001802void Assembler::popq(const Operand& dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001803 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001804 emit_optional_rex_32(dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001805 emit(0x8F);
1806 emit_operand(0, dst);
1807}
1808
1809
1810void Assembler::popfq() {
1811 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001812 emit(0x9D);
1813}
1814
1815
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001816void Assembler::pushq(Register src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001817 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001818 emit_optional_rex_32(src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001819 emit(0x50 | src.low_bits());
1820}
1821
1822
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001823void Assembler::pushq(const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001824 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001825 emit_optional_rex_32(src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001826 emit(0xFF);
1827 emit_operand(6, src);
1828}
1829
1830
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001831void Assembler::pushq(Immediate value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001832 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001833 if (is_int8(value.value_)) {
1834 emit(0x6A);
1835 emit(value.value_); // Emit low byte of value.
1836 } else {
1837 emit(0x68);
1838 emitl(value.value_);
1839 }
1840}
1841
1842
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001843void Assembler::pushq_imm32(int32_t imm32) {
Steve Block1e0659c2011-05-24 12:43:12 +01001844 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01001845 emit(0x68);
1846 emitl(imm32);
1847}
1848
1849
Steve Blocka7e24c12009-10-30 11:49:00 +00001850void Assembler::pushfq() {
1851 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001852 emit(0x9C);
1853}
1854
1855
Steve Blocka7e24c12009-10-30 11:49:00 +00001856void Assembler::ret(int imm16) {
1857 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001858 DCHECK(is_uint16(imm16));
Steve Blocka7e24c12009-10-30 11:49:00 +00001859 if (imm16 == 0) {
1860 emit(0xC3);
1861 } else {
1862 emit(0xC2);
1863 emit(imm16 & 0xFF);
1864 emit((imm16 >> 8) & 0xFF);
1865 }
1866}
1867
1868
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001869void Assembler::ud2() {
1870 EnsureSpace ensure_space(this);
1871 emit(0x0F);
1872 emit(0x0B);
1873}
1874
1875
Steve Blocka7e24c12009-10-30 11:49:00 +00001876void Assembler::setcc(Condition cc, Register reg) {
Steve Block3ce2e202009-11-05 08:53:23 +00001877 if (cc > last_condition) {
1878 movb(reg, Immediate(cc == always ? 1 : 0));
1879 return;
1880 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001881 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001882 DCHECK(is_uint4(cc));
1883 if (!reg.is_byte_register()) {
1884 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
Steve Blocka7e24c12009-10-30 11:49:00 +00001885 emit_rex_32(reg);
1886 }
1887 emit(0x0F);
1888 emit(0x90 | cc);
1889 emit_modrm(0x0, reg);
1890}
1891
1892
1893void Assembler::shld(Register dst, Register src) {
1894 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001895 emit_rex_64(src, dst);
1896 emit(0x0F);
1897 emit(0xA5);
1898 emit_modrm(src, dst);
1899}
1900
1901
1902void Assembler::shrd(Register dst, Register src) {
1903 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001904 emit_rex_64(src, dst);
1905 emit(0x0F);
1906 emit(0xAD);
1907 emit_modrm(src, dst);
1908}
1909
1910
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001911void Assembler::emit_xchg(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001912 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001913 if (src.is(rax) || dst.is(rax)) { // Single-byte encoding
1914 Register other = src.is(rax) ? dst : src;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001915 emit_rex(other, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001916 emit(0x90 | other.low_bits());
Leon Clarkef7060e22010-06-03 12:02:55 +01001917 } else if (dst.low_bits() == 4) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001918 emit_rex(dst, src, size);
Leon Clarkef7060e22010-06-03 12:02:55 +01001919 emit(0x87);
1920 emit_modrm(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001921 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001922 emit_rex(src, dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001923 emit(0x87);
1924 emit_modrm(src, dst);
1925 }
1926}
1927
1928
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001929void Assembler::emit_xchg(Register dst, const Operand& src, int size) {
1930 EnsureSpace ensure_space(this);
1931 emit_rex(dst, src, size);
1932 emit(0x87);
1933 emit_operand(dst, src);
1934}
1935
1936
Steve Blocka7e24c12009-10-30 11:49:00 +00001937void Assembler::store_rax(void* dst, RelocInfo::Mode mode) {
1938 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001939 if (kPointerSize == kInt64Size) {
1940 emit(0x48); // REX.W
1941 emit(0xA3);
1942 emitp(dst, mode);
1943 } else {
1944 DCHECK(kPointerSize == kInt32Size);
1945 emit(0xA3);
1946 emitp(dst, mode);
1947 // In 64-bit mode, need to zero extend the operand to 8 bytes.
1948 // See 2.2.1.4 in Intel64 and IA32 Architectures Software
1949 // Developer's Manual Volume 2.
1950 emitl(0);
1951 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001952}
1953
1954
1955void Assembler::store_rax(ExternalReference ref) {
1956 store_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
1957}
1958
1959
Steve Block3ce2e202009-11-05 08:53:23 +00001960void Assembler::testb(Register dst, Register src) {
1961 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +01001962 if (src.low_bits() == 4) {
1963 emit_rex_32(src, dst);
1964 emit(0x84);
1965 emit_modrm(src, dst);
1966 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001967 if (!dst.is_byte_register() || !src.is_byte_register()) {
Leon Clarkef7060e22010-06-03 12:02:55 +01001968 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1969 emit_rex_32(dst, src);
1970 }
1971 emit(0x84);
1972 emit_modrm(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00001973 }
Steve Block3ce2e202009-11-05 08:53:23 +00001974}
1975
1976
Steve Blocka7e24c12009-10-30 11:49:00 +00001977void Assembler::testb(Register reg, Immediate mask) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001978 DCHECK(is_int8(mask.value_) || is_uint8(mask.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +00001979 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001980 if (reg.is(rax)) {
1981 emit(0xA8);
1982 emit(mask.value_); // Low byte emitted.
1983 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001984 if (!reg.is_byte_register()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001985 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1986 emit_rex_32(reg);
1987 }
1988 emit(0xF6);
1989 emit_modrm(0x0, reg);
1990 emit(mask.value_); // Low byte emitted.
1991 }
1992}
1993
1994
1995void Assembler::testb(const Operand& op, Immediate mask) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001996 DCHECK(is_int8(mask.value_) || is_uint8(mask.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +00001997 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001998 emit_optional_rex_32(rax, op);
1999 emit(0xF6);
2000 emit_operand(rax, op); // Operation code 0
2001 emit(mask.value_); // Low byte emitted.
2002}
2003
2004
Leon Clarkee46be812010-01-19 14:06:41 +00002005void Assembler::testb(const Operand& op, Register reg) {
2006 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002007 if (!reg.is_byte_register()) {
Leon Clarkee46be812010-01-19 14:06:41 +00002008 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2009 emit_rex_32(reg, op);
2010 } else {
2011 emit_optional_rex_32(reg, op);
2012 }
2013 emit(0x84);
2014 emit_operand(reg, op);
2015}
2016
2017
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002018void Assembler::emit_test(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002019 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +01002020 if (src.low_bits() == 4) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002021 emit_rex(src, dst, size);
Leon Clarkef7060e22010-06-03 12:02:55 +01002022 emit(0x85);
2023 emit_modrm(src, dst);
2024 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002025 emit_rex(dst, src, size);
Leon Clarkef7060e22010-06-03 12:02:55 +01002026 emit(0x85);
2027 emit_modrm(dst, src);
2028 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002029}
2030
2031
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002032void Assembler::emit_test(Register reg, Immediate mask, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002033 // testl with a mask that fits in the low byte is exactly testb.
2034 if (is_uint8(mask.value_)) {
2035 testb(reg, mask);
2036 return;
2037 }
2038 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002039 if (reg.is(rax)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002040 emit_rex(rax, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00002041 emit(0xA9);
2042 emit(mask);
2043 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002044 emit_rex(reg, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00002045 emit(0xF7);
2046 emit_modrm(0x0, reg);
2047 emit(mask);
2048 }
2049}
2050
2051
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002052void Assembler::emit_test(const Operand& op, Immediate mask, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002053 // testl with a mask that fits in the low byte is exactly testb.
2054 if (is_uint8(mask.value_)) {
2055 testb(op, mask);
2056 return;
2057 }
2058 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002059 emit_rex(rax, op, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00002060 emit(0xF7);
2061 emit_operand(rax, op); // Operation code 0
2062 emit(mask);
2063}
2064
2065
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002066void Assembler::emit_test(const Operand& op, Register reg, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002067 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002068 emit_rex(reg, op, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00002069 emit(0x85);
2070 emit_operand(reg, op);
2071}
2072
2073
Andrei Popescu31002712010-02-23 13:46:05 +00002074// FPU instructions.
Steve Blocka7e24c12009-10-30 11:49:00 +00002075
2076
2077void Assembler::fld(int i) {
2078 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002079 emit_farith(0xD9, 0xC0, i);
2080}
2081
2082
2083void Assembler::fld1() {
2084 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002085 emit(0xD9);
2086 emit(0xE8);
2087}
2088
2089
2090void Assembler::fldz() {
2091 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002092 emit(0xD9);
2093 emit(0xEE);
2094}
2095
2096
Steve Block6ded16b2010-05-10 14:33:55 +01002097void Assembler::fldpi() {
2098 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002099 emit(0xD9);
2100 emit(0xEB);
2101}
2102
2103
Ben Murdochb0fe1622011-05-05 13:52:32 +01002104void Assembler::fldln2() {
2105 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002106 emit(0xD9);
2107 emit(0xED);
2108}
2109
2110
Steve Blocka7e24c12009-10-30 11:49:00 +00002111void Assembler::fld_s(const Operand& adr) {
2112 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002113 emit_optional_rex_32(adr);
2114 emit(0xD9);
2115 emit_operand(0, adr);
2116}
2117
2118
2119void Assembler::fld_d(const Operand& adr) {
2120 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002121 emit_optional_rex_32(adr);
2122 emit(0xDD);
2123 emit_operand(0, adr);
2124}
2125
2126
2127void Assembler::fstp_s(const Operand& adr) {
2128 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002129 emit_optional_rex_32(adr);
2130 emit(0xD9);
2131 emit_operand(3, adr);
2132}
2133
2134
2135void Assembler::fstp_d(const Operand& adr) {
2136 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002137 emit_optional_rex_32(adr);
2138 emit(0xDD);
2139 emit_operand(3, adr);
2140}
2141
2142
Steve Block3ce2e202009-11-05 08:53:23 +00002143void Assembler::fstp(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002144 DCHECK(is_uint3(index));
Steve Block3ce2e202009-11-05 08:53:23 +00002145 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00002146 emit_farith(0xDD, 0xD8, index);
2147}
2148
2149
Steve Blocka7e24c12009-10-30 11:49:00 +00002150void Assembler::fild_s(const Operand& adr) {
2151 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002152 emit_optional_rex_32(adr);
2153 emit(0xDB);
2154 emit_operand(0, adr);
2155}
2156
2157
2158void Assembler::fild_d(const Operand& adr) {
2159 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002160 emit_optional_rex_32(adr);
2161 emit(0xDF);
2162 emit_operand(5, adr);
2163}
2164
2165
2166void Assembler::fistp_s(const Operand& adr) {
2167 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002168 emit_optional_rex_32(adr);
2169 emit(0xDB);
2170 emit_operand(3, adr);
2171}
2172
2173
2174void Assembler::fisttp_s(const Operand& adr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002175 DCHECK(IsEnabled(SSE3));
Steve Blocka7e24c12009-10-30 11:49:00 +00002176 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002177 emit_optional_rex_32(adr);
2178 emit(0xDB);
2179 emit_operand(1, adr);
2180}
2181
2182
Leon Clarked91b9f72010-01-27 17:25:45 +00002183void Assembler::fisttp_d(const Operand& adr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002184 DCHECK(IsEnabled(SSE3));
Leon Clarked91b9f72010-01-27 17:25:45 +00002185 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00002186 emit_optional_rex_32(adr);
2187 emit(0xDD);
2188 emit_operand(1, adr);
2189}
2190
2191
Steve Blocka7e24c12009-10-30 11:49:00 +00002192void Assembler::fist_s(const Operand& adr) {
2193 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002194 emit_optional_rex_32(adr);
2195 emit(0xDB);
2196 emit_operand(2, adr);
2197}
2198
2199
2200void Assembler::fistp_d(const Operand& adr) {
2201 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002202 emit_optional_rex_32(adr);
2203 emit(0xDF);
Steve Block3ce2e202009-11-05 08:53:23 +00002204 emit_operand(7, adr);
Steve Blocka7e24c12009-10-30 11:49:00 +00002205}
2206
2207
2208void Assembler::fabs() {
2209 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002210 emit(0xD9);
2211 emit(0xE1);
2212}
2213
2214
2215void Assembler::fchs() {
2216 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002217 emit(0xD9);
2218 emit(0xE0);
2219}
2220
2221
2222void Assembler::fcos() {
2223 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002224 emit(0xD9);
2225 emit(0xFF);
2226}
2227
2228
2229void Assembler::fsin() {
2230 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002231 emit(0xD9);
2232 emit(0xFE);
2233}
2234
2235
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002236void Assembler::fptan() {
2237 EnsureSpace ensure_space(this);
2238 emit(0xD9);
2239 emit(0xF2);
2240}
2241
2242
Ben Murdochb0fe1622011-05-05 13:52:32 +01002243void Assembler::fyl2x() {
2244 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002245 emit(0xD9);
2246 emit(0xF1);
2247}
2248
2249
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002250void Assembler::f2xm1() {
2251 EnsureSpace ensure_space(this);
2252 emit(0xD9);
2253 emit(0xF0);
2254}
2255
2256
2257void Assembler::fscale() {
2258 EnsureSpace ensure_space(this);
2259 emit(0xD9);
2260 emit(0xFD);
2261}
2262
2263
2264void Assembler::fninit() {
2265 EnsureSpace ensure_space(this);
2266 emit(0xDB);
2267 emit(0xE3);
2268}
2269
2270
Steve Blocka7e24c12009-10-30 11:49:00 +00002271void Assembler::fadd(int i) {
2272 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002273 emit_farith(0xDC, 0xC0, i);
2274}
2275
2276
2277void Assembler::fsub(int i) {
2278 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002279 emit_farith(0xDC, 0xE8, i);
2280}
2281
2282
2283void Assembler::fisub_s(const Operand& adr) {
2284 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002285 emit_optional_rex_32(adr);
2286 emit(0xDA);
2287 emit_operand(4, adr);
2288}
2289
2290
2291void Assembler::fmul(int i) {
2292 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002293 emit_farith(0xDC, 0xC8, i);
2294}
2295
2296
2297void Assembler::fdiv(int i) {
2298 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002299 emit_farith(0xDC, 0xF8, i);
2300}
2301
2302
2303void Assembler::faddp(int i) {
2304 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002305 emit_farith(0xDE, 0xC0, i);
2306}
2307
2308
2309void Assembler::fsubp(int i) {
2310 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002311 emit_farith(0xDE, 0xE8, i);
2312}
2313
2314
2315void Assembler::fsubrp(int i) {
2316 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002317 emit_farith(0xDE, 0xE0, i);
2318}
2319
2320
2321void Assembler::fmulp(int i) {
2322 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002323 emit_farith(0xDE, 0xC8, i);
2324}
2325
2326
2327void Assembler::fdivp(int i) {
2328 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002329 emit_farith(0xDE, 0xF8, i);
2330}
2331
2332
2333void Assembler::fprem() {
2334 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002335 emit(0xD9);
2336 emit(0xF8);
2337}
2338
2339
2340void Assembler::fprem1() {
2341 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002342 emit(0xD9);
2343 emit(0xF5);
2344}
2345
2346
2347void Assembler::fxch(int i) {
2348 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002349 emit_farith(0xD9, 0xC8, i);
2350}
2351
2352
2353void Assembler::fincstp() {
2354 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002355 emit(0xD9);
2356 emit(0xF7);
2357}
2358
2359
2360void Assembler::ffree(int i) {
2361 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002362 emit_farith(0xDD, 0xC0, i);
2363}
2364
2365
2366void Assembler::ftst() {
2367 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002368 emit(0xD9);
2369 emit(0xE4);
2370}
2371
2372
2373void Assembler::fucomp(int i) {
2374 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002375 emit_farith(0xDD, 0xE8, i);
2376}
2377
2378
2379void Assembler::fucompp() {
2380 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002381 emit(0xDA);
2382 emit(0xE9);
2383}
2384
2385
Steve Block3ce2e202009-11-05 08:53:23 +00002386void Assembler::fucomi(int i) {
2387 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00002388 emit(0xDB);
2389 emit(0xE8 + i);
2390}
2391
2392
2393void Assembler::fucomip() {
2394 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00002395 emit(0xDF);
2396 emit(0xE9);
2397}
2398
2399
Steve Blocka7e24c12009-10-30 11:49:00 +00002400void Assembler::fcompp() {
2401 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002402 emit(0xDE);
2403 emit(0xD9);
2404}
2405
2406
2407void Assembler::fnstsw_ax() {
2408 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002409 emit(0xDF);
2410 emit(0xE0);
2411}
2412
2413
2414void Assembler::fwait() {
2415 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002416 emit(0x9B);
2417}
2418
2419
2420void Assembler::frndint() {
2421 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002422 emit(0xD9);
2423 emit(0xFC);
2424}
2425
2426
2427void Assembler::fnclex() {
2428 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002429 emit(0xDB);
2430 emit(0xE2);
2431}
2432
2433
2434void Assembler::sahf() {
2435 // TODO(X64): Test for presence. Not all 64-bit intel CPU's have sahf
2436 // in 64-bit mode. Test CpuID.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002437 DCHECK(IsEnabled(SAHF));
Steve Blocka7e24c12009-10-30 11:49:00 +00002438 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002439 emit(0x9E);
2440}
2441
2442
2443void Assembler::emit_farith(int b1, int b2, int i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002444 DCHECK(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2445 DCHECK(is_uint3(i)); // illegal stack offset
Steve Blocka7e24c12009-10-30 11:49:00 +00002446 emit(b1);
2447 emit(b2 + i);
2448}
2449
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002450
2451// SSE operations.
2452
2453void Assembler::andps(XMMRegister dst, XMMRegister src) {
2454 EnsureSpace ensure_space(this);
2455 emit_optional_rex_32(dst, src);
2456 emit(0x0F);
2457 emit(0x54);
2458 emit_sse_operand(dst, src);
2459}
2460
2461
2462void Assembler::andps(XMMRegister dst, const Operand& src) {
2463 EnsureSpace ensure_space(this);
2464 emit_optional_rex_32(dst, src);
2465 emit(0x0F);
2466 emit(0x54);
2467 emit_sse_operand(dst, src);
2468}
2469
2470
2471void Assembler::orps(XMMRegister dst, XMMRegister src) {
2472 EnsureSpace ensure_space(this);
2473 emit_optional_rex_32(dst, src);
2474 emit(0x0F);
2475 emit(0x56);
2476 emit_sse_operand(dst, src);
2477}
2478
2479
2480void Assembler::orps(XMMRegister dst, const Operand& src) {
2481 EnsureSpace ensure_space(this);
2482 emit_optional_rex_32(dst, src);
2483 emit(0x0F);
2484 emit(0x56);
2485 emit_sse_operand(dst, src);
2486}
2487
2488
2489void Assembler::xorps(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002490 DCHECK(!IsEnabled(AVX));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002491 EnsureSpace ensure_space(this);
2492 emit_optional_rex_32(dst, src);
2493 emit(0x0F);
2494 emit(0x57);
2495 emit_sse_operand(dst, src);
2496}
2497
2498
2499void Assembler::xorps(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002500 DCHECK(!IsEnabled(AVX));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002501 EnsureSpace ensure_space(this);
2502 emit_optional_rex_32(dst, src);
2503 emit(0x0F);
2504 emit(0x57);
2505 emit_sse_operand(dst, src);
2506}
2507
2508
2509void Assembler::addps(XMMRegister dst, XMMRegister src) {
2510 EnsureSpace ensure_space(this);
2511 emit_optional_rex_32(dst, src);
2512 emit(0x0F);
2513 emit(0x58);
2514 emit_sse_operand(dst, src);
2515}
2516
2517
2518void Assembler::addps(XMMRegister dst, const Operand& src) {
2519 EnsureSpace ensure_space(this);
2520 emit_optional_rex_32(dst, src);
2521 emit(0x0F);
2522 emit(0x58);
2523 emit_sse_operand(dst, src);
2524}
2525
2526
2527void Assembler::subps(XMMRegister dst, XMMRegister src) {
2528 EnsureSpace ensure_space(this);
2529 emit_optional_rex_32(dst, src);
2530 emit(0x0F);
2531 emit(0x5C);
2532 emit_sse_operand(dst, src);
2533}
2534
2535
2536void Assembler::subps(XMMRegister dst, const Operand& src) {
2537 EnsureSpace ensure_space(this);
2538 emit_optional_rex_32(dst, src);
2539 emit(0x0F);
2540 emit(0x5C);
2541 emit_sse_operand(dst, src);
2542}
2543
2544
2545void Assembler::mulps(XMMRegister dst, XMMRegister src) {
2546 EnsureSpace ensure_space(this);
2547 emit_optional_rex_32(dst, src);
2548 emit(0x0F);
2549 emit(0x59);
2550 emit_sse_operand(dst, src);
2551}
2552
2553
2554void Assembler::mulps(XMMRegister dst, const Operand& src) {
2555 EnsureSpace ensure_space(this);
2556 emit_optional_rex_32(dst, src);
2557 emit(0x0F);
2558 emit(0x59);
2559 emit_sse_operand(dst, src);
2560}
2561
2562
2563void Assembler::divps(XMMRegister dst, XMMRegister src) {
2564 EnsureSpace ensure_space(this);
2565 emit_optional_rex_32(dst, src);
2566 emit(0x0F);
2567 emit(0x5E);
2568 emit_sse_operand(dst, src);
2569}
2570
2571
2572void Assembler::divps(XMMRegister dst, const Operand& src) {
2573 EnsureSpace ensure_space(this);
2574 emit_optional_rex_32(dst, src);
2575 emit(0x0F);
2576 emit(0x5E);
2577 emit_sse_operand(dst, src);
2578}
2579
2580
Andrei Popescu31002712010-02-23 13:46:05 +00002581// SSE 2 operations.
Steve Blocka7e24c12009-10-30 11:49:00 +00002582
Steve Block6ded16b2010-05-10 14:33:55 +01002583void Assembler::movd(XMMRegister dst, Register src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002584 DCHECK(!IsEnabled(AVX));
2585 EnsureSpace ensure_space(this);
2586 emit(0x66);
2587 emit_optional_rex_32(dst, src);
2588 emit(0x0F);
2589 emit(0x6E);
2590 emit_sse_operand(dst, src);
2591}
2592
2593
2594void Assembler::movd(XMMRegister dst, const Operand& src) {
2595 DCHECK(!IsEnabled(AVX));
Steve Block6ded16b2010-05-10 14:33:55 +01002596 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002597 emit(0x66);
2598 emit_optional_rex_32(dst, src);
2599 emit(0x0F);
2600 emit(0x6E);
2601 emit_sse_operand(dst, src);
2602}
2603
2604
2605void Assembler::movd(Register dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002606 DCHECK(!IsEnabled(AVX));
Steve Block6ded16b2010-05-10 14:33:55 +01002607 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002608 emit(0x66);
Ben Murdochbb769b22010-08-11 14:56:33 +01002609 emit_optional_rex_32(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002610 emit(0x0F);
2611 emit(0x7E);
Ben Murdochbb769b22010-08-11 14:56:33 +01002612 emit_sse_operand(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002613}
2614
2615
2616void Assembler::movq(XMMRegister dst, Register src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002617 DCHECK(!IsEnabled(AVX));
Steve Block6ded16b2010-05-10 14:33:55 +01002618 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002619 emit(0x66);
2620 emit_rex_64(dst, src);
2621 emit(0x0F);
2622 emit(0x6E);
2623 emit_sse_operand(dst, src);
2624}
2625
2626
2627void Assembler::movq(Register dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002628 DCHECK(!IsEnabled(AVX));
Steve Block6ded16b2010-05-10 14:33:55 +01002629 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002630 emit(0x66);
Ben Murdochbb769b22010-08-11 14:56:33 +01002631 emit_rex_64(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002632 emit(0x0F);
2633 emit(0x7E);
Ben Murdochbb769b22010-08-11 14:56:33 +01002634 emit_sse_operand(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002635}
2636
2637
Ben Murdoch257744e2011-11-30 15:57:28 +00002638void Assembler::movq(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002639 DCHECK(!IsEnabled(AVX));
Ben Murdoch257744e2011-11-30 15:57:28 +00002640 EnsureSpace ensure_space(this);
2641 if (dst.low_bits() == 4) {
2642 // Avoid unnecessary SIB byte.
2643 emit(0xf3);
2644 emit_optional_rex_32(dst, src);
2645 emit(0x0F);
2646 emit(0x7e);
2647 emit_sse_operand(dst, src);
2648 } else {
2649 emit(0x66);
2650 emit_optional_rex_32(src, dst);
2651 emit(0x0F);
2652 emit(0xD6);
2653 emit_sse_operand(src, dst);
2654 }
2655}
2656
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002657
Ben Murdoch8b112d22011-06-08 16:22:53 +01002658void Assembler::movdqa(const Operand& dst, XMMRegister src) {
2659 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002660 emit(0x66);
2661 emit_rex_64(src, dst);
2662 emit(0x0F);
2663 emit(0x7F);
2664 emit_sse_operand(src, dst);
2665}
2666
2667
2668void Assembler::movdqa(XMMRegister dst, const Operand& src) {
Steve Block1e0659c2011-05-24 12:43:12 +01002669 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002670 emit(0x66);
2671 emit_rex_64(dst, src);
2672 emit(0x0F);
2673 emit(0x6F);
2674 emit_sse_operand(dst, src);
2675}
2676
2677
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002678void Assembler::movdqu(const Operand& dst, XMMRegister src) {
2679 EnsureSpace ensure_space(this);
2680 emit(0xF3);
2681 emit_rex_64(src, dst);
2682 emit(0x0F);
2683 emit(0x7F);
2684 emit_sse_operand(src, dst);
2685}
2686
2687
2688void Assembler::movdqu(XMMRegister dst, const Operand& src) {
2689 EnsureSpace ensure_space(this);
2690 emit(0xF3);
2691 emit_rex_64(dst, src);
2692 emit(0x0F);
2693 emit(0x6F);
2694 emit_sse_operand(dst, src);
2695}
2696
2697
Steve Block6ded16b2010-05-10 14:33:55 +01002698void Assembler::extractps(Register dst, XMMRegister src, byte imm8) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002699 DCHECK(IsEnabled(SSE4_1));
2700 DCHECK(is_uint8(imm8));
Steve Block6ded16b2010-05-10 14:33:55 +01002701 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002702 emit(0x66);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002703 emit_optional_rex_32(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002704 emit(0x0F);
2705 emit(0x3A);
2706 emit(0x17);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002707 emit_sse_operand(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002708 emit(imm8);
2709}
2710
2711
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002712void Assembler::pextrd(Register dst, XMMRegister src, int8_t imm8) {
2713 DCHECK(IsEnabled(SSE4_1));
2714 EnsureSpace ensure_space(this);
2715 emit(0x66);
2716 emit_optional_rex_32(src, dst);
2717 emit(0x0F);
2718 emit(0x3A);
2719 emit(0x16);
2720 emit_sse_operand(src, dst);
2721 emit(imm8);
2722}
2723
2724
2725void Assembler::pinsrd(XMMRegister dst, Register src, int8_t imm8) {
2726 DCHECK(IsEnabled(SSE4_1));
2727 EnsureSpace ensure_space(this);
2728 emit(0x66);
2729 emit_optional_rex_32(dst, src);
2730 emit(0x0F);
2731 emit(0x3A);
2732 emit(0x22);
2733 emit_sse_operand(dst, src);
2734 emit(imm8);
2735}
2736
2737
2738void Assembler::pinsrd(XMMRegister dst, const Operand& src, int8_t imm8) {
2739 DCHECK(IsEnabled(SSE4_1));
2740 EnsureSpace ensure_space(this);
2741 emit(0x66);
2742 emit_optional_rex_32(dst, src);
2743 emit(0x0F);
2744 emit(0x3A);
2745 emit(0x22);
2746 emit_sse_operand(dst, src);
2747 emit(imm8);
2748}
2749
2750
Steve Blocka7e24c12009-10-30 11:49:00 +00002751void Assembler::movsd(const Operand& dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002752 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00002753 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002754 emit(0xF2); // double
2755 emit_optional_rex_32(src, dst);
2756 emit(0x0F);
2757 emit(0x11); // store
2758 emit_sse_operand(src, dst);
2759}
2760
2761
Steve Block3ce2e202009-11-05 08:53:23 +00002762void Assembler::movsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002763 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00002764 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002765 emit(0xF2); // double
2766 emit_optional_rex_32(dst, src);
2767 emit(0x0F);
2768 emit(0x10); // load
2769 emit_sse_operand(dst, src);
2770}
2771
2772
2773void Assembler::movsd(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002774 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00002775 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002776 emit(0xF2); // double
2777 emit_optional_rex_32(dst, src);
2778 emit(0x0F);
2779 emit(0x10); // load
2780 emit_sse_operand(dst, src);
2781}
2782
2783
Ben Murdoch257744e2011-11-30 15:57:28 +00002784void Assembler::movaps(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002785 DCHECK(!IsEnabled(AVX));
Ben Murdoch257744e2011-11-30 15:57:28 +00002786 EnsureSpace ensure_space(this);
2787 if (src.low_bits() == 4) {
2788 // Try to avoid an unnecessary SIB byte.
2789 emit_optional_rex_32(src, dst);
2790 emit(0x0F);
2791 emit(0x29);
2792 emit_sse_operand(src, dst);
2793 } else {
2794 emit_optional_rex_32(dst, src);
2795 emit(0x0F);
2796 emit(0x28);
2797 emit_sse_operand(dst, src);
2798 }
2799}
2800
2801
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002802void Assembler::shufps(XMMRegister dst, XMMRegister src, byte imm8) {
2803 DCHECK(is_uint8(imm8));
2804 EnsureSpace ensure_space(this);
2805 emit_optional_rex_32(src, dst);
2806 emit(0x0F);
2807 emit(0xC6);
2808 emit_sse_operand(dst, src);
2809 emit(imm8);
2810}
2811
2812
Ben Murdoch257744e2011-11-30 15:57:28 +00002813void Assembler::movapd(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002814 DCHECK(!IsEnabled(AVX));
Ben Murdoch257744e2011-11-30 15:57:28 +00002815 EnsureSpace ensure_space(this);
2816 if (src.low_bits() == 4) {
2817 // Try to avoid an unnecessary SIB byte.
2818 emit(0x66);
2819 emit_optional_rex_32(src, dst);
2820 emit(0x0F);
2821 emit(0x29);
2822 emit_sse_operand(src, dst);
2823 } else {
2824 emit(0x66);
2825 emit_optional_rex_32(dst, src);
2826 emit(0x0F);
2827 emit(0x28);
2828 emit_sse_operand(dst, src);
2829 }
2830}
2831
2832
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002833void Assembler::addss(XMMRegister dst, XMMRegister src) {
2834 EnsureSpace ensure_space(this);
2835 emit(0xF3);
2836 emit_optional_rex_32(dst, src);
2837 emit(0x0F);
2838 emit(0x58);
2839 emit_sse_operand(dst, src);
2840}
2841
2842
2843void Assembler::addss(XMMRegister dst, const Operand& src) {
2844 EnsureSpace ensure_space(this);
2845 emit(0xF3);
2846 emit_optional_rex_32(dst, src);
2847 emit(0x0F);
2848 emit(0x58);
2849 emit_sse_operand(dst, src);
2850}
2851
2852
2853void Assembler::subss(XMMRegister dst, XMMRegister src) {
2854 EnsureSpace ensure_space(this);
2855 emit(0xF3);
2856 emit_optional_rex_32(dst, src);
2857 emit(0x0F);
2858 emit(0x5C);
2859 emit_sse_operand(dst, src);
2860}
2861
2862
2863void Assembler::subss(XMMRegister dst, const Operand& src) {
2864 EnsureSpace ensure_space(this);
2865 emit(0xF3);
2866 emit_optional_rex_32(dst, src);
2867 emit(0x0F);
2868 emit(0x5C);
2869 emit_sse_operand(dst, src);
2870}
2871
2872
2873void Assembler::mulss(XMMRegister dst, XMMRegister src) {
2874 EnsureSpace ensure_space(this);
2875 emit(0xF3);
2876 emit_optional_rex_32(dst, src);
2877 emit(0x0F);
2878 emit(0x59);
2879 emit_sse_operand(dst, src);
2880}
2881
2882
2883void Assembler::mulss(XMMRegister dst, const Operand& src) {
2884 EnsureSpace ensure_space(this);
2885 emit(0xF3);
2886 emit_optional_rex_32(dst, src);
2887 emit(0x0F);
2888 emit(0x59);
2889 emit_sse_operand(dst, src);
2890}
2891
2892
2893void Assembler::divss(XMMRegister dst, XMMRegister src) {
2894 EnsureSpace ensure_space(this);
2895 emit(0xF3);
2896 emit_optional_rex_32(dst, src);
2897 emit(0x0F);
2898 emit(0x5E);
2899 emit_sse_operand(dst, src);
2900}
2901
2902
2903void Assembler::divss(XMMRegister dst, const Operand& src) {
2904 EnsureSpace ensure_space(this);
2905 emit(0xF3);
2906 emit_optional_rex_32(dst, src);
2907 emit(0x0F);
2908 emit(0x5E);
2909 emit_sse_operand(dst, src);
2910}
2911
2912
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002913void Assembler::maxss(XMMRegister dst, XMMRegister src) {
2914 EnsureSpace ensure_space(this);
2915 emit(0xF3);
2916 emit_optional_rex_32(dst, src);
2917 emit(0x0F);
2918 emit(0x5F);
2919 emit_sse_operand(dst, src);
2920}
2921
2922
2923void Assembler::maxss(XMMRegister dst, const Operand& src) {
2924 EnsureSpace ensure_space(this);
2925 emit(0xF3);
2926 emit_optional_rex_32(dst, src);
2927 emit(0x0F);
2928 emit(0x5F);
2929 emit_sse_operand(dst, src);
2930}
2931
2932
2933void Assembler::minss(XMMRegister dst, XMMRegister src) {
2934 EnsureSpace ensure_space(this);
2935 emit(0xF3);
2936 emit_optional_rex_32(dst, src);
2937 emit(0x0F);
2938 emit(0x5D);
2939 emit_sse_operand(dst, src);
2940}
2941
2942
2943void Assembler::minss(XMMRegister dst, const Operand& src) {
2944 EnsureSpace ensure_space(this);
2945 emit(0xF3);
2946 emit_optional_rex_32(dst, src);
2947 emit(0x0F);
2948 emit(0x5D);
2949 emit_sse_operand(dst, src);
2950}
2951
2952
2953void Assembler::sqrtss(XMMRegister dst, XMMRegister src) {
2954 EnsureSpace ensure_space(this);
2955 emit(0xF3);
2956 emit_optional_rex_32(dst, src);
2957 emit(0x0F);
2958 emit(0x51);
2959 emit_sse_operand(dst, src);
2960}
2961
2962
2963void Assembler::sqrtss(XMMRegister dst, const Operand& src) {
2964 EnsureSpace ensure_space(this);
2965 emit(0xF3);
2966 emit_optional_rex_32(dst, src);
2967 emit(0x0F);
2968 emit(0x51);
2969 emit_sse_operand(dst, src);
2970}
2971
2972
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002973void Assembler::ucomiss(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002974 DCHECK(!IsEnabled(AVX));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002975 EnsureSpace ensure_space(this);
2976 emit_optional_rex_32(dst, src);
2977 emit(0x0f);
2978 emit(0x2e);
2979 emit_sse_operand(dst, src);
2980}
2981
2982
2983void Assembler::ucomiss(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002984 DCHECK(!IsEnabled(AVX));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002985 EnsureSpace ensure_space(this);
2986 emit_optional_rex_32(dst, src);
2987 emit(0x0f);
2988 emit(0x2e);
2989 emit_sse_operand(dst, src);
2990}
2991
2992
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002993void Assembler::movss(XMMRegister dst, XMMRegister src) {
2994 DCHECK(!IsEnabled(AVX));
2995 EnsureSpace ensure_space(this);
2996 emit(0xF3); // single
2997 emit_optional_rex_32(dst, src);
2998 emit(0x0F);
2999 emit(0x10); // load
3000 emit_sse_operand(dst, src);
3001}
3002
3003
Steve Block8defd9f2010-07-08 12:39:36 +01003004void Assembler::movss(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003005 DCHECK(!IsEnabled(AVX));
Steve Block8defd9f2010-07-08 12:39:36 +01003006 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003007 emit(0xF3); // single
3008 emit_optional_rex_32(dst, src);
3009 emit(0x0F);
3010 emit(0x10); // load
3011 emit_sse_operand(dst, src);
3012}
3013
3014
3015void Assembler::movss(const Operand& src, XMMRegister dst) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003016 DCHECK(!IsEnabled(AVX));
Steve Block8defd9f2010-07-08 12:39:36 +01003017 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003018 emit(0xF3); // single
3019 emit_optional_rex_32(dst, src);
3020 emit(0x0F);
3021 emit(0x11); // store
3022 emit_sse_operand(dst, src);
3023}
3024
3025
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003026void Assembler::psllq(XMMRegister reg, byte imm8) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003027 DCHECK(!IsEnabled(AVX));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003028 EnsureSpace ensure_space(this);
3029 emit(0x66);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003030 emit_optional_rex_32(reg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003031 emit(0x0F);
3032 emit(0x73);
3033 emit_sse_operand(rsi, reg); // rsi == 6
3034 emit(imm8);
3035}
3036
3037
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003038void Assembler::psrlq(XMMRegister reg, byte imm8) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003039 DCHECK(!IsEnabled(AVX));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003040 EnsureSpace ensure_space(this);
3041 emit(0x66);
3042 emit_optional_rex_32(reg);
3043 emit(0x0F);
3044 emit(0x73);
3045 emit_sse_operand(rdx, reg); // rdx == 2
3046 emit(imm8);
3047}
3048
3049
3050void Assembler::pslld(XMMRegister reg, byte imm8) {
3051 EnsureSpace ensure_space(this);
3052 emit(0x66);
3053 emit_optional_rex_32(reg);
3054 emit(0x0F);
3055 emit(0x72);
3056 emit_sse_operand(rsi, reg); // rsi == 6
3057 emit(imm8);
3058}
3059
3060
3061void Assembler::psrld(XMMRegister reg, byte imm8) {
3062 EnsureSpace ensure_space(this);
3063 emit(0x66);
3064 emit_optional_rex_32(reg);
3065 emit(0x0F);
3066 emit(0x72);
3067 emit_sse_operand(rdx, reg); // rdx == 2
3068 emit(imm8);
3069}
3070
3071
Steve Blocka7e24c12009-10-30 11:49:00 +00003072void Assembler::cvttss2si(Register dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003073 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00003074 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003075 emit(0xF3);
3076 emit_optional_rex_32(dst, src);
3077 emit(0x0F);
3078 emit(0x2C);
3079 emit_operand(dst, src);
3080}
3081
3082
Steve Block1e0659c2011-05-24 12:43:12 +01003083void Assembler::cvttss2si(Register dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003084 DCHECK(!IsEnabled(AVX));
Steve Block1e0659c2011-05-24 12:43:12 +01003085 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01003086 emit(0xF3);
3087 emit_optional_rex_32(dst, src);
3088 emit(0x0F);
3089 emit(0x2C);
3090 emit_sse_operand(dst, src);
3091}
3092
3093
Steve Blocka7e24c12009-10-30 11:49:00 +00003094void Assembler::cvttsd2si(Register dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003095 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00003096 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003097 emit(0xF2);
3098 emit_optional_rex_32(dst, src);
3099 emit(0x0F);
3100 emit(0x2C);
3101 emit_operand(dst, src);
3102}
3103
3104
Steve Block1e0659c2011-05-24 12:43:12 +01003105void Assembler::cvttsd2si(Register dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003106 DCHECK(!IsEnabled(AVX));
Steve Block1e0659c2011-05-24 12:43:12 +01003107 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01003108 emit(0xF2);
3109 emit_optional_rex_32(dst, src);
3110 emit(0x0F);
3111 emit(0x2C);
3112 emit_sse_operand(dst, src);
3113}
3114
3115
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003116void Assembler::cvttss2siq(Register dst, XMMRegister src) {
3117 DCHECK(!IsEnabled(AVX));
3118 EnsureSpace ensure_space(this);
3119 emit(0xF3);
3120 emit_rex_64(dst, src);
3121 emit(0x0F);
3122 emit(0x2C);
3123 emit_sse_operand(dst, src);
3124}
3125
3126
3127void Assembler::cvttss2siq(Register dst, const Operand& src) {
3128 DCHECK(!IsEnabled(AVX));
3129 EnsureSpace ensure_space(this);
3130 emit(0xF3);
3131 emit_rex_64(dst, src);
3132 emit(0x0F);
3133 emit(0x2C);
3134 emit_sse_operand(dst, src);
3135}
3136
3137
Kristian Monsen25f61362010-05-21 11:50:48 +01003138void Assembler::cvttsd2siq(Register dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003139 DCHECK(!IsEnabled(AVX));
Kristian Monsen25f61362010-05-21 11:50:48 +01003140 EnsureSpace ensure_space(this);
Kristian Monsen25f61362010-05-21 11:50:48 +01003141 emit(0xF2);
3142 emit_rex_64(dst, src);
3143 emit(0x0F);
3144 emit(0x2C);
3145 emit_sse_operand(dst, src);
3146}
3147
3148
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003149void Assembler::cvttsd2siq(Register dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003150 DCHECK(!IsEnabled(AVX));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003151 EnsureSpace ensure_space(this);
3152 emit(0xF2);
3153 emit_rex_64(dst, src);
3154 emit(0x0F);
3155 emit(0x2C);
3156 emit_sse_operand(dst, src);
3157}
3158
3159
Steve Blocka7e24c12009-10-30 11:49:00 +00003160void Assembler::cvtlsi2sd(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003161 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00003162 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003163 emit(0xF2);
3164 emit_optional_rex_32(dst, src);
3165 emit(0x0F);
3166 emit(0x2A);
3167 emit_sse_operand(dst, src);
3168}
3169
3170
3171void Assembler::cvtlsi2sd(XMMRegister dst, Register src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003172 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00003173 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003174 emit(0xF2);
3175 emit_optional_rex_32(dst, src);
3176 emit(0x0F);
3177 emit(0x2A);
3178 emit_sse_operand(dst, src);
3179}
3180
3181
Ben Murdoch097c5b22016-05-18 11:27:45 +01003182void Assembler::cvtlsi2ss(XMMRegister dst, const Operand& src) {
3183 DCHECK(!IsEnabled(AVX));
3184 EnsureSpace ensure_space(this);
3185 emit(0xF3);
3186 emit_optional_rex_32(dst, src);
3187 emit(0x0F);
3188 emit(0x2A);
3189 emit_sse_operand(dst, src);
3190}
3191
3192
Steve Block8defd9f2010-07-08 12:39:36 +01003193void Assembler::cvtlsi2ss(XMMRegister dst, Register src) {
3194 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003195 emit(0xF3);
3196 emit_optional_rex_32(dst, src);
3197 emit(0x0F);
3198 emit(0x2A);
3199 emit_sse_operand(dst, src);
3200}
3201
3202
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003203void Assembler::cvtqsi2ss(XMMRegister dst, const Operand& src) {
3204 DCHECK(!IsEnabled(AVX));
3205 EnsureSpace ensure_space(this);
3206 emit(0xF3);
3207 emit_rex_64(dst, src);
3208 emit(0x0F);
3209 emit(0x2A);
3210 emit_sse_operand(dst, src);
3211}
3212
3213
3214void Assembler::cvtqsi2ss(XMMRegister dst, Register src) {
3215 DCHECK(!IsEnabled(AVX));
3216 EnsureSpace ensure_space(this);
3217 emit(0xF3);
3218 emit_rex_64(dst, src);
3219 emit(0x0F);
3220 emit(0x2A);
3221 emit_sse_operand(dst, src);
3222}
3223
3224
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003225void Assembler::cvtqsi2sd(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003226 DCHECK(!IsEnabled(AVX));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003227 EnsureSpace ensure_space(this);
3228 emit(0xF2);
3229 emit_rex_64(dst, src);
3230 emit(0x0F);
3231 emit(0x2A);
3232 emit_sse_operand(dst, src);
3233}
3234
3235
Steve Blocka7e24c12009-10-30 11:49:00 +00003236void Assembler::cvtqsi2sd(XMMRegister dst, Register src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003237 DCHECK(!IsEnabled(AVX));
Steve Blocka7e24c12009-10-30 11:49:00 +00003238 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003239 emit(0xF2);
3240 emit_rex_64(dst, src);
3241 emit(0x0F);
3242 emit(0x2A);
3243 emit_sse_operand(dst, src);
3244}
3245
3246
Steve Block6ded16b2010-05-10 14:33:55 +01003247void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003248 DCHECK(!IsEnabled(AVX));
Steve Block6ded16b2010-05-10 14:33:55 +01003249 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01003250 emit(0xF3);
3251 emit_optional_rex_32(dst, src);
3252 emit(0x0F);
3253 emit(0x5A);
3254 emit_sse_operand(dst, src);
3255}
3256
3257
Steve Block8defd9f2010-07-08 12:39:36 +01003258void Assembler::cvtss2sd(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003259 DCHECK(!IsEnabled(AVX));
Steve Block8defd9f2010-07-08 12:39:36 +01003260 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003261 emit(0xF3);
3262 emit_optional_rex_32(dst, src);
3263 emit(0x0F);
3264 emit(0x5A);
3265 emit_sse_operand(dst, src);
3266}
3267
3268
3269void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003270 DCHECK(!IsEnabled(AVX));
Steve Block8defd9f2010-07-08 12:39:36 +01003271 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003272 emit(0xF2);
3273 emit_optional_rex_32(dst, src);
3274 emit(0x0F);
3275 emit(0x5A);
3276 emit_sse_operand(dst, src);
3277}
3278
3279
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003280void Assembler::cvtsd2ss(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003281 DCHECK(!IsEnabled(AVX));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003282 EnsureSpace ensure_space(this);
3283 emit(0xF2);
3284 emit_optional_rex_32(dst, src);
3285 emit(0x0F);
3286 emit(0x5A);
3287 emit_sse_operand(dst, src);
3288}
3289
3290
Steve Block8defd9f2010-07-08 12:39:36 +01003291void Assembler::cvtsd2si(Register dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003292 DCHECK(!IsEnabled(AVX));
Steve Block8defd9f2010-07-08 12:39:36 +01003293 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003294 emit(0xF2);
3295 emit_optional_rex_32(dst, src);
3296 emit(0x0F);
3297 emit(0x2D);
3298 emit_sse_operand(dst, src);
3299}
3300
3301
3302void Assembler::cvtsd2siq(Register dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003303 DCHECK(!IsEnabled(AVX));
Steve Block8defd9f2010-07-08 12:39:36 +01003304 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003305 emit(0xF2);
3306 emit_rex_64(dst, src);
3307 emit(0x0F);
3308 emit(0x2D);
3309 emit_sse_operand(dst, src);
3310}
3311
3312
Steve Blocka7e24c12009-10-30 11:49:00 +00003313void Assembler::addsd(XMMRegister dst, XMMRegister src) {
3314 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003315 emit(0xF2);
3316 emit_optional_rex_32(dst, src);
3317 emit(0x0F);
3318 emit(0x58);
3319 emit_sse_operand(dst, src);
3320}
3321
3322
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003323void Assembler::addsd(XMMRegister dst, const Operand& src) {
3324 EnsureSpace ensure_space(this);
3325 emit(0xF2);
3326 emit_optional_rex_32(dst, src);
3327 emit(0x0F);
3328 emit(0x58);
3329 emit_sse_operand(dst, src);
3330}
3331
3332
Steve Blocka7e24c12009-10-30 11:49:00 +00003333void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
3334 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003335 emit(0xF2);
3336 emit_optional_rex_32(dst, src);
3337 emit(0x0F);
3338 emit(0x59);
3339 emit_sse_operand(dst, src);
3340}
3341
3342
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003343void Assembler::mulsd(XMMRegister dst, const Operand& src) {
3344 EnsureSpace ensure_space(this);
3345 emit(0xF2);
3346 emit_optional_rex_32(dst, src);
3347 emit(0x0F);
3348 emit(0x59);
3349 emit_sse_operand(dst, src);
3350}
3351
3352
Steve Blocka7e24c12009-10-30 11:49:00 +00003353void Assembler::subsd(XMMRegister dst, XMMRegister src) {
3354 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003355 emit(0xF2);
3356 emit_optional_rex_32(dst, src);
3357 emit(0x0F);
3358 emit(0x5C);
3359 emit_sse_operand(dst, src);
3360}
3361
3362
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003363void Assembler::subsd(XMMRegister dst, const Operand& src) {
3364 EnsureSpace ensure_space(this);
3365 emit(0xF2);
3366 emit_optional_rex_32(dst, src);
3367 emit(0x0F);
3368 emit(0x5C);
3369 emit_sse_operand(dst, src);
3370}
3371
3372
Steve Blocka7e24c12009-10-30 11:49:00 +00003373void Assembler::divsd(XMMRegister dst, XMMRegister src) {
3374 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003375 emit(0xF2);
3376 emit_optional_rex_32(dst, src);
3377 emit(0x0F);
3378 emit(0x5E);
3379 emit_sse_operand(dst, src);
3380}
3381
3382
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003383void Assembler::divsd(XMMRegister dst, const Operand& src) {
3384 EnsureSpace ensure_space(this);
3385 emit(0xF2);
3386 emit_optional_rex_32(dst, src);
3387 emit(0x0F);
3388 emit(0x5E);
3389 emit_sse_operand(dst, src);
3390}
3391
3392
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003393void Assembler::maxsd(XMMRegister dst, XMMRegister src) {
3394 EnsureSpace ensure_space(this);
3395 emit(0xF2);
3396 emit_optional_rex_32(dst, src);
3397 emit(0x0F);
3398 emit(0x5F);
3399 emit_sse_operand(dst, src);
3400}
3401
3402
3403void Assembler::maxsd(XMMRegister dst, const Operand& src) {
3404 EnsureSpace ensure_space(this);
3405 emit(0xF2);
3406 emit_optional_rex_32(dst, src);
3407 emit(0x0F);
3408 emit(0x5F);
3409 emit_sse_operand(dst, src);
3410}
3411
3412
3413void Assembler::minsd(XMMRegister dst, XMMRegister src) {
3414 EnsureSpace ensure_space(this);
3415 emit(0xF2);
3416 emit_optional_rex_32(dst, src);
3417 emit(0x0F);
3418 emit(0x5D);
3419 emit_sse_operand(dst, src);
3420}
3421
3422
3423void Assembler::minsd(XMMRegister dst, const Operand& src) {
3424 EnsureSpace ensure_space(this);
3425 emit(0xF2);
3426 emit_optional_rex_32(dst, src);
3427 emit(0x0F);
3428 emit(0x5D);
3429 emit_sse_operand(dst, src);
3430}
3431
3432
Ben Murdoche0cee9b2011-05-25 10:26:03 +01003433void Assembler::andpd(XMMRegister dst, XMMRegister src) {
3434 EnsureSpace ensure_space(this);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01003435 emit(0x66);
3436 emit_optional_rex_32(dst, src);
3437 emit(0x0F);
3438 emit(0x54);
3439 emit_sse_operand(dst, src);
3440}
3441
3442
3443void Assembler::orpd(XMMRegister dst, XMMRegister src) {
3444 EnsureSpace ensure_space(this);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01003445 emit(0x66);
3446 emit_optional_rex_32(dst, src);
3447 emit(0x0F);
3448 emit(0x56);
3449 emit_sse_operand(dst, src);
3450}
3451
3452
Andrei Popescu402d9372010-02-26 13:31:12 +00003453void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003454 DCHECK(!IsEnabled(AVX));
Andrei Popescu402d9372010-02-26 13:31:12 +00003455 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003456 emit(0x66);
3457 emit_optional_rex_32(dst, src);
Steve Block6ded16b2010-05-10 14:33:55 +01003458 emit(0x0F);
Andrei Popescu402d9372010-02-26 13:31:12 +00003459 emit(0x57);
3460 emit_sse_operand(dst, src);
3461}
3462
3463
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003464void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003465 DCHECK(!IsEnabled(AVX));
Ben Murdoch257744e2011-11-30 15:57:28 +00003466 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003467 emit(0xF2);
Ben Murdoch257744e2011-11-30 15:57:28 +00003468 emit_optional_rex_32(dst, src);
3469 emit(0x0F);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003470 emit(0x51);
Ben Murdoch257744e2011-11-30 15:57:28 +00003471 emit_sse_operand(dst, src);
3472}
3473
3474
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003475void Assembler::sqrtsd(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003476 DCHECK(!IsEnabled(AVX));
Steve Block6ded16b2010-05-10 14:33:55 +01003477 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01003478 emit(0xF2);
3479 emit_optional_rex_32(dst, src);
3480 emit(0x0F);
3481 emit(0x51);
3482 emit_sse_operand(dst, src);
3483}
3484
3485
Andrei Popescu402d9372010-02-26 13:31:12 +00003486void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003487 DCHECK(!IsEnabled(AVX));
Andrei Popescu402d9372010-02-26 13:31:12 +00003488 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003489 emit(0x66);
3490 emit_optional_rex_32(dst, src);
3491 emit(0x0f);
3492 emit(0x2e);
3493 emit_sse_operand(dst, src);
3494}
3495
Steve Blocka7e24c12009-10-30 11:49:00 +00003496
Steve Block8defd9f2010-07-08 12:39:36 +01003497void Assembler::ucomisd(XMMRegister dst, const Operand& src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003498 DCHECK(!IsEnabled(AVX));
Steve Block8defd9f2010-07-08 12:39:36 +01003499 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003500 emit(0x66);
3501 emit_optional_rex_32(dst, src);
3502 emit(0x0f);
3503 emit(0x2e);
3504 emit_sse_operand(dst, src);
3505}
3506
3507
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003508void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
3509 EnsureSpace ensure_space(this);
3510 emit(0xF2);
3511 emit_optional_rex_32(dst, src);
3512 emit(0x0F);
3513 emit(0xC2);
3514 emit_sse_operand(dst, src);
3515 emit(0x01); // LT == 1
3516}
3517
3518
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003519void Assembler::roundss(XMMRegister dst, XMMRegister src, RoundingMode mode) {
3520 DCHECK(!IsEnabled(AVX));
3521 DCHECK(IsEnabled(SSE4_1));
3522 EnsureSpace ensure_space(this);
3523 emit(0x66);
3524 emit_optional_rex_32(dst, src);
3525 emit(0x0f);
3526 emit(0x3a);
3527 emit(0x0a);
3528 emit_sse_operand(dst, src);
3529 // Mask precision exception.
3530 emit(static_cast<byte>(mode) | 0x8);
3531}
3532
3533
3534void Assembler::roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode) {
3535 DCHECK(!IsEnabled(AVX));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003536 DCHECK(IsEnabled(SSE4_1));
Ben Murdoch257744e2011-11-30 15:57:28 +00003537 EnsureSpace ensure_space(this);
3538 emit(0x66);
3539 emit_optional_rex_32(dst, src);
3540 emit(0x0f);
3541 emit(0x3a);
3542 emit(0x0b);
3543 emit_sse_operand(dst, src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003544 // Mask precision exception.
Ben Murdoch257744e2011-11-30 15:57:28 +00003545 emit(static_cast<byte>(mode) | 0x8);
3546}
3547
3548
Steve Block1e0659c2011-05-24 12:43:12 +01003549void Assembler::movmskpd(Register dst, XMMRegister src) {
3550 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01003551 emit(0x66);
3552 emit_optional_rex_32(dst, src);
3553 emit(0x0f);
3554 emit(0x50);
3555 emit_sse_operand(dst, src);
3556}
3557
Steve Block8defd9f2010-07-08 12:39:36 +01003558
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003559void Assembler::movmskps(Register dst, XMMRegister src) {
3560 EnsureSpace ensure_space(this);
3561 emit_optional_rex_32(dst, src);
3562 emit(0x0f);
3563 emit(0x50);
3564 emit_sse_operand(dst, src);
3565}
3566
3567
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003568void Assembler::pcmpeqd(XMMRegister dst, XMMRegister src) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003569 DCHECK(!IsEnabled(AVX));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003570 EnsureSpace ensure_space(this);
3571 emit(0x66);
3572 emit_optional_rex_32(dst, src);
3573 emit(0x0F);
3574 emit(0x76);
3575 emit_sse_operand(dst, src);
3576}
3577
3578
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003579void Assembler::punpckldq(XMMRegister dst, XMMRegister src) {
3580 EnsureSpace ensure_space(this);
3581 emit(0x66);
3582 emit_optional_rex_32(dst, src);
3583 emit(0x0F);
3584 emit(0x62);
3585 emit_sse_operand(dst, src);
3586}
3587
3588
3589void Assembler::punpckhdq(XMMRegister dst, XMMRegister src) {
3590 EnsureSpace ensure_space(this);
3591 emit(0x66);
3592 emit_optional_rex_32(dst, src);
3593 emit(0x0F);
3594 emit(0x6A);
3595 emit_sse_operand(dst, src);
3596}
3597
3598
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003599// AVX instructions
3600void Assembler::vfmasd(byte op, XMMRegister dst, XMMRegister src1,
3601 XMMRegister src2) {
3602 DCHECK(IsEnabled(FMA3));
3603 EnsureSpace ensure_space(this);
3604 emit_vex_prefix(dst, src1, src2, kLIG, k66, k0F38, kW1);
3605 emit(op);
3606 emit_sse_operand(dst, src2);
3607}
3608
3609
3610void Assembler::vfmasd(byte op, XMMRegister dst, XMMRegister src1,
3611 const Operand& src2) {
3612 DCHECK(IsEnabled(FMA3));
3613 EnsureSpace ensure_space(this);
3614 emit_vex_prefix(dst, src1, src2, kLIG, k66, k0F38, kW1);
3615 emit(op);
3616 emit_sse_operand(dst, src2);
3617}
3618
3619
3620void Assembler::vfmass(byte op, XMMRegister dst, XMMRegister src1,
3621 XMMRegister src2) {
3622 DCHECK(IsEnabled(FMA3));
3623 EnsureSpace ensure_space(this);
3624 emit_vex_prefix(dst, src1, src2, kLIG, k66, k0F38, kW0);
3625 emit(op);
3626 emit_sse_operand(dst, src2);
3627}
3628
3629
3630void Assembler::vfmass(byte op, XMMRegister dst, XMMRegister src1,
3631 const Operand& src2) {
3632 DCHECK(IsEnabled(FMA3));
3633 EnsureSpace ensure_space(this);
3634 emit_vex_prefix(dst, src1, src2, kLIG, k66, k0F38, kW0);
3635 emit(op);
3636 emit_sse_operand(dst, src2);
3637}
3638
3639
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003640void Assembler::vmovd(XMMRegister dst, Register src) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003641 DCHECK(IsEnabled(AVX));
3642 EnsureSpace ensure_space(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003643 XMMRegister isrc = {src.code()};
3644 emit_vex_prefix(dst, xmm0, isrc, kL128, k66, k0F, kW0);
3645 emit(0x6e);
3646 emit_sse_operand(dst, src);
3647}
3648
3649
3650void Assembler::vmovd(XMMRegister dst, const Operand& src) {
3651 DCHECK(IsEnabled(AVX));
3652 EnsureSpace ensure_space(this);
3653 emit_vex_prefix(dst, xmm0, src, kL128, k66, k0F, kW0);
3654 emit(0x6e);
3655 emit_sse_operand(dst, src);
3656}
3657
3658
3659void Assembler::vmovd(Register dst, XMMRegister src) {
3660 DCHECK(IsEnabled(AVX));
3661 EnsureSpace ensure_space(this);
3662 XMMRegister idst = {dst.code()};
3663 emit_vex_prefix(src, xmm0, idst, kL128, k66, k0F, kW0);
3664 emit(0x7e);
3665 emit_sse_operand(src, dst);
3666}
3667
3668
3669void Assembler::vmovq(XMMRegister dst, Register src) {
3670 DCHECK(IsEnabled(AVX));
3671 EnsureSpace ensure_space(this);
3672 XMMRegister isrc = {src.code()};
3673 emit_vex_prefix(dst, xmm0, isrc, kL128, k66, k0F, kW1);
3674 emit(0x6e);
3675 emit_sse_operand(dst, src);
3676}
3677
3678
3679void Assembler::vmovq(XMMRegister dst, const Operand& src) {
3680 DCHECK(IsEnabled(AVX));
3681 EnsureSpace ensure_space(this);
3682 emit_vex_prefix(dst, xmm0, src, kL128, k66, k0F, kW1);
3683 emit(0x6e);
3684 emit_sse_operand(dst, src);
3685}
3686
3687
3688void Assembler::vmovq(Register dst, XMMRegister src) {
3689 DCHECK(IsEnabled(AVX));
3690 EnsureSpace ensure_space(this);
3691 XMMRegister idst = {dst.code()};
3692 emit_vex_prefix(src, xmm0, idst, kL128, k66, k0F, kW1);
3693 emit(0x7e);
3694 emit_sse_operand(src, dst);
3695}
3696
3697
3698void Assembler::vsd(byte op, XMMRegister dst, XMMRegister src1,
3699 XMMRegister src2, SIMDPrefix pp, LeadingOpcode m, VexW w) {
3700 DCHECK(IsEnabled(AVX));
3701 EnsureSpace ensure_space(this);
3702 emit_vex_prefix(dst, src1, src2, kLIG, pp, m, w);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003703 emit(op);
3704 emit_sse_operand(dst, src2);
3705}
3706
3707
3708void Assembler::vsd(byte op, XMMRegister dst, XMMRegister src1,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003709 const Operand& src2, SIMDPrefix pp, LeadingOpcode m,
3710 VexW w) {
3711 DCHECK(IsEnabled(AVX));
3712 EnsureSpace ensure_space(this);
3713 emit_vex_prefix(dst, src1, src2, kLIG, pp, m, w);
3714 emit(op);
3715 emit_sse_operand(dst, src2);
3716}
3717
3718
3719void Assembler::vps(byte op, XMMRegister dst, XMMRegister src1,
3720 XMMRegister src2) {
3721 DCHECK(IsEnabled(AVX));
3722 EnsureSpace ensure_space(this);
3723 emit_vex_prefix(dst, src1, src2, kL128, kNone, k0F, kWIG);
3724 emit(op);
3725 emit_sse_operand(dst, src2);
3726}
3727
3728
3729void Assembler::vps(byte op, XMMRegister dst, XMMRegister src1,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003730 const Operand& src2) {
3731 DCHECK(IsEnabled(AVX));
3732 EnsureSpace ensure_space(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003733 emit_vex_prefix(dst, src1, src2, kL128, kNone, k0F, kWIG);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003734 emit(op);
3735 emit_sse_operand(dst, src2);
3736}
3737
3738
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003739void Assembler::vpd(byte op, XMMRegister dst, XMMRegister src1,
3740 XMMRegister src2) {
3741 DCHECK(IsEnabled(AVX));
3742 EnsureSpace ensure_space(this);
3743 emit_vex_prefix(dst, src1, src2, kL128, k66, k0F, kWIG);
3744 emit(op);
3745 emit_sse_operand(dst, src2);
3746}
3747
3748
3749void Assembler::vpd(byte op, XMMRegister dst, XMMRegister src1,
3750 const Operand& src2) {
3751 DCHECK(IsEnabled(AVX));
3752 EnsureSpace ensure_space(this);
3753 emit_vex_prefix(dst, src1, src2, kL128, k66, k0F, kWIG);
3754 emit(op);
3755 emit_sse_operand(dst, src2);
3756}
3757
3758
3759void Assembler::vucomiss(XMMRegister dst, XMMRegister src) {
3760 DCHECK(IsEnabled(AVX));
3761 EnsureSpace ensure_space(this);
3762 emit_vex_prefix(dst, xmm0, src, kLIG, kNone, k0F, kWIG);
3763 emit(0x2e);
3764 emit_sse_operand(dst, src);
3765}
3766
3767
3768void Assembler::vucomiss(XMMRegister dst, const Operand& src) {
3769 DCHECK(IsEnabled(AVX));
3770 EnsureSpace ensure_space(this);
3771 emit_vex_prefix(dst, xmm0, src, kLIG, kNone, k0F, kWIG);
3772 emit(0x2e);
3773 emit_sse_operand(dst, src);
3774}
3775
3776
3777void Assembler::vss(byte op, XMMRegister dst, XMMRegister src1,
3778 XMMRegister src2) {
3779 DCHECK(IsEnabled(AVX));
3780 EnsureSpace ensure_space(this);
3781 emit_vex_prefix(dst, src1, src2, kLIG, kF3, k0F, kWIG);
3782 emit(op);
3783 emit_sse_operand(dst, src2);
3784}
3785
3786
3787void Assembler::vss(byte op, XMMRegister dst, XMMRegister src1,
3788 const Operand& src2) {
3789 DCHECK(IsEnabled(AVX));
3790 EnsureSpace ensure_space(this);
3791 emit_vex_prefix(dst, src1, src2, kLIG, kF3, k0F, kWIG);
3792 emit(op);
3793 emit_sse_operand(dst, src2);
3794}
3795
3796
3797void Assembler::bmi1q(byte op, Register reg, Register vreg, Register rm) {
3798 DCHECK(IsEnabled(BMI1));
3799 EnsureSpace ensure_space(this);
3800 emit_vex_prefix(reg, vreg, rm, kLZ, kNone, k0F38, kW1);
3801 emit(op);
3802 emit_modrm(reg, rm);
3803}
3804
3805
3806void Assembler::bmi1q(byte op, Register reg, Register vreg, const Operand& rm) {
3807 DCHECK(IsEnabled(BMI1));
3808 EnsureSpace ensure_space(this);
3809 emit_vex_prefix(reg, vreg, rm, kLZ, kNone, k0F38, kW1);
3810 emit(op);
3811 emit_operand(reg, rm);
3812}
3813
3814
3815void Assembler::bmi1l(byte op, Register reg, Register vreg, Register rm) {
3816 DCHECK(IsEnabled(BMI1));
3817 EnsureSpace ensure_space(this);
3818 emit_vex_prefix(reg, vreg, rm, kLZ, kNone, k0F38, kW0);
3819 emit(op);
3820 emit_modrm(reg, rm);
3821}
3822
3823
3824void Assembler::bmi1l(byte op, Register reg, Register vreg, const Operand& rm) {
3825 DCHECK(IsEnabled(BMI1));
3826 EnsureSpace ensure_space(this);
3827 emit_vex_prefix(reg, vreg, rm, kLZ, kNone, k0F38, kW0);
3828 emit(op);
3829 emit_operand(reg, rm);
3830}
3831
3832
3833void Assembler::tzcntq(Register dst, Register src) {
3834 DCHECK(IsEnabled(BMI1));
3835 EnsureSpace ensure_space(this);
3836 emit(0xF3);
3837 emit_rex_64(dst, src);
3838 emit(0x0F);
3839 emit(0xBC);
3840 emit_modrm(dst, src);
3841}
3842
3843
3844void Assembler::tzcntq(Register dst, const Operand& src) {
3845 DCHECK(IsEnabled(BMI1));
3846 EnsureSpace ensure_space(this);
3847 emit(0xF3);
3848 emit_rex_64(dst, src);
3849 emit(0x0F);
3850 emit(0xBC);
3851 emit_operand(dst, src);
3852}
3853
3854
3855void Assembler::tzcntl(Register dst, Register src) {
3856 DCHECK(IsEnabled(BMI1));
3857 EnsureSpace ensure_space(this);
3858 emit(0xF3);
3859 emit_optional_rex_32(dst, src);
3860 emit(0x0F);
3861 emit(0xBC);
3862 emit_modrm(dst, src);
3863}
3864
3865
3866void Assembler::tzcntl(Register dst, const Operand& src) {
3867 DCHECK(IsEnabled(BMI1));
3868 EnsureSpace ensure_space(this);
3869 emit(0xF3);
3870 emit_optional_rex_32(dst, src);
3871 emit(0x0F);
3872 emit(0xBC);
3873 emit_operand(dst, src);
3874}
3875
3876
3877void Assembler::lzcntq(Register dst, Register src) {
3878 DCHECK(IsEnabled(LZCNT));
3879 EnsureSpace ensure_space(this);
3880 emit(0xF3);
3881 emit_rex_64(dst, src);
3882 emit(0x0F);
3883 emit(0xBD);
3884 emit_modrm(dst, src);
3885}
3886
3887
3888void Assembler::lzcntq(Register dst, const Operand& src) {
3889 DCHECK(IsEnabled(LZCNT));
3890 EnsureSpace ensure_space(this);
3891 emit(0xF3);
3892 emit_rex_64(dst, src);
3893 emit(0x0F);
3894 emit(0xBD);
3895 emit_operand(dst, src);
3896}
3897
3898
3899void Assembler::lzcntl(Register dst, Register src) {
3900 DCHECK(IsEnabled(LZCNT));
3901 EnsureSpace ensure_space(this);
3902 emit(0xF3);
3903 emit_optional_rex_32(dst, src);
3904 emit(0x0F);
3905 emit(0xBD);
3906 emit_modrm(dst, src);
3907}
3908
3909
3910void Assembler::lzcntl(Register dst, const Operand& src) {
3911 DCHECK(IsEnabled(LZCNT));
3912 EnsureSpace ensure_space(this);
3913 emit(0xF3);
3914 emit_optional_rex_32(dst, src);
3915 emit(0x0F);
3916 emit(0xBD);
3917 emit_operand(dst, src);
3918}
3919
3920
3921void Assembler::popcntq(Register dst, Register src) {
3922 DCHECK(IsEnabled(POPCNT));
3923 EnsureSpace ensure_space(this);
3924 emit(0xF3);
3925 emit_rex_64(dst, src);
3926 emit(0x0F);
3927 emit(0xB8);
3928 emit_modrm(dst, src);
3929}
3930
3931
3932void Assembler::popcntq(Register dst, const Operand& src) {
3933 DCHECK(IsEnabled(POPCNT));
3934 EnsureSpace ensure_space(this);
3935 emit(0xF3);
3936 emit_rex_64(dst, src);
3937 emit(0x0F);
3938 emit(0xB8);
3939 emit_operand(dst, src);
3940}
3941
3942
3943void Assembler::popcntl(Register dst, Register src) {
3944 DCHECK(IsEnabled(POPCNT));
3945 EnsureSpace ensure_space(this);
3946 emit(0xF3);
3947 emit_optional_rex_32(dst, src);
3948 emit(0x0F);
3949 emit(0xB8);
3950 emit_modrm(dst, src);
3951}
3952
3953
3954void Assembler::popcntl(Register dst, const Operand& src) {
3955 DCHECK(IsEnabled(POPCNT));
3956 EnsureSpace ensure_space(this);
3957 emit(0xF3);
3958 emit_optional_rex_32(dst, src);
3959 emit(0x0F);
3960 emit(0xB8);
3961 emit_operand(dst, src);
3962}
3963
3964
3965void Assembler::bmi2q(SIMDPrefix pp, byte op, Register reg, Register vreg,
3966 Register rm) {
3967 DCHECK(IsEnabled(BMI2));
3968 EnsureSpace ensure_space(this);
3969 emit_vex_prefix(reg, vreg, rm, kLZ, pp, k0F38, kW1);
3970 emit(op);
3971 emit_modrm(reg, rm);
3972}
3973
3974
3975void Assembler::bmi2q(SIMDPrefix pp, byte op, Register reg, Register vreg,
3976 const Operand& rm) {
3977 DCHECK(IsEnabled(BMI2));
3978 EnsureSpace ensure_space(this);
3979 emit_vex_prefix(reg, vreg, rm, kLZ, pp, k0F38, kW1);
3980 emit(op);
3981 emit_operand(reg, rm);
3982}
3983
3984
3985void Assembler::bmi2l(SIMDPrefix pp, byte op, Register reg, Register vreg,
3986 Register rm) {
3987 DCHECK(IsEnabled(BMI2));
3988 EnsureSpace ensure_space(this);
3989 emit_vex_prefix(reg, vreg, rm, kLZ, pp, k0F38, kW0);
3990 emit(op);
3991 emit_modrm(reg, rm);
3992}
3993
3994
3995void Assembler::bmi2l(SIMDPrefix pp, byte op, Register reg, Register vreg,
3996 const Operand& rm) {
3997 DCHECK(IsEnabled(BMI2));
3998 EnsureSpace ensure_space(this);
3999 emit_vex_prefix(reg, vreg, rm, kLZ, pp, k0F38, kW0);
4000 emit(op);
4001 emit_operand(reg, rm);
4002}
4003
4004
4005void Assembler::rorxq(Register dst, Register src, byte imm8) {
4006 DCHECK(IsEnabled(BMI2));
4007 DCHECK(is_uint8(imm8));
4008 Register vreg = {0}; // VEX.vvvv unused
4009 EnsureSpace ensure_space(this);
4010 emit_vex_prefix(dst, vreg, src, kLZ, kF2, k0F3A, kW1);
4011 emit(0xF0);
4012 emit_modrm(dst, src);
4013 emit(imm8);
4014}
4015
4016
4017void Assembler::rorxq(Register dst, const Operand& src, byte imm8) {
4018 DCHECK(IsEnabled(BMI2));
4019 DCHECK(is_uint8(imm8));
4020 Register vreg = {0}; // VEX.vvvv unused
4021 EnsureSpace ensure_space(this);
4022 emit_vex_prefix(dst, vreg, src, kLZ, kF2, k0F3A, kW1);
4023 emit(0xF0);
4024 emit_operand(dst, src);
4025 emit(imm8);
4026}
4027
4028
4029void Assembler::rorxl(Register dst, Register src, byte imm8) {
4030 DCHECK(IsEnabled(BMI2));
4031 DCHECK(is_uint8(imm8));
4032 Register vreg = {0}; // VEX.vvvv unused
4033 EnsureSpace ensure_space(this);
4034 emit_vex_prefix(dst, vreg, src, kLZ, kF2, k0F3A, kW0);
4035 emit(0xF0);
4036 emit_modrm(dst, src);
4037 emit(imm8);
4038}
4039
4040
4041void Assembler::rorxl(Register dst, const Operand& src, byte imm8) {
4042 DCHECK(IsEnabled(BMI2));
4043 DCHECK(is_uint8(imm8));
4044 Register vreg = {0}; // VEX.vvvv unused
4045 EnsureSpace ensure_space(this);
4046 emit_vex_prefix(dst, vreg, src, kLZ, kF2, k0F3A, kW0);
4047 emit(0xF0);
4048 emit_operand(dst, src);
4049 emit(imm8);
4050}
4051
4052
Steve Blocka7e24c12009-10-30 11:49:00 +00004053void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
4054 Register ireg = { reg.code() };
4055 emit_operand(ireg, adr);
4056}
4057
4058
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004059void Assembler::emit_sse_operand(Register reg, const Operand& adr) {
4060 Register ireg = {reg.code()};
4061 emit_operand(ireg, adr);
4062}
4063
4064
Steve Blocka7e24c12009-10-30 11:49:00 +00004065void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
4066 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
4067}
4068
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004069
Steve Blocka7e24c12009-10-30 11:49:00 +00004070void Assembler::emit_sse_operand(XMMRegister dst, Register src) {
4071 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
4072}
4073
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004074
Steve Block6ded16b2010-05-10 14:33:55 +01004075void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
4076 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
4077}
4078
Steve Blocka7e24c12009-10-30 11:49:00 +00004079
Ben Murdochb8e0da22011-05-16 14:20:40 +01004080void Assembler::db(uint8_t data) {
4081 EnsureSpace ensure_space(this);
4082 emit(data);
4083}
4084
4085
Ben Murdochb0fe1622011-05-05 13:52:32 +01004086void Assembler::dd(uint32_t data) {
4087 EnsureSpace ensure_space(this);
4088 emitl(data);
4089}
4090
4091
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004092void Assembler::dq(uint64_t data) {
4093 EnsureSpace ensure_space(this);
4094 emitq(data);
4095}
4096
4097
4098void Assembler::dq(Label* label) {
4099 EnsureSpace ensure_space(this);
4100 if (label->is_bound()) {
4101 internal_reference_positions_.push_back(pc_offset());
4102 emitp(buffer_ + label->pos(), RelocInfo::INTERNAL_REFERENCE);
4103 } else {
4104 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
4105 emitl(0); // Zero for the first 32bit marks it as 64bit absolute address.
4106 if (label->is_linked()) {
4107 emitl(label->pos());
4108 label->link_to(pc_offset() - sizeof(int32_t));
4109 } else {
4110 DCHECK(label->is_unused());
4111 int32_t current = pc_offset();
4112 emitl(current);
4113 label->link_to(current);
4114 }
4115 }
4116}
4117
4118
Andrei Popescu31002712010-02-23 13:46:05 +00004119// Relocation information implementations.
Steve Blocka7e24c12009-10-30 11:49:00 +00004120
4121void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004122 DCHECK(!RelocInfo::IsNone(rmode));
Steve Blocka7e24c12009-10-30 11:49:00 +00004123 // Don't record external references unless the heap will be serialized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004124 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
4125 !serializer_enabled() && !emit_debug_code()) {
4126 return;
4127 } else if (rmode == RelocInfo::CODE_AGE_SEQUENCE) {
4128 // Don't record psuedo relocation info for code age sequence mode.
4129 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00004130 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004131 RelocInfo rinfo(isolate(), pc_, rmode, data, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00004132 reloc_info_writer.Write(&rinfo);
4133}
4134
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004135
Steve Block3ce2e202009-11-05 08:53:23 +00004136const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004137 1 << RelocInfo::RUNTIME_ENTRY |
4138 1 << RelocInfo::INTERNAL_REFERENCE |
4139 1 << RelocInfo::CODE_AGE_SEQUENCE;
Steve Blocka7e24c12009-10-30 11:49:00 +00004140
Leon Clarkef7060e22010-06-03 12:02:55 +01004141
4142bool RelocInfo::IsCodedSpecially() {
4143 // The deserializer needs to know whether a pointer is specially coded. Being
4144 // specially coded on x64 means that it is a relative 32 bit address, as used
4145 // by branch instructions.
4146 return (1 << rmode_) & kApplyMask;
4147}
4148
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004149
4150bool RelocInfo::IsInConstantPool() {
4151 return false;
4152}
4153
4154
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004155} // namespace internal
4156} // namespace v8
Leon Clarkef7060e22010-06-03 12:02:55 +01004157
4158#endif // V8_TARGET_ARCH_X64