blob: 745fdaeb8f2f8572bea2d5843d2fd66e030f9fce [file] [log] [blame]
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
Leon Clarkef7060e22010-06-03 12:02:55 +010030#if defined(V8_TARGET_ARCH_X64)
31
Steve Blocka7e24c12009-10-30 11:49:00 +000032#include "macro-assembler.h"
33#include "serialize.h"
34
35namespace v8 {
36namespace internal {
37
38// -----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +000039// Implementation of CpuFeatures
40
Ben Murdoch8b112d22011-06-08 16:22:53 +010041
42#ifdef DEBUG
43bool CpuFeatures::initialized_ = false;
44#endif
45uint64_t CpuFeatures::supported_ = CpuFeatures::kDefaultCpuFeatures;
46uint64_t CpuFeatures::found_by_runtime_probing_ = 0;
Steve Block44f0eee2011-05-26 01:26:41 +010047
Steve Blocka7e24c12009-10-30 11:49:00 +000048
Ben Murdoch8b112d22011-06-08 16:22:53 +010049void CpuFeatures::Probe() {
50 ASSERT(!initialized_);
51#ifdef DEBUG
52 initialized_ = true;
53#endif
Ben Murdochb0fe1622011-05-05 13:52:32 +010054 supported_ = kDefaultCpuFeatures;
Ben Murdoch8b112d22011-06-08 16:22:53 +010055 if (Serializer::enabled()) {
Steve Blockd0582a62009-12-15 09:54:21 +000056 supported_ |= OS::CpuFeaturesImpliedByPlatform();
57 return; // No features if we might serialize.
58 }
Steve Blocka7e24c12009-10-30 11:49:00 +000059
Ben Murdoch8b112d22011-06-08 16:22:53 +010060 const int kBufferSize = 4 * KB;
61 VirtualMemory* memory = new VirtualMemory(kBufferSize);
62 if (!memory->IsReserved()) {
63 delete memory;
64 return;
65 }
66 ASSERT(memory->size() >= static_cast<size_t>(kBufferSize));
67 if (!memory->Commit(memory->address(), kBufferSize, true/*executable*/)) {
68 delete memory;
69 return;
70 }
71
72 Assembler assm(NULL, memory->address(), kBufferSize);
Steve Blocka7e24c12009-10-30 11:49:00 +000073 Label cpuid, done;
74#define __ assm.
75 // Save old rsp, since we are going to modify the stack.
76 __ push(rbp);
77 __ pushfq();
78 __ push(rcx);
79 __ push(rbx);
80 __ movq(rbp, rsp);
81
82 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
83 __ pushfq();
84 __ pop(rax);
85 __ movq(rdx, rax);
86 __ xor_(rax, Immediate(0x200000)); // Flip bit 21.
87 __ push(rax);
88 __ popfq();
89 __ pushfq();
90 __ pop(rax);
91 __ xor_(rax, rdx); // Different if CPUID is supported.
92 __ j(not_zero, &cpuid);
93
Steve Block9fac8402011-05-12 15:51:54 +010094 // CPUID not supported. Clear the supported features in rax.
Steve Blocka7e24c12009-10-30 11:49:00 +000095 __ xor_(rax, rax);
96 __ jmp(&done);
97
98 // Invoke CPUID with 1 in eax to get feature information in
99 // ecx:edx. Temporarily enable CPUID support because we know it's
100 // safe here.
101 __ bind(&cpuid);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100102 __ movl(rax, Immediate(1));
Steve Blocka7e24c12009-10-30 11:49:00 +0000103 supported_ = kDefaultCpuFeatures | (1 << CPUID);
104 { Scope fscope(CPUID);
105 __ cpuid();
106 // Move the result from ecx:edx to rdi.
107 __ movl(rdi, rdx); // Zero-extended to 64 bits.
108 __ shl(rcx, Immediate(32));
109 __ or_(rdi, rcx);
110
111 // Get the sahf supported flag, from CPUID(0x80000001)
112 __ movq(rax, 0x80000001, RelocInfo::NONE);
113 __ cpuid();
114 }
115 supported_ = kDefaultCpuFeatures;
116
117 // Put the CPU flags in rax.
118 // rax = (rcx & 1) | (rdi & ~1) | (1 << CPUID).
119 __ movl(rax, Immediate(1));
120 __ and_(rcx, rax); // Bit 0 is set if SAHF instruction supported.
121 __ not_(rax);
122 __ and_(rax, rdi);
123 __ or_(rax, rcx);
124 __ or_(rax, Immediate(1 << CPUID));
125
126 // Done.
127 __ bind(&done);
128 __ movq(rsp, rbp);
129 __ pop(rbx);
130 __ pop(rcx);
131 __ popfq();
132 __ pop(rbp);
133 __ ret(0);
134#undef __
135
Steve Blocka7e24c12009-10-30 11:49:00 +0000136 typedef uint64_t (*F0)();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100137 F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000138 supported_ = probe();
Steve Blockd0582a62009-12-15 09:54:21 +0000139 found_by_runtime_probing_ = supported_;
140 found_by_runtime_probing_ &= ~kDefaultCpuFeatures;
141 uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform();
142 supported_ |= os_guarantees;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100143 found_by_runtime_probing_ &= ~os_guarantees;
Steve Blocka7e24c12009-10-30 11:49:00 +0000144 // SSE2 and CMOV must be available on an X64 CPU.
145 ASSERT(IsSupported(CPUID));
146 ASSERT(IsSupported(SSE2));
147 ASSERT(IsSupported(CMOV));
Ben Murdoch8b112d22011-06-08 16:22:53 +0100148
149 delete memory;
Steve Blocka7e24c12009-10-30 11:49:00 +0000150}
151
152
153// -----------------------------------------------------------------------------
154// Implementation of RelocInfo
155
156// Patch the code at the current PC with a call to the target address.
157// Additional guard int3 instructions can be added if required.
158void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
159 // Load register with immediate 64 and call through a register instructions
160 // takes up 13 bytes and int3 takes up one byte.
161 static const int kCallCodeSize = 13;
162 int code_size = kCallCodeSize + guard_bytes;
163
164 // Create a code patcher.
165 CodePatcher patcher(pc_, code_size);
166
167 // Add a label for checking the size of the code used for returning.
168#ifdef DEBUG
169 Label check_codesize;
170 patcher.masm()->bind(&check_codesize);
171#endif
172
173 // Patch the code.
174 patcher.masm()->movq(r10, target, RelocInfo::NONE);
175 patcher.masm()->call(r10);
176
177 // Check that the size of the code generated is as expected.
178 ASSERT_EQ(kCallCodeSize,
179 patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
180
181 // Add the requested number of int3 instructions after the call.
182 for (int i = 0; i < guard_bytes; i++) {
183 patcher.masm()->int3();
184 }
185}
186
187
188void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
189 // Patch the code at the current address with the supplied instructions.
190 for (int i = 0; i < instruction_count; i++) {
191 *(pc_ + i) = *(instructions + i);
192 }
193
194 // Indicate that code has changed.
195 CPU::FlushICache(pc_, instruction_count);
196}
197
Ben Murdochb8e0da22011-05-16 14:20:40 +0100198
199// -----------------------------------------------------------------------------
200// Register constants.
201
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100202const int Register::kRegisterCodeByAllocationIndex[kNumAllocatableRegisters] = {
Steve Block44f0eee2011-05-26 01:26:41 +0100203 // rax, rbx, rdx, rcx, rdi, r8, r9, r11, r14, r15
204 0, 3, 2, 1, 7, 8, 9, 11, 14, 15
Ben Murdochb8e0da22011-05-16 14:20:40 +0100205};
206
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100207const int Register::kAllocationIndexByRegisterCode[kNumRegisters] = {
Steve Block44f0eee2011-05-26 01:26:41 +0100208 0, 3, 2, 1, -1, -1, -1, 4, 5, 6, -1, 7, -1, -1, 8, 9
Ben Murdochb8e0da22011-05-16 14:20:40 +0100209};
210
211
Steve Blocka7e24c12009-10-30 11:49:00 +0000212// -----------------------------------------------------------------------------
213// Implementation of Operand
214
Andrei Popescu402d9372010-02-26 13:31:12 +0000215Operand::Operand(Register base, int32_t disp) : rex_(0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000216 len_ = 1;
217 if (base.is(rsp) || base.is(r12)) {
218 // SIB byte is needed to encode (rsp + offset) or (r12 + offset).
219 set_sib(times_1, rsp, base);
220 }
221
222 if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
223 set_modrm(0, base);
224 } else if (is_int8(disp)) {
225 set_modrm(1, base);
226 set_disp8(disp);
227 } else {
228 set_modrm(2, base);
229 set_disp32(disp);
230 }
231}
232
233
234Operand::Operand(Register base,
235 Register index,
236 ScaleFactor scale,
Andrei Popescu402d9372010-02-26 13:31:12 +0000237 int32_t disp) : rex_(0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000238 ASSERT(!index.is(rsp));
239 len_ = 1;
240 set_sib(scale, index, base);
241 if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
242 // This call to set_modrm doesn't overwrite the REX.B (or REX.X) bits
243 // possibly set by set_sib.
244 set_modrm(0, rsp);
245 } else if (is_int8(disp)) {
246 set_modrm(1, rsp);
247 set_disp8(disp);
248 } else {
249 set_modrm(2, rsp);
250 set_disp32(disp);
251 }
252}
253
254
Andrei Popescu402d9372010-02-26 13:31:12 +0000255Operand::Operand(Register index,
256 ScaleFactor scale,
257 int32_t disp) : rex_(0) {
258 ASSERT(!index.is(rsp));
259 len_ = 1;
260 set_modrm(0, rsp);
261 set_sib(scale, index, rbp);
262 set_disp32(disp);
263}
264
265
Leon Clarkef7060e22010-06-03 12:02:55 +0100266Operand::Operand(const Operand& operand, int32_t offset) {
267 ASSERT(operand.len_ >= 1);
268 // Operand encodes REX ModR/M [SIB] [Disp].
269 byte modrm = operand.buf_[0];
270 ASSERT(modrm < 0xC0); // Disallow mode 3 (register target).
271 bool has_sib = ((modrm & 0x07) == 0x04);
272 byte mode = modrm & 0xC0;
273 int disp_offset = has_sib ? 2 : 1;
274 int base_reg = (has_sib ? operand.buf_[1] : modrm) & 0x07;
275 // Mode 0 with rbp/r13 as ModR/M or SIB base register always has a 32-bit
276 // displacement.
277 bool is_baseless = (mode == 0) && (base_reg == 0x05); // No base or RIP base.
278 int32_t disp_value = 0;
279 if (mode == 0x80 || is_baseless) {
280 // Mode 2 or mode 0 with rbp/r13 as base: Word displacement.
Iain Merrick75681382010-08-19 15:07:18 +0100281 disp_value = *BitCast<const int32_t*>(&operand.buf_[disp_offset]);
Leon Clarkef7060e22010-06-03 12:02:55 +0100282 } else if (mode == 0x40) {
283 // Mode 1: Byte displacement.
284 disp_value = static_cast<signed char>(operand.buf_[disp_offset]);
285 }
286
287 // Write new operand with same registers, but with modified displacement.
288 ASSERT(offset >= 0 ? disp_value + offset > disp_value
289 : disp_value + offset < disp_value); // No overflow.
290 disp_value += offset;
291 rex_ = operand.rex_;
292 if (!is_int8(disp_value) || is_baseless) {
293 // Need 32 bits of displacement, mode 2 or mode 1 with register rbp/r13.
294 buf_[0] = (modrm & 0x3f) | (is_baseless ? 0x00 : 0x80);
295 len_ = disp_offset + 4;
296 Memory::int32_at(&buf_[disp_offset]) = disp_value;
297 } else if (disp_value != 0 || (base_reg == 0x05)) {
298 // Need 8 bits of displacement.
299 buf_[0] = (modrm & 0x3f) | 0x40; // Mode 1.
300 len_ = disp_offset + 1;
301 buf_[disp_offset] = static_cast<byte>(disp_value);
302 } else {
303 // Need no displacement.
304 buf_[0] = (modrm & 0x3f); // Mode 0.
305 len_ = disp_offset;
306 }
307 if (has_sib) {
308 buf_[1] = operand.buf_[1];
309 }
310}
311
Steve Block1e0659c2011-05-24 12:43:12 +0100312
313bool Operand::AddressUsesRegister(Register reg) const {
314 int code = reg.code();
315 ASSERT((buf_[0] & 0xC0) != 0xC0); // Always a memory operand.
316 // Start with only low three bits of base register. Initial decoding doesn't
317 // distinguish on the REX.B bit.
318 int base_code = buf_[0] & 0x07;
319 if (base_code == rsp.code()) {
320 // SIB byte present in buf_[1].
321 // Check the index register from the SIB byte + REX.X prefix.
322 int index_code = ((buf_[1] >> 3) & 0x07) | ((rex_ & 0x02) << 2);
323 // Index code (including REX.X) of 0x04 (rsp) means no index register.
324 if (index_code != rsp.code() && index_code == code) return true;
325 // Add REX.B to get the full base register code.
326 base_code = (buf_[1] & 0x07) | ((rex_ & 0x01) << 3);
327 // A base register of 0x05 (rbp) with mod = 0 means no base register.
328 if (base_code == rbp.code() && ((buf_[0] & 0xC0) == 0)) return false;
329 return code == base_code;
330 } else {
331 // A base register with low bits of 0x05 (rbp or r13) and mod = 0 means
332 // no base register.
333 if (base_code == rbp.code() && ((buf_[0] & 0xC0) == 0)) return false;
334 base_code |= ((rex_ & 0x01) << 3);
335 return code == base_code;
336 }
337}
338
339
Steve Blocka7e24c12009-10-30 11:49:00 +0000340// -----------------------------------------------------------------------------
Andrei Popescu31002712010-02-23 13:46:05 +0000341// Implementation of Assembler.
Steve Blocka7e24c12009-10-30 11:49:00 +0000342
343#ifdef GENERATED_CODE_COVERAGE
344static void InitCoverageLog();
345#endif
346
Ben Murdoch8b112d22011-06-08 16:22:53 +0100347Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size)
348 : AssemblerBase(arg_isolate),
Steve Block44f0eee2011-05-26 01:26:41 +0100349 code_targets_(100),
350 positions_recorder_(this),
351 emit_debug_code_(FLAG_debug_code) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000352 if (buffer == NULL) {
Andrei Popescu31002712010-02-23 13:46:05 +0000353 // Do our own buffer management.
Steve Blocka7e24c12009-10-30 11:49:00 +0000354 if (buffer_size <= kMinimalBufferSize) {
355 buffer_size = kMinimalBufferSize;
356
Ben Murdoch8b112d22011-06-08 16:22:53 +0100357 if (isolate() != NULL && isolate()->assembler_spare_buffer() != NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +0100358 buffer = isolate()->assembler_spare_buffer();
359 isolate()->set_assembler_spare_buffer(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000360 }
361 }
362 if (buffer == NULL) {
363 buffer_ = NewArray<byte>(buffer_size);
364 } else {
365 buffer_ = static_cast<byte*>(buffer);
366 }
367 buffer_size_ = buffer_size;
368 own_buffer_ = true;
369 } else {
Andrei Popescu31002712010-02-23 13:46:05 +0000370 // Use externally provided buffer instead.
Steve Blocka7e24c12009-10-30 11:49:00 +0000371 ASSERT(buffer_size > 0);
372 buffer_ = static_cast<byte*>(buffer);
373 buffer_size_ = buffer_size;
374 own_buffer_ = false;
375 }
376
377 // Clear the buffer in debug mode unless it was provided by the
378 // caller in which case we can't be sure it's okay to overwrite
379 // existing code in it.
380#ifdef DEBUG
381 if (own_buffer_) {
382 memset(buffer_, 0xCC, buffer_size); // int3
383 }
384#endif
385
Andrei Popescu31002712010-02-23 13:46:05 +0000386 // Setup buffer pointers.
Steve Blocka7e24c12009-10-30 11:49:00 +0000387 ASSERT(buffer_ != NULL);
388 pc_ = buffer_;
389 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
390
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800391
Steve Blocka7e24c12009-10-30 11:49:00 +0000392#ifdef GENERATED_CODE_COVERAGE
393 InitCoverageLog();
394#endif
395}
396
397
398Assembler::~Assembler() {
399 if (own_buffer_) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100400 if (isolate() != NULL &&
401 isolate()->assembler_spare_buffer() == NULL &&
Steve Block44f0eee2011-05-26 01:26:41 +0100402 buffer_size_ == kMinimalBufferSize) {
403 isolate()->set_assembler_spare_buffer(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000404 } else {
405 DeleteArray(buffer_);
406 }
407 }
408}
409
410
411void Assembler::GetCode(CodeDesc* desc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000412 // Finalize code (at this point overflow() may be true, but the gap ensures
413 // that we are still not overlapping instructions and relocation info).
414 ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap.
415 // Setup code descriptor.
Steve Blocka7e24c12009-10-30 11:49:00 +0000416 desc->buffer = buffer_;
417 desc->buffer_size = buffer_size_;
418 desc->instr_size = pc_offset();
419 ASSERT(desc->instr_size > 0); // Zero-size code objects upset the system.
Steve Blockd0582a62009-12-15 09:54:21 +0000420 desc->reloc_size =
421 static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos());
Steve Blocka7e24c12009-10-30 11:49:00 +0000422 desc->origin = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000423}
424
425
426void Assembler::Align(int m) {
427 ASSERT(IsPowerOf2(m));
Steve Block8defd9f2010-07-08 12:39:36 +0100428 int delta = (m - (pc_offset() & (m - 1))) & (m - 1);
429 while (delta >= 9) {
430 nop(9);
431 delta -= 9;
432 }
433 if (delta > 0) {
434 nop(delta);
Steve Blocka7e24c12009-10-30 11:49:00 +0000435 }
436}
437
438
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100439void Assembler::CodeTargetAlign() {
440 Align(16); // Preferred alignment of jump targets on x64.
441}
442
443
Steve Blocka7e24c12009-10-30 11:49:00 +0000444void Assembler::bind_to(Label* L, int pos) {
445 ASSERT(!L->is_bound()); // Label may only be bound once.
Steve Blocka7e24c12009-10-30 11:49:00 +0000446 ASSERT(0 <= pos && pos <= pc_offset()); // Position must be valid.
447 if (L->is_linked()) {
448 int current = L->pos();
449 int next = long_at(current);
450 while (next != current) {
Andrei Popescu31002712010-02-23 13:46:05 +0000451 // Relative address, relative to point after address.
Steve Blocka7e24c12009-10-30 11:49:00 +0000452 int imm32 = pos - (current + sizeof(int32_t));
453 long_at_put(current, imm32);
454 current = next;
455 next = long_at(next);
456 }
457 // Fix up last fixup on linked list.
458 int last_imm32 = pos - (current + sizeof(int32_t));
459 long_at_put(current, last_imm32);
460 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000461 while (L->is_near_linked()) {
462 int fixup_pos = L->near_link_pos();
463 int offset_to_next =
464 static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
465 ASSERT(offset_to_next <= 0);
466 int disp = pos - (fixup_pos + sizeof(int8_t));
467 ASSERT(is_int8(disp));
468 set_byte_at(fixup_pos, disp);
469 if (offset_to_next < 0) {
470 L->link_to(fixup_pos + offset_to_next, Label::kNear);
471 } else {
472 L->UnuseNear();
473 }
474 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000475 L->bind_to(pos);
476}
477
478
479void Assembler::bind(Label* L) {
480 bind_to(L, pc_offset());
481}
482
483
484void Assembler::GrowBuffer() {
Andrei Popescu31002712010-02-23 13:46:05 +0000485 ASSERT(buffer_overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +0000486 if (!own_buffer_) FATAL("external code buffer is too small");
487
Andrei Popescu31002712010-02-23 13:46:05 +0000488 // Compute new buffer size.
Steve Blocka7e24c12009-10-30 11:49:00 +0000489 CodeDesc desc; // the new buffer
490 if (buffer_size_ < 4*KB) {
491 desc.buffer_size = 4*KB;
492 } else {
493 desc.buffer_size = 2*buffer_size_;
494 }
495 // Some internal data structures overflow for very large buffers,
496 // they must ensure that kMaximalBufferSize is not too large.
497 if ((desc.buffer_size > kMaximalBufferSize) ||
Steve Block44f0eee2011-05-26 01:26:41 +0100498 (desc.buffer_size > HEAP->MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000499 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
500 }
501
Andrei Popescu31002712010-02-23 13:46:05 +0000502 // Setup new buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +0000503 desc.buffer = NewArray<byte>(desc.buffer_size);
504 desc.instr_size = pc_offset();
Steve Blockd0582a62009-12-15 09:54:21 +0000505 desc.reloc_size =
506 static_cast<int>((buffer_ + buffer_size_) - (reloc_info_writer.pos()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000507
508 // Clear the buffer in debug mode. Use 'int3' instructions to make
509 // sure to get into problems if we ever run uninitialized code.
510#ifdef DEBUG
511 memset(desc.buffer, 0xCC, desc.buffer_size);
512#endif
513
Andrei Popescu31002712010-02-23 13:46:05 +0000514 // Copy the data.
Steve Blocka7e24c12009-10-30 11:49:00 +0000515 intptr_t pc_delta = desc.buffer - buffer_;
516 intptr_t rc_delta = (desc.buffer + desc.buffer_size) -
517 (buffer_ + buffer_size_);
518 memmove(desc.buffer, buffer_, desc.instr_size);
519 memmove(rc_delta + reloc_info_writer.pos(),
520 reloc_info_writer.pos(), desc.reloc_size);
521
Andrei Popescu31002712010-02-23 13:46:05 +0000522 // Switch buffers.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100523 if (isolate() != NULL &&
524 isolate()->assembler_spare_buffer() == NULL &&
Steve Block44f0eee2011-05-26 01:26:41 +0100525 buffer_size_ == kMinimalBufferSize) {
526 isolate()->set_assembler_spare_buffer(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000527 } else {
528 DeleteArray(buffer_);
529 }
530 buffer_ = desc.buffer;
531 buffer_size_ = desc.buffer_size;
532 pc_ += pc_delta;
Steve Blocka7e24c12009-10-30 11:49:00 +0000533 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
534 reloc_info_writer.last_pc() + pc_delta);
535
Andrei Popescu31002712010-02-23 13:46:05 +0000536 // Relocate runtime entries.
Steve Blocka7e24c12009-10-30 11:49:00 +0000537 for (RelocIterator it(desc); !it.done(); it.next()) {
538 RelocInfo::Mode rmode = it.rinfo()->rmode();
539 if (rmode == RelocInfo::INTERNAL_REFERENCE) {
540 intptr_t* p = reinterpret_cast<intptr_t*>(it.rinfo()->pc());
541 if (*p != 0) { // 0 means uninitialized.
542 *p += pc_delta;
543 }
544 }
545 }
546
547 ASSERT(!buffer_overflow());
548}
549
550
551void Assembler::emit_operand(int code, const Operand& adr) {
552 ASSERT(is_uint3(code));
553 const unsigned length = adr.len_;
554 ASSERT(length > 0);
555
556 // Emit updated ModR/M byte containing the given register.
557 ASSERT((adr.buf_[0] & 0x38) == 0);
558 pc_[0] = adr.buf_[0] | code << 3;
559
560 // Emit the rest of the encoded operand.
561 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
562 pc_ += length;
563}
564
565
Andrei Popescu31002712010-02-23 13:46:05 +0000566// Assembler Instruction implementations.
Steve Blocka7e24c12009-10-30 11:49:00 +0000567
568void Assembler::arithmetic_op(byte opcode, Register reg, const Operand& op) {
569 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000570 emit_rex_64(reg, op);
571 emit(opcode);
572 emit_operand(reg, op);
573}
574
575
576void Assembler::arithmetic_op(byte opcode, Register reg, Register rm_reg) {
577 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +0100578 ASSERT((opcode & 0xC6) == 2);
579 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
580 // Swap reg and rm_reg and change opcode operand order.
581 emit_rex_64(rm_reg, reg);
582 emit(opcode ^ 0x02);
583 emit_modrm(rm_reg, reg);
584 } else {
585 emit_rex_64(reg, rm_reg);
586 emit(opcode);
587 emit_modrm(reg, rm_reg);
588 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000589}
590
591
592void Assembler::arithmetic_op_16(byte opcode, Register reg, Register rm_reg) {
593 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +0100594 ASSERT((opcode & 0xC6) == 2);
595 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
596 // Swap reg and rm_reg and change opcode operand order.
597 emit(0x66);
598 emit_optional_rex_32(rm_reg, reg);
599 emit(opcode ^ 0x02);
600 emit_modrm(rm_reg, reg);
601 } else {
602 emit(0x66);
603 emit_optional_rex_32(reg, rm_reg);
604 emit(opcode);
605 emit_modrm(reg, rm_reg);
606 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000607}
608
609
610void Assembler::arithmetic_op_16(byte opcode,
611 Register reg,
612 const Operand& rm_reg) {
613 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000614 emit(0x66);
615 emit_optional_rex_32(reg, rm_reg);
616 emit(opcode);
617 emit_operand(reg, rm_reg);
618}
619
620
621void Assembler::arithmetic_op_32(byte opcode, Register reg, Register rm_reg) {
622 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +0100623 ASSERT((opcode & 0xC6) == 2);
624 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
625 // Swap reg and rm_reg and change opcode operand order.
626 emit_optional_rex_32(rm_reg, reg);
627 emit(opcode ^ 0x02); // E.g. 0x03 -> 0x01 for ADD.
628 emit_modrm(rm_reg, reg);
629 } else {
630 emit_optional_rex_32(reg, rm_reg);
631 emit(opcode);
632 emit_modrm(reg, rm_reg);
633 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000634}
635
636
637void Assembler::arithmetic_op_32(byte opcode,
638 Register reg,
639 const Operand& rm_reg) {
640 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000641 emit_optional_rex_32(reg, rm_reg);
642 emit(opcode);
643 emit_operand(reg, rm_reg);
644}
645
646
647void Assembler::immediate_arithmetic_op(byte subcode,
648 Register dst,
649 Immediate src) {
650 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000651 emit_rex_64(dst);
652 if (is_int8(src.value_)) {
653 emit(0x83);
654 emit_modrm(subcode, dst);
655 emit(src.value_);
656 } else if (dst.is(rax)) {
657 emit(0x05 | (subcode << 3));
658 emitl(src.value_);
659 } else {
660 emit(0x81);
661 emit_modrm(subcode, dst);
662 emitl(src.value_);
663 }
664}
665
666void Assembler::immediate_arithmetic_op(byte subcode,
667 const Operand& dst,
668 Immediate src) {
669 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000670 emit_rex_64(dst);
671 if (is_int8(src.value_)) {
672 emit(0x83);
673 emit_operand(subcode, dst);
674 emit(src.value_);
675 } else {
676 emit(0x81);
677 emit_operand(subcode, dst);
678 emitl(src.value_);
679 }
680}
681
682
683void Assembler::immediate_arithmetic_op_16(byte subcode,
684 Register dst,
685 Immediate src) {
686 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000687 emit(0x66); // Operand size override prefix.
688 emit_optional_rex_32(dst);
689 if (is_int8(src.value_)) {
690 emit(0x83);
691 emit_modrm(subcode, dst);
692 emit(src.value_);
693 } else if (dst.is(rax)) {
694 emit(0x05 | (subcode << 3));
Steve Block3ce2e202009-11-05 08:53:23 +0000695 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000696 } else {
697 emit(0x81);
698 emit_modrm(subcode, dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000699 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000700 }
701}
702
703
704void Assembler::immediate_arithmetic_op_16(byte subcode,
705 const Operand& dst,
706 Immediate src) {
707 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000708 emit(0x66); // Operand size override prefix.
709 emit_optional_rex_32(dst);
710 if (is_int8(src.value_)) {
711 emit(0x83);
712 emit_operand(subcode, dst);
713 emit(src.value_);
714 } else {
715 emit(0x81);
716 emit_operand(subcode, dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000717 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000718 }
719}
720
721
722void Assembler::immediate_arithmetic_op_32(byte subcode,
723 Register dst,
724 Immediate src) {
725 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000726 emit_optional_rex_32(dst);
727 if (is_int8(src.value_)) {
728 emit(0x83);
729 emit_modrm(subcode, dst);
730 emit(src.value_);
731 } else if (dst.is(rax)) {
732 emit(0x05 | (subcode << 3));
733 emitl(src.value_);
734 } else {
735 emit(0x81);
736 emit_modrm(subcode, dst);
737 emitl(src.value_);
738 }
739}
740
741
742void Assembler::immediate_arithmetic_op_32(byte subcode,
743 const Operand& dst,
744 Immediate src) {
745 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000746 emit_optional_rex_32(dst);
747 if (is_int8(src.value_)) {
748 emit(0x83);
749 emit_operand(subcode, dst);
750 emit(src.value_);
751 } else {
752 emit(0x81);
753 emit_operand(subcode, dst);
754 emitl(src.value_);
755 }
756}
757
758
759void Assembler::immediate_arithmetic_op_8(byte subcode,
760 const Operand& dst,
761 Immediate src) {
762 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000763 emit_optional_rex_32(dst);
764 ASSERT(is_int8(src.value_) || is_uint8(src.value_));
765 emit(0x80);
766 emit_operand(subcode, dst);
767 emit(src.value_);
768}
769
770
771void Assembler::immediate_arithmetic_op_8(byte subcode,
772 Register dst,
773 Immediate src) {
774 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000775 if (dst.code() > 3) {
776 // Use 64-bit mode byte registers.
777 emit_rex_64(dst);
778 }
779 ASSERT(is_int8(src.value_) || is_uint8(src.value_));
780 emit(0x80);
781 emit_modrm(subcode, dst);
782 emit(src.value_);
783}
784
785
786void Assembler::shift(Register dst, Immediate shift_amount, int subcode) {
787 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000788 ASSERT(is_uint6(shift_amount.value_)); // illegal shift count
789 if (shift_amount.value_ == 1) {
790 emit_rex_64(dst);
791 emit(0xD1);
792 emit_modrm(subcode, dst);
793 } else {
794 emit_rex_64(dst);
795 emit(0xC1);
796 emit_modrm(subcode, dst);
797 emit(shift_amount.value_);
798 }
799}
800
801
802void Assembler::shift(Register dst, int subcode) {
803 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000804 emit_rex_64(dst);
805 emit(0xD3);
806 emit_modrm(subcode, dst);
807}
808
809
810void Assembler::shift_32(Register dst, int subcode) {
811 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000812 emit_optional_rex_32(dst);
813 emit(0xD3);
814 emit_modrm(subcode, dst);
815}
816
817
818void Assembler::shift_32(Register dst, Immediate shift_amount, int subcode) {
819 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +0000820 ASSERT(is_uint5(shift_amount.value_)); // illegal shift count
Steve Blocka7e24c12009-10-30 11:49:00 +0000821 if (shift_amount.value_ == 1) {
822 emit_optional_rex_32(dst);
823 emit(0xD1);
824 emit_modrm(subcode, dst);
825 } else {
826 emit_optional_rex_32(dst);
827 emit(0xC1);
828 emit_modrm(subcode, dst);
829 emit(shift_amount.value_);
830 }
831}
832
833
834void Assembler::bt(const Operand& dst, Register src) {
835 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000836 emit_rex_64(src, dst);
837 emit(0x0F);
838 emit(0xA3);
839 emit_operand(src, dst);
840}
841
842
843void Assembler::bts(const Operand& dst, Register src) {
844 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000845 emit_rex_64(src, dst);
846 emit(0x0F);
847 emit(0xAB);
848 emit_operand(src, dst);
849}
850
851
852void Assembler::call(Label* L) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100853 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000854 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000855 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +0000856 emit(0xE8);
857 if (L->is_bound()) {
858 int offset = L->pos() - pc_offset() - sizeof(int32_t);
859 ASSERT(offset <= 0);
860 emitl(offset);
861 } else if (L->is_linked()) {
862 emitl(L->pos());
863 L->link_to(pc_offset() - sizeof(int32_t));
864 } else {
865 ASSERT(L->is_unused());
866 int32_t current = pc_offset();
867 emitl(current);
868 L->link_to(current);
869 }
870}
871
872
Ben Murdoch257744e2011-11-30 15:57:28 +0000873void Assembler::call(Handle<Code> target,
874 RelocInfo::Mode rmode,
875 unsigned ast_id) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800876 positions_recorder()->WriteRecordedPositions();
Steve Block3ce2e202009-11-05 08:53:23 +0000877 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000878 // 1110 1000 #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +0000879 emit(0xE8);
Ben Murdoch257744e2011-11-30 15:57:28 +0000880 emit_code_target(target, rmode, ast_id);
Steve Block3ce2e202009-11-05 08:53:23 +0000881}
882
883
Steve Blocka7e24c12009-10-30 11:49:00 +0000884void Assembler::call(Register adr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100885 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000886 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000887 // Opcode: FF /2 r64.
Steve Block8defd9f2010-07-08 12:39:36 +0100888 emit_optional_rex_32(adr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000889 emit(0xFF);
890 emit_modrm(0x2, adr);
891}
892
893
894void Assembler::call(const Operand& op) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100895 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000896 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000897 // Opcode: FF /2 m64.
Steve Block8defd9f2010-07-08 12:39:36 +0100898 emit_optional_rex_32(op);
Steve Blocka7e24c12009-10-30 11:49:00 +0000899 emit(0xFF);
Steve Block8defd9f2010-07-08 12:39:36 +0100900 emit_operand(0x2, op);
Steve Blocka7e24c12009-10-30 11:49:00 +0000901}
902
903
Steve Block1e0659c2011-05-24 12:43:12 +0100904// Calls directly to the given address using a relative offset.
905// Should only ever be used in Code objects for calls within the
906// same Code object. Should not be used when generating new code (use labels),
907// but only when patching existing code.
908void Assembler::call(Address target) {
909 positions_recorder()->WriteRecordedPositions();
910 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +0100911 // 1110 1000 #32-bit disp.
912 emit(0xE8);
913 Address source = pc_ + 4;
914 intptr_t displacement = target - source;
915 ASSERT(is_int32(displacement));
916 emitl(static_cast<int32_t>(displacement));
917}
918
919
Steve Block3ce2e202009-11-05 08:53:23 +0000920void Assembler::clc() {
921 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +0000922 emit(0xF8);
923}
924
Steve Block44f0eee2011-05-26 01:26:41 +0100925void Assembler::cld() {
926 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +0100927 emit(0xFC);
928}
929
Steve Blocka7e24c12009-10-30 11:49:00 +0000930void Assembler::cdq() {
931 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000932 emit(0x99);
933}
934
935
936void Assembler::cmovq(Condition cc, Register dst, Register src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000937 if (cc == always) {
938 movq(dst, src);
939 } else if (cc == never) {
940 return;
941 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000942 // No need to check CpuInfo for CMOV support, it's a required part of the
943 // 64-bit architecture.
944 ASSERT(cc >= 0); // Use mov for unconditional moves.
945 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000946 // Opcode: REX.W 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000947 emit_rex_64(dst, src);
948 emit(0x0f);
949 emit(0x40 + cc);
950 emit_modrm(dst, src);
951}
952
953
954void Assembler::cmovq(Condition cc, Register dst, const Operand& src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000955 if (cc == always) {
956 movq(dst, src);
957 } else if (cc == never) {
958 return;
959 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000960 ASSERT(cc >= 0);
961 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000962 // Opcode: REX.W 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000963 emit_rex_64(dst, src);
964 emit(0x0f);
965 emit(0x40 + cc);
966 emit_operand(dst, src);
967}
968
969
970void Assembler::cmovl(Condition cc, Register dst, Register src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000971 if (cc == always) {
972 movl(dst, src);
973 } else if (cc == never) {
974 return;
975 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000976 ASSERT(cc >= 0);
977 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000978 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000979 emit_optional_rex_32(dst, src);
980 emit(0x0f);
981 emit(0x40 + cc);
982 emit_modrm(dst, src);
983}
984
985
986void Assembler::cmovl(Condition cc, Register dst, const Operand& src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000987 if (cc == always) {
988 movl(dst, src);
989 } else if (cc == never) {
990 return;
991 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000992 ASSERT(cc >= 0);
993 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000994 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000995 emit_optional_rex_32(dst, src);
996 emit(0x0f);
997 emit(0x40 + cc);
998 emit_operand(dst, src);
999}
1000
1001
1002void Assembler::cmpb_al(Immediate imm8) {
1003 ASSERT(is_int8(imm8.value_) || is_uint8(imm8.value_));
1004 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001005 emit(0x3c);
1006 emit(imm8.value_);
1007}
1008
1009
1010void Assembler::cpuid() {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001011 ASSERT(CpuFeatures::IsEnabled(CPUID));
Steve Blocka7e24c12009-10-30 11:49:00 +00001012 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001013 emit(0x0F);
1014 emit(0xA2);
1015}
1016
1017
1018void Assembler::cqo() {
1019 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001020 emit_rex_64();
1021 emit(0x99);
1022}
1023
1024
1025void Assembler::decq(Register dst) {
1026 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001027 emit_rex_64(dst);
1028 emit(0xFF);
1029 emit_modrm(0x1, dst);
1030}
1031
1032
1033void Assembler::decq(const Operand& dst) {
1034 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001035 emit_rex_64(dst);
1036 emit(0xFF);
1037 emit_operand(1, dst);
1038}
1039
1040
1041void Assembler::decl(Register dst) {
1042 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001043 emit_optional_rex_32(dst);
1044 emit(0xFF);
1045 emit_modrm(0x1, dst);
1046}
1047
1048
1049void Assembler::decl(const Operand& dst) {
1050 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001051 emit_optional_rex_32(dst);
1052 emit(0xFF);
1053 emit_operand(1, dst);
1054}
1055
1056
Steve Block3ce2e202009-11-05 08:53:23 +00001057void Assembler::decb(Register dst) {
1058 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001059 if (dst.code() > 3) {
1060 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1061 emit_rex_32(dst);
1062 }
1063 emit(0xFE);
1064 emit_modrm(0x1, dst);
1065}
1066
1067
1068void Assembler::decb(const Operand& dst) {
1069 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001070 emit_optional_rex_32(dst);
1071 emit(0xFE);
1072 emit_operand(1, dst);
1073}
1074
1075
Steve Blocka7e24c12009-10-30 11:49:00 +00001076void Assembler::enter(Immediate size) {
1077 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001078 emit(0xC8);
1079 emitw(size.value_); // 16 bit operand, always.
1080 emit(0);
1081}
1082
1083
1084void Assembler::hlt() {
1085 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001086 emit(0xF4);
1087}
1088
1089
1090void Assembler::idivq(Register src) {
1091 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001092 emit_rex_64(src);
1093 emit(0xF7);
1094 emit_modrm(0x7, src);
1095}
1096
1097
1098void Assembler::idivl(Register src) {
1099 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001100 emit_optional_rex_32(src);
1101 emit(0xF7);
1102 emit_modrm(0x7, src);
1103}
1104
1105
1106void Assembler::imul(Register src) {
1107 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001108 emit_rex_64(src);
1109 emit(0xF7);
1110 emit_modrm(0x5, src);
1111}
1112
1113
1114void Assembler::imul(Register dst, Register src) {
1115 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001116 emit_rex_64(dst, src);
1117 emit(0x0F);
1118 emit(0xAF);
1119 emit_modrm(dst, src);
1120}
1121
1122
1123void Assembler::imul(Register dst, const Operand& src) {
1124 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001125 emit_rex_64(dst, src);
1126 emit(0x0F);
1127 emit(0xAF);
1128 emit_operand(dst, src);
1129}
1130
1131
1132void Assembler::imul(Register dst, Register src, Immediate imm) {
1133 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001134 emit_rex_64(dst, src);
1135 if (is_int8(imm.value_)) {
1136 emit(0x6B);
1137 emit_modrm(dst, src);
1138 emit(imm.value_);
1139 } else {
1140 emit(0x69);
1141 emit_modrm(dst, src);
1142 emitl(imm.value_);
1143 }
1144}
1145
1146
1147void Assembler::imull(Register dst, Register src) {
1148 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001149 emit_optional_rex_32(dst, src);
1150 emit(0x0F);
1151 emit(0xAF);
1152 emit_modrm(dst, src);
1153}
1154
1155
Steve Block1e0659c2011-05-24 12:43:12 +01001156void Assembler::imull(Register dst, const Operand& src) {
1157 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01001158 emit_optional_rex_32(dst, src);
1159 emit(0x0F);
1160 emit(0xAF);
1161 emit_operand(dst, src);
1162}
1163
1164
Steve Block6ded16b2010-05-10 14:33:55 +01001165void Assembler::imull(Register dst, Register src, Immediate imm) {
1166 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01001167 emit_optional_rex_32(dst, src);
1168 if (is_int8(imm.value_)) {
1169 emit(0x6B);
1170 emit_modrm(dst, src);
1171 emit(imm.value_);
1172 } else {
1173 emit(0x69);
1174 emit_modrm(dst, src);
1175 emitl(imm.value_);
1176 }
1177}
1178
1179
Steve Blocka7e24c12009-10-30 11:49:00 +00001180void Assembler::incq(Register dst) {
1181 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001182 emit_rex_64(dst);
1183 emit(0xFF);
1184 emit_modrm(0x0, dst);
1185}
1186
1187
1188void Assembler::incq(const Operand& dst) {
1189 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001190 emit_rex_64(dst);
1191 emit(0xFF);
1192 emit_operand(0, dst);
1193}
1194
1195
1196void Assembler::incl(const Operand& dst) {
1197 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001198 emit_optional_rex_32(dst);
1199 emit(0xFF);
1200 emit_operand(0, dst);
1201}
1202
1203
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001204void Assembler::incl(Register dst) {
1205 EnsureSpace ensure_space(this);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001206 emit_optional_rex_32(dst);
1207 emit(0xFF);
1208 emit_modrm(0, dst);
1209}
1210
1211
Steve Blocka7e24c12009-10-30 11:49:00 +00001212void Assembler::int3() {
1213 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001214 emit(0xCC);
1215}
1216
1217
Ben Murdoch257744e2011-11-30 15:57:28 +00001218void Assembler::j(Condition cc, Label* L, Label::Distance distance) {
Steve Block3ce2e202009-11-05 08:53:23 +00001219 if (cc == always) {
1220 jmp(L);
1221 return;
1222 } else if (cc == never) {
1223 return;
1224 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001225 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001226 ASSERT(is_uint4(cc));
1227 if (L->is_bound()) {
1228 const int short_size = 2;
1229 const int long_size = 6;
1230 int offs = L->pos() - pc_offset();
1231 ASSERT(offs <= 0);
1232 if (is_int8(offs - short_size)) {
Andrei Popescu31002712010-02-23 13:46:05 +00001233 // 0111 tttn #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001234 emit(0x70 | cc);
1235 emit((offs - short_size) & 0xFF);
1236 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001237 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001238 emit(0x0F);
1239 emit(0x80 | cc);
1240 emitl(offs - long_size);
1241 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001242 } else if (distance == Label::kNear) {
1243 // 0111 tttn #8-bit disp
1244 emit(0x70 | cc);
1245 byte disp = 0x00;
1246 if (L->is_near_linked()) {
1247 int offset = L->near_link_pos() - pc_offset();
1248 ASSERT(is_int8(offset));
1249 disp = static_cast<byte>(offset & 0xFF);
1250 }
1251 L->link_to(pc_offset(), Label::kNear);
1252 emit(disp);
Steve Blocka7e24c12009-10-30 11:49:00 +00001253 } else if (L->is_linked()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001254 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001255 emit(0x0F);
1256 emit(0x80 | cc);
1257 emitl(L->pos());
1258 L->link_to(pc_offset() - sizeof(int32_t));
1259 } else {
1260 ASSERT(L->is_unused());
1261 emit(0x0F);
1262 emit(0x80 | cc);
1263 int32_t current = pc_offset();
1264 emitl(current);
1265 L->link_to(current);
1266 }
1267}
1268
1269
Steve Block3ce2e202009-11-05 08:53:23 +00001270void Assembler::j(Condition cc,
1271 Handle<Code> target,
1272 RelocInfo::Mode rmode) {
1273 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001274 ASSERT(is_uint4(cc));
Andrei Popescu31002712010-02-23 13:46:05 +00001275 // 0000 1111 1000 tttn #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +00001276 emit(0x0F);
1277 emit(0x80 | cc);
1278 emit_code_target(target, rmode);
1279}
1280
1281
Ben Murdoch257744e2011-11-30 15:57:28 +00001282void Assembler::jmp(Label* L, Label::Distance distance) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001283 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01001284 const int short_size = sizeof(int8_t);
1285 const int long_size = sizeof(int32_t);
Steve Blocka7e24c12009-10-30 11:49:00 +00001286 if (L->is_bound()) {
1287 int offs = L->pos() - pc_offset() - 1;
1288 ASSERT(offs <= 0);
Steve Block6ded16b2010-05-10 14:33:55 +01001289 if (is_int8(offs - short_size)) {
Andrei Popescu31002712010-02-23 13:46:05 +00001290 // 1110 1011 #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001291 emit(0xEB);
Steve Block6ded16b2010-05-10 14:33:55 +01001292 emit((offs - short_size) & 0xFF);
Steve Blocka7e24c12009-10-30 11:49:00 +00001293 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001294 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001295 emit(0xE9);
Steve Block6ded16b2010-05-10 14:33:55 +01001296 emitl(offs - long_size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001297 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001298 } else if (distance == Label::kNear) {
1299 emit(0xEB);
1300 byte disp = 0x00;
1301 if (L->is_near_linked()) {
1302 int offset = L->near_link_pos() - pc_offset();
1303 ASSERT(is_int8(offset));
1304 disp = static_cast<byte>(offset & 0xFF);
1305 }
1306 L->link_to(pc_offset(), Label::kNear);
1307 emit(disp);
1308 } else if (L->is_linked()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001309 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001310 emit(0xE9);
1311 emitl(L->pos());
Steve Block6ded16b2010-05-10 14:33:55 +01001312 L->link_to(pc_offset() - long_size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001313 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001314 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001315 ASSERT(L->is_unused());
1316 emit(0xE9);
1317 int32_t current = pc_offset();
1318 emitl(current);
1319 L->link_to(current);
1320 }
1321}
1322
1323
Steve Block3ce2e202009-11-05 08:53:23 +00001324void Assembler::jmp(Handle<Code> target, RelocInfo::Mode rmode) {
1325 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +00001326 // 1110 1001 #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +00001327 emit(0xE9);
1328 emit_code_target(target, rmode);
1329}
1330
1331
Steve Blocka7e24c12009-10-30 11:49:00 +00001332void Assembler::jmp(Register target) {
1333 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +00001334 // Opcode FF/4 r64.
Steve Block8defd9f2010-07-08 12:39:36 +01001335 emit_optional_rex_32(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001336 emit(0xFF);
1337 emit_modrm(0x4, target);
1338}
1339
1340
1341void Assembler::jmp(const Operand& src) {
1342 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +00001343 // Opcode FF/4 m64.
Steve Blocka7e24c12009-10-30 11:49:00 +00001344 emit_optional_rex_32(src);
1345 emit(0xFF);
1346 emit_operand(0x4, src);
1347}
1348
1349
1350void Assembler::lea(Register dst, const Operand& src) {
1351 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001352 emit_rex_64(dst, src);
1353 emit(0x8D);
1354 emit_operand(dst, src);
1355}
1356
1357
Steve Block6ded16b2010-05-10 14:33:55 +01001358void Assembler::leal(Register dst, const Operand& src) {
1359 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01001360 emit_optional_rex_32(dst, src);
1361 emit(0x8D);
1362 emit_operand(dst, src);
1363}
1364
1365
Steve Blocka7e24c12009-10-30 11:49:00 +00001366void Assembler::load_rax(void* value, RelocInfo::Mode mode) {
1367 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001368 emit(0x48); // REX.W
1369 emit(0xA1);
1370 emitq(reinterpret_cast<uintptr_t>(value), mode);
1371}
1372
1373
1374void Assembler::load_rax(ExternalReference ref) {
1375 load_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
1376}
1377
1378
1379void Assembler::leave() {
1380 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001381 emit(0xC9);
1382}
1383
1384
1385void Assembler::movb(Register dst, const Operand& src) {
1386 EnsureSpace ensure_space(this);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001387 if (dst.code() > 3) {
1388 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1389 emit_rex_32(dst, src);
1390 } else {
1391 emit_optional_rex_32(dst, src);
1392 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001393 emit(0x8A);
1394 emit_operand(dst, src);
1395}
1396
Steve Block6ded16b2010-05-10 14:33:55 +01001397
Steve Blocka7e24c12009-10-30 11:49:00 +00001398void Assembler::movb(Register dst, Immediate imm) {
1399 EnsureSpace ensure_space(this);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001400 if (dst.code() > 3) {
1401 emit_rex_32(dst);
1402 }
1403 emit(0xB0 + dst.low_bits());
Steve Blocka7e24c12009-10-30 11:49:00 +00001404 emit(imm.value_);
1405}
1406
Steve Block6ded16b2010-05-10 14:33:55 +01001407
Steve Blocka7e24c12009-10-30 11:49:00 +00001408void Assembler::movb(const Operand& dst, Register src) {
1409 EnsureSpace ensure_space(this);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001410 if (src.code() > 3) {
1411 emit_rex_32(src, dst);
1412 } else {
1413 emit_optional_rex_32(src, dst);
1414 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001415 emit(0x88);
1416 emit_operand(src, dst);
1417}
1418
Steve Block6ded16b2010-05-10 14:33:55 +01001419
Steve Block3ce2e202009-11-05 08:53:23 +00001420void Assembler::movw(const Operand& dst, Register src) {
1421 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001422 emit(0x66);
1423 emit_optional_rex_32(src, dst);
1424 emit(0x89);
1425 emit_operand(src, dst);
1426}
1427
Steve Block6ded16b2010-05-10 14:33:55 +01001428
Steve Blocka7e24c12009-10-30 11:49:00 +00001429void Assembler::movl(Register dst, const Operand& src) {
1430 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001431 emit_optional_rex_32(dst, src);
1432 emit(0x8B);
1433 emit_operand(dst, src);
1434}
1435
1436
1437void Assembler::movl(Register dst, Register src) {
1438 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +01001439 if (src.low_bits() == 4) {
1440 emit_optional_rex_32(src, dst);
1441 emit(0x89);
1442 emit_modrm(src, dst);
1443 } else {
1444 emit_optional_rex_32(dst, src);
1445 emit(0x8B);
1446 emit_modrm(dst, src);
1447 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001448}
1449
1450
1451void Assembler::movl(const Operand& dst, Register src) {
1452 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001453 emit_optional_rex_32(src, dst);
1454 emit(0x89);
1455 emit_operand(src, dst);
1456}
1457
1458
1459void Assembler::movl(const Operand& dst, Immediate value) {
1460 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001461 emit_optional_rex_32(dst);
1462 emit(0xC7);
1463 emit_operand(0x0, dst);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001464 emit(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001465}
1466
1467
1468void Assembler::movl(Register dst, Immediate value) {
1469 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001470 emit_optional_rex_32(dst);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001471 emit(0xB8 + dst.low_bits());
1472 emit(value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001473}
1474
1475
1476void Assembler::movq(Register dst, const Operand& src) {
1477 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001478 emit_rex_64(dst, src);
1479 emit(0x8B);
1480 emit_operand(dst, src);
1481}
1482
1483
1484void Assembler::movq(Register dst, Register src) {
1485 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +01001486 if (src.low_bits() == 4) {
1487 emit_rex_64(src, dst);
1488 emit(0x89);
1489 emit_modrm(src, dst);
1490 } else {
1491 emit_rex_64(dst, src);
1492 emit(0x8B);
1493 emit_modrm(dst, src);
1494 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001495}
1496
1497
1498void Assembler::movq(Register dst, Immediate value) {
1499 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001500 emit_rex_64(dst);
1501 emit(0xC7);
1502 emit_modrm(0x0, dst);
1503 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates.
1504}
1505
1506
1507void Assembler::movq(const Operand& dst, Register src) {
1508 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001509 emit_rex_64(src, dst);
1510 emit(0x89);
1511 emit_operand(src, dst);
1512}
1513
1514
1515void Assembler::movq(Register dst, void* value, RelocInfo::Mode rmode) {
1516 // This method must not be used with heap object references. The stored
1517 // address is not GC safe. Use the handle version instead.
1518 ASSERT(rmode > RelocInfo::LAST_GCED_ENUM);
1519 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001520 emit_rex_64(dst);
1521 emit(0xB8 | dst.low_bits());
1522 emitq(reinterpret_cast<uintptr_t>(value), rmode);
1523}
1524
1525
1526void Assembler::movq(Register dst, int64_t value, RelocInfo::Mode rmode) {
1527 // Non-relocatable values might not need a 64-bit representation.
1528 if (rmode == RelocInfo::NONE) {
1529 // Sadly, there is no zero or sign extending move for 8-bit immediates.
1530 if (is_int32(value)) {
1531 movq(dst, Immediate(static_cast<int32_t>(value)));
1532 return;
1533 } else if (is_uint32(value)) {
1534 movl(dst, Immediate(static_cast<int32_t>(value)));
1535 return;
1536 }
1537 // Value cannot be represented by 32 bits, so do a full 64 bit immediate
1538 // value.
1539 }
1540 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001541 emit_rex_64(dst);
1542 emit(0xB8 | dst.low_bits());
1543 emitq(value, rmode);
1544}
1545
1546
1547void Assembler::movq(Register dst, ExternalReference ref) {
Ben Murdochbb769b22010-08-11 14:56:33 +01001548 int64_t value = reinterpret_cast<int64_t>(ref.address());
1549 movq(dst, value, RelocInfo::EXTERNAL_REFERENCE);
Steve Blocka7e24c12009-10-30 11:49:00 +00001550}
1551
1552
1553void Assembler::movq(const Operand& dst, Immediate value) {
1554 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001555 emit_rex_64(dst);
1556 emit(0xC7);
1557 emit_operand(0, dst);
1558 emit(value);
1559}
1560
1561
Andrei Popescu31002712010-02-23 13:46:05 +00001562// Loads the ip-relative location of the src label into the target location
1563// (as a 32-bit offset sign extended to 64-bit).
Steve Blocka7e24c12009-10-30 11:49:00 +00001564void Assembler::movl(const Operand& dst, Label* src) {
1565 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001566 emit_optional_rex_32(dst);
1567 emit(0xC7);
1568 emit_operand(0, dst);
1569 if (src->is_bound()) {
1570 int offset = src->pos() - pc_offset() - sizeof(int32_t);
1571 ASSERT(offset <= 0);
1572 emitl(offset);
1573 } else if (src->is_linked()) {
1574 emitl(src->pos());
1575 src->link_to(pc_offset() - sizeof(int32_t));
1576 } else {
1577 ASSERT(src->is_unused());
1578 int32_t current = pc_offset();
1579 emitl(current);
1580 src->link_to(current);
1581 }
1582}
1583
1584
1585void Assembler::movq(Register dst, Handle<Object> value, RelocInfo::Mode mode) {
1586 // If there is no relocation info, emit the value of the handle efficiently
1587 // (possibly using less that 8 bytes for the value).
1588 if (mode == RelocInfo::NONE) {
1589 // There is no possible reason to store a heap pointer without relocation
1590 // info, so it must be a smi.
1591 ASSERT(value->IsSmi());
Steve Block3ce2e202009-11-05 08:53:23 +00001592 movq(dst, reinterpret_cast<int64_t>(*value), RelocInfo::NONE);
Steve Blocka7e24c12009-10-30 11:49:00 +00001593 } else {
1594 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001595 ASSERT(value->IsHeapObject());
Steve Block44f0eee2011-05-26 01:26:41 +01001596 ASSERT(!HEAP->InNewSpace(*value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001597 emit_rex_64(dst);
1598 emit(0xB8 | dst.low_bits());
1599 emitq(reinterpret_cast<uintptr_t>(value.location()), mode);
1600 }
1601}
1602
1603
Steve Block3ce2e202009-11-05 08:53:23 +00001604void Assembler::movsxbq(Register dst, const Operand& src) {
1605 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001606 emit_rex_64(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00001607 emit(0x0F);
1608 emit(0xBE);
1609 emit_operand(dst, src);
1610}
1611
1612
1613void Assembler::movsxwq(Register dst, const Operand& src) {
1614 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001615 emit_rex_64(dst, src);
1616 emit(0x0F);
1617 emit(0xBF);
1618 emit_operand(dst, src);
1619}
1620
1621
Steve Blocka7e24c12009-10-30 11:49:00 +00001622void Assembler::movsxlq(Register dst, Register src) {
1623 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001624 emit_rex_64(dst, src);
1625 emit(0x63);
1626 emit_modrm(dst, src);
1627}
1628
1629
1630void Assembler::movsxlq(Register dst, const Operand& src) {
1631 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001632 emit_rex_64(dst, src);
1633 emit(0x63);
1634 emit_operand(dst, src);
1635}
1636
1637
1638void Assembler::movzxbq(Register dst, const Operand& src) {
1639 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001640 emit_optional_rex_32(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001641 emit(0x0F);
1642 emit(0xB6);
1643 emit_operand(dst, src);
1644}
1645
1646
1647void Assembler::movzxbl(Register dst, const Operand& src) {
1648 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001649 emit_optional_rex_32(dst, src);
1650 emit(0x0F);
1651 emit(0xB6);
1652 emit_operand(dst, src);
1653}
1654
1655
Steve Block3ce2e202009-11-05 08:53:23 +00001656void Assembler::movzxwq(Register dst, const Operand& src) {
1657 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001658 emit_optional_rex_32(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00001659 emit(0x0F);
1660 emit(0xB7);
1661 emit_operand(dst, src);
1662}
1663
1664
Steve Blocka7e24c12009-10-30 11:49:00 +00001665void Assembler::movzxwl(Register dst, const Operand& src) {
1666 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001667 emit_optional_rex_32(dst, src);
1668 emit(0x0F);
1669 emit(0xB7);
1670 emit_operand(dst, src);
1671}
1672
1673
Leon Clarked91b9f72010-01-27 17:25:45 +00001674void Assembler::repmovsb() {
1675 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001676 emit(0xF3);
1677 emit(0xA4);
1678}
1679
1680
1681void Assembler::repmovsw() {
1682 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001683 emit(0x66); // Operand size override.
1684 emit(0xF3);
1685 emit(0xA4);
1686}
1687
1688
1689void Assembler::repmovsl() {
1690 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001691 emit(0xF3);
1692 emit(0xA5);
1693}
1694
1695
1696void Assembler::repmovsq() {
1697 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001698 emit(0xF3);
1699 emit_rex_64();
1700 emit(0xA5);
1701}
1702
1703
Steve Blocka7e24c12009-10-30 11:49:00 +00001704void Assembler::mul(Register src) {
1705 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001706 emit_rex_64(src);
1707 emit(0xF7);
1708 emit_modrm(0x4, src);
1709}
1710
1711
1712void Assembler::neg(Register dst) {
1713 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001714 emit_rex_64(dst);
1715 emit(0xF7);
1716 emit_modrm(0x3, dst);
1717}
1718
1719
1720void Assembler::negl(Register dst) {
1721 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001722 emit_optional_rex_32(dst);
1723 emit(0xF7);
1724 emit_modrm(0x3, dst);
1725}
1726
1727
1728void Assembler::neg(const Operand& dst) {
1729 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001730 emit_rex_64(dst);
1731 emit(0xF7);
1732 emit_operand(3, dst);
1733}
1734
1735
1736void Assembler::nop() {
1737 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001738 emit(0x90);
1739}
1740
1741
1742void Assembler::not_(Register dst) {
1743 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001744 emit_rex_64(dst);
1745 emit(0xF7);
1746 emit_modrm(0x2, dst);
1747}
1748
1749
1750void Assembler::not_(const Operand& dst) {
1751 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001752 emit_rex_64(dst);
1753 emit(0xF7);
1754 emit_operand(2, dst);
1755}
1756
1757
Steve Block6ded16b2010-05-10 14:33:55 +01001758void Assembler::notl(Register dst) {
1759 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01001760 emit_optional_rex_32(dst);
1761 emit(0xF7);
1762 emit_modrm(0x2, dst);
1763}
1764
1765
Steve Blocka7e24c12009-10-30 11:49:00 +00001766void Assembler::nop(int n) {
1767 // The recommended muti-byte sequences of NOP instructions from the Intel 64
1768 // and IA-32 Architectures Software Developer's Manual.
1769 //
1770 // Length Assembly Byte Sequence
1771 // 2 bytes 66 NOP 66 90H
1772 // 3 bytes NOP DWORD ptr [EAX] 0F 1F 00H
1773 // 4 bytes NOP DWORD ptr [EAX + 00H] 0F 1F 40 00H
1774 // 5 bytes NOP DWORD ptr [EAX + EAX*1 + 00H] 0F 1F 44 00 00H
1775 // 6 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00H] 66 0F 1F 44 00 00H
1776 // 7 bytes NOP DWORD ptr [EAX + 00000000H] 0F 1F 80 00 00 00 00H
1777 // 8 bytes NOP DWORD ptr [EAX + EAX*1 + 00000000H] 0F 1F 84 00 00 00 00 00H
1778 // 9 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 66 0F 1F 84 00 00 00 00
1779 // 00000000H] 00H
1780
1781 ASSERT(1 <= n);
1782 ASSERT(n <= 9);
1783 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001784 switch (n) {
1785 case 1:
1786 emit(0x90);
1787 return;
1788 case 2:
1789 emit(0x66);
1790 emit(0x90);
1791 return;
1792 case 3:
1793 emit(0x0f);
1794 emit(0x1f);
1795 emit(0x00);
1796 return;
1797 case 4:
1798 emit(0x0f);
1799 emit(0x1f);
1800 emit(0x40);
1801 emit(0x00);
1802 return;
1803 case 5:
1804 emit(0x0f);
1805 emit(0x1f);
1806 emit(0x44);
1807 emit(0x00);
1808 emit(0x00);
1809 return;
1810 case 6:
1811 emit(0x66);
1812 emit(0x0f);
1813 emit(0x1f);
1814 emit(0x44);
1815 emit(0x00);
1816 emit(0x00);
1817 return;
1818 case 7:
1819 emit(0x0f);
1820 emit(0x1f);
1821 emit(0x80);
1822 emit(0x00);
1823 emit(0x00);
1824 emit(0x00);
1825 emit(0x00);
1826 return;
1827 case 8:
1828 emit(0x0f);
1829 emit(0x1f);
1830 emit(0x84);
1831 emit(0x00);
1832 emit(0x00);
1833 emit(0x00);
1834 emit(0x00);
1835 emit(0x00);
1836 return;
1837 case 9:
1838 emit(0x66);
1839 emit(0x0f);
1840 emit(0x1f);
1841 emit(0x84);
1842 emit(0x00);
1843 emit(0x00);
1844 emit(0x00);
1845 emit(0x00);
1846 emit(0x00);
1847 return;
1848 }
1849}
1850
1851
1852void Assembler::pop(Register dst) {
1853 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001854 emit_optional_rex_32(dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001855 emit(0x58 | dst.low_bits());
1856}
1857
1858
1859void Assembler::pop(const Operand& dst) {
1860 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001861 emit_optional_rex_32(dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001862 emit(0x8F);
1863 emit_operand(0, dst);
1864}
1865
1866
1867void Assembler::popfq() {
1868 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001869 emit(0x9D);
1870}
1871
1872
1873void Assembler::push(Register src) {
1874 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001875 emit_optional_rex_32(src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001876 emit(0x50 | src.low_bits());
1877}
1878
1879
1880void Assembler::push(const Operand& src) {
1881 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01001882 emit_optional_rex_32(src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001883 emit(0xFF);
1884 emit_operand(6, src);
1885}
1886
1887
1888void Assembler::push(Immediate value) {
1889 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001890 if (is_int8(value.value_)) {
1891 emit(0x6A);
1892 emit(value.value_); // Emit low byte of value.
1893 } else {
1894 emit(0x68);
1895 emitl(value.value_);
1896 }
1897}
1898
1899
Steve Block1e0659c2011-05-24 12:43:12 +01001900void Assembler::push_imm32(int32_t imm32) {
1901 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01001902 emit(0x68);
1903 emitl(imm32);
1904}
1905
1906
Steve Blocka7e24c12009-10-30 11:49:00 +00001907void Assembler::pushfq() {
1908 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001909 emit(0x9C);
1910}
1911
1912
Steve Blocka7e24c12009-10-30 11:49:00 +00001913void Assembler::rdtsc() {
1914 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001915 emit(0x0F);
1916 emit(0x31);
1917}
1918
1919
1920void Assembler::ret(int imm16) {
1921 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001922 ASSERT(is_uint16(imm16));
1923 if (imm16 == 0) {
1924 emit(0xC3);
1925 } else {
1926 emit(0xC2);
1927 emit(imm16 & 0xFF);
1928 emit((imm16 >> 8) & 0xFF);
1929 }
1930}
1931
1932
1933void Assembler::setcc(Condition cc, Register reg) {
Steve Block3ce2e202009-11-05 08:53:23 +00001934 if (cc > last_condition) {
1935 movb(reg, Immediate(cc == always ? 1 : 0));
1936 return;
1937 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001938 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001939 ASSERT(is_uint4(cc));
1940 if (reg.code() > 3) { // Use x64 byte registers, where different.
1941 emit_rex_32(reg);
1942 }
1943 emit(0x0F);
1944 emit(0x90 | cc);
1945 emit_modrm(0x0, reg);
1946}
1947
1948
1949void Assembler::shld(Register dst, Register src) {
1950 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001951 emit_rex_64(src, dst);
1952 emit(0x0F);
1953 emit(0xA5);
1954 emit_modrm(src, dst);
1955}
1956
1957
1958void Assembler::shrd(Register dst, Register src) {
1959 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001960 emit_rex_64(src, dst);
1961 emit(0x0F);
1962 emit(0xAD);
1963 emit_modrm(src, dst);
1964}
1965
1966
1967void Assembler::xchg(Register dst, Register src) {
1968 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001969 if (src.is(rax) || dst.is(rax)) { // Single-byte encoding
1970 Register other = src.is(rax) ? dst : src;
1971 emit_rex_64(other);
1972 emit(0x90 | other.low_bits());
Leon Clarkef7060e22010-06-03 12:02:55 +01001973 } else if (dst.low_bits() == 4) {
1974 emit_rex_64(dst, src);
1975 emit(0x87);
1976 emit_modrm(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001977 } else {
1978 emit_rex_64(src, dst);
1979 emit(0x87);
1980 emit_modrm(src, dst);
1981 }
1982}
1983
1984
1985void Assembler::store_rax(void* dst, RelocInfo::Mode mode) {
1986 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001987 emit(0x48); // REX.W
1988 emit(0xA3);
1989 emitq(reinterpret_cast<uintptr_t>(dst), mode);
1990}
1991
1992
1993void Assembler::store_rax(ExternalReference ref) {
1994 store_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
1995}
1996
1997
Steve Block3ce2e202009-11-05 08:53:23 +00001998void Assembler::testb(Register dst, Register src) {
1999 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +01002000 if (src.low_bits() == 4) {
2001 emit_rex_32(src, dst);
2002 emit(0x84);
2003 emit_modrm(src, dst);
2004 } else {
2005 if (dst.code() > 3 || src.code() > 3) {
2006 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2007 emit_rex_32(dst, src);
2008 }
2009 emit(0x84);
2010 emit_modrm(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00002011 }
Steve Block3ce2e202009-11-05 08:53:23 +00002012}
2013
2014
Steve Blocka7e24c12009-10-30 11:49:00 +00002015void Assembler::testb(Register reg, Immediate mask) {
2016 ASSERT(is_int8(mask.value_) || is_uint8(mask.value_));
2017 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002018 if (reg.is(rax)) {
2019 emit(0xA8);
2020 emit(mask.value_); // Low byte emitted.
2021 } else {
2022 if (reg.code() > 3) {
2023 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2024 emit_rex_32(reg);
2025 }
2026 emit(0xF6);
2027 emit_modrm(0x0, reg);
2028 emit(mask.value_); // Low byte emitted.
2029 }
2030}
2031
2032
2033void Assembler::testb(const Operand& op, Immediate mask) {
2034 ASSERT(is_int8(mask.value_) || is_uint8(mask.value_));
2035 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002036 emit_optional_rex_32(rax, op);
2037 emit(0xF6);
2038 emit_operand(rax, op); // Operation code 0
2039 emit(mask.value_); // Low byte emitted.
2040}
2041
2042
Leon Clarkee46be812010-01-19 14:06:41 +00002043void Assembler::testb(const Operand& op, Register reg) {
2044 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002045 if (reg.code() > 3) {
2046 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2047 emit_rex_32(reg, op);
2048 } else {
2049 emit_optional_rex_32(reg, op);
2050 }
2051 emit(0x84);
2052 emit_operand(reg, op);
2053}
2054
2055
Steve Blocka7e24c12009-10-30 11:49:00 +00002056void Assembler::testl(Register dst, Register src) {
2057 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +01002058 if (src.low_bits() == 4) {
2059 emit_optional_rex_32(src, dst);
2060 emit(0x85);
2061 emit_modrm(src, dst);
2062 } else {
2063 emit_optional_rex_32(dst, src);
2064 emit(0x85);
2065 emit_modrm(dst, src);
2066 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002067}
2068
2069
2070void Assembler::testl(Register reg, Immediate mask) {
2071 // testl with a mask that fits in the low byte is exactly testb.
2072 if (is_uint8(mask.value_)) {
2073 testb(reg, mask);
2074 return;
2075 }
2076 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002077 if (reg.is(rax)) {
2078 emit(0xA9);
2079 emit(mask);
2080 } else {
2081 emit_optional_rex_32(rax, reg);
2082 emit(0xF7);
2083 emit_modrm(0x0, reg);
2084 emit(mask);
2085 }
2086}
2087
2088
2089void Assembler::testl(const Operand& op, Immediate mask) {
2090 // testl with a mask that fits in the low byte is exactly testb.
2091 if (is_uint8(mask.value_)) {
2092 testb(op, mask);
2093 return;
2094 }
2095 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002096 emit_optional_rex_32(rax, op);
2097 emit(0xF7);
2098 emit_operand(rax, op); // Operation code 0
2099 emit(mask);
2100}
2101
2102
2103void Assembler::testq(const Operand& op, Register reg) {
2104 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002105 emit_rex_64(reg, op);
2106 emit(0x85);
2107 emit_operand(reg, op);
2108}
2109
2110
2111void Assembler::testq(Register dst, Register src) {
2112 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +01002113 if (src.low_bits() == 4) {
2114 emit_rex_64(src, dst);
2115 emit(0x85);
2116 emit_modrm(src, dst);
2117 } else {
2118 emit_rex_64(dst, src);
2119 emit(0x85);
2120 emit_modrm(dst, src);
2121 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002122}
2123
2124
2125void Assembler::testq(Register dst, Immediate mask) {
2126 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002127 if (dst.is(rax)) {
2128 emit_rex_64();
2129 emit(0xA9);
2130 emit(mask);
2131 } else {
2132 emit_rex_64(dst);
2133 emit(0xF7);
2134 emit_modrm(0, dst);
2135 emit(mask);
2136 }
2137}
2138
2139
Andrei Popescu31002712010-02-23 13:46:05 +00002140// FPU instructions.
Steve Blocka7e24c12009-10-30 11:49:00 +00002141
2142
2143void Assembler::fld(int i) {
2144 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002145 emit_farith(0xD9, 0xC0, i);
2146}
2147
2148
2149void Assembler::fld1() {
2150 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002151 emit(0xD9);
2152 emit(0xE8);
2153}
2154
2155
2156void Assembler::fldz() {
2157 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002158 emit(0xD9);
2159 emit(0xEE);
2160}
2161
2162
Steve Block6ded16b2010-05-10 14:33:55 +01002163void Assembler::fldpi() {
2164 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002165 emit(0xD9);
2166 emit(0xEB);
2167}
2168
2169
Ben Murdochb0fe1622011-05-05 13:52:32 +01002170void Assembler::fldln2() {
2171 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002172 emit(0xD9);
2173 emit(0xED);
2174}
2175
2176
Steve Blocka7e24c12009-10-30 11:49:00 +00002177void Assembler::fld_s(const Operand& adr) {
2178 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002179 emit_optional_rex_32(adr);
2180 emit(0xD9);
2181 emit_operand(0, adr);
2182}
2183
2184
2185void Assembler::fld_d(const Operand& adr) {
2186 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002187 emit_optional_rex_32(adr);
2188 emit(0xDD);
2189 emit_operand(0, adr);
2190}
2191
2192
2193void Assembler::fstp_s(const Operand& adr) {
2194 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002195 emit_optional_rex_32(adr);
2196 emit(0xD9);
2197 emit_operand(3, adr);
2198}
2199
2200
2201void Assembler::fstp_d(const Operand& adr) {
2202 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002203 emit_optional_rex_32(adr);
2204 emit(0xDD);
2205 emit_operand(3, adr);
2206}
2207
2208
Steve Block3ce2e202009-11-05 08:53:23 +00002209void Assembler::fstp(int index) {
2210 ASSERT(is_uint3(index));
2211 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00002212 emit_farith(0xDD, 0xD8, index);
2213}
2214
2215
Steve Blocka7e24c12009-10-30 11:49:00 +00002216void Assembler::fild_s(const Operand& adr) {
2217 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002218 emit_optional_rex_32(adr);
2219 emit(0xDB);
2220 emit_operand(0, adr);
2221}
2222
2223
2224void Assembler::fild_d(const Operand& adr) {
2225 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002226 emit_optional_rex_32(adr);
2227 emit(0xDF);
2228 emit_operand(5, adr);
2229}
2230
2231
2232void Assembler::fistp_s(const Operand& adr) {
2233 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002234 emit_optional_rex_32(adr);
2235 emit(0xDB);
2236 emit_operand(3, adr);
2237}
2238
2239
2240void Assembler::fisttp_s(const Operand& adr) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002241 ASSERT(CpuFeatures::IsEnabled(SSE3));
Steve Blocka7e24c12009-10-30 11:49:00 +00002242 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002243 emit_optional_rex_32(adr);
2244 emit(0xDB);
2245 emit_operand(1, adr);
2246}
2247
2248
Leon Clarked91b9f72010-01-27 17:25:45 +00002249void Assembler::fisttp_d(const Operand& adr) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002250 ASSERT(CpuFeatures::IsEnabled(SSE3));
Leon Clarked91b9f72010-01-27 17:25:45 +00002251 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00002252 emit_optional_rex_32(adr);
2253 emit(0xDD);
2254 emit_operand(1, adr);
2255}
2256
2257
Steve Blocka7e24c12009-10-30 11:49:00 +00002258void Assembler::fist_s(const Operand& adr) {
2259 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002260 emit_optional_rex_32(adr);
2261 emit(0xDB);
2262 emit_operand(2, adr);
2263}
2264
2265
2266void Assembler::fistp_d(const Operand& adr) {
2267 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002268 emit_optional_rex_32(adr);
2269 emit(0xDF);
Steve Block3ce2e202009-11-05 08:53:23 +00002270 emit_operand(7, adr);
Steve Blocka7e24c12009-10-30 11:49:00 +00002271}
2272
2273
2274void Assembler::fabs() {
2275 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002276 emit(0xD9);
2277 emit(0xE1);
2278}
2279
2280
2281void Assembler::fchs() {
2282 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002283 emit(0xD9);
2284 emit(0xE0);
2285}
2286
2287
2288void Assembler::fcos() {
2289 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002290 emit(0xD9);
2291 emit(0xFF);
2292}
2293
2294
2295void Assembler::fsin() {
2296 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002297 emit(0xD9);
2298 emit(0xFE);
2299}
2300
2301
Ben Murdochb0fe1622011-05-05 13:52:32 +01002302void Assembler::fyl2x() {
2303 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002304 emit(0xD9);
2305 emit(0xF1);
2306}
2307
2308
Steve Blocka7e24c12009-10-30 11:49:00 +00002309void Assembler::fadd(int i) {
2310 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002311 emit_farith(0xDC, 0xC0, i);
2312}
2313
2314
2315void Assembler::fsub(int i) {
2316 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002317 emit_farith(0xDC, 0xE8, i);
2318}
2319
2320
2321void Assembler::fisub_s(const Operand& adr) {
2322 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002323 emit_optional_rex_32(adr);
2324 emit(0xDA);
2325 emit_operand(4, adr);
2326}
2327
2328
2329void Assembler::fmul(int i) {
2330 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002331 emit_farith(0xDC, 0xC8, i);
2332}
2333
2334
2335void Assembler::fdiv(int i) {
2336 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002337 emit_farith(0xDC, 0xF8, i);
2338}
2339
2340
2341void Assembler::faddp(int i) {
2342 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002343 emit_farith(0xDE, 0xC0, i);
2344}
2345
2346
2347void Assembler::fsubp(int i) {
2348 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002349 emit_farith(0xDE, 0xE8, i);
2350}
2351
2352
2353void Assembler::fsubrp(int i) {
2354 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002355 emit_farith(0xDE, 0xE0, i);
2356}
2357
2358
2359void Assembler::fmulp(int i) {
2360 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002361 emit_farith(0xDE, 0xC8, i);
2362}
2363
2364
2365void Assembler::fdivp(int i) {
2366 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002367 emit_farith(0xDE, 0xF8, i);
2368}
2369
2370
2371void Assembler::fprem() {
2372 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002373 emit(0xD9);
2374 emit(0xF8);
2375}
2376
2377
2378void Assembler::fprem1() {
2379 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002380 emit(0xD9);
2381 emit(0xF5);
2382}
2383
2384
2385void Assembler::fxch(int i) {
2386 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002387 emit_farith(0xD9, 0xC8, i);
2388}
2389
2390
2391void Assembler::fincstp() {
2392 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002393 emit(0xD9);
2394 emit(0xF7);
2395}
2396
2397
2398void Assembler::ffree(int i) {
2399 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002400 emit_farith(0xDD, 0xC0, i);
2401}
2402
2403
2404void Assembler::ftst() {
2405 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002406 emit(0xD9);
2407 emit(0xE4);
2408}
2409
2410
2411void Assembler::fucomp(int i) {
2412 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002413 emit_farith(0xDD, 0xE8, i);
2414}
2415
2416
2417void Assembler::fucompp() {
2418 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002419 emit(0xDA);
2420 emit(0xE9);
2421}
2422
2423
Steve Block3ce2e202009-11-05 08:53:23 +00002424void Assembler::fucomi(int i) {
2425 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00002426 emit(0xDB);
2427 emit(0xE8 + i);
2428}
2429
2430
2431void Assembler::fucomip() {
2432 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00002433 emit(0xDF);
2434 emit(0xE9);
2435}
2436
2437
Steve Blocka7e24c12009-10-30 11:49:00 +00002438void Assembler::fcompp() {
2439 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002440 emit(0xDE);
2441 emit(0xD9);
2442}
2443
2444
2445void Assembler::fnstsw_ax() {
2446 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002447 emit(0xDF);
2448 emit(0xE0);
2449}
2450
2451
2452void Assembler::fwait() {
2453 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002454 emit(0x9B);
2455}
2456
2457
2458void Assembler::frndint() {
2459 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002460 emit(0xD9);
2461 emit(0xFC);
2462}
2463
2464
2465void Assembler::fnclex() {
2466 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002467 emit(0xDB);
2468 emit(0xE2);
2469}
2470
2471
2472void Assembler::sahf() {
2473 // TODO(X64): Test for presence. Not all 64-bit intel CPU's have sahf
2474 // in 64-bit mode. Test CpuID.
2475 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002476 emit(0x9E);
2477}
2478
2479
2480void Assembler::emit_farith(int b1, int b2, int i) {
2481 ASSERT(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2482 ASSERT(is_uint3(i)); // illegal stack offset
2483 emit(b1);
2484 emit(b2 + i);
2485}
2486
Andrei Popescu31002712010-02-23 13:46:05 +00002487// SSE 2 operations.
Steve Blocka7e24c12009-10-30 11:49:00 +00002488
Steve Block6ded16b2010-05-10 14:33:55 +01002489void Assembler::movd(XMMRegister dst, Register src) {
2490 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002491 emit(0x66);
2492 emit_optional_rex_32(dst, src);
2493 emit(0x0F);
2494 emit(0x6E);
2495 emit_sse_operand(dst, src);
2496}
2497
2498
2499void Assembler::movd(Register dst, XMMRegister src) {
2500 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002501 emit(0x66);
Ben Murdochbb769b22010-08-11 14:56:33 +01002502 emit_optional_rex_32(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002503 emit(0x0F);
2504 emit(0x7E);
Ben Murdochbb769b22010-08-11 14:56:33 +01002505 emit_sse_operand(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002506}
2507
2508
2509void Assembler::movq(XMMRegister dst, Register src) {
2510 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002511 emit(0x66);
2512 emit_rex_64(dst, src);
2513 emit(0x0F);
2514 emit(0x6E);
2515 emit_sse_operand(dst, src);
2516}
2517
2518
2519void Assembler::movq(Register dst, XMMRegister src) {
2520 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002521 emit(0x66);
Ben Murdochbb769b22010-08-11 14:56:33 +01002522 emit_rex_64(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002523 emit(0x0F);
2524 emit(0x7E);
Ben Murdochbb769b22010-08-11 14:56:33 +01002525 emit_sse_operand(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002526}
2527
2528
Ben Murdoch257744e2011-11-30 15:57:28 +00002529void Assembler::movq(XMMRegister dst, XMMRegister src) {
2530 EnsureSpace ensure_space(this);
2531 if (dst.low_bits() == 4) {
2532 // Avoid unnecessary SIB byte.
2533 emit(0xf3);
2534 emit_optional_rex_32(dst, src);
2535 emit(0x0F);
2536 emit(0x7e);
2537 emit_sse_operand(dst, src);
2538 } else {
2539 emit(0x66);
2540 emit_optional_rex_32(src, dst);
2541 emit(0x0F);
2542 emit(0xD6);
2543 emit_sse_operand(src, dst);
2544 }
2545}
2546
Ben Murdoch8b112d22011-06-08 16:22:53 +01002547void Assembler::movdqa(const Operand& dst, XMMRegister src) {
2548 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002549 emit(0x66);
2550 emit_rex_64(src, dst);
2551 emit(0x0F);
2552 emit(0x7F);
2553 emit_sse_operand(src, dst);
2554}
2555
2556
2557void Assembler::movdqa(XMMRegister dst, const Operand& src) {
Steve Block1e0659c2011-05-24 12:43:12 +01002558 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002559 emit(0x66);
2560 emit_rex_64(dst, src);
2561 emit(0x0F);
2562 emit(0x6F);
2563 emit_sse_operand(dst, src);
2564}
2565
2566
Steve Block6ded16b2010-05-10 14:33:55 +01002567void Assembler::extractps(Register dst, XMMRegister src, byte imm8) {
2568 ASSERT(is_uint2(imm8));
2569 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002570 emit(0x66);
2571 emit_optional_rex_32(dst, src);
2572 emit(0x0F);
2573 emit(0x3A);
2574 emit(0x17);
2575 emit_sse_operand(dst, src);
2576 emit(imm8);
2577}
2578
2579
Steve Blocka7e24c12009-10-30 11:49:00 +00002580void Assembler::movsd(const Operand& dst, XMMRegister src) {
2581 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002582 emit(0xF2); // double
2583 emit_optional_rex_32(src, dst);
2584 emit(0x0F);
2585 emit(0x11); // store
2586 emit_sse_operand(src, dst);
2587}
2588
2589
Steve Block3ce2e202009-11-05 08:53:23 +00002590void Assembler::movsd(XMMRegister dst, XMMRegister src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002591 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002592 emit(0xF2); // double
2593 emit_optional_rex_32(dst, src);
2594 emit(0x0F);
2595 emit(0x10); // load
2596 emit_sse_operand(dst, src);
2597}
2598
2599
2600void Assembler::movsd(XMMRegister dst, const Operand& src) {
2601 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002602 emit(0xF2); // double
2603 emit_optional_rex_32(dst, src);
2604 emit(0x0F);
2605 emit(0x10); // load
2606 emit_sse_operand(dst, src);
2607}
2608
2609
Ben Murdoch257744e2011-11-30 15:57:28 +00002610void Assembler::movaps(XMMRegister dst, XMMRegister src) {
2611 EnsureSpace ensure_space(this);
2612 if (src.low_bits() == 4) {
2613 // Try to avoid an unnecessary SIB byte.
2614 emit_optional_rex_32(src, dst);
2615 emit(0x0F);
2616 emit(0x29);
2617 emit_sse_operand(src, dst);
2618 } else {
2619 emit_optional_rex_32(dst, src);
2620 emit(0x0F);
2621 emit(0x28);
2622 emit_sse_operand(dst, src);
2623 }
2624}
2625
2626
2627void Assembler::movapd(XMMRegister dst, XMMRegister src) {
2628 EnsureSpace ensure_space(this);
2629 if (src.low_bits() == 4) {
2630 // Try to avoid an unnecessary SIB byte.
2631 emit(0x66);
2632 emit_optional_rex_32(src, dst);
2633 emit(0x0F);
2634 emit(0x29);
2635 emit_sse_operand(src, dst);
2636 } else {
2637 emit(0x66);
2638 emit_optional_rex_32(dst, src);
2639 emit(0x0F);
2640 emit(0x28);
2641 emit_sse_operand(dst, src);
2642 }
2643}
2644
2645
Steve Block8defd9f2010-07-08 12:39:36 +01002646void Assembler::movss(XMMRegister dst, const Operand& src) {
2647 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01002648 emit(0xF3); // single
2649 emit_optional_rex_32(dst, src);
2650 emit(0x0F);
2651 emit(0x10); // load
2652 emit_sse_operand(dst, src);
2653}
2654
2655
2656void Assembler::movss(const Operand& src, XMMRegister dst) {
2657 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01002658 emit(0xF3); // single
2659 emit_optional_rex_32(dst, src);
2660 emit(0x0F);
2661 emit(0x11); // store
2662 emit_sse_operand(dst, src);
2663}
2664
2665
Steve Blocka7e24c12009-10-30 11:49:00 +00002666void Assembler::cvttss2si(Register dst, const Operand& src) {
2667 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002668 emit(0xF3);
2669 emit_optional_rex_32(dst, src);
2670 emit(0x0F);
2671 emit(0x2C);
2672 emit_operand(dst, src);
2673}
2674
2675
Steve Block1e0659c2011-05-24 12:43:12 +01002676void Assembler::cvttss2si(Register dst, XMMRegister src) {
2677 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002678 emit(0xF3);
2679 emit_optional_rex_32(dst, src);
2680 emit(0x0F);
2681 emit(0x2C);
2682 emit_sse_operand(dst, src);
2683}
2684
2685
Steve Blocka7e24c12009-10-30 11:49:00 +00002686void Assembler::cvttsd2si(Register dst, const Operand& src) {
2687 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002688 emit(0xF2);
2689 emit_optional_rex_32(dst, src);
2690 emit(0x0F);
2691 emit(0x2C);
2692 emit_operand(dst, src);
2693}
2694
2695
Steve Block1e0659c2011-05-24 12:43:12 +01002696void Assembler::cvttsd2si(Register dst, XMMRegister src) {
2697 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002698 emit(0xF2);
2699 emit_optional_rex_32(dst, src);
2700 emit(0x0F);
2701 emit(0x2C);
2702 emit_sse_operand(dst, src);
2703}
2704
2705
Kristian Monsen25f61362010-05-21 11:50:48 +01002706void Assembler::cvttsd2siq(Register dst, XMMRegister src) {
2707 EnsureSpace ensure_space(this);
Kristian Monsen25f61362010-05-21 11:50:48 +01002708 emit(0xF2);
2709 emit_rex_64(dst, src);
2710 emit(0x0F);
2711 emit(0x2C);
2712 emit_sse_operand(dst, src);
2713}
2714
2715
Steve Blocka7e24c12009-10-30 11:49:00 +00002716void Assembler::cvtlsi2sd(XMMRegister dst, const Operand& src) {
2717 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002718 emit(0xF2);
2719 emit_optional_rex_32(dst, src);
2720 emit(0x0F);
2721 emit(0x2A);
2722 emit_sse_operand(dst, src);
2723}
2724
2725
2726void Assembler::cvtlsi2sd(XMMRegister dst, Register src) {
2727 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002728 emit(0xF2);
2729 emit_optional_rex_32(dst, src);
2730 emit(0x0F);
2731 emit(0x2A);
2732 emit_sse_operand(dst, src);
2733}
2734
2735
Steve Block8defd9f2010-07-08 12:39:36 +01002736void Assembler::cvtlsi2ss(XMMRegister dst, Register src) {
2737 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01002738 emit(0xF3);
2739 emit_optional_rex_32(dst, src);
2740 emit(0x0F);
2741 emit(0x2A);
2742 emit_sse_operand(dst, src);
2743}
2744
2745
Steve Blocka7e24c12009-10-30 11:49:00 +00002746void Assembler::cvtqsi2sd(XMMRegister dst, Register src) {
2747 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002748 emit(0xF2);
2749 emit_rex_64(dst, src);
2750 emit(0x0F);
2751 emit(0x2A);
2752 emit_sse_operand(dst, src);
2753}
2754
2755
Steve Block6ded16b2010-05-10 14:33:55 +01002756void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
2757 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002758 emit(0xF3);
2759 emit_optional_rex_32(dst, src);
2760 emit(0x0F);
2761 emit(0x5A);
2762 emit_sse_operand(dst, src);
2763}
2764
2765
Steve Block8defd9f2010-07-08 12:39:36 +01002766void Assembler::cvtss2sd(XMMRegister dst, const Operand& src) {
2767 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01002768 emit(0xF3);
2769 emit_optional_rex_32(dst, src);
2770 emit(0x0F);
2771 emit(0x5A);
2772 emit_sse_operand(dst, src);
2773}
2774
2775
2776void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
2777 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01002778 emit(0xF2);
2779 emit_optional_rex_32(dst, src);
2780 emit(0x0F);
2781 emit(0x5A);
2782 emit_sse_operand(dst, src);
2783}
2784
2785
2786void Assembler::cvtsd2si(Register dst, XMMRegister src) {
2787 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01002788 emit(0xF2);
2789 emit_optional_rex_32(dst, src);
2790 emit(0x0F);
2791 emit(0x2D);
2792 emit_sse_operand(dst, src);
2793}
2794
2795
2796void Assembler::cvtsd2siq(Register dst, XMMRegister src) {
2797 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01002798 emit(0xF2);
2799 emit_rex_64(dst, src);
2800 emit(0x0F);
2801 emit(0x2D);
2802 emit_sse_operand(dst, src);
2803}
2804
2805
Steve Blocka7e24c12009-10-30 11:49:00 +00002806void Assembler::addsd(XMMRegister dst, XMMRegister src) {
2807 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002808 emit(0xF2);
2809 emit_optional_rex_32(dst, src);
2810 emit(0x0F);
2811 emit(0x58);
2812 emit_sse_operand(dst, src);
2813}
2814
2815
2816void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
2817 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002818 emit(0xF2);
2819 emit_optional_rex_32(dst, src);
2820 emit(0x0F);
2821 emit(0x59);
2822 emit_sse_operand(dst, src);
2823}
2824
2825
2826void Assembler::subsd(XMMRegister dst, XMMRegister src) {
2827 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002828 emit(0xF2);
2829 emit_optional_rex_32(dst, src);
2830 emit(0x0F);
2831 emit(0x5C);
2832 emit_sse_operand(dst, src);
2833}
2834
2835
2836void Assembler::divsd(XMMRegister dst, XMMRegister src) {
2837 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002838 emit(0xF2);
2839 emit_optional_rex_32(dst, src);
2840 emit(0x0F);
2841 emit(0x5E);
2842 emit_sse_operand(dst, src);
2843}
2844
2845
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002846void Assembler::andpd(XMMRegister dst, XMMRegister src) {
2847 EnsureSpace ensure_space(this);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002848 emit(0x66);
2849 emit_optional_rex_32(dst, src);
2850 emit(0x0F);
2851 emit(0x54);
2852 emit_sse_operand(dst, src);
2853}
2854
2855
2856void Assembler::orpd(XMMRegister dst, XMMRegister src) {
2857 EnsureSpace ensure_space(this);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002858 emit(0x66);
2859 emit_optional_rex_32(dst, src);
2860 emit(0x0F);
2861 emit(0x56);
2862 emit_sse_operand(dst, src);
2863}
2864
2865
Andrei Popescu402d9372010-02-26 13:31:12 +00002866void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
2867 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002868 emit(0x66);
2869 emit_optional_rex_32(dst, src);
Steve Block6ded16b2010-05-10 14:33:55 +01002870 emit(0x0F);
Andrei Popescu402d9372010-02-26 13:31:12 +00002871 emit(0x57);
2872 emit_sse_operand(dst, src);
2873}
2874
2875
Ben Murdoch257744e2011-11-30 15:57:28 +00002876void Assembler::xorps(XMMRegister dst, XMMRegister src) {
2877 EnsureSpace ensure_space(this);
2878 emit_optional_rex_32(dst, src);
2879 emit(0x0F);
2880 emit(0x57);
2881 emit_sse_operand(dst, src);
2882}
2883
2884
Steve Block6ded16b2010-05-10 14:33:55 +01002885void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
2886 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002887 emit(0xF2);
2888 emit_optional_rex_32(dst, src);
2889 emit(0x0F);
2890 emit(0x51);
2891 emit_sse_operand(dst, src);
2892}
2893
2894
Andrei Popescu402d9372010-02-26 13:31:12 +00002895void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
2896 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002897 emit(0x66);
2898 emit_optional_rex_32(dst, src);
2899 emit(0x0f);
2900 emit(0x2e);
2901 emit_sse_operand(dst, src);
2902}
2903
Steve Blocka7e24c12009-10-30 11:49:00 +00002904
Steve Block8defd9f2010-07-08 12:39:36 +01002905void Assembler::ucomisd(XMMRegister dst, const Operand& src) {
2906 EnsureSpace ensure_space(this);
Steve Block8defd9f2010-07-08 12:39:36 +01002907 emit(0x66);
2908 emit_optional_rex_32(dst, src);
2909 emit(0x0f);
2910 emit(0x2e);
2911 emit_sse_operand(dst, src);
2912}
2913
2914
Ben Murdoch257744e2011-11-30 15:57:28 +00002915void Assembler::roundsd(XMMRegister dst, XMMRegister src,
2916 Assembler::RoundingMode mode) {
2917 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
2918 EnsureSpace ensure_space(this);
2919 emit(0x66);
2920 emit_optional_rex_32(dst, src);
2921 emit(0x0f);
2922 emit(0x3a);
2923 emit(0x0b);
2924 emit_sse_operand(dst, src);
2925 // Mask precision exeption.
2926 emit(static_cast<byte>(mode) | 0x8);
2927}
2928
2929
Steve Block1e0659c2011-05-24 12:43:12 +01002930void Assembler::movmskpd(Register dst, XMMRegister src) {
2931 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002932 emit(0x66);
2933 emit_optional_rex_32(dst, src);
2934 emit(0x0f);
2935 emit(0x50);
2936 emit_sse_operand(dst, src);
2937}
2938
Steve Block8defd9f2010-07-08 12:39:36 +01002939
Steve Blocka7e24c12009-10-30 11:49:00 +00002940void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
2941 Register ireg = { reg.code() };
2942 emit_operand(ireg, adr);
2943}
2944
2945
2946void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
2947 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
2948}
2949
2950void Assembler::emit_sse_operand(XMMRegister dst, Register src) {
2951 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
2952}
2953
Steve Block6ded16b2010-05-10 14:33:55 +01002954void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
2955 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
2956}
2957
Steve Blocka7e24c12009-10-30 11:49:00 +00002958
Ben Murdochb8e0da22011-05-16 14:20:40 +01002959void Assembler::db(uint8_t data) {
2960 EnsureSpace ensure_space(this);
2961 emit(data);
2962}
2963
2964
Ben Murdochb0fe1622011-05-05 13:52:32 +01002965void Assembler::dd(uint32_t data) {
2966 EnsureSpace ensure_space(this);
2967 emitl(data);
2968}
2969
2970
Andrei Popescu31002712010-02-23 13:46:05 +00002971// Relocation information implementations.
Steve Blocka7e24c12009-10-30 11:49:00 +00002972
2973void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2974 ASSERT(rmode != RelocInfo::NONE);
2975 // Don't record external references unless the heap will be serialized.
Steve Block1e0659c2011-05-24 12:43:12 +01002976 if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
2977#ifdef DEBUG
2978 if (!Serializer::enabled()) {
2979 Serializer::TooLateToEnableNow();
2980 }
2981#endif
Steve Block44f0eee2011-05-26 01:26:41 +01002982 if (!Serializer::enabled() && !emit_debug_code()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002983 return;
2984 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002985 }
2986 RelocInfo rinfo(pc_, rmode, data);
2987 reloc_info_writer.Write(&rinfo);
2988}
2989
2990void Assembler::RecordJSReturn() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002991 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00002992 EnsureSpace ensure_space(this);
2993 RecordRelocInfo(RelocInfo::JS_RETURN);
2994}
2995
2996
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002997void Assembler::RecordDebugBreakSlot() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002998 positions_recorder()->WriteRecordedPositions();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002999 EnsureSpace ensure_space(this);
3000 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
3001}
3002
3003
Ben Murdoche0cee9b2011-05-25 10:26:03 +01003004void Assembler::RecordComment(const char* msg, bool force) {
3005 if (FLAG_code_comments || force) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003006 EnsureSpace ensure_space(this);
3007 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
3008 }
3009}
3010
3011
Steve Block3ce2e202009-11-05 08:53:23 +00003012const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
Ben Murdochbb769b22010-08-11 14:56:33 +01003013 1 << RelocInfo::INTERNAL_REFERENCE;
Steve Blocka7e24c12009-10-30 11:49:00 +00003014
Leon Clarkef7060e22010-06-03 12:02:55 +01003015
3016bool RelocInfo::IsCodedSpecially() {
3017 // The deserializer needs to know whether a pointer is specially coded. Being
3018 // specially coded on x64 means that it is a relative 32 bit address, as used
3019 // by branch instructions.
3020 return (1 << rmode_) & kApplyMask;
3021}
3022
3023
3024
Steve Blocka7e24c12009-10-30 11:49:00 +00003025} } // namespace v8::internal
Leon Clarkef7060e22010-06-03 12:02:55 +01003026
3027#endif // V8_TARGET_ARCH_X64