blob: a42f6324e34abe4058d7ab9cc24a3faafb4f0f77 [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 Murdoch3ef787d2012-04-12 10:51:47 +010035// Copyright 2012 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 Murdoch3ef787d2012-04-12 10:51:47 +010058// The Probe method needs executable memory, so it uses Heap::CreateCode.
59// Allocation failure is silent and leads to safe default.
Ben Murdoch8b112d22011-06-08 16:22:53 +010060void CpuFeatures::Probe() {
61 ASSERT(!initialized_);
Steve Blocka7e24c12009-10-30 11:49:00 +000062 ASSERT(supported_ == 0);
Ben Murdoch8b112d22011-06-08 16:22:53 +010063#ifdef DEBUG
64 initialized_ = true;
65#endif
66 if (Serializer::enabled()) {
Steve Blockd0582a62009-12-15 09:54:21 +000067 supported_ |= OS::CpuFeaturesImpliedByPlatform();
68 return; // No features if we might serialize.
69 }
Steve Blocka7e24c12009-10-30 11:49:00 +000070
Ben Murdoch8b112d22011-06-08 16:22:53 +010071 const int kBufferSize = 4 * KB;
72 VirtualMemory* memory = new VirtualMemory(kBufferSize);
73 if (!memory->IsReserved()) {
74 delete memory;
75 return;
76 }
77 ASSERT(memory->size() >= static_cast<size_t>(kBufferSize));
78 if (!memory->Commit(memory->address(), kBufferSize, true/*executable*/)) {
79 delete memory;
80 return;
81 }
82
83 Assembler assm(NULL, memory->address(), kBufferSize);
Steve Blocka7e24c12009-10-30 11:49:00 +000084 Label cpuid, done;
85#define __ assm.
86 // Save old esp, since we are going to modify the stack.
87 __ push(ebp);
88 __ pushfd();
89 __ push(ecx);
90 __ push(ebx);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010091 __ mov(ebp, esp);
Steve Blocka7e24c12009-10-30 11:49:00 +000092
93 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
94 __ pushfd();
95 __ pop(eax);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010096 __ mov(edx, eax);
Steve Blocka7e24c12009-10-30 11:49:00 +000097 __ xor_(eax, 0x200000); // Flip bit 21.
98 __ push(eax);
99 __ popfd();
100 __ pushfd();
101 __ pop(eax);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100102 __ xor_(eax, edx); // Different if CPUID is supported.
Steve Blocka7e24c12009-10-30 11:49:00 +0000103 __ j(not_zero, &cpuid);
104
105 // CPUID not supported. Clear the supported features in edx:eax.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100106 __ xor_(eax, eax);
107 __ xor_(edx, edx);
Steve Blocka7e24c12009-10-30 11:49:00 +0000108 __ jmp(&done);
109
110 // Invoke CPUID with 1 in eax to get feature information in
111 // ecx:edx. Temporarily enable CPUID support because we know it's
112 // safe here.
113 __ bind(&cpuid);
114 __ mov(eax, 1);
115 supported_ = (1 << CPUID);
116 { Scope fscope(CPUID);
117 __ cpuid();
118 }
119 supported_ = 0;
120
121 // Move the result from ecx:edx to edx:eax and make sure to mark the
122 // CPUID feature as supported.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100123 __ mov(eax, edx);
Steve Blocka7e24c12009-10-30 11:49:00 +0000124 __ or_(eax, 1 << CPUID);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100125 __ mov(edx, ecx);
Steve Blocka7e24c12009-10-30 11:49:00 +0000126
127 // Done.
128 __ bind(&done);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100129 __ mov(esp, ebp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000130 __ pop(ebx);
131 __ pop(ecx);
132 __ popfd();
133 __ pop(ebp);
134 __ ret(0);
135#undef __
136
Steve Blocka7e24c12009-10-30 11:49:00 +0000137 typedef uint64_t (*F0)();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100138 F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000139 supported_ = probe();
Steve Blockd0582a62009-12-15 09:54:21 +0000140 found_by_runtime_probing_ = supported_;
141 uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform();
142 supported_ |= os_guarantees;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100143 found_by_runtime_probing_ &= ~os_guarantees;
144
145 delete memory;
Steve Blocka7e24c12009-10-30 11:49:00 +0000146}
147
148
149// -----------------------------------------------------------------------------
150// Implementation of Displacement
151
152void Displacement::init(Label* L, Type type) {
153 ASSERT(!L->is_bound());
154 int next = 0;
155 if (L->is_linked()) {
156 next = L->pos();
157 ASSERT(next > 0); // Displacements must be at positions > 0
158 }
159 // Ensure that we _never_ overflow the next field.
160 ASSERT(NextField::is_valid(Assembler::kMaximalBufferSize));
161 data_ = NextField::encode(next) | TypeField::encode(type);
162}
163
164
165// -----------------------------------------------------------------------------
166// Implementation of RelocInfo
167
168
169const int RelocInfo::kApplyMask =
170 RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
Ben Murdochbb769b22010-08-11 14:56:33 +0100171 1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE |
172 1 << RelocInfo::DEBUG_BREAK_SLOT;
Steve Blocka7e24c12009-10-30 11:49:00 +0000173
174
Leon Clarkef7060e22010-06-03 12:02:55 +0100175bool RelocInfo::IsCodedSpecially() {
176 // The deserializer needs to know whether a pointer is specially coded. Being
177 // specially coded on IA32 means that it is a relative address, as used by
178 // branch instructions. These are also the ones that need changing when a
179 // code object moves.
180 return (1 << rmode_) & kApplyMask;
181}
182
183
Steve Blocka7e24c12009-10-30 11:49:00 +0000184void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
185 // Patch the code at the current address with the supplied instructions.
186 for (int i = 0; i < instruction_count; i++) {
187 *(pc_ + i) = *(instructions + i);
188 }
189
190 // Indicate that code has changed.
191 CPU::FlushICache(pc_, instruction_count);
192}
193
194
195// Patch the code at the current PC with a call to the target address.
196// Additional guard int3 instructions can be added if required.
197void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
198 // Call instruction takes up 5 bytes and int3 takes up one byte.
199 static const int kCallCodeSize = 5;
200 int code_size = kCallCodeSize + guard_bytes;
201
202 // Create a code patcher.
203 CodePatcher patcher(pc_, code_size);
204
205 // Add a label for checking the size of the code used for returning.
206#ifdef DEBUG
207 Label check_codesize;
208 patcher.masm()->bind(&check_codesize);
209#endif
210
211 // Patch the code.
212 patcher.masm()->call(target, RelocInfo::NONE);
213
214 // Check that the size of the code generated is as expected.
215 ASSERT_EQ(kCallCodeSize,
216 patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
217
218 // Add the requested number of int3 instructions after the call.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100219 ASSERT_GE(guard_bytes, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000220 for (int i = 0; i < guard_bytes; i++) {
221 patcher.masm()->int3();
222 }
223}
224
225
226// -----------------------------------------------------------------------------
227// Implementation of Operand
228
229Operand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) {
230 // [base + disp/r]
231 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
232 // [base]
233 set_modrm(0, base);
234 if (base.is(esp)) set_sib(times_1, esp, base);
235 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
236 // [base + disp8]
237 set_modrm(1, base);
238 if (base.is(esp)) set_sib(times_1, esp, base);
239 set_disp8(disp);
240 } else {
241 // [base + disp/r]
242 set_modrm(2, base);
243 if (base.is(esp)) set_sib(times_1, esp, base);
244 set_dispr(disp, rmode);
245 }
246}
247
248
249Operand::Operand(Register base,
250 Register index,
251 ScaleFactor scale,
252 int32_t disp,
253 RelocInfo::Mode rmode) {
254 ASSERT(!index.is(esp)); // illegal addressing mode
255 // [base + index*scale + disp/r]
256 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
257 // [base + index*scale]
258 set_modrm(0, esp);
259 set_sib(scale, index, base);
260 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
261 // [base + index*scale + disp8]
262 set_modrm(1, esp);
263 set_sib(scale, index, base);
264 set_disp8(disp);
265 } else {
266 // [base + index*scale + disp/r]
267 set_modrm(2, esp);
268 set_sib(scale, index, base);
269 set_dispr(disp, rmode);
270 }
271}
272
273
274Operand::Operand(Register index,
275 ScaleFactor scale,
276 int32_t disp,
277 RelocInfo::Mode rmode) {
278 ASSERT(!index.is(esp)); // illegal addressing mode
279 // [index*scale + disp/r]
280 set_modrm(0, esp);
281 set_sib(scale, index, ebp);
282 set_dispr(disp, rmode);
283}
284
285
286bool Operand::is_reg(Register reg) const {
287 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only.
288 && ((buf_[0] & 0x07) == reg.code()); // register codes match.
289}
290
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100291
292bool Operand::is_reg_only() const {
293 return (buf_[0] & 0xF8) == 0xC0; // Addressing mode is register only.
294}
295
296
297Register Operand::reg() const {
298 ASSERT(is_reg_only());
299 return Register::from_code(buf_[0] & 0x07);
300}
301
302
Steve Blocka7e24c12009-10-30 11:49:00 +0000303// -----------------------------------------------------------------------------
Andrei Popescu31002712010-02-23 13:46:05 +0000304// Implementation of Assembler.
Steve Blocka7e24c12009-10-30 11:49:00 +0000305
306// Emit a single byte. Must always be inlined.
307#define EMIT(x) \
308 *pc_++ = (x)
309
310
311#ifdef GENERATED_CODE_COVERAGE
312static void InitCoverageLog();
313#endif
314
Ben Murdoch8b112d22011-06-08 16:22:53 +0100315Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size)
316 : AssemblerBase(arg_isolate),
Steve Block44f0eee2011-05-26 01:26:41 +0100317 positions_recorder_(this),
318 emit_debug_code_(FLAG_debug_code) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000319 if (buffer == NULL) {
Andrei Popescu31002712010-02-23 13:46:05 +0000320 // Do our own buffer management.
Steve Blocka7e24c12009-10-30 11:49:00 +0000321 if (buffer_size <= kMinimalBufferSize) {
322 buffer_size = kMinimalBufferSize;
323
Steve Block44f0eee2011-05-26 01:26:41 +0100324 if (isolate()->assembler_spare_buffer() != NULL) {
325 buffer = isolate()->assembler_spare_buffer();
326 isolate()->set_assembler_spare_buffer(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000327 }
328 }
329 if (buffer == NULL) {
330 buffer_ = NewArray<byte>(buffer_size);
331 } else {
332 buffer_ = static_cast<byte*>(buffer);
333 }
334 buffer_size_ = buffer_size;
335 own_buffer_ = true;
336 } else {
Andrei Popescu31002712010-02-23 13:46:05 +0000337 // Use externally provided buffer instead.
Steve Blocka7e24c12009-10-30 11:49:00 +0000338 ASSERT(buffer_size > 0);
339 buffer_ = static_cast<byte*>(buffer);
340 buffer_size_ = buffer_size;
341 own_buffer_ = false;
342 }
343
344 // Clear the buffer in debug mode unless it was provided by the
345 // caller in which case we can't be sure it's okay to overwrite
346 // existing code in it; see CodePatcher::CodePatcher(...).
347#ifdef DEBUG
348 if (own_buffer_) {
349 memset(buffer_, 0xCC, buffer_size); // int3
350 }
351#endif
352
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100353 // Set up buffer pointers.
Steve Blocka7e24c12009-10-30 11:49:00 +0000354 ASSERT(buffer_ != NULL);
355 pc_ = buffer_;
356 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
357
Steve Blocka7e24c12009-10-30 11:49:00 +0000358#ifdef GENERATED_CODE_COVERAGE
359 InitCoverageLog();
360#endif
361}
362
363
364Assembler::~Assembler() {
365 if (own_buffer_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100366 if (isolate()->assembler_spare_buffer() == NULL &&
367 buffer_size_ == kMinimalBufferSize) {
368 isolate()->set_assembler_spare_buffer(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000369 } else {
370 DeleteArray(buffer_);
371 }
372 }
373}
374
375
376void Assembler::GetCode(CodeDesc* desc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000377 // Finalize code (at this point overflow() may be true, but the gap ensures
378 // that we are still not overlapping instructions and relocation info).
379 ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100380 // Set up code descriptor.
Steve Blocka7e24c12009-10-30 11:49:00 +0000381 desc->buffer = buffer_;
382 desc->buffer_size = buffer_size_;
383 desc->instr_size = pc_offset();
384 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
385 desc->origin = this;
Steve Blocka7e24c12009-10-30 11:49:00 +0000386}
387
388
389void Assembler::Align(int m) {
390 ASSERT(IsPowerOf2(m));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100391 int mask = m - 1;
392 int addr = pc_offset();
393 Nop((m - (addr & mask)) & mask);
394}
395
396
397bool Assembler::IsNop(Address addr) {
398 Address a = addr;
399 while (*a == 0x66) a++;
400 if (*a == 0x90) return true;
401 if (a[0] == 0xf && a[1] == 0x1f) return true;
402 return false;
403}
404
405
406void Assembler::Nop(int bytes) {
407 EnsureSpace ensure_space(this);
408
409 if (!CpuFeatures::IsSupported(SSE2)) {
410 // Older CPUs that do not support SSE2 may not support multibyte NOP
411 // instructions.
412 for (; bytes > 0; bytes--) {
413 EMIT(0x90);
414 }
415 return;
416 }
417
418 // Multi byte nops from http://support.amd.com/us/Processor_TechDocs/40546.pdf
419 while (bytes > 0) {
420 switch (bytes) {
421 case 2:
422 EMIT(0x66);
423 case 1:
424 EMIT(0x90);
425 return;
426 case 3:
427 EMIT(0xf);
428 EMIT(0x1f);
429 EMIT(0);
430 return;
431 case 4:
432 EMIT(0xf);
433 EMIT(0x1f);
434 EMIT(0x40);
435 EMIT(0);
436 return;
437 case 6:
438 EMIT(0x66);
439 case 5:
440 EMIT(0xf);
441 EMIT(0x1f);
442 EMIT(0x44);
443 EMIT(0);
444 EMIT(0);
445 return;
446 case 7:
447 EMIT(0xf);
448 EMIT(0x1f);
449 EMIT(0x80);
450 EMIT(0);
451 EMIT(0);
452 EMIT(0);
453 EMIT(0);
454 return;
455 default:
456 case 11:
457 EMIT(0x66);
458 bytes--;
459 case 10:
460 EMIT(0x66);
461 bytes--;
462 case 9:
463 EMIT(0x66);
464 bytes--;
465 case 8:
466 EMIT(0xf);
467 EMIT(0x1f);
468 EMIT(0x84);
469 EMIT(0);
470 EMIT(0);
471 EMIT(0);
472 EMIT(0);
473 EMIT(0);
474 bytes -= 8;
475 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000476 }
477}
478
479
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100480void Assembler::CodeTargetAlign() {
481 Align(16); // Preferred alignment of jump targets on ia32.
482}
483
484
Steve Blocka7e24c12009-10-30 11:49:00 +0000485void Assembler::cpuid() {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100486 ASSERT(CpuFeatures::IsEnabled(CPUID));
Steve Blocka7e24c12009-10-30 11:49:00 +0000487 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000488 EMIT(0x0F);
489 EMIT(0xA2);
490}
491
492
493void Assembler::pushad() {
494 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000495 EMIT(0x60);
496}
497
498
499void Assembler::popad() {
500 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000501 EMIT(0x61);
502}
503
504
505void Assembler::pushfd() {
506 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000507 EMIT(0x9C);
508}
509
510
511void Assembler::popfd() {
512 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000513 EMIT(0x9D);
514}
515
516
517void Assembler::push(const Immediate& x) {
518 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000519 if (x.is_int8()) {
520 EMIT(0x6a);
521 EMIT(x.x_);
522 } else {
523 EMIT(0x68);
524 emit(x);
525 }
526}
527
528
Ben Murdochb0fe1622011-05-05 13:52:32 +0100529void Assembler::push_imm32(int32_t imm32) {
530 EnsureSpace ensure_space(this);
531 EMIT(0x68);
532 emit(imm32);
533}
534
535
Steve Blocka7e24c12009-10-30 11:49:00 +0000536void Assembler::push(Register src) {
537 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000538 EMIT(0x50 | src.code());
539}
540
541
542void Assembler::push(const Operand& src) {
543 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000544 EMIT(0xFF);
545 emit_operand(esi, src);
546}
547
548
549void Assembler::pop(Register dst) {
550 ASSERT(reloc_info_writer.last_pc() != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000551 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000552 EMIT(0x58 | dst.code());
553}
554
555
556void Assembler::pop(const Operand& dst) {
557 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000558 EMIT(0x8F);
559 emit_operand(eax, dst);
560}
561
562
563void Assembler::enter(const Immediate& size) {
564 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000565 EMIT(0xC8);
566 emit_w(size);
567 EMIT(0);
568}
569
570
571void Assembler::leave() {
572 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000573 EMIT(0xC9);
574}
575
576
577void Assembler::mov_b(Register dst, const Operand& src) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100578 CHECK(dst.is_byte_register());
Steve Blocka7e24c12009-10-30 11:49:00 +0000579 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000580 EMIT(0x8A);
581 emit_operand(dst, src);
582}
583
584
585void Assembler::mov_b(const Operand& dst, int8_t imm8) {
586 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000587 EMIT(0xC6);
588 emit_operand(eax, dst);
589 EMIT(imm8);
590}
591
592
593void Assembler::mov_b(const Operand& dst, Register src) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100594 CHECK(src.is_byte_register());
Steve Blocka7e24c12009-10-30 11:49:00 +0000595 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000596 EMIT(0x88);
597 emit_operand(src, dst);
598}
599
600
601void Assembler::mov_w(Register dst, const Operand& src) {
602 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000603 EMIT(0x66);
604 EMIT(0x8B);
605 emit_operand(dst, src);
606}
607
608
609void Assembler::mov_w(const Operand& dst, Register src) {
610 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000611 EMIT(0x66);
612 EMIT(0x89);
613 emit_operand(src, dst);
614}
615
616
617void Assembler::mov(Register dst, int32_t imm32) {
618 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000619 EMIT(0xB8 | dst.code());
620 emit(imm32);
621}
622
623
624void Assembler::mov(Register dst, const Immediate& x) {
625 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000626 EMIT(0xB8 | dst.code());
627 emit(x);
628}
629
630
631void Assembler::mov(Register dst, Handle<Object> handle) {
632 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000633 EMIT(0xB8 | dst.code());
634 emit(handle);
635}
636
637
638void Assembler::mov(Register dst, const Operand& src) {
639 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000640 EMIT(0x8B);
641 emit_operand(dst, src);
642}
643
644
645void Assembler::mov(Register dst, Register src) {
646 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000647 EMIT(0x89);
648 EMIT(0xC0 | src.code() << 3 | dst.code());
649}
650
651
652void Assembler::mov(const Operand& dst, const Immediate& x) {
653 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000654 EMIT(0xC7);
655 emit_operand(eax, dst);
656 emit(x);
657}
658
659
660void Assembler::mov(const Operand& dst, Handle<Object> handle) {
661 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000662 EMIT(0xC7);
663 emit_operand(eax, dst);
664 emit(handle);
665}
666
667
668void Assembler::mov(const Operand& dst, Register src) {
669 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000670 EMIT(0x89);
671 emit_operand(src, dst);
672}
673
674
675void Assembler::movsx_b(Register dst, const Operand& src) {
676 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000677 EMIT(0x0F);
678 EMIT(0xBE);
679 emit_operand(dst, src);
680}
681
682
683void Assembler::movsx_w(Register dst, const Operand& src) {
684 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000685 EMIT(0x0F);
686 EMIT(0xBF);
687 emit_operand(dst, src);
688}
689
690
691void Assembler::movzx_b(Register dst, const Operand& src) {
692 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000693 EMIT(0x0F);
694 EMIT(0xB6);
695 emit_operand(dst, src);
696}
697
698
699void Assembler::movzx_w(Register dst, const Operand& src) {
700 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000701 EMIT(0x0F);
702 EMIT(0xB7);
703 emit_operand(dst, src);
704}
705
706
Steve Blocka7e24c12009-10-30 11:49:00 +0000707void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100708 ASSERT(CpuFeatures::IsEnabled(CMOV));
Steve Blocka7e24c12009-10-30 11:49:00 +0000709 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000710 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000711 EMIT(0x0F);
712 EMIT(0x40 + cc);
713 emit_operand(dst, src);
714}
715
716
Steve Block6ded16b2010-05-10 14:33:55 +0100717void Assembler::cld() {
718 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +0100719 EMIT(0xFC);
720}
721
722
Leon Clarkee46be812010-01-19 14:06:41 +0000723void Assembler::rep_movs() {
724 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +0000725 EMIT(0xF3);
726 EMIT(0xA5);
727}
728
729
Steve Block6ded16b2010-05-10 14:33:55 +0100730void Assembler::rep_stos() {
731 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +0100732 EMIT(0xF3);
733 EMIT(0xAB);
734}
735
736
Leon Clarkef7060e22010-06-03 12:02:55 +0100737void Assembler::stos() {
738 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +0100739 EMIT(0xAB);
740}
741
742
Steve Blocka7e24c12009-10-30 11:49:00 +0000743void Assembler::xchg(Register dst, Register src) {
744 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000745 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding.
Steve Blocka7e24c12009-10-30 11:49:00 +0000746 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code()));
747 } else {
748 EMIT(0x87);
749 EMIT(0xC0 | src.code() << 3 | dst.code());
750 }
751}
752
753
754void Assembler::adc(Register dst, int32_t imm32) {
755 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000756 emit_arith(2, Operand(dst), Immediate(imm32));
757}
758
759
760void Assembler::adc(Register dst, const Operand& src) {
761 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000762 EMIT(0x13);
763 emit_operand(dst, src);
764}
765
766
767void Assembler::add(Register dst, const Operand& src) {
768 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000769 EMIT(0x03);
770 emit_operand(dst, src);
771}
772
773
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100774void Assembler::add(const Operand& dst, Register src) {
775 EnsureSpace ensure_space(this);
776 EMIT(0x01);
777 emit_operand(src, dst);
778}
779
780
Steve Blocka7e24c12009-10-30 11:49:00 +0000781void Assembler::add(const Operand& dst, const Immediate& x) {
782 ASSERT(reloc_info_writer.last_pc() != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000783 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000784 emit_arith(0, dst, x);
785}
786
787
788void Assembler::and_(Register dst, int32_t imm32) {
Steve Block59151502010-09-22 15:07:15 +0100789 and_(dst, Immediate(imm32));
790}
791
792
793void Assembler::and_(Register dst, const Immediate& x) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000794 EnsureSpace ensure_space(this);
Steve Block59151502010-09-22 15:07:15 +0100795 emit_arith(4, Operand(dst), x);
Steve Blocka7e24c12009-10-30 11:49:00 +0000796}
797
798
799void Assembler::and_(Register dst, const Operand& src) {
800 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000801 EMIT(0x23);
802 emit_operand(dst, src);
803}
804
805
806void Assembler::and_(const Operand& dst, const Immediate& x) {
807 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000808 emit_arith(4, dst, x);
809}
810
811
812void Assembler::and_(const Operand& dst, Register src) {
813 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000814 EMIT(0x21);
815 emit_operand(src, dst);
816}
817
818
819void Assembler::cmpb(const Operand& op, int8_t imm8) {
820 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100821 if (op.is_reg(eax)) {
822 EMIT(0x3C);
823 } else {
824 EMIT(0x80);
825 emit_operand(edi, op); // edi == 7
826 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000827 EMIT(imm8);
828}
829
830
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100831void Assembler::cmpb(const Operand& op, Register reg) {
832 CHECK(reg.is_byte_register());
Leon Clarked91b9f72010-01-27 17:25:45 +0000833 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +0000834 EMIT(0x38);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100835 emit_operand(reg, op);
Leon Clarked91b9f72010-01-27 17:25:45 +0000836}
837
838
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100839void Assembler::cmpb(Register reg, const Operand& op) {
840 CHECK(reg.is_byte_register());
Leon Clarked91b9f72010-01-27 17:25:45 +0000841 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +0000842 EMIT(0x3A);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100843 emit_operand(reg, op);
Leon Clarked91b9f72010-01-27 17:25:45 +0000844}
845
846
Steve Blocka7e24c12009-10-30 11:49:00 +0000847void Assembler::cmpw(const Operand& op, Immediate imm16) {
848 ASSERT(imm16.is_int16());
849 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000850 EMIT(0x66);
851 EMIT(0x81);
852 emit_operand(edi, op);
853 emit_w(imm16);
854}
855
856
857void Assembler::cmp(Register reg, int32_t imm32) {
858 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000859 emit_arith(7, Operand(reg), Immediate(imm32));
860}
861
862
863void Assembler::cmp(Register reg, Handle<Object> handle) {
864 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000865 emit_arith(7, Operand(reg), Immediate(handle));
866}
867
868
869void Assembler::cmp(Register reg, const Operand& op) {
870 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000871 EMIT(0x3B);
872 emit_operand(reg, op);
873}
874
875
876void Assembler::cmp(const Operand& op, const Immediate& imm) {
877 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000878 emit_arith(7, op, imm);
879}
880
881
882void Assembler::cmp(const Operand& op, Handle<Object> handle) {
883 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000884 emit_arith(7, op, Immediate(handle));
885}
886
887
888void Assembler::cmpb_al(const Operand& op) {
889 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000890 EMIT(0x38); // CMP r/m8, r8
891 emit_operand(eax, op); // eax has same code as register al.
892}
893
894
895void Assembler::cmpw_ax(const Operand& op) {
896 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000897 EMIT(0x66);
898 EMIT(0x39); // CMP r/m16, r16
899 emit_operand(eax, op); // eax has same code as register ax.
900}
901
902
903void Assembler::dec_b(Register dst) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100904 CHECK(dst.is_byte_register());
Steve Blocka7e24c12009-10-30 11:49:00 +0000905 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000906 EMIT(0xFE);
907 EMIT(0xC8 | dst.code());
908}
909
910
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100911void Assembler::dec_b(const Operand& dst) {
912 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100913 EMIT(0xFE);
914 emit_operand(ecx, dst);
915}
916
917
Steve Blocka7e24c12009-10-30 11:49:00 +0000918void Assembler::dec(Register dst) {
919 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000920 EMIT(0x48 | dst.code());
921}
922
923
924void Assembler::dec(const Operand& dst) {
925 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000926 EMIT(0xFF);
927 emit_operand(ecx, dst);
928}
929
930
931void Assembler::cdq() {
932 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000933 EMIT(0x99);
934}
935
936
937void Assembler::idiv(Register src) {
938 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000939 EMIT(0xF7);
940 EMIT(0xF8 | src.code());
941}
942
943
944void Assembler::imul(Register reg) {
945 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000946 EMIT(0xF7);
947 EMIT(0xE8 | reg.code());
948}
949
950
951void Assembler::imul(Register dst, const Operand& src) {
952 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000953 EMIT(0x0F);
954 EMIT(0xAF);
955 emit_operand(dst, src);
956}
957
958
959void Assembler::imul(Register dst, Register src, int32_t imm32) {
960 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000961 if (is_int8(imm32)) {
962 EMIT(0x6B);
963 EMIT(0xC0 | dst.code() << 3 | src.code());
964 EMIT(imm32);
965 } else {
966 EMIT(0x69);
967 EMIT(0xC0 | dst.code() << 3 | src.code());
968 emit(imm32);
969 }
970}
971
972
973void Assembler::inc(Register dst) {
974 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000975 EMIT(0x40 | dst.code());
976}
977
978
979void Assembler::inc(const Operand& dst) {
980 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000981 EMIT(0xFF);
982 emit_operand(eax, dst);
983}
984
985
986void Assembler::lea(Register dst, const Operand& src) {
987 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000988 EMIT(0x8D);
989 emit_operand(dst, src);
990}
991
992
993void Assembler::mul(Register src) {
994 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000995 EMIT(0xF7);
996 EMIT(0xE0 | src.code());
997}
998
999
1000void Assembler::neg(Register dst) {
1001 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001002 EMIT(0xF7);
1003 EMIT(0xD8 | dst.code());
1004}
1005
1006
1007void Assembler::not_(Register dst) {
1008 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001009 EMIT(0xF7);
1010 EMIT(0xD0 | dst.code());
1011}
1012
1013
1014void Assembler::or_(Register dst, int32_t imm32) {
1015 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001016 emit_arith(1, Operand(dst), Immediate(imm32));
1017}
1018
1019
1020void Assembler::or_(Register dst, const Operand& src) {
1021 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001022 EMIT(0x0B);
1023 emit_operand(dst, src);
1024}
1025
1026
1027void Assembler::or_(const Operand& dst, const Immediate& x) {
1028 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001029 emit_arith(1, dst, x);
1030}
1031
1032
1033void Assembler::or_(const Operand& dst, Register src) {
1034 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001035 EMIT(0x09);
1036 emit_operand(src, dst);
1037}
1038
1039
1040void Assembler::rcl(Register dst, uint8_t imm8) {
1041 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001042 ASSERT(is_uint5(imm8)); // illegal shift count
1043 if (imm8 == 1) {
1044 EMIT(0xD1);
1045 EMIT(0xD0 | dst.code());
1046 } else {
1047 EMIT(0xC1);
1048 EMIT(0xD0 | dst.code());
1049 EMIT(imm8);
1050 }
1051}
1052
1053
Iain Merrick75681382010-08-19 15:07:18 +01001054void Assembler::rcr(Register dst, uint8_t imm8) {
1055 EnsureSpace ensure_space(this);
Iain Merrick75681382010-08-19 15:07:18 +01001056 ASSERT(is_uint5(imm8)); // illegal shift count
1057 if (imm8 == 1) {
1058 EMIT(0xD1);
1059 EMIT(0xD8 | dst.code());
1060 } else {
1061 EMIT(0xC1);
1062 EMIT(0xD8 | dst.code());
1063 EMIT(imm8);
1064 }
1065}
1066
1067
Steve Blocka7e24c12009-10-30 11:49:00 +00001068void Assembler::sar(Register dst, uint8_t imm8) {
1069 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001070 ASSERT(is_uint5(imm8)); // illegal shift count
1071 if (imm8 == 1) {
1072 EMIT(0xD1);
1073 EMIT(0xF8 | dst.code());
1074 } else {
1075 EMIT(0xC1);
1076 EMIT(0xF8 | dst.code());
1077 EMIT(imm8);
1078 }
1079}
1080
1081
Steve Blockd0582a62009-12-15 09:54:21 +00001082void Assembler::sar_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001083 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001084 EMIT(0xD3);
1085 EMIT(0xF8 | dst.code());
1086}
1087
1088
1089void Assembler::sbb(Register dst, const Operand& src) {
1090 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001091 EMIT(0x1B);
1092 emit_operand(dst, src);
1093}
1094
1095
1096void Assembler::shld(Register dst, const Operand& src) {
1097 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001098 EMIT(0x0F);
1099 EMIT(0xA5);
1100 emit_operand(dst, src);
1101}
1102
1103
1104void Assembler::shl(Register dst, uint8_t imm8) {
1105 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001106 ASSERT(is_uint5(imm8)); // illegal shift count
1107 if (imm8 == 1) {
1108 EMIT(0xD1);
1109 EMIT(0xE0 | dst.code());
1110 } else {
1111 EMIT(0xC1);
1112 EMIT(0xE0 | dst.code());
1113 EMIT(imm8);
1114 }
1115}
1116
1117
Steve Blockd0582a62009-12-15 09:54:21 +00001118void Assembler::shl_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001119 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001120 EMIT(0xD3);
1121 EMIT(0xE0 | dst.code());
1122}
1123
1124
1125void Assembler::shrd(Register dst, const Operand& src) {
1126 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001127 EMIT(0x0F);
1128 EMIT(0xAD);
1129 emit_operand(dst, src);
1130}
1131
1132
1133void Assembler::shr(Register dst, uint8_t imm8) {
1134 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001135 ASSERT(is_uint5(imm8)); // illegal shift count
Steve Blockd0582a62009-12-15 09:54:21 +00001136 if (imm8 == 1) {
1137 EMIT(0xD1);
1138 EMIT(0xE8 | dst.code());
1139 } else {
1140 EMIT(0xC1);
1141 EMIT(0xE8 | dst.code());
1142 EMIT(imm8);
1143 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001144}
1145
1146
1147void Assembler::shr_cl(Register dst) {
1148 EnsureSpace ensure_space(this);
Steve Blockd0582a62009-12-15 09:54:21 +00001149 EMIT(0xD3);
Steve Blocka7e24c12009-10-30 11:49:00 +00001150 EMIT(0xE8 | dst.code());
1151}
1152
1153
1154void Assembler::sub(const Operand& dst, const Immediate& x) {
1155 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001156 emit_arith(5, dst, x);
1157}
1158
1159
1160void Assembler::sub(Register dst, const Operand& src) {
1161 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001162 EMIT(0x2B);
1163 emit_operand(dst, src);
1164}
1165
1166
1167void Assembler::sub(const Operand& dst, Register src) {
1168 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001169 EMIT(0x29);
1170 emit_operand(src, dst);
1171}
1172
1173
1174void Assembler::test(Register reg, const Immediate& imm) {
1175 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001176 // Only use test against byte for registers that have a byte
1177 // variant: eax, ebx, ecx, and edx.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001178 if (imm.rmode_ == RelocInfo::NONE &&
1179 is_uint8(imm.x_) &&
1180 reg.is_byte_register()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001181 uint8_t imm8 = imm.x_;
1182 if (reg.is(eax)) {
1183 EMIT(0xA8);
1184 EMIT(imm8);
1185 } else {
1186 emit_arith_b(0xF6, 0xC0, reg, imm8);
1187 }
1188 } else {
1189 // This is not using emit_arith because test doesn't support
1190 // sign-extension of 8-bit operands.
1191 if (reg.is(eax)) {
1192 EMIT(0xA9);
1193 } else {
1194 EMIT(0xF7);
1195 EMIT(0xC0 | reg.code());
1196 }
1197 emit(imm);
1198 }
1199}
1200
1201
1202void Assembler::test(Register reg, const Operand& op) {
1203 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001204 EMIT(0x85);
1205 emit_operand(reg, op);
1206}
1207
1208
Leon Clarkee46be812010-01-19 14:06:41 +00001209void Assembler::test_b(Register reg, const Operand& op) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001210 CHECK(reg.is_byte_register());
Leon Clarkee46be812010-01-19 14:06:41 +00001211 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00001212 EMIT(0x84);
1213 emit_operand(reg, op);
1214}
1215
1216
Steve Blocka7e24c12009-10-30 11:49:00 +00001217void Assembler::test(const Operand& op, const Immediate& imm) {
1218 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001219 EMIT(0xF7);
1220 emit_operand(eax, op);
1221 emit(imm);
1222}
1223
1224
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001225void Assembler::test_b(const Operand& op, uint8_t imm8) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001226 if (op.is_reg_only() && !op.reg().is_byte_register()) {
1227 test(op, Immediate(imm8));
1228 return;
1229 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001230 EnsureSpace ensure_space(this);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001231 EMIT(0xF6);
1232 emit_operand(eax, op);
1233 EMIT(imm8);
1234}
1235
1236
Steve Blocka7e24c12009-10-30 11:49:00 +00001237void Assembler::xor_(Register dst, int32_t imm32) {
1238 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001239 emit_arith(6, Operand(dst), Immediate(imm32));
1240}
1241
1242
1243void Assembler::xor_(Register dst, const Operand& src) {
1244 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001245 EMIT(0x33);
1246 emit_operand(dst, src);
1247}
1248
1249
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001250void Assembler::xor_(const Operand& dst, Register src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001251 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001252 EMIT(0x31);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001253 emit_operand(src, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001254}
1255
1256
1257void Assembler::xor_(const Operand& dst, const Immediate& x) {
1258 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001259 emit_arith(6, dst, x);
1260}
1261
1262
1263void Assembler::bt(const Operand& dst, Register src) {
1264 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001265 EMIT(0x0F);
1266 EMIT(0xA3);
1267 emit_operand(src, dst);
1268}
1269
1270
1271void Assembler::bts(const Operand& dst, Register src) {
1272 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001273 EMIT(0x0F);
1274 EMIT(0xAB);
1275 emit_operand(src, dst);
1276}
1277
1278
1279void Assembler::hlt() {
1280 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001281 EMIT(0xF4);
1282}
1283
1284
1285void Assembler::int3() {
1286 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001287 EMIT(0xCC);
1288}
1289
1290
1291void Assembler::nop() {
1292 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001293 EMIT(0x90);
1294}
1295
1296
1297void Assembler::rdtsc() {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001298 ASSERT(CpuFeatures::IsEnabled(RDTSC));
Steve Blocka7e24c12009-10-30 11:49:00 +00001299 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001300 EMIT(0x0F);
1301 EMIT(0x31);
1302}
1303
1304
1305void Assembler::ret(int imm16) {
1306 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001307 ASSERT(is_uint16(imm16));
1308 if (imm16 == 0) {
1309 EMIT(0xC3);
1310 } else {
1311 EMIT(0xC2);
1312 EMIT(imm16 & 0xFF);
1313 EMIT((imm16 >> 8) & 0xFF);
1314 }
1315}
1316
1317
1318// Labels refer to positions in the (to be) generated code.
1319// There are bound, linked, and unused labels.
1320//
1321// Bound labels refer to known positions in the already
1322// generated code. pos() is the position the label refers to.
1323//
1324// Linked labels refer to unknown positions in the code
1325// to be generated; pos() is the position of the 32bit
1326// Displacement of the last instruction using the label.
1327
1328
1329void Assembler::print(Label* L) {
1330 if (L->is_unused()) {
1331 PrintF("unused label\n");
1332 } else if (L->is_bound()) {
1333 PrintF("bound label to %d\n", L->pos());
1334 } else if (L->is_linked()) {
1335 Label l = *L;
1336 PrintF("unbound label");
1337 while (l.is_linked()) {
1338 Displacement disp = disp_at(&l);
1339 PrintF("@ %d ", l.pos());
1340 disp.print();
1341 PrintF("\n");
1342 disp.next(&l);
1343 }
1344 } else {
1345 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
1346 }
1347}
1348
1349
1350void Assembler::bind_to(Label* L, int pos) {
1351 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001352 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position
1353 while (L->is_linked()) {
1354 Displacement disp = disp_at(L);
1355 int fixup_pos = L->pos();
1356 if (disp.type() == Displacement::CODE_RELATIVE) {
1357 // Relative to Code* heap object pointer.
1358 long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
1359 } else {
1360 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
1361 ASSERT(byte_at(fixup_pos - 1) == 0xE9); // jmp expected
1362 }
Andrei Popescu31002712010-02-23 13:46:05 +00001363 // Relative address, relative to point after address.
Steve Blocka7e24c12009-10-30 11:49:00 +00001364 int imm32 = pos - (fixup_pos + sizeof(int32_t));
1365 long_at_put(fixup_pos, imm32);
1366 }
1367 disp.next(L);
1368 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001369 while (L->is_near_linked()) {
1370 int fixup_pos = L->near_link_pos();
1371 int offset_to_next =
1372 static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
1373 ASSERT(offset_to_next <= 0);
1374 // Relative address, relative to point after address.
1375 int disp = pos - fixup_pos - sizeof(int8_t);
1376 ASSERT(0 <= disp && disp <= 127);
1377 set_byte_at(fixup_pos, disp);
1378 if (offset_to_next < 0) {
1379 L->link_to(fixup_pos + offset_to_next, Label::kNear);
1380 } else {
1381 L->UnuseNear();
1382 }
1383 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001384 L->bind_to(pos);
1385}
1386
1387
Steve Blocka7e24c12009-10-30 11:49:00 +00001388void Assembler::bind(Label* L) {
1389 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001390 ASSERT(!L->is_bound()); // label can only be bound once
1391 bind_to(L, pc_offset());
1392}
1393
1394
1395void Assembler::call(Label* L) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001396 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001397 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001398 if (L->is_bound()) {
1399 const int long_size = 5;
1400 int offs = L->pos() - pc_offset();
1401 ASSERT(offs <= 0);
Andrei Popescu31002712010-02-23 13:46:05 +00001402 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001403 EMIT(0xE8);
1404 emit(offs - long_size);
1405 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001406 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001407 EMIT(0xE8);
1408 emit_disp(L, Displacement::OTHER);
1409 }
1410}
1411
1412
1413void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001414 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001415 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001416 ASSERT(!RelocInfo::IsCodeTarget(rmode));
1417 EMIT(0xE8);
1418 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1419}
1420
1421
Ben Murdoch257744e2011-11-30 15:57:28 +00001422int Assembler::CallSize(const Operand& adr) {
1423 // Call size is 1 (opcode) + adr.len_ (operand).
1424 return 1 + adr.len_;
1425}
1426
1427
Steve Blocka7e24c12009-10-30 11:49:00 +00001428void Assembler::call(const Operand& adr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001429 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001430 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001431 EMIT(0xFF);
1432 emit_operand(edx, adr);
1433}
1434
1435
Ben Murdoch257744e2011-11-30 15:57:28 +00001436int Assembler::CallSize(Handle<Code> code, RelocInfo::Mode rmode) {
1437 return 1 /* EMIT */ + sizeof(uint32_t) /* emit */;
Steve Blocka7e24c12009-10-30 11:49:00 +00001438}
1439
1440
Ben Murdoch257744e2011-11-30 15:57:28 +00001441void Assembler::call(Handle<Code> code,
1442 RelocInfo::Mode rmode,
1443 unsigned ast_id) {
1444 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001445 EnsureSpace ensure_space(this);
Ben Murdoch257744e2011-11-30 15:57:28 +00001446 ASSERT(RelocInfo::IsCodeTarget(rmode));
1447 EMIT(0xE8);
1448 emit(reinterpret_cast<intptr_t>(code.location()), rmode, ast_id);
1449}
1450
1451
1452void Assembler::jmp(Label* L, Label::Distance distance) {
1453 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001454 if (L->is_bound()) {
1455 const int short_size = 2;
1456 const int long_size = 5;
1457 int offs = L->pos() - pc_offset();
1458 ASSERT(offs <= 0);
1459 if (is_int8(offs - short_size)) {
Andrei Popescu31002712010-02-23 13:46:05 +00001460 // 1110 1011 #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001461 EMIT(0xEB);
1462 EMIT((offs - short_size) & 0xFF);
1463 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001464 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001465 EMIT(0xE9);
1466 emit(offs - long_size);
1467 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001468 } else if (distance == Label::kNear) {
1469 EMIT(0xEB);
1470 emit_near_disp(L);
Steve Blocka7e24c12009-10-30 11:49:00 +00001471 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001472 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001473 EMIT(0xE9);
1474 emit_disp(L, Displacement::UNCONDITIONAL_JUMP);
1475 }
1476}
1477
1478
1479void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
1480 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001481 ASSERT(!RelocInfo::IsCodeTarget(rmode));
1482 EMIT(0xE9);
1483 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1484}
1485
1486
1487void Assembler::jmp(const Operand& adr) {
1488 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001489 EMIT(0xFF);
1490 emit_operand(esp, adr);
1491}
1492
1493
1494void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
1495 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001496 ASSERT(RelocInfo::IsCodeTarget(rmode));
1497 EMIT(0xE9);
1498 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
1499}
1500
1501
Ben Murdoch257744e2011-11-30 15:57:28 +00001502void Assembler::j(Condition cc, Label* L, Label::Distance distance) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001503 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001504 ASSERT(0 <= cc && cc < 16);
Steve Blocka7e24c12009-10-30 11:49:00 +00001505 if (L->is_bound()) {
1506 const int short_size = 2;
1507 const int long_size = 6;
1508 int offs = L->pos() - pc_offset();
1509 ASSERT(offs <= 0);
1510 if (is_int8(offs - short_size)) {
1511 // 0111 tttn #8-bit disp
1512 EMIT(0x70 | cc);
1513 EMIT((offs - short_size) & 0xFF);
1514 } else {
1515 // 0000 1111 1000 tttn #32-bit disp
1516 EMIT(0x0F);
1517 EMIT(0x80 | cc);
1518 emit(offs - long_size);
1519 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001520 } else if (distance == Label::kNear) {
1521 EMIT(0x70 | cc);
1522 emit_near_disp(L);
Steve Blocka7e24c12009-10-30 11:49:00 +00001523 } else {
1524 // 0000 1111 1000 tttn #32-bit disp
1525 // Note: could eliminate cond. jumps to this jump if condition
1526 // is the same however, seems to be rather unlikely case.
1527 EMIT(0x0F);
1528 EMIT(0x80 | cc);
1529 emit_disp(L, Displacement::OTHER);
1530 }
1531}
1532
1533
Ben Murdoch257744e2011-11-30 15:57:28 +00001534void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001535 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001536 ASSERT((0 <= cc) && (cc < 16));
Andrei Popescu31002712010-02-23 13:46:05 +00001537 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001538 EMIT(0x0F);
1539 EMIT(0x80 | cc);
1540 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1541}
1542
1543
Ben Murdoch257744e2011-11-30 15:57:28 +00001544void Assembler::j(Condition cc, Handle<Code> code) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001545 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001546 // 0000 1111 1000 tttn #32-bit disp
1547 EMIT(0x0F);
1548 EMIT(0x80 | cc);
1549 emit(reinterpret_cast<intptr_t>(code.location()), RelocInfo::CODE_TARGET);
1550}
1551
1552
Andrei Popescu31002712010-02-23 13:46:05 +00001553// FPU instructions.
Steve Blocka7e24c12009-10-30 11:49:00 +00001554
Steve Blocka7e24c12009-10-30 11:49:00 +00001555void Assembler::fld(int i) {
1556 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001557 emit_farith(0xD9, 0xC0, i);
1558}
1559
1560
Andrei Popescu402d9372010-02-26 13:31:12 +00001561void Assembler::fstp(int i) {
1562 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00001563 emit_farith(0xDD, 0xD8, i);
1564}
1565
1566
Steve Blocka7e24c12009-10-30 11:49:00 +00001567void Assembler::fld1() {
1568 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001569 EMIT(0xD9);
1570 EMIT(0xE8);
1571}
1572
1573
Andrei Popescu402d9372010-02-26 13:31:12 +00001574void Assembler::fldpi() {
1575 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00001576 EMIT(0xD9);
1577 EMIT(0xEB);
1578}
1579
1580
Steve Blocka7e24c12009-10-30 11:49:00 +00001581void Assembler::fldz() {
1582 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001583 EMIT(0xD9);
1584 EMIT(0xEE);
1585}
1586
1587
Ben Murdochb0fe1622011-05-05 13:52:32 +01001588void Assembler::fldln2() {
1589 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001590 EMIT(0xD9);
1591 EMIT(0xED);
1592}
1593
1594
Steve Blocka7e24c12009-10-30 11:49:00 +00001595void Assembler::fld_s(const Operand& adr) {
1596 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001597 EMIT(0xD9);
1598 emit_operand(eax, adr);
1599}
1600
1601
1602void Assembler::fld_d(const Operand& adr) {
1603 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001604 EMIT(0xDD);
1605 emit_operand(eax, adr);
1606}
1607
1608
1609void Assembler::fstp_s(const Operand& adr) {
1610 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001611 EMIT(0xD9);
1612 emit_operand(ebx, adr);
1613}
1614
1615
1616void Assembler::fstp_d(const Operand& adr) {
1617 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001618 EMIT(0xDD);
1619 emit_operand(ebx, adr);
1620}
1621
1622
Andrei Popescu402d9372010-02-26 13:31:12 +00001623void Assembler::fst_d(const Operand& adr) {
1624 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00001625 EMIT(0xDD);
1626 emit_operand(edx, adr);
1627}
1628
1629
Steve Blocka7e24c12009-10-30 11:49:00 +00001630void Assembler::fild_s(const Operand& adr) {
1631 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001632 EMIT(0xDB);
1633 emit_operand(eax, adr);
1634}
1635
1636
1637void Assembler::fild_d(const Operand& adr) {
1638 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001639 EMIT(0xDF);
1640 emit_operand(ebp, adr);
1641}
1642
1643
1644void Assembler::fistp_s(const Operand& adr) {
1645 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001646 EMIT(0xDB);
1647 emit_operand(ebx, adr);
1648}
1649
1650
1651void Assembler::fisttp_s(const Operand& adr) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001652 ASSERT(CpuFeatures::IsEnabled(SSE3));
Steve Blocka7e24c12009-10-30 11:49:00 +00001653 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001654 EMIT(0xDB);
1655 emit_operand(ecx, adr);
1656}
1657
1658
Leon Clarkee46be812010-01-19 14:06:41 +00001659void Assembler::fisttp_d(const Operand& adr) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001660 ASSERT(CpuFeatures::IsEnabled(SSE3));
Leon Clarkee46be812010-01-19 14:06:41 +00001661 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00001662 EMIT(0xDD);
1663 emit_operand(ecx, adr);
1664}
1665
1666
Steve Blocka7e24c12009-10-30 11:49:00 +00001667void Assembler::fist_s(const Operand& adr) {
1668 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001669 EMIT(0xDB);
1670 emit_operand(edx, adr);
1671}
1672
1673
1674void Assembler::fistp_d(const Operand& adr) {
1675 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001676 EMIT(0xDF);
1677 emit_operand(edi, adr);
1678}
1679
1680
1681void Assembler::fabs() {
1682 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001683 EMIT(0xD9);
1684 EMIT(0xE1);
1685}
1686
1687
1688void Assembler::fchs() {
1689 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001690 EMIT(0xD9);
1691 EMIT(0xE0);
1692}
1693
1694
1695void Assembler::fcos() {
1696 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001697 EMIT(0xD9);
1698 EMIT(0xFF);
1699}
1700
1701
1702void Assembler::fsin() {
1703 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001704 EMIT(0xD9);
1705 EMIT(0xFE);
1706}
1707
1708
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001709void Assembler::fptan() {
1710 EnsureSpace ensure_space(this);
1711 EMIT(0xD9);
1712 EMIT(0xF2);
1713}
1714
1715
Ben Murdochb0fe1622011-05-05 13:52:32 +01001716void Assembler::fyl2x() {
1717 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001718 EMIT(0xD9);
1719 EMIT(0xF1);
1720}
1721
1722
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001723void Assembler::f2xm1() {
1724 EnsureSpace ensure_space(this);
1725 EMIT(0xD9);
1726 EMIT(0xF0);
1727}
1728
1729
1730void Assembler::fscale() {
1731 EnsureSpace ensure_space(this);
1732 EMIT(0xD9);
1733 EMIT(0xFD);
1734}
1735
1736
1737void Assembler::fninit() {
1738 EnsureSpace ensure_space(this);
1739 EMIT(0xDB);
1740 EMIT(0xE3);
1741}
1742
1743
Steve Blocka7e24c12009-10-30 11:49:00 +00001744void Assembler::fadd(int i) {
1745 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001746 emit_farith(0xDC, 0xC0, i);
1747}
1748
1749
1750void Assembler::fsub(int i) {
1751 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001752 emit_farith(0xDC, 0xE8, i);
1753}
1754
1755
1756void Assembler::fisub_s(const Operand& adr) {
1757 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001758 EMIT(0xDA);
1759 emit_operand(esp, adr);
1760}
1761
1762
1763void Assembler::fmul(int i) {
1764 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001765 emit_farith(0xDC, 0xC8, i);
1766}
1767
1768
1769void Assembler::fdiv(int i) {
1770 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001771 emit_farith(0xDC, 0xF8, i);
1772}
1773
1774
1775void Assembler::faddp(int i) {
1776 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001777 emit_farith(0xDE, 0xC0, i);
1778}
1779
1780
1781void Assembler::fsubp(int i) {
1782 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001783 emit_farith(0xDE, 0xE8, i);
1784}
1785
1786
1787void Assembler::fsubrp(int i) {
1788 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001789 emit_farith(0xDE, 0xE0, i);
1790}
1791
1792
1793void Assembler::fmulp(int i) {
1794 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001795 emit_farith(0xDE, 0xC8, i);
1796}
1797
1798
1799void Assembler::fdivp(int i) {
1800 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001801 emit_farith(0xDE, 0xF8, i);
1802}
1803
1804
1805void Assembler::fprem() {
1806 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001807 EMIT(0xD9);
1808 EMIT(0xF8);
1809}
1810
1811
1812void Assembler::fprem1() {
1813 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001814 EMIT(0xD9);
1815 EMIT(0xF5);
1816}
1817
1818
1819void Assembler::fxch(int i) {
1820 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001821 emit_farith(0xD9, 0xC8, i);
1822}
1823
1824
1825void Assembler::fincstp() {
1826 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001827 EMIT(0xD9);
1828 EMIT(0xF7);
1829}
1830
1831
1832void Assembler::ffree(int i) {
1833 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001834 emit_farith(0xDD, 0xC0, i);
1835}
1836
1837
1838void Assembler::ftst() {
1839 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001840 EMIT(0xD9);
1841 EMIT(0xE4);
1842}
1843
1844
1845void Assembler::fucomp(int i) {
1846 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001847 emit_farith(0xDD, 0xE8, i);
1848}
1849
1850
1851void Assembler::fucompp() {
1852 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001853 EMIT(0xDA);
1854 EMIT(0xE9);
1855}
1856
1857
Steve Block3ce2e202009-11-05 08:53:23 +00001858void Assembler::fucomi(int i) {
1859 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001860 EMIT(0xDB);
1861 EMIT(0xE8 + i);
1862}
1863
1864
1865void Assembler::fucomip() {
1866 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001867 EMIT(0xDF);
1868 EMIT(0xE9);
1869}
1870
1871
Steve Blocka7e24c12009-10-30 11:49:00 +00001872void Assembler::fcompp() {
1873 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001874 EMIT(0xDE);
1875 EMIT(0xD9);
1876}
1877
1878
1879void Assembler::fnstsw_ax() {
1880 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001881 EMIT(0xDF);
1882 EMIT(0xE0);
1883}
1884
1885
1886void Assembler::fwait() {
1887 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001888 EMIT(0x9B);
1889}
1890
1891
1892void Assembler::frndint() {
1893 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001894 EMIT(0xD9);
1895 EMIT(0xFC);
1896}
1897
1898
1899void Assembler::fnclex() {
1900 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001901 EMIT(0xDB);
1902 EMIT(0xE2);
1903}
1904
1905
1906void Assembler::sahf() {
1907 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001908 EMIT(0x9E);
1909}
1910
1911
1912void Assembler::setcc(Condition cc, Register reg) {
1913 ASSERT(reg.is_byte_register());
1914 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001915 EMIT(0x0F);
1916 EMIT(0x90 | cc);
1917 EMIT(0xC0 | reg.code());
1918}
1919
1920
1921void Assembler::cvttss2si(Register dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001922 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00001923 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001924 EMIT(0xF3);
1925 EMIT(0x0F);
1926 EMIT(0x2C);
1927 emit_operand(dst, src);
1928}
1929
1930
1931void Assembler::cvttsd2si(Register dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001932 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00001933 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001934 EMIT(0xF2);
1935 EMIT(0x0F);
1936 EMIT(0x2C);
1937 emit_operand(dst, src);
1938}
1939
1940
1941void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001942 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00001943 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001944 EMIT(0xF2);
1945 EMIT(0x0F);
1946 EMIT(0x2A);
1947 emit_sse_operand(dst, src);
1948}
1949
1950
Steve Block6ded16b2010-05-10 14:33:55 +01001951void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001952 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block6ded16b2010-05-10 14:33:55 +01001953 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01001954 EMIT(0xF3);
1955 EMIT(0x0F);
1956 EMIT(0x5A);
1957 emit_sse_operand(dst, src);
1958}
1959
1960
Steve Block44f0eee2011-05-26 01:26:41 +01001961void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001962 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block44f0eee2011-05-26 01:26:41 +01001963 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +01001964 EMIT(0xF2);
1965 EMIT(0x0F);
1966 EMIT(0x5A);
1967 emit_sse_operand(dst, src);
1968}
1969
1970
Steve Blocka7e24c12009-10-30 11:49:00 +00001971void Assembler::addsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001972 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00001973 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001974 EMIT(0xF2);
1975 EMIT(0x0F);
1976 EMIT(0x58);
1977 emit_sse_operand(dst, src);
1978}
1979
1980
1981void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001982 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00001983 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001984 EMIT(0xF2);
1985 EMIT(0x0F);
1986 EMIT(0x59);
1987 emit_sse_operand(dst, src);
1988}
1989
1990
1991void Assembler::subsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001992 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00001993 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001994 EMIT(0xF2);
1995 EMIT(0x0F);
1996 EMIT(0x5C);
1997 emit_sse_operand(dst, src);
1998}
1999
2000
2001void Assembler::divsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002002 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002003 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002004 EMIT(0xF2);
2005 EMIT(0x0F);
2006 EMIT(0x5E);
2007 emit_sse_operand(dst, src);
2008}
2009
2010
Leon Clarkee46be812010-01-19 14:06:41 +00002011void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002012 ASSERT(CpuFeatures::IsEnabled(SSE2));
Leon Clarkee46be812010-01-19 14:06:41 +00002013 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002014 EMIT(0x66);
2015 EMIT(0x0F);
2016 EMIT(0x57);
2017 emit_sse_operand(dst, src);
2018}
2019
2020
Ben Murdoch257744e2011-11-30 15:57:28 +00002021void Assembler::xorps(XMMRegister dst, XMMRegister src) {
2022 EnsureSpace ensure_space(this);
2023 EMIT(0x0F);
2024 EMIT(0x57);
2025 emit_sse_operand(dst, src);
2026}
2027
2028
Steve Block6ded16b2010-05-10 14:33:55 +01002029void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
2030 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002031 EMIT(0xF2);
2032 EMIT(0x0F);
2033 EMIT(0x51);
2034 emit_sse_operand(dst, src);
2035}
2036
2037
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002038void Assembler::andpd(XMMRegister dst, XMMRegister src) {
2039 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002040 EMIT(0x66);
2041 EMIT(0x0F);
2042 EMIT(0x54);
2043 emit_sse_operand(dst, src);
2044}
2045
2046
Steve Block6ded16b2010-05-10 14:33:55 +01002047void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002048 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block6ded16b2010-05-10 14:33:55 +01002049 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002050 EMIT(0x66);
2051 EMIT(0x0F);
2052 EMIT(0x2E);
2053 emit_sse_operand(dst, src);
2054}
2055
2056
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002057void Assembler::ucomisd(XMMRegister dst, const Operand& src) {
2058 ASSERT(CpuFeatures::IsEnabled(SSE2));
2059 EnsureSpace ensure_space(this);
2060 EMIT(0x66);
2061 EMIT(0x0F);
2062 EMIT(0x2E);
2063 emit_sse_operand(dst, src);
2064}
2065
2066
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002067void Assembler::roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode) {
2068 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
2069 EnsureSpace ensure_space(this);
2070 EMIT(0x66);
2071 EMIT(0x0F);
2072 EMIT(0x3A);
2073 EMIT(0x0B);
2074 emit_sse_operand(dst, src);
2075 // Mask precision exeption.
2076 EMIT(static_cast<byte>(mode) | 0x8);
2077}
2078
Steve Block6ded16b2010-05-10 14:33:55 +01002079void Assembler::movmskpd(Register dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002080 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block6ded16b2010-05-10 14:33:55 +01002081 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002082 EMIT(0x66);
2083 EMIT(0x0F);
2084 EMIT(0x50);
2085 emit_sse_operand(dst, src);
2086}
2087
2088
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002089void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002090 ASSERT(CpuFeatures::IsEnabled(SSE2));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002091 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002092 EMIT(0xF2);
2093 EMIT(0x0F);
2094 EMIT(0xC2);
2095 emit_sse_operand(dst, src);
2096 EMIT(1); // LT == 1
2097}
2098
2099
2100void Assembler::movaps(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002101 ASSERT(CpuFeatures::IsEnabled(SSE2));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002102 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002103 EMIT(0x0F);
2104 EMIT(0x28);
2105 emit_sse_operand(dst, src);
2106}
2107
2108
2109void Assembler::movdqa(const Operand& dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002110 ASSERT(CpuFeatures::IsEnabled(SSE2));
Leon Clarkee46be812010-01-19 14:06:41 +00002111 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002112 EMIT(0x66);
2113 EMIT(0x0F);
2114 EMIT(0x7F);
2115 emit_sse_operand(src, dst);
2116}
2117
2118
2119void Assembler::movdqa(XMMRegister dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002120 ASSERT(CpuFeatures::IsEnabled(SSE2));
Leon Clarkee46be812010-01-19 14:06:41 +00002121 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002122 EMIT(0x66);
2123 EMIT(0x0F);
2124 EMIT(0x6F);
2125 emit_sse_operand(dst, src);
2126}
2127
2128
2129void Assembler::movdqu(const Operand& dst, XMMRegister src ) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002130 ASSERT(CpuFeatures::IsEnabled(SSE2));
Leon Clarkee46be812010-01-19 14:06:41 +00002131 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002132 EMIT(0xF3);
2133 EMIT(0x0F);
2134 EMIT(0x7F);
2135 emit_sse_operand(src, dst);
2136}
2137
2138
2139void Assembler::movdqu(XMMRegister dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002140 ASSERT(CpuFeatures::IsEnabled(SSE2));
Leon Clarkee46be812010-01-19 14:06:41 +00002141 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002142 EMIT(0xF3);
2143 EMIT(0x0F);
2144 EMIT(0x6F);
2145 emit_sse_operand(dst, src);
2146}
2147
2148
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002149void Assembler::movntdqa(XMMRegister dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002150 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002151 EnsureSpace ensure_space(this);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002152 EMIT(0x66);
2153 EMIT(0x0F);
2154 EMIT(0x38);
2155 EMIT(0x2A);
2156 emit_sse_operand(dst, src);
2157}
2158
2159
2160void Assembler::movntdq(const Operand& dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002161 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002162 EnsureSpace ensure_space(this);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002163 EMIT(0x66);
2164 EMIT(0x0F);
2165 EMIT(0xE7);
2166 emit_sse_operand(src, dst);
2167}
2168
2169
2170void Assembler::prefetch(const Operand& src, int level) {
2171 ASSERT(is_uint2(level));
2172 EnsureSpace ensure_space(this);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002173 EMIT(0x0F);
2174 EMIT(0x18);
2175 XMMRegister code = { level }; // Emit hint number in Reg position of RegR/M.
2176 emit_sse_operand(code, src);
2177}
2178
2179
Steve Blocka7e24c12009-10-30 11:49:00 +00002180void Assembler::movdbl(XMMRegister dst, const Operand& src) {
2181 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002182 movsd(dst, src);
2183}
2184
2185
2186void Assembler::movdbl(const Operand& dst, XMMRegister src) {
2187 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002188 movsd(dst, src);
2189}
2190
2191
2192void Assembler::movsd(const Operand& dst, XMMRegister src ) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002193 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002194 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002195 EMIT(0xF2); // double
2196 EMIT(0x0F);
2197 EMIT(0x11); // store
2198 emit_sse_operand(src, dst);
2199}
2200
2201
2202void Assembler::movsd(XMMRegister dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002203 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002204 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002205 EMIT(0xF2); // double
2206 EMIT(0x0F);
2207 EMIT(0x10); // load
2208 emit_sse_operand(dst, src);
2209}
2210
Ben Murdochb0fe1622011-05-05 13:52:32 +01002211
Steve Block6ded16b2010-05-10 14:33:55 +01002212void Assembler::movsd(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002213 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block6ded16b2010-05-10 14:33:55 +01002214 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002215 EMIT(0xF2);
2216 EMIT(0x0F);
2217 EMIT(0x10);
2218 emit_sse_operand(dst, src);
2219}
2220
2221
Steve Block44f0eee2011-05-26 01:26:41 +01002222void Assembler::movss(const Operand& dst, XMMRegister src ) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002223 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block44f0eee2011-05-26 01:26:41 +01002224 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +01002225 EMIT(0xF3); // float
2226 EMIT(0x0F);
2227 EMIT(0x11); // store
2228 emit_sse_operand(src, dst);
2229}
2230
2231
2232void Assembler::movss(XMMRegister dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002233 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block44f0eee2011-05-26 01:26:41 +01002234 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +01002235 EMIT(0xF3); // float
2236 EMIT(0x0F);
2237 EMIT(0x10); // load
2238 emit_sse_operand(dst, src);
2239}
2240
2241
2242void Assembler::movss(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002243 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block44f0eee2011-05-26 01:26:41 +01002244 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +01002245 EMIT(0xF3);
2246 EMIT(0x0F);
2247 EMIT(0x10);
2248 emit_sse_operand(dst, src);
2249}
2250
2251
Steve Block6ded16b2010-05-10 14:33:55 +01002252void Assembler::movd(XMMRegister dst, const Operand& src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002253 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block6ded16b2010-05-10 14:33:55 +01002254 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002255 EMIT(0x66);
2256 EMIT(0x0F);
2257 EMIT(0x6E);
2258 emit_sse_operand(dst, src);
2259}
2260
2261
Ben Murdochb0fe1622011-05-05 13:52:32 +01002262void Assembler::movd(const Operand& dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002263 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002264 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002265 EMIT(0x66);
2266 EMIT(0x0F);
2267 EMIT(0x7E);
2268 emit_sse_operand(src, dst);
2269}
2270
2271
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002272void Assembler::extractps(Register dst, XMMRegister src, byte imm8) {
2273 ASSERT(CpuFeatures::IsSupported(SSE4_1));
2274 ASSERT(is_uint8(imm8));
2275 EnsureSpace ensure_space(this);
2276 EMIT(0x66);
2277 EMIT(0x0F);
2278 EMIT(0x3A);
2279 EMIT(0x17);
2280 emit_sse_operand(dst, src);
2281 EMIT(imm8);
2282}
2283
2284
Ben Murdochb0fe1622011-05-05 13:52:32 +01002285void Assembler::pand(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002286 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002287 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002288 EMIT(0x66);
2289 EMIT(0x0F);
2290 EMIT(0xDB);
2291 emit_sse_operand(dst, src);
2292}
2293
2294
Steve Block6ded16b2010-05-10 14:33:55 +01002295void Assembler::pxor(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002296 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Block6ded16b2010-05-10 14:33:55 +01002297 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002298 EMIT(0x66);
2299 EMIT(0x0F);
2300 EMIT(0xEF);
2301 emit_sse_operand(dst, src);
2302}
2303
2304
Ben Murdochb8e0da22011-05-16 14:20:40 +01002305void Assembler::por(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002306 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdochb8e0da22011-05-16 14:20:40 +01002307 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002308 EMIT(0x66);
2309 EMIT(0x0F);
2310 EMIT(0xEB);
2311 emit_sse_operand(dst, src);
2312}
2313
2314
Steve Block6ded16b2010-05-10 14:33:55 +01002315void Assembler::ptest(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002316 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
Steve Block6ded16b2010-05-10 14:33:55 +01002317 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002318 EMIT(0x66);
2319 EMIT(0x0F);
2320 EMIT(0x38);
2321 EMIT(0x17);
2322 emit_sse_operand(dst, src);
2323}
2324
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002325
Ben Murdochb0fe1622011-05-05 13:52:32 +01002326void Assembler::psllq(XMMRegister reg, int8_t shift) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002327 ASSERT(CpuFeatures::IsEnabled(SSE2));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002328 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002329 EMIT(0x66);
2330 EMIT(0x0F);
2331 EMIT(0x73);
2332 emit_sse_operand(esi, reg); // esi == 6
Ben Murdochb0fe1622011-05-05 13:52:32 +01002333 EMIT(shift);
2334}
2335
2336
Ben Murdochb8e0da22011-05-16 14:20:40 +01002337void Assembler::psllq(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002338 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdochb8e0da22011-05-16 14:20:40 +01002339 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002340 EMIT(0x66);
2341 EMIT(0x0F);
2342 EMIT(0xF3);
2343 emit_sse_operand(dst, src);
2344}
2345
2346
2347void Assembler::psrlq(XMMRegister reg, int8_t shift) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002348 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdochb8e0da22011-05-16 14:20:40 +01002349 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002350 EMIT(0x66);
2351 EMIT(0x0F);
2352 EMIT(0x73);
2353 emit_sse_operand(edx, reg); // edx == 2
2354 EMIT(shift);
2355}
2356
2357
2358void Assembler::psrlq(XMMRegister dst, XMMRegister src) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002359 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdochb8e0da22011-05-16 14:20:40 +01002360 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002361 EMIT(0x66);
2362 EMIT(0x0F);
2363 EMIT(0xD3);
2364 emit_sse_operand(dst, src);
2365}
2366
2367
Ben Murdochb0fe1622011-05-05 13:52:32 +01002368void Assembler::pshufd(XMMRegister dst, XMMRegister src, int8_t shuffle) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002369 ASSERT(CpuFeatures::IsEnabled(SSE2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002370 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002371 EMIT(0x66);
2372 EMIT(0x0F);
2373 EMIT(0x70);
2374 emit_sse_operand(dst, src);
2375 EMIT(shuffle);
2376}
2377
2378
2379void Assembler::pextrd(const Operand& dst, XMMRegister src, int8_t offset) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002380 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002381 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002382 EMIT(0x66);
2383 EMIT(0x0F);
2384 EMIT(0x3A);
2385 EMIT(0x16);
2386 emit_sse_operand(src, dst);
2387 EMIT(offset);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002388}
2389
2390
Steve Block1e0659c2011-05-24 12:43:12 +01002391void Assembler::pinsrd(XMMRegister dst, const Operand& src, int8_t offset) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002392 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
Steve Block1e0659c2011-05-24 12:43:12 +01002393 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002394 EMIT(0x66);
2395 EMIT(0x0F);
2396 EMIT(0x3A);
2397 EMIT(0x22);
2398 emit_sse_operand(dst, src);
2399 EMIT(offset);
2400}
2401
2402
Steve Blocka7e24c12009-10-30 11:49:00 +00002403void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
2404 Register ireg = { reg.code() };
2405 emit_operand(ireg, adr);
2406}
2407
2408
2409void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
2410 EMIT(0xC0 | dst.code() << 3 | src.code());
2411}
2412
2413
Steve Block6ded16b2010-05-10 14:33:55 +01002414void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
2415 EMIT(0xC0 | dst.code() << 3 | src.code());
2416}
2417
2418
Steve Blocka7e24c12009-10-30 11:49:00 +00002419void Assembler::Print() {
2420 Disassembler::Decode(stdout, buffer_, pc_);
2421}
2422
2423
2424void Assembler::RecordJSReturn() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002425 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00002426 EnsureSpace ensure_space(this);
2427 RecordRelocInfo(RelocInfo::JS_RETURN);
2428}
2429
2430
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002431void Assembler::RecordDebugBreakSlot() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002432 positions_recorder()->WriteRecordedPositions();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002433 EnsureSpace ensure_space(this);
2434 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
2435}
2436
2437
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002438void Assembler::RecordComment(const char* msg, bool force) {
2439 if (FLAG_code_comments || force) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002440 EnsureSpace ensure_space(this);
2441 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
2442 }
2443}
2444
2445
Steve Blocka7e24c12009-10-30 11:49:00 +00002446void Assembler::GrowBuffer() {
Andrei Popescu31002712010-02-23 13:46:05 +00002447 ASSERT(overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +00002448 if (!own_buffer_) FATAL("external code buffer is too small");
2449
Andrei Popescu31002712010-02-23 13:46:05 +00002450 // Compute new buffer size.
Steve Blocka7e24c12009-10-30 11:49:00 +00002451 CodeDesc desc; // the new buffer
2452 if (buffer_size_ < 4*KB) {
2453 desc.buffer_size = 4*KB;
2454 } else {
2455 desc.buffer_size = 2*buffer_size_;
2456 }
2457 // Some internal data structures overflow for very large buffers,
2458 // they must ensure that kMaximalBufferSize is not too large.
2459 if ((desc.buffer_size > kMaximalBufferSize) ||
Steve Block44f0eee2011-05-26 01:26:41 +01002460 (desc.buffer_size > isolate()->heap()->MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002461 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
2462 }
2463
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002464 // Set up new buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +00002465 desc.buffer = NewArray<byte>(desc.buffer_size);
2466 desc.instr_size = pc_offset();
2467 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
2468
2469 // Clear the buffer in debug mode. Use 'int3' instructions to make
2470 // sure to get into problems if we ever run uninitialized code.
2471#ifdef DEBUG
2472 memset(desc.buffer, 0xCC, desc.buffer_size);
2473#endif
2474
Andrei Popescu31002712010-02-23 13:46:05 +00002475 // Copy the data.
Steve Blocka7e24c12009-10-30 11:49:00 +00002476 int pc_delta = desc.buffer - buffer_;
2477 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
2478 memmove(desc.buffer, buffer_, desc.instr_size);
2479 memmove(rc_delta + reloc_info_writer.pos(),
2480 reloc_info_writer.pos(), desc.reloc_size);
2481
Andrei Popescu31002712010-02-23 13:46:05 +00002482 // Switch buffers.
Steve Block44f0eee2011-05-26 01:26:41 +01002483 if (isolate()->assembler_spare_buffer() == NULL &&
2484 buffer_size_ == kMinimalBufferSize) {
2485 isolate()->set_assembler_spare_buffer(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +00002486 } else {
2487 DeleteArray(buffer_);
2488 }
2489 buffer_ = desc.buffer;
2490 buffer_size_ = desc.buffer_size;
2491 pc_ += pc_delta;
Steve Blocka7e24c12009-10-30 11:49:00 +00002492 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2493 reloc_info_writer.last_pc() + pc_delta);
2494
Andrei Popescu31002712010-02-23 13:46:05 +00002495 // Relocate runtime entries.
Steve Blocka7e24c12009-10-30 11:49:00 +00002496 for (RelocIterator it(desc); !it.done(); it.next()) {
2497 RelocInfo::Mode rmode = it.rinfo()->rmode();
2498 if (rmode == RelocInfo::RUNTIME_ENTRY) {
2499 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2500 *p -= pc_delta; // relocate entry
2501 } else if (rmode == RelocInfo::INTERNAL_REFERENCE) {
2502 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2503 if (*p != 0) { // 0 means uninitialized.
2504 *p += pc_delta;
2505 }
2506 }
2507 }
2508
2509 ASSERT(!overflow());
2510}
2511
2512
2513void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
2514 ASSERT(is_uint8(op1) && is_uint8(op2)); // wrong opcode
2515 ASSERT(is_uint8(imm8));
2516 ASSERT((op1 & 0x01) == 0); // should be 8bit operation
2517 EMIT(op1);
2518 EMIT(op2 | dst.code());
2519 EMIT(imm8);
2520}
2521
2522
2523void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
2524 ASSERT((0 <= sel) && (sel <= 7));
2525 Register ireg = { sel };
2526 if (x.is_int8()) {
2527 EMIT(0x83); // using a sign-extended 8-bit immediate.
2528 emit_operand(ireg, dst);
2529 EMIT(x.x_ & 0xFF);
2530 } else if (dst.is_reg(eax)) {
2531 EMIT((sel << 3) | 0x05); // short form if the destination is eax.
2532 emit(x);
2533 } else {
2534 EMIT(0x81); // using a literal 32-bit immediate.
2535 emit_operand(ireg, dst);
2536 emit(x);
2537 }
2538}
2539
2540
2541void Assembler::emit_operand(Register reg, const Operand& adr) {
2542 const unsigned length = adr.len_;
2543 ASSERT(length > 0);
2544
2545 // Emit updated ModRM byte containing the given register.
2546 pc_[0] = (adr.buf_[0] & ~0x38) | (reg.code() << 3);
2547
2548 // Emit the rest of the encoded operand.
2549 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
2550 pc_ += length;
2551
2552 // Emit relocation information if necessary.
2553 if (length >= sizeof(int32_t) && adr.rmode_ != RelocInfo::NONE) {
2554 pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
2555 RecordRelocInfo(adr.rmode_);
2556 pc_ += sizeof(int32_t);
2557 }
2558}
2559
2560
2561void Assembler::emit_farith(int b1, int b2, int i) {
2562 ASSERT(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2563 ASSERT(0 <= i && i < 8); // illegal stack offset
2564 EMIT(b1);
2565 EMIT(b2 + i);
2566}
2567
2568
Ben Murdochb0fe1622011-05-05 13:52:32 +01002569void Assembler::db(uint8_t data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002570 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002571 EMIT(data);
2572}
2573
2574
2575void Assembler::dd(uint32_t data) {
2576 EnsureSpace ensure_space(this);
2577 emit(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00002578}
2579
2580
2581void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2582 ASSERT(rmode != RelocInfo::NONE);
2583 // Don't record external references unless the heap will be serialized.
Steve Blockd0582a62009-12-15 09:54:21 +00002584 if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
2585#ifdef DEBUG
2586 if (!Serializer::enabled()) {
2587 Serializer::TooLateToEnableNow();
2588 }
2589#endif
Steve Block44f0eee2011-05-26 01:26:41 +01002590 if (!Serializer::enabled() && !emit_debug_code()) {
Steve Blockd0582a62009-12-15 09:54:21 +00002591 return;
2592 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002593 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002594 RelocInfo rinfo(pc_, rmode, data, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00002595 reloc_info_writer.Write(&rinfo);
2596}
2597
2598
2599#ifdef GENERATED_CODE_COVERAGE
2600static FILE* coverage_log = NULL;
2601
2602
2603static void InitCoverageLog() {
2604 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
2605 if (file_name != NULL) {
2606 coverage_log = fopen(file_name, "aw+");
2607 }
2608}
2609
2610
2611void LogGeneratedCodeCoverage(const char* file_line) {
2612 const char* return_address = (&file_line)[-1];
2613 char* push_insn = const_cast<char*>(return_address - 12);
2614 push_insn[0] = 0xeb; // Relative branch insn.
2615 push_insn[1] = 13; // Skip over coverage insns.
2616 if (coverage_log != NULL) {
2617 fprintf(coverage_log, "%s\n", file_line);
2618 fflush(coverage_log);
2619 }
2620}
2621
2622#endif
2623
2624} } // namespace v8::internal
Leon Clarkef7060e22010-06-03 12:02:55 +01002625
2626#endif // V8_TARGET_ARCH_IA32