blob: 999647487eeea53e635777ffce253056849d0d7c [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions
6// are met:
7//
8// - Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// - Redistribution in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the
14// distribution.
15//
16// - Neither the name of Sun Microsystems or the names of contributors may
17// be used to endorse or promote products derived from this software without
18// specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31// OF THE POSSIBILITY OF SUCH DAMAGE.
32
33// The original source code covered by the above license above has been modified
34// significantly by Google Inc.
Ben Murdoch85b71792012-04-11 18:30:58 +010035// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +000036
37#include "v8.h"
38
Leon Clarkef7060e22010-06-03 12:02:55 +010039#if defined(V8_TARGET_ARCH_IA32)
40
Steve Blocka7e24c12009-10-30 11:49:00 +000041#include "disassembler.h"
42#include "macro-assembler.h"
43#include "serialize.h"
44
45namespace v8 {
46namespace internal {
47
48// -----------------------------------------------------------------------------
49// Implementation of CpuFeatures
50
Ben Murdoch8b112d22011-06-08 16:22:53 +010051#ifdef DEBUG
52bool CpuFeatures::initialized_ = false;
53#endif
54uint64_t CpuFeatures::supported_ = 0;
55uint64_t CpuFeatures::found_by_runtime_probing_ = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000056
57
Ben Murdoch8b112d22011-06-08 16:22:53 +010058void CpuFeatures::Probe() {
59 ASSERT(!initialized_);
Steve Blocka7e24c12009-10-30 11:49:00 +000060 ASSERT(supported_ == 0);
Ben Murdoch8b112d22011-06-08 16:22:53 +010061#ifdef DEBUG
62 initialized_ = true;
63#endif
64 if (Serializer::enabled()) {
Steve Blockd0582a62009-12-15 09:54:21 +000065 supported_ |= OS::CpuFeaturesImpliedByPlatform();
66 return; // No features if we might serialize.
67 }
Steve Blocka7e24c12009-10-30 11:49:00 +000068
Ben Murdoch8b112d22011-06-08 16:22:53 +010069 const int kBufferSize = 4 * KB;
70 VirtualMemory* memory = new VirtualMemory(kBufferSize);
71 if (!memory->IsReserved()) {
72 delete memory;
73 return;
74 }
75 ASSERT(memory->size() >= static_cast<size_t>(kBufferSize));
76 if (!memory->Commit(memory->address(), kBufferSize, true/*executable*/)) {
77 delete memory;
78 return;
79 }
80
81 Assembler assm(NULL, memory->address(), kBufferSize);
Steve Blocka7e24c12009-10-30 11:49:00 +000082 Label cpuid, done;
83#define __ assm.
84 // Save old esp, since we are going to modify the stack.
85 __ push(ebp);
86 __ pushfd();
87 __ push(ecx);
88 __ push(ebx);
Ben Murdoch85b71792012-04-11 18:30:58 +010089 __ mov(ebp, Operand(esp));
Steve Blocka7e24c12009-10-30 11:49:00 +000090
91 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
92 __ pushfd();
93 __ pop(eax);
Ben Murdoch85b71792012-04-11 18:30:58 +010094 __ mov(edx, Operand(eax));
Steve Blocka7e24c12009-10-30 11:49:00 +000095 __ xor_(eax, 0x200000); // Flip bit 21.
96 __ push(eax);
97 __ popfd();
98 __ pushfd();
99 __ pop(eax);
Ben Murdoch85b71792012-04-11 18:30:58 +0100100 __ xor_(eax, Operand(edx)); // Different if CPUID is supported.
Steve Blocka7e24c12009-10-30 11:49:00 +0000101 __ j(not_zero, &cpuid);
102
103 // CPUID not supported. Clear the supported features in edx:eax.
Ben Murdoch85b71792012-04-11 18:30:58 +0100104 __ xor_(eax, Operand(eax));
105 __ xor_(edx, Operand(edx));
Steve Blocka7e24c12009-10-30 11:49:00 +0000106 __ jmp(&done);
107
108 // Invoke CPUID with 1 in eax to get feature information in
109 // ecx:edx. Temporarily enable CPUID support because we know it's
110 // safe here.
111 __ bind(&cpuid);
112 __ mov(eax, 1);
113 supported_ = (1 << CPUID);
114 { Scope fscope(CPUID);
115 __ cpuid();
116 }
117 supported_ = 0;
118
119 // Move the result from ecx:edx to edx:eax and make sure to mark the
120 // CPUID feature as supported.
Ben Murdoch85b71792012-04-11 18:30:58 +0100121 __ mov(eax, Operand(edx));
Steve Blocka7e24c12009-10-30 11:49:00 +0000122 __ or_(eax, 1 << CPUID);
Ben Murdoch85b71792012-04-11 18:30:58 +0100123 __ mov(edx, Operand(ecx));
Steve Blocka7e24c12009-10-30 11:49:00 +0000124
125 // Done.
126 __ bind(&done);
Ben Murdoch85b71792012-04-11 18:30:58 +0100127 __ mov(esp, Operand(ebp));
Steve Blocka7e24c12009-10-30 11:49:00 +0000128 __ pop(ebx);
129 __ pop(ecx);
130 __ popfd();
131 __ pop(ebp);
132 __ ret(0);
133#undef __
134
Steve Blocka7e24c12009-10-30 11:49:00 +0000135 typedef uint64_t (*F0)();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100136 F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000137 supported_ = probe();
Steve Blockd0582a62009-12-15 09:54:21 +0000138 found_by_runtime_probing_ = supported_;
139 uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform();
140 supported_ |= os_guarantees;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100141 found_by_runtime_probing_ &= ~os_guarantees;
142
143 delete memory;
Steve Blocka7e24c12009-10-30 11:49:00 +0000144}
145
146
147// -----------------------------------------------------------------------------
148// Implementation of Displacement
149
150void Displacement::init(Label* L, Type type) {
151 ASSERT(!L->is_bound());
152 int next = 0;
153 if (L->is_linked()) {
154 next = L->pos();
155 ASSERT(next > 0); // Displacements must be at positions > 0
156 }
157 // Ensure that we _never_ overflow the next field.
158 ASSERT(NextField::is_valid(Assembler::kMaximalBufferSize));
159 data_ = NextField::encode(next) | TypeField::encode(type);
160}
161
162
163// -----------------------------------------------------------------------------
164// Implementation of RelocInfo
165
166
167const int RelocInfo::kApplyMask =
168 RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
Ben Murdochbb769b22010-08-11 14:56:33 +0100169 1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE |
170 1 << RelocInfo::DEBUG_BREAK_SLOT;
Steve Blocka7e24c12009-10-30 11:49:00 +0000171
172
Leon Clarkef7060e22010-06-03 12:02:55 +0100173bool RelocInfo::IsCodedSpecially() {
174 // The deserializer needs to know whether a pointer is specially coded. Being
175 // specially coded on IA32 means that it is a relative address, as used by
176 // branch instructions. These are also the ones that need changing when a
177 // code object moves.
178 return (1 << rmode_) & kApplyMask;
179}
180
181
Steve Blocka7e24c12009-10-30 11:49:00 +0000182void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
183 // Patch the code at the current address with the supplied instructions.
184 for (int i = 0; i < instruction_count; i++) {
185 *(pc_ + i) = *(instructions + i);
186 }
187
188 // Indicate that code has changed.
189 CPU::FlushICache(pc_, instruction_count);
190}
191
192
193// Patch the code at the current PC with a call to the target address.
194// Additional guard int3 instructions can be added if required.
195void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
196 // Call instruction takes up 5 bytes and int3 takes up one byte.
197 static const int kCallCodeSize = 5;
198 int code_size = kCallCodeSize + guard_bytes;
199
200 // Create a code patcher.
201 CodePatcher patcher(pc_, code_size);
202
203 // Add a label for checking the size of the code used for returning.
204#ifdef DEBUG
205 Label check_codesize;
206 patcher.masm()->bind(&check_codesize);
207#endif
208
209 // Patch the code.
210 patcher.masm()->call(target, RelocInfo::NONE);
211
212 // Check that the size of the code generated is as expected.
213 ASSERT_EQ(kCallCodeSize,
214 patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
215
216 // Add the requested number of int3 instructions after the call.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100217 ASSERT_GE(guard_bytes, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000218 for (int i = 0; i < guard_bytes; i++) {
219 patcher.masm()->int3();
220 }
221}
222
223
224// -----------------------------------------------------------------------------
225// Implementation of Operand
226
227Operand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) {
228 // [base + disp/r]
229 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
230 // [base]
231 set_modrm(0, base);
232 if (base.is(esp)) set_sib(times_1, esp, base);
233 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
234 // [base + disp8]
235 set_modrm(1, base);
236 if (base.is(esp)) set_sib(times_1, esp, base);
237 set_disp8(disp);
238 } else {
239 // [base + disp/r]
240 set_modrm(2, base);
241 if (base.is(esp)) set_sib(times_1, esp, base);
242 set_dispr(disp, rmode);
243 }
244}
245
246
247Operand::Operand(Register base,
248 Register index,
249 ScaleFactor scale,
250 int32_t disp,
251 RelocInfo::Mode rmode) {
252 ASSERT(!index.is(esp)); // illegal addressing mode
253 // [base + index*scale + disp/r]
254 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
255 // [base + index*scale]
256 set_modrm(0, esp);
257 set_sib(scale, index, base);
258 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
259 // [base + index*scale + disp8]
260 set_modrm(1, esp);
261 set_sib(scale, index, base);
262 set_disp8(disp);
263 } else {
264 // [base + index*scale + disp/r]
265 set_modrm(2, esp);
266 set_sib(scale, index, base);
267 set_dispr(disp, rmode);
268 }
269}
270
271
272Operand::Operand(Register index,
273 ScaleFactor scale,
274 int32_t disp,
275 RelocInfo::Mode rmode) {
276 ASSERT(!index.is(esp)); // illegal addressing mode
277 // [index*scale + disp/r]
278 set_modrm(0, esp);
279 set_sib(scale, index, ebp);
280 set_dispr(disp, rmode);
281}
282
283
284bool Operand::is_reg(Register reg) const {
285 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only.
286 && ((buf_[0] & 0x07) == reg.code()); // register codes match.
287}
288
289// -----------------------------------------------------------------------------
Andrei Popescu31002712010-02-23 13:46:05 +0000290// Implementation of Assembler.
Steve Blocka7e24c12009-10-30 11:49:00 +0000291
292// Emit a single byte. Must always be inlined.
293#define EMIT(x) \
294 *pc_++ = (x)
295
296
297#ifdef GENERATED_CODE_COVERAGE
298static void InitCoverageLog();
299#endif
300
Ben Murdoch8b112d22011-06-08 16:22:53 +0100301Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size)
302 : AssemblerBase(arg_isolate),
Steve Block44f0eee2011-05-26 01:26:41 +0100303 positions_recorder_(this),
304 emit_debug_code_(FLAG_debug_code) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000305 if (buffer == NULL) {
Andrei Popescu31002712010-02-23 13:46:05 +0000306 // Do our own buffer management.
Steve Blocka7e24c12009-10-30 11:49:00 +0000307 if (buffer_size <= kMinimalBufferSize) {
308 buffer_size = kMinimalBufferSize;
309
Steve Block44f0eee2011-05-26 01:26:41 +0100310 if (isolate()->assembler_spare_buffer() != NULL) {
311 buffer = isolate()->assembler_spare_buffer();
312 isolate()->set_assembler_spare_buffer(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000313 }
314 }
315 if (buffer == NULL) {
316 buffer_ = NewArray<byte>(buffer_size);
317 } else {
318 buffer_ = static_cast<byte*>(buffer);
319 }
320 buffer_size_ = buffer_size;
321 own_buffer_ = true;
322 } else {
Andrei Popescu31002712010-02-23 13:46:05 +0000323 // Use externally provided buffer instead.
Steve Blocka7e24c12009-10-30 11:49:00 +0000324 ASSERT(buffer_size > 0);
325 buffer_ = static_cast<byte*>(buffer);
326 buffer_size_ = buffer_size;
327 own_buffer_ = false;
328 }
329
330 // Clear the buffer in debug mode unless it was provided by the
331 // caller in which case we can't be sure it's okay to overwrite
332 // existing code in it; see CodePatcher::CodePatcher(...).
333#ifdef DEBUG
334 if (own_buffer_) {
335 memset(buffer_, 0xCC, buffer_size); // int3
336 }
337#endif
338
Ben Murdoch85b71792012-04-11 18:30:58 +0100339 // Setup buffer pointers.
Steve Blocka7e24c12009-10-30 11:49:00 +0000340 ASSERT(buffer_ != NULL);
341 pc_ = buffer_;
342 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
343
Steve Blocka7e24c12009-10-30 11:49:00 +0000344#ifdef GENERATED_CODE_COVERAGE
345 InitCoverageLog();
346#endif
347}
348
349
350Assembler::~Assembler() {
351 if (own_buffer_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100352 if (isolate()->assembler_spare_buffer() == NULL &&
353 buffer_size_ == kMinimalBufferSize) {
354 isolate()->set_assembler_spare_buffer(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000355 } else {
356 DeleteArray(buffer_);
357 }
358 }
359}
360
361
362void Assembler::GetCode(CodeDesc* desc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000363 // Finalize code (at this point overflow() may be true, but the gap ensures
364 // that we are still not overlapping instructions and relocation info).
365 ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap.
Ben Murdoch85b71792012-04-11 18:30:58 +0100366 // Setup code descriptor.
Steve Blocka7e24c12009-10-30 11:49:00 +0000367 desc->buffer = buffer_;
368 desc->buffer_size = buffer_size_;
369 desc->instr_size = pc_offset();
370 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
371 desc->origin = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000372}
373
374
375void Assembler::Align(int m) {
376 ASSERT(IsPowerOf2(m));
Ben Murdoch85b71792012-04-11 18:30:58 +0100377 while ((pc_offset() & (m - 1)) != 0) {
378 nop();
Steve Blocka7e24c12009-10-30 11:49:00 +0000379 }
380}
381
382
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100383void Assembler::CodeTargetAlign() {
384 Align(16); // Preferred alignment of jump targets on ia32.
385}
386
387
Steve Blocka7e24c12009-10-30 11:49:00 +0000388void Assembler::cpuid() {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100389 ASSERT(CpuFeatures::IsEnabled(CPUID));
Steve Blocka7e24c12009-10-30 11:49:00 +0000390 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 EMIT(0x0F);
392 EMIT(0xA2);
393}
394
395
396void Assembler::pushad() {
397 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000398 EMIT(0x60);
399}
400
401
402void Assembler::popad() {
403 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000404 EMIT(0x61);
405}
406
407
408void Assembler::pushfd() {
409 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000410 EMIT(0x9C);
411}
412
413
414void Assembler::popfd() {
415 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000416 EMIT(0x9D);
417}
418
419
420void Assembler::push(const Immediate& x) {
421 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000422 if (x.is_int8()) {
423 EMIT(0x6a);
424 EMIT(x.x_);
425 } else {
426 EMIT(0x68);
427 emit(x);
428 }
429}
430
431
Ben Murdochb0fe1622011-05-05 13:52:32 +0100432void Assembler::push_imm32(int32_t imm32) {
433 EnsureSpace ensure_space(this);
434 EMIT(0x68);
435 emit(imm32);
436}
437
438
Steve Blocka7e24c12009-10-30 11:49:00 +0000439void Assembler::push(Register src) {
440 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000441 EMIT(0x50 | src.code());
442}
443
444
445void Assembler::push(const Operand& src) {
446 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000447 EMIT(0xFF);
448 emit_operand(esi, src);
449}
450
451
Ben Murdoch85b71792012-04-11 18:30:58 +0100452void Assembler::push(Handle<Object> handle) {
453 EnsureSpace ensure_space(this);
454 EMIT(0x68);
455 emit(handle);
456}
457
458
Steve Blocka7e24c12009-10-30 11:49:00 +0000459void Assembler::pop(Register dst) {
460 ASSERT(reloc_info_writer.last_pc() != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000461 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000462 EMIT(0x58 | dst.code());
463}
464
465
466void Assembler::pop(const Operand& dst) {
467 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000468 EMIT(0x8F);
469 emit_operand(eax, dst);
470}
471
472
473void Assembler::enter(const Immediate& size) {
474 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000475 EMIT(0xC8);
476 emit_w(size);
477 EMIT(0);
478}
479
480
481void Assembler::leave() {
482 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000483 EMIT(0xC9);
484}
485
486
487void Assembler::mov_b(Register dst, const Operand& src) {
Ben Murdoch85b71792012-04-11 18:30:58 +0100488 ASSERT(dst.code() < 4);
Steve Blocka7e24c12009-10-30 11:49:00 +0000489 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000490 EMIT(0x8A);
491 emit_operand(dst, src);
492}
493
494
495void Assembler::mov_b(const Operand& dst, int8_t imm8) {
496 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000497 EMIT(0xC6);
498 emit_operand(eax, dst);
499 EMIT(imm8);
500}
501
502
503void Assembler::mov_b(const Operand& dst, Register src) {
Ben Murdoch85b71792012-04-11 18:30:58 +0100504 ASSERT(src.code() < 4);
Steve Blocka7e24c12009-10-30 11:49:00 +0000505 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000506 EMIT(0x88);
507 emit_operand(src, dst);
508}
509
510
511void Assembler::mov_w(Register dst, const Operand& src) {
512 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000513 EMIT(0x66);
514 EMIT(0x8B);
515 emit_operand(dst, src);
516}
517
518
519void Assembler::mov_w(const Operand& dst, Register src) {
520 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000521 EMIT(0x66);
522 EMIT(0x89);
523 emit_operand(src, dst);
524}
525
526
527void Assembler::mov(Register dst, int32_t imm32) {
528 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000529 EMIT(0xB8 | dst.code());
530 emit(imm32);
531}
532
533
534void Assembler::mov(Register dst, const Immediate& x) {
535 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000536 EMIT(0xB8 | dst.code());
537 emit(x);
538}
539
540
541void Assembler::mov(Register dst, Handle<Object> handle) {
542 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000543 EMIT(0xB8 | dst.code());
544 emit(handle);
545}
546
547
548void Assembler::mov(Register dst, const Operand& src) {
549 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000550 EMIT(0x8B);
551 emit_operand(dst, src);
552}
553
554
555void Assembler::mov(Register dst, Register src) {
556 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000557 EMIT(0x89);
558 EMIT(0xC0 | src.code() << 3 | dst.code());
559}
560
561
562void Assembler::mov(const Operand& dst, const Immediate& x) {
563 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000564 EMIT(0xC7);
565 emit_operand(eax, dst);
566 emit(x);
567}
568
569
570void Assembler::mov(const Operand& dst, Handle<Object> handle) {
571 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000572 EMIT(0xC7);
573 emit_operand(eax, dst);
574 emit(handle);
575}
576
577
578void Assembler::mov(const Operand& dst, Register src) {
579 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000580 EMIT(0x89);
581 emit_operand(src, dst);
582}
583
584
585void Assembler::movsx_b(Register dst, const Operand& src) {
586 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000587 EMIT(0x0F);
588 EMIT(0xBE);
589 emit_operand(dst, src);
590}
591
592
593void Assembler::movsx_w(Register dst, const Operand& src) {
594 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000595 EMIT(0x0F);
596 EMIT(0xBF);
597 emit_operand(dst, src);
598}
599
600
601void Assembler::movzx_b(Register dst, const Operand& src) {
602 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000603 EMIT(0x0F);
604 EMIT(0xB6);
605 emit_operand(dst, src);
606}
607
608
609void Assembler::movzx_w(Register dst, const Operand& src) {
610 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000611 EMIT(0x0F);
612 EMIT(0xB7);
613 emit_operand(dst, src);
614}
615
616
Ben Murdoch85b71792012-04-11 18:30:58 +0100617void Assembler::cmov(Condition cc, Register dst, int32_t imm32) {
618 ASSERT(CpuFeatures::IsEnabled(CMOV));
619 EnsureSpace ensure_space(this);
620 UNIMPLEMENTED();
621 USE(cc);
622 USE(dst);
623 USE(imm32);
624}
625
626
627void Assembler::cmov(Condition cc, Register dst, Handle<Object> handle) {
628 ASSERT(CpuFeatures::IsEnabled(CMOV));
629 EnsureSpace ensure_space(this);
630 UNIMPLEMENTED();
631 USE(cc);
632 USE(dst);
633 USE(handle);
634}
635
636
Steve Blocka7e24c12009-10-30 11:49:00 +0000637void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100638 ASSERT(CpuFeatures::IsEnabled(CMOV));
Steve Blocka7e24c12009-10-30 11:49:00 +0000639 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000640 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000641 EMIT(0x0F);
642 EMIT(0x40 + cc);
643 emit_operand(dst, src);
644}
645
646
Steve Block6ded16b2010-05-10 14:33:55 +0100647void Assembler::cld() {
648 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +0100649 EMIT(0xFC);
650}
651
652
Leon Clarkee46be812010-01-19 14:06:41 +0000653void Assembler::rep_movs() {
654 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +0000655 EMIT(0xF3);
656 EMIT(0xA5);
657}
658
659
Steve Block6ded16b2010-05-10 14:33:55 +0100660void Assembler::rep_stos() {
661 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +0100662 EMIT(0xF3);
663 EMIT(0xAB);
664}
665
666
Leon Clarkef7060e22010-06-03 12:02:55 +0100667void Assembler::stos() {
668 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +0100669 EMIT(0xAB);
670}
671
672
Steve Blocka7e24c12009-10-30 11:49:00 +0000673void Assembler::xchg(Register dst, Register src) {
674 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000675 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding.
Steve Blocka7e24c12009-10-30 11:49:00 +0000676 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code()));
677 } else {
678 EMIT(0x87);
679 EMIT(0xC0 | src.code() << 3 | dst.code());
680 }
681}
682
683
684void Assembler::adc(Register dst, int32_t imm32) {
685 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000686 emit_arith(2, Operand(dst), Immediate(imm32));
687}
688
689
690void Assembler::adc(Register dst, const Operand& src) {
691 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000692 EMIT(0x13);
693 emit_operand(dst, src);
694}
695
696
697void Assembler::add(Register dst, const Operand& src) {
698 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000699 EMIT(0x03);
700 emit_operand(dst, src);
701}
702
703
704void Assembler::add(const Operand& dst, const Immediate& x) {
705 ASSERT(reloc_info_writer.last_pc() != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000706 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000707 emit_arith(0, dst, x);
708}
709
710
711void Assembler::and_(Register dst, int32_t imm32) {
Steve Block59151502010-09-22 15:07:15 +0100712 and_(dst, Immediate(imm32));
713}
714
715
716void Assembler::and_(Register dst, const Immediate& x) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000717 EnsureSpace ensure_space(this);
Steve Block59151502010-09-22 15:07:15 +0100718 emit_arith(4, Operand(dst), x);
Steve Blocka7e24c12009-10-30 11:49:00 +0000719}
720
721
722void Assembler::and_(Register dst, const Operand& src) {
723 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000724 EMIT(0x23);
725 emit_operand(dst, src);
726}
727
728
729void Assembler::and_(const Operand& dst, const Immediate& x) {
730 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000731 emit_arith(4, dst, x);
732}
733
734
735void Assembler::and_(const Operand& dst, Register src) {
736 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000737 EMIT(0x21);
738 emit_operand(src, dst);
739}
740
741
742void Assembler::cmpb(const Operand& op, int8_t imm8) {
743 EnsureSpace ensure_space(this);
Ben Murdoch85b71792012-04-11 18:30:58 +0100744 EMIT(0x80);
745 emit_operand(edi, op); // edi == 7
Steve Blocka7e24c12009-10-30 11:49:00 +0000746 EMIT(imm8);
747}
748
749
Ben Murdoch85b71792012-04-11 18:30:58 +0100750void Assembler::cmpb(const Operand& dst, Register src) {
751 ASSERT(src.is_byte_register());
Leon Clarked91b9f72010-01-27 17:25:45 +0000752 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +0000753 EMIT(0x38);
Ben Murdoch85b71792012-04-11 18:30:58 +0100754 emit_operand(src, dst);
Leon Clarked91b9f72010-01-27 17:25:45 +0000755}
756
757
Ben Murdoch85b71792012-04-11 18:30:58 +0100758void Assembler::cmpb(Register dst, const Operand& src) {
759 ASSERT(dst.is_byte_register());
Leon Clarked91b9f72010-01-27 17:25:45 +0000760 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +0000761 EMIT(0x3A);
Ben Murdoch85b71792012-04-11 18:30:58 +0100762 emit_operand(dst, src);
Leon Clarked91b9f72010-01-27 17:25:45 +0000763}
764
765
Steve Blocka7e24c12009-10-30 11:49:00 +0000766void Assembler::cmpw(const Operand& op, Immediate imm16) {
767 ASSERT(imm16.is_int16());
768 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000769 EMIT(0x66);
770 EMIT(0x81);
771 emit_operand(edi, op);
772 emit_w(imm16);
773}
774
775
776void Assembler::cmp(Register reg, int32_t imm32) {
777 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000778 emit_arith(7, Operand(reg), Immediate(imm32));
779}
780
781
782void Assembler::cmp(Register reg, Handle<Object> handle) {
783 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000784 emit_arith(7, Operand(reg), Immediate(handle));
785}
786
787
788void Assembler::cmp(Register reg, const Operand& op) {
789 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000790 EMIT(0x3B);
791 emit_operand(reg, op);
792}
793
794
795void Assembler::cmp(const Operand& op, const Immediate& imm) {
796 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000797 emit_arith(7, op, imm);
798}
799
800
801void Assembler::cmp(const Operand& op, Handle<Object> handle) {
802 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000803 emit_arith(7, op, Immediate(handle));
804}
805
806
807void Assembler::cmpb_al(const Operand& op) {
808 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000809 EMIT(0x38); // CMP r/m8, r8
810 emit_operand(eax, op); // eax has same code as register al.
811}
812
813
814void Assembler::cmpw_ax(const Operand& op) {
815 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000816 EMIT(0x66);
817 EMIT(0x39); // CMP r/m16, r16
818 emit_operand(eax, op); // eax has same code as register ax.
819}
820
821
822void Assembler::dec_b(Register dst) {
823 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000824 EMIT(0xFE);
825 EMIT(0xC8 | dst.code());
826}
827
828
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100829void Assembler::dec_b(const Operand& dst) {
830 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100831 EMIT(0xFE);
832 emit_operand(ecx, dst);
833}
834
835
Steve Blocka7e24c12009-10-30 11:49:00 +0000836void Assembler::dec(Register dst) {
837 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000838 EMIT(0x48 | dst.code());
839}
840
841
842void Assembler::dec(const Operand& dst) {
843 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000844 EMIT(0xFF);
845 emit_operand(ecx, dst);
846}
847
848
849void Assembler::cdq() {
850 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000851 EMIT(0x99);
852}
853
854
855void Assembler::idiv(Register src) {
856 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000857 EMIT(0xF7);
858 EMIT(0xF8 | src.code());
859}
860
861
862void Assembler::imul(Register reg) {
863 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000864 EMIT(0xF7);
865 EMIT(0xE8 | reg.code());
866}
867
868
869void Assembler::imul(Register dst, const Operand& src) {
870 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000871 EMIT(0x0F);
872 EMIT(0xAF);
873 emit_operand(dst, src);
874}
875
876
877void Assembler::imul(Register dst, Register src, int32_t imm32) {
878 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000879 if (is_int8(imm32)) {
880 EMIT(0x6B);
881 EMIT(0xC0 | dst.code() << 3 | src.code());
882 EMIT(imm32);
883 } else {
884 EMIT(0x69);
885 EMIT(0xC0 | dst.code() << 3 | src.code());
886 emit(imm32);
887 }
888}
889
890
891void Assembler::inc(Register dst) {
892 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000893 EMIT(0x40 | dst.code());
894}
895
896
897void Assembler::inc(const Operand& dst) {
898 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000899 EMIT(0xFF);
900 emit_operand(eax, dst);
901}
902
903
904void Assembler::lea(Register dst, const Operand& src) {
905 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000906 EMIT(0x8D);
907 emit_operand(dst, src);
908}
909
910
911void Assembler::mul(Register src) {
912 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000913 EMIT(0xF7);
914 EMIT(0xE0 | src.code());
915}
916
917
918void Assembler::neg(Register dst) {
919 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000920 EMIT(0xF7);
921 EMIT(0xD8 | dst.code());
922}
923
924
925void Assembler::not_(Register dst) {
926 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000927 EMIT(0xF7);
928 EMIT(0xD0 | dst.code());
929}
930
931
932void Assembler::or_(Register dst, int32_t imm32) {
933 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000934 emit_arith(1, Operand(dst), Immediate(imm32));
935}
936
937
938void Assembler::or_(Register dst, const Operand& src) {
939 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000940 EMIT(0x0B);
941 emit_operand(dst, src);
942}
943
944
945void Assembler::or_(const Operand& dst, const Immediate& x) {
946 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000947 emit_arith(1, dst, x);
948}
949
950
951void Assembler::or_(const Operand& dst, Register src) {
952 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000953 EMIT(0x09);
954 emit_operand(src, dst);
955}
956
957
958void Assembler::rcl(Register dst, uint8_t imm8) {
959 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000960 ASSERT(is_uint5(imm8)); // illegal shift count
961 if (imm8 == 1) {
962 EMIT(0xD1);
963 EMIT(0xD0 | dst.code());
964 } else {
965 EMIT(0xC1);
966 EMIT(0xD0 | dst.code());
967 EMIT(imm8);
968 }
969}
970
971
Iain Merrick75681382010-08-19 15:07:18 +0100972void Assembler::rcr(Register dst, uint8_t imm8) {
973 EnsureSpace ensure_space(this);
Iain Merrick75681382010-08-19 15:07:18 +0100974 ASSERT(is_uint5(imm8)); // illegal shift count
975 if (imm8 == 1) {
976 EMIT(0xD1);
977 EMIT(0xD8 | dst.code());
978 } else {
979 EMIT(0xC1);
980 EMIT(0xD8 | dst.code());
981 EMIT(imm8);
982 }
983}
984
985
Steve Blocka7e24c12009-10-30 11:49:00 +0000986void Assembler::sar(Register dst, uint8_t imm8) {
987 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000988 ASSERT(is_uint5(imm8)); // illegal shift count
989 if (imm8 == 1) {
990 EMIT(0xD1);
991 EMIT(0xF8 | dst.code());
992 } else {
993 EMIT(0xC1);
994 EMIT(0xF8 | dst.code());
995 EMIT(imm8);
996 }
997}
998
999
Steve Blockd0582a62009-12-15 09:54:21 +00001000void Assembler::sar_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001001 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001002 EMIT(0xD3);
1003 EMIT(0xF8 | dst.code());
1004}
1005
1006
1007void Assembler::sbb(Register dst, const Operand& src) {
1008 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001009 EMIT(0x1B);
1010 emit_operand(dst, src);
1011}
1012
1013
1014void Assembler::shld(Register dst, const Operand& src) {
1015 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001016 EMIT(0x0F);
1017 EMIT(0xA5);
1018 emit_operand(dst, src);
1019}
1020
1021
1022void Assembler::shl(Register dst, uint8_t imm8) {
1023 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001024 ASSERT(is_uint5(imm8)); // illegal shift count
1025 if (imm8 == 1) {
1026 EMIT(0xD1);
1027 EMIT(0xE0 | dst.code());
1028 } else {
1029 EMIT(0xC1);
1030 EMIT(0xE0 | dst.code());
1031 EMIT(imm8);
1032 }
1033}
1034
1035
Steve Blockd0582a62009-12-15 09:54:21 +00001036void Assembler::shl_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001037 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001038 EMIT(0xD3);
1039 EMIT(0xE0 | dst.code());
1040}
1041
1042
1043void Assembler::shrd(Register dst, const Operand& src) {
1044 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001045 EMIT(0x0F);
1046 EMIT(0xAD);
1047 emit_operand(dst, src);
1048}
1049
1050
1051void Assembler::shr(Register dst, uint8_t imm8) {
1052 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001053 ASSERT(is_uint5(imm8)); // illegal shift count
Steve Blockd0582a62009-12-15 09:54:21 +00001054 if (imm8 == 1) {
1055 EMIT(0xD1);
1056 EMIT(0xE8 | dst.code());
1057 } else {
1058 EMIT(0xC1);
1059 EMIT(0xE8 | dst.code());
1060 EMIT(imm8);
1061 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001062}
1063
1064
1065void Assembler::shr_cl(Register dst) {
1066 EnsureSpace ensure_space(this);
Steve Blockd0582a62009-12-15 09:54:21 +00001067 EMIT(0xD3);
Steve Blocka7e24c12009-10-30 11:49:00 +00001068 EMIT(0xE8 | dst.code());
1069}
1070
1071
Ben Murdoch85b71792012-04-11 18:30:58 +01001072void Assembler::subb(const Operand& op, int8_t imm8) {
1073 EnsureSpace ensure_space(this);
1074 if (op.is_reg(eax)) {
1075 EMIT(0x2c);
1076 } else {
1077 EMIT(0x80);
1078 emit_operand(ebp, op); // ebp == 5
1079 }
1080 EMIT(imm8);
1081}
1082
1083
Steve Blocka7e24c12009-10-30 11:49:00 +00001084void Assembler::sub(const Operand& dst, const Immediate& x) {
1085 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001086 emit_arith(5, dst, x);
1087}
1088
1089
1090void Assembler::sub(Register dst, const Operand& src) {
1091 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001092 EMIT(0x2B);
1093 emit_operand(dst, src);
1094}
1095
1096
Ben Murdoch85b71792012-04-11 18:30:58 +01001097void Assembler::subb(Register dst, const Operand& src) {
1098 ASSERT(dst.code() < 4);
1099 EnsureSpace ensure_space(this);
1100 EMIT(0x2A);
1101 emit_operand(dst, src);
1102}
1103
1104
Steve Blocka7e24c12009-10-30 11:49:00 +00001105void Assembler::sub(const Operand& dst, Register src) {
1106 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001107 EMIT(0x29);
1108 emit_operand(src, dst);
1109}
1110
1111
1112void Assembler::test(Register reg, const Immediate& imm) {
1113 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001114 // Only use test against byte for registers that have a byte
1115 // variant: eax, ebx, ecx, and edx.
Ben Murdoch85b71792012-04-11 18:30:58 +01001116 if (imm.rmode_ == RelocInfo::NONE && is_uint8(imm.x_) && reg.code() < 4) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001117 uint8_t imm8 = imm.x_;
1118 if (reg.is(eax)) {
1119 EMIT(0xA8);
1120 EMIT(imm8);
1121 } else {
1122 emit_arith_b(0xF6, 0xC0, reg, imm8);
1123 }
1124 } else {
1125 // This is not using emit_arith because test doesn't support
1126 // sign-extension of 8-bit operands.
1127 if (reg.is(eax)) {
1128 EMIT(0xA9);
1129 } else {
1130 EMIT(0xF7);
1131 EMIT(0xC0 | reg.code());
1132 }
1133 emit(imm);
1134 }
1135}
1136
1137
1138void Assembler::test(Register reg, const Operand& op) {
1139 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001140 EMIT(0x85);
1141 emit_operand(reg, op);
1142}
1143
1144
Leon Clarkee46be812010-01-19 14:06:41 +00001145void Assembler::test_b(Register reg, const Operand& op) {
1146 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00001147 EMIT(0x84);
1148 emit_operand(reg, op);
1149}
1150
1151
Steve Blocka7e24c12009-10-30 11:49:00 +00001152void Assembler::test(const Operand& op, const Immediate& imm) {
1153 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001154 EMIT(0xF7);
1155 emit_operand(eax, op);
1156 emit(imm);
1157}
1158
1159
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001160void Assembler::test_b(const Operand& op, uint8_t imm8) {
1161 EnsureSpace ensure_space(this);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001162 EMIT(0xF6);
1163 emit_operand(eax, op);
1164 EMIT(imm8);
1165}
1166
1167
Steve Blocka7e24c12009-10-30 11:49:00 +00001168void Assembler::xor_(Register dst, int32_t imm32) {
1169 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001170 emit_arith(6, Operand(dst), Immediate(imm32));
1171}
1172
1173
1174void Assembler::xor_(Register dst, const Operand& src) {
1175 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001176 EMIT(0x33);
1177 emit_operand(dst, src);
1178}
1179
1180
Ben Murdoch85b71792012-04-11 18:30:58 +01001181void Assembler::xor_(const Operand& src, Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001182 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001183 EMIT(0x31);
Ben Murdoch85b71792012-04-11 18:30:58 +01001184 emit_operand(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001185}
1186
1187
1188void Assembler::xor_(const Operand& dst, const Immediate& x) {
1189 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001190 emit_arith(6, dst, x);
1191}
1192
1193
1194void Assembler::bt(const Operand& dst, Register src) {
1195 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001196 EMIT(0x0F);
1197 EMIT(0xA3);
1198 emit_operand(src, dst);
1199}
1200
1201
1202void Assembler::bts(const Operand& dst, Register src) {
1203 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001204 EMIT(0x0F);
1205 EMIT(0xAB);
1206 emit_operand(src, dst);
1207}
1208
1209
1210void Assembler::hlt() {
1211 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001212 EMIT(0xF4);
1213}
1214
1215
1216void Assembler::int3() {
1217 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001218 EMIT(0xCC);
1219}
1220
1221
1222void Assembler::nop() {
1223 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001224 EMIT(0x90);
1225}
1226
1227
1228void Assembler::rdtsc() {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001229 ASSERT(CpuFeatures::IsEnabled(RDTSC));
Steve Blocka7e24c12009-10-30 11:49:00 +00001230 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001231 EMIT(0x0F);
1232 EMIT(0x31);
1233}
1234
1235
1236void Assembler::ret(int imm16) {
1237 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001238 ASSERT(is_uint16(imm16));
1239 if (imm16 == 0) {
1240 EMIT(0xC3);
1241 } else {
1242 EMIT(0xC2);
1243 EMIT(imm16 & 0xFF);
1244 EMIT((imm16 >> 8) & 0xFF);
1245 }
1246}
1247
1248
1249// Labels refer to positions in the (to be) generated code.
1250// There are bound, linked, and unused labels.
1251//
1252// Bound labels refer to known positions in the already
1253// generated code. pos() is the position the label refers to.
1254//
1255// Linked labels refer to unknown positions in the code
1256// to be generated; pos() is the position of the 32bit
1257// Displacement of the last instruction using the label.
1258
1259
1260void Assembler::print(Label* L) {
1261 if (L->is_unused()) {
1262 PrintF("unused label\n");
1263 } else if (L->is_bound()) {
1264 PrintF("bound label to %d\n", L->pos());
1265 } else if (L->is_linked()) {
1266 Label l = *L;
1267 PrintF("unbound label");
1268 while (l.is_linked()) {
1269 Displacement disp = disp_at(&l);
1270 PrintF("@ %d ", l.pos());
1271 disp.print();
1272 PrintF("\n");
1273 disp.next(&l);
1274 }
1275 } else {
1276 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
1277 }
1278}
1279
1280
1281void Assembler::bind_to(Label* L, int pos) {
1282 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001283 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position
1284 while (L->is_linked()) {
1285 Displacement disp = disp_at(L);
1286 int fixup_pos = L->pos();
1287 if (disp.type() == Displacement::CODE_RELATIVE) {
1288 // Relative to Code* heap object pointer.
1289 long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
1290 } else {
1291 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
1292 ASSERT(byte_at(fixup_pos - 1) == 0xE9); // jmp expected
1293 }
Andrei Popescu31002712010-02-23 13:46:05 +00001294 // Relative address, relative to point after address.
Steve Blocka7e24c12009-10-30 11:49:00 +00001295 int imm32 = pos - (fixup_pos + sizeof(int32_t));
1296 long_at_put(fixup_pos, imm32);
1297 }
1298 disp.next(L);
1299 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001300 while (L->is_near_linked()) {
1301 int fixup_pos = L->near_link_pos();
1302 int offset_to_next =
1303 static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
1304 ASSERT(offset_to_next <= 0);
1305 // Relative address, relative to point after address.
1306 int disp = pos - fixup_pos - sizeof(int8_t);
1307 ASSERT(0 <= disp && disp <= 127);
1308 set_byte_at(fixup_pos, disp);
1309 if (offset_to_next < 0) {
1310 L->link_to(fixup_pos + offset_to_next, Label::kNear);
1311 } else {
1312 L->UnuseNear();
1313 }
1314 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001315 L->bind_to(pos);
1316}
1317
1318
Steve Blocka7e24c12009-10-30 11:49:00 +00001319void Assembler::bind(Label* L) {
1320 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001321 ASSERT(!L->is_bound()); // label can only be bound once
1322 bind_to(L, pc_offset());
1323}
1324
1325
1326void Assembler::call(Label* L) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001327 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001328 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001329 if (L->is_bound()) {
1330 const int long_size = 5;
1331 int offs = L->pos() - pc_offset();
1332 ASSERT(offs <= 0);
Andrei Popescu31002712010-02-23 13:46:05 +00001333 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001334 EMIT(0xE8);
1335 emit(offs - long_size);
1336 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001337 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001338 EMIT(0xE8);
1339 emit_disp(L, Displacement::OTHER);
1340 }
1341}
1342
1343
1344void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001345 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001346 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001347 ASSERT(!RelocInfo::IsCodeTarget(rmode));
1348 EMIT(0xE8);
1349 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1350}
1351
1352
Ben Murdoch257744e2011-11-30 15:57:28 +00001353int Assembler::CallSize(const Operand& adr) {
1354 // Call size is 1 (opcode) + adr.len_ (operand).
1355 return 1 + adr.len_;
1356}
1357
1358
Steve Blocka7e24c12009-10-30 11:49:00 +00001359void Assembler::call(const Operand& adr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001360 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001361 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001362 EMIT(0xFF);
1363 emit_operand(edx, adr);
1364}
1365
1366
Ben Murdoch257744e2011-11-30 15:57:28 +00001367int Assembler::CallSize(Handle<Code> code, RelocInfo::Mode rmode) {
1368 return 1 /* EMIT */ + sizeof(uint32_t) /* emit */;
Steve Blocka7e24c12009-10-30 11:49:00 +00001369}
1370
1371
Ben Murdoch257744e2011-11-30 15:57:28 +00001372void Assembler::call(Handle<Code> code,
1373 RelocInfo::Mode rmode,
1374 unsigned ast_id) {
1375 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001376 EnsureSpace ensure_space(this);
Ben Murdoch257744e2011-11-30 15:57:28 +00001377 ASSERT(RelocInfo::IsCodeTarget(rmode));
1378 EMIT(0xE8);
1379 emit(reinterpret_cast<intptr_t>(code.location()), rmode, ast_id);
1380}
1381
1382
1383void Assembler::jmp(Label* L, Label::Distance distance) {
1384 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001385 if (L->is_bound()) {
1386 const int short_size = 2;
1387 const int long_size = 5;
1388 int offs = L->pos() - pc_offset();
1389 ASSERT(offs <= 0);
1390 if (is_int8(offs - short_size)) {
Andrei Popescu31002712010-02-23 13:46:05 +00001391 // 1110 1011 #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001392 EMIT(0xEB);
1393 EMIT((offs - short_size) & 0xFF);
1394 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001395 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001396 EMIT(0xE9);
1397 emit(offs - long_size);
1398 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001399 } else if (distance == Label::kNear) {
1400 EMIT(0xEB);
1401 emit_near_disp(L);
Steve Blocka7e24c12009-10-30 11:49:00 +00001402 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001403 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001404 EMIT(0xE9);
1405 emit_disp(L, Displacement::UNCONDITIONAL_JUMP);
1406 }
1407}
1408
1409
1410void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
1411 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001412 ASSERT(!RelocInfo::IsCodeTarget(rmode));
1413 EMIT(0xE9);
1414 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1415}
1416
1417
1418void Assembler::jmp(const Operand& adr) {
1419 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001420 EMIT(0xFF);
1421 emit_operand(esp, adr);
1422}
1423
1424
1425void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
1426 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001427 ASSERT(RelocInfo::IsCodeTarget(rmode));
1428 EMIT(0xE9);
1429 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
1430}
1431
1432
Ben Murdoch257744e2011-11-30 15:57:28 +00001433void Assembler::j(Condition cc, Label* L, Label::Distance distance) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001434 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001435 ASSERT(0 <= cc && cc < 16);
Steve Blocka7e24c12009-10-30 11:49:00 +00001436 if (L->is_bound()) {
1437 const int short_size = 2;
1438 const int long_size = 6;
1439 int offs = L->pos() - pc_offset();
1440 ASSERT(offs <= 0);
1441 if (is_int8(offs - short_size)) {
1442 // 0111 tttn #8-bit disp
1443 EMIT(0x70 | cc);
1444 EMIT((offs - short_size) & 0xFF);
1445 } else {
1446 // 0000 1111 1000 tttn #32-bit disp
1447 EMIT(0x0F);
1448 EMIT(0x80 | cc);
1449 emit(offs - long_size);
1450 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001451 } else if (distance == Label::kNear) {
1452 EMIT(0x70 | cc);
1453 emit_near_disp(L);
Steve Blocka7e24c12009-10-30 11:49:00 +00001454 } else {
1455 // 0000 1111 1000 tttn #32-bit disp
1456 // Note: could eliminate cond. jumps to this jump if condition
1457 // is the same however, seems to be rather unlikely case.
1458 EMIT(0x0F);
1459 EMIT(0x80 | cc);
1460 emit_disp(L, Displacement::OTHER);
1461 }
1462}
1463
1464
Ben Murdoch257744e2011-11-30 15:57:28 +00001465void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001466 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001467 ASSERT((0 <= cc) && (cc < 16));
Andrei Popescu31002712010-02-23 13:46:05 +00001468 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001469 EMIT(0x0F);
1470 EMIT(0x80 | cc);
1471 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1472}
1473
1474
Ben Murdoch257744e2011-11-30 15:57:28 +00001475void Assembler::j(Condition cc, Handle<Code> code) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001476 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001477 // 0000 1111 1000 tttn #32-bit disp
1478 EMIT(0x0F);
1479 EMIT(0x80 | cc);
1480 emit(reinterpret_cast<intptr_t>(code.location()), RelocInfo::CODE_TARGET);
1481}
1482
1483
Andrei Popescu31002712010-02-23 13:46:05 +00001484// FPU instructions.
Steve Blocka7e24c12009-10-30 11:49:00 +00001485
Steve Blocka7e24c12009-10-30 11:49:00 +00001486void Assembler::fld(int i) {
1487 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001488 emit_farith(0xD9, 0xC0, i);
1489}
1490
1491
Andrei Popescu402d9372010-02-26 13:31:12 +00001492void Assembler::fstp(int i) {
1493 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00001494 emit_farith(0xDD, 0xD8, i);
1495}
1496
1497
Steve Blocka7e24c12009-10-30 11:49:00 +00001498void Assembler::fld1() {
1499 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001500 EMIT(0xD9);
1501 EMIT(0xE8);
1502}
1503
1504
Andrei Popescu402d9372010-02-26 13:31:12 +00001505void Assembler::fldpi() {
1506 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00001507 EMIT(0xD9);
1508 EMIT(0xEB);
1509}
1510
1511
Steve Blocka7e24c12009-10-30 11:49:00 +00001512void Assembler::fldz() {
1513 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001514 EMIT(0xD9);
1515 EMIT(0xEE);
1516}
1517
1518
Ben Murdochb0fe1622011-05-05 13:52:32 +01001519void Assembler::fldln2() {
1520 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001521 EMIT(0xD9);
1522 EMIT(0xED);
1523}
1524
1525
Steve Blocka7e24c12009-10-30 11:49:00 +00001526void Assembler::fld_s(const Operand& adr) {
1527 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001528 EMIT(0xD9);
1529 emit_operand(eax, adr);
1530}
1531
1532
1533void Assembler::fld_d(const Operand& adr) {
1534 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001535 EMIT(0xDD);
1536 emit_operand(eax, adr);
1537}
1538
1539
1540void Assembler::fstp_s(const Operand& adr) {
1541 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001542 EMIT(0xD9);
1543 emit_operand(ebx, adr);
1544}
1545
1546
1547void Assembler::fstp_d(const Operand& adr) {
1548 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001549 EMIT(0xDD);
1550 emit_operand(ebx, adr);
1551}
1552
1553
Andrei Popescu402d9372010-02-26 13:31:12 +00001554void Assembler::fst_d(const Operand& adr) {
1555 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00001556 EMIT(0xDD);
1557 emit_operand(edx, adr);
1558}
1559
1560
Steve Blocka7e24c12009-10-30 11:49:00 +00001561void Assembler::fild_s(const Operand& adr) {
1562 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001563 EMIT(0xDB);
1564 emit_operand(eax, adr);
1565}
1566
1567
1568void Assembler::fild_d(const Operand& adr) {
1569 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001570 EMIT(0xDF);
1571 emit_operand(ebp, adr);
1572}
1573
1574
1575void Assembler::fistp_s(const Operand& adr) {
1576 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001577 EMIT(0xDB);
1578 emit_operand(ebx, adr);
1579}
1580
1581
1582void Assembler::fisttp_s(const Operand& adr) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001583 ASSERT(CpuFeatures::IsEnabled(SSE3));
Steve Blocka7e24c12009-10-30 11:49:00 +00001584 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001585 EMIT(0xDB);
1586 emit_operand(ecx, adr);
1587}
1588
1589
Leon Clarkee46be812010-01-19 14:06:41 +00001590void Assembler::fisttp_d(const Operand& adr) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001591 ASSERT(CpuFeatures::IsEnabled(SSE3));
Leon Clarkee46be812010-01-19 14:06:41 +00001592 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00001593 EMIT(0xDD);
1594 emit_operand(ecx, adr);
1595}
1596
1597
Steve Blocka7e24c12009-10-30 11:49:00 +00001598void Assembler::fist_s(const Operand& adr) {
1599 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001600 EMIT(0xDB);
1601 emit_operand(edx, adr);
1602}
1603
1604
1605void Assembler::fistp_d(const Operand& adr) {
1606 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001607 EMIT(0xDF);
1608 emit_operand(edi, adr);
1609}
1610
1611
1612void Assembler::fabs() {
1613 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001614 EMIT(0xD9);
1615 EMIT(0xE1);
1616}
1617
1618
1619void Assembler::fchs() {
1620 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001621 EMIT(0xD9);
1622 EMIT(0xE0);
1623}
1624
1625
1626void Assembler::fcos() {
1627 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001628 EMIT(0xD9);
1629 EMIT(0xFF);
1630}
1631
1632
1633void Assembler::fsin() {
1634 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001635 EMIT(0xD9);
1636 EMIT(0xFE);
1637}
1638
1639
Ben Murdochb0fe1622011-05-05 13:52:32 +01001640void Assembler::fyl2x() {
1641 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001642 EMIT(0xD9);
1643 EMIT(0xF1);
1644}
1645
1646
Steve Blocka7e24c12009-10-30 11:49:00 +00001647void Assembler::fadd(int i) {
1648 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001649 emit_farith(0xDC, 0xC0, i);
1650}
1651
1652
1653void Assembler::fsub(int i) {
1654 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001655 emit_farith(0xDC, 0xE8, i);
1656}
1657
1658
1659void Assembler::fisub_s(const Operand& adr) {
1660 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001661 EMIT(0xDA);
1662 emit_operand(esp, adr);
1663}
1664
1665
1666void Assembler::fmul(int i) {
1667 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001668 emit_farith(0xDC, 0xC8, i);
1669}
1670
1671
1672void Assembler::fdiv(int i) {
1673 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001674 emit_farith(0xDC, 0xF8, i);
1675}
1676
1677
1678void Assembler::faddp(int i) {
1679 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001680 emit_farith(0xDE, 0xC0, i);
1681}
1682
1683
1684void Assembler::fsubp(int i) {
1685 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001686 emit_farith(0xDE, 0xE8, i);
1687}
1688
1689
1690void Assembler::fsubrp(int i) {
1691 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001692 emit_farith(0xDE, 0xE0, i);
1693}
1694
1695
1696void Assembler::fmulp(int i) {
1697 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001698 emit_farith(0xDE, 0xC8, i);
1699}
1700
1701
1702void Assembler::fdivp(int i) {
1703 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001704 emit_farith(0xDE, 0xF8, i);
1705}
1706
1707
1708void Assembler::fprem() {
1709 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001710 EMIT(0xD9);
1711 EMIT(0xF8);
1712}
1713
1714
1715void Assembler::fprem1() {
1716 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001717 EMIT(0xD9);
1718 EMIT(0xF5);
1719}
1720
1721
1722void Assembler::fxch(int i) {
1723 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001724 emit_farith(0xD9, 0xC8, i);
1725}
1726
1727
1728void Assembler::fincstp() {
1729 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001730 EMIT(0xD9);
1731 EMIT(0xF7);
1732}
1733
1734
1735void Assembler::ffree(int i) {
1736 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001737 emit_farith(0xDD, 0xC0, i);
1738}
1739
1740
1741void Assembler::ftst() {
1742 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001743 EMIT(0xD9);
1744 EMIT(0xE4);
1745}
1746
1747
1748void Assembler::fucomp(int i) {
1749 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001750 emit_farith(0xDD, 0xE8, i);
1751}
1752
1753
1754void Assembler::fucompp() {
1755 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001756 EMIT(0xDA);
1757 EMIT(0xE9);
1758}
1759
1760
Steve Block3ce2e202009-11-05 08:53:23 +00001761void Assembler::fucomi(int i) {
1762 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001763 EMIT(0xDB);
1764 EMIT(0xE8 + i);
1765}
1766
1767
1768void Assembler::fucomip() {
1769 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001770 EMIT(0xDF);
1771 EMIT(0xE9);
1772}
1773
1774
Steve Blocka7e24c12009-10-30 11:49:00 +00001775void Assembler::fcompp() {
1776 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001777 EMIT(0xDE);
1778 EMIT(0xD9);
1779}
1780
1781
1782void Assembler::fnstsw_ax() {
1783 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001784 EMIT(0xDF);
1785 EMIT(0xE0);
1786}
1787
1788
1789void Assembler::fwait() {
1790 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001791 EMIT(0x9B);
1792}
1793
1794
1795void Assembler::frndint() {
1796 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001797 EMIT(0xD9);
1798 EMIT(0xFC);
1799}
1800
1801
1802void Assembler::fnclex() {
1803 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001804 EMIT(0xDB);
1805 EMIT(0xE2);
1806}
1807
1808
1809void Assembler::sahf() {
1810 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001811 EMIT(0x9E);
1812}
1813
1814
1815void Assembler::setcc(Condition cc, Register reg) {
1816 ASSERT(reg.is_byte_register());
1817 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001818 EMIT(0x0F);
1819 EMIT(0x90 | cc);
1820 EMIT(0xC0 | reg.code());
1821}
1822
1823
1824void Assembler::cvttss2si(Register dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001825 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00001826 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001827 EMIT(0xF3);
1828 EMIT(0x0F);
1829 EMIT(0x2C);
1830 emit_operand(dst, src);
1831}
1832
1833
1834void Assembler::cvttsd2si(Register dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001835 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00001836 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001837 EMIT(0xF2);
1838 EMIT(0x0F);
1839 EMIT(0x2C);
1840 emit_operand(dst, src);
1841}
1842
1843
1844void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001845 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00001846 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001847 EMIT(0xF2);
1848 EMIT(0x0F);
1849 EMIT(0x2A);
1850 emit_sse_operand(dst, src);
1851}
1852
1853
Steve Block6ded16b2010-05-10 14:33:55 +01001854void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001855 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block6ded16b2010-05-10 14:33:55 +01001856 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01001857 EMIT(0xF3);
1858 EMIT(0x0F);
1859 EMIT(0x5A);
1860 emit_sse_operand(dst, src);
1861}
1862
1863
Steve Block44f0eee2011-05-26 01:26:41 +01001864void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001865 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block44f0eee2011-05-26 01:26:41 +01001866 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +01001867 EMIT(0xF2);
1868 EMIT(0x0F);
1869 EMIT(0x5A);
1870 emit_sse_operand(dst, src);
1871}
1872
1873
Steve Blocka7e24c12009-10-30 11:49:00 +00001874void Assembler::addsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001875 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00001876 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001877 EMIT(0xF2);
1878 EMIT(0x0F);
1879 EMIT(0x58);
1880 emit_sse_operand(dst, src);
1881}
1882
1883
1884void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001885 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00001886 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001887 EMIT(0xF2);
1888 EMIT(0x0F);
1889 EMIT(0x59);
1890 emit_sse_operand(dst, src);
1891}
1892
1893
1894void Assembler::subsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001895 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00001896 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001897 EMIT(0xF2);
1898 EMIT(0x0F);
1899 EMIT(0x5C);
1900 emit_sse_operand(dst, src);
1901}
1902
1903
1904void Assembler::divsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001905 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00001906 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001907 EMIT(0xF2);
1908 EMIT(0x0F);
1909 EMIT(0x5E);
1910 emit_sse_operand(dst, src);
1911}
1912
1913
Leon Clarkee46be812010-01-19 14:06:41 +00001914void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001915 ASSERT(CpuFeatures::IsEnabled(SSE2));
Leon Clarkee46be812010-01-19 14:06:41 +00001916 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00001917 EMIT(0x66);
1918 EMIT(0x0F);
1919 EMIT(0x57);
1920 emit_sse_operand(dst, src);
1921}
1922
1923
Ben Murdoch257744e2011-11-30 15:57:28 +00001924void Assembler::xorps(XMMRegister dst, XMMRegister src) {
1925 EnsureSpace ensure_space(this);
1926 EMIT(0x0F);
1927 EMIT(0x57);
1928 emit_sse_operand(dst, src);
1929}
1930
1931
Steve Block6ded16b2010-05-10 14:33:55 +01001932void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
1933 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01001934 EMIT(0xF2);
1935 EMIT(0x0F);
1936 EMIT(0x51);
1937 emit_sse_operand(dst, src);
1938}
1939
1940
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001941void Assembler::andpd(XMMRegister dst, XMMRegister src) {
1942 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001943 EMIT(0x66);
1944 EMIT(0x0F);
1945 EMIT(0x54);
1946 emit_sse_operand(dst, src);
1947}
1948
1949
Steve Block6ded16b2010-05-10 14:33:55 +01001950void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001951 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block6ded16b2010-05-10 14:33:55 +01001952 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01001953 EMIT(0x66);
1954 EMIT(0x0F);
1955 EMIT(0x2E);
1956 emit_sse_operand(dst, src);
1957}
1958
1959
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001960void Assembler::roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode) {
1961 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
1962 EnsureSpace ensure_space(this);
1963 EMIT(0x66);
1964 EMIT(0x0F);
1965 EMIT(0x3A);
1966 EMIT(0x0B);
1967 emit_sse_operand(dst, src);
1968 // Mask precision exeption.
1969 EMIT(static_cast<byte>(mode) | 0x8);
1970}
1971
Steve Block6ded16b2010-05-10 14:33:55 +01001972void Assembler::movmskpd(Register dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001973 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block6ded16b2010-05-10 14:33:55 +01001974 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01001975 EMIT(0x66);
1976 EMIT(0x0F);
1977 EMIT(0x50);
1978 emit_sse_operand(dst, src);
1979}
1980
1981
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001982void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001983 ASSERT(CpuFeatures::IsEnabled(SSE2));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001984 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001985 EMIT(0xF2);
1986 EMIT(0x0F);
1987 EMIT(0xC2);
1988 emit_sse_operand(dst, src);
1989 EMIT(1); // LT == 1
1990}
1991
1992
1993void Assembler::movaps(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001994 ASSERT(CpuFeatures::IsEnabled(SSE2));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001995 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001996 EMIT(0x0F);
1997 EMIT(0x28);
1998 emit_sse_operand(dst, src);
1999}
2000
2001
2002void Assembler::movdqa(const Operand& dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002003 ASSERT(CpuFeatures::IsEnabled(SSE2));
Leon Clarkee46be812010-01-19 14:06:41 +00002004 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002005 EMIT(0x66);
2006 EMIT(0x0F);
2007 EMIT(0x7F);
2008 emit_sse_operand(src, dst);
2009}
2010
2011
2012void Assembler::movdqa(XMMRegister dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002013 ASSERT(CpuFeatures::IsEnabled(SSE2));
Leon Clarkee46be812010-01-19 14:06:41 +00002014 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002015 EMIT(0x66);
2016 EMIT(0x0F);
2017 EMIT(0x6F);
2018 emit_sse_operand(dst, src);
2019}
2020
2021
2022void Assembler::movdqu(const Operand& dst, XMMRegister src ) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002023 ASSERT(CpuFeatures::IsEnabled(SSE2));
Leon Clarkee46be812010-01-19 14:06:41 +00002024 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002025 EMIT(0xF3);
2026 EMIT(0x0F);
2027 EMIT(0x7F);
2028 emit_sse_operand(src, dst);
2029}
2030
2031
2032void Assembler::movdqu(XMMRegister dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002033 ASSERT(CpuFeatures::IsEnabled(SSE2));
Leon Clarkee46be812010-01-19 14:06:41 +00002034 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002035 EMIT(0xF3);
2036 EMIT(0x0F);
2037 EMIT(0x6F);
2038 emit_sse_operand(dst, src);
2039}
2040
2041
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002042void Assembler::movntdqa(XMMRegister dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002043 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002044 EnsureSpace ensure_space(this);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002045 EMIT(0x66);
2046 EMIT(0x0F);
2047 EMIT(0x38);
2048 EMIT(0x2A);
2049 emit_sse_operand(dst, src);
2050}
2051
2052
2053void Assembler::movntdq(const Operand& dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002054 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002055 EnsureSpace ensure_space(this);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002056 EMIT(0x66);
2057 EMIT(0x0F);
2058 EMIT(0xE7);
2059 emit_sse_operand(src, dst);
2060}
2061
2062
2063void Assembler::prefetch(const Operand& src, int level) {
2064 ASSERT(is_uint2(level));
2065 EnsureSpace ensure_space(this);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002066 EMIT(0x0F);
2067 EMIT(0x18);
2068 XMMRegister code = { level }; // Emit hint number in Reg position of RegR/M.
2069 emit_sse_operand(code, src);
2070}
2071
2072
Steve Blocka7e24c12009-10-30 11:49:00 +00002073void Assembler::movdbl(XMMRegister dst, const Operand& src) {
2074 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002075 movsd(dst, src);
2076}
2077
2078
2079void Assembler::movdbl(const Operand& dst, XMMRegister src) {
2080 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002081 movsd(dst, src);
2082}
2083
2084
2085void Assembler::movsd(const Operand& dst, XMMRegister src ) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002086 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002087 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002088 EMIT(0xF2); // double
2089 EMIT(0x0F);
2090 EMIT(0x11); // store
2091 emit_sse_operand(src, dst);
2092}
2093
2094
2095void Assembler::movsd(XMMRegister dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002096 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002097 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002098 EMIT(0xF2); // double
2099 EMIT(0x0F);
2100 EMIT(0x10); // load
2101 emit_sse_operand(dst, src);
2102}
2103
Ben Murdochb0fe1622011-05-05 13:52:32 +01002104
Steve Block6ded16b2010-05-10 14:33:55 +01002105void Assembler::movsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002106 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block6ded16b2010-05-10 14:33:55 +01002107 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002108 EMIT(0xF2);
2109 EMIT(0x0F);
2110 EMIT(0x10);
2111 emit_sse_operand(dst, src);
2112}
2113
2114
Steve Block44f0eee2011-05-26 01:26:41 +01002115void Assembler::movss(const Operand& dst, XMMRegister src ) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002116 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block44f0eee2011-05-26 01:26:41 +01002117 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +01002118 EMIT(0xF3); // float
2119 EMIT(0x0F);
2120 EMIT(0x11); // store
2121 emit_sse_operand(src, dst);
2122}
2123
2124
2125void Assembler::movss(XMMRegister dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002126 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block44f0eee2011-05-26 01:26:41 +01002127 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +01002128 EMIT(0xF3); // float
2129 EMIT(0x0F);
2130 EMIT(0x10); // load
2131 emit_sse_operand(dst, src);
2132}
2133
2134
2135void Assembler::movss(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002136 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block44f0eee2011-05-26 01:26:41 +01002137 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +01002138 EMIT(0xF3);
2139 EMIT(0x0F);
2140 EMIT(0x10);
2141 emit_sse_operand(dst, src);
2142}
2143
2144
Steve Block6ded16b2010-05-10 14:33:55 +01002145void Assembler::movd(XMMRegister dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002146 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block6ded16b2010-05-10 14:33:55 +01002147 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002148 EMIT(0x66);
2149 EMIT(0x0F);
2150 EMIT(0x6E);
2151 emit_sse_operand(dst, src);
2152}
2153
2154
Ben Murdochb0fe1622011-05-05 13:52:32 +01002155void Assembler::movd(const Operand& dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002156 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002157 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002158 EMIT(0x66);
2159 EMIT(0x0F);
2160 EMIT(0x7E);
2161 emit_sse_operand(src, dst);
2162}
2163
2164
2165void Assembler::pand(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002166 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002167 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002168 EMIT(0x66);
2169 EMIT(0x0F);
2170 EMIT(0xDB);
2171 emit_sse_operand(dst, src);
2172}
2173
2174
Steve Block6ded16b2010-05-10 14:33:55 +01002175void Assembler::pxor(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002176 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block6ded16b2010-05-10 14:33:55 +01002177 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002178 EMIT(0x66);
2179 EMIT(0x0F);
2180 EMIT(0xEF);
2181 emit_sse_operand(dst, src);
2182}
2183
2184
Ben Murdochb8e0da22011-05-16 14:20:40 +01002185void Assembler::por(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002186 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdochb8e0da22011-05-16 14:20:40 +01002187 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002188 EMIT(0x66);
2189 EMIT(0x0F);
2190 EMIT(0xEB);
2191 emit_sse_operand(dst, src);
2192}
2193
2194
Steve Block6ded16b2010-05-10 14:33:55 +01002195void Assembler::ptest(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002196 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
Steve Block6ded16b2010-05-10 14:33:55 +01002197 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002198 EMIT(0x66);
2199 EMIT(0x0F);
2200 EMIT(0x38);
2201 EMIT(0x17);
2202 emit_sse_operand(dst, src);
2203}
2204
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002205
Ben Murdochb0fe1622011-05-05 13:52:32 +01002206void Assembler::psllq(XMMRegister reg, int8_t shift) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002207 ASSERT(CpuFeatures::IsEnabled(SSE2));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002208 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002209 EMIT(0x66);
2210 EMIT(0x0F);
2211 EMIT(0x73);
2212 emit_sse_operand(esi, reg); // esi == 6
Ben Murdochb0fe1622011-05-05 13:52:32 +01002213 EMIT(shift);
2214}
2215
2216
Ben Murdochb8e0da22011-05-16 14:20:40 +01002217void Assembler::psllq(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002218 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdochb8e0da22011-05-16 14:20:40 +01002219 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002220 EMIT(0x66);
2221 EMIT(0x0F);
2222 EMIT(0xF3);
2223 emit_sse_operand(dst, src);
2224}
2225
2226
2227void Assembler::psrlq(XMMRegister reg, int8_t shift) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002228 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdochb8e0da22011-05-16 14:20:40 +01002229 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002230 EMIT(0x66);
2231 EMIT(0x0F);
2232 EMIT(0x73);
2233 emit_sse_operand(edx, reg); // edx == 2
2234 EMIT(shift);
2235}
2236
2237
2238void Assembler::psrlq(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002239 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdochb8e0da22011-05-16 14:20:40 +01002240 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002241 EMIT(0x66);
2242 EMIT(0x0F);
2243 EMIT(0xD3);
2244 emit_sse_operand(dst, src);
2245}
2246
2247
Ben Murdochb0fe1622011-05-05 13:52:32 +01002248void Assembler::pshufd(XMMRegister dst, XMMRegister src, int8_t shuffle) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002249 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002250 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002251 EMIT(0x66);
2252 EMIT(0x0F);
2253 EMIT(0x70);
2254 emit_sse_operand(dst, src);
2255 EMIT(shuffle);
2256}
2257
2258
2259void Assembler::pextrd(const Operand& dst, XMMRegister src, int8_t offset) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002260 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002261 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002262 EMIT(0x66);
2263 EMIT(0x0F);
2264 EMIT(0x3A);
2265 EMIT(0x16);
2266 emit_sse_operand(src, dst);
2267 EMIT(offset);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002268}
2269
2270
Steve Block1e0659c2011-05-24 12:43:12 +01002271void Assembler::pinsrd(XMMRegister dst, const Operand& src, int8_t offset) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002272 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
Steve Block1e0659c2011-05-24 12:43:12 +01002273 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002274 EMIT(0x66);
2275 EMIT(0x0F);
2276 EMIT(0x3A);
2277 EMIT(0x22);
2278 emit_sse_operand(dst, src);
2279 EMIT(offset);
2280}
2281
2282
Steve Blocka7e24c12009-10-30 11:49:00 +00002283void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
2284 Register ireg = { reg.code() };
2285 emit_operand(ireg, adr);
2286}
2287
2288
2289void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
2290 EMIT(0xC0 | dst.code() << 3 | src.code());
2291}
2292
2293
Steve Block6ded16b2010-05-10 14:33:55 +01002294void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
2295 EMIT(0xC0 | dst.code() << 3 | src.code());
2296}
2297
2298
Steve Blocka7e24c12009-10-30 11:49:00 +00002299void Assembler::Print() {
2300 Disassembler::Decode(stdout, buffer_, pc_);
2301}
2302
2303
2304void Assembler::RecordJSReturn() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002305 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00002306 EnsureSpace ensure_space(this);
2307 RecordRelocInfo(RelocInfo::JS_RETURN);
2308}
2309
2310
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002311void Assembler::RecordDebugBreakSlot() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002312 positions_recorder()->WriteRecordedPositions();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002313 EnsureSpace ensure_space(this);
2314 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
2315}
2316
2317
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002318void Assembler::RecordComment(const char* msg, bool force) {
2319 if (FLAG_code_comments || force) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002320 EnsureSpace ensure_space(this);
2321 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
2322 }
2323}
2324
2325
Steve Blocka7e24c12009-10-30 11:49:00 +00002326void Assembler::GrowBuffer() {
Andrei Popescu31002712010-02-23 13:46:05 +00002327 ASSERT(overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +00002328 if (!own_buffer_) FATAL("external code buffer is too small");
2329
Andrei Popescu31002712010-02-23 13:46:05 +00002330 // Compute new buffer size.
Steve Blocka7e24c12009-10-30 11:49:00 +00002331 CodeDesc desc; // the new buffer
2332 if (buffer_size_ < 4*KB) {
2333 desc.buffer_size = 4*KB;
2334 } else {
2335 desc.buffer_size = 2*buffer_size_;
2336 }
2337 // Some internal data structures overflow for very large buffers,
2338 // they must ensure that kMaximalBufferSize is not too large.
2339 if ((desc.buffer_size > kMaximalBufferSize) ||
Steve Block44f0eee2011-05-26 01:26:41 +01002340 (desc.buffer_size > isolate()->heap()->MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002341 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
2342 }
2343
Ben Murdoch85b71792012-04-11 18:30:58 +01002344 // Setup new buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +00002345 desc.buffer = NewArray<byte>(desc.buffer_size);
2346 desc.instr_size = pc_offset();
2347 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
2348
2349 // Clear the buffer in debug mode. Use 'int3' instructions to make
2350 // sure to get into problems if we ever run uninitialized code.
2351#ifdef DEBUG
2352 memset(desc.buffer, 0xCC, desc.buffer_size);
2353#endif
2354
Andrei Popescu31002712010-02-23 13:46:05 +00002355 // Copy the data.
Steve Blocka7e24c12009-10-30 11:49:00 +00002356 int pc_delta = desc.buffer - buffer_;
2357 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
2358 memmove(desc.buffer, buffer_, desc.instr_size);
2359 memmove(rc_delta + reloc_info_writer.pos(),
2360 reloc_info_writer.pos(), desc.reloc_size);
2361
Andrei Popescu31002712010-02-23 13:46:05 +00002362 // Switch buffers.
Steve Block44f0eee2011-05-26 01:26:41 +01002363 if (isolate()->assembler_spare_buffer() == NULL &&
2364 buffer_size_ == kMinimalBufferSize) {
2365 isolate()->set_assembler_spare_buffer(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +00002366 } else {
2367 DeleteArray(buffer_);
2368 }
2369 buffer_ = desc.buffer;
2370 buffer_size_ = desc.buffer_size;
2371 pc_ += pc_delta;
Steve Blocka7e24c12009-10-30 11:49:00 +00002372 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2373 reloc_info_writer.last_pc() + pc_delta);
2374
Andrei Popescu31002712010-02-23 13:46:05 +00002375 // Relocate runtime entries.
Steve Blocka7e24c12009-10-30 11:49:00 +00002376 for (RelocIterator it(desc); !it.done(); it.next()) {
2377 RelocInfo::Mode rmode = it.rinfo()->rmode();
2378 if (rmode == RelocInfo::RUNTIME_ENTRY) {
2379 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2380 *p -= pc_delta; // relocate entry
2381 } else if (rmode == RelocInfo::INTERNAL_REFERENCE) {
2382 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2383 if (*p != 0) { // 0 means uninitialized.
2384 *p += pc_delta;
2385 }
2386 }
2387 }
2388
2389 ASSERT(!overflow());
2390}
2391
2392
2393void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
2394 ASSERT(is_uint8(op1) && is_uint8(op2)); // wrong opcode
2395 ASSERT(is_uint8(imm8));
2396 ASSERT((op1 & 0x01) == 0); // should be 8bit operation
2397 EMIT(op1);
2398 EMIT(op2 | dst.code());
2399 EMIT(imm8);
2400}
2401
2402
2403void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
2404 ASSERT((0 <= sel) && (sel <= 7));
2405 Register ireg = { sel };
2406 if (x.is_int8()) {
2407 EMIT(0x83); // using a sign-extended 8-bit immediate.
2408 emit_operand(ireg, dst);
2409 EMIT(x.x_ & 0xFF);
2410 } else if (dst.is_reg(eax)) {
2411 EMIT((sel << 3) | 0x05); // short form if the destination is eax.
2412 emit(x);
2413 } else {
2414 EMIT(0x81); // using a literal 32-bit immediate.
2415 emit_operand(ireg, dst);
2416 emit(x);
2417 }
2418}
2419
2420
2421void Assembler::emit_operand(Register reg, const Operand& adr) {
2422 const unsigned length = adr.len_;
2423 ASSERT(length > 0);
2424
2425 // Emit updated ModRM byte containing the given register.
2426 pc_[0] = (adr.buf_[0] & ~0x38) | (reg.code() << 3);
2427
2428 // Emit the rest of the encoded operand.
2429 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
2430 pc_ += length;
2431
2432 // Emit relocation information if necessary.
2433 if (length >= sizeof(int32_t) && adr.rmode_ != RelocInfo::NONE) {
2434 pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
2435 RecordRelocInfo(adr.rmode_);
2436 pc_ += sizeof(int32_t);
2437 }
2438}
2439
2440
2441void Assembler::emit_farith(int b1, int b2, int i) {
2442 ASSERT(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2443 ASSERT(0 <= i && i < 8); // illegal stack offset
2444 EMIT(b1);
2445 EMIT(b2 + i);
2446}
2447
2448
Ben Murdochb0fe1622011-05-05 13:52:32 +01002449void Assembler::db(uint8_t data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002450 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002451 EMIT(data);
2452}
2453
2454
2455void Assembler::dd(uint32_t data) {
2456 EnsureSpace ensure_space(this);
2457 emit(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00002458}
2459
2460
2461void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2462 ASSERT(rmode != RelocInfo::NONE);
2463 // Don't record external references unless the heap will be serialized.
Steve Blockd0582a62009-12-15 09:54:21 +00002464 if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
2465#ifdef DEBUG
2466 if (!Serializer::enabled()) {
2467 Serializer::TooLateToEnableNow();
2468 }
2469#endif
Steve Block44f0eee2011-05-26 01:26:41 +01002470 if (!Serializer::enabled() && !emit_debug_code()) {
Steve Blockd0582a62009-12-15 09:54:21 +00002471 return;
2472 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002473 }
Ben Murdoch85b71792012-04-11 18:30:58 +01002474 RelocInfo rinfo(pc_, rmode, data);
Steve Blocka7e24c12009-10-30 11:49:00 +00002475 reloc_info_writer.Write(&rinfo);
2476}
2477
2478
2479#ifdef GENERATED_CODE_COVERAGE
2480static FILE* coverage_log = NULL;
2481
2482
2483static void InitCoverageLog() {
2484 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
2485 if (file_name != NULL) {
2486 coverage_log = fopen(file_name, "aw+");
2487 }
2488}
2489
2490
2491void LogGeneratedCodeCoverage(const char* file_line) {
2492 const char* return_address = (&file_line)[-1];
2493 char* push_insn = const_cast<char*>(return_address - 12);
2494 push_insn[0] = 0xeb; // Relative branch insn.
2495 push_insn[1] = 13; // Skip over coverage insns.
2496 if (coverage_log != NULL) {
2497 fprintf(coverage_log, "%s\n", file_line);
2498 fflush(coverage_log);
2499 }
2500}
2501
2502#endif
2503
2504} } // namespace v8::internal
Leon Clarkef7060e22010-06-03 12:02:55 +01002505
2506#endif // V8_TARGET_ARCH_IA32