blob: 0744b8a3069fc2a1e60fc64079a043b2317e7ea7 [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
Steve Block44f0eee2011-05-26 01:26:41 +010041CpuFeatures::CpuFeatures()
42 : supported_(kDefaultCpuFeatures),
43 enabled_(0),
44 found_by_runtime_probing_(0) {
45}
46
Steve Blocka7e24c12009-10-30 11:49:00 +000047
Ben Murdochb0fe1622011-05-05 13:52:32 +010048void CpuFeatures::Probe(bool portable) {
Steve Block44f0eee2011-05-26 01:26:41 +010049 ASSERT(HEAP->HasBeenSetup());
Ben Murdochb0fe1622011-05-05 13:52:32 +010050 supported_ = kDefaultCpuFeatures;
51 if (portable && Serializer::enabled()) {
Steve Blockd0582a62009-12-15 09:54:21 +000052 supported_ |= OS::CpuFeaturesImpliedByPlatform();
53 return; // No features if we might serialize.
54 }
Steve Blocka7e24c12009-10-30 11:49:00 +000055
56 Assembler assm(NULL, 0);
57 Label cpuid, done;
58#define __ assm.
59 // Save old rsp, since we are going to modify the stack.
60 __ push(rbp);
61 __ pushfq();
62 __ push(rcx);
63 __ push(rbx);
64 __ movq(rbp, rsp);
65
66 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
67 __ pushfq();
68 __ pop(rax);
69 __ movq(rdx, rax);
70 __ xor_(rax, Immediate(0x200000)); // Flip bit 21.
71 __ push(rax);
72 __ popfq();
73 __ pushfq();
74 __ pop(rax);
75 __ xor_(rax, rdx); // Different if CPUID is supported.
76 __ j(not_zero, &cpuid);
77
Steve Block9fac8402011-05-12 15:51:54 +010078 // CPUID not supported. Clear the supported features in rax.
Steve Blocka7e24c12009-10-30 11:49:00 +000079 __ xor_(rax, rax);
80 __ jmp(&done);
81
82 // Invoke CPUID with 1 in eax to get feature information in
83 // ecx:edx. Temporarily enable CPUID support because we know it's
84 // safe here.
85 __ bind(&cpuid);
86 __ movq(rax, Immediate(1));
87 supported_ = kDefaultCpuFeatures | (1 << CPUID);
88 { Scope fscope(CPUID);
89 __ cpuid();
90 // Move the result from ecx:edx to rdi.
91 __ movl(rdi, rdx); // Zero-extended to 64 bits.
92 __ shl(rcx, Immediate(32));
93 __ or_(rdi, rcx);
94
95 // Get the sahf supported flag, from CPUID(0x80000001)
96 __ movq(rax, 0x80000001, RelocInfo::NONE);
97 __ cpuid();
98 }
99 supported_ = kDefaultCpuFeatures;
100
101 // Put the CPU flags in rax.
102 // rax = (rcx & 1) | (rdi & ~1) | (1 << CPUID).
103 __ movl(rax, Immediate(1));
104 __ and_(rcx, rax); // Bit 0 is set if SAHF instruction supported.
105 __ not_(rax);
106 __ and_(rax, rdi);
107 __ or_(rax, rcx);
108 __ or_(rax, Immediate(1 << CPUID));
109
110 // Done.
111 __ bind(&done);
112 __ movq(rsp, rbp);
113 __ pop(rbx);
114 __ pop(rcx);
115 __ popfq();
116 __ pop(rbp);
117 __ ret(0);
118#undef __
119
120 CodeDesc desc;
121 assm.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +0100122 Isolate* isolate = Isolate::Current();
123 MaybeObject* maybe_code =
124 isolate->heap()->CreateCode(desc,
125 Code::ComputeFlags(Code::STUB),
126 Handle<Object>());
John Reck59135872010-11-02 12:39:01 -0700127 Object* code;
128 if (!maybe_code->ToObject(&code)) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000129 if (!code->IsCode()) return;
Steve Block44f0eee2011-05-26 01:26:41 +0100130 PROFILE(isolate,
131 CodeCreateEvent(Logger::BUILTIN_TAG,
Steve Block6ded16b2010-05-10 14:33:55 +0100132 Code::cast(code), "CpuFeatures::Probe"));
Steve Blocka7e24c12009-10-30 11:49:00 +0000133 typedef uint64_t (*F0)();
134 F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry());
135 supported_ = probe();
Steve Blockd0582a62009-12-15 09:54:21 +0000136 found_by_runtime_probing_ = supported_;
137 found_by_runtime_probing_ &= ~kDefaultCpuFeatures;
138 uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform();
139 supported_ |= os_guarantees;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100140 found_by_runtime_probing_ &= portable ? ~os_guarantees : 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000141 // SSE2 and CMOV must be available on an X64 CPU.
142 ASSERT(IsSupported(CPUID));
143 ASSERT(IsSupported(SSE2));
144 ASSERT(IsSupported(CMOV));
145}
146
147
148// -----------------------------------------------------------------------------
149// Implementation of RelocInfo
150
151// Patch the code at the current PC with a call to the target address.
152// Additional guard int3 instructions can be added if required.
153void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
154 // Load register with immediate 64 and call through a register instructions
155 // takes up 13 bytes and int3 takes up one byte.
156 static const int kCallCodeSize = 13;
157 int code_size = kCallCodeSize + guard_bytes;
158
159 // Create a code patcher.
160 CodePatcher patcher(pc_, code_size);
161
162 // Add a label for checking the size of the code used for returning.
163#ifdef DEBUG
164 Label check_codesize;
165 patcher.masm()->bind(&check_codesize);
166#endif
167
168 // Patch the code.
169 patcher.masm()->movq(r10, target, RelocInfo::NONE);
170 patcher.masm()->call(r10);
171
172 // Check that the size of the code generated is as expected.
173 ASSERT_EQ(kCallCodeSize,
174 patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
175
176 // Add the requested number of int3 instructions after the call.
177 for (int i = 0; i < guard_bytes; i++) {
178 patcher.masm()->int3();
179 }
180}
181
182
183void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
184 // Patch the code at the current address with the supplied instructions.
185 for (int i = 0; i < instruction_count; i++) {
186 *(pc_ + i) = *(instructions + i);
187 }
188
189 // Indicate that code has changed.
190 CPU::FlushICache(pc_, instruction_count);
191}
192
Ben Murdochb8e0da22011-05-16 14:20:40 +0100193
194// -----------------------------------------------------------------------------
195// Register constants.
196
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100197const int Register::kRegisterCodeByAllocationIndex[kNumAllocatableRegisters] = {
Steve Block44f0eee2011-05-26 01:26:41 +0100198 // rax, rbx, rdx, rcx, rdi, r8, r9, r11, r14, r15
199 0, 3, 2, 1, 7, 8, 9, 11, 14, 15
Ben Murdochb8e0da22011-05-16 14:20:40 +0100200};
201
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100202const int Register::kAllocationIndexByRegisterCode[kNumRegisters] = {
Steve Block44f0eee2011-05-26 01:26:41 +0100203 0, 3, 2, 1, -1, -1, -1, 4, 5, 6, -1, 7, -1, -1, 8, 9
Ben Murdochb8e0da22011-05-16 14:20:40 +0100204};
205
206
Steve Blocka7e24c12009-10-30 11:49:00 +0000207// -----------------------------------------------------------------------------
208// Implementation of Operand
209
Andrei Popescu402d9372010-02-26 13:31:12 +0000210Operand::Operand(Register base, int32_t disp) : rex_(0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000211 len_ = 1;
212 if (base.is(rsp) || base.is(r12)) {
213 // SIB byte is needed to encode (rsp + offset) or (r12 + offset).
214 set_sib(times_1, rsp, base);
215 }
216
217 if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
218 set_modrm(0, base);
219 } else if (is_int8(disp)) {
220 set_modrm(1, base);
221 set_disp8(disp);
222 } else {
223 set_modrm(2, base);
224 set_disp32(disp);
225 }
226}
227
228
229Operand::Operand(Register base,
230 Register index,
231 ScaleFactor scale,
Andrei Popescu402d9372010-02-26 13:31:12 +0000232 int32_t disp) : rex_(0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000233 ASSERT(!index.is(rsp));
234 len_ = 1;
235 set_sib(scale, index, base);
236 if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
237 // This call to set_modrm doesn't overwrite the REX.B (or REX.X) bits
238 // possibly set by set_sib.
239 set_modrm(0, rsp);
240 } else if (is_int8(disp)) {
241 set_modrm(1, rsp);
242 set_disp8(disp);
243 } else {
244 set_modrm(2, rsp);
245 set_disp32(disp);
246 }
247}
248
249
Andrei Popescu402d9372010-02-26 13:31:12 +0000250Operand::Operand(Register index,
251 ScaleFactor scale,
252 int32_t disp) : rex_(0) {
253 ASSERT(!index.is(rsp));
254 len_ = 1;
255 set_modrm(0, rsp);
256 set_sib(scale, index, rbp);
257 set_disp32(disp);
258}
259
260
Leon Clarkef7060e22010-06-03 12:02:55 +0100261Operand::Operand(const Operand& operand, int32_t offset) {
262 ASSERT(operand.len_ >= 1);
263 // Operand encodes REX ModR/M [SIB] [Disp].
264 byte modrm = operand.buf_[0];
265 ASSERT(modrm < 0xC0); // Disallow mode 3 (register target).
266 bool has_sib = ((modrm & 0x07) == 0x04);
267 byte mode = modrm & 0xC0;
268 int disp_offset = has_sib ? 2 : 1;
269 int base_reg = (has_sib ? operand.buf_[1] : modrm) & 0x07;
270 // Mode 0 with rbp/r13 as ModR/M or SIB base register always has a 32-bit
271 // displacement.
272 bool is_baseless = (mode == 0) && (base_reg == 0x05); // No base or RIP base.
273 int32_t disp_value = 0;
274 if (mode == 0x80 || is_baseless) {
275 // Mode 2 or mode 0 with rbp/r13 as base: Word displacement.
Iain Merrick75681382010-08-19 15:07:18 +0100276 disp_value = *BitCast<const int32_t*>(&operand.buf_[disp_offset]);
Leon Clarkef7060e22010-06-03 12:02:55 +0100277 } else if (mode == 0x40) {
278 // Mode 1: Byte displacement.
279 disp_value = static_cast<signed char>(operand.buf_[disp_offset]);
280 }
281
282 // Write new operand with same registers, but with modified displacement.
283 ASSERT(offset >= 0 ? disp_value + offset > disp_value
284 : disp_value + offset < disp_value); // No overflow.
285 disp_value += offset;
286 rex_ = operand.rex_;
287 if (!is_int8(disp_value) || is_baseless) {
288 // Need 32 bits of displacement, mode 2 or mode 1 with register rbp/r13.
289 buf_[0] = (modrm & 0x3f) | (is_baseless ? 0x00 : 0x80);
290 len_ = disp_offset + 4;
291 Memory::int32_at(&buf_[disp_offset]) = disp_value;
292 } else if (disp_value != 0 || (base_reg == 0x05)) {
293 // Need 8 bits of displacement.
294 buf_[0] = (modrm & 0x3f) | 0x40; // Mode 1.
295 len_ = disp_offset + 1;
296 buf_[disp_offset] = static_cast<byte>(disp_value);
297 } else {
298 // Need no displacement.
299 buf_[0] = (modrm & 0x3f); // Mode 0.
300 len_ = disp_offset;
301 }
302 if (has_sib) {
303 buf_[1] = operand.buf_[1];
304 }
305}
306
Steve Block1e0659c2011-05-24 12:43:12 +0100307
308bool Operand::AddressUsesRegister(Register reg) const {
309 int code = reg.code();
310 ASSERT((buf_[0] & 0xC0) != 0xC0); // Always a memory operand.
311 // Start with only low three bits of base register. Initial decoding doesn't
312 // distinguish on the REX.B bit.
313 int base_code = buf_[0] & 0x07;
314 if (base_code == rsp.code()) {
315 // SIB byte present in buf_[1].
316 // Check the index register from the SIB byte + REX.X prefix.
317 int index_code = ((buf_[1] >> 3) & 0x07) | ((rex_ & 0x02) << 2);
318 // Index code (including REX.X) of 0x04 (rsp) means no index register.
319 if (index_code != rsp.code() && index_code == code) return true;
320 // Add REX.B to get the full base register code.
321 base_code = (buf_[1] & 0x07) | ((rex_ & 0x01) << 3);
322 // A base register of 0x05 (rbp) with mod = 0 means no base register.
323 if (base_code == rbp.code() && ((buf_[0] & 0xC0) == 0)) return false;
324 return code == base_code;
325 } else {
326 // A base register with low bits of 0x05 (rbp or r13) and mod = 0 means
327 // no base register.
328 if (base_code == rbp.code() && ((buf_[0] & 0xC0) == 0)) return false;
329 base_code |= ((rex_ & 0x01) << 3);
330 return code == base_code;
331 }
332}
333
334
Steve Blocka7e24c12009-10-30 11:49:00 +0000335// -----------------------------------------------------------------------------
Andrei Popescu31002712010-02-23 13:46:05 +0000336// Implementation of Assembler.
Steve Blocka7e24c12009-10-30 11:49:00 +0000337
338#ifdef GENERATED_CODE_COVERAGE
339static void InitCoverageLog();
340#endif
341
Steve Block3ce2e202009-11-05 08:53:23 +0000342Assembler::Assembler(void* buffer, int buffer_size)
Steve Block44f0eee2011-05-26 01:26:41 +0100343 : AssemblerBase(Isolate::Current()),
344 code_targets_(100),
345 positions_recorder_(this),
346 emit_debug_code_(FLAG_debug_code) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000347 if (buffer == NULL) {
Andrei Popescu31002712010-02-23 13:46:05 +0000348 // Do our own buffer management.
Steve Blocka7e24c12009-10-30 11:49:00 +0000349 if (buffer_size <= kMinimalBufferSize) {
350 buffer_size = kMinimalBufferSize;
351
Steve Block44f0eee2011-05-26 01:26:41 +0100352 if (isolate()->assembler_spare_buffer() != NULL) {
353 buffer = isolate()->assembler_spare_buffer();
354 isolate()->set_assembler_spare_buffer(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000355 }
356 }
357 if (buffer == NULL) {
358 buffer_ = NewArray<byte>(buffer_size);
359 } else {
360 buffer_ = static_cast<byte*>(buffer);
361 }
362 buffer_size_ = buffer_size;
363 own_buffer_ = true;
364 } else {
Andrei Popescu31002712010-02-23 13:46:05 +0000365 // Use externally provided buffer instead.
Steve Blocka7e24c12009-10-30 11:49:00 +0000366 ASSERT(buffer_size > 0);
367 buffer_ = static_cast<byte*>(buffer);
368 buffer_size_ = buffer_size;
369 own_buffer_ = false;
370 }
371
372 // Clear the buffer in debug mode unless it was provided by the
373 // caller in which case we can't be sure it's okay to overwrite
374 // existing code in it.
375#ifdef DEBUG
376 if (own_buffer_) {
377 memset(buffer_, 0xCC, buffer_size); // int3
378 }
379#endif
380
Andrei Popescu31002712010-02-23 13:46:05 +0000381 // Setup buffer pointers.
Steve Blocka7e24c12009-10-30 11:49:00 +0000382 ASSERT(buffer_ != NULL);
383 pc_ = buffer_;
384 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
385
386 last_pc_ = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800387
Steve Blocka7e24c12009-10-30 11:49:00 +0000388#ifdef GENERATED_CODE_COVERAGE
389 InitCoverageLog();
390#endif
391}
392
393
394Assembler::~Assembler() {
395 if (own_buffer_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100396 if (isolate()->assembler_spare_buffer() == NULL &&
397 buffer_size_ == kMinimalBufferSize) {
398 isolate()->set_assembler_spare_buffer(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000399 } else {
400 DeleteArray(buffer_);
401 }
402 }
403}
404
405
406void Assembler::GetCode(CodeDesc* desc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000407 // Finalize code (at this point overflow() may be true, but the gap ensures
408 // that we are still not overlapping instructions and relocation info).
409 ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap.
410 // Setup code descriptor.
Steve Blocka7e24c12009-10-30 11:49:00 +0000411 desc->buffer = buffer_;
412 desc->buffer_size = buffer_size_;
413 desc->instr_size = pc_offset();
414 ASSERT(desc->instr_size > 0); // Zero-size code objects upset the system.
Steve Blockd0582a62009-12-15 09:54:21 +0000415 desc->reloc_size =
416 static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos());
Steve Blocka7e24c12009-10-30 11:49:00 +0000417 desc->origin = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000418}
419
420
421void Assembler::Align(int m) {
422 ASSERT(IsPowerOf2(m));
Steve Block8defd9f2010-07-08 12:39:36 +0100423 int delta = (m - (pc_offset() & (m - 1))) & (m - 1);
424 while (delta >= 9) {
425 nop(9);
426 delta -= 9;
427 }
428 if (delta > 0) {
429 nop(delta);
Steve Blocka7e24c12009-10-30 11:49:00 +0000430 }
431}
432
433
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100434void Assembler::CodeTargetAlign() {
435 Align(16); // Preferred alignment of jump targets on x64.
436}
437
438
Steve Blocka7e24c12009-10-30 11:49:00 +0000439void Assembler::bind_to(Label* L, int pos) {
440 ASSERT(!L->is_bound()); // Label may only be bound once.
441 last_pc_ = NULL;
442 ASSERT(0 <= pos && pos <= pc_offset()); // Position must be valid.
443 if (L->is_linked()) {
444 int current = L->pos();
445 int next = long_at(current);
446 while (next != current) {
Andrei Popescu31002712010-02-23 13:46:05 +0000447 // Relative address, relative to point after address.
Steve Blocka7e24c12009-10-30 11:49:00 +0000448 int imm32 = pos - (current + sizeof(int32_t));
449 long_at_put(current, imm32);
450 current = next;
451 next = long_at(next);
452 }
453 // Fix up last fixup on linked list.
454 int last_imm32 = pos - (current + sizeof(int32_t));
455 long_at_put(current, last_imm32);
456 }
457 L->bind_to(pos);
458}
459
460
461void Assembler::bind(Label* L) {
462 bind_to(L, pc_offset());
463}
464
465
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100466void Assembler::bind(NearLabel* L) {
467 ASSERT(!L->is_bound());
468 last_pc_ = NULL;
469 while (L->unresolved_branches_ > 0) {
470 int branch_pos = L->unresolved_positions_[L->unresolved_branches_ - 1];
471 int disp = pc_offset() - branch_pos;
472 ASSERT(is_int8(disp));
473 set_byte_at(branch_pos - sizeof(int8_t), disp);
474 L->unresolved_branches_--;
475 }
476 L->bind_to(pc_offset());
477}
478
479
Steve Blocka7e24c12009-10-30 11:49:00 +0000480void Assembler::GrowBuffer() {
Andrei Popescu31002712010-02-23 13:46:05 +0000481 ASSERT(buffer_overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +0000482 if (!own_buffer_) FATAL("external code buffer is too small");
483
Andrei Popescu31002712010-02-23 13:46:05 +0000484 // Compute new buffer size.
Steve Blocka7e24c12009-10-30 11:49:00 +0000485 CodeDesc desc; // the new buffer
486 if (buffer_size_ < 4*KB) {
487 desc.buffer_size = 4*KB;
488 } else {
489 desc.buffer_size = 2*buffer_size_;
490 }
491 // Some internal data structures overflow for very large buffers,
492 // they must ensure that kMaximalBufferSize is not too large.
493 if ((desc.buffer_size > kMaximalBufferSize) ||
Steve Block44f0eee2011-05-26 01:26:41 +0100494 (desc.buffer_size > HEAP->MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000495 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
496 }
497
Andrei Popescu31002712010-02-23 13:46:05 +0000498 // Setup new buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +0000499 desc.buffer = NewArray<byte>(desc.buffer_size);
500 desc.instr_size = pc_offset();
Steve Blockd0582a62009-12-15 09:54:21 +0000501 desc.reloc_size =
502 static_cast<int>((buffer_ + buffer_size_) - (reloc_info_writer.pos()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000503
504 // Clear the buffer in debug mode. Use 'int3' instructions to make
505 // sure to get into problems if we ever run uninitialized code.
506#ifdef DEBUG
507 memset(desc.buffer, 0xCC, desc.buffer_size);
508#endif
509
Andrei Popescu31002712010-02-23 13:46:05 +0000510 // Copy the data.
Steve Blocka7e24c12009-10-30 11:49:00 +0000511 intptr_t pc_delta = desc.buffer - buffer_;
512 intptr_t rc_delta = (desc.buffer + desc.buffer_size) -
513 (buffer_ + buffer_size_);
514 memmove(desc.buffer, buffer_, desc.instr_size);
515 memmove(rc_delta + reloc_info_writer.pos(),
516 reloc_info_writer.pos(), desc.reloc_size);
517
Andrei Popescu31002712010-02-23 13:46:05 +0000518 // Switch buffers.
Steve Block44f0eee2011-05-26 01:26:41 +0100519 if (isolate()->assembler_spare_buffer() == NULL &&
520 buffer_size_ == kMinimalBufferSize) {
521 isolate()->set_assembler_spare_buffer(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000522 } else {
523 DeleteArray(buffer_);
524 }
525 buffer_ = desc.buffer;
526 buffer_size_ = desc.buffer_size;
527 pc_ += pc_delta;
528 if (last_pc_ != NULL) {
529 last_pc_ += pc_delta;
530 }
531 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
532 reloc_info_writer.last_pc() + pc_delta);
533
Andrei Popescu31002712010-02-23 13:46:05 +0000534 // Relocate runtime entries.
Steve Blocka7e24c12009-10-30 11:49:00 +0000535 for (RelocIterator it(desc); !it.done(); it.next()) {
536 RelocInfo::Mode rmode = it.rinfo()->rmode();
537 if (rmode == RelocInfo::INTERNAL_REFERENCE) {
538 intptr_t* p = reinterpret_cast<intptr_t*>(it.rinfo()->pc());
539 if (*p != 0) { // 0 means uninitialized.
540 *p += pc_delta;
541 }
542 }
543 }
544
545 ASSERT(!buffer_overflow());
546}
547
548
549void Assembler::emit_operand(int code, const Operand& adr) {
550 ASSERT(is_uint3(code));
551 const unsigned length = adr.len_;
552 ASSERT(length > 0);
553
554 // Emit updated ModR/M byte containing the given register.
555 ASSERT((adr.buf_[0] & 0x38) == 0);
556 pc_[0] = adr.buf_[0] | code << 3;
557
558 // Emit the rest of the encoded operand.
559 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
560 pc_ += length;
561}
562
563
Andrei Popescu31002712010-02-23 13:46:05 +0000564// Assembler Instruction implementations.
Steve Blocka7e24c12009-10-30 11:49:00 +0000565
566void Assembler::arithmetic_op(byte opcode, Register reg, const Operand& op) {
567 EnsureSpace ensure_space(this);
568 last_pc_ = pc_;
569 emit_rex_64(reg, op);
570 emit(opcode);
571 emit_operand(reg, op);
572}
573
574
575void Assembler::arithmetic_op(byte opcode, Register reg, Register rm_reg) {
576 EnsureSpace ensure_space(this);
577 last_pc_ = pc_;
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);
594 last_pc_ = pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +0100595 ASSERT((opcode & 0xC6) == 2);
596 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
597 // Swap reg and rm_reg and change opcode operand order.
598 emit(0x66);
599 emit_optional_rex_32(rm_reg, reg);
600 emit(opcode ^ 0x02);
601 emit_modrm(rm_reg, reg);
602 } else {
603 emit(0x66);
604 emit_optional_rex_32(reg, rm_reg);
605 emit(opcode);
606 emit_modrm(reg, rm_reg);
607 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000608}
609
610
611void Assembler::arithmetic_op_16(byte opcode,
612 Register reg,
613 const Operand& rm_reg) {
614 EnsureSpace ensure_space(this);
615 last_pc_ = pc_;
616 emit(0x66);
617 emit_optional_rex_32(reg, rm_reg);
618 emit(opcode);
619 emit_operand(reg, rm_reg);
620}
621
622
623void Assembler::arithmetic_op_32(byte opcode, Register reg, Register rm_reg) {
624 EnsureSpace ensure_space(this);
625 last_pc_ = pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +0100626 ASSERT((opcode & 0xC6) == 2);
627 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
628 // Swap reg and rm_reg and change opcode operand order.
629 emit_optional_rex_32(rm_reg, reg);
630 emit(opcode ^ 0x02); // E.g. 0x03 -> 0x01 for ADD.
631 emit_modrm(rm_reg, reg);
632 } else {
633 emit_optional_rex_32(reg, rm_reg);
634 emit(opcode);
635 emit_modrm(reg, rm_reg);
636 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000637}
638
639
640void Assembler::arithmetic_op_32(byte opcode,
641 Register reg,
642 const Operand& rm_reg) {
643 EnsureSpace ensure_space(this);
644 last_pc_ = pc_;
645 emit_optional_rex_32(reg, rm_reg);
646 emit(opcode);
647 emit_operand(reg, rm_reg);
648}
649
650
651void Assembler::immediate_arithmetic_op(byte subcode,
652 Register dst,
653 Immediate src) {
654 EnsureSpace ensure_space(this);
655 last_pc_ = pc_;
656 emit_rex_64(dst);
657 if (is_int8(src.value_)) {
658 emit(0x83);
659 emit_modrm(subcode, dst);
660 emit(src.value_);
661 } else if (dst.is(rax)) {
662 emit(0x05 | (subcode << 3));
663 emitl(src.value_);
664 } else {
665 emit(0x81);
666 emit_modrm(subcode, dst);
667 emitl(src.value_);
668 }
669}
670
671void Assembler::immediate_arithmetic_op(byte subcode,
672 const Operand& dst,
673 Immediate src) {
674 EnsureSpace ensure_space(this);
675 last_pc_ = pc_;
676 emit_rex_64(dst);
677 if (is_int8(src.value_)) {
678 emit(0x83);
679 emit_operand(subcode, dst);
680 emit(src.value_);
681 } else {
682 emit(0x81);
683 emit_operand(subcode, dst);
684 emitl(src.value_);
685 }
686}
687
688
689void Assembler::immediate_arithmetic_op_16(byte subcode,
690 Register dst,
691 Immediate src) {
692 EnsureSpace ensure_space(this);
693 last_pc_ = pc_;
694 emit(0x66); // Operand size override prefix.
695 emit_optional_rex_32(dst);
696 if (is_int8(src.value_)) {
697 emit(0x83);
698 emit_modrm(subcode, dst);
699 emit(src.value_);
700 } else if (dst.is(rax)) {
701 emit(0x05 | (subcode << 3));
Steve Block3ce2e202009-11-05 08:53:23 +0000702 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000703 } else {
704 emit(0x81);
705 emit_modrm(subcode, dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000706 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000707 }
708}
709
710
711void Assembler::immediate_arithmetic_op_16(byte subcode,
712 const Operand& dst,
713 Immediate src) {
714 EnsureSpace ensure_space(this);
715 last_pc_ = pc_;
716 emit(0x66); // Operand size override prefix.
717 emit_optional_rex_32(dst);
718 if (is_int8(src.value_)) {
719 emit(0x83);
720 emit_operand(subcode, dst);
721 emit(src.value_);
722 } else {
723 emit(0x81);
724 emit_operand(subcode, dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000725 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000726 }
727}
728
729
730void Assembler::immediate_arithmetic_op_32(byte subcode,
731 Register dst,
732 Immediate src) {
733 EnsureSpace ensure_space(this);
734 last_pc_ = pc_;
735 emit_optional_rex_32(dst);
736 if (is_int8(src.value_)) {
737 emit(0x83);
738 emit_modrm(subcode, dst);
739 emit(src.value_);
740 } else if (dst.is(rax)) {
741 emit(0x05 | (subcode << 3));
742 emitl(src.value_);
743 } else {
744 emit(0x81);
745 emit_modrm(subcode, dst);
746 emitl(src.value_);
747 }
748}
749
750
751void Assembler::immediate_arithmetic_op_32(byte subcode,
752 const Operand& dst,
753 Immediate src) {
754 EnsureSpace ensure_space(this);
755 last_pc_ = pc_;
756 emit_optional_rex_32(dst);
757 if (is_int8(src.value_)) {
758 emit(0x83);
759 emit_operand(subcode, dst);
760 emit(src.value_);
761 } else {
762 emit(0x81);
763 emit_operand(subcode, dst);
764 emitl(src.value_);
765 }
766}
767
768
769void Assembler::immediate_arithmetic_op_8(byte subcode,
770 const Operand& dst,
771 Immediate src) {
772 EnsureSpace ensure_space(this);
773 last_pc_ = pc_;
774 emit_optional_rex_32(dst);
775 ASSERT(is_int8(src.value_) || is_uint8(src.value_));
776 emit(0x80);
777 emit_operand(subcode, dst);
778 emit(src.value_);
779}
780
781
782void Assembler::immediate_arithmetic_op_8(byte subcode,
783 Register dst,
784 Immediate src) {
785 EnsureSpace ensure_space(this);
786 last_pc_ = pc_;
787 if (dst.code() > 3) {
788 // Use 64-bit mode byte registers.
789 emit_rex_64(dst);
790 }
791 ASSERT(is_int8(src.value_) || is_uint8(src.value_));
792 emit(0x80);
793 emit_modrm(subcode, dst);
794 emit(src.value_);
795}
796
797
798void Assembler::shift(Register dst, Immediate shift_amount, int subcode) {
799 EnsureSpace ensure_space(this);
800 last_pc_ = pc_;
801 ASSERT(is_uint6(shift_amount.value_)); // illegal shift count
802 if (shift_amount.value_ == 1) {
803 emit_rex_64(dst);
804 emit(0xD1);
805 emit_modrm(subcode, dst);
806 } else {
807 emit_rex_64(dst);
808 emit(0xC1);
809 emit_modrm(subcode, dst);
810 emit(shift_amount.value_);
811 }
812}
813
814
815void Assembler::shift(Register dst, int subcode) {
816 EnsureSpace ensure_space(this);
817 last_pc_ = pc_;
818 emit_rex_64(dst);
819 emit(0xD3);
820 emit_modrm(subcode, dst);
821}
822
823
824void Assembler::shift_32(Register dst, int subcode) {
825 EnsureSpace ensure_space(this);
826 last_pc_ = pc_;
827 emit_optional_rex_32(dst);
828 emit(0xD3);
829 emit_modrm(subcode, dst);
830}
831
832
833void Assembler::shift_32(Register dst, Immediate shift_amount, int subcode) {
834 EnsureSpace ensure_space(this);
835 last_pc_ = pc_;
Steve Block3ce2e202009-11-05 08:53:23 +0000836 ASSERT(is_uint5(shift_amount.value_)); // illegal shift count
Steve Blocka7e24c12009-10-30 11:49:00 +0000837 if (shift_amount.value_ == 1) {
838 emit_optional_rex_32(dst);
839 emit(0xD1);
840 emit_modrm(subcode, dst);
841 } else {
842 emit_optional_rex_32(dst);
843 emit(0xC1);
844 emit_modrm(subcode, dst);
845 emit(shift_amount.value_);
846 }
847}
848
849
850void Assembler::bt(const Operand& dst, Register src) {
851 EnsureSpace ensure_space(this);
852 last_pc_ = pc_;
853 emit_rex_64(src, dst);
854 emit(0x0F);
855 emit(0xA3);
856 emit_operand(src, dst);
857}
858
859
860void Assembler::bts(const Operand& dst, Register src) {
861 EnsureSpace ensure_space(this);
862 last_pc_ = pc_;
863 emit_rex_64(src, dst);
864 emit(0x0F);
865 emit(0xAB);
866 emit_operand(src, dst);
867}
868
869
870void Assembler::call(Label* L) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100871 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000872 EnsureSpace ensure_space(this);
873 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000874 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +0000875 emit(0xE8);
876 if (L->is_bound()) {
877 int offset = L->pos() - pc_offset() - sizeof(int32_t);
878 ASSERT(offset <= 0);
879 emitl(offset);
880 } else if (L->is_linked()) {
881 emitl(L->pos());
882 L->link_to(pc_offset() - sizeof(int32_t));
883 } else {
884 ASSERT(L->is_unused());
885 int32_t current = pc_offset();
886 emitl(current);
887 L->link_to(current);
888 }
889}
890
891
Steve Block3ce2e202009-11-05 08:53:23 +0000892void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800893 positions_recorder()->WriteRecordedPositions();
Steve Block3ce2e202009-11-05 08:53:23 +0000894 EnsureSpace ensure_space(this);
895 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000896 // 1110 1000 #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +0000897 emit(0xE8);
898 emit_code_target(target, rmode);
899}
900
901
Steve Blocka7e24c12009-10-30 11:49:00 +0000902void Assembler::call(Register adr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100903 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000904 EnsureSpace ensure_space(this);
905 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000906 // Opcode: FF /2 r64.
Steve Block8defd9f2010-07-08 12:39:36 +0100907 emit_optional_rex_32(adr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000908 emit(0xFF);
909 emit_modrm(0x2, adr);
910}
911
912
913void Assembler::call(const Operand& op) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100914 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000915 EnsureSpace ensure_space(this);
916 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000917 // Opcode: FF /2 m64.
Steve Block8defd9f2010-07-08 12:39:36 +0100918 emit_optional_rex_32(op);
Steve Blocka7e24c12009-10-30 11:49:00 +0000919 emit(0xFF);
Steve Block8defd9f2010-07-08 12:39:36 +0100920 emit_operand(0x2, op);
Steve Blocka7e24c12009-10-30 11:49:00 +0000921}
922
923
Steve Block1e0659c2011-05-24 12:43:12 +0100924// Calls directly to the given address using a relative offset.
925// Should only ever be used in Code objects for calls within the
926// same Code object. Should not be used when generating new code (use labels),
927// but only when patching existing code.
928void Assembler::call(Address target) {
929 positions_recorder()->WriteRecordedPositions();
930 EnsureSpace ensure_space(this);
931 last_pc_ = pc_;
932 // 1110 1000 #32-bit disp.
933 emit(0xE8);
934 Address source = pc_ + 4;
935 intptr_t displacement = target - source;
936 ASSERT(is_int32(displacement));
937 emitl(static_cast<int32_t>(displacement));
938}
939
940
Steve Block3ce2e202009-11-05 08:53:23 +0000941void Assembler::clc() {
942 EnsureSpace ensure_space(this);
943 last_pc_ = pc_;
944 emit(0xF8);
945}
946
Steve Block44f0eee2011-05-26 01:26:41 +0100947void Assembler::cld() {
948 EnsureSpace ensure_space(this);
949 last_pc_ = pc_;
950 emit(0xFC);
951}
952
Steve Blocka7e24c12009-10-30 11:49:00 +0000953void Assembler::cdq() {
954 EnsureSpace ensure_space(this);
955 last_pc_ = pc_;
956 emit(0x99);
957}
958
959
960void Assembler::cmovq(Condition cc, Register dst, Register src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000961 if (cc == always) {
962 movq(dst, src);
963 } else if (cc == never) {
964 return;
965 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000966 // No need to check CpuInfo for CMOV support, it's a required part of the
967 // 64-bit architecture.
968 ASSERT(cc >= 0); // Use mov for unconditional moves.
969 EnsureSpace ensure_space(this);
970 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000971 // Opcode: REX.W 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000972 emit_rex_64(dst, src);
973 emit(0x0f);
974 emit(0x40 + cc);
975 emit_modrm(dst, src);
976}
977
978
979void Assembler::cmovq(Condition cc, Register dst, const Operand& src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000980 if (cc == always) {
981 movq(dst, src);
982 } else if (cc == never) {
983 return;
984 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000985 ASSERT(cc >= 0);
986 EnsureSpace ensure_space(this);
987 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000988 // Opcode: REX.W 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000989 emit_rex_64(dst, src);
990 emit(0x0f);
991 emit(0x40 + cc);
992 emit_operand(dst, src);
993}
994
995
996void Assembler::cmovl(Condition cc, Register dst, Register src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000997 if (cc == always) {
998 movl(dst, src);
999 } else if (cc == never) {
1000 return;
1001 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001002 ASSERT(cc >= 0);
1003 EnsureSpace ensure_space(this);
1004 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +00001005 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +00001006 emit_optional_rex_32(dst, src);
1007 emit(0x0f);
1008 emit(0x40 + cc);
1009 emit_modrm(dst, src);
1010}
1011
1012
1013void Assembler::cmovl(Condition cc, Register dst, const Operand& src) {
Steve Block3ce2e202009-11-05 08:53:23 +00001014 if (cc == always) {
1015 movl(dst, src);
1016 } else if (cc == never) {
1017 return;
1018 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001019 ASSERT(cc >= 0);
1020 EnsureSpace ensure_space(this);
1021 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +00001022 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +00001023 emit_optional_rex_32(dst, src);
1024 emit(0x0f);
1025 emit(0x40 + cc);
1026 emit_operand(dst, src);
1027}
1028
1029
1030void Assembler::cmpb_al(Immediate imm8) {
1031 ASSERT(is_int8(imm8.value_) || is_uint8(imm8.value_));
1032 EnsureSpace ensure_space(this);
1033 last_pc_ = pc_;
1034 emit(0x3c);
1035 emit(imm8.value_);
1036}
1037
1038
1039void Assembler::cpuid() {
Steve Block44f0eee2011-05-26 01:26:41 +01001040 ASSERT(isolate()->cpu_features()->IsEnabled(CPUID));
Steve Blocka7e24c12009-10-30 11:49:00 +00001041 EnsureSpace ensure_space(this);
1042 last_pc_ = pc_;
1043 emit(0x0F);
1044 emit(0xA2);
1045}
1046
1047
1048void Assembler::cqo() {
1049 EnsureSpace ensure_space(this);
1050 last_pc_ = pc_;
1051 emit_rex_64();
1052 emit(0x99);
1053}
1054
1055
1056void Assembler::decq(Register dst) {
1057 EnsureSpace ensure_space(this);
1058 last_pc_ = pc_;
1059 emit_rex_64(dst);
1060 emit(0xFF);
1061 emit_modrm(0x1, dst);
1062}
1063
1064
1065void Assembler::decq(const Operand& dst) {
1066 EnsureSpace ensure_space(this);
1067 last_pc_ = pc_;
1068 emit_rex_64(dst);
1069 emit(0xFF);
1070 emit_operand(1, dst);
1071}
1072
1073
1074void Assembler::decl(Register dst) {
1075 EnsureSpace ensure_space(this);
1076 last_pc_ = pc_;
1077 emit_optional_rex_32(dst);
1078 emit(0xFF);
1079 emit_modrm(0x1, dst);
1080}
1081
1082
1083void Assembler::decl(const Operand& dst) {
1084 EnsureSpace ensure_space(this);
1085 last_pc_ = pc_;
1086 emit_optional_rex_32(dst);
1087 emit(0xFF);
1088 emit_operand(1, dst);
1089}
1090
1091
Steve Block3ce2e202009-11-05 08:53:23 +00001092void Assembler::decb(Register dst) {
1093 EnsureSpace ensure_space(this);
1094 last_pc_ = pc_;
1095 if (dst.code() > 3) {
1096 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1097 emit_rex_32(dst);
1098 }
1099 emit(0xFE);
1100 emit_modrm(0x1, dst);
1101}
1102
1103
1104void Assembler::decb(const Operand& dst) {
1105 EnsureSpace ensure_space(this);
1106 last_pc_ = pc_;
1107 emit_optional_rex_32(dst);
1108 emit(0xFE);
1109 emit_operand(1, dst);
1110}
1111
1112
Steve Blocka7e24c12009-10-30 11:49:00 +00001113void Assembler::enter(Immediate size) {
1114 EnsureSpace ensure_space(this);
1115 last_pc_ = pc_;
1116 emit(0xC8);
1117 emitw(size.value_); // 16 bit operand, always.
1118 emit(0);
1119}
1120
1121
1122void Assembler::hlt() {
1123 EnsureSpace ensure_space(this);
1124 last_pc_ = pc_;
1125 emit(0xF4);
1126}
1127
1128
1129void Assembler::idivq(Register src) {
1130 EnsureSpace ensure_space(this);
1131 last_pc_ = pc_;
1132 emit_rex_64(src);
1133 emit(0xF7);
1134 emit_modrm(0x7, src);
1135}
1136
1137
1138void Assembler::idivl(Register src) {
1139 EnsureSpace ensure_space(this);
1140 last_pc_ = pc_;
1141 emit_optional_rex_32(src);
1142 emit(0xF7);
1143 emit_modrm(0x7, src);
1144}
1145
1146
1147void Assembler::imul(Register src) {
1148 EnsureSpace ensure_space(this);
1149 last_pc_ = pc_;
1150 emit_rex_64(src);
1151 emit(0xF7);
1152 emit_modrm(0x5, src);
1153}
1154
1155
1156void Assembler::imul(Register dst, Register src) {
1157 EnsureSpace ensure_space(this);
1158 last_pc_ = pc_;
1159 emit_rex_64(dst, src);
1160 emit(0x0F);
1161 emit(0xAF);
1162 emit_modrm(dst, src);
1163}
1164
1165
1166void Assembler::imul(Register dst, const Operand& src) {
1167 EnsureSpace ensure_space(this);
1168 last_pc_ = pc_;
1169 emit_rex_64(dst, src);
1170 emit(0x0F);
1171 emit(0xAF);
1172 emit_operand(dst, src);
1173}
1174
1175
1176void Assembler::imul(Register dst, Register src, Immediate imm) {
1177 EnsureSpace ensure_space(this);
1178 last_pc_ = pc_;
1179 emit_rex_64(dst, src);
1180 if (is_int8(imm.value_)) {
1181 emit(0x6B);
1182 emit_modrm(dst, src);
1183 emit(imm.value_);
1184 } else {
1185 emit(0x69);
1186 emit_modrm(dst, src);
1187 emitl(imm.value_);
1188 }
1189}
1190
1191
1192void Assembler::imull(Register dst, Register src) {
1193 EnsureSpace ensure_space(this);
1194 last_pc_ = pc_;
1195 emit_optional_rex_32(dst, src);
1196 emit(0x0F);
1197 emit(0xAF);
1198 emit_modrm(dst, src);
1199}
1200
1201
Steve Block1e0659c2011-05-24 12:43:12 +01001202void Assembler::imull(Register dst, const Operand& src) {
1203 EnsureSpace ensure_space(this);
1204 last_pc_ = pc_;
1205 emit_optional_rex_32(dst, src);
1206 emit(0x0F);
1207 emit(0xAF);
1208 emit_operand(dst, src);
1209}
1210
1211
Steve Block6ded16b2010-05-10 14:33:55 +01001212void Assembler::imull(Register dst, Register src, Immediate imm) {
1213 EnsureSpace ensure_space(this);
1214 last_pc_ = pc_;
1215 emit_optional_rex_32(dst, src);
1216 if (is_int8(imm.value_)) {
1217 emit(0x6B);
1218 emit_modrm(dst, src);
1219 emit(imm.value_);
1220 } else {
1221 emit(0x69);
1222 emit_modrm(dst, src);
1223 emitl(imm.value_);
1224 }
1225}
1226
1227
Steve Blocka7e24c12009-10-30 11:49:00 +00001228void Assembler::incq(Register dst) {
1229 EnsureSpace ensure_space(this);
1230 last_pc_ = pc_;
1231 emit_rex_64(dst);
1232 emit(0xFF);
1233 emit_modrm(0x0, dst);
1234}
1235
1236
1237void Assembler::incq(const Operand& dst) {
1238 EnsureSpace ensure_space(this);
1239 last_pc_ = pc_;
1240 emit_rex_64(dst);
1241 emit(0xFF);
1242 emit_operand(0, dst);
1243}
1244
1245
1246void Assembler::incl(const Operand& dst) {
1247 EnsureSpace ensure_space(this);
1248 last_pc_ = pc_;
1249 emit_optional_rex_32(dst);
1250 emit(0xFF);
1251 emit_operand(0, dst);
1252}
1253
1254
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001255void Assembler::incl(Register dst) {
1256 EnsureSpace ensure_space(this);
1257 last_pc_ = pc_;
1258 emit_optional_rex_32(dst);
1259 emit(0xFF);
1260 emit_modrm(0, dst);
1261}
1262
1263
Steve Blocka7e24c12009-10-30 11:49:00 +00001264void Assembler::int3() {
1265 EnsureSpace ensure_space(this);
1266 last_pc_ = pc_;
1267 emit(0xCC);
1268}
1269
1270
1271void Assembler::j(Condition cc, Label* L) {
Steve Block3ce2e202009-11-05 08:53:23 +00001272 if (cc == always) {
1273 jmp(L);
1274 return;
1275 } else if (cc == never) {
1276 return;
1277 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001278 EnsureSpace ensure_space(this);
1279 last_pc_ = pc_;
1280 ASSERT(is_uint4(cc));
1281 if (L->is_bound()) {
1282 const int short_size = 2;
1283 const int long_size = 6;
1284 int offs = L->pos() - pc_offset();
1285 ASSERT(offs <= 0);
1286 if (is_int8(offs - short_size)) {
Andrei Popescu31002712010-02-23 13:46:05 +00001287 // 0111 tttn #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001288 emit(0x70 | cc);
1289 emit((offs - short_size) & 0xFF);
1290 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001291 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001292 emit(0x0F);
1293 emit(0x80 | cc);
1294 emitl(offs - long_size);
1295 }
1296 } else if (L->is_linked()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001297 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001298 emit(0x0F);
1299 emit(0x80 | cc);
1300 emitl(L->pos());
1301 L->link_to(pc_offset() - sizeof(int32_t));
1302 } else {
1303 ASSERT(L->is_unused());
1304 emit(0x0F);
1305 emit(0x80 | cc);
1306 int32_t current = pc_offset();
1307 emitl(current);
1308 L->link_to(current);
1309 }
1310}
1311
1312
Steve Block3ce2e202009-11-05 08:53:23 +00001313void Assembler::j(Condition cc,
1314 Handle<Code> target,
1315 RelocInfo::Mode rmode) {
1316 EnsureSpace ensure_space(this);
1317 last_pc_ = pc_;
1318 ASSERT(is_uint4(cc));
Andrei Popescu31002712010-02-23 13:46:05 +00001319 // 0000 1111 1000 tttn #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +00001320 emit(0x0F);
1321 emit(0x80 | cc);
1322 emit_code_target(target, rmode);
1323}
1324
1325
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001326void Assembler::j(Condition cc, NearLabel* L, Hint hint) {
1327 EnsureSpace ensure_space(this);
1328 last_pc_ = pc_;
1329 ASSERT(0 <= cc && cc < 16);
1330 if (FLAG_emit_branch_hints && hint != no_hint) emit(hint);
1331 if (L->is_bound()) {
1332 const int short_size = 2;
1333 int offs = L->pos() - pc_offset();
1334 ASSERT(offs <= 0);
1335 ASSERT(is_int8(offs - short_size));
1336 // 0111 tttn #8-bit disp
1337 emit(0x70 | cc);
1338 emit((offs - short_size) & 0xFF);
1339 } else {
1340 emit(0x70 | cc);
1341 emit(0x00); // The displacement will be resolved later.
1342 L->link_to(pc_offset());
1343 }
1344}
1345
1346
Steve Blocka7e24c12009-10-30 11:49:00 +00001347void Assembler::jmp(Label* L) {
1348 EnsureSpace ensure_space(this);
1349 last_pc_ = pc_;
Steve Block6ded16b2010-05-10 14:33:55 +01001350 const int short_size = sizeof(int8_t);
1351 const int long_size = sizeof(int32_t);
Steve Blocka7e24c12009-10-30 11:49:00 +00001352 if (L->is_bound()) {
1353 int offs = L->pos() - pc_offset() - 1;
1354 ASSERT(offs <= 0);
Steve Block6ded16b2010-05-10 14:33:55 +01001355 if (is_int8(offs - short_size)) {
Andrei Popescu31002712010-02-23 13:46:05 +00001356 // 1110 1011 #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001357 emit(0xEB);
Steve Block6ded16b2010-05-10 14:33:55 +01001358 emit((offs - short_size) & 0xFF);
Steve Blocka7e24c12009-10-30 11:49:00 +00001359 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001360 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001361 emit(0xE9);
Steve Block6ded16b2010-05-10 14:33:55 +01001362 emitl(offs - long_size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001363 }
1364 } else if (L->is_linked()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001365 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001366 emit(0xE9);
1367 emitl(L->pos());
Steve Block6ded16b2010-05-10 14:33:55 +01001368 L->link_to(pc_offset() - long_size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001369 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001370 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001371 ASSERT(L->is_unused());
1372 emit(0xE9);
1373 int32_t current = pc_offset();
1374 emitl(current);
1375 L->link_to(current);
1376 }
1377}
1378
1379
Steve Block3ce2e202009-11-05 08:53:23 +00001380void Assembler::jmp(Handle<Code> target, RelocInfo::Mode rmode) {
1381 EnsureSpace ensure_space(this);
1382 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +00001383 // 1110 1001 #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +00001384 emit(0xE9);
1385 emit_code_target(target, rmode);
1386}
1387
1388
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001389void Assembler::jmp(NearLabel* L) {
1390 EnsureSpace ensure_space(this);
1391 last_pc_ = pc_;
1392 if (L->is_bound()) {
1393 const int short_size = sizeof(int8_t);
1394 int offs = L->pos() - pc_offset();
1395 ASSERT(offs <= 0);
1396 ASSERT(is_int8(offs - short_size));
1397 // 1110 1011 #8-bit disp.
1398 emit(0xEB);
1399 emit((offs - short_size) & 0xFF);
1400 } else {
1401 emit(0xEB);
1402 emit(0x00); // The displacement will be resolved later.
1403 L->link_to(pc_offset());
1404 }
1405}
1406
1407
Steve Blocka7e24c12009-10-30 11:49:00 +00001408void Assembler::jmp(Register target) {
1409 EnsureSpace ensure_space(this);
1410 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +00001411 // Opcode FF/4 r64.
Steve Block8defd9f2010-07-08 12:39:36 +01001412 emit_optional_rex_32(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001413 emit(0xFF);
1414 emit_modrm(0x4, target);
1415}
1416
1417
1418void Assembler::jmp(const Operand& src) {
1419 EnsureSpace ensure_space(this);
1420 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +00001421 // Opcode FF/4 m64.
Steve Blocka7e24c12009-10-30 11:49:00 +00001422 emit_optional_rex_32(src);
1423 emit(0xFF);
1424 emit_operand(0x4, src);
1425}
1426
1427
1428void Assembler::lea(Register dst, const Operand& src) {
1429 EnsureSpace ensure_space(this);
1430 last_pc_ = pc_;
1431 emit_rex_64(dst, src);
1432 emit(0x8D);
1433 emit_operand(dst, src);
1434}
1435
1436
Steve Block6ded16b2010-05-10 14:33:55 +01001437void Assembler::leal(Register dst, const Operand& src) {
1438 EnsureSpace ensure_space(this);
1439 last_pc_ = pc_;
1440 emit_optional_rex_32(dst, src);
1441 emit(0x8D);
1442 emit_operand(dst, src);
1443}
1444
1445
Steve Blocka7e24c12009-10-30 11:49:00 +00001446void Assembler::load_rax(void* value, RelocInfo::Mode mode) {
1447 EnsureSpace ensure_space(this);
1448 last_pc_ = pc_;
1449 emit(0x48); // REX.W
1450 emit(0xA1);
1451 emitq(reinterpret_cast<uintptr_t>(value), mode);
1452}
1453
1454
1455void Assembler::load_rax(ExternalReference ref) {
1456 load_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
1457}
1458
1459
1460void Assembler::leave() {
1461 EnsureSpace ensure_space(this);
1462 last_pc_ = pc_;
1463 emit(0xC9);
1464}
1465
1466
1467void Assembler::movb(Register dst, const Operand& src) {
1468 EnsureSpace ensure_space(this);
1469 last_pc_ = pc_;
1470 emit_rex_32(dst, src);
1471 emit(0x8A);
1472 emit_operand(dst, src);
1473}
1474
Steve Block6ded16b2010-05-10 14:33:55 +01001475
Steve Blocka7e24c12009-10-30 11:49:00 +00001476void Assembler::movb(Register dst, Immediate imm) {
1477 EnsureSpace ensure_space(this);
1478 last_pc_ = pc_;
1479 emit_rex_32(dst);
1480 emit(0xC6);
1481 emit_modrm(0x0, dst);
1482 emit(imm.value_);
1483}
1484
Steve Block6ded16b2010-05-10 14:33:55 +01001485
Steve Blocka7e24c12009-10-30 11:49:00 +00001486void Assembler::movb(const Operand& dst, Register src) {
1487 EnsureSpace ensure_space(this);
1488 last_pc_ = pc_;
1489 emit_rex_32(src, dst);
1490 emit(0x88);
1491 emit_operand(src, dst);
1492}
1493
Steve Block6ded16b2010-05-10 14:33:55 +01001494
Steve Block3ce2e202009-11-05 08:53:23 +00001495void Assembler::movw(const Operand& dst, Register src) {
1496 EnsureSpace ensure_space(this);
1497 last_pc_ = pc_;
1498 emit(0x66);
1499 emit_optional_rex_32(src, dst);
1500 emit(0x89);
1501 emit_operand(src, dst);
1502}
1503
Steve Block6ded16b2010-05-10 14:33:55 +01001504
Steve Blocka7e24c12009-10-30 11:49:00 +00001505void Assembler::movl(Register dst, const Operand& src) {
1506 EnsureSpace ensure_space(this);
1507 last_pc_ = pc_;
1508 emit_optional_rex_32(dst, src);
1509 emit(0x8B);
1510 emit_operand(dst, src);
1511}
1512
1513
1514void Assembler::movl(Register dst, Register src) {
1515 EnsureSpace ensure_space(this);
1516 last_pc_ = pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +01001517 if (src.low_bits() == 4) {
1518 emit_optional_rex_32(src, dst);
1519 emit(0x89);
1520 emit_modrm(src, dst);
1521 } else {
1522 emit_optional_rex_32(dst, src);
1523 emit(0x8B);
1524 emit_modrm(dst, src);
1525 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001526}
1527
1528
1529void Assembler::movl(const Operand& dst, Register src) {
1530 EnsureSpace ensure_space(this);
1531 last_pc_ = pc_;
1532 emit_optional_rex_32(src, dst);
1533 emit(0x89);
1534 emit_operand(src, dst);
1535}
1536
1537
1538void Assembler::movl(const Operand& dst, Immediate value) {
1539 EnsureSpace ensure_space(this);
1540 last_pc_ = pc_;
1541 emit_optional_rex_32(dst);
1542 emit(0xC7);
1543 emit_operand(0x0, dst);
1544 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates.
1545}
1546
1547
1548void Assembler::movl(Register dst, Immediate value) {
1549 EnsureSpace ensure_space(this);
1550 last_pc_ = pc_;
1551 emit_optional_rex_32(dst);
1552 emit(0xC7);
1553 emit_modrm(0x0, dst);
1554 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates.
1555}
1556
1557
1558void Assembler::movq(Register dst, const Operand& src) {
1559 EnsureSpace ensure_space(this);
1560 last_pc_ = pc_;
1561 emit_rex_64(dst, src);
1562 emit(0x8B);
1563 emit_operand(dst, src);
1564}
1565
1566
1567void Assembler::movq(Register dst, Register src) {
1568 EnsureSpace ensure_space(this);
1569 last_pc_ = pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +01001570 if (src.low_bits() == 4) {
1571 emit_rex_64(src, dst);
1572 emit(0x89);
1573 emit_modrm(src, dst);
1574 } else {
1575 emit_rex_64(dst, src);
1576 emit(0x8B);
1577 emit_modrm(dst, src);
1578 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001579}
1580
1581
1582void Assembler::movq(Register dst, Immediate value) {
1583 EnsureSpace ensure_space(this);
1584 last_pc_ = pc_;
1585 emit_rex_64(dst);
1586 emit(0xC7);
1587 emit_modrm(0x0, dst);
1588 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates.
1589}
1590
1591
1592void Assembler::movq(const Operand& dst, Register src) {
1593 EnsureSpace ensure_space(this);
1594 last_pc_ = pc_;
1595 emit_rex_64(src, dst);
1596 emit(0x89);
1597 emit_operand(src, dst);
1598}
1599
1600
1601void Assembler::movq(Register dst, void* value, RelocInfo::Mode rmode) {
1602 // This method must not be used with heap object references. The stored
1603 // address is not GC safe. Use the handle version instead.
1604 ASSERT(rmode > RelocInfo::LAST_GCED_ENUM);
1605 EnsureSpace ensure_space(this);
1606 last_pc_ = pc_;
1607 emit_rex_64(dst);
1608 emit(0xB8 | dst.low_bits());
1609 emitq(reinterpret_cast<uintptr_t>(value), rmode);
1610}
1611
1612
1613void Assembler::movq(Register dst, int64_t value, RelocInfo::Mode rmode) {
1614 // Non-relocatable values might not need a 64-bit representation.
1615 if (rmode == RelocInfo::NONE) {
1616 // Sadly, there is no zero or sign extending move for 8-bit immediates.
1617 if (is_int32(value)) {
1618 movq(dst, Immediate(static_cast<int32_t>(value)));
1619 return;
1620 } else if (is_uint32(value)) {
1621 movl(dst, Immediate(static_cast<int32_t>(value)));
1622 return;
1623 }
1624 // Value cannot be represented by 32 bits, so do a full 64 bit immediate
1625 // value.
1626 }
1627 EnsureSpace ensure_space(this);
1628 last_pc_ = pc_;
1629 emit_rex_64(dst);
1630 emit(0xB8 | dst.low_bits());
1631 emitq(value, rmode);
1632}
1633
1634
1635void Assembler::movq(Register dst, ExternalReference ref) {
Ben Murdochbb769b22010-08-11 14:56:33 +01001636 int64_t value = reinterpret_cast<int64_t>(ref.address());
1637 movq(dst, value, RelocInfo::EXTERNAL_REFERENCE);
Steve Blocka7e24c12009-10-30 11:49:00 +00001638}
1639
1640
1641void Assembler::movq(const Operand& dst, Immediate value) {
1642 EnsureSpace ensure_space(this);
1643 last_pc_ = pc_;
1644 emit_rex_64(dst);
1645 emit(0xC7);
1646 emit_operand(0, dst);
1647 emit(value);
1648}
1649
1650
Andrei Popescu31002712010-02-23 13:46:05 +00001651// Loads the ip-relative location of the src label into the target location
1652// (as a 32-bit offset sign extended to 64-bit).
Steve Blocka7e24c12009-10-30 11:49:00 +00001653void Assembler::movl(const Operand& dst, Label* src) {
1654 EnsureSpace ensure_space(this);
1655 last_pc_ = pc_;
1656 emit_optional_rex_32(dst);
1657 emit(0xC7);
1658 emit_operand(0, dst);
1659 if (src->is_bound()) {
1660 int offset = src->pos() - pc_offset() - sizeof(int32_t);
1661 ASSERT(offset <= 0);
1662 emitl(offset);
1663 } else if (src->is_linked()) {
1664 emitl(src->pos());
1665 src->link_to(pc_offset() - sizeof(int32_t));
1666 } else {
1667 ASSERT(src->is_unused());
1668 int32_t current = pc_offset();
1669 emitl(current);
1670 src->link_to(current);
1671 }
1672}
1673
1674
1675void Assembler::movq(Register dst, Handle<Object> value, RelocInfo::Mode mode) {
1676 // If there is no relocation info, emit the value of the handle efficiently
1677 // (possibly using less that 8 bytes for the value).
1678 if (mode == RelocInfo::NONE) {
1679 // There is no possible reason to store a heap pointer without relocation
1680 // info, so it must be a smi.
1681 ASSERT(value->IsSmi());
Steve Block3ce2e202009-11-05 08:53:23 +00001682 movq(dst, reinterpret_cast<int64_t>(*value), RelocInfo::NONE);
Steve Blocka7e24c12009-10-30 11:49:00 +00001683 } else {
1684 EnsureSpace ensure_space(this);
1685 last_pc_ = pc_;
1686 ASSERT(value->IsHeapObject());
Steve Block44f0eee2011-05-26 01:26:41 +01001687 ASSERT(!HEAP->InNewSpace(*value));
Steve Blocka7e24c12009-10-30 11:49:00 +00001688 emit_rex_64(dst);
1689 emit(0xB8 | dst.low_bits());
1690 emitq(reinterpret_cast<uintptr_t>(value.location()), mode);
1691 }
1692}
1693
1694
Steve Block3ce2e202009-11-05 08:53:23 +00001695void Assembler::movsxbq(Register dst, const Operand& src) {
1696 EnsureSpace ensure_space(this);
1697 last_pc_ = pc_;
Steve Block8defd9f2010-07-08 12:39:36 +01001698 emit_rex_64(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00001699 emit(0x0F);
1700 emit(0xBE);
1701 emit_operand(dst, src);
1702}
1703
1704
1705void Assembler::movsxwq(Register dst, const Operand& src) {
1706 EnsureSpace ensure_space(this);
1707 last_pc_ = pc_;
1708 emit_rex_64(dst, src);
1709 emit(0x0F);
1710 emit(0xBF);
1711 emit_operand(dst, src);
1712}
1713
1714
Steve Blocka7e24c12009-10-30 11:49:00 +00001715void Assembler::movsxlq(Register dst, Register src) {
1716 EnsureSpace ensure_space(this);
1717 last_pc_ = pc_;
1718 emit_rex_64(dst, src);
1719 emit(0x63);
1720 emit_modrm(dst, src);
1721}
1722
1723
1724void Assembler::movsxlq(Register dst, const Operand& src) {
1725 EnsureSpace ensure_space(this);
1726 last_pc_ = pc_;
1727 emit_rex_64(dst, src);
1728 emit(0x63);
1729 emit_operand(dst, src);
1730}
1731
1732
1733void Assembler::movzxbq(Register dst, const Operand& src) {
1734 EnsureSpace ensure_space(this);
1735 last_pc_ = pc_;
Steve Block8defd9f2010-07-08 12:39:36 +01001736 emit_optional_rex_32(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001737 emit(0x0F);
1738 emit(0xB6);
1739 emit_operand(dst, src);
1740}
1741
1742
1743void Assembler::movzxbl(Register dst, const Operand& src) {
1744 EnsureSpace ensure_space(this);
1745 last_pc_ = pc_;
1746 emit_optional_rex_32(dst, src);
1747 emit(0x0F);
1748 emit(0xB6);
1749 emit_operand(dst, src);
1750}
1751
1752
Steve Block3ce2e202009-11-05 08:53:23 +00001753void Assembler::movzxwq(Register dst, const Operand& src) {
1754 EnsureSpace ensure_space(this);
1755 last_pc_ = pc_;
Steve Block8defd9f2010-07-08 12:39:36 +01001756 emit_optional_rex_32(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00001757 emit(0x0F);
1758 emit(0xB7);
1759 emit_operand(dst, src);
1760}
1761
1762
Steve Blocka7e24c12009-10-30 11:49:00 +00001763void Assembler::movzxwl(Register dst, const Operand& src) {
1764 EnsureSpace ensure_space(this);
1765 last_pc_ = pc_;
1766 emit_optional_rex_32(dst, src);
1767 emit(0x0F);
1768 emit(0xB7);
1769 emit_operand(dst, src);
1770}
1771
1772
Leon Clarked91b9f72010-01-27 17:25:45 +00001773void Assembler::repmovsb() {
1774 EnsureSpace ensure_space(this);
1775 last_pc_ = pc_;
1776 emit(0xF3);
1777 emit(0xA4);
1778}
1779
1780
1781void Assembler::repmovsw() {
1782 EnsureSpace ensure_space(this);
1783 last_pc_ = pc_;
1784 emit(0x66); // Operand size override.
1785 emit(0xF3);
1786 emit(0xA4);
1787}
1788
1789
1790void Assembler::repmovsl() {
1791 EnsureSpace ensure_space(this);
1792 last_pc_ = pc_;
1793 emit(0xF3);
1794 emit(0xA5);
1795}
1796
1797
1798void Assembler::repmovsq() {
1799 EnsureSpace ensure_space(this);
1800 last_pc_ = pc_;
1801 emit(0xF3);
1802 emit_rex_64();
1803 emit(0xA5);
1804}
1805
1806
Steve Blocka7e24c12009-10-30 11:49:00 +00001807void Assembler::mul(Register src) {
1808 EnsureSpace ensure_space(this);
1809 last_pc_ = pc_;
1810 emit_rex_64(src);
1811 emit(0xF7);
1812 emit_modrm(0x4, src);
1813}
1814
1815
1816void Assembler::neg(Register dst) {
1817 EnsureSpace ensure_space(this);
1818 last_pc_ = pc_;
1819 emit_rex_64(dst);
1820 emit(0xF7);
1821 emit_modrm(0x3, dst);
1822}
1823
1824
1825void Assembler::negl(Register dst) {
1826 EnsureSpace ensure_space(this);
1827 last_pc_ = pc_;
1828 emit_optional_rex_32(dst);
1829 emit(0xF7);
1830 emit_modrm(0x3, dst);
1831}
1832
1833
1834void Assembler::neg(const Operand& dst) {
1835 EnsureSpace ensure_space(this);
1836 last_pc_ = pc_;
1837 emit_rex_64(dst);
1838 emit(0xF7);
1839 emit_operand(3, dst);
1840}
1841
1842
1843void Assembler::nop() {
1844 EnsureSpace ensure_space(this);
1845 last_pc_ = pc_;
1846 emit(0x90);
1847}
1848
1849
1850void Assembler::not_(Register dst) {
1851 EnsureSpace ensure_space(this);
1852 last_pc_ = pc_;
1853 emit_rex_64(dst);
1854 emit(0xF7);
1855 emit_modrm(0x2, dst);
1856}
1857
1858
1859void Assembler::not_(const Operand& dst) {
1860 EnsureSpace ensure_space(this);
1861 last_pc_ = pc_;
1862 emit_rex_64(dst);
1863 emit(0xF7);
1864 emit_operand(2, dst);
1865}
1866
1867
Steve Block6ded16b2010-05-10 14:33:55 +01001868void Assembler::notl(Register dst) {
1869 EnsureSpace ensure_space(this);
1870 last_pc_ = pc_;
1871 emit_optional_rex_32(dst);
1872 emit(0xF7);
1873 emit_modrm(0x2, dst);
1874}
1875
1876
Steve Blocka7e24c12009-10-30 11:49:00 +00001877void Assembler::nop(int n) {
1878 // The recommended muti-byte sequences of NOP instructions from the Intel 64
1879 // and IA-32 Architectures Software Developer's Manual.
1880 //
1881 // Length Assembly Byte Sequence
1882 // 2 bytes 66 NOP 66 90H
1883 // 3 bytes NOP DWORD ptr [EAX] 0F 1F 00H
1884 // 4 bytes NOP DWORD ptr [EAX + 00H] 0F 1F 40 00H
1885 // 5 bytes NOP DWORD ptr [EAX + EAX*1 + 00H] 0F 1F 44 00 00H
1886 // 6 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00H] 66 0F 1F 44 00 00H
1887 // 7 bytes NOP DWORD ptr [EAX + 00000000H] 0F 1F 80 00 00 00 00H
1888 // 8 bytes NOP DWORD ptr [EAX + EAX*1 + 00000000H] 0F 1F 84 00 00 00 00 00H
1889 // 9 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 66 0F 1F 84 00 00 00 00
1890 // 00000000H] 00H
1891
1892 ASSERT(1 <= n);
1893 ASSERT(n <= 9);
1894 EnsureSpace ensure_space(this);
1895 last_pc_ = pc_;
1896 switch (n) {
1897 case 1:
1898 emit(0x90);
1899 return;
1900 case 2:
1901 emit(0x66);
1902 emit(0x90);
1903 return;
1904 case 3:
1905 emit(0x0f);
1906 emit(0x1f);
1907 emit(0x00);
1908 return;
1909 case 4:
1910 emit(0x0f);
1911 emit(0x1f);
1912 emit(0x40);
1913 emit(0x00);
1914 return;
1915 case 5:
1916 emit(0x0f);
1917 emit(0x1f);
1918 emit(0x44);
1919 emit(0x00);
1920 emit(0x00);
1921 return;
1922 case 6:
1923 emit(0x66);
1924 emit(0x0f);
1925 emit(0x1f);
1926 emit(0x44);
1927 emit(0x00);
1928 emit(0x00);
1929 return;
1930 case 7:
1931 emit(0x0f);
1932 emit(0x1f);
1933 emit(0x80);
1934 emit(0x00);
1935 emit(0x00);
1936 emit(0x00);
1937 emit(0x00);
1938 return;
1939 case 8:
1940 emit(0x0f);
1941 emit(0x1f);
1942 emit(0x84);
1943 emit(0x00);
1944 emit(0x00);
1945 emit(0x00);
1946 emit(0x00);
1947 emit(0x00);
1948 return;
1949 case 9:
1950 emit(0x66);
1951 emit(0x0f);
1952 emit(0x1f);
1953 emit(0x84);
1954 emit(0x00);
1955 emit(0x00);
1956 emit(0x00);
1957 emit(0x00);
1958 emit(0x00);
1959 return;
1960 }
1961}
1962
1963
1964void Assembler::pop(Register dst) {
1965 EnsureSpace ensure_space(this);
1966 last_pc_ = pc_;
Steve Block8defd9f2010-07-08 12:39:36 +01001967 emit_optional_rex_32(dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001968 emit(0x58 | dst.low_bits());
1969}
1970
1971
1972void Assembler::pop(const Operand& dst) {
1973 EnsureSpace ensure_space(this);
1974 last_pc_ = pc_;
Steve Block8defd9f2010-07-08 12:39:36 +01001975 emit_optional_rex_32(dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001976 emit(0x8F);
1977 emit_operand(0, dst);
1978}
1979
1980
1981void Assembler::popfq() {
1982 EnsureSpace ensure_space(this);
1983 last_pc_ = pc_;
1984 emit(0x9D);
1985}
1986
1987
1988void Assembler::push(Register src) {
1989 EnsureSpace ensure_space(this);
1990 last_pc_ = pc_;
Steve Block8defd9f2010-07-08 12:39:36 +01001991 emit_optional_rex_32(src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001992 emit(0x50 | src.low_bits());
1993}
1994
1995
1996void Assembler::push(const Operand& src) {
1997 EnsureSpace ensure_space(this);
1998 last_pc_ = pc_;
Steve Block8defd9f2010-07-08 12:39:36 +01001999 emit_optional_rex_32(src);
Steve Blocka7e24c12009-10-30 11:49:00 +00002000 emit(0xFF);
2001 emit_operand(6, src);
2002}
2003
2004
2005void Assembler::push(Immediate value) {
2006 EnsureSpace ensure_space(this);
2007 last_pc_ = pc_;
2008 if (is_int8(value.value_)) {
2009 emit(0x6A);
2010 emit(value.value_); // Emit low byte of value.
2011 } else {
2012 emit(0x68);
2013 emitl(value.value_);
2014 }
2015}
2016
2017
Steve Block1e0659c2011-05-24 12:43:12 +01002018void Assembler::push_imm32(int32_t imm32) {
2019 EnsureSpace ensure_space(this);
2020 last_pc_ = pc_;
2021 emit(0x68);
2022 emitl(imm32);
2023}
2024
2025
Steve Blocka7e24c12009-10-30 11:49:00 +00002026void Assembler::pushfq() {
2027 EnsureSpace ensure_space(this);
2028 last_pc_ = pc_;
2029 emit(0x9C);
2030}
2031
2032
Steve Blocka7e24c12009-10-30 11:49:00 +00002033void Assembler::rdtsc() {
2034 EnsureSpace ensure_space(this);
2035 last_pc_ = pc_;
2036 emit(0x0F);
2037 emit(0x31);
2038}
2039
2040
2041void Assembler::ret(int imm16) {
2042 EnsureSpace ensure_space(this);
2043 last_pc_ = pc_;
2044 ASSERT(is_uint16(imm16));
2045 if (imm16 == 0) {
2046 emit(0xC3);
2047 } else {
2048 emit(0xC2);
2049 emit(imm16 & 0xFF);
2050 emit((imm16 >> 8) & 0xFF);
2051 }
2052}
2053
2054
2055void Assembler::setcc(Condition cc, Register reg) {
Steve Block3ce2e202009-11-05 08:53:23 +00002056 if (cc > last_condition) {
2057 movb(reg, Immediate(cc == always ? 1 : 0));
2058 return;
2059 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002060 EnsureSpace ensure_space(this);
2061 last_pc_ = pc_;
2062 ASSERT(is_uint4(cc));
2063 if (reg.code() > 3) { // Use x64 byte registers, where different.
2064 emit_rex_32(reg);
2065 }
2066 emit(0x0F);
2067 emit(0x90 | cc);
2068 emit_modrm(0x0, reg);
2069}
2070
2071
2072void Assembler::shld(Register dst, Register src) {
2073 EnsureSpace ensure_space(this);
2074 last_pc_ = pc_;
2075 emit_rex_64(src, dst);
2076 emit(0x0F);
2077 emit(0xA5);
2078 emit_modrm(src, dst);
2079}
2080
2081
2082void Assembler::shrd(Register dst, Register src) {
2083 EnsureSpace ensure_space(this);
2084 last_pc_ = pc_;
2085 emit_rex_64(src, dst);
2086 emit(0x0F);
2087 emit(0xAD);
2088 emit_modrm(src, dst);
2089}
2090
2091
2092void Assembler::xchg(Register dst, Register src) {
2093 EnsureSpace ensure_space(this);
2094 last_pc_ = pc_;
2095 if (src.is(rax) || dst.is(rax)) { // Single-byte encoding
2096 Register other = src.is(rax) ? dst : src;
2097 emit_rex_64(other);
2098 emit(0x90 | other.low_bits());
Leon Clarkef7060e22010-06-03 12:02:55 +01002099 } else if (dst.low_bits() == 4) {
2100 emit_rex_64(dst, src);
2101 emit(0x87);
2102 emit_modrm(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00002103 } else {
2104 emit_rex_64(src, dst);
2105 emit(0x87);
2106 emit_modrm(src, dst);
2107 }
2108}
2109
2110
2111void Assembler::store_rax(void* dst, RelocInfo::Mode mode) {
2112 EnsureSpace ensure_space(this);
2113 last_pc_ = pc_;
2114 emit(0x48); // REX.W
2115 emit(0xA3);
2116 emitq(reinterpret_cast<uintptr_t>(dst), mode);
2117}
2118
2119
2120void Assembler::store_rax(ExternalReference ref) {
2121 store_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
2122}
2123
2124
Steve Block3ce2e202009-11-05 08:53:23 +00002125void Assembler::testb(Register dst, Register src) {
2126 EnsureSpace ensure_space(this);
2127 last_pc_ = pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +01002128 if (src.low_bits() == 4) {
2129 emit_rex_32(src, dst);
2130 emit(0x84);
2131 emit_modrm(src, dst);
2132 } else {
2133 if (dst.code() > 3 || src.code() > 3) {
2134 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2135 emit_rex_32(dst, src);
2136 }
2137 emit(0x84);
2138 emit_modrm(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00002139 }
Steve Block3ce2e202009-11-05 08:53:23 +00002140}
2141
2142
Steve Blocka7e24c12009-10-30 11:49:00 +00002143void Assembler::testb(Register reg, Immediate mask) {
2144 ASSERT(is_int8(mask.value_) || is_uint8(mask.value_));
2145 EnsureSpace ensure_space(this);
2146 last_pc_ = pc_;
2147 if (reg.is(rax)) {
2148 emit(0xA8);
2149 emit(mask.value_); // Low byte emitted.
2150 } else {
2151 if (reg.code() > 3) {
2152 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2153 emit_rex_32(reg);
2154 }
2155 emit(0xF6);
2156 emit_modrm(0x0, reg);
2157 emit(mask.value_); // Low byte emitted.
2158 }
2159}
2160
2161
2162void Assembler::testb(const Operand& op, Immediate mask) {
2163 ASSERT(is_int8(mask.value_) || is_uint8(mask.value_));
2164 EnsureSpace ensure_space(this);
2165 last_pc_ = pc_;
2166 emit_optional_rex_32(rax, op);
2167 emit(0xF6);
2168 emit_operand(rax, op); // Operation code 0
2169 emit(mask.value_); // Low byte emitted.
2170}
2171
2172
Leon Clarkee46be812010-01-19 14:06:41 +00002173void Assembler::testb(const Operand& op, Register reg) {
2174 EnsureSpace ensure_space(this);
2175 last_pc_ = pc_;
2176 if (reg.code() > 3) {
2177 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2178 emit_rex_32(reg, op);
2179 } else {
2180 emit_optional_rex_32(reg, op);
2181 }
2182 emit(0x84);
2183 emit_operand(reg, op);
2184}
2185
2186
Steve Blocka7e24c12009-10-30 11:49:00 +00002187void Assembler::testl(Register dst, Register src) {
2188 EnsureSpace ensure_space(this);
2189 last_pc_ = pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +01002190 if (src.low_bits() == 4) {
2191 emit_optional_rex_32(src, dst);
2192 emit(0x85);
2193 emit_modrm(src, dst);
2194 } else {
2195 emit_optional_rex_32(dst, src);
2196 emit(0x85);
2197 emit_modrm(dst, src);
2198 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002199}
2200
2201
2202void Assembler::testl(Register reg, Immediate mask) {
2203 // testl with a mask that fits in the low byte is exactly testb.
2204 if (is_uint8(mask.value_)) {
2205 testb(reg, mask);
2206 return;
2207 }
2208 EnsureSpace ensure_space(this);
2209 last_pc_ = pc_;
2210 if (reg.is(rax)) {
2211 emit(0xA9);
2212 emit(mask);
2213 } else {
2214 emit_optional_rex_32(rax, reg);
2215 emit(0xF7);
2216 emit_modrm(0x0, reg);
2217 emit(mask);
2218 }
2219}
2220
2221
2222void Assembler::testl(const Operand& op, Immediate mask) {
2223 // testl with a mask that fits in the low byte is exactly testb.
2224 if (is_uint8(mask.value_)) {
2225 testb(op, mask);
2226 return;
2227 }
2228 EnsureSpace ensure_space(this);
2229 last_pc_ = pc_;
2230 emit_optional_rex_32(rax, op);
2231 emit(0xF7);
2232 emit_operand(rax, op); // Operation code 0
2233 emit(mask);
2234}
2235
2236
2237void Assembler::testq(const Operand& op, Register reg) {
2238 EnsureSpace ensure_space(this);
2239 last_pc_ = pc_;
2240 emit_rex_64(reg, op);
2241 emit(0x85);
2242 emit_operand(reg, op);
2243}
2244
2245
2246void Assembler::testq(Register dst, Register src) {
2247 EnsureSpace ensure_space(this);
2248 last_pc_ = pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +01002249 if (src.low_bits() == 4) {
2250 emit_rex_64(src, dst);
2251 emit(0x85);
2252 emit_modrm(src, dst);
2253 } else {
2254 emit_rex_64(dst, src);
2255 emit(0x85);
2256 emit_modrm(dst, src);
2257 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002258}
2259
2260
2261void Assembler::testq(Register dst, Immediate mask) {
2262 EnsureSpace ensure_space(this);
2263 last_pc_ = pc_;
2264 if (dst.is(rax)) {
2265 emit_rex_64();
2266 emit(0xA9);
2267 emit(mask);
2268 } else {
2269 emit_rex_64(dst);
2270 emit(0xF7);
2271 emit_modrm(0, dst);
2272 emit(mask);
2273 }
2274}
2275
2276
Andrei Popescu31002712010-02-23 13:46:05 +00002277// FPU instructions.
Steve Blocka7e24c12009-10-30 11:49:00 +00002278
2279
2280void Assembler::fld(int i) {
2281 EnsureSpace ensure_space(this);
2282 last_pc_ = pc_;
2283 emit_farith(0xD9, 0xC0, i);
2284}
2285
2286
2287void Assembler::fld1() {
2288 EnsureSpace ensure_space(this);
2289 last_pc_ = pc_;
2290 emit(0xD9);
2291 emit(0xE8);
2292}
2293
2294
2295void Assembler::fldz() {
2296 EnsureSpace ensure_space(this);
2297 last_pc_ = pc_;
2298 emit(0xD9);
2299 emit(0xEE);
2300}
2301
2302
Steve Block6ded16b2010-05-10 14:33:55 +01002303void Assembler::fldpi() {
2304 EnsureSpace ensure_space(this);
2305 last_pc_ = pc_;
2306 emit(0xD9);
2307 emit(0xEB);
2308}
2309
2310
Ben Murdochb0fe1622011-05-05 13:52:32 +01002311void Assembler::fldln2() {
2312 EnsureSpace ensure_space(this);
2313 last_pc_ = pc_;
2314 emit(0xD9);
2315 emit(0xED);
2316}
2317
2318
Steve Blocka7e24c12009-10-30 11:49:00 +00002319void Assembler::fld_s(const Operand& adr) {
2320 EnsureSpace ensure_space(this);
2321 last_pc_ = pc_;
2322 emit_optional_rex_32(adr);
2323 emit(0xD9);
2324 emit_operand(0, adr);
2325}
2326
2327
2328void Assembler::fld_d(const Operand& adr) {
2329 EnsureSpace ensure_space(this);
2330 last_pc_ = pc_;
2331 emit_optional_rex_32(adr);
2332 emit(0xDD);
2333 emit_operand(0, adr);
2334}
2335
2336
2337void Assembler::fstp_s(const Operand& adr) {
2338 EnsureSpace ensure_space(this);
2339 last_pc_ = pc_;
2340 emit_optional_rex_32(adr);
2341 emit(0xD9);
2342 emit_operand(3, adr);
2343}
2344
2345
2346void Assembler::fstp_d(const Operand& adr) {
2347 EnsureSpace ensure_space(this);
2348 last_pc_ = pc_;
2349 emit_optional_rex_32(adr);
2350 emit(0xDD);
2351 emit_operand(3, adr);
2352}
2353
2354
Steve Block3ce2e202009-11-05 08:53:23 +00002355void Assembler::fstp(int index) {
2356 ASSERT(is_uint3(index));
2357 EnsureSpace ensure_space(this);
2358 last_pc_ = pc_;
2359 emit_farith(0xDD, 0xD8, index);
2360}
2361
2362
Steve Blocka7e24c12009-10-30 11:49:00 +00002363void Assembler::fild_s(const Operand& adr) {
2364 EnsureSpace ensure_space(this);
2365 last_pc_ = pc_;
2366 emit_optional_rex_32(adr);
2367 emit(0xDB);
2368 emit_operand(0, adr);
2369}
2370
2371
2372void Assembler::fild_d(const Operand& adr) {
2373 EnsureSpace ensure_space(this);
2374 last_pc_ = pc_;
2375 emit_optional_rex_32(adr);
2376 emit(0xDF);
2377 emit_operand(5, adr);
2378}
2379
2380
2381void Assembler::fistp_s(const Operand& adr) {
2382 EnsureSpace ensure_space(this);
2383 last_pc_ = pc_;
2384 emit_optional_rex_32(adr);
2385 emit(0xDB);
2386 emit_operand(3, adr);
2387}
2388
2389
2390void Assembler::fisttp_s(const Operand& adr) {
Steve Block44f0eee2011-05-26 01:26:41 +01002391 ASSERT(isolate()->cpu_features()->IsEnabled(SSE3));
Steve Blocka7e24c12009-10-30 11:49:00 +00002392 EnsureSpace ensure_space(this);
2393 last_pc_ = pc_;
2394 emit_optional_rex_32(adr);
2395 emit(0xDB);
2396 emit_operand(1, adr);
2397}
2398
2399
Leon Clarked91b9f72010-01-27 17:25:45 +00002400void Assembler::fisttp_d(const Operand& adr) {
Steve Block44f0eee2011-05-26 01:26:41 +01002401 ASSERT(isolate()->cpu_features()->IsEnabled(SSE3));
Leon Clarked91b9f72010-01-27 17:25:45 +00002402 EnsureSpace ensure_space(this);
2403 last_pc_ = pc_;
2404 emit_optional_rex_32(adr);
2405 emit(0xDD);
2406 emit_operand(1, adr);
2407}
2408
2409
Steve Blocka7e24c12009-10-30 11:49:00 +00002410void Assembler::fist_s(const Operand& adr) {
2411 EnsureSpace ensure_space(this);
2412 last_pc_ = pc_;
2413 emit_optional_rex_32(adr);
2414 emit(0xDB);
2415 emit_operand(2, adr);
2416}
2417
2418
2419void Assembler::fistp_d(const Operand& adr) {
2420 EnsureSpace ensure_space(this);
2421 last_pc_ = pc_;
2422 emit_optional_rex_32(adr);
2423 emit(0xDF);
Steve Block3ce2e202009-11-05 08:53:23 +00002424 emit_operand(7, adr);
Steve Blocka7e24c12009-10-30 11:49:00 +00002425}
2426
2427
2428void Assembler::fabs() {
2429 EnsureSpace ensure_space(this);
2430 last_pc_ = pc_;
2431 emit(0xD9);
2432 emit(0xE1);
2433}
2434
2435
2436void Assembler::fchs() {
2437 EnsureSpace ensure_space(this);
2438 last_pc_ = pc_;
2439 emit(0xD9);
2440 emit(0xE0);
2441}
2442
2443
2444void Assembler::fcos() {
2445 EnsureSpace ensure_space(this);
2446 last_pc_ = pc_;
2447 emit(0xD9);
2448 emit(0xFF);
2449}
2450
2451
2452void Assembler::fsin() {
2453 EnsureSpace ensure_space(this);
2454 last_pc_ = pc_;
2455 emit(0xD9);
2456 emit(0xFE);
2457}
2458
2459
Ben Murdochb0fe1622011-05-05 13:52:32 +01002460void Assembler::fyl2x() {
2461 EnsureSpace ensure_space(this);
2462 last_pc_ = pc_;
2463 emit(0xD9);
2464 emit(0xF1);
2465}
2466
2467
Steve Blocka7e24c12009-10-30 11:49:00 +00002468void Assembler::fadd(int i) {
2469 EnsureSpace ensure_space(this);
2470 last_pc_ = pc_;
2471 emit_farith(0xDC, 0xC0, i);
2472}
2473
2474
2475void Assembler::fsub(int i) {
2476 EnsureSpace ensure_space(this);
2477 last_pc_ = pc_;
2478 emit_farith(0xDC, 0xE8, i);
2479}
2480
2481
2482void Assembler::fisub_s(const Operand& adr) {
2483 EnsureSpace ensure_space(this);
2484 last_pc_ = pc_;
2485 emit_optional_rex_32(adr);
2486 emit(0xDA);
2487 emit_operand(4, adr);
2488}
2489
2490
2491void Assembler::fmul(int i) {
2492 EnsureSpace ensure_space(this);
2493 last_pc_ = pc_;
2494 emit_farith(0xDC, 0xC8, i);
2495}
2496
2497
2498void Assembler::fdiv(int i) {
2499 EnsureSpace ensure_space(this);
2500 last_pc_ = pc_;
2501 emit_farith(0xDC, 0xF8, i);
2502}
2503
2504
2505void Assembler::faddp(int i) {
2506 EnsureSpace ensure_space(this);
2507 last_pc_ = pc_;
2508 emit_farith(0xDE, 0xC0, i);
2509}
2510
2511
2512void Assembler::fsubp(int i) {
2513 EnsureSpace ensure_space(this);
2514 last_pc_ = pc_;
2515 emit_farith(0xDE, 0xE8, i);
2516}
2517
2518
2519void Assembler::fsubrp(int i) {
2520 EnsureSpace ensure_space(this);
2521 last_pc_ = pc_;
2522 emit_farith(0xDE, 0xE0, i);
2523}
2524
2525
2526void Assembler::fmulp(int i) {
2527 EnsureSpace ensure_space(this);
2528 last_pc_ = pc_;
2529 emit_farith(0xDE, 0xC8, i);
2530}
2531
2532
2533void Assembler::fdivp(int i) {
2534 EnsureSpace ensure_space(this);
2535 last_pc_ = pc_;
2536 emit_farith(0xDE, 0xF8, i);
2537}
2538
2539
2540void Assembler::fprem() {
2541 EnsureSpace ensure_space(this);
2542 last_pc_ = pc_;
2543 emit(0xD9);
2544 emit(0xF8);
2545}
2546
2547
2548void Assembler::fprem1() {
2549 EnsureSpace ensure_space(this);
2550 last_pc_ = pc_;
2551 emit(0xD9);
2552 emit(0xF5);
2553}
2554
2555
2556void Assembler::fxch(int i) {
2557 EnsureSpace ensure_space(this);
2558 last_pc_ = pc_;
2559 emit_farith(0xD9, 0xC8, i);
2560}
2561
2562
2563void Assembler::fincstp() {
2564 EnsureSpace ensure_space(this);
2565 last_pc_ = pc_;
2566 emit(0xD9);
2567 emit(0xF7);
2568}
2569
2570
2571void Assembler::ffree(int i) {
2572 EnsureSpace ensure_space(this);
2573 last_pc_ = pc_;
2574 emit_farith(0xDD, 0xC0, i);
2575}
2576
2577
2578void Assembler::ftst() {
2579 EnsureSpace ensure_space(this);
2580 last_pc_ = pc_;
2581 emit(0xD9);
2582 emit(0xE4);
2583}
2584
2585
2586void Assembler::fucomp(int i) {
2587 EnsureSpace ensure_space(this);
2588 last_pc_ = pc_;
2589 emit_farith(0xDD, 0xE8, i);
2590}
2591
2592
2593void Assembler::fucompp() {
2594 EnsureSpace ensure_space(this);
2595 last_pc_ = pc_;
2596 emit(0xDA);
2597 emit(0xE9);
2598}
2599
2600
Steve Block3ce2e202009-11-05 08:53:23 +00002601void Assembler::fucomi(int i) {
2602 EnsureSpace ensure_space(this);
2603 last_pc_ = pc_;
2604 emit(0xDB);
2605 emit(0xE8 + i);
2606}
2607
2608
2609void Assembler::fucomip() {
2610 EnsureSpace ensure_space(this);
2611 last_pc_ = pc_;
2612 emit(0xDF);
2613 emit(0xE9);
2614}
2615
2616
Steve Blocka7e24c12009-10-30 11:49:00 +00002617void Assembler::fcompp() {
2618 EnsureSpace ensure_space(this);
2619 last_pc_ = pc_;
2620 emit(0xDE);
2621 emit(0xD9);
2622}
2623
2624
2625void Assembler::fnstsw_ax() {
2626 EnsureSpace ensure_space(this);
2627 last_pc_ = pc_;
2628 emit(0xDF);
2629 emit(0xE0);
2630}
2631
2632
2633void Assembler::fwait() {
2634 EnsureSpace ensure_space(this);
2635 last_pc_ = pc_;
2636 emit(0x9B);
2637}
2638
2639
2640void Assembler::frndint() {
2641 EnsureSpace ensure_space(this);
2642 last_pc_ = pc_;
2643 emit(0xD9);
2644 emit(0xFC);
2645}
2646
2647
2648void Assembler::fnclex() {
2649 EnsureSpace ensure_space(this);
2650 last_pc_ = pc_;
2651 emit(0xDB);
2652 emit(0xE2);
2653}
2654
2655
2656void Assembler::sahf() {
2657 // TODO(X64): Test for presence. Not all 64-bit intel CPU's have sahf
2658 // in 64-bit mode. Test CpuID.
2659 EnsureSpace ensure_space(this);
2660 last_pc_ = pc_;
2661 emit(0x9E);
2662}
2663
2664
2665void Assembler::emit_farith(int b1, int b2, int i) {
2666 ASSERT(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2667 ASSERT(is_uint3(i)); // illegal stack offset
2668 emit(b1);
2669 emit(b2 + i);
2670}
2671
Andrei Popescu31002712010-02-23 13:46:05 +00002672// SSE 2 operations.
Steve Blocka7e24c12009-10-30 11:49:00 +00002673
Steve Block6ded16b2010-05-10 14:33:55 +01002674void Assembler::movd(XMMRegister dst, Register src) {
2675 EnsureSpace ensure_space(this);
2676 last_pc_ = pc_;
2677 emit(0x66);
2678 emit_optional_rex_32(dst, src);
2679 emit(0x0F);
2680 emit(0x6E);
2681 emit_sse_operand(dst, src);
2682}
2683
2684
2685void Assembler::movd(Register dst, XMMRegister src) {
2686 EnsureSpace ensure_space(this);
2687 last_pc_ = pc_;
2688 emit(0x66);
Ben Murdochbb769b22010-08-11 14:56:33 +01002689 emit_optional_rex_32(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002690 emit(0x0F);
2691 emit(0x7E);
Ben Murdochbb769b22010-08-11 14:56:33 +01002692 emit_sse_operand(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002693}
2694
2695
2696void Assembler::movq(XMMRegister dst, Register src) {
2697 EnsureSpace ensure_space(this);
2698 last_pc_ = pc_;
2699 emit(0x66);
2700 emit_rex_64(dst, src);
2701 emit(0x0F);
2702 emit(0x6E);
2703 emit_sse_operand(dst, src);
2704}
2705
2706
2707void Assembler::movq(Register dst, XMMRegister src) {
2708 EnsureSpace ensure_space(this);
2709 last_pc_ = pc_;
2710 emit(0x66);
Ben Murdochbb769b22010-08-11 14:56:33 +01002711 emit_rex_64(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002712 emit(0x0F);
2713 emit(0x7E);
Ben Murdochbb769b22010-08-11 14:56:33 +01002714 emit_sse_operand(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002715}
2716
2717
Steve Block1e0659c2011-05-24 12:43:12 +01002718void Assembler::movdqa(const Operand& dst, XMMRegister src) {
Steve Block44f0eee2011-05-26 01:26:41 +01002719 ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
Steve Block1e0659c2011-05-24 12:43:12 +01002720 EnsureSpace ensure_space(this);
2721 last_pc_ = pc_;
2722 emit(0x66);
2723 emit_rex_64(src, dst);
2724 emit(0x0F);
2725 emit(0x7F);
2726 emit_sse_operand(src, dst);
2727}
2728
2729
2730void Assembler::movdqa(XMMRegister dst, const Operand& src) {
Steve Block44f0eee2011-05-26 01:26:41 +01002731 ASSERT(isolate()->cpu_features()->IsEnabled(SSE2));
Steve Block1e0659c2011-05-24 12:43:12 +01002732 EnsureSpace ensure_space(this);
2733 last_pc_ = pc_;
2734 emit(0x66);
2735 emit_rex_64(dst, src);
2736 emit(0x0F);
2737 emit(0x6F);
2738 emit_sse_operand(dst, src);
2739}
2740
2741
Steve Block6ded16b2010-05-10 14:33:55 +01002742void Assembler::extractps(Register dst, XMMRegister src, byte imm8) {
2743 ASSERT(is_uint2(imm8));
2744 EnsureSpace ensure_space(this);
2745 last_pc_ = pc_;
2746 emit(0x66);
2747 emit_optional_rex_32(dst, src);
2748 emit(0x0F);
2749 emit(0x3A);
2750 emit(0x17);
2751 emit_sse_operand(dst, src);
2752 emit(imm8);
2753}
2754
2755
Steve Blocka7e24c12009-10-30 11:49:00 +00002756void Assembler::movsd(const Operand& dst, XMMRegister src) {
2757 EnsureSpace ensure_space(this);
2758 last_pc_ = pc_;
2759 emit(0xF2); // double
2760 emit_optional_rex_32(src, dst);
2761 emit(0x0F);
2762 emit(0x11); // store
2763 emit_sse_operand(src, dst);
2764}
2765
2766
Steve Block3ce2e202009-11-05 08:53:23 +00002767void Assembler::movsd(XMMRegister dst, XMMRegister src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002768 EnsureSpace ensure_space(this);
2769 last_pc_ = pc_;
2770 emit(0xF2); // double
2771 emit_optional_rex_32(dst, src);
2772 emit(0x0F);
2773 emit(0x10); // load
2774 emit_sse_operand(dst, src);
2775}
2776
2777
2778void Assembler::movsd(XMMRegister dst, const Operand& src) {
2779 EnsureSpace ensure_space(this);
2780 last_pc_ = pc_;
2781 emit(0xF2); // double
2782 emit_optional_rex_32(dst, src);
2783 emit(0x0F);
2784 emit(0x10); // load
2785 emit_sse_operand(dst, src);
2786}
2787
2788
Steve Block8defd9f2010-07-08 12:39:36 +01002789void Assembler::movss(XMMRegister dst, const Operand& src) {
2790 EnsureSpace ensure_space(this);
2791 last_pc_ = pc_;
2792 emit(0xF3); // single
2793 emit_optional_rex_32(dst, src);
2794 emit(0x0F);
2795 emit(0x10); // load
2796 emit_sse_operand(dst, src);
2797}
2798
2799
2800void Assembler::movss(const Operand& src, XMMRegister dst) {
2801 EnsureSpace ensure_space(this);
2802 last_pc_ = pc_;
2803 emit(0xF3); // single
2804 emit_optional_rex_32(dst, src);
2805 emit(0x0F);
2806 emit(0x11); // store
2807 emit_sse_operand(dst, src);
2808}
2809
2810
Steve Blocka7e24c12009-10-30 11:49:00 +00002811void Assembler::cvttss2si(Register dst, const Operand& src) {
2812 EnsureSpace ensure_space(this);
2813 last_pc_ = pc_;
2814 emit(0xF3);
2815 emit_optional_rex_32(dst, src);
2816 emit(0x0F);
2817 emit(0x2C);
2818 emit_operand(dst, src);
2819}
2820
2821
Steve Block1e0659c2011-05-24 12:43:12 +01002822void Assembler::cvttss2si(Register dst, XMMRegister src) {
2823 EnsureSpace ensure_space(this);
2824 last_pc_ = pc_;
2825 emit(0xF3);
2826 emit_optional_rex_32(dst, src);
2827 emit(0x0F);
2828 emit(0x2C);
2829 emit_sse_operand(dst, src);
2830}
2831
2832
Steve Blocka7e24c12009-10-30 11:49:00 +00002833void Assembler::cvttsd2si(Register dst, const Operand& src) {
2834 EnsureSpace ensure_space(this);
2835 last_pc_ = pc_;
2836 emit(0xF2);
2837 emit_optional_rex_32(dst, src);
2838 emit(0x0F);
2839 emit(0x2C);
2840 emit_operand(dst, src);
2841}
2842
2843
Steve Block1e0659c2011-05-24 12:43:12 +01002844void Assembler::cvttsd2si(Register dst, XMMRegister src) {
2845 EnsureSpace ensure_space(this);
2846 last_pc_ = pc_;
2847 emit(0xF2);
2848 emit_optional_rex_32(dst, src);
2849 emit(0x0F);
2850 emit(0x2C);
2851 emit_sse_operand(dst, src);
2852}
2853
2854
Kristian Monsen25f61362010-05-21 11:50:48 +01002855void Assembler::cvttsd2siq(Register dst, XMMRegister src) {
2856 EnsureSpace ensure_space(this);
2857 last_pc_ = pc_;
2858 emit(0xF2);
2859 emit_rex_64(dst, src);
2860 emit(0x0F);
2861 emit(0x2C);
2862 emit_sse_operand(dst, src);
2863}
2864
2865
Steve Blocka7e24c12009-10-30 11:49:00 +00002866void Assembler::cvtlsi2sd(XMMRegister dst, const Operand& src) {
2867 EnsureSpace ensure_space(this);
2868 last_pc_ = pc_;
2869 emit(0xF2);
2870 emit_optional_rex_32(dst, src);
2871 emit(0x0F);
2872 emit(0x2A);
2873 emit_sse_operand(dst, src);
2874}
2875
2876
2877void Assembler::cvtlsi2sd(XMMRegister dst, Register src) {
2878 EnsureSpace ensure_space(this);
2879 last_pc_ = pc_;
2880 emit(0xF2);
2881 emit_optional_rex_32(dst, src);
2882 emit(0x0F);
2883 emit(0x2A);
2884 emit_sse_operand(dst, src);
2885}
2886
2887
Steve Block8defd9f2010-07-08 12:39:36 +01002888void Assembler::cvtlsi2ss(XMMRegister dst, Register src) {
2889 EnsureSpace ensure_space(this);
2890 last_pc_ = pc_;
2891 emit(0xF3);
2892 emit_optional_rex_32(dst, src);
2893 emit(0x0F);
2894 emit(0x2A);
2895 emit_sse_operand(dst, src);
2896}
2897
2898
Steve Blocka7e24c12009-10-30 11:49:00 +00002899void Assembler::cvtqsi2sd(XMMRegister dst, Register src) {
2900 EnsureSpace ensure_space(this);
2901 last_pc_ = pc_;
2902 emit(0xF2);
2903 emit_rex_64(dst, src);
2904 emit(0x0F);
2905 emit(0x2A);
2906 emit_sse_operand(dst, src);
2907}
2908
2909
Steve Block6ded16b2010-05-10 14:33:55 +01002910void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
2911 EnsureSpace ensure_space(this);
2912 last_pc_ = pc_;
2913 emit(0xF3);
2914 emit_optional_rex_32(dst, src);
2915 emit(0x0F);
2916 emit(0x5A);
2917 emit_sse_operand(dst, src);
2918}
2919
2920
Steve Block8defd9f2010-07-08 12:39:36 +01002921void Assembler::cvtss2sd(XMMRegister dst, const Operand& src) {
2922 EnsureSpace ensure_space(this);
2923 last_pc_ = pc_;
2924 emit(0xF3);
2925 emit_optional_rex_32(dst, src);
2926 emit(0x0F);
2927 emit(0x5A);
2928 emit_sse_operand(dst, src);
2929}
2930
2931
2932void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
2933 EnsureSpace ensure_space(this);
2934 last_pc_ = pc_;
2935 emit(0xF2);
2936 emit_optional_rex_32(dst, src);
2937 emit(0x0F);
2938 emit(0x5A);
2939 emit_sse_operand(dst, src);
2940}
2941
2942
2943void Assembler::cvtsd2si(Register dst, XMMRegister src) {
2944 EnsureSpace ensure_space(this);
2945 last_pc_ = pc_;
2946 emit(0xF2);
2947 emit_optional_rex_32(dst, src);
2948 emit(0x0F);
2949 emit(0x2D);
2950 emit_sse_operand(dst, src);
2951}
2952
2953
2954void Assembler::cvtsd2siq(Register dst, XMMRegister src) {
2955 EnsureSpace ensure_space(this);
2956 last_pc_ = pc_;
2957 emit(0xF2);
2958 emit_rex_64(dst, src);
2959 emit(0x0F);
2960 emit(0x2D);
2961 emit_sse_operand(dst, src);
2962}
2963
2964
Steve Blocka7e24c12009-10-30 11:49:00 +00002965void Assembler::addsd(XMMRegister dst, XMMRegister src) {
2966 EnsureSpace ensure_space(this);
2967 last_pc_ = pc_;
2968 emit(0xF2);
2969 emit_optional_rex_32(dst, src);
2970 emit(0x0F);
2971 emit(0x58);
2972 emit_sse_operand(dst, src);
2973}
2974
2975
2976void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
2977 EnsureSpace ensure_space(this);
2978 last_pc_ = pc_;
2979 emit(0xF2);
2980 emit_optional_rex_32(dst, src);
2981 emit(0x0F);
2982 emit(0x59);
2983 emit_sse_operand(dst, src);
2984}
2985
2986
2987void Assembler::subsd(XMMRegister dst, XMMRegister src) {
2988 EnsureSpace ensure_space(this);
2989 last_pc_ = pc_;
2990 emit(0xF2);
2991 emit_optional_rex_32(dst, src);
2992 emit(0x0F);
2993 emit(0x5C);
2994 emit_sse_operand(dst, src);
2995}
2996
2997
2998void Assembler::divsd(XMMRegister dst, XMMRegister src) {
2999 EnsureSpace ensure_space(this);
3000 last_pc_ = pc_;
3001 emit(0xF2);
3002 emit_optional_rex_32(dst, src);
3003 emit(0x0F);
3004 emit(0x5E);
3005 emit_sse_operand(dst, src);
3006}
3007
3008
Ben Murdoche0cee9b2011-05-25 10:26:03 +01003009void Assembler::andpd(XMMRegister dst, XMMRegister src) {
3010 EnsureSpace ensure_space(this);
3011 last_pc_ = pc_;
3012 emit(0x66);
3013 emit_optional_rex_32(dst, src);
3014 emit(0x0F);
3015 emit(0x54);
3016 emit_sse_operand(dst, src);
3017}
3018
3019
3020void Assembler::orpd(XMMRegister dst, XMMRegister src) {
3021 EnsureSpace ensure_space(this);
3022 last_pc_ = pc_;
3023 emit(0x66);
3024 emit_optional_rex_32(dst, src);
3025 emit(0x0F);
3026 emit(0x56);
3027 emit_sse_operand(dst, src);
3028}
3029
3030
Andrei Popescu402d9372010-02-26 13:31:12 +00003031void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
3032 EnsureSpace ensure_space(this);
3033 last_pc_ = pc_;
3034 emit(0x66);
3035 emit_optional_rex_32(dst, src);
Steve Block6ded16b2010-05-10 14:33:55 +01003036 emit(0x0F);
Andrei Popescu402d9372010-02-26 13:31:12 +00003037 emit(0x57);
3038 emit_sse_operand(dst, src);
3039}
3040
3041
Steve Block6ded16b2010-05-10 14:33:55 +01003042void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
3043 EnsureSpace ensure_space(this);
3044 last_pc_ = pc_;
3045 emit(0xF2);
3046 emit_optional_rex_32(dst, src);
3047 emit(0x0F);
3048 emit(0x51);
3049 emit_sse_operand(dst, src);
3050}
3051
3052
Andrei Popescu402d9372010-02-26 13:31:12 +00003053void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
3054 EnsureSpace ensure_space(this);
3055 last_pc_ = pc_;
3056 emit(0x66);
3057 emit_optional_rex_32(dst, src);
3058 emit(0x0f);
3059 emit(0x2e);
3060 emit_sse_operand(dst, src);
3061}
3062
Steve Blocka7e24c12009-10-30 11:49:00 +00003063
Steve Block8defd9f2010-07-08 12:39:36 +01003064void Assembler::ucomisd(XMMRegister dst, const Operand& src) {
3065 EnsureSpace ensure_space(this);
3066 last_pc_ = pc_;
3067 emit(0x66);
3068 emit_optional_rex_32(dst, src);
3069 emit(0x0f);
3070 emit(0x2e);
3071 emit_sse_operand(dst, src);
3072}
3073
3074
Steve Block1e0659c2011-05-24 12:43:12 +01003075void Assembler::movmskpd(Register dst, XMMRegister src) {
3076 EnsureSpace ensure_space(this);
3077 last_pc_ = pc_;
3078 emit(0x66);
3079 emit_optional_rex_32(dst, src);
3080 emit(0x0f);
3081 emit(0x50);
3082 emit_sse_operand(dst, src);
3083}
3084
Steve Block8defd9f2010-07-08 12:39:36 +01003085
Steve Blocka7e24c12009-10-30 11:49:00 +00003086void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
3087 Register ireg = { reg.code() };
3088 emit_operand(ireg, adr);
3089}
3090
3091
3092void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
3093 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
3094}
3095
3096void Assembler::emit_sse_operand(XMMRegister dst, Register src) {
3097 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
3098}
3099
Steve Block6ded16b2010-05-10 14:33:55 +01003100void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
3101 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
3102}
3103
Steve Blocka7e24c12009-10-30 11:49:00 +00003104
Ben Murdochb8e0da22011-05-16 14:20:40 +01003105void Assembler::db(uint8_t data) {
3106 EnsureSpace ensure_space(this);
3107 emit(data);
3108}
3109
3110
Ben Murdochb0fe1622011-05-05 13:52:32 +01003111void Assembler::dd(uint32_t data) {
3112 EnsureSpace ensure_space(this);
3113 emitl(data);
3114}
3115
3116
Andrei Popescu31002712010-02-23 13:46:05 +00003117// Relocation information implementations.
Steve Blocka7e24c12009-10-30 11:49:00 +00003118
3119void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
3120 ASSERT(rmode != RelocInfo::NONE);
3121 // Don't record external references unless the heap will be serialized.
Steve Block1e0659c2011-05-24 12:43:12 +01003122 if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
3123#ifdef DEBUG
3124 if (!Serializer::enabled()) {
3125 Serializer::TooLateToEnableNow();
3126 }
3127#endif
Steve Block44f0eee2011-05-26 01:26:41 +01003128 if (!Serializer::enabled() && !emit_debug_code()) {
Steve Block1e0659c2011-05-24 12:43:12 +01003129 return;
3130 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003131 }
3132 RelocInfo rinfo(pc_, rmode, data);
3133 reloc_info_writer.Write(&rinfo);
3134}
3135
3136void Assembler::RecordJSReturn() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003137 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00003138 EnsureSpace ensure_space(this);
3139 RecordRelocInfo(RelocInfo::JS_RETURN);
3140}
3141
3142
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003143void Assembler::RecordDebugBreakSlot() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003144 positions_recorder()->WriteRecordedPositions();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003145 EnsureSpace ensure_space(this);
3146 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
3147}
3148
3149
Ben Murdoche0cee9b2011-05-25 10:26:03 +01003150void Assembler::RecordComment(const char* msg, bool force) {
3151 if (FLAG_code_comments || force) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003152 EnsureSpace ensure_space(this);
3153 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
3154 }
3155}
3156
3157
Steve Block3ce2e202009-11-05 08:53:23 +00003158const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
Ben Murdochbb769b22010-08-11 14:56:33 +01003159 1 << RelocInfo::INTERNAL_REFERENCE;
Steve Blocka7e24c12009-10-30 11:49:00 +00003160
Leon Clarkef7060e22010-06-03 12:02:55 +01003161
3162bool RelocInfo::IsCodedSpecially() {
3163 // The deserializer needs to know whether a pointer is specially coded. Being
3164 // specially coded on x64 means that it is a relative 32 bit address, as used
3165 // by branch instructions.
3166 return (1 << rmode_) & kApplyMask;
3167}
3168
3169
3170
Steve Blocka7e24c12009-10-30 11:49:00 +00003171} } // namespace v8::internal
Leon Clarkef7060e22010-06-03 12:02:55 +01003172
3173#endif // V8_TARGET_ARCH_X64