blob: fd722b23bd34fd86db481b1c694c6fa8e2a20804 [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
7#if V8_OS_MACOSX
8#include <sys/sysctl.h>
9#endif
Steve Blocka7e24c12009-10-30 11:49:00 +000010
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#if V8_TARGET_ARCH_X64
Leon Clarkef7060e22010-06-03 12:02:55 +010012
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013#include "src/base/bits.h"
14#include "src/macro-assembler.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015#include "src/v8.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000016
17namespace v8 {
18namespace internal {
19
20// -----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +000021// Implementation of CpuFeatures
22
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023namespace {
24
25bool EnableAVX() {
26#if V8_OS_MACOSX
27 // Mac OS X 10.9 has a bug where AVX transitions were indeed being caused by
28 // ISRs, so we detect Mac OS X 10.9 here and disable AVX in that case.
29 char buffer[128];
30 size_t buffer_size = arraysize(buffer);
31 int ctl_name[] = { CTL_KERN , KERN_OSRELEASE };
32 if (sysctl(ctl_name, 2, buffer, &buffer_size, nullptr, 0) != 0) {
33 V8_Fatal(__FILE__, __LINE__, "V8 failed to get kernel version");
34 }
35 // The buffer now contains a string of the form XX.YY.ZZ, where
36 // XX is the major kernel version component. 13.x.x (Mavericks) is
37 // affected by this bug, so disable AVX there.
38 if (memcmp(buffer, "13.", 3) == 0) return false;
39#endif // V8_OS_MACOSX
40 return FLAG_enable_avx;
41}
42
43} // namespace
44
45
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046void CpuFeatures::ProbeImpl(bool cross_compile) {
47 base::CPU cpu;
48 CHECK(cpu.has_sse2()); // SSE2 support is mandatory.
49 CHECK(cpu.has_cmov()); // CMOV support is mandatory.
Ben Murdoch8b112d22011-06-08 16:22:53 +010050
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051 // Only use statically determined features for cross compile (snapshot).
52 if (cross_compile) return;
Steve Block44f0eee2011-05-26 01:26:41 +010053
Ben Murdochb8a8cc12014-11-26 15:28:44 +000054 if (cpu.has_sse41() && FLAG_enable_sse4_1) supported_ |= 1u << SSE4_1;
55 if (cpu.has_sse3() && FLAG_enable_sse3) supported_ |= 1u << SSE3;
56 // SAHF is not generally available in long mode.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040057 if (cpu.has_sahf() && FLAG_enable_sahf) supported_ |= 1u << SAHF;
58 if (cpu.has_avx() && EnableAVX()) supported_ |= 1u << AVX;
59 if (cpu.has_fma3() && FLAG_enable_fma3) supported_ |= 1u << FMA3;
Steve Blocka7e24c12009-10-30 11:49:00 +000060}
61
62
Ben Murdochb8a8cc12014-11-26 15:28:44 +000063void CpuFeatures::PrintTarget() { }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040064void CpuFeatures::PrintFeatures() {
65 printf("SSE3=%d SSE4_1=%d SAHF=%d AVX=%d FMA3=%d\n",
66 CpuFeatures::IsSupported(SSE3), CpuFeatures::IsSupported(SSE4_1),
67 CpuFeatures::IsSupported(SAHF), CpuFeatures::IsSupported(AVX),
68 CpuFeatures::IsSupported(FMA3));
69}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000070
71
Steve Blocka7e24c12009-10-30 11:49:00 +000072// -----------------------------------------------------------------------------
73// Implementation of RelocInfo
74
75// Patch the code at the current PC with a call to the target address.
76// Additional guard int3 instructions can be added if required.
77void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000078 int code_size = Assembler::kCallSequenceLength + guard_bytes;
Steve Blocka7e24c12009-10-30 11:49:00 +000079
80 // Create a code patcher.
81 CodePatcher patcher(pc_, code_size);
82
83 // Add a label for checking the size of the code used for returning.
84#ifdef DEBUG
85 Label check_codesize;
86 patcher.masm()->bind(&check_codesize);
87#endif
88
89 // Patch the code.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000090 patcher.masm()->movp(kScratchRegister, reinterpret_cast<void*>(target),
91 Assembler::RelocInfoNone());
92 patcher.masm()->call(kScratchRegister);
Steve Blocka7e24c12009-10-30 11:49:00 +000093
94 // Check that the size of the code generated is as expected.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000095 DCHECK_EQ(Assembler::kCallSequenceLength,
Steve Blocka7e24c12009-10-30 11:49:00 +000096 patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
97
98 // Add the requested number of int3 instructions after the call.
99 for (int i = 0; i < guard_bytes; i++) {
100 patcher.masm()->int3();
101 }
102}
103
104
105void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
106 // Patch the code at the current address with the supplied instructions.
107 for (int i = 0; i < instruction_count; i++) {
108 *(pc_ + i) = *(instructions + i);
109 }
110
111 // Indicate that code has changed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112 CpuFeatures::FlushICache(pc_, instruction_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000113}
114
Ben Murdochb8e0da22011-05-16 14:20:40 +0100115
116// -----------------------------------------------------------------------------
117// Register constants.
118
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000119const int
120 Register::kRegisterCodeByAllocationIndex[kMaxNumAllocatableRegisters] = {
121 // rax, rbx, rdx, rcx, rsi, rdi, r8, r9, r11, r14, r15
122 0, 3, 2, 1, 6, 7, 8, 9, 11, 14, 15
Ben Murdochb8e0da22011-05-16 14:20:40 +0100123};
124
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100125const int Register::kAllocationIndexByRegisterCode[kNumRegisters] = {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000126 0, 3, 2, 1, -1, -1, 4, 5, 6, 7, -1, 8, -1, -1, 9, 10
Ben Murdochb8e0da22011-05-16 14:20:40 +0100127};
128
129
Steve Blocka7e24c12009-10-30 11:49:00 +0000130// -----------------------------------------------------------------------------
131// Implementation of Operand
132
Andrei Popescu402d9372010-02-26 13:31:12 +0000133Operand::Operand(Register base, int32_t disp) : rex_(0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000134 len_ = 1;
135 if (base.is(rsp) || base.is(r12)) {
136 // SIB byte is needed to encode (rsp + offset) or (r12 + offset).
137 set_sib(times_1, rsp, base);
138 }
139
140 if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
141 set_modrm(0, base);
142 } else if (is_int8(disp)) {
143 set_modrm(1, base);
144 set_disp8(disp);
145 } else {
146 set_modrm(2, base);
147 set_disp32(disp);
148 }
149}
150
151
152Operand::Operand(Register base,
153 Register index,
154 ScaleFactor scale,
Andrei Popescu402d9372010-02-26 13:31:12 +0000155 int32_t disp) : rex_(0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000156 DCHECK(!index.is(rsp));
Steve Blocka7e24c12009-10-30 11:49:00 +0000157 len_ = 1;
158 set_sib(scale, index, base);
159 if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
160 // This call to set_modrm doesn't overwrite the REX.B (or REX.X) bits
161 // possibly set by set_sib.
162 set_modrm(0, rsp);
163 } else if (is_int8(disp)) {
164 set_modrm(1, rsp);
165 set_disp8(disp);
166 } else {
167 set_modrm(2, rsp);
168 set_disp32(disp);
169 }
170}
171
172
Andrei Popescu402d9372010-02-26 13:31:12 +0000173Operand::Operand(Register index,
174 ScaleFactor scale,
175 int32_t disp) : rex_(0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176 DCHECK(!index.is(rsp));
Andrei Popescu402d9372010-02-26 13:31:12 +0000177 len_ = 1;
178 set_modrm(0, rsp);
179 set_sib(scale, index, rbp);
180 set_disp32(disp);
181}
182
183
Leon Clarkef7060e22010-06-03 12:02:55 +0100184Operand::Operand(const Operand& operand, int32_t offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185 DCHECK(operand.len_ >= 1);
Leon Clarkef7060e22010-06-03 12:02:55 +0100186 // Operand encodes REX ModR/M [SIB] [Disp].
187 byte modrm = operand.buf_[0];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188 DCHECK(modrm < 0xC0); // Disallow mode 3 (register target).
Leon Clarkef7060e22010-06-03 12:02:55 +0100189 bool has_sib = ((modrm & 0x07) == 0x04);
190 byte mode = modrm & 0xC0;
191 int disp_offset = has_sib ? 2 : 1;
192 int base_reg = (has_sib ? operand.buf_[1] : modrm) & 0x07;
193 // Mode 0 with rbp/r13 as ModR/M or SIB base register always has a 32-bit
194 // displacement.
195 bool is_baseless = (mode == 0) && (base_reg == 0x05); // No base or RIP base.
196 int32_t disp_value = 0;
197 if (mode == 0x80 || is_baseless) {
198 // Mode 2 or mode 0 with rbp/r13 as base: Word displacement.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199 disp_value = *bit_cast<const int32_t*>(&operand.buf_[disp_offset]);
Leon Clarkef7060e22010-06-03 12:02:55 +0100200 } else if (mode == 0x40) {
201 // Mode 1: Byte displacement.
202 disp_value = static_cast<signed char>(operand.buf_[disp_offset]);
203 }
204
205 // Write new operand with same registers, but with modified displacement.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206 DCHECK(offset >= 0 ? disp_value + offset > disp_value
Leon Clarkef7060e22010-06-03 12:02:55 +0100207 : disp_value + offset < disp_value); // No overflow.
208 disp_value += offset;
209 rex_ = operand.rex_;
210 if (!is_int8(disp_value) || is_baseless) {
211 // Need 32 bits of displacement, mode 2 or mode 1 with register rbp/r13.
212 buf_[0] = (modrm & 0x3f) | (is_baseless ? 0x00 : 0x80);
213 len_ = disp_offset + 4;
214 Memory::int32_at(&buf_[disp_offset]) = disp_value;
215 } else if (disp_value != 0 || (base_reg == 0x05)) {
216 // Need 8 bits of displacement.
217 buf_[0] = (modrm & 0x3f) | 0x40; // Mode 1.
218 len_ = disp_offset + 1;
219 buf_[disp_offset] = static_cast<byte>(disp_value);
220 } else {
221 // Need no displacement.
222 buf_[0] = (modrm & 0x3f); // Mode 0.
223 len_ = disp_offset;
224 }
225 if (has_sib) {
226 buf_[1] = operand.buf_[1];
227 }
228}
229
Steve Block1e0659c2011-05-24 12:43:12 +0100230
231bool Operand::AddressUsesRegister(Register reg) const {
232 int code = reg.code();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233 DCHECK((buf_[0] & 0xC0) != 0xC0); // Always a memory operand.
Steve Block1e0659c2011-05-24 12:43:12 +0100234 // Start with only low three bits of base register. Initial decoding doesn't
235 // distinguish on the REX.B bit.
236 int base_code = buf_[0] & 0x07;
237 if (base_code == rsp.code()) {
238 // SIB byte present in buf_[1].
239 // Check the index register from the SIB byte + REX.X prefix.
240 int index_code = ((buf_[1] >> 3) & 0x07) | ((rex_ & 0x02) << 2);
241 // Index code (including REX.X) of 0x04 (rsp) means no index register.
242 if (index_code != rsp.code() && index_code == code) return true;
243 // Add REX.B to get the full base register code.
244 base_code = (buf_[1] & 0x07) | ((rex_ & 0x01) << 3);
245 // A base register of 0x05 (rbp) with mod = 0 means no base register.
246 if (base_code == rbp.code() && ((buf_[0] & 0xC0) == 0)) return false;
247 return code == base_code;
248 } else {
249 // A base register with low bits of 0x05 (rbp or r13) and mod = 0 means
250 // no base register.
251 if (base_code == rbp.code() && ((buf_[0] & 0xC0) == 0)) return false;
252 base_code |= ((rex_ & 0x01) << 3);
253 return code == base_code;
254 }
255}
256
257
Steve Blocka7e24c12009-10-30 11:49:00 +0000258// -----------------------------------------------------------------------------
Andrei Popescu31002712010-02-23 13:46:05 +0000259// Implementation of Assembler.
Steve Blocka7e24c12009-10-30 11:49:00 +0000260
261#ifdef GENERATED_CODE_COVERAGE
262static void InitCoverageLog();
263#endif
264
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000265Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
266 : AssemblerBase(isolate, buffer, buffer_size),
Steve Block44f0eee2011-05-26 01:26:41 +0100267 code_targets_(100),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000268 positions_recorder_(this) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000269 // Clear the buffer in debug mode unless it was provided by the
270 // caller in which case we can't be sure it's okay to overwrite
271 // existing code in it.
272#ifdef DEBUG
273 if (own_buffer_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000274 memset(buffer_, 0xCC, buffer_size_); // int3
Steve Blocka7e24c12009-10-30 11:49:00 +0000275 }
276#endif
277
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000279
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800280
Steve Blocka7e24c12009-10-30 11:49:00 +0000281#ifdef GENERATED_CODE_COVERAGE
282 InitCoverageLog();
283#endif
284}
285
286
Steve Blocka7e24c12009-10-30 11:49:00 +0000287void Assembler::GetCode(CodeDesc* desc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000288 // Finalize code (at this point overflow() may be true, but the gap ensures
289 // that we are still not overlapping instructions and relocation info).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000290 DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100291 // Set up code descriptor.
Steve Blocka7e24c12009-10-30 11:49:00 +0000292 desc->buffer = buffer_;
293 desc->buffer_size = buffer_size_;
294 desc->instr_size = pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000295 DCHECK(desc->instr_size > 0); // Zero-size code objects upset the system.
Steve Blockd0582a62009-12-15 09:54:21 +0000296 desc->reloc_size =
297 static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos());
Steve Blocka7e24c12009-10-30 11:49:00 +0000298 desc->origin = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000299}
300
301
302void Assembler::Align(int m) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303 DCHECK(base::bits::IsPowerOfTwo32(m));
Steve Block8defd9f2010-07-08 12:39:36 +0100304 int delta = (m - (pc_offset() & (m - 1))) & (m - 1);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100305 Nop(delta);
Steve Blocka7e24c12009-10-30 11:49:00 +0000306}
307
308
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100309void Assembler::CodeTargetAlign() {
310 Align(16); // Preferred alignment of jump targets on x64.
311}
312
313
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100314bool Assembler::IsNop(Address addr) {
315 Address a = addr;
316 while (*a == 0x66) a++;
317 if (*a == 0x90) return true;
318 if (a[0] == 0xf && a[1] == 0x1f) return true;
319 return false;
320}
321
322
Steve Blocka7e24c12009-10-30 11:49:00 +0000323void Assembler::bind_to(Label* L, int pos) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000324 DCHECK(!L->is_bound()); // Label may only be bound once.
325 DCHECK(0 <= pos && pos <= pc_offset()); // Position must be valid.
Steve Blocka7e24c12009-10-30 11:49:00 +0000326 if (L->is_linked()) {
327 int current = L->pos();
328 int next = long_at(current);
329 while (next != current) {
Andrei Popescu31002712010-02-23 13:46:05 +0000330 // Relative address, relative to point after address.
Steve Blocka7e24c12009-10-30 11:49:00 +0000331 int imm32 = pos - (current + sizeof(int32_t));
332 long_at_put(current, imm32);
333 current = next;
334 next = long_at(next);
335 }
336 // Fix up last fixup on linked list.
337 int last_imm32 = pos - (current + sizeof(int32_t));
338 long_at_put(current, last_imm32);
339 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000340 while (L->is_near_linked()) {
341 int fixup_pos = L->near_link_pos();
342 int offset_to_next =
343 static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000344 DCHECK(offset_to_next <= 0);
Ben Murdoch257744e2011-11-30 15:57:28 +0000345 int disp = pos - (fixup_pos + sizeof(int8_t));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000346 CHECK(is_int8(disp));
Ben Murdoch257744e2011-11-30 15:57:28 +0000347 set_byte_at(fixup_pos, disp);
348 if (offset_to_next < 0) {
349 L->link_to(fixup_pos + offset_to_next, Label::kNear);
350 } else {
351 L->UnuseNear();
352 }
353 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000354 L->bind_to(pos);
355}
356
357
358void Assembler::bind(Label* L) {
359 bind_to(L, pc_offset());
360}
361
362
363void Assembler::GrowBuffer() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000364 DCHECK(buffer_overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +0000365 if (!own_buffer_) FATAL("external code buffer is too small");
366
Andrei Popescu31002712010-02-23 13:46:05 +0000367 // Compute new buffer size.
Steve Blocka7e24c12009-10-30 11:49:00 +0000368 CodeDesc desc; // the new buffer
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000369 desc.buffer_size = 2 * buffer_size_;
370
Steve Blocka7e24c12009-10-30 11:49:00 +0000371 // Some internal data structures overflow for very large buffers,
372 // they must ensure that kMaximalBufferSize is not too large.
373 if ((desc.buffer_size > kMaximalBufferSize) ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000374 (desc.buffer_size > isolate()->heap()->MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000375 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
376 }
377
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100378 // Set up new buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +0000379 desc.buffer = NewArray<byte>(desc.buffer_size);
380 desc.instr_size = pc_offset();
Steve Blockd0582a62009-12-15 09:54:21 +0000381 desc.reloc_size =
382 static_cast<int>((buffer_ + buffer_size_) - (reloc_info_writer.pos()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000383
384 // Clear the buffer in debug mode. Use 'int3' instructions to make
385 // sure to get into problems if we ever run uninitialized code.
386#ifdef DEBUG
387 memset(desc.buffer, 0xCC, desc.buffer_size);
388#endif
389
Andrei Popescu31002712010-02-23 13:46:05 +0000390 // Copy the data.
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 intptr_t pc_delta = desc.buffer - buffer_;
392 intptr_t rc_delta = (desc.buffer + desc.buffer_size) -
393 (buffer_ + buffer_size_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000394 MemMove(desc.buffer, buffer_, desc.instr_size);
395 MemMove(rc_delta + reloc_info_writer.pos(), reloc_info_writer.pos(),
396 desc.reloc_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000397
Andrei Popescu31002712010-02-23 13:46:05 +0000398 // Switch buffers.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000399 DeleteArray(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000400 buffer_ = desc.buffer;
401 buffer_size_ = desc.buffer_size;
402 pc_ += pc_delta;
Steve Blocka7e24c12009-10-30 11:49:00 +0000403 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
404 reloc_info_writer.last_pc() + pc_delta);
405
Andrei Popescu31002712010-02-23 13:46:05 +0000406 // Relocate runtime entries.
Steve Blocka7e24c12009-10-30 11:49:00 +0000407 for (RelocIterator it(desc); !it.done(); it.next()) {
408 RelocInfo::Mode rmode = it.rinfo()->rmode();
409 if (rmode == RelocInfo::INTERNAL_REFERENCE) {
410 intptr_t* p = reinterpret_cast<intptr_t*>(it.rinfo()->pc());
411 if (*p != 0) { // 0 means uninitialized.
412 *p += pc_delta;
413 }
414 }
415 }
416
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000417 DCHECK(!buffer_overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +0000418}
419
420
421void Assembler::emit_operand(int code, const Operand& adr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000422 DCHECK(is_uint3(code));
Steve Blocka7e24c12009-10-30 11:49:00 +0000423 const unsigned length = adr.len_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000424 DCHECK(length > 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000425
426 // Emit updated ModR/M byte containing the given register.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000427 DCHECK((adr.buf_[0] & 0x38) == 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000428 pc_[0] = adr.buf_[0] | code << 3;
429
430 // Emit the rest of the encoded operand.
431 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
432 pc_ += length;
433}
434
435
Andrei Popescu31002712010-02-23 13:46:05 +0000436// Assembler Instruction implementations.
Steve Blocka7e24c12009-10-30 11:49:00 +0000437
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000438void Assembler::arithmetic_op(byte opcode,
439 Register reg,
440 const Operand& op,
441 int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000442 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000443 emit_rex(reg, op, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000444 emit(opcode);
445 emit_operand(reg, op);
446}
447
448
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000449void Assembler::arithmetic_op(byte opcode,
450 Register reg,
451 Register rm_reg,
452 int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000453 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000454 DCHECK((opcode & 0xC6) == 2);
Leon Clarkef7060e22010-06-03 12:02:55 +0100455 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
456 // Swap reg and rm_reg and change opcode operand order.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000457 emit_rex(rm_reg, reg, size);
Leon Clarkef7060e22010-06-03 12:02:55 +0100458 emit(opcode ^ 0x02);
459 emit_modrm(rm_reg, reg);
460 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000461 emit_rex(reg, rm_reg, size);
Leon Clarkef7060e22010-06-03 12:02:55 +0100462 emit(opcode);
463 emit_modrm(reg, rm_reg);
464 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000465}
466
467
468void Assembler::arithmetic_op_16(byte opcode, Register reg, Register rm_reg) {
469 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000470 DCHECK((opcode & 0xC6) == 2);
Leon Clarkef7060e22010-06-03 12:02:55 +0100471 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
472 // Swap reg and rm_reg and change opcode operand order.
473 emit(0x66);
474 emit_optional_rex_32(rm_reg, reg);
475 emit(opcode ^ 0x02);
476 emit_modrm(rm_reg, reg);
477 } else {
478 emit(0x66);
479 emit_optional_rex_32(reg, rm_reg);
480 emit(opcode);
481 emit_modrm(reg, rm_reg);
482 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000483}
484
485
486void Assembler::arithmetic_op_16(byte opcode,
487 Register reg,
488 const Operand& rm_reg) {
489 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000490 emit(0x66);
491 emit_optional_rex_32(reg, rm_reg);
492 emit(opcode);
493 emit_operand(reg, rm_reg);
494}
495
496
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000497void Assembler::arithmetic_op_8(byte opcode, Register reg, const Operand& op) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000498 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000499 if (!reg.is_byte_register()) {
500 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
501 emit_rex_32(reg);
502 }
503 emit(opcode);
504 emit_operand(reg, op);
505}
506
507
508void Assembler::arithmetic_op_8(byte opcode, Register reg, Register rm_reg) {
509 EnsureSpace ensure_space(this);
510 DCHECK((opcode & 0xC6) == 2);
511 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
Leon Clarkef7060e22010-06-03 12:02:55 +0100512 // Swap reg and rm_reg and change opcode operand order.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000513 if (!rm_reg.is_byte_register() || !reg.is_byte_register()) {
514 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
515 emit_rex_32(rm_reg, reg);
516 }
517 emit(opcode ^ 0x02);
Leon Clarkef7060e22010-06-03 12:02:55 +0100518 emit_modrm(rm_reg, reg);
519 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000520 if (!reg.is_byte_register() || !rm_reg.is_byte_register()) {
521 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
522 emit_rex_32(reg, rm_reg);
523 }
Leon Clarkef7060e22010-06-03 12:02:55 +0100524 emit(opcode);
525 emit_modrm(reg, rm_reg);
526 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000527}
528
529
Steve Blocka7e24c12009-10-30 11:49:00 +0000530void Assembler::immediate_arithmetic_op(byte subcode,
531 Register dst,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 Immediate src,
533 int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000534 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000536 if (is_int8(src.value_)) {
537 emit(0x83);
538 emit_modrm(subcode, dst);
539 emit(src.value_);
540 } else if (dst.is(rax)) {
541 emit(0x05 | (subcode << 3));
542 emitl(src.value_);
543 } else {
544 emit(0x81);
545 emit_modrm(subcode, dst);
546 emitl(src.value_);
547 }
548}
549
550void Assembler::immediate_arithmetic_op(byte subcode,
551 const Operand& dst,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000552 Immediate src,
553 int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000554 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000555 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000556 if (is_int8(src.value_)) {
557 emit(0x83);
558 emit_operand(subcode, dst);
559 emit(src.value_);
560 } else {
561 emit(0x81);
562 emit_operand(subcode, dst);
563 emitl(src.value_);
564 }
565}
566
567
568void Assembler::immediate_arithmetic_op_16(byte subcode,
569 Register dst,
570 Immediate src) {
571 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000572 emit(0x66); // Operand size override prefix.
573 emit_optional_rex_32(dst);
574 if (is_int8(src.value_)) {
575 emit(0x83);
576 emit_modrm(subcode, dst);
577 emit(src.value_);
578 } else if (dst.is(rax)) {
579 emit(0x05 | (subcode << 3));
Steve Block3ce2e202009-11-05 08:53:23 +0000580 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000581 } else {
582 emit(0x81);
583 emit_modrm(subcode, dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000584 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000585 }
586}
587
588
589void Assembler::immediate_arithmetic_op_16(byte subcode,
590 const Operand& dst,
591 Immediate src) {
592 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000593 emit(0x66); // Operand size override prefix.
594 emit_optional_rex_32(dst);
595 if (is_int8(src.value_)) {
596 emit(0x83);
597 emit_operand(subcode, dst);
598 emit(src.value_);
599 } else {
600 emit(0x81);
601 emit_operand(subcode, dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000602 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000603 }
604}
605
606
Steve Blocka7e24c12009-10-30 11:49:00 +0000607void Assembler::immediate_arithmetic_op_8(byte subcode,
608 const Operand& dst,
609 Immediate src) {
610 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000611 emit_optional_rex_32(dst);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000612 DCHECK(is_int8(src.value_) || is_uint8(src.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000613 emit(0x80);
614 emit_operand(subcode, dst);
615 emit(src.value_);
616}
617
618
619void Assembler::immediate_arithmetic_op_8(byte subcode,
620 Register dst,
621 Immediate src) {
622 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100623 if (!dst.is_byte_register()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000624 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
625 emit_rex_32(dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000626 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000627 DCHECK(is_int8(src.value_) || is_uint8(src.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000628 emit(0x80);
629 emit_modrm(subcode, dst);
630 emit(src.value_);
631}
632
633
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000634void Assembler::shift(Register dst,
635 Immediate shift_amount,
636 int subcode,
637 int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000638 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000639 DCHECK(size == kInt64Size ? is_uint6(shift_amount.value_)
640 : is_uint5(shift_amount.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000641 if (shift_amount.value_ == 1) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000642 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000643 emit(0xD1);
644 emit_modrm(subcode, dst);
645 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000646 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000647 emit(0xC1);
648 emit_modrm(subcode, dst);
649 emit(shift_amount.value_);
650 }
651}
652
653
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400654void Assembler::shift(Operand dst, Immediate shift_amount, int subcode,
655 int size) {
656 EnsureSpace ensure_space(this);
657 DCHECK(size == kInt64Size ? is_uint6(shift_amount.value_)
658 : is_uint5(shift_amount.value_));
659 if (shift_amount.value_ == 1) {
660 emit_rex(dst, size);
661 emit(0xD1);
662 emit_operand(subcode, dst);
663 } else {
664 emit_rex(dst, size);
665 emit(0xC1);
666 emit_operand(subcode, dst);
667 emit(shift_amount.value_);
668 }
669}
670
671
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000672void Assembler::shift(Register dst, int subcode, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000673 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000674 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000675 emit(0xD3);
676 emit_modrm(subcode, dst);
677}
678
679
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400680void Assembler::shift(Operand dst, int subcode, int size) {
681 EnsureSpace ensure_space(this);
682 emit_rex(dst, size);
683 emit(0xD3);
684 emit_operand(subcode, dst);
685}
686
687
Steve Blocka7e24c12009-10-30 11:49:00 +0000688void Assembler::bt(const Operand& dst, Register src) {
689 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000690 emit_rex_64(src, dst);
691 emit(0x0F);
692 emit(0xA3);
693 emit_operand(src, dst);
694}
695
696
697void Assembler::bts(const Operand& dst, Register src) {
698 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000699 emit_rex_64(src, dst);
700 emit(0x0F);
701 emit(0xAB);
702 emit_operand(src, dst);
703}
704
705
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000706void Assembler::bsrl(Register dst, Register src) {
707 EnsureSpace ensure_space(this);
708 emit_optional_rex_32(dst, src);
709 emit(0x0F);
710 emit(0xBD);
711 emit_modrm(dst, src);
712}
713
714
Steve Blocka7e24c12009-10-30 11:49:00 +0000715void Assembler::call(Label* L) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100716 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000717 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000718 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +0000719 emit(0xE8);
720 if (L->is_bound()) {
721 int offset = L->pos() - pc_offset() - sizeof(int32_t);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000722 DCHECK(offset <= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000723 emitl(offset);
724 } else if (L->is_linked()) {
725 emitl(L->pos());
726 L->link_to(pc_offset() - sizeof(int32_t));
727 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000728 DCHECK(L->is_unused());
Steve Blocka7e24c12009-10-30 11:49:00 +0000729 int32_t current = pc_offset();
730 emitl(current);
731 L->link_to(current);
732 }
733}
734
735
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000736void Assembler::call(Address entry, RelocInfo::Mode rmode) {
737 DCHECK(RelocInfo::IsRuntimeEntry(rmode));
738 positions_recorder()->WriteRecordedPositions();
739 EnsureSpace ensure_space(this);
740 // 1110 1000 #32-bit disp.
741 emit(0xE8);
742 emit_runtime_entry(entry, rmode);
743}
744
745
Ben Murdoch257744e2011-11-30 15:57:28 +0000746void Assembler::call(Handle<Code> target,
747 RelocInfo::Mode rmode,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000748 TypeFeedbackId ast_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800749 positions_recorder()->WriteRecordedPositions();
Steve Block3ce2e202009-11-05 08:53:23 +0000750 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000751 // 1110 1000 #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +0000752 emit(0xE8);
Ben Murdoch257744e2011-11-30 15:57:28 +0000753 emit_code_target(target, rmode, ast_id);
Steve Block3ce2e202009-11-05 08:53:23 +0000754}
755
756
Steve Blocka7e24c12009-10-30 11:49:00 +0000757void Assembler::call(Register adr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100758 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000759 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000760 // Opcode: FF /2 r64.
Steve Block8defd9f2010-07-08 12:39:36 +0100761 emit_optional_rex_32(adr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000762 emit(0xFF);
763 emit_modrm(0x2, adr);
764}
765
766
767void Assembler::call(const Operand& op) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100768 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000769 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000770 // Opcode: FF /2 m64.
Steve Block8defd9f2010-07-08 12:39:36 +0100771 emit_optional_rex_32(op);
Steve Blocka7e24c12009-10-30 11:49:00 +0000772 emit(0xFF);
Steve Block8defd9f2010-07-08 12:39:36 +0100773 emit_operand(0x2, op);
Steve Blocka7e24c12009-10-30 11:49:00 +0000774}
775
776
Steve Block1e0659c2011-05-24 12:43:12 +0100777// Calls directly to the given address using a relative offset.
778// Should only ever be used in Code objects for calls within the
779// same Code object. Should not be used when generating new code (use labels),
780// but only when patching existing code.
781void Assembler::call(Address target) {
782 positions_recorder()->WriteRecordedPositions();
783 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +0100784 // 1110 1000 #32-bit disp.
785 emit(0xE8);
786 Address source = pc_ + 4;
787 intptr_t displacement = target - source;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000788 DCHECK(is_int32(displacement));
Steve Block1e0659c2011-05-24 12:43:12 +0100789 emitl(static_cast<int32_t>(displacement));
790}
791
792
Steve Block3ce2e202009-11-05 08:53:23 +0000793void Assembler::clc() {
794 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +0000795 emit(0xF8);
796}
797
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000798
Steve Block44f0eee2011-05-26 01:26:41 +0100799void Assembler::cld() {
800 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +0100801 emit(0xFC);
802}
803
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000804
Steve Blocka7e24c12009-10-30 11:49:00 +0000805void Assembler::cdq() {
806 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000807 emit(0x99);
808}
809
810
811void Assembler::cmovq(Condition cc, Register dst, Register src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000812 if (cc == always) {
813 movq(dst, src);
814 } else if (cc == never) {
815 return;
816 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000817 // No need to check CpuInfo for CMOV support, it's a required part of the
818 // 64-bit architecture.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000819 DCHECK(cc >= 0); // Use mov for unconditional moves.
Steve Blocka7e24c12009-10-30 11:49:00 +0000820 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000821 // Opcode: REX.W 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000822 emit_rex_64(dst, src);
823 emit(0x0f);
824 emit(0x40 + cc);
825 emit_modrm(dst, src);
826}
827
828
829void Assembler::cmovq(Condition cc, Register dst, const Operand& src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000830 if (cc == always) {
831 movq(dst, src);
832 } else if (cc == never) {
833 return;
834 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000835 DCHECK(cc >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000836 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000837 // Opcode: REX.W 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000838 emit_rex_64(dst, src);
839 emit(0x0f);
840 emit(0x40 + cc);
841 emit_operand(dst, src);
842}
843
844
845void Assembler::cmovl(Condition cc, Register dst, Register src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000846 if (cc == always) {
847 movl(dst, src);
848 } else if (cc == never) {
849 return;
850 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000851 DCHECK(cc >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000852 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000853 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000854 emit_optional_rex_32(dst, src);
855 emit(0x0f);
856 emit(0x40 + cc);
857 emit_modrm(dst, src);
858}
859
860
861void Assembler::cmovl(Condition cc, Register dst, const Operand& src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000862 if (cc == always) {
863 movl(dst, src);
864 } else if (cc == never) {
865 return;
866 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000867 DCHECK(cc >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000868 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000869 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000870 emit_optional_rex_32(dst, src);
871 emit(0x0f);
872 emit(0x40 + cc);
873 emit_operand(dst, src);
874}
875
876
877void Assembler::cmpb_al(Immediate imm8) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000878 DCHECK(is_int8(imm8.value_) || is_uint8(imm8.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000879 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000880 emit(0x3c);
881 emit(imm8.value_);
882}
883
884
885void Assembler::cpuid() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000886 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000887 emit(0x0F);
888 emit(0xA2);
889}
890
891
892void Assembler::cqo() {
893 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000894 emit_rex_64();
895 emit(0x99);
896}
897
898
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000899void Assembler::emit_dec(Register dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000900 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000901 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000902 emit(0xFF);
903 emit_modrm(0x1, dst);
904}
905
906
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000907void Assembler::emit_dec(const Operand& dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000908 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000909 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000910 emit(0xFF);
911 emit_operand(1, dst);
912}
913
914
Steve Block3ce2e202009-11-05 08:53:23 +0000915void Assembler::decb(Register dst) {
916 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100917 if (!dst.is_byte_register()) {
Steve Block3ce2e202009-11-05 08:53:23 +0000918 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
919 emit_rex_32(dst);
920 }
921 emit(0xFE);
922 emit_modrm(0x1, dst);
923}
924
925
926void Assembler::decb(const Operand& dst) {
927 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +0000928 emit_optional_rex_32(dst);
929 emit(0xFE);
930 emit_operand(1, dst);
931}
932
933
Steve Blocka7e24c12009-10-30 11:49:00 +0000934void Assembler::enter(Immediate size) {
935 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000936 emit(0xC8);
937 emitw(size.value_); // 16 bit operand, always.
938 emit(0);
939}
940
941
942void Assembler::hlt() {
943 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000944 emit(0xF4);
945}
946
947
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000948void Assembler::emit_idiv(Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000949 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000950 emit_rex(src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000951 emit(0xF7);
952 emit_modrm(0x7, src);
953}
954
955
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000956void Assembler::emit_div(Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000957 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000958 emit_rex(src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000959 emit(0xF7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000960 emit_modrm(0x6, src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000961}
962
963
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000964void Assembler::emit_imul(Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000965 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000966 emit_rex(src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000967 emit(0xF7);
968 emit_modrm(0x5, src);
969}
970
971
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400972void Assembler::emit_imul(const Operand& src, int size) {
973 EnsureSpace ensure_space(this);
974 emit_rex(src, size);
975 emit(0xF7);
976 emit_operand(0x5, src);
977}
978
979
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000980void Assembler::emit_imul(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000981 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000982 emit_rex(dst, src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000983 emit(0x0F);
984 emit(0xAF);
985 emit_modrm(dst, src);
986}
987
988
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000989void Assembler::emit_imul(Register dst, const Operand& src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000990 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000991 emit_rex(dst, src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000992 emit(0x0F);
993 emit(0xAF);
994 emit_operand(dst, src);
995}
996
997
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998void Assembler::emit_imul(Register dst, Register src, Immediate imm, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000999 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001000 emit_rex(dst, src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001001 if (is_int8(imm.value_)) {
1002 emit(0x6B);
1003 emit_modrm(dst, src);
1004 emit(imm.value_);
1005 } else {
1006 emit(0x69);
1007 emit_modrm(dst, src);
1008 emitl(imm.value_);
1009 }
1010}
1011
1012
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001013void Assembler::emit_imul(Register dst, const Operand& src, Immediate imm,
1014 int size) {
1015 EnsureSpace ensure_space(this);
1016 emit_rex(dst, src, size);
1017 if (is_int8(imm.value_)) {
1018 emit(0x6B);
1019 emit_operand(dst, src);
1020 emit(imm.value_);
1021 } else {
1022 emit(0x69);
1023 emit_operand(dst, src);
1024 emitl(imm.value_);
1025 }
1026}
1027
1028
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001029void Assembler::emit_inc(Register dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001030 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001031 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001032 emit(0xFF);
1033 emit_modrm(0x0, dst);
1034}
1035
1036
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001037void Assembler::emit_inc(const Operand& dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001038 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001039 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001040 emit(0xFF);
1041 emit_operand(0, dst);
1042}
1043
1044
Steve Blocka7e24c12009-10-30 11:49:00 +00001045void Assembler::int3() {
1046 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001047 emit(0xCC);
1048}
1049
1050
Ben Murdoch257744e2011-11-30 15:57:28 +00001051void Assembler::j(Condition cc, Label* L, Label::Distance distance) {
Steve Block3ce2e202009-11-05 08:53:23 +00001052 if (cc == always) {
1053 jmp(L);
1054 return;
1055 } else if (cc == never) {
1056 return;
1057 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001058 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001059 DCHECK(is_uint4(cc));
Steve Blocka7e24c12009-10-30 11:49:00 +00001060 if (L->is_bound()) {
1061 const int short_size = 2;
1062 const int long_size = 6;
1063 int offs = L->pos() - pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001064 DCHECK(offs <= 0);
1065 // Determine whether we can use 1-byte offsets for backwards branches,
1066 // which have a max range of 128 bytes.
1067
1068 // We also need to check predictable_code_size() flag here, because on x64,
1069 // when the full code generator recompiles code for debugging, some places
1070 // need to be padded out to a certain size. The debugger is keeping track of
1071 // how often it did this so that it can adjust return addresses on the
1072 // stack, but if the size of jump instructions can also change, that's not
1073 // enough and the calculated offsets would be incorrect.
1074 if (is_int8(offs - short_size) && !predictable_code_size()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001075 // 0111 tttn #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001076 emit(0x70 | cc);
1077 emit((offs - short_size) & 0xFF);
1078 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001079 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001080 emit(0x0F);
1081 emit(0x80 | cc);
1082 emitl(offs - long_size);
1083 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001084 } else if (distance == Label::kNear) {
1085 // 0111 tttn #8-bit disp
1086 emit(0x70 | cc);
1087 byte disp = 0x00;
1088 if (L->is_near_linked()) {
1089 int offset = L->near_link_pos() - pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001090 DCHECK(is_int8(offset));
Ben Murdoch257744e2011-11-30 15:57:28 +00001091 disp = static_cast<byte>(offset & 0xFF);
1092 }
1093 L->link_to(pc_offset(), Label::kNear);
1094 emit(disp);
Steve Blocka7e24c12009-10-30 11:49:00 +00001095 } else if (L->is_linked()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001096 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001097 emit(0x0F);
1098 emit(0x80 | cc);
1099 emitl(L->pos());
1100 L->link_to(pc_offset() - sizeof(int32_t));
1101 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001102 DCHECK(L->is_unused());
Steve Blocka7e24c12009-10-30 11:49:00 +00001103 emit(0x0F);
1104 emit(0x80 | cc);
1105 int32_t current = pc_offset();
1106 emitl(current);
1107 L->link_to(current);
1108 }
1109}
1110
1111
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001112void Assembler::j(Condition cc, Address entry, RelocInfo::Mode rmode) {
1113 DCHECK(RelocInfo::IsRuntimeEntry(rmode));
1114 EnsureSpace ensure_space(this);
1115 DCHECK(is_uint4(cc));
1116 emit(0x0F);
1117 emit(0x80 | cc);
1118 emit_runtime_entry(entry, rmode);
1119}
1120
1121
Steve Block3ce2e202009-11-05 08:53:23 +00001122void Assembler::j(Condition cc,
1123 Handle<Code> target,
1124 RelocInfo::Mode rmode) {
1125 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001126 DCHECK(is_uint4(cc));
Andrei Popescu31002712010-02-23 13:46:05 +00001127 // 0000 1111 1000 tttn #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +00001128 emit(0x0F);
1129 emit(0x80 | cc);
1130 emit_code_target(target, rmode);
1131}
1132
1133
Ben Murdoch257744e2011-11-30 15:57:28 +00001134void Assembler::jmp(Label* L, Label::Distance distance) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001135 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01001136 const int short_size = sizeof(int8_t);
1137 const int long_size = sizeof(int32_t);
Steve Blocka7e24c12009-10-30 11:49:00 +00001138 if (L->is_bound()) {
1139 int offs = L->pos() - pc_offset() - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001140 DCHECK(offs <= 0);
1141 if (is_int8(offs - short_size) && !predictable_code_size()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001142 // 1110 1011 #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001143 emit(0xEB);
Steve Block6ded16b2010-05-10 14:33:55 +01001144 emit((offs - short_size) & 0xFF);
Steve Blocka7e24c12009-10-30 11:49:00 +00001145 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001146 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001147 emit(0xE9);
Steve Block6ded16b2010-05-10 14:33:55 +01001148 emitl(offs - long_size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001149 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001150 } else if (distance == Label::kNear) {
1151 emit(0xEB);
1152 byte disp = 0x00;
1153 if (L->is_near_linked()) {
1154 int offset = L->near_link_pos() - pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001155 DCHECK(is_int8(offset));
Ben Murdoch257744e2011-11-30 15:57:28 +00001156 disp = static_cast<byte>(offset & 0xFF);
1157 }
1158 L->link_to(pc_offset(), Label::kNear);
1159 emit(disp);
1160 } else if (L->is_linked()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001161 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001162 emit(0xE9);
1163 emitl(L->pos());
Steve Block6ded16b2010-05-10 14:33:55 +01001164 L->link_to(pc_offset() - long_size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001165 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001166 // 1110 1001 #32-bit disp.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001167 DCHECK(L->is_unused());
Steve Blocka7e24c12009-10-30 11:49:00 +00001168 emit(0xE9);
1169 int32_t current = pc_offset();
1170 emitl(current);
1171 L->link_to(current);
1172 }
1173}
1174
1175
Steve Block3ce2e202009-11-05 08:53:23 +00001176void Assembler::jmp(Handle<Code> target, RelocInfo::Mode rmode) {
1177 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +00001178 // 1110 1001 #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +00001179 emit(0xE9);
1180 emit_code_target(target, rmode);
1181}
1182
1183
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001184void Assembler::jmp(Address entry, RelocInfo::Mode rmode) {
1185 DCHECK(RelocInfo::IsRuntimeEntry(rmode));
1186 EnsureSpace ensure_space(this);
1187 DCHECK(RelocInfo::IsRuntimeEntry(rmode));
1188 emit(0xE9);
1189 emit_runtime_entry(entry, rmode);
1190}
1191
1192
Steve Blocka7e24c12009-10-30 11:49:00 +00001193void Assembler::jmp(Register target) {
1194 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +00001195 // Opcode FF/4 r64.
Steve Block8defd9f2010-07-08 12:39:36 +01001196 emit_optional_rex_32(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001197 emit(0xFF);
1198 emit_modrm(0x4, target);
1199}
1200
1201
1202void Assembler::jmp(const Operand& src) {
1203 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +00001204 // Opcode FF/4 m64.
Steve Blocka7e24c12009-10-30 11:49:00 +00001205 emit_optional_rex_32(src);
1206 emit(0xFF);
1207 emit_operand(0x4, src);
1208}
1209
1210
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001211void Assembler::emit_lea(Register dst, const Operand& src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001212 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001213 emit_rex(dst, src, size);
Steve Block6ded16b2010-05-10 14:33:55 +01001214 emit(0x8D);
1215 emit_operand(dst, src);
1216}
1217
1218
Steve Blocka7e24c12009-10-30 11:49:00 +00001219void Assembler::load_rax(void* value, RelocInfo::Mode mode) {
1220 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001221 if (kPointerSize == kInt64Size) {
1222 emit(0x48); // REX.W
1223 emit(0xA1);
1224 emitp(value, mode);
1225 } else {
1226 DCHECK(kPointerSize == kInt32Size);
1227 emit(0xA1);
1228 emitp(value, mode);
1229 // In 64-bit mode, need to zero extend the operand to 8 bytes.
1230 // See 2.2.1.4 in Intel64 and IA32 Architectures Software
1231 // Developer's Manual Volume 2.
1232 emitl(0);
1233 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001234}
1235
1236
1237void Assembler::load_rax(ExternalReference ref) {
1238 load_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
1239}
1240
1241
1242void Assembler::leave() {
1243 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001244 emit(0xC9);
1245}
1246
1247
1248void Assembler::movb(Register dst, const Operand& src) {
1249 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001250 if (!dst.is_byte_register()) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001251 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1252 emit_rex_32(dst, src);
1253 } else {
1254 emit_optional_rex_32(dst, src);
1255 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001256 emit(0x8A);
1257 emit_operand(dst, src);
1258}
1259
Steve Block6ded16b2010-05-10 14:33:55 +01001260
Steve Blocka7e24c12009-10-30 11:49:00 +00001261void Assembler::movb(Register dst, Immediate imm) {
1262 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001263 if (!dst.is_byte_register()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001264 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001265 emit_rex_32(dst);
1266 }
1267 emit(0xB0 + dst.low_bits());
Steve Blocka7e24c12009-10-30 11:49:00 +00001268 emit(imm.value_);
1269}
1270
Steve Block6ded16b2010-05-10 14:33:55 +01001271
Steve Blocka7e24c12009-10-30 11:49:00 +00001272void Assembler::movb(const Operand& dst, Register src) {
1273 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001274 if (!src.is_byte_register()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001275 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001276 emit_rex_32(src, dst);
1277 } else {
1278 emit_optional_rex_32(src, dst);
1279 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001280 emit(0x88);
1281 emit_operand(src, dst);
1282}
1283
Steve Block6ded16b2010-05-10 14:33:55 +01001284
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001285void Assembler::movb(const Operand& dst, Immediate imm) {
1286 EnsureSpace ensure_space(this);
1287 emit_optional_rex_32(dst);
1288 emit(0xC6);
1289 emit_operand(0x0, dst);
1290 emit(static_cast<byte>(imm.value_));
1291}
1292
1293
1294void Assembler::movw(Register dst, const Operand& src) {
1295 EnsureSpace ensure_space(this);
1296 emit(0x66);
1297 emit_optional_rex_32(dst, src);
1298 emit(0x8B);
1299 emit_operand(dst, src);
1300}
1301
1302
Steve Block3ce2e202009-11-05 08:53:23 +00001303void Assembler::movw(const Operand& dst, Register src) {
1304 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001305 emit(0x66);
1306 emit_optional_rex_32(src, dst);
1307 emit(0x89);
1308 emit_operand(src, dst);
1309}
1310
Steve Block6ded16b2010-05-10 14:33:55 +01001311
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001312void Assembler::movw(const Operand& dst, Immediate imm) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001313 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001314 emit(0x66);
1315 emit_optional_rex_32(dst);
1316 emit(0xC7);
1317 emit_operand(0x0, dst);
1318 emit(static_cast<byte>(imm.value_ & 0xff));
1319 emit(static_cast<byte>(imm.value_ >> 8));
1320}
1321
1322
1323void Assembler::emit_mov(Register dst, const Operand& src, int size) {
1324 EnsureSpace ensure_space(this);
1325 emit_rex(dst, src, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001326 emit(0x8B);
1327 emit_operand(dst, src);
1328}
1329
1330
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001331void Assembler::emit_mov(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001332 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +01001333 if (src.low_bits() == 4) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001334 emit_rex(src, dst, size);
Leon Clarkef7060e22010-06-03 12:02:55 +01001335 emit(0x89);
1336 emit_modrm(src, dst);
1337 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001338 emit_rex(dst, src, size);
Leon Clarkef7060e22010-06-03 12:02:55 +01001339 emit(0x8B);
1340 emit_modrm(dst, src);
1341 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001342}
1343
1344
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001345void Assembler::emit_mov(const Operand& dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001346 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001347 emit_rex(src, dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001348 emit(0x89);
1349 emit_operand(src, dst);
1350}
1351
1352
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001353void Assembler::emit_mov(Register dst, Immediate value, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001354 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001355 emit_rex(dst, size);
1356 if (size == kInt64Size) {
1357 emit(0xC7);
1358 emit_modrm(0x0, dst);
1359 } else {
1360 DCHECK(size == kInt32Size);
1361 emit(0xB8 + dst.low_bits());
1362 }
1363 emit(value);
1364}
1365
1366
1367void Assembler::emit_mov(const Operand& dst, Immediate value, int size) {
1368 EnsureSpace ensure_space(this);
1369 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001370 emit(0xC7);
1371 emit_operand(0x0, dst);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001372 emit(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001373}
1374
1375
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001376void Assembler::movp(Register dst, void* value, RelocInfo::Mode rmode) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001377 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001378 emit_rex(dst, kPointerSize);
1379 emit(0xB8 | dst.low_bits());
1380 emitp(value, rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001381}
1382
1383
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001384void Assembler::movq(Register dst, int64_t value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001385 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001386 emit_rex_64(dst);
1387 emit(0xB8 | dst.low_bits());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001388 emitq(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001389}
1390
1391
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001392void Assembler::movq(Register dst, uint64_t value) {
1393 movq(dst, static_cast<int64_t>(value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001394}
1395
1396
Andrei Popescu31002712010-02-23 13:46:05 +00001397// Loads the ip-relative location of the src label into the target location
1398// (as a 32-bit offset sign extended to 64-bit).
Steve Blocka7e24c12009-10-30 11:49:00 +00001399void Assembler::movl(const Operand& dst, Label* src) {
1400 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001401 emit_optional_rex_32(dst);
1402 emit(0xC7);
1403 emit_operand(0, dst);
1404 if (src->is_bound()) {
1405 int offset = src->pos() - pc_offset() - sizeof(int32_t);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001406 DCHECK(offset <= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001407 emitl(offset);
1408 } else if (src->is_linked()) {
1409 emitl(src->pos());
1410 src->link_to(pc_offset() - sizeof(int32_t));
1411 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001412 DCHECK(src->is_unused());
Steve Blocka7e24c12009-10-30 11:49:00 +00001413 int32_t current = pc_offset();
1414 emitl(current);
1415 src->link_to(current);
1416 }
1417}
1418
1419
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001420void Assembler::movsxbl(Register dst, Register src) {
1421 EnsureSpace ensure_space(this);
1422 if (!src.is_byte_register()) {
1423 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1424 emit_rex_32(dst, src);
1425 } else {
1426 emit_optional_rex_32(dst, src);
1427 }
1428 emit(0x0F);
1429 emit(0xBE);
1430 emit_modrm(dst, src);
1431}
1432
1433
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001434void Assembler::movsxbl(Register dst, const Operand& src) {
1435 EnsureSpace ensure_space(this);
1436 emit_optional_rex_32(dst, src);
1437 emit(0x0F);
1438 emit(0xBE);
1439 emit_operand(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001440}
1441
1442
Steve Block3ce2e202009-11-05 08:53:23 +00001443void Assembler::movsxbq(Register dst, const Operand& src) {
1444 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001445 emit_rex_64(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00001446 emit(0x0F);
1447 emit(0xBE);
1448 emit_operand(dst, src);
1449}
1450
1451
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001452void Assembler::movsxwl(Register dst, Register src) {
1453 EnsureSpace ensure_space(this);
1454 emit_optional_rex_32(dst, src);
1455 emit(0x0F);
1456 emit(0xBF);
1457 emit_modrm(dst, src);
1458}
1459
1460
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001461void Assembler::movsxwl(Register dst, const Operand& src) {
1462 EnsureSpace ensure_space(this);
1463 emit_optional_rex_32(dst, src);
1464 emit(0x0F);
1465 emit(0xBF);
1466 emit_operand(dst, src);
1467}
1468
1469
Steve Block3ce2e202009-11-05 08:53:23 +00001470void Assembler::movsxwq(Register dst, const Operand& src) {
1471 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001472 emit_rex_64(dst, src);
1473 emit(0x0F);
1474 emit(0xBF);
1475 emit_operand(dst, src);
1476}
1477
1478
Steve Blocka7e24c12009-10-30 11:49:00 +00001479void Assembler::movsxlq(Register dst, Register src) {
1480 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001481 emit_rex_64(dst, src);
1482 emit(0x63);
1483 emit_modrm(dst, src);
1484}
1485
1486
1487void Assembler::movsxlq(Register dst, const Operand& src) {
1488 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001489 emit_rex_64(dst, src);
1490 emit(0x63);
1491 emit_operand(dst, src);
1492}
1493
1494
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001495void Assembler::emit_movzxb(Register dst, const Operand& src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001496 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001497 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
1498 // there is no need to make this a 64 bit operation.
Steve Block8defd9f2010-07-08 12:39:36 +01001499 emit_optional_rex_32(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001500 emit(0x0F);
1501 emit(0xB6);
1502 emit_operand(dst, src);
1503}
1504
1505
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001506void Assembler::emit_movzxb(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001507 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001508 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
1509 // there is no need to make this a 64 bit operation.
1510 if (!src.is_byte_register()) {
1511 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1512 emit_rex_32(dst, src);
1513 } else {
1514 emit_optional_rex_32(dst, src);
1515 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001516 emit(0x0F);
1517 emit(0xB6);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001518 emit_modrm(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001519}
1520
1521
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001522void Assembler::emit_movzxw(Register dst, const Operand& src, int size) {
Steve Block3ce2e202009-11-05 08:53:23 +00001523 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001524 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
1525 // there is no need to make this a 64 bit operation.
Steve Block8defd9f2010-07-08 12:39:36 +01001526 emit_optional_rex_32(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00001527 emit(0x0F);
1528 emit(0xB7);
1529 emit_operand(dst, src);
1530}
1531
1532
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001533void Assembler::emit_movzxw(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001534 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001535 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
1536 // there is no need to make this a 64 bit operation.
Steve Blocka7e24c12009-10-30 11:49:00 +00001537 emit_optional_rex_32(dst, src);
1538 emit(0x0F);
1539 emit(0xB7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001540 emit_modrm(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001541}
1542
1543
Leon Clarked91b9f72010-01-27 17:25:45 +00001544void Assembler::repmovsb() {
1545 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001546 emit(0xF3);
1547 emit(0xA4);
1548}
1549
1550
1551void Assembler::repmovsw() {
1552 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001553 emit(0x66); // Operand size override.
1554 emit(0xF3);
1555 emit(0xA4);
1556}
1557
1558
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001559void Assembler::emit_repmovs(int size) {
Leon Clarked91b9f72010-01-27 17:25:45 +00001560 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001561 emit(0xF3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001562 emit_rex(size);
Leon Clarked91b9f72010-01-27 17:25:45 +00001563 emit(0xA5);
1564}
1565
1566
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001567void Assembler::mull(Register src) {
1568 EnsureSpace ensure_space(this);
1569 emit_optional_rex_32(src);
1570 emit(0xF7);
1571 emit_modrm(0x4, src);
1572}
1573
1574
1575void Assembler::mull(const Operand& src) {
1576 EnsureSpace ensure_space(this);
1577 emit_optional_rex_32(src);
1578 emit(0xF7);
1579 emit_operand(0x4, src);
1580}
1581
1582
1583void Assembler::mulq(Register src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001584 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001585 emit_rex_64(src);
1586 emit(0xF7);
1587 emit_modrm(0x4, src);
1588}
1589
1590
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001591void Assembler::emit_neg(Register dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001592 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001593 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001594 emit(0xF7);
1595 emit_modrm(0x3, dst);
1596}
1597
1598
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001599void Assembler::emit_neg(const Operand& dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001600 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001601 emit_rex_64(dst);
1602 emit(0xF7);
1603 emit_operand(3, dst);
1604}
1605
1606
1607void Assembler::nop() {
1608 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001609 emit(0x90);
1610}
1611
1612
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001613void Assembler::emit_not(Register dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001614 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001615 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001616 emit(0xF7);
1617 emit_modrm(0x2, dst);
1618}
1619
1620
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001621void Assembler::emit_not(const Operand& dst, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001622 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001623 emit_rex(dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001624 emit(0xF7);
1625 emit_operand(2, dst);
1626}
1627
1628
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001629void Assembler::Nop(int n) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001630 // The recommended muti-byte sequences of NOP instructions from the Intel 64
1631 // and IA-32 Architectures Software Developer's Manual.
1632 //
1633 // Length Assembly Byte Sequence
1634 // 2 bytes 66 NOP 66 90H
1635 // 3 bytes NOP DWORD ptr [EAX] 0F 1F 00H
1636 // 4 bytes NOP DWORD ptr [EAX + 00H] 0F 1F 40 00H
1637 // 5 bytes NOP DWORD ptr [EAX + EAX*1 + 00H] 0F 1F 44 00 00H
1638 // 6 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00H] 66 0F 1F 44 00 00H
1639 // 7 bytes NOP DWORD ptr [EAX + 00000000H] 0F 1F 80 00 00 00 00H
1640 // 8 bytes NOP DWORD ptr [EAX + EAX*1 + 00000000H] 0F 1F 84 00 00 00 00 00H
1641 // 9 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 66 0F 1F 84 00 00 00 00
1642 // 00000000H] 00H
1643
Steve Blocka7e24c12009-10-30 11:49:00 +00001644 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001645 while (n > 0) {
1646 switch (n) {
1647 case 2:
1648 emit(0x66);
1649 case 1:
1650 emit(0x90);
1651 return;
1652 case 3:
1653 emit(0x0f);
1654 emit(0x1f);
1655 emit(0x00);
1656 return;
1657 case 4:
1658 emit(0x0f);
1659 emit(0x1f);
1660 emit(0x40);
1661 emit(0x00);
1662 return;
1663 case 6:
1664 emit(0x66);
1665 case 5:
1666 emit(0x0f);
1667 emit(0x1f);
1668 emit(0x44);
1669 emit(0x00);
1670 emit(0x00);
1671 return;
1672 case 7:
1673 emit(0x0f);
1674 emit(0x1f);
1675 emit(0x80);
1676 emit(0x00);
1677 emit(0x00);
1678 emit(0x00);
1679 emit(0x00);
1680 return;
1681 default:
1682 case 11:
1683 emit(0x66);
1684 n--;
1685 case 10:
1686 emit(0x66);
1687 n--;
1688 case 9:
1689 emit(0x66);
1690 n--;
1691 case 8:
1692 emit(0x0f);
1693 emit(0x1f);
1694 emit(0x84);
1695 emit(0x00);
1696 emit(0x00);
1697 emit(0x00);
1698 emit(0x00);
1699 emit(0x00);
1700 n -= 8;
1701 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001702 }
1703}
1704
1705
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001706void Assembler::popq(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001707 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001708 emit_optional_rex_32(dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001709 emit(0x58 | dst.low_bits());
1710}
1711
1712
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001713void Assembler::popq(const Operand& dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001714 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001715 emit_optional_rex_32(dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001716 emit(0x8F);
1717 emit_operand(0, dst);
1718}
1719
1720
1721void Assembler::popfq() {
1722 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001723 emit(0x9D);
1724}
1725
1726
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001727void Assembler::pushq(Register src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001728 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001729 emit_optional_rex_32(src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001730 emit(0x50 | src.low_bits());
1731}
1732
1733
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001734void Assembler::pushq(const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001735 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001736 emit_optional_rex_32(src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001737 emit(0xFF);
1738 emit_operand(6, src);
1739}
1740
1741
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001742void Assembler::pushq(Immediate value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001743 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001744 if (is_int8(value.value_)) {
1745 emit(0x6A);
1746 emit(value.value_); // Emit low byte of value.
1747 } else {
1748 emit(0x68);
1749 emitl(value.value_);
1750 }
1751}
1752
1753
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001754void Assembler::pushq_imm32(int32_t imm32) {
Steve Block1e0659c2011-05-24 12:43:12 +01001755 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01001756 emit(0x68);
1757 emitl(imm32);
1758}
1759
1760
Steve Blocka7e24c12009-10-30 11:49:00 +00001761void Assembler::pushfq() {
1762 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001763 emit(0x9C);
1764}
1765
1766
Steve Blocka7e24c12009-10-30 11:49:00 +00001767void Assembler::ret(int imm16) {
1768 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001769 DCHECK(is_uint16(imm16));
Steve Blocka7e24c12009-10-30 11:49:00 +00001770 if (imm16 == 0) {
1771 emit(0xC3);
1772 } else {
1773 emit(0xC2);
1774 emit(imm16 & 0xFF);
1775 emit((imm16 >> 8) & 0xFF);
1776 }
1777}
1778
1779
1780void Assembler::setcc(Condition cc, Register reg) {
Steve Block3ce2e202009-11-05 08:53:23 +00001781 if (cc > last_condition) {
1782 movb(reg, Immediate(cc == always ? 1 : 0));
1783 return;
1784 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001785 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001786 DCHECK(is_uint4(cc));
1787 if (!reg.is_byte_register()) {
1788 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
Steve Blocka7e24c12009-10-30 11:49:00 +00001789 emit_rex_32(reg);
1790 }
1791 emit(0x0F);
1792 emit(0x90 | cc);
1793 emit_modrm(0x0, reg);
1794}
1795
1796
1797void Assembler::shld(Register dst, Register src) {
1798 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001799 emit_rex_64(src, dst);
1800 emit(0x0F);
1801 emit(0xA5);
1802 emit_modrm(src, dst);
1803}
1804
1805
1806void Assembler::shrd(Register dst, Register src) {
1807 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001808 emit_rex_64(src, dst);
1809 emit(0x0F);
1810 emit(0xAD);
1811 emit_modrm(src, dst);
1812}
1813
1814
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001815void Assembler::emit_xchg(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001816 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001817 if (src.is(rax) || dst.is(rax)) { // Single-byte encoding
1818 Register other = src.is(rax) ? dst : src;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001819 emit_rex(other, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001820 emit(0x90 | other.low_bits());
Leon Clarkef7060e22010-06-03 12:02:55 +01001821 } else if (dst.low_bits() == 4) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001822 emit_rex(dst, src, size);
Leon Clarkef7060e22010-06-03 12:02:55 +01001823 emit(0x87);
1824 emit_modrm(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001825 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001826 emit_rex(src, dst, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001827 emit(0x87);
1828 emit_modrm(src, dst);
1829 }
1830}
1831
1832
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001833void Assembler::emit_xchg(Register dst, const Operand& src, int size) {
1834 EnsureSpace ensure_space(this);
1835 emit_rex(dst, src, size);
1836 emit(0x87);
1837 emit_operand(dst, src);
1838}
1839
1840
Steve Blocka7e24c12009-10-30 11:49:00 +00001841void Assembler::store_rax(void* dst, RelocInfo::Mode mode) {
1842 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001843 if (kPointerSize == kInt64Size) {
1844 emit(0x48); // REX.W
1845 emit(0xA3);
1846 emitp(dst, mode);
1847 } else {
1848 DCHECK(kPointerSize == kInt32Size);
1849 emit(0xA3);
1850 emitp(dst, mode);
1851 // In 64-bit mode, need to zero extend the operand to 8 bytes.
1852 // See 2.2.1.4 in Intel64 and IA32 Architectures Software
1853 // Developer's Manual Volume 2.
1854 emitl(0);
1855 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001856}
1857
1858
1859void Assembler::store_rax(ExternalReference ref) {
1860 store_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
1861}
1862
1863
Steve Block3ce2e202009-11-05 08:53:23 +00001864void Assembler::testb(Register dst, Register src) {
1865 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +01001866 if (src.low_bits() == 4) {
1867 emit_rex_32(src, dst);
1868 emit(0x84);
1869 emit_modrm(src, dst);
1870 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001871 if (!dst.is_byte_register() || !src.is_byte_register()) {
Leon Clarkef7060e22010-06-03 12:02:55 +01001872 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1873 emit_rex_32(dst, src);
1874 }
1875 emit(0x84);
1876 emit_modrm(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00001877 }
Steve Block3ce2e202009-11-05 08:53:23 +00001878}
1879
1880
Steve Blocka7e24c12009-10-30 11:49:00 +00001881void Assembler::testb(Register reg, Immediate mask) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001882 DCHECK(is_int8(mask.value_) || is_uint8(mask.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +00001883 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001884 if (reg.is(rax)) {
1885 emit(0xA8);
1886 emit(mask.value_); // Low byte emitted.
1887 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001888 if (!reg.is_byte_register()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001889 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1890 emit_rex_32(reg);
1891 }
1892 emit(0xF6);
1893 emit_modrm(0x0, reg);
1894 emit(mask.value_); // Low byte emitted.
1895 }
1896}
1897
1898
1899void Assembler::testb(const Operand& op, Immediate mask) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001900 DCHECK(is_int8(mask.value_) || is_uint8(mask.value_));
Steve Blocka7e24c12009-10-30 11:49:00 +00001901 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001902 emit_optional_rex_32(rax, op);
1903 emit(0xF6);
1904 emit_operand(rax, op); // Operation code 0
1905 emit(mask.value_); // Low byte emitted.
1906}
1907
1908
Leon Clarkee46be812010-01-19 14:06:41 +00001909void Assembler::testb(const Operand& op, Register reg) {
1910 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001911 if (!reg.is_byte_register()) {
Leon Clarkee46be812010-01-19 14:06:41 +00001912 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1913 emit_rex_32(reg, op);
1914 } else {
1915 emit_optional_rex_32(reg, op);
1916 }
1917 emit(0x84);
1918 emit_operand(reg, op);
1919}
1920
1921
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001922void Assembler::emit_test(Register dst, Register src, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001923 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +01001924 if (src.low_bits() == 4) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001925 emit_rex(src, dst, size);
Leon Clarkef7060e22010-06-03 12:02:55 +01001926 emit(0x85);
1927 emit_modrm(src, dst);
1928 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001929 emit_rex(dst, src, size);
Leon Clarkef7060e22010-06-03 12:02:55 +01001930 emit(0x85);
1931 emit_modrm(dst, src);
1932 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001933}
1934
1935
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001936void Assembler::emit_test(Register reg, Immediate mask, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001937 // testl with a mask that fits in the low byte is exactly testb.
1938 if (is_uint8(mask.value_)) {
1939 testb(reg, mask);
1940 return;
1941 }
1942 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001943 if (reg.is(rax)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001944 emit_rex(rax, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001945 emit(0xA9);
1946 emit(mask);
1947 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001948 emit_rex(reg, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001949 emit(0xF7);
1950 emit_modrm(0x0, reg);
1951 emit(mask);
1952 }
1953}
1954
1955
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001956void Assembler::emit_test(const Operand& op, Immediate mask, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001957 // testl with a mask that fits in the low byte is exactly testb.
1958 if (is_uint8(mask.value_)) {
1959 testb(op, mask);
1960 return;
1961 }
1962 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001963 emit_rex(rax, op, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001964 emit(0xF7);
1965 emit_operand(rax, op); // Operation code 0
1966 emit(mask);
1967}
1968
1969
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001970void Assembler::emit_test(const Operand& op, Register reg, int size) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001971 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001972 emit_rex(reg, op, size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001973 emit(0x85);
1974 emit_operand(reg, op);
1975}
1976
1977
Andrei Popescu31002712010-02-23 13:46:05 +00001978// FPU instructions.
Steve Blocka7e24c12009-10-30 11:49:00 +00001979
1980
1981void Assembler::fld(int i) {
1982 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001983 emit_farith(0xD9, 0xC0, i);
1984}
1985
1986
1987void Assembler::fld1() {
1988 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001989 emit(0xD9);
1990 emit(0xE8);
1991}
1992
1993
1994void Assembler::fldz() {
1995 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001996 emit(0xD9);
1997 emit(0xEE);
1998}
1999
2000
Steve Block6ded16b2010-05-10 14:33:55 +01002001void Assembler::fldpi() {
2002 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002003 emit(0xD9);
2004 emit(0xEB);
2005}
2006
2007
Ben Murdochb0fe1622011-05-05 13:52:32 +01002008void Assembler::fldln2() {
2009 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002010 emit(0xD9);
2011 emit(0xED);
2012}
2013
2014
Steve Blocka7e24c12009-10-30 11:49:00 +00002015void Assembler::fld_s(const Operand& adr) {
2016 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002017 emit_optional_rex_32(adr);
2018 emit(0xD9);
2019 emit_operand(0, adr);
2020}
2021
2022
2023void Assembler::fld_d(const Operand& adr) {
2024 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002025 emit_optional_rex_32(adr);
2026 emit(0xDD);
2027 emit_operand(0, adr);
2028}
2029
2030
2031void Assembler::fstp_s(const Operand& adr) {
2032 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002033 emit_optional_rex_32(adr);
2034 emit(0xD9);
2035 emit_operand(3, adr);
2036}
2037
2038
2039void Assembler::fstp_d(const Operand& adr) {
2040 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002041 emit_optional_rex_32(adr);
2042 emit(0xDD);
2043 emit_operand(3, adr);
2044}
2045
2046
Steve Block3ce2e202009-11-05 08:53:23 +00002047void Assembler::fstp(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002048 DCHECK(is_uint3(index));
Steve Block3ce2e202009-11-05 08:53:23 +00002049 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00002050 emit_farith(0xDD, 0xD8, index);
2051}
2052
2053
Steve Blocka7e24c12009-10-30 11:49:00 +00002054void Assembler::fild_s(const Operand& adr) {
2055 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002056 emit_optional_rex_32(adr);
2057 emit(0xDB);
2058 emit_operand(0, adr);
2059}
2060
2061
2062void Assembler::fild_d(const Operand& adr) {
2063 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002064 emit_optional_rex_32(adr);
2065 emit(0xDF);
2066 emit_operand(5, adr);
2067}
2068
2069
2070void Assembler::fistp_s(const Operand& adr) {
2071 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002072 emit_optional_rex_32(adr);
2073 emit(0xDB);
2074 emit_operand(3, adr);
2075}
2076
2077
2078void Assembler::fisttp_s(const Operand& adr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002079 DCHECK(IsEnabled(SSE3));
Steve Blocka7e24c12009-10-30 11:49:00 +00002080 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002081 emit_optional_rex_32(adr);
2082 emit(0xDB);
2083 emit_operand(1, adr);
2084}
2085
2086
Leon Clarked91b9f72010-01-27 17:25:45 +00002087void Assembler::fisttp_d(const Operand& adr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002088 DCHECK(IsEnabled(SSE3));
Leon Clarked91b9f72010-01-27 17:25:45 +00002089 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00002090 emit_optional_rex_32(adr);
2091 emit(0xDD);
2092 emit_operand(1, adr);
2093}
2094
2095
Steve Blocka7e24c12009-10-30 11:49:00 +00002096void Assembler::fist_s(const Operand& adr) {
2097 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002098 emit_optional_rex_32(adr);
2099 emit(0xDB);
2100 emit_operand(2, adr);
2101}
2102
2103
2104void Assembler::fistp_d(const Operand& adr) {
2105 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002106 emit_optional_rex_32(adr);
2107 emit(0xDF);
Steve Block3ce2e202009-11-05 08:53:23 +00002108 emit_operand(7, adr);
Steve Blocka7e24c12009-10-30 11:49:00 +00002109}
2110
2111
2112void Assembler::fabs() {
2113 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002114 emit(0xD9);
2115 emit(0xE1);
2116}
2117
2118
2119void Assembler::fchs() {
2120 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002121 emit(0xD9);
2122 emit(0xE0);
2123}
2124
2125
2126void Assembler::fcos() {
2127 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002128 emit(0xD9);
2129 emit(0xFF);
2130}
2131
2132
2133void Assembler::fsin() {
2134 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002135 emit(0xD9);
2136 emit(0xFE);
2137}
2138
2139
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002140void Assembler::fptan() {
2141 EnsureSpace ensure_space(this);
2142 emit(0xD9);
2143 emit(0xF2);
2144}
2145
2146
Ben Murdochb0fe1622011-05-05 13:52:32 +01002147void Assembler::fyl2x() {
2148 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002149 emit(0xD9);
2150 emit(0xF1);
2151}
2152
2153
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002154void Assembler::f2xm1() {
2155 EnsureSpace ensure_space(this);
2156 emit(0xD9);
2157 emit(0xF0);
2158}
2159
2160
2161void Assembler::fscale() {
2162 EnsureSpace ensure_space(this);
2163 emit(0xD9);
2164 emit(0xFD);
2165}
2166
2167
2168void Assembler::fninit() {
2169 EnsureSpace ensure_space(this);
2170 emit(0xDB);
2171 emit(0xE3);
2172}
2173
2174
Steve Blocka7e24c12009-10-30 11:49:00 +00002175void Assembler::fadd(int i) {
2176 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002177 emit_farith(0xDC, 0xC0, i);
2178}
2179
2180
2181void Assembler::fsub(int i) {
2182 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002183 emit_farith(0xDC, 0xE8, i);
2184}
2185
2186
2187void Assembler::fisub_s(const Operand& adr) {
2188 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002189 emit_optional_rex_32(adr);
2190 emit(0xDA);
2191 emit_operand(4, adr);
2192}
2193
2194
2195void Assembler::fmul(int i) {
2196 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002197 emit_farith(0xDC, 0xC8, i);
2198}
2199
2200
2201void Assembler::fdiv(int i) {
2202 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002203 emit_farith(0xDC, 0xF8, i);
2204}
2205
2206
2207void Assembler::faddp(int i) {
2208 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002209 emit_farith(0xDE, 0xC0, i);
2210}
2211
2212
2213void Assembler::fsubp(int i) {
2214 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002215 emit_farith(0xDE, 0xE8, i);
2216}
2217
2218
2219void Assembler::fsubrp(int i) {
2220 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002221 emit_farith(0xDE, 0xE0, i);
2222}
2223
2224
2225void Assembler::fmulp(int i) {
2226 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002227 emit_farith(0xDE, 0xC8, i);
2228}
2229
2230
2231void Assembler::fdivp(int i) {
2232 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002233 emit_farith(0xDE, 0xF8, i);
2234}
2235
2236
2237void Assembler::fprem() {
2238 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002239 emit(0xD9);
2240 emit(0xF8);
2241}
2242
2243
2244void Assembler::fprem1() {
2245 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002246 emit(0xD9);
2247 emit(0xF5);
2248}
2249
2250
2251void Assembler::fxch(int i) {
2252 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002253 emit_farith(0xD9, 0xC8, i);
2254}
2255
2256
2257void Assembler::fincstp() {
2258 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002259 emit(0xD9);
2260 emit(0xF7);
2261}
2262
2263
2264void Assembler::ffree(int i) {
2265 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002266 emit_farith(0xDD, 0xC0, i);
2267}
2268
2269
2270void Assembler::ftst() {
2271 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002272 emit(0xD9);
2273 emit(0xE4);
2274}
2275
2276
2277void Assembler::fucomp(int i) {
2278 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002279 emit_farith(0xDD, 0xE8, i);
2280}
2281
2282
2283void Assembler::fucompp() {
2284 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002285 emit(0xDA);
2286 emit(0xE9);
2287}
2288
2289
Steve Block3ce2e202009-11-05 08:53:23 +00002290void Assembler::fucomi(int i) {
2291 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00002292 emit(0xDB);
2293 emit(0xE8 + i);
2294}
2295
2296
2297void Assembler::fucomip() {
2298 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00002299 emit(0xDF);
2300 emit(0xE9);
2301}
2302
2303
Steve Blocka7e24c12009-10-30 11:49:00 +00002304void Assembler::fcompp() {
2305 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002306 emit(0xDE);
2307 emit(0xD9);
2308}
2309
2310
2311void Assembler::fnstsw_ax() {
2312 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002313 emit(0xDF);
2314 emit(0xE0);
2315}
2316
2317
2318void Assembler::fwait() {
2319 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002320 emit(0x9B);
2321}
2322
2323
2324void Assembler::frndint() {
2325 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002326 emit(0xD9);
2327 emit(0xFC);
2328}
2329
2330
2331void Assembler::fnclex() {
2332 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002333 emit(0xDB);
2334 emit(0xE2);
2335}
2336
2337
2338void Assembler::sahf() {
2339 // TODO(X64): Test for presence. Not all 64-bit intel CPU's have sahf
2340 // in 64-bit mode. Test CpuID.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002341 DCHECK(IsEnabled(SAHF));
Steve Blocka7e24c12009-10-30 11:49:00 +00002342 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002343 emit(0x9E);
2344}
2345
2346
2347void Assembler::emit_farith(int b1, int b2, int i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002348 DCHECK(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2349 DCHECK(is_uint3(i)); // illegal stack offset
Steve Blocka7e24c12009-10-30 11:49:00 +00002350 emit(b1);
2351 emit(b2 + i);
2352}
2353
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002354
2355// SSE operations.
2356
2357void Assembler::andps(XMMRegister dst, XMMRegister src) {
2358 EnsureSpace ensure_space(this);
2359 emit_optional_rex_32(dst, src);
2360 emit(0x0F);
2361 emit(0x54);
2362 emit_sse_operand(dst, src);
2363}
2364
2365
2366void Assembler::andps(XMMRegister dst, const Operand& src) {
2367 EnsureSpace ensure_space(this);
2368 emit_optional_rex_32(dst, src);
2369 emit(0x0F);
2370 emit(0x54);
2371 emit_sse_operand(dst, src);
2372}
2373
2374
2375void Assembler::orps(XMMRegister dst, XMMRegister src) {
2376 EnsureSpace ensure_space(this);
2377 emit_optional_rex_32(dst, src);
2378 emit(0x0F);
2379 emit(0x56);
2380 emit_sse_operand(dst, src);
2381}
2382
2383
2384void Assembler::orps(XMMRegister dst, const Operand& src) {
2385 EnsureSpace ensure_space(this);
2386 emit_optional_rex_32(dst, src);
2387 emit(0x0F);
2388 emit(0x56);
2389 emit_sse_operand(dst, src);
2390}
2391
2392
2393void Assembler::xorps(XMMRegister dst, XMMRegister src) {
2394 EnsureSpace ensure_space(this);
2395 emit_optional_rex_32(dst, src);
2396 emit(0x0F);
2397 emit(0x57);
2398 emit_sse_operand(dst, src);
2399}
2400
2401
2402void Assembler::xorps(XMMRegister dst, const Operand& src) {
2403 EnsureSpace ensure_space(this);
2404 emit_optional_rex_32(dst, src);
2405 emit(0x0F);
2406 emit(0x57);
2407 emit_sse_operand(dst, src);
2408}
2409
2410
2411void Assembler::addps(XMMRegister dst, XMMRegister src) {
2412 EnsureSpace ensure_space(this);
2413 emit_optional_rex_32(dst, src);
2414 emit(0x0F);
2415 emit(0x58);
2416 emit_sse_operand(dst, src);
2417}
2418
2419
2420void Assembler::addps(XMMRegister dst, const Operand& src) {
2421 EnsureSpace ensure_space(this);
2422 emit_optional_rex_32(dst, src);
2423 emit(0x0F);
2424 emit(0x58);
2425 emit_sse_operand(dst, src);
2426}
2427
2428
2429void Assembler::subps(XMMRegister dst, XMMRegister src) {
2430 EnsureSpace ensure_space(this);
2431 emit_optional_rex_32(dst, src);
2432 emit(0x0F);
2433 emit(0x5C);
2434 emit_sse_operand(dst, src);
2435}
2436
2437
2438void Assembler::subps(XMMRegister dst, const Operand& src) {
2439 EnsureSpace ensure_space(this);
2440 emit_optional_rex_32(dst, src);
2441 emit(0x0F);
2442 emit(0x5C);
2443 emit_sse_operand(dst, src);
2444}
2445
2446
2447void Assembler::mulps(XMMRegister dst, XMMRegister src) {
2448 EnsureSpace ensure_space(this);
2449 emit_optional_rex_32(dst, src);
2450 emit(0x0F);
2451 emit(0x59);
2452 emit_sse_operand(dst, src);
2453}
2454
2455
2456void Assembler::mulps(XMMRegister dst, const Operand& src) {
2457 EnsureSpace ensure_space(this);
2458 emit_optional_rex_32(dst, src);
2459 emit(0x0F);
2460 emit(0x59);
2461 emit_sse_operand(dst, src);
2462}
2463
2464
2465void Assembler::divps(XMMRegister dst, XMMRegister src) {
2466 EnsureSpace ensure_space(this);
2467 emit_optional_rex_32(dst, src);
2468 emit(0x0F);
2469 emit(0x5E);
2470 emit_sse_operand(dst, src);
2471}
2472
2473
2474void Assembler::divps(XMMRegister dst, const Operand& src) {
2475 EnsureSpace ensure_space(this);
2476 emit_optional_rex_32(dst, src);
2477 emit(0x0F);
2478 emit(0x5E);
2479 emit_sse_operand(dst, src);
2480}
2481
2482
Andrei Popescu31002712010-02-23 13:46:05 +00002483// SSE 2 operations.
Steve Blocka7e24c12009-10-30 11:49:00 +00002484
Steve Block6ded16b2010-05-10 14:33:55 +01002485void Assembler::movd(XMMRegister dst, Register src) {
2486 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002487 emit(0x66);
2488 emit_optional_rex_32(dst, src);
2489 emit(0x0F);
2490 emit(0x6E);
2491 emit_sse_operand(dst, src);
2492}
2493
2494
2495void Assembler::movd(Register dst, XMMRegister src) {
2496 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002497 emit(0x66);
Ben Murdochbb769b22010-08-11 14:56:33 +01002498 emit_optional_rex_32(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002499 emit(0x0F);
2500 emit(0x7E);
Ben Murdochbb769b22010-08-11 14:56:33 +01002501 emit_sse_operand(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002502}
2503
2504
2505void Assembler::movq(XMMRegister dst, Register src) {
2506 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002507 emit(0x66);
2508 emit_rex_64(dst, src);
2509 emit(0x0F);
2510 emit(0x6E);
2511 emit_sse_operand(dst, src);
2512}
2513
2514
2515void Assembler::movq(Register dst, XMMRegister src) {
2516 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002517 emit(0x66);
Ben Murdochbb769b22010-08-11 14:56:33 +01002518 emit_rex_64(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002519 emit(0x0F);
2520 emit(0x7E);
Ben Murdochbb769b22010-08-11 14:56:33 +01002521 emit_sse_operand(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002522}
2523
2524
Ben Murdoch257744e2011-11-30 15:57:28 +00002525void Assembler::movq(XMMRegister dst, XMMRegister src) {
2526 EnsureSpace ensure_space(this);
2527 if (dst.low_bits() == 4) {
2528 // Avoid unnecessary SIB byte.
2529 emit(0xf3);
2530 emit_optional_rex_32(dst, src);
2531 emit(0x0F);
2532 emit(0x7e);
2533 emit_sse_operand(dst, src);
2534 } else {
2535 emit(0x66);
2536 emit_optional_rex_32(src, dst);
2537 emit(0x0F);
2538 emit(0xD6);
2539 emit_sse_operand(src, dst);
2540 }
2541}
2542
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002543
Ben Murdoch8b112d22011-06-08 16:22:53 +01002544void Assembler::movdqa(const Operand& dst, XMMRegister src) {
2545 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002546 emit(0x66);
2547 emit_rex_64(src, dst);
2548 emit(0x0F);
2549 emit(0x7F);
2550 emit_sse_operand(src, dst);
2551}
2552
2553
2554void Assembler::movdqa(XMMRegister dst, const Operand& src) {
Steve Block1e0659c2011-05-24 12:43:12 +01002555 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002556 emit(0x66);
2557 emit_rex_64(dst, src);
2558 emit(0x0F);
2559 emit(0x6F);
2560 emit_sse_operand(dst, src);
2561}
2562
2563
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002564void Assembler::movdqu(const Operand& dst, XMMRegister src) {
2565 EnsureSpace ensure_space(this);
2566 emit(0xF3);
2567 emit_rex_64(src, dst);
2568 emit(0x0F);
2569 emit(0x7F);
2570 emit_sse_operand(src, dst);
2571}
2572
2573
2574void Assembler::movdqu(XMMRegister dst, const Operand& src) {
2575 EnsureSpace ensure_space(this);
2576 emit(0xF3);
2577 emit_rex_64(dst, src);
2578 emit(0x0F);
2579 emit(0x6F);
2580 emit_sse_operand(dst, src);
2581}
2582
2583
Steve Block6ded16b2010-05-10 14:33:55 +01002584void Assembler::extractps(Register dst, XMMRegister src, byte imm8) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002585 DCHECK(IsEnabled(SSE4_1));
2586 DCHECK(is_uint8(imm8));
Steve Block6ded16b2010-05-10 14:33:55 +01002587 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002588 emit(0x66);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002589 emit_optional_rex_32(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002590 emit(0x0F);
2591 emit(0x3A);
2592 emit(0x17);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002593 emit_sse_operand(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002594 emit(imm8);
2595}
2596
2597
Steve Blocka7e24c12009-10-30 11:49:00 +00002598void Assembler::movsd(const Operand& dst, XMMRegister src) {
2599 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002600 emit(0xF2); // double
2601 emit_optional_rex_32(src, dst);
2602 emit(0x0F);
2603 emit(0x11); // store
2604 emit_sse_operand(src, dst);
2605}
2606
2607
Steve Block3ce2e202009-11-05 08:53:23 +00002608void Assembler::movsd(XMMRegister dst, XMMRegister src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002609 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002610 emit(0xF2); // double
2611 emit_optional_rex_32(dst, src);
2612 emit(0x0F);
2613 emit(0x10); // load
2614 emit_sse_operand(dst, src);
2615}
2616
2617
2618void Assembler::movsd(XMMRegister dst, const Operand& src) {
2619 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002620 emit(0xF2); // double
2621 emit_optional_rex_32(dst, src);
2622 emit(0x0F);
2623 emit(0x10); // load
2624 emit_sse_operand(dst, src);
2625}
2626
2627
Ben Murdoch257744e2011-11-30 15:57:28 +00002628void Assembler::movaps(XMMRegister dst, XMMRegister src) {
2629 EnsureSpace ensure_space(this);
2630 if (src.low_bits() == 4) {
2631 // Try to avoid an unnecessary SIB byte.
2632 emit_optional_rex_32(src, dst);
2633 emit(0x0F);
2634 emit(0x29);
2635 emit_sse_operand(src, dst);
2636 } else {
2637 emit_optional_rex_32(dst, src);
2638 emit(0x0F);
2639 emit(0x28);
2640 emit_sse_operand(dst, src);
2641 }
2642}
2643
2644
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002645void Assembler::shufps(XMMRegister dst, XMMRegister src, byte imm8) {
2646 DCHECK(is_uint8(imm8));
2647 EnsureSpace ensure_space(this);
2648 emit_optional_rex_32(src, dst);
2649 emit(0x0F);
2650 emit(0xC6);
2651 emit_sse_operand(dst, src);
2652 emit(imm8);
2653}
2654
2655
Ben Murdoch257744e2011-11-30 15:57:28 +00002656void Assembler::movapd(XMMRegister dst, XMMRegister src) {
2657 EnsureSpace ensure_space(this);
2658 if (src.low_bits() == 4) {
2659 // Try to avoid an unnecessary SIB byte.
2660 emit(0x66);
2661 emit_optional_rex_32(src, dst);
2662 emit(0x0F);
2663 emit(0x29);
2664 emit_sse_operand(src, dst);
2665 } else {
2666 emit(0x66);
2667 emit_optional_rex_32(dst, src);
2668 emit(0x0F);
2669 emit(0x28);
2670 emit_sse_operand(dst, src);
2671 }
2672}
2673
2674
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002675void Assembler::addss(XMMRegister dst, XMMRegister src) {
2676 EnsureSpace ensure_space(this);
2677 emit(0xF3);
2678 emit_optional_rex_32(dst, src);
2679 emit(0x0F);
2680 emit(0x58);
2681 emit_sse_operand(dst, src);
2682}
2683
2684
2685void Assembler::addss(XMMRegister dst, const Operand& src) {
2686 EnsureSpace ensure_space(this);
2687 emit(0xF3);
2688 emit_optional_rex_32(dst, src);
2689 emit(0x0F);
2690 emit(0x58);
2691 emit_sse_operand(dst, src);
2692}
2693
2694
2695void Assembler::subss(XMMRegister dst, XMMRegister src) {
2696 EnsureSpace ensure_space(this);
2697 emit(0xF3);
2698 emit_optional_rex_32(dst, src);
2699 emit(0x0F);
2700 emit(0x5C);
2701 emit_sse_operand(dst, src);
2702}
2703
2704
2705void Assembler::subss(XMMRegister dst, const Operand& src) {
2706 EnsureSpace ensure_space(this);
2707 emit(0xF3);
2708 emit_optional_rex_32(dst, src);
2709 emit(0x0F);
2710 emit(0x5C);
2711 emit_sse_operand(dst, src);
2712}
2713
2714
2715void Assembler::mulss(XMMRegister dst, XMMRegister src) {
2716 EnsureSpace ensure_space(this);
2717 emit(0xF3);
2718 emit_optional_rex_32(dst, src);
2719 emit(0x0F);
2720 emit(0x59);
2721 emit_sse_operand(dst, src);
2722}
2723
2724
2725void Assembler::mulss(XMMRegister dst, const Operand& src) {
2726 EnsureSpace ensure_space(this);
2727 emit(0xF3);
2728 emit_optional_rex_32(dst, src);
2729 emit(0x0F);
2730 emit(0x59);
2731 emit_sse_operand(dst, src);
2732}
2733
2734
2735void Assembler::divss(XMMRegister dst, XMMRegister src) {
2736 EnsureSpace ensure_space(this);
2737 emit(0xF3);
2738 emit_optional_rex_32(dst, src);
2739 emit(0x0F);
2740 emit(0x5E);
2741 emit_sse_operand(dst, src);
2742}
2743
2744
2745void Assembler::divss(XMMRegister dst, const Operand& src) {
2746 EnsureSpace ensure_space(this);
2747 emit(0xF3);
2748 emit_optional_rex_32(dst, src);
2749 emit(0x0F);
2750 emit(0x5E);
2751 emit_sse_operand(dst, src);
2752}
2753
2754
2755void Assembler::ucomiss(XMMRegister dst, XMMRegister src) {
2756 EnsureSpace ensure_space(this);
2757 emit_optional_rex_32(dst, src);
2758 emit(0x0f);
2759 emit(0x2e);
2760 emit_sse_operand(dst, src);
2761}
2762
2763
2764void Assembler::ucomiss(XMMRegister dst, const Operand& src) {
2765 EnsureSpace ensure_space(this);
2766 emit_optional_rex_32(dst, src);
2767 emit(0x0f);
2768 emit(0x2e);
2769 emit_sse_operand(dst, src);
2770}
2771
2772
Steve Block8defd9f2010-07-08 12:39:36 +01002773void Assembler::movss(XMMRegister dst, const Operand& src) {
2774 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01002775 emit(0xF3); // single
2776 emit_optional_rex_32(dst, src);
2777 emit(0x0F);
2778 emit(0x10); // load
2779 emit_sse_operand(dst, src);
2780}
2781
2782
2783void Assembler::movss(const Operand& src, XMMRegister dst) {
2784 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01002785 emit(0xF3); // single
2786 emit_optional_rex_32(dst, src);
2787 emit(0x0F);
2788 emit(0x11); // store
2789 emit_sse_operand(dst, src);
2790}
2791
2792
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002793void Assembler::psllq(XMMRegister reg, byte imm8) {
2794 EnsureSpace ensure_space(this);
2795 emit(0x66);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002796 emit_optional_rex_32(reg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002797 emit(0x0F);
2798 emit(0x73);
2799 emit_sse_operand(rsi, reg); // rsi == 6
2800 emit(imm8);
2801}
2802
2803
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002804void Assembler::psrlq(XMMRegister reg, byte imm8) {
2805 EnsureSpace ensure_space(this);
2806 emit(0x66);
2807 emit_optional_rex_32(reg);
2808 emit(0x0F);
2809 emit(0x73);
2810 emit_sse_operand(rdx, reg); // rdx == 2
2811 emit(imm8);
2812}
2813
2814
2815void Assembler::pslld(XMMRegister reg, byte imm8) {
2816 EnsureSpace ensure_space(this);
2817 emit(0x66);
2818 emit_optional_rex_32(reg);
2819 emit(0x0F);
2820 emit(0x72);
2821 emit_sse_operand(rsi, reg); // rsi == 6
2822 emit(imm8);
2823}
2824
2825
2826void Assembler::psrld(XMMRegister reg, byte imm8) {
2827 EnsureSpace ensure_space(this);
2828 emit(0x66);
2829 emit_optional_rex_32(reg);
2830 emit(0x0F);
2831 emit(0x72);
2832 emit_sse_operand(rdx, reg); // rdx == 2
2833 emit(imm8);
2834}
2835
2836
Steve Blocka7e24c12009-10-30 11:49:00 +00002837void Assembler::cvttss2si(Register dst, const Operand& src) {
2838 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002839 emit(0xF3);
2840 emit_optional_rex_32(dst, src);
2841 emit(0x0F);
2842 emit(0x2C);
2843 emit_operand(dst, src);
2844}
2845
2846
Steve Block1e0659c2011-05-24 12:43:12 +01002847void Assembler::cvttss2si(Register dst, XMMRegister src) {
2848 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002849 emit(0xF3);
2850 emit_optional_rex_32(dst, src);
2851 emit(0x0F);
2852 emit(0x2C);
2853 emit_sse_operand(dst, src);
2854}
2855
2856
Steve Blocka7e24c12009-10-30 11:49:00 +00002857void Assembler::cvttsd2si(Register dst, const Operand& src) {
2858 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002859 emit(0xF2);
2860 emit_optional_rex_32(dst, src);
2861 emit(0x0F);
2862 emit(0x2C);
2863 emit_operand(dst, src);
2864}
2865
2866
Steve Block1e0659c2011-05-24 12:43:12 +01002867void Assembler::cvttsd2si(Register dst, XMMRegister src) {
2868 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002869 emit(0xF2);
2870 emit_optional_rex_32(dst, src);
2871 emit(0x0F);
2872 emit(0x2C);
2873 emit_sse_operand(dst, src);
2874}
2875
2876
Kristian Monsen25f61362010-05-21 11:50:48 +01002877void Assembler::cvttsd2siq(Register dst, XMMRegister src) {
2878 EnsureSpace ensure_space(this);
Kristian Monsen25f61362010-05-21 11:50:48 +01002879 emit(0xF2);
2880 emit_rex_64(dst, src);
2881 emit(0x0F);
2882 emit(0x2C);
2883 emit_sse_operand(dst, src);
2884}
2885
2886
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002887void Assembler::cvttsd2siq(Register dst, const Operand& src) {
2888 EnsureSpace ensure_space(this);
2889 emit(0xF2);
2890 emit_rex_64(dst, src);
2891 emit(0x0F);
2892 emit(0x2C);
2893 emit_sse_operand(dst, src);
2894}
2895
2896
Steve Blocka7e24c12009-10-30 11:49:00 +00002897void Assembler::cvtlsi2sd(XMMRegister dst, const Operand& src) {
2898 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002899 emit(0xF2);
2900 emit_optional_rex_32(dst, src);
2901 emit(0x0F);
2902 emit(0x2A);
2903 emit_sse_operand(dst, src);
2904}
2905
2906
2907void Assembler::cvtlsi2sd(XMMRegister dst, Register src) {
2908 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002909 emit(0xF2);
2910 emit_optional_rex_32(dst, src);
2911 emit(0x0F);
2912 emit(0x2A);
2913 emit_sse_operand(dst, src);
2914}
2915
2916
Steve Block8defd9f2010-07-08 12:39:36 +01002917void Assembler::cvtlsi2ss(XMMRegister dst, Register src) {
2918 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01002919 emit(0xF3);
2920 emit_optional_rex_32(dst, src);
2921 emit(0x0F);
2922 emit(0x2A);
2923 emit_sse_operand(dst, src);
2924}
2925
2926
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002927void Assembler::cvtqsi2sd(XMMRegister dst, const Operand& src) {
2928 EnsureSpace ensure_space(this);
2929 emit(0xF2);
2930 emit_rex_64(dst, src);
2931 emit(0x0F);
2932 emit(0x2A);
2933 emit_sse_operand(dst, src);
2934}
2935
2936
Steve Blocka7e24c12009-10-30 11:49:00 +00002937void Assembler::cvtqsi2sd(XMMRegister dst, Register src) {
2938 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002939 emit(0xF2);
2940 emit_rex_64(dst, src);
2941 emit(0x0F);
2942 emit(0x2A);
2943 emit_sse_operand(dst, src);
2944}
2945
2946
Steve Block6ded16b2010-05-10 14:33:55 +01002947void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
2948 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002949 emit(0xF3);
2950 emit_optional_rex_32(dst, src);
2951 emit(0x0F);
2952 emit(0x5A);
2953 emit_sse_operand(dst, src);
2954}
2955
2956
Steve Block8defd9f2010-07-08 12:39:36 +01002957void Assembler::cvtss2sd(XMMRegister dst, const Operand& src) {
2958 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01002959 emit(0xF3);
2960 emit_optional_rex_32(dst, src);
2961 emit(0x0F);
2962 emit(0x5A);
2963 emit_sse_operand(dst, src);
2964}
2965
2966
2967void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
2968 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01002969 emit(0xF2);
2970 emit_optional_rex_32(dst, src);
2971 emit(0x0F);
2972 emit(0x5A);
2973 emit_sse_operand(dst, src);
2974}
2975
2976
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002977void Assembler::cvtsd2ss(XMMRegister dst, const Operand& src) {
2978 EnsureSpace ensure_space(this);
2979 emit(0xF2);
2980 emit_optional_rex_32(dst, src);
2981 emit(0x0F);
2982 emit(0x5A);
2983 emit_sse_operand(dst, src);
2984}
2985
2986
Steve Block8defd9f2010-07-08 12:39:36 +01002987void Assembler::cvtsd2si(Register dst, XMMRegister src) {
2988 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01002989 emit(0xF2);
2990 emit_optional_rex_32(dst, src);
2991 emit(0x0F);
2992 emit(0x2D);
2993 emit_sse_operand(dst, src);
2994}
2995
2996
2997void Assembler::cvtsd2siq(Register dst, XMMRegister src) {
2998 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01002999 emit(0xF2);
3000 emit_rex_64(dst, src);
3001 emit(0x0F);
3002 emit(0x2D);
3003 emit_sse_operand(dst, src);
3004}
3005
3006
Steve Blocka7e24c12009-10-30 11:49:00 +00003007void Assembler::addsd(XMMRegister dst, XMMRegister src) {
3008 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003009 emit(0xF2);
3010 emit_optional_rex_32(dst, src);
3011 emit(0x0F);
3012 emit(0x58);
3013 emit_sse_operand(dst, src);
3014}
3015
3016
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003017void Assembler::addsd(XMMRegister dst, const Operand& src) {
3018 EnsureSpace ensure_space(this);
3019 emit(0xF2);
3020 emit_optional_rex_32(dst, src);
3021 emit(0x0F);
3022 emit(0x58);
3023 emit_sse_operand(dst, src);
3024}
3025
3026
Steve Blocka7e24c12009-10-30 11:49:00 +00003027void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
3028 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003029 emit(0xF2);
3030 emit_optional_rex_32(dst, src);
3031 emit(0x0F);
3032 emit(0x59);
3033 emit_sse_operand(dst, src);
3034}
3035
3036
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003037void Assembler::mulsd(XMMRegister dst, const Operand& src) {
3038 EnsureSpace ensure_space(this);
3039 emit(0xF2);
3040 emit_optional_rex_32(dst, src);
3041 emit(0x0F);
3042 emit(0x59);
3043 emit_sse_operand(dst, src);
3044}
3045
3046
Steve Blocka7e24c12009-10-30 11:49:00 +00003047void Assembler::subsd(XMMRegister dst, XMMRegister src) {
3048 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003049 emit(0xF2);
3050 emit_optional_rex_32(dst, src);
3051 emit(0x0F);
3052 emit(0x5C);
3053 emit_sse_operand(dst, src);
3054}
3055
3056
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003057void Assembler::subsd(XMMRegister dst, const Operand& src) {
3058 EnsureSpace ensure_space(this);
3059 emit(0xF2);
3060 emit_optional_rex_32(dst, src);
3061 emit(0x0F);
3062 emit(0x5C);
3063 emit_sse_operand(dst, src);
3064}
3065
3066
Steve Blocka7e24c12009-10-30 11:49:00 +00003067void Assembler::divsd(XMMRegister dst, XMMRegister src) {
3068 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00003069 emit(0xF2);
3070 emit_optional_rex_32(dst, src);
3071 emit(0x0F);
3072 emit(0x5E);
3073 emit_sse_operand(dst, src);
3074}
3075
3076
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003077void Assembler::divsd(XMMRegister dst, const Operand& src) {
3078 EnsureSpace ensure_space(this);
3079 emit(0xF2);
3080 emit_optional_rex_32(dst, src);
3081 emit(0x0F);
3082 emit(0x5E);
3083 emit_sse_operand(dst, src);
3084}
3085
3086
Ben Murdoche0cee9b2011-05-25 10:26:03 +01003087void Assembler::andpd(XMMRegister dst, XMMRegister src) {
3088 EnsureSpace ensure_space(this);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01003089 emit(0x66);
3090 emit_optional_rex_32(dst, src);
3091 emit(0x0F);
3092 emit(0x54);
3093 emit_sse_operand(dst, src);
3094}
3095
3096
3097void Assembler::orpd(XMMRegister dst, XMMRegister src) {
3098 EnsureSpace ensure_space(this);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01003099 emit(0x66);
3100 emit_optional_rex_32(dst, src);
3101 emit(0x0F);
3102 emit(0x56);
3103 emit_sse_operand(dst, src);
3104}
3105
3106
Andrei Popescu402d9372010-02-26 13:31:12 +00003107void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
3108 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003109 emit(0x66);
3110 emit_optional_rex_32(dst, src);
Steve Block6ded16b2010-05-10 14:33:55 +01003111 emit(0x0F);
Andrei Popescu402d9372010-02-26 13:31:12 +00003112 emit(0x57);
3113 emit_sse_operand(dst, src);
3114}
3115
3116
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003117void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch257744e2011-11-30 15:57:28 +00003118 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003119 emit(0xF2);
Ben Murdoch257744e2011-11-30 15:57:28 +00003120 emit_optional_rex_32(dst, src);
3121 emit(0x0F);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003122 emit(0x51);
Ben Murdoch257744e2011-11-30 15:57:28 +00003123 emit_sse_operand(dst, src);
3124}
3125
3126
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003127void Assembler::sqrtsd(XMMRegister dst, const Operand& src) {
Steve Block6ded16b2010-05-10 14:33:55 +01003128 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01003129 emit(0xF2);
3130 emit_optional_rex_32(dst, src);
3131 emit(0x0F);
3132 emit(0x51);
3133 emit_sse_operand(dst, src);
3134}
3135
3136
Andrei Popescu402d9372010-02-26 13:31:12 +00003137void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
3138 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003139 emit(0x66);
3140 emit_optional_rex_32(dst, src);
3141 emit(0x0f);
3142 emit(0x2e);
3143 emit_sse_operand(dst, src);
3144}
3145
Steve Blocka7e24c12009-10-30 11:49:00 +00003146
Steve Block8defd9f2010-07-08 12:39:36 +01003147void Assembler::ucomisd(XMMRegister dst, const Operand& src) {
3148 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01003149 emit(0x66);
3150 emit_optional_rex_32(dst, src);
3151 emit(0x0f);
3152 emit(0x2e);
3153 emit_sse_operand(dst, src);
3154}
3155
3156
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003157void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
3158 EnsureSpace ensure_space(this);
3159 emit(0xF2);
3160 emit_optional_rex_32(dst, src);
3161 emit(0x0F);
3162 emit(0xC2);
3163 emit_sse_operand(dst, src);
3164 emit(0x01); // LT == 1
3165}
3166
3167
Ben Murdoch257744e2011-11-30 15:57:28 +00003168void Assembler::roundsd(XMMRegister dst, XMMRegister src,
3169 Assembler::RoundingMode mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003170 DCHECK(IsEnabled(SSE4_1));
Ben Murdoch257744e2011-11-30 15:57:28 +00003171 EnsureSpace ensure_space(this);
3172 emit(0x66);
3173 emit_optional_rex_32(dst, src);
3174 emit(0x0f);
3175 emit(0x3a);
3176 emit(0x0b);
3177 emit_sse_operand(dst, src);
3178 // Mask precision exeption.
3179 emit(static_cast<byte>(mode) | 0x8);
3180}
3181
3182
Steve Block1e0659c2011-05-24 12:43:12 +01003183void Assembler::movmskpd(Register dst, XMMRegister src) {
3184 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01003185 emit(0x66);
3186 emit_optional_rex_32(dst, src);
3187 emit(0x0f);
3188 emit(0x50);
3189 emit_sse_operand(dst, src);
3190}
3191
Steve Block8defd9f2010-07-08 12:39:36 +01003192
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003193void Assembler::movmskps(Register dst, XMMRegister src) {
3194 EnsureSpace ensure_space(this);
3195 emit_optional_rex_32(dst, src);
3196 emit(0x0f);
3197 emit(0x50);
3198 emit_sse_operand(dst, src);
3199}
3200
3201
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003202void Assembler::pcmpeqd(XMMRegister dst, XMMRegister src) {
3203 EnsureSpace ensure_space(this);
3204 emit(0x66);
3205 emit_optional_rex_32(dst, src);
3206 emit(0x0F);
3207 emit(0x76);
3208 emit_sse_operand(dst, src);
3209}
3210
3211
3212// AVX instructions
3213void Assembler::vfmasd(byte op, XMMRegister dst, XMMRegister src1,
3214 XMMRegister src2) {
3215 DCHECK(IsEnabled(FMA3));
3216 EnsureSpace ensure_space(this);
3217 emit_vex_prefix(dst, src1, src2, kLIG, k66, k0F38, kW1);
3218 emit(op);
3219 emit_sse_operand(dst, src2);
3220}
3221
3222
3223void Assembler::vfmasd(byte op, XMMRegister dst, XMMRegister src1,
3224 const Operand& src2) {
3225 DCHECK(IsEnabled(FMA3));
3226 EnsureSpace ensure_space(this);
3227 emit_vex_prefix(dst, src1, src2, kLIG, k66, k0F38, kW1);
3228 emit(op);
3229 emit_sse_operand(dst, src2);
3230}
3231
3232
3233void Assembler::vfmass(byte op, XMMRegister dst, XMMRegister src1,
3234 XMMRegister src2) {
3235 DCHECK(IsEnabled(FMA3));
3236 EnsureSpace ensure_space(this);
3237 emit_vex_prefix(dst, src1, src2, kLIG, k66, k0F38, kW0);
3238 emit(op);
3239 emit_sse_operand(dst, src2);
3240}
3241
3242
3243void Assembler::vfmass(byte op, XMMRegister dst, XMMRegister src1,
3244 const Operand& src2) {
3245 DCHECK(IsEnabled(FMA3));
3246 EnsureSpace ensure_space(this);
3247 emit_vex_prefix(dst, src1, src2, kLIG, k66, k0F38, kW0);
3248 emit(op);
3249 emit_sse_operand(dst, src2);
3250}
3251
3252
3253void Assembler::vsd(byte op, XMMRegister dst, XMMRegister src1,
3254 XMMRegister src2) {
3255 DCHECK(IsEnabled(AVX));
3256 EnsureSpace ensure_space(this);
3257 emit_vex_prefix(dst, src1, src2, kLIG, kF2, k0F, kWIG);
3258 emit(op);
3259 emit_sse_operand(dst, src2);
3260}
3261
3262
3263void Assembler::vsd(byte op, XMMRegister dst, XMMRegister src1,
3264 const Operand& src2) {
3265 DCHECK(IsEnabled(AVX));
3266 EnsureSpace ensure_space(this);
3267 emit_vex_prefix(dst, src1, src2, kLIG, kF2, k0F, kWIG);
3268 emit(op);
3269 emit_sse_operand(dst, src2);
3270}
3271
3272
Steve Blocka7e24c12009-10-30 11:49:00 +00003273void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
3274 Register ireg = { reg.code() };
3275 emit_operand(ireg, adr);
3276}
3277
3278
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003279void Assembler::emit_sse_operand(Register reg, const Operand& adr) {
3280 Register ireg = {reg.code()};
3281 emit_operand(ireg, adr);
3282}
3283
3284
Steve Blocka7e24c12009-10-30 11:49:00 +00003285void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
3286 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
3287}
3288
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003289
Steve Blocka7e24c12009-10-30 11:49:00 +00003290void Assembler::emit_sse_operand(XMMRegister dst, Register src) {
3291 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
3292}
3293
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003294
Steve Block6ded16b2010-05-10 14:33:55 +01003295void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
3296 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
3297}
3298
Steve Blocka7e24c12009-10-30 11:49:00 +00003299
Ben Murdochb8e0da22011-05-16 14:20:40 +01003300void Assembler::db(uint8_t data) {
3301 EnsureSpace ensure_space(this);
3302 emit(data);
3303}
3304
3305
Ben Murdochb0fe1622011-05-05 13:52:32 +01003306void Assembler::dd(uint32_t data) {
3307 EnsureSpace ensure_space(this);
3308 emitl(data);
3309}
3310
3311
Andrei Popescu31002712010-02-23 13:46:05 +00003312// Relocation information implementations.
Steve Blocka7e24c12009-10-30 11:49:00 +00003313
3314void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003315 DCHECK(!RelocInfo::IsNone(rmode));
Steve Blocka7e24c12009-10-30 11:49:00 +00003316 // Don't record external references unless the heap will be serialized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003317 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
3318 !serializer_enabled() && !emit_debug_code()) {
3319 return;
3320 } else if (rmode == RelocInfo::CODE_AGE_SEQUENCE) {
3321 // Don't record psuedo relocation info for code age sequence mode.
3322 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00003323 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003324 RelocInfo rinfo(pc_, rmode, data, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00003325 reloc_info_writer.Write(&rinfo);
3326}
3327
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003328
Steve Blocka7e24c12009-10-30 11:49:00 +00003329void Assembler::RecordJSReturn() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003330 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00003331 EnsureSpace ensure_space(this);
3332 RecordRelocInfo(RelocInfo::JS_RETURN);
3333}
3334
3335
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003336void Assembler::RecordDebugBreakSlot() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003337 positions_recorder()->WriteRecordedPositions();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003338 EnsureSpace ensure_space(this);
3339 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
3340}
3341
3342
Ben Murdoche0cee9b2011-05-25 10:26:03 +01003343void Assembler::RecordComment(const char* msg, bool force) {
3344 if (FLAG_code_comments || force) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003345 EnsureSpace ensure_space(this);
3346 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
3347 }
3348}
3349
3350
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003351Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
3352 // No out-of-line constant pool support.
3353 DCHECK(!FLAG_enable_ool_constant_pool);
3354 return isolate->factory()->empty_constant_pool_array();
3355}
3356
3357
3358void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
3359 // No out-of-line constant pool support.
3360 DCHECK(!FLAG_enable_ool_constant_pool);
3361 return;
3362}
3363
3364
Steve Block3ce2e202009-11-05 08:53:23 +00003365const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003366 1 << RelocInfo::RUNTIME_ENTRY |
3367 1 << RelocInfo::INTERNAL_REFERENCE |
3368 1 << RelocInfo::CODE_AGE_SEQUENCE;
Steve Blocka7e24c12009-10-30 11:49:00 +00003369
Leon Clarkef7060e22010-06-03 12:02:55 +01003370
3371bool RelocInfo::IsCodedSpecially() {
3372 // The deserializer needs to know whether a pointer is specially coded. Being
3373 // specially coded on x64 means that it is a relative 32 bit address, as used
3374 // by branch instructions.
3375 return (1 << rmode_) & kApplyMask;
3376}
3377
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003378
3379bool RelocInfo::IsInConstantPool() {
3380 return false;
3381}
3382
3383
Steve Blocka7e24c12009-10-30 11:49:00 +00003384} } // namespace v8::internal
Leon Clarkef7060e22010-06-03 12:02:55 +01003385
3386#endif // V8_TARGET_ARCH_X64