blob: 8f15f23ba7de6cf5ffa90c22aa6e422e14dfd199 [file] [log] [blame]
Ben Murdochb0fe1622011-05-05 13:52:32 +01001// Copyright 2010 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
41// The required user mode extensions in X64 are (from AMD64 ABI Table A.1):
42// fpu, tsc, cx8, cmov, mmx, sse, sse2, fxsr, syscall
43uint64_t CpuFeatures::supported_ = kDefaultCpuFeatures;
44uint64_t CpuFeatures::enabled_ = 0;
Steve Blockd0582a62009-12-15 09:54:21 +000045uint64_t CpuFeatures::found_by_runtime_probing_ = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000046
Ben Murdochb0fe1622011-05-05 13:52:32 +010047void CpuFeatures::Probe(bool portable) {
Steve Blocka7e24c12009-10-30 11:49:00 +000048 ASSERT(Heap::HasBeenSetup());
Ben Murdochb0fe1622011-05-05 13:52:32 +010049 supported_ = kDefaultCpuFeatures;
50 if (portable && Serializer::enabled()) {
Steve Blockd0582a62009-12-15 09:54:21 +000051 supported_ |= OS::CpuFeaturesImpliedByPlatform();
52 return; // No features if we might serialize.
53 }
Steve Blocka7e24c12009-10-30 11:49:00 +000054
55 Assembler assm(NULL, 0);
56 Label cpuid, done;
57#define __ assm.
58 // Save old rsp, since we are going to modify the stack.
59 __ push(rbp);
60 __ pushfq();
61 __ push(rcx);
62 __ push(rbx);
63 __ movq(rbp, rsp);
64
65 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
66 __ pushfq();
67 __ pop(rax);
68 __ movq(rdx, rax);
69 __ xor_(rax, Immediate(0x200000)); // Flip bit 21.
70 __ push(rax);
71 __ popfq();
72 __ pushfq();
73 __ pop(rax);
74 __ xor_(rax, rdx); // Different if CPUID is supported.
75 __ j(not_zero, &cpuid);
76
77 // CPUID not supported. Clear the supported features in edx:eax.
78 __ xor_(rax, rax);
79 __ jmp(&done);
80
81 // Invoke CPUID with 1 in eax to get feature information in
82 // ecx:edx. Temporarily enable CPUID support because we know it's
83 // safe here.
84 __ bind(&cpuid);
85 __ movq(rax, Immediate(1));
86 supported_ = kDefaultCpuFeatures | (1 << CPUID);
87 { Scope fscope(CPUID);
88 __ cpuid();
89 // Move the result from ecx:edx to rdi.
90 __ movl(rdi, rdx); // Zero-extended to 64 bits.
91 __ shl(rcx, Immediate(32));
92 __ or_(rdi, rcx);
93
94 // Get the sahf supported flag, from CPUID(0x80000001)
95 __ movq(rax, 0x80000001, RelocInfo::NONE);
96 __ cpuid();
97 }
98 supported_ = kDefaultCpuFeatures;
99
100 // Put the CPU flags in rax.
101 // rax = (rcx & 1) | (rdi & ~1) | (1 << CPUID).
102 __ movl(rax, Immediate(1));
103 __ and_(rcx, rax); // Bit 0 is set if SAHF instruction supported.
104 __ not_(rax);
105 __ and_(rax, rdi);
106 __ or_(rax, rcx);
107 __ or_(rax, Immediate(1 << CPUID));
108
109 // Done.
110 __ bind(&done);
111 __ movq(rsp, rbp);
112 __ pop(rbx);
113 __ pop(rcx);
114 __ popfq();
115 __ pop(rbp);
116 __ ret(0);
117#undef __
118
119 CodeDesc desc;
120 assm.GetCode(&desc);
John Reck59135872010-11-02 12:39:01 -0700121 MaybeObject* maybe_code = Heap::CreateCode(desc,
122 Code::ComputeFlags(Code::STUB),
123 Handle<Object>());
124 Object* code;
125 if (!maybe_code->ToObject(&code)) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000126 if (!code->IsCode()) return;
Steve Block6ded16b2010-05-10 14:33:55 +0100127 PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG,
128 Code::cast(code), "CpuFeatures::Probe"));
Steve Blocka7e24c12009-10-30 11:49:00 +0000129 typedef uint64_t (*F0)();
130 F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry());
131 supported_ = probe();
Steve Blockd0582a62009-12-15 09:54:21 +0000132 found_by_runtime_probing_ = supported_;
133 found_by_runtime_probing_ &= ~kDefaultCpuFeatures;
134 uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform();
135 supported_ |= os_guarantees;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100136 found_by_runtime_probing_ &= portable ? ~os_guarantees : 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000137 // SSE2 and CMOV must be available on an X64 CPU.
138 ASSERT(IsSupported(CPUID));
139 ASSERT(IsSupported(SSE2));
140 ASSERT(IsSupported(CMOV));
141}
142
143
144// -----------------------------------------------------------------------------
145// Implementation of RelocInfo
146
147// Patch the code at the current PC with a call to the target address.
148// Additional guard int3 instructions can be added if required.
149void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
150 // Load register with immediate 64 and call through a register instructions
151 // takes up 13 bytes and int3 takes up one byte.
152 static const int kCallCodeSize = 13;
153 int code_size = kCallCodeSize + guard_bytes;
154
155 // Create a code patcher.
156 CodePatcher patcher(pc_, code_size);
157
158 // Add a label for checking the size of the code used for returning.
159#ifdef DEBUG
160 Label check_codesize;
161 patcher.masm()->bind(&check_codesize);
162#endif
163
164 // Patch the code.
165 patcher.masm()->movq(r10, target, RelocInfo::NONE);
166 patcher.masm()->call(r10);
167
168 // Check that the size of the code generated is as expected.
169 ASSERT_EQ(kCallCodeSize,
170 patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
171
172 // Add the requested number of int3 instructions after the call.
173 for (int i = 0; i < guard_bytes; i++) {
174 patcher.masm()->int3();
175 }
176}
177
178
179void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
180 // Patch the code at the current address with the supplied instructions.
181 for (int i = 0; i < instruction_count; i++) {
182 *(pc_ + i) = *(instructions + i);
183 }
184
185 // Indicate that code has changed.
186 CPU::FlushICache(pc_, instruction_count);
187}
188
189// -----------------------------------------------------------------------------
190// Implementation of Operand
191
Andrei Popescu402d9372010-02-26 13:31:12 +0000192Operand::Operand(Register base, int32_t disp) : rex_(0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000193 len_ = 1;
194 if (base.is(rsp) || base.is(r12)) {
195 // SIB byte is needed to encode (rsp + offset) or (r12 + offset).
196 set_sib(times_1, rsp, base);
197 }
198
199 if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
200 set_modrm(0, base);
201 } else if (is_int8(disp)) {
202 set_modrm(1, base);
203 set_disp8(disp);
204 } else {
205 set_modrm(2, base);
206 set_disp32(disp);
207 }
208}
209
210
211Operand::Operand(Register base,
212 Register index,
213 ScaleFactor scale,
Andrei Popescu402d9372010-02-26 13:31:12 +0000214 int32_t disp) : rex_(0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000215 ASSERT(!index.is(rsp));
216 len_ = 1;
217 set_sib(scale, index, base);
218 if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
219 // This call to set_modrm doesn't overwrite the REX.B (or REX.X) bits
220 // possibly set by set_sib.
221 set_modrm(0, rsp);
222 } else if (is_int8(disp)) {
223 set_modrm(1, rsp);
224 set_disp8(disp);
225 } else {
226 set_modrm(2, rsp);
227 set_disp32(disp);
228 }
229}
230
231
Andrei Popescu402d9372010-02-26 13:31:12 +0000232Operand::Operand(Register index,
233 ScaleFactor scale,
234 int32_t disp) : rex_(0) {
235 ASSERT(!index.is(rsp));
236 len_ = 1;
237 set_modrm(0, rsp);
238 set_sib(scale, index, rbp);
239 set_disp32(disp);
240}
241
242
Leon Clarkef7060e22010-06-03 12:02:55 +0100243Operand::Operand(const Operand& operand, int32_t offset) {
244 ASSERT(operand.len_ >= 1);
245 // Operand encodes REX ModR/M [SIB] [Disp].
246 byte modrm = operand.buf_[0];
247 ASSERT(modrm < 0xC0); // Disallow mode 3 (register target).
248 bool has_sib = ((modrm & 0x07) == 0x04);
249 byte mode = modrm & 0xC0;
250 int disp_offset = has_sib ? 2 : 1;
251 int base_reg = (has_sib ? operand.buf_[1] : modrm) & 0x07;
252 // Mode 0 with rbp/r13 as ModR/M or SIB base register always has a 32-bit
253 // displacement.
254 bool is_baseless = (mode == 0) && (base_reg == 0x05); // No base or RIP base.
255 int32_t disp_value = 0;
256 if (mode == 0x80 || is_baseless) {
257 // Mode 2 or mode 0 with rbp/r13 as base: Word displacement.
Iain Merrick75681382010-08-19 15:07:18 +0100258 disp_value = *BitCast<const int32_t*>(&operand.buf_[disp_offset]);
Leon Clarkef7060e22010-06-03 12:02:55 +0100259 } else if (mode == 0x40) {
260 // Mode 1: Byte displacement.
261 disp_value = static_cast<signed char>(operand.buf_[disp_offset]);
262 }
263
264 // Write new operand with same registers, but with modified displacement.
265 ASSERT(offset >= 0 ? disp_value + offset > disp_value
266 : disp_value + offset < disp_value); // No overflow.
267 disp_value += offset;
268 rex_ = operand.rex_;
269 if (!is_int8(disp_value) || is_baseless) {
270 // Need 32 bits of displacement, mode 2 or mode 1 with register rbp/r13.
271 buf_[0] = (modrm & 0x3f) | (is_baseless ? 0x00 : 0x80);
272 len_ = disp_offset + 4;
273 Memory::int32_at(&buf_[disp_offset]) = disp_value;
274 } else if (disp_value != 0 || (base_reg == 0x05)) {
275 // Need 8 bits of displacement.
276 buf_[0] = (modrm & 0x3f) | 0x40; // Mode 1.
277 len_ = disp_offset + 1;
278 buf_[disp_offset] = static_cast<byte>(disp_value);
279 } else {
280 // Need no displacement.
281 buf_[0] = (modrm & 0x3f); // Mode 0.
282 len_ = disp_offset;
283 }
284 if (has_sib) {
285 buf_[1] = operand.buf_[1];
286 }
287}
288
Steve Blocka7e24c12009-10-30 11:49:00 +0000289// -----------------------------------------------------------------------------
Andrei Popescu31002712010-02-23 13:46:05 +0000290// Implementation of Assembler.
Steve Blocka7e24c12009-10-30 11:49:00 +0000291
292#ifdef GENERATED_CODE_COVERAGE
293static void InitCoverageLog();
294#endif
295
296byte* Assembler::spare_buffer_ = NULL;
297
Steve Block3ce2e202009-11-05 08:53:23 +0000298Assembler::Assembler(void* buffer, int buffer_size)
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800299 : code_targets_(100), positions_recorder_(this) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000300 if (buffer == NULL) {
Andrei Popescu31002712010-02-23 13:46:05 +0000301 // Do our own buffer management.
Steve Blocka7e24c12009-10-30 11:49:00 +0000302 if (buffer_size <= kMinimalBufferSize) {
303 buffer_size = kMinimalBufferSize;
304
305 if (spare_buffer_ != NULL) {
306 buffer = spare_buffer_;
307 spare_buffer_ = NULL;
308 }
309 }
310 if (buffer == NULL) {
311 buffer_ = NewArray<byte>(buffer_size);
312 } else {
313 buffer_ = static_cast<byte*>(buffer);
314 }
315 buffer_size_ = buffer_size;
316 own_buffer_ = true;
317 } else {
Andrei Popescu31002712010-02-23 13:46:05 +0000318 // Use externally provided buffer instead.
Steve Blocka7e24c12009-10-30 11:49:00 +0000319 ASSERT(buffer_size > 0);
320 buffer_ = static_cast<byte*>(buffer);
321 buffer_size_ = buffer_size;
322 own_buffer_ = false;
323 }
324
325 // Clear the buffer in debug mode unless it was provided by the
326 // caller in which case we can't be sure it's okay to overwrite
327 // existing code in it.
328#ifdef DEBUG
329 if (own_buffer_) {
330 memset(buffer_, 0xCC, buffer_size); // int3
331 }
332#endif
333
Andrei Popescu31002712010-02-23 13:46:05 +0000334 // Setup buffer pointers.
Steve Blocka7e24c12009-10-30 11:49:00 +0000335 ASSERT(buffer_ != NULL);
336 pc_ = buffer_;
337 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
338
339 last_pc_ = NULL;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800340
Steve Blocka7e24c12009-10-30 11:49:00 +0000341#ifdef GENERATED_CODE_COVERAGE
342 InitCoverageLog();
343#endif
344}
345
346
347Assembler::~Assembler() {
348 if (own_buffer_) {
349 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
350 spare_buffer_ = buffer_;
351 } else {
352 DeleteArray(buffer_);
353 }
354 }
355}
356
357
358void Assembler::GetCode(CodeDesc* desc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000359 // Finalize code (at this point overflow() may be true, but the gap ensures
360 // that we are still not overlapping instructions and relocation info).
361 ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap.
362 // Setup code descriptor.
Steve Blocka7e24c12009-10-30 11:49:00 +0000363 desc->buffer = buffer_;
364 desc->buffer_size = buffer_size_;
365 desc->instr_size = pc_offset();
366 ASSERT(desc->instr_size > 0); // Zero-size code objects upset the system.
Steve Blockd0582a62009-12-15 09:54:21 +0000367 desc->reloc_size =
368 static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos());
Steve Blocka7e24c12009-10-30 11:49:00 +0000369 desc->origin = this;
370
371 Counters::reloc_info_size.Increment(desc->reloc_size);
372}
373
374
375void Assembler::Align(int m) {
376 ASSERT(IsPowerOf2(m));
Steve Block8defd9f2010-07-08 12:39:36 +0100377 int delta = (m - (pc_offset() & (m - 1))) & (m - 1);
378 while (delta >= 9) {
379 nop(9);
380 delta -= 9;
381 }
382 if (delta > 0) {
383 nop(delta);
Steve Blocka7e24c12009-10-30 11:49:00 +0000384 }
385}
386
387
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100388void Assembler::CodeTargetAlign() {
389 Align(16); // Preferred alignment of jump targets on x64.
390}
391
392
Steve Blocka7e24c12009-10-30 11:49:00 +0000393void Assembler::bind_to(Label* L, int pos) {
394 ASSERT(!L->is_bound()); // Label may only be bound once.
395 last_pc_ = NULL;
396 ASSERT(0 <= pos && pos <= pc_offset()); // Position must be valid.
397 if (L->is_linked()) {
398 int current = L->pos();
399 int next = long_at(current);
400 while (next != current) {
Andrei Popescu31002712010-02-23 13:46:05 +0000401 // Relative address, relative to point after address.
Steve Blocka7e24c12009-10-30 11:49:00 +0000402 int imm32 = pos - (current + sizeof(int32_t));
403 long_at_put(current, imm32);
404 current = next;
405 next = long_at(next);
406 }
407 // Fix up last fixup on linked list.
408 int last_imm32 = pos - (current + sizeof(int32_t));
409 long_at_put(current, last_imm32);
410 }
411 L->bind_to(pos);
412}
413
414
415void Assembler::bind(Label* L) {
416 bind_to(L, pc_offset());
417}
418
419
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100420void Assembler::bind(NearLabel* L) {
421 ASSERT(!L->is_bound());
422 last_pc_ = NULL;
423 while (L->unresolved_branches_ > 0) {
424 int branch_pos = L->unresolved_positions_[L->unresolved_branches_ - 1];
425 int disp = pc_offset() - branch_pos;
426 ASSERT(is_int8(disp));
427 set_byte_at(branch_pos - sizeof(int8_t), disp);
428 L->unresolved_branches_--;
429 }
430 L->bind_to(pc_offset());
431}
432
433
Steve Blocka7e24c12009-10-30 11:49:00 +0000434void Assembler::GrowBuffer() {
Andrei Popescu31002712010-02-23 13:46:05 +0000435 ASSERT(buffer_overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +0000436 if (!own_buffer_) FATAL("external code buffer is too small");
437
Andrei Popescu31002712010-02-23 13:46:05 +0000438 // Compute new buffer size.
Steve Blocka7e24c12009-10-30 11:49:00 +0000439 CodeDesc desc; // the new buffer
440 if (buffer_size_ < 4*KB) {
441 desc.buffer_size = 4*KB;
442 } else {
443 desc.buffer_size = 2*buffer_size_;
444 }
445 // Some internal data structures overflow for very large buffers,
446 // they must ensure that kMaximalBufferSize is not too large.
447 if ((desc.buffer_size > kMaximalBufferSize) ||
Steve Block3ce2e202009-11-05 08:53:23 +0000448 (desc.buffer_size > Heap::MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000449 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
450 }
451
Andrei Popescu31002712010-02-23 13:46:05 +0000452 // Setup new buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +0000453 desc.buffer = NewArray<byte>(desc.buffer_size);
454 desc.instr_size = pc_offset();
Steve Blockd0582a62009-12-15 09:54:21 +0000455 desc.reloc_size =
456 static_cast<int>((buffer_ + buffer_size_) - (reloc_info_writer.pos()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000457
458 // Clear the buffer in debug mode. Use 'int3' instructions to make
459 // sure to get into problems if we ever run uninitialized code.
460#ifdef DEBUG
461 memset(desc.buffer, 0xCC, desc.buffer_size);
462#endif
463
Andrei Popescu31002712010-02-23 13:46:05 +0000464 // Copy the data.
Steve Blocka7e24c12009-10-30 11:49:00 +0000465 intptr_t pc_delta = desc.buffer - buffer_;
466 intptr_t rc_delta = (desc.buffer + desc.buffer_size) -
467 (buffer_ + buffer_size_);
468 memmove(desc.buffer, buffer_, desc.instr_size);
469 memmove(rc_delta + reloc_info_writer.pos(),
470 reloc_info_writer.pos(), desc.reloc_size);
471
Andrei Popescu31002712010-02-23 13:46:05 +0000472 // Switch buffers.
Steve Blocka7e24c12009-10-30 11:49:00 +0000473 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
474 spare_buffer_ = buffer_;
475 } else {
476 DeleteArray(buffer_);
477 }
478 buffer_ = desc.buffer;
479 buffer_size_ = desc.buffer_size;
480 pc_ += pc_delta;
481 if (last_pc_ != NULL) {
482 last_pc_ += pc_delta;
483 }
484 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
485 reloc_info_writer.last_pc() + pc_delta);
486
Andrei Popescu31002712010-02-23 13:46:05 +0000487 // Relocate runtime entries.
Steve Blocka7e24c12009-10-30 11:49:00 +0000488 for (RelocIterator it(desc); !it.done(); it.next()) {
489 RelocInfo::Mode rmode = it.rinfo()->rmode();
490 if (rmode == RelocInfo::INTERNAL_REFERENCE) {
491 intptr_t* p = reinterpret_cast<intptr_t*>(it.rinfo()->pc());
492 if (*p != 0) { // 0 means uninitialized.
493 *p += pc_delta;
494 }
495 }
496 }
497
498 ASSERT(!buffer_overflow());
499}
500
501
502void Assembler::emit_operand(int code, const Operand& adr) {
503 ASSERT(is_uint3(code));
504 const unsigned length = adr.len_;
505 ASSERT(length > 0);
506
507 // Emit updated ModR/M byte containing the given register.
508 ASSERT((adr.buf_[0] & 0x38) == 0);
509 pc_[0] = adr.buf_[0] | code << 3;
510
511 // Emit the rest of the encoded operand.
512 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
513 pc_ += length;
514}
515
516
Andrei Popescu31002712010-02-23 13:46:05 +0000517// Assembler Instruction implementations.
Steve Blocka7e24c12009-10-30 11:49:00 +0000518
519void Assembler::arithmetic_op(byte opcode, Register reg, const Operand& op) {
520 EnsureSpace ensure_space(this);
521 last_pc_ = pc_;
522 emit_rex_64(reg, op);
523 emit(opcode);
524 emit_operand(reg, op);
525}
526
527
528void Assembler::arithmetic_op(byte opcode, Register reg, Register rm_reg) {
529 EnsureSpace ensure_space(this);
530 last_pc_ = pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +0100531 ASSERT((opcode & 0xC6) == 2);
532 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
533 // Swap reg and rm_reg and change opcode operand order.
534 emit_rex_64(rm_reg, reg);
535 emit(opcode ^ 0x02);
536 emit_modrm(rm_reg, reg);
537 } else {
538 emit_rex_64(reg, rm_reg);
539 emit(opcode);
540 emit_modrm(reg, rm_reg);
541 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000542}
543
544
545void Assembler::arithmetic_op_16(byte opcode, Register reg, Register rm_reg) {
546 EnsureSpace ensure_space(this);
547 last_pc_ = pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +0100548 ASSERT((opcode & 0xC6) == 2);
549 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
550 // Swap reg and rm_reg and change opcode operand order.
551 emit(0x66);
552 emit_optional_rex_32(rm_reg, reg);
553 emit(opcode ^ 0x02);
554 emit_modrm(rm_reg, reg);
555 } else {
556 emit(0x66);
557 emit_optional_rex_32(reg, rm_reg);
558 emit(opcode);
559 emit_modrm(reg, rm_reg);
560 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000561}
562
563
564void Assembler::arithmetic_op_16(byte opcode,
565 Register reg,
566 const Operand& rm_reg) {
567 EnsureSpace ensure_space(this);
568 last_pc_ = pc_;
569 emit(0x66);
570 emit_optional_rex_32(reg, rm_reg);
571 emit(opcode);
572 emit_operand(reg, rm_reg);
573}
574
575
576void Assembler::arithmetic_op_32(byte opcode, Register reg, Register rm_reg) {
577 EnsureSpace ensure_space(this);
578 last_pc_ = pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +0100579 ASSERT((opcode & 0xC6) == 2);
580 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
581 // Swap reg and rm_reg and change opcode operand order.
582 emit_optional_rex_32(rm_reg, reg);
583 emit(opcode ^ 0x02); // E.g. 0x03 -> 0x01 for ADD.
584 emit_modrm(rm_reg, reg);
585 } else {
586 emit_optional_rex_32(reg, rm_reg);
587 emit(opcode);
588 emit_modrm(reg, rm_reg);
589 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000590}
591
592
593void Assembler::arithmetic_op_32(byte opcode,
594 Register reg,
595 const Operand& rm_reg) {
596 EnsureSpace ensure_space(this);
597 last_pc_ = pc_;
598 emit_optional_rex_32(reg, rm_reg);
599 emit(opcode);
600 emit_operand(reg, rm_reg);
601}
602
603
604void Assembler::immediate_arithmetic_op(byte subcode,
605 Register dst,
606 Immediate src) {
607 EnsureSpace ensure_space(this);
608 last_pc_ = pc_;
609 emit_rex_64(dst);
610 if (is_int8(src.value_)) {
611 emit(0x83);
612 emit_modrm(subcode, dst);
613 emit(src.value_);
614 } else if (dst.is(rax)) {
615 emit(0x05 | (subcode << 3));
616 emitl(src.value_);
617 } else {
618 emit(0x81);
619 emit_modrm(subcode, dst);
620 emitl(src.value_);
621 }
622}
623
624void Assembler::immediate_arithmetic_op(byte subcode,
625 const Operand& dst,
626 Immediate src) {
627 EnsureSpace ensure_space(this);
628 last_pc_ = pc_;
629 emit_rex_64(dst);
630 if (is_int8(src.value_)) {
631 emit(0x83);
632 emit_operand(subcode, dst);
633 emit(src.value_);
634 } else {
635 emit(0x81);
636 emit_operand(subcode, dst);
637 emitl(src.value_);
638 }
639}
640
641
642void Assembler::immediate_arithmetic_op_16(byte subcode,
643 Register dst,
644 Immediate src) {
645 EnsureSpace ensure_space(this);
646 last_pc_ = pc_;
647 emit(0x66); // Operand size override prefix.
648 emit_optional_rex_32(dst);
649 if (is_int8(src.value_)) {
650 emit(0x83);
651 emit_modrm(subcode, dst);
652 emit(src.value_);
653 } else if (dst.is(rax)) {
654 emit(0x05 | (subcode << 3));
Steve Block3ce2e202009-11-05 08:53:23 +0000655 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000656 } else {
657 emit(0x81);
658 emit_modrm(subcode, dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000659 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000660 }
661}
662
663
664void Assembler::immediate_arithmetic_op_16(byte subcode,
665 const Operand& dst,
666 Immediate src) {
667 EnsureSpace ensure_space(this);
668 last_pc_ = pc_;
669 emit(0x66); // Operand size override prefix.
670 emit_optional_rex_32(dst);
671 if (is_int8(src.value_)) {
672 emit(0x83);
673 emit_operand(subcode, dst);
674 emit(src.value_);
675 } else {
676 emit(0x81);
677 emit_operand(subcode, dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000678 emitw(src.value_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000679 }
680}
681
682
683void Assembler::immediate_arithmetic_op_32(byte subcode,
684 Register dst,
685 Immediate src) {
686 EnsureSpace ensure_space(this);
687 last_pc_ = pc_;
688 emit_optional_rex_32(dst);
689 if (is_int8(src.value_)) {
690 emit(0x83);
691 emit_modrm(subcode, dst);
692 emit(src.value_);
693 } else if (dst.is(rax)) {
694 emit(0x05 | (subcode << 3));
695 emitl(src.value_);
696 } else {
697 emit(0x81);
698 emit_modrm(subcode, dst);
699 emitl(src.value_);
700 }
701}
702
703
704void Assembler::immediate_arithmetic_op_32(byte subcode,
705 const Operand& dst,
706 Immediate src) {
707 EnsureSpace ensure_space(this);
708 last_pc_ = pc_;
709 emit_optional_rex_32(dst);
710 if (is_int8(src.value_)) {
711 emit(0x83);
712 emit_operand(subcode, dst);
713 emit(src.value_);
714 } else {
715 emit(0x81);
716 emit_operand(subcode, dst);
717 emitl(src.value_);
718 }
719}
720
721
722void Assembler::immediate_arithmetic_op_8(byte subcode,
723 const Operand& dst,
724 Immediate src) {
725 EnsureSpace ensure_space(this);
726 last_pc_ = pc_;
727 emit_optional_rex_32(dst);
728 ASSERT(is_int8(src.value_) || is_uint8(src.value_));
729 emit(0x80);
730 emit_operand(subcode, dst);
731 emit(src.value_);
732}
733
734
735void Assembler::immediate_arithmetic_op_8(byte subcode,
736 Register dst,
737 Immediate src) {
738 EnsureSpace ensure_space(this);
739 last_pc_ = pc_;
740 if (dst.code() > 3) {
741 // Use 64-bit mode byte registers.
742 emit_rex_64(dst);
743 }
744 ASSERT(is_int8(src.value_) || is_uint8(src.value_));
745 emit(0x80);
746 emit_modrm(subcode, dst);
747 emit(src.value_);
748}
749
750
751void Assembler::shift(Register dst, Immediate shift_amount, int subcode) {
752 EnsureSpace ensure_space(this);
753 last_pc_ = pc_;
754 ASSERT(is_uint6(shift_amount.value_)); // illegal shift count
755 if (shift_amount.value_ == 1) {
756 emit_rex_64(dst);
757 emit(0xD1);
758 emit_modrm(subcode, dst);
759 } else {
760 emit_rex_64(dst);
761 emit(0xC1);
762 emit_modrm(subcode, dst);
763 emit(shift_amount.value_);
764 }
765}
766
767
768void Assembler::shift(Register dst, int subcode) {
769 EnsureSpace ensure_space(this);
770 last_pc_ = pc_;
771 emit_rex_64(dst);
772 emit(0xD3);
773 emit_modrm(subcode, dst);
774}
775
776
777void Assembler::shift_32(Register dst, int subcode) {
778 EnsureSpace ensure_space(this);
779 last_pc_ = pc_;
780 emit_optional_rex_32(dst);
781 emit(0xD3);
782 emit_modrm(subcode, dst);
783}
784
785
786void Assembler::shift_32(Register dst, Immediate shift_amount, int subcode) {
787 EnsureSpace ensure_space(this);
788 last_pc_ = pc_;
Steve Block3ce2e202009-11-05 08:53:23 +0000789 ASSERT(is_uint5(shift_amount.value_)); // illegal shift count
Steve Blocka7e24c12009-10-30 11:49:00 +0000790 if (shift_amount.value_ == 1) {
791 emit_optional_rex_32(dst);
792 emit(0xD1);
793 emit_modrm(subcode, dst);
794 } else {
795 emit_optional_rex_32(dst);
796 emit(0xC1);
797 emit_modrm(subcode, dst);
798 emit(shift_amount.value_);
799 }
800}
801
802
803void Assembler::bt(const Operand& dst, Register src) {
804 EnsureSpace ensure_space(this);
805 last_pc_ = pc_;
806 emit_rex_64(src, dst);
807 emit(0x0F);
808 emit(0xA3);
809 emit_operand(src, dst);
810}
811
812
813void Assembler::bts(const Operand& dst, Register src) {
814 EnsureSpace ensure_space(this);
815 last_pc_ = pc_;
816 emit_rex_64(src, dst);
817 emit(0x0F);
818 emit(0xAB);
819 emit_operand(src, dst);
820}
821
822
823void Assembler::call(Label* L) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100824 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000825 EnsureSpace ensure_space(this);
826 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000827 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +0000828 emit(0xE8);
829 if (L->is_bound()) {
830 int offset = L->pos() - pc_offset() - sizeof(int32_t);
831 ASSERT(offset <= 0);
832 emitl(offset);
833 } else if (L->is_linked()) {
834 emitl(L->pos());
835 L->link_to(pc_offset() - sizeof(int32_t));
836 } else {
837 ASSERT(L->is_unused());
838 int32_t current = pc_offset();
839 emitl(current);
840 L->link_to(current);
841 }
842}
843
844
Steve Block3ce2e202009-11-05 08:53:23 +0000845void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800846 positions_recorder()->WriteRecordedPositions();
Steve Block3ce2e202009-11-05 08:53:23 +0000847 EnsureSpace ensure_space(this);
848 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000849 // 1110 1000 #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +0000850 emit(0xE8);
851 emit_code_target(target, rmode);
852}
853
854
Steve Blocka7e24c12009-10-30 11:49:00 +0000855void Assembler::call(Register adr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100856 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000857 EnsureSpace ensure_space(this);
858 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000859 // Opcode: FF /2 r64.
Steve Block8defd9f2010-07-08 12:39:36 +0100860 emit_optional_rex_32(adr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000861 emit(0xFF);
862 emit_modrm(0x2, adr);
863}
864
865
866void Assembler::call(const Operand& op) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100867 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +0000868 EnsureSpace ensure_space(this);
869 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000870 // Opcode: FF /2 m64.
Steve Block8defd9f2010-07-08 12:39:36 +0100871 emit_optional_rex_32(op);
Steve Blocka7e24c12009-10-30 11:49:00 +0000872 emit(0xFF);
Steve Block8defd9f2010-07-08 12:39:36 +0100873 emit_operand(0x2, op);
Steve Blocka7e24c12009-10-30 11:49:00 +0000874}
875
876
Steve Block3ce2e202009-11-05 08:53:23 +0000877void Assembler::clc() {
878 EnsureSpace ensure_space(this);
879 last_pc_ = pc_;
880 emit(0xF8);
881}
882
Steve Blocka7e24c12009-10-30 11:49:00 +0000883void Assembler::cdq() {
884 EnsureSpace ensure_space(this);
885 last_pc_ = pc_;
886 emit(0x99);
887}
888
889
890void Assembler::cmovq(Condition cc, Register dst, Register src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000891 if (cc == always) {
892 movq(dst, src);
893 } else if (cc == never) {
894 return;
895 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000896 // No need to check CpuInfo for CMOV support, it's a required part of the
897 // 64-bit architecture.
898 ASSERT(cc >= 0); // Use mov for unconditional moves.
899 EnsureSpace ensure_space(this);
900 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000901 // Opcode: REX.W 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000902 emit_rex_64(dst, src);
903 emit(0x0f);
904 emit(0x40 + cc);
905 emit_modrm(dst, src);
906}
907
908
909void Assembler::cmovq(Condition cc, Register dst, const Operand& src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000910 if (cc == always) {
911 movq(dst, src);
912 } else if (cc == never) {
913 return;
914 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000915 ASSERT(cc >= 0);
916 EnsureSpace ensure_space(this);
917 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000918 // Opcode: REX.W 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000919 emit_rex_64(dst, src);
920 emit(0x0f);
921 emit(0x40 + cc);
922 emit_operand(dst, src);
923}
924
925
926void Assembler::cmovl(Condition cc, Register dst, Register src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000927 if (cc == always) {
928 movl(dst, src);
929 } else if (cc == never) {
930 return;
931 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000932 ASSERT(cc >= 0);
933 EnsureSpace ensure_space(this);
934 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000935 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000936 emit_optional_rex_32(dst, src);
937 emit(0x0f);
938 emit(0x40 + cc);
939 emit_modrm(dst, src);
940}
941
942
943void Assembler::cmovl(Condition cc, Register dst, const Operand& src) {
Steve Block3ce2e202009-11-05 08:53:23 +0000944 if (cc == always) {
945 movl(dst, src);
946 } else if (cc == never) {
947 return;
948 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000949 ASSERT(cc >= 0);
950 EnsureSpace ensure_space(this);
951 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000952 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000953 emit_optional_rex_32(dst, src);
954 emit(0x0f);
955 emit(0x40 + cc);
956 emit_operand(dst, src);
957}
958
959
960void Assembler::cmpb_al(Immediate imm8) {
961 ASSERT(is_int8(imm8.value_) || is_uint8(imm8.value_));
962 EnsureSpace ensure_space(this);
963 last_pc_ = pc_;
964 emit(0x3c);
965 emit(imm8.value_);
966}
967
968
969void Assembler::cpuid() {
Steve Blockd0582a62009-12-15 09:54:21 +0000970 ASSERT(CpuFeatures::IsEnabled(CPUID));
Steve Blocka7e24c12009-10-30 11:49:00 +0000971 EnsureSpace ensure_space(this);
972 last_pc_ = pc_;
973 emit(0x0F);
974 emit(0xA2);
975}
976
977
978void Assembler::cqo() {
979 EnsureSpace ensure_space(this);
980 last_pc_ = pc_;
981 emit_rex_64();
982 emit(0x99);
983}
984
985
986void Assembler::decq(Register dst) {
987 EnsureSpace ensure_space(this);
988 last_pc_ = pc_;
989 emit_rex_64(dst);
990 emit(0xFF);
991 emit_modrm(0x1, dst);
992}
993
994
995void Assembler::decq(const Operand& dst) {
996 EnsureSpace ensure_space(this);
997 last_pc_ = pc_;
998 emit_rex_64(dst);
999 emit(0xFF);
1000 emit_operand(1, dst);
1001}
1002
1003
1004void Assembler::decl(Register dst) {
1005 EnsureSpace ensure_space(this);
1006 last_pc_ = pc_;
1007 emit_optional_rex_32(dst);
1008 emit(0xFF);
1009 emit_modrm(0x1, dst);
1010}
1011
1012
1013void Assembler::decl(const Operand& dst) {
1014 EnsureSpace ensure_space(this);
1015 last_pc_ = pc_;
1016 emit_optional_rex_32(dst);
1017 emit(0xFF);
1018 emit_operand(1, dst);
1019}
1020
1021
Steve Block3ce2e202009-11-05 08:53:23 +00001022void Assembler::decb(Register dst) {
1023 EnsureSpace ensure_space(this);
1024 last_pc_ = pc_;
1025 if (dst.code() > 3) {
1026 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1027 emit_rex_32(dst);
1028 }
1029 emit(0xFE);
1030 emit_modrm(0x1, dst);
1031}
1032
1033
1034void Assembler::decb(const Operand& dst) {
1035 EnsureSpace ensure_space(this);
1036 last_pc_ = pc_;
1037 emit_optional_rex_32(dst);
1038 emit(0xFE);
1039 emit_operand(1, dst);
1040}
1041
1042
Steve Blocka7e24c12009-10-30 11:49:00 +00001043void Assembler::enter(Immediate size) {
1044 EnsureSpace ensure_space(this);
1045 last_pc_ = pc_;
1046 emit(0xC8);
1047 emitw(size.value_); // 16 bit operand, always.
1048 emit(0);
1049}
1050
1051
1052void Assembler::hlt() {
1053 EnsureSpace ensure_space(this);
1054 last_pc_ = pc_;
1055 emit(0xF4);
1056}
1057
1058
1059void Assembler::idivq(Register src) {
1060 EnsureSpace ensure_space(this);
1061 last_pc_ = pc_;
1062 emit_rex_64(src);
1063 emit(0xF7);
1064 emit_modrm(0x7, src);
1065}
1066
1067
1068void Assembler::idivl(Register src) {
1069 EnsureSpace ensure_space(this);
1070 last_pc_ = pc_;
1071 emit_optional_rex_32(src);
1072 emit(0xF7);
1073 emit_modrm(0x7, src);
1074}
1075
1076
1077void Assembler::imul(Register src) {
1078 EnsureSpace ensure_space(this);
1079 last_pc_ = pc_;
1080 emit_rex_64(src);
1081 emit(0xF7);
1082 emit_modrm(0x5, src);
1083}
1084
1085
1086void Assembler::imul(Register dst, Register src) {
1087 EnsureSpace ensure_space(this);
1088 last_pc_ = pc_;
1089 emit_rex_64(dst, src);
1090 emit(0x0F);
1091 emit(0xAF);
1092 emit_modrm(dst, src);
1093}
1094
1095
1096void Assembler::imul(Register dst, const Operand& src) {
1097 EnsureSpace ensure_space(this);
1098 last_pc_ = pc_;
1099 emit_rex_64(dst, src);
1100 emit(0x0F);
1101 emit(0xAF);
1102 emit_operand(dst, src);
1103}
1104
1105
1106void Assembler::imul(Register dst, Register src, Immediate imm) {
1107 EnsureSpace ensure_space(this);
1108 last_pc_ = pc_;
1109 emit_rex_64(dst, src);
1110 if (is_int8(imm.value_)) {
1111 emit(0x6B);
1112 emit_modrm(dst, src);
1113 emit(imm.value_);
1114 } else {
1115 emit(0x69);
1116 emit_modrm(dst, src);
1117 emitl(imm.value_);
1118 }
1119}
1120
1121
1122void Assembler::imull(Register dst, Register src) {
1123 EnsureSpace ensure_space(this);
1124 last_pc_ = pc_;
1125 emit_optional_rex_32(dst, src);
1126 emit(0x0F);
1127 emit(0xAF);
1128 emit_modrm(dst, src);
1129}
1130
1131
Steve Block6ded16b2010-05-10 14:33:55 +01001132void Assembler::imull(Register dst, Register src, Immediate imm) {
1133 EnsureSpace ensure_space(this);
1134 last_pc_ = pc_;
1135 emit_optional_rex_32(dst, src);
1136 if (is_int8(imm.value_)) {
1137 emit(0x6B);
1138 emit_modrm(dst, src);
1139 emit(imm.value_);
1140 } else {
1141 emit(0x69);
1142 emit_modrm(dst, src);
1143 emitl(imm.value_);
1144 }
1145}
1146
1147
Steve Blocka7e24c12009-10-30 11:49:00 +00001148void Assembler::incq(Register dst) {
1149 EnsureSpace ensure_space(this);
1150 last_pc_ = pc_;
1151 emit_rex_64(dst);
1152 emit(0xFF);
1153 emit_modrm(0x0, dst);
1154}
1155
1156
1157void Assembler::incq(const Operand& dst) {
1158 EnsureSpace ensure_space(this);
1159 last_pc_ = pc_;
1160 emit_rex_64(dst);
1161 emit(0xFF);
1162 emit_operand(0, dst);
1163}
1164
1165
1166void Assembler::incl(const Operand& dst) {
1167 EnsureSpace ensure_space(this);
1168 last_pc_ = pc_;
1169 emit_optional_rex_32(dst);
1170 emit(0xFF);
1171 emit_operand(0, dst);
1172}
1173
1174
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001175void Assembler::incl(Register dst) {
1176 EnsureSpace ensure_space(this);
1177 last_pc_ = pc_;
1178 emit_optional_rex_32(dst);
1179 emit(0xFF);
1180 emit_modrm(0, dst);
1181}
1182
1183
Steve Blocka7e24c12009-10-30 11:49:00 +00001184void Assembler::int3() {
1185 EnsureSpace ensure_space(this);
1186 last_pc_ = pc_;
1187 emit(0xCC);
1188}
1189
1190
1191void Assembler::j(Condition cc, Label* L) {
Steve Block3ce2e202009-11-05 08:53:23 +00001192 if (cc == always) {
1193 jmp(L);
1194 return;
1195 } else if (cc == never) {
1196 return;
1197 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001198 EnsureSpace ensure_space(this);
1199 last_pc_ = pc_;
1200 ASSERT(is_uint4(cc));
1201 if (L->is_bound()) {
1202 const int short_size = 2;
1203 const int long_size = 6;
1204 int offs = L->pos() - pc_offset();
1205 ASSERT(offs <= 0);
1206 if (is_int8(offs - short_size)) {
Andrei Popescu31002712010-02-23 13:46:05 +00001207 // 0111 tttn #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001208 emit(0x70 | cc);
1209 emit((offs - short_size) & 0xFF);
1210 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001211 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001212 emit(0x0F);
1213 emit(0x80 | cc);
1214 emitl(offs - long_size);
1215 }
1216 } else if (L->is_linked()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001217 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001218 emit(0x0F);
1219 emit(0x80 | cc);
1220 emitl(L->pos());
1221 L->link_to(pc_offset() - sizeof(int32_t));
1222 } else {
1223 ASSERT(L->is_unused());
1224 emit(0x0F);
1225 emit(0x80 | cc);
1226 int32_t current = pc_offset();
1227 emitl(current);
1228 L->link_to(current);
1229 }
1230}
1231
1232
Steve Block3ce2e202009-11-05 08:53:23 +00001233void Assembler::j(Condition cc,
1234 Handle<Code> target,
1235 RelocInfo::Mode rmode) {
1236 EnsureSpace ensure_space(this);
1237 last_pc_ = pc_;
1238 ASSERT(is_uint4(cc));
Andrei Popescu31002712010-02-23 13:46:05 +00001239 // 0000 1111 1000 tttn #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +00001240 emit(0x0F);
1241 emit(0x80 | cc);
1242 emit_code_target(target, rmode);
1243}
1244
1245
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001246void Assembler::j(Condition cc, NearLabel* L, Hint hint) {
1247 EnsureSpace ensure_space(this);
1248 last_pc_ = pc_;
1249 ASSERT(0 <= cc && cc < 16);
1250 if (FLAG_emit_branch_hints && hint != no_hint) emit(hint);
1251 if (L->is_bound()) {
1252 const int short_size = 2;
1253 int offs = L->pos() - pc_offset();
1254 ASSERT(offs <= 0);
1255 ASSERT(is_int8(offs - short_size));
1256 // 0111 tttn #8-bit disp
1257 emit(0x70 | cc);
1258 emit((offs - short_size) & 0xFF);
1259 } else {
1260 emit(0x70 | cc);
1261 emit(0x00); // The displacement will be resolved later.
1262 L->link_to(pc_offset());
1263 }
1264}
1265
1266
Steve Blocka7e24c12009-10-30 11:49:00 +00001267void Assembler::jmp(Label* L) {
1268 EnsureSpace ensure_space(this);
1269 last_pc_ = pc_;
Steve Block6ded16b2010-05-10 14:33:55 +01001270 const int short_size = sizeof(int8_t);
1271 const int long_size = sizeof(int32_t);
Steve Blocka7e24c12009-10-30 11:49:00 +00001272 if (L->is_bound()) {
1273 int offs = L->pos() - pc_offset() - 1;
1274 ASSERT(offs <= 0);
Steve Block6ded16b2010-05-10 14:33:55 +01001275 if (is_int8(offs - short_size)) {
Andrei Popescu31002712010-02-23 13:46:05 +00001276 // 1110 1011 #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001277 emit(0xEB);
Steve Block6ded16b2010-05-10 14:33:55 +01001278 emit((offs - short_size) & 0xFF);
Steve Blocka7e24c12009-10-30 11:49:00 +00001279 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001280 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001281 emit(0xE9);
Steve Block6ded16b2010-05-10 14:33:55 +01001282 emitl(offs - long_size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001283 }
1284 } else if (L->is_linked()) {
Andrei Popescu31002712010-02-23 13:46:05 +00001285 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001286 emit(0xE9);
1287 emitl(L->pos());
Steve Block6ded16b2010-05-10 14:33:55 +01001288 L->link_to(pc_offset() - long_size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001289 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001290 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001291 ASSERT(L->is_unused());
1292 emit(0xE9);
1293 int32_t current = pc_offset();
1294 emitl(current);
1295 L->link_to(current);
1296 }
1297}
1298
1299
Steve Block3ce2e202009-11-05 08:53:23 +00001300void Assembler::jmp(Handle<Code> target, RelocInfo::Mode rmode) {
1301 EnsureSpace ensure_space(this);
1302 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +00001303 // 1110 1001 #32-bit disp.
Steve Block3ce2e202009-11-05 08:53:23 +00001304 emit(0xE9);
1305 emit_code_target(target, rmode);
1306}
1307
1308
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001309void Assembler::jmp(NearLabel* L) {
1310 EnsureSpace ensure_space(this);
1311 last_pc_ = pc_;
1312 if (L->is_bound()) {
1313 const int short_size = sizeof(int8_t);
1314 int offs = L->pos() - pc_offset();
1315 ASSERT(offs <= 0);
1316 ASSERT(is_int8(offs - short_size));
1317 // 1110 1011 #8-bit disp.
1318 emit(0xEB);
1319 emit((offs - short_size) & 0xFF);
1320 } else {
1321 emit(0xEB);
1322 emit(0x00); // The displacement will be resolved later.
1323 L->link_to(pc_offset());
1324 }
1325}
1326
1327
Steve Blocka7e24c12009-10-30 11:49:00 +00001328void Assembler::jmp(Register target) {
1329 EnsureSpace ensure_space(this);
1330 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +00001331 // Opcode FF/4 r64.
Steve Block8defd9f2010-07-08 12:39:36 +01001332 emit_optional_rex_32(target);
Steve Blocka7e24c12009-10-30 11:49:00 +00001333 emit(0xFF);
1334 emit_modrm(0x4, target);
1335}
1336
1337
1338void Assembler::jmp(const Operand& src) {
1339 EnsureSpace ensure_space(this);
1340 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +00001341 // Opcode FF/4 m64.
Steve Blocka7e24c12009-10-30 11:49:00 +00001342 emit_optional_rex_32(src);
1343 emit(0xFF);
1344 emit_operand(0x4, src);
1345}
1346
1347
1348void Assembler::lea(Register dst, const Operand& src) {
1349 EnsureSpace ensure_space(this);
1350 last_pc_ = pc_;
1351 emit_rex_64(dst, src);
1352 emit(0x8D);
1353 emit_operand(dst, src);
1354}
1355
1356
Steve Block6ded16b2010-05-10 14:33:55 +01001357void Assembler::leal(Register dst, const Operand& src) {
1358 EnsureSpace ensure_space(this);
1359 last_pc_ = pc_;
1360 emit_optional_rex_32(dst, src);
1361 emit(0x8D);
1362 emit_operand(dst, src);
1363}
1364
1365
Steve Blocka7e24c12009-10-30 11:49:00 +00001366void Assembler::load_rax(void* value, RelocInfo::Mode mode) {
1367 EnsureSpace ensure_space(this);
1368 last_pc_ = pc_;
1369 emit(0x48); // REX.W
1370 emit(0xA1);
1371 emitq(reinterpret_cast<uintptr_t>(value), mode);
1372}
1373
1374
1375void Assembler::load_rax(ExternalReference ref) {
1376 load_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
1377}
1378
1379
1380void Assembler::leave() {
1381 EnsureSpace ensure_space(this);
1382 last_pc_ = pc_;
1383 emit(0xC9);
1384}
1385
1386
1387void Assembler::movb(Register dst, const Operand& src) {
1388 EnsureSpace ensure_space(this);
1389 last_pc_ = pc_;
1390 emit_rex_32(dst, src);
1391 emit(0x8A);
1392 emit_operand(dst, src);
1393}
1394
Steve Block6ded16b2010-05-10 14:33:55 +01001395
Steve Blocka7e24c12009-10-30 11:49:00 +00001396void Assembler::movb(Register dst, Immediate imm) {
1397 EnsureSpace ensure_space(this);
1398 last_pc_ = pc_;
1399 emit_rex_32(dst);
1400 emit(0xC6);
1401 emit_modrm(0x0, dst);
1402 emit(imm.value_);
1403}
1404
Steve Block6ded16b2010-05-10 14:33:55 +01001405
Steve Blocka7e24c12009-10-30 11:49:00 +00001406void Assembler::movb(const Operand& dst, Register src) {
1407 EnsureSpace ensure_space(this);
1408 last_pc_ = pc_;
1409 emit_rex_32(src, dst);
1410 emit(0x88);
1411 emit_operand(src, dst);
1412}
1413
Steve Block6ded16b2010-05-10 14:33:55 +01001414
Steve Block3ce2e202009-11-05 08:53:23 +00001415void Assembler::movw(const Operand& dst, Register src) {
1416 EnsureSpace ensure_space(this);
1417 last_pc_ = pc_;
1418 emit(0x66);
1419 emit_optional_rex_32(src, dst);
1420 emit(0x89);
1421 emit_operand(src, dst);
1422}
1423
Steve Block6ded16b2010-05-10 14:33:55 +01001424
Steve Blocka7e24c12009-10-30 11:49:00 +00001425void Assembler::movl(Register dst, const Operand& src) {
1426 EnsureSpace ensure_space(this);
1427 last_pc_ = pc_;
1428 emit_optional_rex_32(dst, src);
1429 emit(0x8B);
1430 emit_operand(dst, src);
1431}
1432
1433
1434void Assembler::movl(Register dst, Register src) {
1435 EnsureSpace ensure_space(this);
1436 last_pc_ = pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +01001437 if (src.low_bits() == 4) {
1438 emit_optional_rex_32(src, dst);
1439 emit(0x89);
1440 emit_modrm(src, dst);
1441 } else {
1442 emit_optional_rex_32(dst, src);
1443 emit(0x8B);
1444 emit_modrm(dst, src);
1445 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001446}
1447
1448
1449void Assembler::movl(const Operand& dst, Register src) {
1450 EnsureSpace ensure_space(this);
1451 last_pc_ = pc_;
1452 emit_optional_rex_32(src, dst);
1453 emit(0x89);
1454 emit_operand(src, dst);
1455}
1456
1457
1458void Assembler::movl(const Operand& dst, Immediate value) {
1459 EnsureSpace ensure_space(this);
1460 last_pc_ = pc_;
1461 emit_optional_rex_32(dst);
1462 emit(0xC7);
1463 emit_operand(0x0, dst);
1464 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates.
1465}
1466
1467
1468void Assembler::movl(Register dst, Immediate value) {
1469 EnsureSpace ensure_space(this);
1470 last_pc_ = pc_;
1471 emit_optional_rex_32(dst);
1472 emit(0xC7);
1473 emit_modrm(0x0, dst);
1474 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates.
1475}
1476
1477
1478void Assembler::movq(Register dst, const Operand& src) {
1479 EnsureSpace ensure_space(this);
1480 last_pc_ = pc_;
1481 emit_rex_64(dst, src);
1482 emit(0x8B);
1483 emit_operand(dst, src);
1484}
1485
1486
1487void Assembler::movq(Register dst, Register src) {
1488 EnsureSpace ensure_space(this);
1489 last_pc_ = pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +01001490 if (src.low_bits() == 4) {
1491 emit_rex_64(src, dst);
1492 emit(0x89);
1493 emit_modrm(src, dst);
1494 } else {
1495 emit_rex_64(dst, src);
1496 emit(0x8B);
1497 emit_modrm(dst, src);
1498 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001499}
1500
1501
1502void Assembler::movq(Register dst, Immediate value) {
1503 EnsureSpace ensure_space(this);
1504 last_pc_ = pc_;
1505 emit_rex_64(dst);
1506 emit(0xC7);
1507 emit_modrm(0x0, dst);
1508 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates.
1509}
1510
1511
1512void Assembler::movq(const Operand& dst, Register src) {
1513 EnsureSpace ensure_space(this);
1514 last_pc_ = pc_;
1515 emit_rex_64(src, dst);
1516 emit(0x89);
1517 emit_operand(src, dst);
1518}
1519
1520
1521void Assembler::movq(Register dst, void* value, RelocInfo::Mode rmode) {
1522 // This method must not be used with heap object references. The stored
1523 // address is not GC safe. Use the handle version instead.
1524 ASSERT(rmode > RelocInfo::LAST_GCED_ENUM);
1525 EnsureSpace ensure_space(this);
1526 last_pc_ = pc_;
1527 emit_rex_64(dst);
1528 emit(0xB8 | dst.low_bits());
1529 emitq(reinterpret_cast<uintptr_t>(value), rmode);
1530}
1531
1532
1533void Assembler::movq(Register dst, int64_t value, RelocInfo::Mode rmode) {
1534 // Non-relocatable values might not need a 64-bit representation.
1535 if (rmode == RelocInfo::NONE) {
1536 // Sadly, there is no zero or sign extending move for 8-bit immediates.
1537 if (is_int32(value)) {
1538 movq(dst, Immediate(static_cast<int32_t>(value)));
1539 return;
1540 } else if (is_uint32(value)) {
1541 movl(dst, Immediate(static_cast<int32_t>(value)));
1542 return;
1543 }
1544 // Value cannot be represented by 32 bits, so do a full 64 bit immediate
1545 // value.
1546 }
1547 EnsureSpace ensure_space(this);
1548 last_pc_ = pc_;
1549 emit_rex_64(dst);
1550 emit(0xB8 | dst.low_bits());
1551 emitq(value, rmode);
1552}
1553
1554
1555void Assembler::movq(Register dst, ExternalReference ref) {
Ben Murdochbb769b22010-08-11 14:56:33 +01001556 int64_t value = reinterpret_cast<int64_t>(ref.address());
1557 movq(dst, value, RelocInfo::EXTERNAL_REFERENCE);
Steve Blocka7e24c12009-10-30 11:49:00 +00001558}
1559
1560
1561void Assembler::movq(const Operand& dst, Immediate value) {
1562 EnsureSpace ensure_space(this);
1563 last_pc_ = pc_;
1564 emit_rex_64(dst);
1565 emit(0xC7);
1566 emit_operand(0, dst);
1567 emit(value);
1568}
1569
1570
Andrei Popescu31002712010-02-23 13:46:05 +00001571// Loads the ip-relative location of the src label into the target location
1572// (as a 32-bit offset sign extended to 64-bit).
Steve Blocka7e24c12009-10-30 11:49:00 +00001573void Assembler::movl(const Operand& dst, Label* src) {
1574 EnsureSpace ensure_space(this);
1575 last_pc_ = pc_;
1576 emit_optional_rex_32(dst);
1577 emit(0xC7);
1578 emit_operand(0, dst);
1579 if (src->is_bound()) {
1580 int offset = src->pos() - pc_offset() - sizeof(int32_t);
1581 ASSERT(offset <= 0);
1582 emitl(offset);
1583 } else if (src->is_linked()) {
1584 emitl(src->pos());
1585 src->link_to(pc_offset() - sizeof(int32_t));
1586 } else {
1587 ASSERT(src->is_unused());
1588 int32_t current = pc_offset();
1589 emitl(current);
1590 src->link_to(current);
1591 }
1592}
1593
1594
1595void Assembler::movq(Register dst, Handle<Object> value, RelocInfo::Mode mode) {
1596 // If there is no relocation info, emit the value of the handle efficiently
1597 // (possibly using less that 8 bytes for the value).
1598 if (mode == RelocInfo::NONE) {
1599 // There is no possible reason to store a heap pointer without relocation
1600 // info, so it must be a smi.
1601 ASSERT(value->IsSmi());
Steve Block3ce2e202009-11-05 08:53:23 +00001602 movq(dst, reinterpret_cast<int64_t>(*value), RelocInfo::NONE);
Steve Blocka7e24c12009-10-30 11:49:00 +00001603 } else {
1604 EnsureSpace ensure_space(this);
1605 last_pc_ = pc_;
1606 ASSERT(value->IsHeapObject());
1607 ASSERT(!Heap::InNewSpace(*value));
1608 emit_rex_64(dst);
1609 emit(0xB8 | dst.low_bits());
1610 emitq(reinterpret_cast<uintptr_t>(value.location()), mode);
1611 }
1612}
1613
1614
Steve Block3ce2e202009-11-05 08:53:23 +00001615void Assembler::movsxbq(Register dst, const Operand& src) {
1616 EnsureSpace ensure_space(this);
1617 last_pc_ = pc_;
Steve Block8defd9f2010-07-08 12:39:36 +01001618 emit_rex_64(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00001619 emit(0x0F);
1620 emit(0xBE);
1621 emit_operand(dst, src);
1622}
1623
1624
1625void Assembler::movsxwq(Register dst, const Operand& src) {
1626 EnsureSpace ensure_space(this);
1627 last_pc_ = pc_;
1628 emit_rex_64(dst, src);
1629 emit(0x0F);
1630 emit(0xBF);
1631 emit_operand(dst, src);
1632}
1633
1634
Steve Blocka7e24c12009-10-30 11:49:00 +00001635void Assembler::movsxlq(Register dst, Register src) {
1636 EnsureSpace ensure_space(this);
1637 last_pc_ = pc_;
1638 emit_rex_64(dst, src);
1639 emit(0x63);
1640 emit_modrm(dst, src);
1641}
1642
1643
1644void Assembler::movsxlq(Register dst, const Operand& src) {
1645 EnsureSpace ensure_space(this);
1646 last_pc_ = pc_;
1647 emit_rex_64(dst, src);
1648 emit(0x63);
1649 emit_operand(dst, src);
1650}
1651
1652
1653void Assembler::movzxbq(Register dst, const Operand& src) {
1654 EnsureSpace ensure_space(this);
1655 last_pc_ = pc_;
Steve Block8defd9f2010-07-08 12:39:36 +01001656 emit_optional_rex_32(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001657 emit(0x0F);
1658 emit(0xB6);
1659 emit_operand(dst, src);
1660}
1661
1662
1663void Assembler::movzxbl(Register dst, const Operand& src) {
1664 EnsureSpace ensure_space(this);
1665 last_pc_ = pc_;
1666 emit_optional_rex_32(dst, src);
1667 emit(0x0F);
1668 emit(0xB6);
1669 emit_operand(dst, src);
1670}
1671
1672
Steve Block3ce2e202009-11-05 08:53:23 +00001673void Assembler::movzxwq(Register dst, const Operand& src) {
1674 EnsureSpace ensure_space(this);
1675 last_pc_ = pc_;
Steve Block8defd9f2010-07-08 12:39:36 +01001676 emit_optional_rex_32(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00001677 emit(0x0F);
1678 emit(0xB7);
1679 emit_operand(dst, src);
1680}
1681
1682
Steve Blocka7e24c12009-10-30 11:49:00 +00001683void Assembler::movzxwl(Register dst, const Operand& src) {
1684 EnsureSpace ensure_space(this);
1685 last_pc_ = pc_;
1686 emit_optional_rex_32(dst, src);
1687 emit(0x0F);
1688 emit(0xB7);
1689 emit_operand(dst, src);
1690}
1691
1692
Leon Clarked91b9f72010-01-27 17:25:45 +00001693void Assembler::repmovsb() {
1694 EnsureSpace ensure_space(this);
1695 last_pc_ = pc_;
1696 emit(0xF3);
1697 emit(0xA4);
1698}
1699
1700
1701void Assembler::repmovsw() {
1702 EnsureSpace ensure_space(this);
1703 last_pc_ = pc_;
1704 emit(0x66); // Operand size override.
1705 emit(0xF3);
1706 emit(0xA4);
1707}
1708
1709
1710void Assembler::repmovsl() {
1711 EnsureSpace ensure_space(this);
1712 last_pc_ = pc_;
1713 emit(0xF3);
1714 emit(0xA5);
1715}
1716
1717
1718void Assembler::repmovsq() {
1719 EnsureSpace ensure_space(this);
1720 last_pc_ = pc_;
1721 emit(0xF3);
1722 emit_rex_64();
1723 emit(0xA5);
1724}
1725
1726
Steve Blocka7e24c12009-10-30 11:49:00 +00001727void Assembler::mul(Register src) {
1728 EnsureSpace ensure_space(this);
1729 last_pc_ = pc_;
1730 emit_rex_64(src);
1731 emit(0xF7);
1732 emit_modrm(0x4, src);
1733}
1734
1735
1736void Assembler::neg(Register dst) {
1737 EnsureSpace ensure_space(this);
1738 last_pc_ = pc_;
1739 emit_rex_64(dst);
1740 emit(0xF7);
1741 emit_modrm(0x3, dst);
1742}
1743
1744
1745void Assembler::negl(Register dst) {
1746 EnsureSpace ensure_space(this);
1747 last_pc_ = pc_;
1748 emit_optional_rex_32(dst);
1749 emit(0xF7);
1750 emit_modrm(0x3, dst);
1751}
1752
1753
1754void Assembler::neg(const Operand& dst) {
1755 EnsureSpace ensure_space(this);
1756 last_pc_ = pc_;
1757 emit_rex_64(dst);
1758 emit(0xF7);
1759 emit_operand(3, dst);
1760}
1761
1762
1763void Assembler::nop() {
1764 EnsureSpace ensure_space(this);
1765 last_pc_ = pc_;
1766 emit(0x90);
1767}
1768
1769
1770void Assembler::not_(Register dst) {
1771 EnsureSpace ensure_space(this);
1772 last_pc_ = pc_;
1773 emit_rex_64(dst);
1774 emit(0xF7);
1775 emit_modrm(0x2, dst);
1776}
1777
1778
1779void Assembler::not_(const Operand& dst) {
1780 EnsureSpace ensure_space(this);
1781 last_pc_ = pc_;
1782 emit_rex_64(dst);
1783 emit(0xF7);
1784 emit_operand(2, dst);
1785}
1786
1787
Steve Block6ded16b2010-05-10 14:33:55 +01001788void Assembler::notl(Register dst) {
1789 EnsureSpace ensure_space(this);
1790 last_pc_ = pc_;
1791 emit_optional_rex_32(dst);
1792 emit(0xF7);
1793 emit_modrm(0x2, dst);
1794}
1795
1796
Steve Blocka7e24c12009-10-30 11:49:00 +00001797void Assembler::nop(int n) {
1798 // The recommended muti-byte sequences of NOP instructions from the Intel 64
1799 // and IA-32 Architectures Software Developer's Manual.
1800 //
1801 // Length Assembly Byte Sequence
1802 // 2 bytes 66 NOP 66 90H
1803 // 3 bytes NOP DWORD ptr [EAX] 0F 1F 00H
1804 // 4 bytes NOP DWORD ptr [EAX + 00H] 0F 1F 40 00H
1805 // 5 bytes NOP DWORD ptr [EAX + EAX*1 + 00H] 0F 1F 44 00 00H
1806 // 6 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 00H] 66 0F 1F 44 00 00H
1807 // 7 bytes NOP DWORD ptr [EAX + 00000000H] 0F 1F 80 00 00 00 00H
1808 // 8 bytes NOP DWORD ptr [EAX + EAX*1 + 00000000H] 0F 1F 84 00 00 00 00 00H
1809 // 9 bytes 66 NOP DWORD ptr [EAX + EAX*1 + 66 0F 1F 84 00 00 00 00
1810 // 00000000H] 00H
1811
1812 ASSERT(1 <= n);
1813 ASSERT(n <= 9);
1814 EnsureSpace ensure_space(this);
1815 last_pc_ = pc_;
1816 switch (n) {
1817 case 1:
1818 emit(0x90);
1819 return;
1820 case 2:
1821 emit(0x66);
1822 emit(0x90);
1823 return;
1824 case 3:
1825 emit(0x0f);
1826 emit(0x1f);
1827 emit(0x00);
1828 return;
1829 case 4:
1830 emit(0x0f);
1831 emit(0x1f);
1832 emit(0x40);
1833 emit(0x00);
1834 return;
1835 case 5:
1836 emit(0x0f);
1837 emit(0x1f);
1838 emit(0x44);
1839 emit(0x00);
1840 emit(0x00);
1841 return;
1842 case 6:
1843 emit(0x66);
1844 emit(0x0f);
1845 emit(0x1f);
1846 emit(0x44);
1847 emit(0x00);
1848 emit(0x00);
1849 return;
1850 case 7:
1851 emit(0x0f);
1852 emit(0x1f);
1853 emit(0x80);
1854 emit(0x00);
1855 emit(0x00);
1856 emit(0x00);
1857 emit(0x00);
1858 return;
1859 case 8:
1860 emit(0x0f);
1861 emit(0x1f);
1862 emit(0x84);
1863 emit(0x00);
1864 emit(0x00);
1865 emit(0x00);
1866 emit(0x00);
1867 emit(0x00);
1868 return;
1869 case 9:
1870 emit(0x66);
1871 emit(0x0f);
1872 emit(0x1f);
1873 emit(0x84);
1874 emit(0x00);
1875 emit(0x00);
1876 emit(0x00);
1877 emit(0x00);
1878 emit(0x00);
1879 return;
1880 }
1881}
1882
1883
1884void Assembler::pop(Register dst) {
1885 EnsureSpace ensure_space(this);
1886 last_pc_ = pc_;
Steve Block8defd9f2010-07-08 12:39:36 +01001887 emit_optional_rex_32(dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001888 emit(0x58 | dst.low_bits());
1889}
1890
1891
1892void Assembler::pop(const Operand& dst) {
1893 EnsureSpace ensure_space(this);
1894 last_pc_ = pc_;
Steve Block8defd9f2010-07-08 12:39:36 +01001895 emit_optional_rex_32(dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001896 emit(0x8F);
1897 emit_operand(0, dst);
1898}
1899
1900
1901void Assembler::popfq() {
1902 EnsureSpace ensure_space(this);
1903 last_pc_ = pc_;
1904 emit(0x9D);
1905}
1906
1907
1908void Assembler::push(Register src) {
1909 EnsureSpace ensure_space(this);
1910 last_pc_ = pc_;
Steve Block8defd9f2010-07-08 12:39:36 +01001911 emit_optional_rex_32(src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001912 emit(0x50 | src.low_bits());
1913}
1914
1915
1916void Assembler::push(const Operand& src) {
1917 EnsureSpace ensure_space(this);
1918 last_pc_ = pc_;
Steve Block8defd9f2010-07-08 12:39:36 +01001919 emit_optional_rex_32(src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001920 emit(0xFF);
1921 emit_operand(6, src);
1922}
1923
1924
1925void Assembler::push(Immediate value) {
1926 EnsureSpace ensure_space(this);
1927 last_pc_ = pc_;
1928 if (is_int8(value.value_)) {
1929 emit(0x6A);
1930 emit(value.value_); // Emit low byte of value.
1931 } else {
1932 emit(0x68);
1933 emitl(value.value_);
1934 }
1935}
1936
1937
1938void Assembler::pushfq() {
1939 EnsureSpace ensure_space(this);
1940 last_pc_ = pc_;
1941 emit(0x9C);
1942}
1943
1944
Steve Blocka7e24c12009-10-30 11:49:00 +00001945void Assembler::rdtsc() {
1946 EnsureSpace ensure_space(this);
1947 last_pc_ = pc_;
1948 emit(0x0F);
1949 emit(0x31);
1950}
1951
1952
1953void Assembler::ret(int imm16) {
1954 EnsureSpace ensure_space(this);
1955 last_pc_ = pc_;
1956 ASSERT(is_uint16(imm16));
1957 if (imm16 == 0) {
1958 emit(0xC3);
1959 } else {
1960 emit(0xC2);
1961 emit(imm16 & 0xFF);
1962 emit((imm16 >> 8) & 0xFF);
1963 }
1964}
1965
1966
1967void Assembler::setcc(Condition cc, Register reg) {
Steve Block3ce2e202009-11-05 08:53:23 +00001968 if (cc > last_condition) {
1969 movb(reg, Immediate(cc == always ? 1 : 0));
1970 return;
1971 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001972 EnsureSpace ensure_space(this);
1973 last_pc_ = pc_;
1974 ASSERT(is_uint4(cc));
1975 if (reg.code() > 3) { // Use x64 byte registers, where different.
1976 emit_rex_32(reg);
1977 }
1978 emit(0x0F);
1979 emit(0x90 | cc);
1980 emit_modrm(0x0, reg);
1981}
1982
1983
1984void Assembler::shld(Register dst, Register src) {
1985 EnsureSpace ensure_space(this);
1986 last_pc_ = pc_;
1987 emit_rex_64(src, dst);
1988 emit(0x0F);
1989 emit(0xA5);
1990 emit_modrm(src, dst);
1991}
1992
1993
1994void Assembler::shrd(Register dst, Register src) {
1995 EnsureSpace ensure_space(this);
1996 last_pc_ = pc_;
1997 emit_rex_64(src, dst);
1998 emit(0x0F);
1999 emit(0xAD);
2000 emit_modrm(src, dst);
2001}
2002
2003
2004void Assembler::xchg(Register dst, Register src) {
2005 EnsureSpace ensure_space(this);
2006 last_pc_ = pc_;
2007 if (src.is(rax) || dst.is(rax)) { // Single-byte encoding
2008 Register other = src.is(rax) ? dst : src;
2009 emit_rex_64(other);
2010 emit(0x90 | other.low_bits());
Leon Clarkef7060e22010-06-03 12:02:55 +01002011 } else if (dst.low_bits() == 4) {
2012 emit_rex_64(dst, src);
2013 emit(0x87);
2014 emit_modrm(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00002015 } else {
2016 emit_rex_64(src, dst);
2017 emit(0x87);
2018 emit_modrm(src, dst);
2019 }
2020}
2021
2022
2023void Assembler::store_rax(void* dst, RelocInfo::Mode mode) {
2024 EnsureSpace ensure_space(this);
2025 last_pc_ = pc_;
2026 emit(0x48); // REX.W
2027 emit(0xA3);
2028 emitq(reinterpret_cast<uintptr_t>(dst), mode);
2029}
2030
2031
2032void Assembler::store_rax(ExternalReference ref) {
2033 store_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
2034}
2035
2036
Steve Block3ce2e202009-11-05 08:53:23 +00002037void Assembler::testb(Register dst, Register src) {
2038 EnsureSpace ensure_space(this);
2039 last_pc_ = pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +01002040 if (src.low_bits() == 4) {
2041 emit_rex_32(src, dst);
2042 emit(0x84);
2043 emit_modrm(src, dst);
2044 } else {
2045 if (dst.code() > 3 || src.code() > 3) {
2046 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2047 emit_rex_32(dst, src);
2048 }
2049 emit(0x84);
2050 emit_modrm(dst, src);
Steve Block3ce2e202009-11-05 08:53:23 +00002051 }
Steve Block3ce2e202009-11-05 08:53:23 +00002052}
2053
2054
Steve Blocka7e24c12009-10-30 11:49:00 +00002055void Assembler::testb(Register reg, Immediate mask) {
2056 ASSERT(is_int8(mask.value_) || is_uint8(mask.value_));
2057 EnsureSpace ensure_space(this);
2058 last_pc_ = pc_;
2059 if (reg.is(rax)) {
2060 emit(0xA8);
2061 emit(mask.value_); // Low byte emitted.
2062 } else {
2063 if (reg.code() > 3) {
2064 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2065 emit_rex_32(reg);
2066 }
2067 emit(0xF6);
2068 emit_modrm(0x0, reg);
2069 emit(mask.value_); // Low byte emitted.
2070 }
2071}
2072
2073
2074void Assembler::testb(const Operand& op, Immediate mask) {
2075 ASSERT(is_int8(mask.value_) || is_uint8(mask.value_));
2076 EnsureSpace ensure_space(this);
2077 last_pc_ = pc_;
2078 emit_optional_rex_32(rax, op);
2079 emit(0xF6);
2080 emit_operand(rax, op); // Operation code 0
2081 emit(mask.value_); // Low byte emitted.
2082}
2083
2084
Leon Clarkee46be812010-01-19 14:06:41 +00002085void Assembler::testb(const Operand& op, Register reg) {
2086 EnsureSpace ensure_space(this);
2087 last_pc_ = pc_;
2088 if (reg.code() > 3) {
2089 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2090 emit_rex_32(reg, op);
2091 } else {
2092 emit_optional_rex_32(reg, op);
2093 }
2094 emit(0x84);
2095 emit_operand(reg, op);
2096}
2097
2098
Steve Blocka7e24c12009-10-30 11:49:00 +00002099void Assembler::testl(Register dst, Register src) {
2100 EnsureSpace ensure_space(this);
2101 last_pc_ = pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +01002102 if (src.low_bits() == 4) {
2103 emit_optional_rex_32(src, dst);
2104 emit(0x85);
2105 emit_modrm(src, dst);
2106 } else {
2107 emit_optional_rex_32(dst, src);
2108 emit(0x85);
2109 emit_modrm(dst, src);
2110 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002111}
2112
2113
2114void Assembler::testl(Register reg, Immediate mask) {
2115 // testl with a mask that fits in the low byte is exactly testb.
2116 if (is_uint8(mask.value_)) {
2117 testb(reg, mask);
2118 return;
2119 }
2120 EnsureSpace ensure_space(this);
2121 last_pc_ = pc_;
2122 if (reg.is(rax)) {
2123 emit(0xA9);
2124 emit(mask);
2125 } else {
2126 emit_optional_rex_32(rax, reg);
2127 emit(0xF7);
2128 emit_modrm(0x0, reg);
2129 emit(mask);
2130 }
2131}
2132
2133
2134void Assembler::testl(const Operand& op, Immediate mask) {
2135 // testl with a mask that fits in the low byte is exactly testb.
2136 if (is_uint8(mask.value_)) {
2137 testb(op, mask);
2138 return;
2139 }
2140 EnsureSpace ensure_space(this);
2141 last_pc_ = pc_;
2142 emit_optional_rex_32(rax, op);
2143 emit(0xF7);
2144 emit_operand(rax, op); // Operation code 0
2145 emit(mask);
2146}
2147
2148
2149void Assembler::testq(const Operand& op, Register reg) {
2150 EnsureSpace ensure_space(this);
2151 last_pc_ = pc_;
2152 emit_rex_64(reg, op);
2153 emit(0x85);
2154 emit_operand(reg, op);
2155}
2156
2157
2158void Assembler::testq(Register dst, Register src) {
2159 EnsureSpace ensure_space(this);
2160 last_pc_ = pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +01002161 if (src.low_bits() == 4) {
2162 emit_rex_64(src, dst);
2163 emit(0x85);
2164 emit_modrm(src, dst);
2165 } else {
2166 emit_rex_64(dst, src);
2167 emit(0x85);
2168 emit_modrm(dst, src);
2169 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002170}
2171
2172
2173void Assembler::testq(Register dst, Immediate mask) {
2174 EnsureSpace ensure_space(this);
2175 last_pc_ = pc_;
2176 if (dst.is(rax)) {
2177 emit_rex_64();
2178 emit(0xA9);
2179 emit(mask);
2180 } else {
2181 emit_rex_64(dst);
2182 emit(0xF7);
2183 emit_modrm(0, dst);
2184 emit(mask);
2185 }
2186}
2187
2188
Andrei Popescu31002712010-02-23 13:46:05 +00002189// FPU instructions.
Steve Blocka7e24c12009-10-30 11:49:00 +00002190
2191
2192void Assembler::fld(int i) {
2193 EnsureSpace ensure_space(this);
2194 last_pc_ = pc_;
2195 emit_farith(0xD9, 0xC0, i);
2196}
2197
2198
2199void Assembler::fld1() {
2200 EnsureSpace ensure_space(this);
2201 last_pc_ = pc_;
2202 emit(0xD9);
2203 emit(0xE8);
2204}
2205
2206
2207void Assembler::fldz() {
2208 EnsureSpace ensure_space(this);
2209 last_pc_ = pc_;
2210 emit(0xD9);
2211 emit(0xEE);
2212}
2213
2214
Steve Block6ded16b2010-05-10 14:33:55 +01002215void Assembler::fldpi() {
2216 EnsureSpace ensure_space(this);
2217 last_pc_ = pc_;
2218 emit(0xD9);
2219 emit(0xEB);
2220}
2221
2222
Ben Murdochb0fe1622011-05-05 13:52:32 +01002223void Assembler::fldln2() {
2224 EnsureSpace ensure_space(this);
2225 last_pc_ = pc_;
2226 emit(0xD9);
2227 emit(0xED);
2228}
2229
2230
Steve Blocka7e24c12009-10-30 11:49:00 +00002231void Assembler::fld_s(const Operand& adr) {
2232 EnsureSpace ensure_space(this);
2233 last_pc_ = pc_;
2234 emit_optional_rex_32(adr);
2235 emit(0xD9);
2236 emit_operand(0, adr);
2237}
2238
2239
2240void Assembler::fld_d(const Operand& adr) {
2241 EnsureSpace ensure_space(this);
2242 last_pc_ = pc_;
2243 emit_optional_rex_32(adr);
2244 emit(0xDD);
2245 emit_operand(0, adr);
2246}
2247
2248
2249void Assembler::fstp_s(const Operand& adr) {
2250 EnsureSpace ensure_space(this);
2251 last_pc_ = pc_;
2252 emit_optional_rex_32(adr);
2253 emit(0xD9);
2254 emit_operand(3, adr);
2255}
2256
2257
2258void Assembler::fstp_d(const Operand& adr) {
2259 EnsureSpace ensure_space(this);
2260 last_pc_ = pc_;
2261 emit_optional_rex_32(adr);
2262 emit(0xDD);
2263 emit_operand(3, adr);
2264}
2265
2266
Steve Block3ce2e202009-11-05 08:53:23 +00002267void Assembler::fstp(int index) {
2268 ASSERT(is_uint3(index));
2269 EnsureSpace ensure_space(this);
2270 last_pc_ = pc_;
2271 emit_farith(0xDD, 0xD8, index);
2272}
2273
2274
Steve Blocka7e24c12009-10-30 11:49:00 +00002275void Assembler::fild_s(const Operand& adr) {
2276 EnsureSpace ensure_space(this);
2277 last_pc_ = pc_;
2278 emit_optional_rex_32(adr);
2279 emit(0xDB);
2280 emit_operand(0, adr);
2281}
2282
2283
2284void Assembler::fild_d(const Operand& adr) {
2285 EnsureSpace ensure_space(this);
2286 last_pc_ = pc_;
2287 emit_optional_rex_32(adr);
2288 emit(0xDF);
2289 emit_operand(5, adr);
2290}
2291
2292
2293void Assembler::fistp_s(const Operand& adr) {
2294 EnsureSpace ensure_space(this);
2295 last_pc_ = pc_;
2296 emit_optional_rex_32(adr);
2297 emit(0xDB);
2298 emit_operand(3, adr);
2299}
2300
2301
2302void Assembler::fisttp_s(const Operand& adr) {
Steve Blockd0582a62009-12-15 09:54:21 +00002303 ASSERT(CpuFeatures::IsEnabled(SSE3));
Steve Blocka7e24c12009-10-30 11:49:00 +00002304 EnsureSpace ensure_space(this);
2305 last_pc_ = pc_;
2306 emit_optional_rex_32(adr);
2307 emit(0xDB);
2308 emit_operand(1, adr);
2309}
2310
2311
Leon Clarked91b9f72010-01-27 17:25:45 +00002312void Assembler::fisttp_d(const Operand& adr) {
2313 ASSERT(CpuFeatures::IsEnabled(SSE3));
2314 EnsureSpace ensure_space(this);
2315 last_pc_ = pc_;
2316 emit_optional_rex_32(adr);
2317 emit(0xDD);
2318 emit_operand(1, adr);
2319}
2320
2321
Steve Blocka7e24c12009-10-30 11:49:00 +00002322void Assembler::fist_s(const Operand& adr) {
2323 EnsureSpace ensure_space(this);
2324 last_pc_ = pc_;
2325 emit_optional_rex_32(adr);
2326 emit(0xDB);
2327 emit_operand(2, adr);
2328}
2329
2330
2331void Assembler::fistp_d(const Operand& adr) {
2332 EnsureSpace ensure_space(this);
2333 last_pc_ = pc_;
2334 emit_optional_rex_32(adr);
2335 emit(0xDF);
Steve Block3ce2e202009-11-05 08:53:23 +00002336 emit_operand(7, adr);
Steve Blocka7e24c12009-10-30 11:49:00 +00002337}
2338
2339
2340void Assembler::fabs() {
2341 EnsureSpace ensure_space(this);
2342 last_pc_ = pc_;
2343 emit(0xD9);
2344 emit(0xE1);
2345}
2346
2347
2348void Assembler::fchs() {
2349 EnsureSpace ensure_space(this);
2350 last_pc_ = pc_;
2351 emit(0xD9);
2352 emit(0xE0);
2353}
2354
2355
2356void Assembler::fcos() {
2357 EnsureSpace ensure_space(this);
2358 last_pc_ = pc_;
2359 emit(0xD9);
2360 emit(0xFF);
2361}
2362
2363
2364void Assembler::fsin() {
2365 EnsureSpace ensure_space(this);
2366 last_pc_ = pc_;
2367 emit(0xD9);
2368 emit(0xFE);
2369}
2370
2371
Ben Murdochb0fe1622011-05-05 13:52:32 +01002372void Assembler::fyl2x() {
2373 EnsureSpace ensure_space(this);
2374 last_pc_ = pc_;
2375 emit(0xD9);
2376 emit(0xF1);
2377}
2378
2379
Steve Blocka7e24c12009-10-30 11:49:00 +00002380void Assembler::fadd(int i) {
2381 EnsureSpace ensure_space(this);
2382 last_pc_ = pc_;
2383 emit_farith(0xDC, 0xC0, i);
2384}
2385
2386
2387void Assembler::fsub(int i) {
2388 EnsureSpace ensure_space(this);
2389 last_pc_ = pc_;
2390 emit_farith(0xDC, 0xE8, i);
2391}
2392
2393
2394void Assembler::fisub_s(const Operand& adr) {
2395 EnsureSpace ensure_space(this);
2396 last_pc_ = pc_;
2397 emit_optional_rex_32(adr);
2398 emit(0xDA);
2399 emit_operand(4, adr);
2400}
2401
2402
2403void Assembler::fmul(int i) {
2404 EnsureSpace ensure_space(this);
2405 last_pc_ = pc_;
2406 emit_farith(0xDC, 0xC8, i);
2407}
2408
2409
2410void Assembler::fdiv(int i) {
2411 EnsureSpace ensure_space(this);
2412 last_pc_ = pc_;
2413 emit_farith(0xDC, 0xF8, i);
2414}
2415
2416
2417void Assembler::faddp(int i) {
2418 EnsureSpace ensure_space(this);
2419 last_pc_ = pc_;
2420 emit_farith(0xDE, 0xC0, i);
2421}
2422
2423
2424void Assembler::fsubp(int i) {
2425 EnsureSpace ensure_space(this);
2426 last_pc_ = pc_;
2427 emit_farith(0xDE, 0xE8, i);
2428}
2429
2430
2431void Assembler::fsubrp(int i) {
2432 EnsureSpace ensure_space(this);
2433 last_pc_ = pc_;
2434 emit_farith(0xDE, 0xE0, i);
2435}
2436
2437
2438void Assembler::fmulp(int i) {
2439 EnsureSpace ensure_space(this);
2440 last_pc_ = pc_;
2441 emit_farith(0xDE, 0xC8, i);
2442}
2443
2444
2445void Assembler::fdivp(int i) {
2446 EnsureSpace ensure_space(this);
2447 last_pc_ = pc_;
2448 emit_farith(0xDE, 0xF8, i);
2449}
2450
2451
2452void Assembler::fprem() {
2453 EnsureSpace ensure_space(this);
2454 last_pc_ = pc_;
2455 emit(0xD9);
2456 emit(0xF8);
2457}
2458
2459
2460void Assembler::fprem1() {
2461 EnsureSpace ensure_space(this);
2462 last_pc_ = pc_;
2463 emit(0xD9);
2464 emit(0xF5);
2465}
2466
2467
2468void Assembler::fxch(int i) {
2469 EnsureSpace ensure_space(this);
2470 last_pc_ = pc_;
2471 emit_farith(0xD9, 0xC8, i);
2472}
2473
2474
2475void Assembler::fincstp() {
2476 EnsureSpace ensure_space(this);
2477 last_pc_ = pc_;
2478 emit(0xD9);
2479 emit(0xF7);
2480}
2481
2482
2483void Assembler::ffree(int i) {
2484 EnsureSpace ensure_space(this);
2485 last_pc_ = pc_;
2486 emit_farith(0xDD, 0xC0, i);
2487}
2488
2489
2490void Assembler::ftst() {
2491 EnsureSpace ensure_space(this);
2492 last_pc_ = pc_;
2493 emit(0xD9);
2494 emit(0xE4);
2495}
2496
2497
2498void Assembler::fucomp(int i) {
2499 EnsureSpace ensure_space(this);
2500 last_pc_ = pc_;
2501 emit_farith(0xDD, 0xE8, i);
2502}
2503
2504
2505void Assembler::fucompp() {
2506 EnsureSpace ensure_space(this);
2507 last_pc_ = pc_;
2508 emit(0xDA);
2509 emit(0xE9);
2510}
2511
2512
Steve Block3ce2e202009-11-05 08:53:23 +00002513void Assembler::fucomi(int i) {
2514 EnsureSpace ensure_space(this);
2515 last_pc_ = pc_;
2516 emit(0xDB);
2517 emit(0xE8 + i);
2518}
2519
2520
2521void Assembler::fucomip() {
2522 EnsureSpace ensure_space(this);
2523 last_pc_ = pc_;
2524 emit(0xDF);
2525 emit(0xE9);
2526}
2527
2528
Steve Blocka7e24c12009-10-30 11:49:00 +00002529void Assembler::fcompp() {
2530 EnsureSpace ensure_space(this);
2531 last_pc_ = pc_;
2532 emit(0xDE);
2533 emit(0xD9);
2534}
2535
2536
2537void Assembler::fnstsw_ax() {
2538 EnsureSpace ensure_space(this);
2539 last_pc_ = pc_;
2540 emit(0xDF);
2541 emit(0xE0);
2542}
2543
2544
2545void Assembler::fwait() {
2546 EnsureSpace ensure_space(this);
2547 last_pc_ = pc_;
2548 emit(0x9B);
2549}
2550
2551
2552void Assembler::frndint() {
2553 EnsureSpace ensure_space(this);
2554 last_pc_ = pc_;
2555 emit(0xD9);
2556 emit(0xFC);
2557}
2558
2559
2560void Assembler::fnclex() {
2561 EnsureSpace ensure_space(this);
2562 last_pc_ = pc_;
2563 emit(0xDB);
2564 emit(0xE2);
2565}
2566
2567
2568void Assembler::sahf() {
2569 // TODO(X64): Test for presence. Not all 64-bit intel CPU's have sahf
2570 // in 64-bit mode. Test CpuID.
2571 EnsureSpace ensure_space(this);
2572 last_pc_ = pc_;
2573 emit(0x9E);
2574}
2575
2576
2577void Assembler::emit_farith(int b1, int b2, int i) {
2578 ASSERT(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2579 ASSERT(is_uint3(i)); // illegal stack offset
2580 emit(b1);
2581 emit(b2 + i);
2582}
2583
Andrei Popescu31002712010-02-23 13:46:05 +00002584// SSE 2 operations.
Steve Blocka7e24c12009-10-30 11:49:00 +00002585
Steve Block6ded16b2010-05-10 14:33:55 +01002586void Assembler::movd(XMMRegister dst, Register src) {
2587 EnsureSpace ensure_space(this);
2588 last_pc_ = pc_;
2589 emit(0x66);
2590 emit_optional_rex_32(dst, src);
2591 emit(0x0F);
2592 emit(0x6E);
2593 emit_sse_operand(dst, src);
2594}
2595
2596
2597void Assembler::movd(Register dst, XMMRegister src) {
2598 EnsureSpace ensure_space(this);
2599 last_pc_ = pc_;
2600 emit(0x66);
Ben Murdochbb769b22010-08-11 14:56:33 +01002601 emit_optional_rex_32(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002602 emit(0x0F);
2603 emit(0x7E);
Ben Murdochbb769b22010-08-11 14:56:33 +01002604 emit_sse_operand(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002605}
2606
2607
2608void Assembler::movq(XMMRegister dst, Register src) {
2609 EnsureSpace ensure_space(this);
2610 last_pc_ = pc_;
2611 emit(0x66);
2612 emit_rex_64(dst, src);
2613 emit(0x0F);
2614 emit(0x6E);
2615 emit_sse_operand(dst, src);
2616}
2617
2618
2619void Assembler::movq(Register dst, XMMRegister src) {
2620 EnsureSpace ensure_space(this);
2621 last_pc_ = pc_;
2622 emit(0x66);
Ben Murdochbb769b22010-08-11 14:56:33 +01002623 emit_rex_64(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002624 emit(0x0F);
2625 emit(0x7E);
Ben Murdochbb769b22010-08-11 14:56:33 +01002626 emit_sse_operand(src, dst);
Steve Block6ded16b2010-05-10 14:33:55 +01002627}
2628
2629
2630void Assembler::extractps(Register dst, XMMRegister src, byte imm8) {
2631 ASSERT(is_uint2(imm8));
2632 EnsureSpace ensure_space(this);
2633 last_pc_ = pc_;
2634 emit(0x66);
2635 emit_optional_rex_32(dst, src);
2636 emit(0x0F);
2637 emit(0x3A);
2638 emit(0x17);
2639 emit_sse_operand(dst, src);
2640 emit(imm8);
2641}
2642
2643
Steve Blocka7e24c12009-10-30 11:49:00 +00002644void Assembler::movsd(const Operand& dst, XMMRegister src) {
2645 EnsureSpace ensure_space(this);
2646 last_pc_ = pc_;
2647 emit(0xF2); // double
2648 emit_optional_rex_32(src, dst);
2649 emit(0x0F);
2650 emit(0x11); // store
2651 emit_sse_operand(src, dst);
2652}
2653
2654
Steve Block3ce2e202009-11-05 08:53:23 +00002655void Assembler::movsd(XMMRegister dst, XMMRegister src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002656 EnsureSpace ensure_space(this);
2657 last_pc_ = pc_;
2658 emit(0xF2); // double
2659 emit_optional_rex_32(dst, src);
2660 emit(0x0F);
2661 emit(0x10); // load
2662 emit_sse_operand(dst, src);
2663}
2664
2665
2666void Assembler::movsd(XMMRegister dst, const Operand& src) {
2667 EnsureSpace ensure_space(this);
2668 last_pc_ = pc_;
2669 emit(0xF2); // double
2670 emit_optional_rex_32(dst, src);
2671 emit(0x0F);
2672 emit(0x10); // load
2673 emit_sse_operand(dst, src);
2674}
2675
2676
Steve Block8defd9f2010-07-08 12:39:36 +01002677void Assembler::movss(XMMRegister dst, const Operand& src) {
2678 EnsureSpace ensure_space(this);
2679 last_pc_ = pc_;
2680 emit(0xF3); // single
2681 emit_optional_rex_32(dst, src);
2682 emit(0x0F);
2683 emit(0x10); // load
2684 emit_sse_operand(dst, src);
2685}
2686
2687
2688void Assembler::movss(const Operand& src, XMMRegister dst) {
2689 EnsureSpace ensure_space(this);
2690 last_pc_ = pc_;
2691 emit(0xF3); // single
2692 emit_optional_rex_32(dst, src);
2693 emit(0x0F);
2694 emit(0x11); // store
2695 emit_sse_operand(dst, src);
2696}
2697
2698
Steve Blocka7e24c12009-10-30 11:49:00 +00002699void Assembler::cvttss2si(Register dst, const Operand& src) {
2700 EnsureSpace ensure_space(this);
2701 last_pc_ = pc_;
2702 emit(0xF3);
2703 emit_optional_rex_32(dst, src);
2704 emit(0x0F);
2705 emit(0x2C);
2706 emit_operand(dst, src);
2707}
2708
2709
2710void Assembler::cvttsd2si(Register dst, const Operand& src) {
2711 EnsureSpace ensure_space(this);
2712 last_pc_ = pc_;
2713 emit(0xF2);
2714 emit_optional_rex_32(dst, src);
2715 emit(0x0F);
2716 emit(0x2C);
2717 emit_operand(dst, src);
2718}
2719
2720
Kristian Monsen25f61362010-05-21 11:50:48 +01002721void Assembler::cvttsd2siq(Register dst, XMMRegister src) {
2722 EnsureSpace ensure_space(this);
2723 last_pc_ = pc_;
2724 emit(0xF2);
2725 emit_rex_64(dst, src);
2726 emit(0x0F);
2727 emit(0x2C);
2728 emit_sse_operand(dst, src);
2729}
2730
2731
Steve Blocka7e24c12009-10-30 11:49:00 +00002732void Assembler::cvtlsi2sd(XMMRegister dst, const Operand& src) {
2733 EnsureSpace ensure_space(this);
2734 last_pc_ = pc_;
2735 emit(0xF2);
2736 emit_optional_rex_32(dst, src);
2737 emit(0x0F);
2738 emit(0x2A);
2739 emit_sse_operand(dst, src);
2740}
2741
2742
2743void Assembler::cvtlsi2sd(XMMRegister dst, Register src) {
2744 EnsureSpace ensure_space(this);
2745 last_pc_ = pc_;
2746 emit(0xF2);
2747 emit_optional_rex_32(dst, src);
2748 emit(0x0F);
2749 emit(0x2A);
2750 emit_sse_operand(dst, src);
2751}
2752
2753
Steve Block8defd9f2010-07-08 12:39:36 +01002754void Assembler::cvtlsi2ss(XMMRegister dst, Register src) {
2755 EnsureSpace ensure_space(this);
2756 last_pc_ = pc_;
2757 emit(0xF3);
2758 emit_optional_rex_32(dst, src);
2759 emit(0x0F);
2760 emit(0x2A);
2761 emit_sse_operand(dst, src);
2762}
2763
2764
Steve Blocka7e24c12009-10-30 11:49:00 +00002765void Assembler::cvtqsi2sd(XMMRegister dst, Register src) {
2766 EnsureSpace ensure_space(this);
2767 last_pc_ = pc_;
2768 emit(0xF2);
2769 emit_rex_64(dst, src);
2770 emit(0x0F);
2771 emit(0x2A);
2772 emit_sse_operand(dst, src);
2773}
2774
2775
Steve Block6ded16b2010-05-10 14:33:55 +01002776void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
2777 EnsureSpace ensure_space(this);
2778 last_pc_ = pc_;
2779 emit(0xF3);
2780 emit_optional_rex_32(dst, src);
2781 emit(0x0F);
2782 emit(0x5A);
2783 emit_sse_operand(dst, src);
2784}
2785
2786
Steve Block8defd9f2010-07-08 12:39:36 +01002787void Assembler::cvtss2sd(XMMRegister dst, const Operand& src) {
2788 EnsureSpace ensure_space(this);
2789 last_pc_ = pc_;
2790 emit(0xF3);
2791 emit_optional_rex_32(dst, src);
2792 emit(0x0F);
2793 emit(0x5A);
2794 emit_sse_operand(dst, src);
2795}
2796
2797
2798void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
2799 EnsureSpace ensure_space(this);
2800 last_pc_ = pc_;
2801 emit(0xF2);
2802 emit_optional_rex_32(dst, src);
2803 emit(0x0F);
2804 emit(0x5A);
2805 emit_sse_operand(dst, src);
2806}
2807
2808
2809void Assembler::cvtsd2si(Register dst, XMMRegister src) {
2810 EnsureSpace ensure_space(this);
2811 last_pc_ = pc_;
2812 emit(0xF2);
2813 emit_optional_rex_32(dst, src);
2814 emit(0x0F);
2815 emit(0x2D);
2816 emit_sse_operand(dst, src);
2817}
2818
2819
2820void Assembler::cvtsd2siq(Register dst, XMMRegister src) {
2821 EnsureSpace ensure_space(this);
2822 last_pc_ = pc_;
2823 emit(0xF2);
2824 emit_rex_64(dst, src);
2825 emit(0x0F);
2826 emit(0x2D);
2827 emit_sse_operand(dst, src);
2828}
2829
2830
Steve Blocka7e24c12009-10-30 11:49:00 +00002831void Assembler::addsd(XMMRegister dst, XMMRegister src) {
2832 EnsureSpace ensure_space(this);
2833 last_pc_ = pc_;
2834 emit(0xF2);
2835 emit_optional_rex_32(dst, src);
2836 emit(0x0F);
2837 emit(0x58);
2838 emit_sse_operand(dst, src);
2839}
2840
2841
2842void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
2843 EnsureSpace ensure_space(this);
2844 last_pc_ = pc_;
2845 emit(0xF2);
2846 emit_optional_rex_32(dst, src);
2847 emit(0x0F);
2848 emit(0x59);
2849 emit_sse_operand(dst, src);
2850}
2851
2852
2853void Assembler::subsd(XMMRegister dst, XMMRegister src) {
2854 EnsureSpace ensure_space(this);
2855 last_pc_ = pc_;
2856 emit(0xF2);
2857 emit_optional_rex_32(dst, src);
2858 emit(0x0F);
2859 emit(0x5C);
2860 emit_sse_operand(dst, src);
2861}
2862
2863
2864void Assembler::divsd(XMMRegister dst, XMMRegister src) {
2865 EnsureSpace ensure_space(this);
2866 last_pc_ = pc_;
2867 emit(0xF2);
2868 emit_optional_rex_32(dst, src);
2869 emit(0x0F);
2870 emit(0x5E);
2871 emit_sse_operand(dst, src);
2872}
2873
2874
Andrei Popescu402d9372010-02-26 13:31:12 +00002875void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
2876 EnsureSpace ensure_space(this);
2877 last_pc_ = pc_;
2878 emit(0x66);
2879 emit_optional_rex_32(dst, src);
Steve Block6ded16b2010-05-10 14:33:55 +01002880 emit(0x0F);
Andrei Popescu402d9372010-02-26 13:31:12 +00002881 emit(0x57);
2882 emit_sse_operand(dst, src);
2883}
2884
2885
Steve Block6ded16b2010-05-10 14:33:55 +01002886void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
2887 EnsureSpace ensure_space(this);
2888 last_pc_ = pc_;
2889 emit(0xF2);
2890 emit_optional_rex_32(dst, src);
2891 emit(0x0F);
2892 emit(0x51);
2893 emit_sse_operand(dst, src);
2894}
2895
2896
Andrei Popescu402d9372010-02-26 13:31:12 +00002897void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
2898 EnsureSpace ensure_space(this);
2899 last_pc_ = pc_;
2900 emit(0x66);
2901 emit_optional_rex_32(dst, src);
2902 emit(0x0f);
2903 emit(0x2e);
2904 emit_sse_operand(dst, src);
2905}
2906
Steve Blocka7e24c12009-10-30 11:49:00 +00002907
Steve Block8defd9f2010-07-08 12:39:36 +01002908void Assembler::ucomisd(XMMRegister dst, const Operand& src) {
2909 EnsureSpace ensure_space(this);
2910 last_pc_ = pc_;
2911 emit(0x66);
2912 emit_optional_rex_32(dst, src);
2913 emit(0x0f);
2914 emit(0x2e);
2915 emit_sse_operand(dst, src);
2916}
2917
2918
2919
Steve Blocka7e24c12009-10-30 11:49:00 +00002920void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
2921 Register ireg = { reg.code() };
2922 emit_operand(ireg, adr);
2923}
2924
2925
2926void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
2927 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
2928}
2929
2930void Assembler::emit_sse_operand(XMMRegister dst, Register src) {
2931 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
2932}
2933
Steve Block6ded16b2010-05-10 14:33:55 +01002934void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
2935 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
2936}
2937
Steve Blocka7e24c12009-10-30 11:49:00 +00002938
Ben Murdochb0fe1622011-05-05 13:52:32 +01002939void Assembler::dd(uint32_t data) {
2940 EnsureSpace ensure_space(this);
2941 emitl(data);
2942}
2943
2944
Andrei Popescu31002712010-02-23 13:46:05 +00002945// Relocation information implementations.
Steve Blocka7e24c12009-10-30 11:49:00 +00002946
2947void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2948 ASSERT(rmode != RelocInfo::NONE);
2949 // Don't record external references unless the heap will be serialized.
2950 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
2951 !Serializer::enabled() &&
2952 !FLAG_debug_code) {
2953 return;
2954 }
2955 RelocInfo rinfo(pc_, rmode, data);
2956 reloc_info_writer.Write(&rinfo);
2957}
2958
2959void Assembler::RecordJSReturn() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002960 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00002961 EnsureSpace ensure_space(this);
2962 RecordRelocInfo(RelocInfo::JS_RETURN);
2963}
2964
2965
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002966void Assembler::RecordDebugBreakSlot() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002967 positions_recorder()->WriteRecordedPositions();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002968 EnsureSpace ensure_space(this);
2969 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
2970}
2971
2972
Steve Blocka7e24c12009-10-30 11:49:00 +00002973void Assembler::RecordComment(const char* msg) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002974 if (FLAG_code_comments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002975 EnsureSpace ensure_space(this);
2976 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
2977 }
2978}
2979
2980
Steve Block3ce2e202009-11-05 08:53:23 +00002981const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
Ben Murdochbb769b22010-08-11 14:56:33 +01002982 1 << RelocInfo::INTERNAL_REFERENCE;
Steve Blocka7e24c12009-10-30 11:49:00 +00002983
Leon Clarkef7060e22010-06-03 12:02:55 +01002984
2985bool RelocInfo::IsCodedSpecially() {
2986 // The deserializer needs to know whether a pointer is specially coded. Being
2987 // specially coded on x64 means that it is a relative 32 bit address, as used
2988 // by branch instructions.
2989 return (1 << rmode_) & kApplyMask;
2990}
2991
2992
2993
Steve Blocka7e24c12009-10-30 11:49:00 +00002994} } // namespace v8::internal
Leon Clarkef7060e22010-06-03 12:02:55 +01002995
2996#endif // V8_TARGET_ARCH_X64