blob: 125f503bec33109adfd606d5a26720d92d0efa31 [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.
35// Copyright 2006-2008 the V8 project authors. All rights reserved.
36
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
51// Safe default is no features.
52uint64_t CpuFeatures::supported_ = 0;
53uint64_t CpuFeatures::enabled_ = 0;
Steve Blockd0582a62009-12-15 09:54:21 +000054uint64_t CpuFeatures::found_by_runtime_probing_ = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000055
56
57// The Probe method needs executable memory, so it uses Heap::CreateCode.
58// Allocation failure is silent and leads to safe default.
59void CpuFeatures::Probe() {
60 ASSERT(Heap::HasBeenSetup());
61 ASSERT(supported_ == 0);
Steve Blockd0582a62009-12-15 09:54:21 +000062 if (Serializer::enabled()) {
63 supported_ |= OS::CpuFeaturesImpliedByPlatform();
64 return; // No features if we might serialize.
65 }
Steve Blocka7e24c12009-10-30 11:49:00 +000066
67 Assembler assm(NULL, 0);
68 Label cpuid, done;
69#define __ assm.
70 // Save old esp, since we are going to modify the stack.
71 __ push(ebp);
72 __ pushfd();
73 __ push(ecx);
74 __ push(ebx);
75 __ mov(ebp, Operand(esp));
76
77 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
78 __ pushfd();
79 __ pop(eax);
80 __ mov(edx, Operand(eax));
81 __ xor_(eax, 0x200000); // Flip bit 21.
82 __ push(eax);
83 __ popfd();
84 __ pushfd();
85 __ pop(eax);
86 __ xor_(eax, Operand(edx)); // Different if CPUID is supported.
87 __ j(not_zero, &cpuid);
88
89 // CPUID not supported. Clear the supported features in edx:eax.
90 __ xor_(eax, Operand(eax));
91 __ xor_(edx, Operand(edx));
92 __ jmp(&done);
93
94 // Invoke CPUID with 1 in eax to get feature information in
95 // ecx:edx. Temporarily enable CPUID support because we know it's
96 // safe here.
97 __ bind(&cpuid);
98 __ mov(eax, 1);
99 supported_ = (1 << CPUID);
100 { Scope fscope(CPUID);
101 __ cpuid();
102 }
103 supported_ = 0;
104
105 // Move the result from ecx:edx to edx:eax and make sure to mark the
106 // CPUID feature as supported.
107 __ mov(eax, Operand(edx));
108 __ or_(eax, 1 << CPUID);
109 __ mov(edx, Operand(ecx));
110
111 // Done.
112 __ bind(&done);
113 __ mov(esp, Operand(ebp));
114 __ pop(ebx);
115 __ pop(ecx);
116 __ popfd();
117 __ pop(ebp);
118 __ ret(0);
119#undef __
120
121 CodeDesc desc;
122 assm.GetCode(&desc);
John Reck59135872010-11-02 12:39:01 -0700123
124 Object* code;
125 { MaybeObject* maybe_code = Heap::CreateCode(desc,
126 Code::ComputeFlags(Code::STUB),
127 Handle<Code>::null());
128 if (!maybe_code->ToObject(&code)) return;
129 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000130 if (!code->IsCode()) return;
John Reck59135872010-11-02 12:39:01 -0700131
Steve Block6ded16b2010-05-10 14:33:55 +0100132 PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG,
133 Code::cast(code), "CpuFeatures::Probe"));
Steve Blocka7e24c12009-10-30 11:49:00 +0000134 typedef uint64_t (*F0)();
135 F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry());
136 supported_ = probe();
Steve Blockd0582a62009-12-15 09:54:21 +0000137 found_by_runtime_probing_ = supported_;
138 uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform();
139 supported_ |= os_guarantees;
140 found_by_runtime_probing_ &= ~os_guarantees;
Steve Blocka7e24c12009-10-30 11:49:00 +0000141}
142
143
144// -----------------------------------------------------------------------------
145// Implementation of Displacement
146
147void Displacement::init(Label* L, Type type) {
148 ASSERT(!L->is_bound());
149 int next = 0;
150 if (L->is_linked()) {
151 next = L->pos();
152 ASSERT(next > 0); // Displacements must be at positions > 0
153 }
154 // Ensure that we _never_ overflow the next field.
155 ASSERT(NextField::is_valid(Assembler::kMaximalBufferSize));
156 data_ = NextField::encode(next) | TypeField::encode(type);
157}
158
159
160// -----------------------------------------------------------------------------
161// Implementation of RelocInfo
162
163
164const int RelocInfo::kApplyMask =
165 RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
Ben Murdochbb769b22010-08-11 14:56:33 +0100166 1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE |
167 1 << RelocInfo::DEBUG_BREAK_SLOT;
Steve Blocka7e24c12009-10-30 11:49:00 +0000168
169
Leon Clarkef7060e22010-06-03 12:02:55 +0100170bool RelocInfo::IsCodedSpecially() {
171 // The deserializer needs to know whether a pointer is specially coded. Being
172 // specially coded on IA32 means that it is a relative address, as used by
173 // branch instructions. These are also the ones that need changing when a
174 // code object moves.
175 return (1 << rmode_) & kApplyMask;
176}
177
178
Steve Blocka7e24c12009-10-30 11:49:00 +0000179void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
180 // Patch the code at the current address with the supplied instructions.
181 for (int i = 0; i < instruction_count; i++) {
182 *(pc_ + i) = *(instructions + i);
183 }
184
185 // Indicate that code has changed.
186 CPU::FlushICache(pc_, instruction_count);
187}
188
189
190// Patch the code at the current PC with a call to the target address.
191// Additional guard int3 instructions can be added if required.
192void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
193 // Call instruction takes up 5 bytes and int3 takes up one byte.
194 static const int kCallCodeSize = 5;
195 int code_size = kCallCodeSize + guard_bytes;
196
197 // Create a code patcher.
198 CodePatcher patcher(pc_, code_size);
199
200 // Add a label for checking the size of the code used for returning.
201#ifdef DEBUG
202 Label check_codesize;
203 patcher.masm()->bind(&check_codesize);
204#endif
205
206 // Patch the code.
207 patcher.masm()->call(target, RelocInfo::NONE);
208
209 // Check that the size of the code generated is as expected.
210 ASSERT_EQ(kCallCodeSize,
211 patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
212
213 // Add the requested number of int3 instructions after the call.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100214 ASSERT_GE(guard_bytes, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000215 for (int i = 0; i < guard_bytes; i++) {
216 patcher.masm()->int3();
217 }
218}
219
220
221// -----------------------------------------------------------------------------
222// Implementation of Operand
223
224Operand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) {
225 // [base + disp/r]
226 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
227 // [base]
228 set_modrm(0, base);
229 if (base.is(esp)) set_sib(times_1, esp, base);
230 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
231 // [base + disp8]
232 set_modrm(1, base);
233 if (base.is(esp)) set_sib(times_1, esp, base);
234 set_disp8(disp);
235 } else {
236 // [base + disp/r]
237 set_modrm(2, base);
238 if (base.is(esp)) set_sib(times_1, esp, base);
239 set_dispr(disp, rmode);
240 }
241}
242
243
244Operand::Operand(Register base,
245 Register index,
246 ScaleFactor scale,
247 int32_t disp,
248 RelocInfo::Mode rmode) {
249 ASSERT(!index.is(esp)); // illegal addressing mode
250 // [base + index*scale + disp/r]
251 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
252 // [base + index*scale]
253 set_modrm(0, esp);
254 set_sib(scale, index, base);
255 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
256 // [base + index*scale + disp8]
257 set_modrm(1, esp);
258 set_sib(scale, index, base);
259 set_disp8(disp);
260 } else {
261 // [base + index*scale + disp/r]
262 set_modrm(2, esp);
263 set_sib(scale, index, base);
264 set_dispr(disp, rmode);
265 }
266}
267
268
269Operand::Operand(Register index,
270 ScaleFactor scale,
271 int32_t disp,
272 RelocInfo::Mode rmode) {
273 ASSERT(!index.is(esp)); // illegal addressing mode
274 // [index*scale + disp/r]
275 set_modrm(0, esp);
276 set_sib(scale, index, ebp);
277 set_dispr(disp, rmode);
278}
279
280
281bool Operand::is_reg(Register reg) const {
282 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only.
283 && ((buf_[0] & 0x07) == reg.code()); // register codes match.
284}
285
286// -----------------------------------------------------------------------------
Andrei Popescu31002712010-02-23 13:46:05 +0000287// Implementation of Assembler.
Steve Blocka7e24c12009-10-30 11:49:00 +0000288
289// Emit a single byte. Must always be inlined.
290#define EMIT(x) \
291 *pc_++ = (x)
292
293
294#ifdef GENERATED_CODE_COVERAGE
295static void InitCoverageLog();
296#endif
297
Andrei Popescu31002712010-02-23 13:46:05 +0000298// Spare buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +0000299byte* Assembler::spare_buffer_ = NULL;
300
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800301Assembler::Assembler(void* buffer, int buffer_size)
302 : positions_recorder_(this) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000303 if (buffer == NULL) {
Andrei Popescu31002712010-02-23 13:46:05 +0000304 // Do our own buffer management.
Steve Blocka7e24c12009-10-30 11:49:00 +0000305 if (buffer_size <= kMinimalBufferSize) {
306 buffer_size = kMinimalBufferSize;
307
308 if (spare_buffer_ != NULL) {
309 buffer = spare_buffer_;
310 spare_buffer_ = NULL;
311 }
312 }
313 if (buffer == NULL) {
314 buffer_ = NewArray<byte>(buffer_size);
315 } else {
316 buffer_ = static_cast<byte*>(buffer);
317 }
318 buffer_size_ = buffer_size;
319 own_buffer_ = true;
320 } else {
Andrei Popescu31002712010-02-23 13:46:05 +0000321 // Use externally provided buffer instead.
Steve Blocka7e24c12009-10-30 11:49:00 +0000322 ASSERT(buffer_size > 0);
323 buffer_ = static_cast<byte*>(buffer);
324 buffer_size_ = buffer_size;
325 own_buffer_ = false;
326 }
327
328 // Clear the buffer in debug mode unless it was provided by the
329 // caller in which case we can't be sure it's okay to overwrite
330 // existing code in it; see CodePatcher::CodePatcher(...).
331#ifdef DEBUG
332 if (own_buffer_) {
333 memset(buffer_, 0xCC, buffer_size); // int3
334 }
335#endif
336
Andrei Popescu31002712010-02-23 13:46:05 +0000337 // Setup buffer pointers.
Steve Blocka7e24c12009-10-30 11:49:00 +0000338 ASSERT(buffer_ != NULL);
339 pc_ = buffer_;
340 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
341
342 last_pc_ = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000343#ifdef GENERATED_CODE_COVERAGE
344 InitCoverageLog();
345#endif
346}
347
348
349Assembler::~Assembler() {
350 if (own_buffer_) {
351 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
352 spare_buffer_ = buffer_;
353 } else {
354 DeleteArray(buffer_);
355 }
356 }
357}
358
359
360void Assembler::GetCode(CodeDesc* desc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000361 // Finalize code (at this point overflow() may be true, but the gap ensures
362 // that we are still not overlapping instructions and relocation info).
363 ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap.
364 // Setup code descriptor.
Steve Blocka7e24c12009-10-30 11:49:00 +0000365 desc->buffer = buffer_;
366 desc->buffer_size = buffer_size_;
367 desc->instr_size = pc_offset();
368 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
369 desc->origin = this;
370
371 Counters::reloc_info_size.Increment(desc->reloc_size);
372}
373
374
375void Assembler::Align(int m) {
376 ASSERT(IsPowerOf2(m));
377 while ((pc_offset() & (m - 1)) != 0) {
378 nop();
379 }
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() {
Steve Blockd0582a62009-12-15 09:54:21 +0000389 ASSERT(CpuFeatures::IsEnabled(CPUID));
Steve Blocka7e24c12009-10-30 11:49:00 +0000390 EnsureSpace ensure_space(this);
391 last_pc_ = pc_;
392 EMIT(0x0F);
393 EMIT(0xA2);
394}
395
396
397void Assembler::pushad() {
398 EnsureSpace ensure_space(this);
399 last_pc_ = pc_;
400 EMIT(0x60);
401}
402
403
404void Assembler::popad() {
405 EnsureSpace ensure_space(this);
406 last_pc_ = pc_;
407 EMIT(0x61);
408}
409
410
411void Assembler::pushfd() {
412 EnsureSpace ensure_space(this);
413 last_pc_ = pc_;
414 EMIT(0x9C);
415}
416
417
418void Assembler::popfd() {
419 EnsureSpace ensure_space(this);
420 last_pc_ = pc_;
421 EMIT(0x9D);
422}
423
424
425void Assembler::push(const Immediate& x) {
426 EnsureSpace ensure_space(this);
427 last_pc_ = pc_;
428 if (x.is_int8()) {
429 EMIT(0x6a);
430 EMIT(x.x_);
431 } else {
432 EMIT(0x68);
433 emit(x);
434 }
435}
436
437
438void Assembler::push(Register src) {
439 EnsureSpace ensure_space(this);
440 last_pc_ = pc_;
441 EMIT(0x50 | src.code());
442}
443
444
445void Assembler::push(const Operand& src) {
446 EnsureSpace ensure_space(this);
447 last_pc_ = pc_;
448 EMIT(0xFF);
449 emit_operand(esi, src);
450}
451
452
453void Assembler::pop(Register dst) {
454 ASSERT(reloc_info_writer.last_pc() != NULL);
Leon Clarkef7060e22010-06-03 12:02:55 +0100455 if (FLAG_peephole_optimization && (reloc_info_writer.last_pc() <= last_pc_)) {
Andrei Popescu31002712010-02-23 13:46:05 +0000456 // (last_pc_ != NULL) is rolled into the above check.
Steve Blocka7e24c12009-10-30 11:49:00 +0000457 // If a last_pc_ is set, we need to make sure that there has not been any
458 // relocation information generated between the last instruction and this
459 // pop instruction.
460 byte instr = last_pc_[0];
461 if ((instr & ~0x7) == 0x50) {
462 int push_reg_code = instr & 0x7;
463 if (push_reg_code == dst.code()) {
464 pc_ = last_pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +0100465 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000466 PrintF("%d push/pop (same reg) eliminated\n", pc_offset());
467 }
468 } else {
469 // Convert 'push src; pop dst' to 'mov dst, src'.
470 last_pc_[0] = 0x8b;
471 Register src = { push_reg_code };
472 EnsureSpace ensure_space(this);
473 emit_operand(dst, Operand(src));
Leon Clarkef7060e22010-06-03 12:02:55 +0100474 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000475 PrintF("%d push/pop (reg->reg) eliminated\n", pc_offset());
476 }
477 }
478 last_pc_ = NULL;
479 return;
480 } else if (instr == 0xff) { // push of an operand, convert to a move
481 byte op1 = last_pc_[1];
Andrei Popescu31002712010-02-23 13:46:05 +0000482 // Check if the operation is really a push.
Steve Blocka7e24c12009-10-30 11:49:00 +0000483 if ((op1 & 0x38) == (6 << 3)) {
484 op1 = (op1 & ~0x38) | static_cast<byte>(dst.code() << 3);
485 last_pc_[0] = 0x8b;
486 last_pc_[1] = op1;
487 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100488 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000489 PrintF("%d push/pop (op->reg) eliminated\n", pc_offset());
490 }
491 return;
492 }
493 } else if ((instr == 0x89) &&
494 (last_pc_[1] == 0x04) &&
495 (last_pc_[2] == 0x24)) {
496 // 0x71283c 396 890424 mov [esp],eax
497 // 0x71283f 399 58 pop eax
498 if (dst.is(eax)) {
499 // change to
500 // 0x710fac 216 83c404 add esp,0x4
501 last_pc_[0] = 0x83;
502 last_pc_[1] = 0xc4;
503 last_pc_[2] = 0x04;
504 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100505 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000506 PrintF("%d push/pop (mov-pop) eliminated\n", pc_offset());
507 }
508 return;
509 }
510 } else if (instr == 0x6a && dst.is(eax)) { // push of immediate 8 bit
511 byte imm8 = last_pc_[1];
512 if (imm8 == 0) {
513 // 6a00 push 0x0
514 // 58 pop eax
515 last_pc_[0] = 0x31;
516 last_pc_[1] = 0xc0;
517 // change to
518 // 31c0 xor eax,eax
519 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100520 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000521 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
522 }
523 return;
524 } else {
525 // 6a00 push 0xXX
526 // 58 pop eax
527 last_pc_[0] = 0xb8;
528 EnsureSpace ensure_space(this);
529 if ((imm8 & 0x80) != 0) {
530 EMIT(0xff);
531 EMIT(0xff);
532 EMIT(0xff);
533 // change to
534 // b8XXffffff mov eax,0xffffffXX
535 } else {
536 EMIT(0x00);
537 EMIT(0x00);
538 EMIT(0x00);
539 // change to
540 // b8XX000000 mov eax,0x000000XX
541 }
542 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100543 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000544 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
545 }
546 return;
547 }
548 } else if (instr == 0x68 && dst.is(eax)) { // push of immediate 32 bit
549 // 68XXXXXXXX push 0xXXXXXXXX
550 // 58 pop eax
551 last_pc_[0] = 0xb8;
552 last_pc_ = NULL;
553 // change to
554 // b8XXXXXXXX mov eax,0xXXXXXXXX
Leon Clarkef7060e22010-06-03 12:02:55 +0100555 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000556 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
557 }
558 return;
559 }
560
561 // Other potential patterns for peephole:
562 // 0x712716 102 890424 mov [esp], eax
563 // 0x712719 105 8b1424 mov edx, [esp]
564 }
565 EnsureSpace ensure_space(this);
566 last_pc_ = pc_;
567 EMIT(0x58 | dst.code());
568}
569
570
571void Assembler::pop(const Operand& dst) {
572 EnsureSpace ensure_space(this);
573 last_pc_ = pc_;
574 EMIT(0x8F);
575 emit_operand(eax, dst);
576}
577
578
579void Assembler::enter(const Immediate& size) {
580 EnsureSpace ensure_space(this);
581 last_pc_ = pc_;
582 EMIT(0xC8);
583 emit_w(size);
584 EMIT(0);
585}
586
587
588void Assembler::leave() {
589 EnsureSpace ensure_space(this);
590 last_pc_ = pc_;
591 EMIT(0xC9);
592}
593
594
595void Assembler::mov_b(Register dst, const Operand& src) {
Leon Clarkee46be812010-01-19 14:06:41 +0000596 ASSERT(dst.code() < 4);
Steve Blocka7e24c12009-10-30 11:49:00 +0000597 EnsureSpace ensure_space(this);
598 last_pc_ = pc_;
599 EMIT(0x8A);
600 emit_operand(dst, src);
601}
602
603
604void Assembler::mov_b(const Operand& dst, int8_t imm8) {
605 EnsureSpace ensure_space(this);
606 last_pc_ = pc_;
607 EMIT(0xC6);
608 emit_operand(eax, dst);
609 EMIT(imm8);
610}
611
612
613void Assembler::mov_b(const Operand& dst, Register src) {
Leon Clarkee46be812010-01-19 14:06:41 +0000614 ASSERT(src.code() < 4);
Steve Blocka7e24c12009-10-30 11:49:00 +0000615 EnsureSpace ensure_space(this);
616 last_pc_ = pc_;
617 EMIT(0x88);
618 emit_operand(src, dst);
619}
620
621
622void Assembler::mov_w(Register dst, const Operand& src) {
623 EnsureSpace ensure_space(this);
624 last_pc_ = pc_;
625 EMIT(0x66);
626 EMIT(0x8B);
627 emit_operand(dst, src);
628}
629
630
631void Assembler::mov_w(const Operand& dst, Register src) {
632 EnsureSpace ensure_space(this);
633 last_pc_ = pc_;
634 EMIT(0x66);
635 EMIT(0x89);
636 emit_operand(src, dst);
637}
638
639
640void Assembler::mov(Register dst, int32_t imm32) {
641 EnsureSpace ensure_space(this);
642 last_pc_ = pc_;
643 EMIT(0xB8 | dst.code());
644 emit(imm32);
645}
646
647
648void Assembler::mov(Register dst, const Immediate& x) {
649 EnsureSpace ensure_space(this);
650 last_pc_ = pc_;
651 EMIT(0xB8 | dst.code());
652 emit(x);
653}
654
655
656void Assembler::mov(Register dst, Handle<Object> handle) {
657 EnsureSpace ensure_space(this);
658 last_pc_ = pc_;
659 EMIT(0xB8 | dst.code());
660 emit(handle);
661}
662
663
664void Assembler::mov(Register dst, const Operand& src) {
665 EnsureSpace ensure_space(this);
666 last_pc_ = pc_;
667 EMIT(0x8B);
668 emit_operand(dst, src);
669}
670
671
672void Assembler::mov(Register dst, Register src) {
673 EnsureSpace ensure_space(this);
674 last_pc_ = pc_;
675 EMIT(0x89);
676 EMIT(0xC0 | src.code() << 3 | dst.code());
677}
678
679
680void Assembler::mov(const Operand& dst, const Immediate& x) {
681 EnsureSpace ensure_space(this);
682 last_pc_ = pc_;
683 EMIT(0xC7);
684 emit_operand(eax, dst);
685 emit(x);
686}
687
688
689void Assembler::mov(const Operand& dst, Handle<Object> handle) {
690 EnsureSpace ensure_space(this);
691 last_pc_ = pc_;
692 EMIT(0xC7);
693 emit_operand(eax, dst);
694 emit(handle);
695}
696
697
698void Assembler::mov(const Operand& dst, Register src) {
699 EnsureSpace ensure_space(this);
700 last_pc_ = pc_;
701 EMIT(0x89);
702 emit_operand(src, dst);
703}
704
705
706void Assembler::movsx_b(Register dst, const Operand& src) {
707 EnsureSpace ensure_space(this);
708 last_pc_ = pc_;
709 EMIT(0x0F);
710 EMIT(0xBE);
711 emit_operand(dst, src);
712}
713
714
715void Assembler::movsx_w(Register dst, const Operand& src) {
716 EnsureSpace ensure_space(this);
717 last_pc_ = pc_;
718 EMIT(0x0F);
719 EMIT(0xBF);
720 emit_operand(dst, src);
721}
722
723
724void Assembler::movzx_b(Register dst, const Operand& src) {
725 EnsureSpace ensure_space(this);
726 last_pc_ = pc_;
727 EMIT(0x0F);
728 EMIT(0xB6);
729 emit_operand(dst, src);
730}
731
732
733void Assembler::movzx_w(Register dst, const Operand& src) {
734 EnsureSpace ensure_space(this);
735 last_pc_ = pc_;
736 EMIT(0x0F);
737 EMIT(0xB7);
738 emit_operand(dst, src);
739}
740
741
742void Assembler::cmov(Condition cc, Register dst, int32_t imm32) {
Steve Blockd0582a62009-12-15 09:54:21 +0000743 ASSERT(CpuFeatures::IsEnabled(CMOV));
Steve Blocka7e24c12009-10-30 11:49:00 +0000744 EnsureSpace ensure_space(this);
745 last_pc_ = pc_;
746 UNIMPLEMENTED();
747 USE(cc);
748 USE(dst);
749 USE(imm32);
750}
751
752
753void Assembler::cmov(Condition cc, Register dst, Handle<Object> handle) {
Steve Blockd0582a62009-12-15 09:54:21 +0000754 ASSERT(CpuFeatures::IsEnabled(CMOV));
Steve Blocka7e24c12009-10-30 11:49:00 +0000755 EnsureSpace ensure_space(this);
756 last_pc_ = pc_;
757 UNIMPLEMENTED();
758 USE(cc);
759 USE(dst);
760 USE(handle);
761}
762
763
764void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +0000765 ASSERT(CpuFeatures::IsEnabled(CMOV));
Steve Blocka7e24c12009-10-30 11:49:00 +0000766 EnsureSpace ensure_space(this);
767 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000768 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000769 EMIT(0x0F);
770 EMIT(0x40 + cc);
771 emit_operand(dst, src);
772}
773
774
Steve Block6ded16b2010-05-10 14:33:55 +0100775void Assembler::cld() {
776 EnsureSpace ensure_space(this);
777 last_pc_ = pc_;
778 EMIT(0xFC);
779}
780
781
Leon Clarkee46be812010-01-19 14:06:41 +0000782void Assembler::rep_movs() {
783 EnsureSpace ensure_space(this);
784 last_pc_ = pc_;
785 EMIT(0xF3);
786 EMIT(0xA5);
787}
788
789
Steve Block6ded16b2010-05-10 14:33:55 +0100790void Assembler::rep_stos() {
791 EnsureSpace ensure_space(this);
792 last_pc_ = pc_;
793 EMIT(0xF3);
794 EMIT(0xAB);
795}
796
797
Leon Clarkef7060e22010-06-03 12:02:55 +0100798void Assembler::stos() {
799 EnsureSpace ensure_space(this);
800 last_pc_ = pc_;
801 EMIT(0xAB);
802}
803
804
Steve Blocka7e24c12009-10-30 11:49:00 +0000805void Assembler::xchg(Register dst, Register src) {
806 EnsureSpace ensure_space(this);
807 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000808 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding.
Steve Blocka7e24c12009-10-30 11:49:00 +0000809 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code()));
810 } else {
811 EMIT(0x87);
812 EMIT(0xC0 | src.code() << 3 | dst.code());
813 }
814}
815
816
817void Assembler::adc(Register dst, int32_t imm32) {
818 EnsureSpace ensure_space(this);
819 last_pc_ = pc_;
820 emit_arith(2, Operand(dst), Immediate(imm32));
821}
822
823
824void Assembler::adc(Register dst, const Operand& src) {
825 EnsureSpace ensure_space(this);
826 last_pc_ = pc_;
827 EMIT(0x13);
828 emit_operand(dst, src);
829}
830
831
832void Assembler::add(Register dst, const Operand& src) {
833 EnsureSpace ensure_space(this);
834 last_pc_ = pc_;
835 EMIT(0x03);
836 emit_operand(dst, src);
837}
838
839
840void Assembler::add(const Operand& dst, const Immediate& x) {
841 ASSERT(reloc_info_writer.last_pc() != NULL);
Leon Clarkef7060e22010-06-03 12:02:55 +0100842 if (FLAG_peephole_optimization && (reloc_info_writer.last_pc() <= last_pc_)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000843 byte instr = last_pc_[0];
844 if ((instr & 0xf8) == 0x50) {
845 // Last instruction was a push. Check whether this is a pop without a
846 // result.
847 if ((dst.is_reg(esp)) &&
848 (x.x_ == kPointerSize) && (x.rmode_ == RelocInfo::NONE)) {
849 pc_ = last_pc_;
850 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100851 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000852 PrintF("%d push/pop(noreg) eliminated\n", pc_offset());
853 }
854 return;
855 }
856 }
857 }
858 EnsureSpace ensure_space(this);
859 last_pc_ = pc_;
860 emit_arith(0, dst, x);
861}
862
863
864void Assembler::and_(Register dst, int32_t imm32) {
Steve Block59151502010-09-22 15:07:15 +0100865 and_(dst, Immediate(imm32));
866}
867
868
869void Assembler::and_(Register dst, const Immediate& x) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000870 EnsureSpace ensure_space(this);
871 last_pc_ = pc_;
Steve Block59151502010-09-22 15:07:15 +0100872 emit_arith(4, Operand(dst), x);
Steve Blocka7e24c12009-10-30 11:49:00 +0000873}
874
875
876void Assembler::and_(Register dst, const Operand& src) {
877 EnsureSpace ensure_space(this);
878 last_pc_ = pc_;
879 EMIT(0x23);
880 emit_operand(dst, src);
881}
882
883
884void Assembler::and_(const Operand& dst, const Immediate& x) {
885 EnsureSpace ensure_space(this);
886 last_pc_ = pc_;
887 emit_arith(4, dst, x);
888}
889
890
891void Assembler::and_(const Operand& dst, Register src) {
892 EnsureSpace ensure_space(this);
893 last_pc_ = pc_;
894 EMIT(0x21);
895 emit_operand(src, dst);
896}
897
898
899void Assembler::cmpb(const Operand& op, int8_t imm8) {
900 EnsureSpace ensure_space(this);
901 last_pc_ = pc_;
902 EMIT(0x80);
903 emit_operand(edi, op); // edi == 7
904 EMIT(imm8);
905}
906
907
Leon Clarked91b9f72010-01-27 17:25:45 +0000908void Assembler::cmpb(const Operand& dst, Register src) {
909 ASSERT(src.is_byte_register());
910 EnsureSpace ensure_space(this);
911 last_pc_ = pc_;
912 EMIT(0x38);
913 emit_operand(src, dst);
914}
915
916
917void Assembler::cmpb(Register dst, const Operand& src) {
918 ASSERT(dst.is_byte_register());
919 EnsureSpace ensure_space(this);
920 last_pc_ = pc_;
921 EMIT(0x3A);
922 emit_operand(dst, src);
923}
924
925
Steve Blocka7e24c12009-10-30 11:49:00 +0000926void Assembler::cmpw(const Operand& op, Immediate imm16) {
927 ASSERT(imm16.is_int16());
928 EnsureSpace ensure_space(this);
929 last_pc_ = pc_;
930 EMIT(0x66);
931 EMIT(0x81);
932 emit_operand(edi, op);
933 emit_w(imm16);
934}
935
936
937void Assembler::cmp(Register reg, int32_t imm32) {
938 EnsureSpace ensure_space(this);
939 last_pc_ = pc_;
940 emit_arith(7, Operand(reg), Immediate(imm32));
941}
942
943
944void Assembler::cmp(Register reg, Handle<Object> handle) {
945 EnsureSpace ensure_space(this);
946 last_pc_ = pc_;
947 emit_arith(7, Operand(reg), Immediate(handle));
948}
949
950
951void Assembler::cmp(Register reg, const Operand& op) {
952 EnsureSpace ensure_space(this);
953 last_pc_ = pc_;
954 EMIT(0x3B);
955 emit_operand(reg, op);
956}
957
958
959void Assembler::cmp(const Operand& op, const Immediate& imm) {
960 EnsureSpace ensure_space(this);
961 last_pc_ = pc_;
962 emit_arith(7, op, imm);
963}
964
965
966void Assembler::cmp(const Operand& op, Handle<Object> handle) {
967 EnsureSpace ensure_space(this);
968 last_pc_ = pc_;
969 emit_arith(7, op, Immediate(handle));
970}
971
972
973void Assembler::cmpb_al(const Operand& op) {
974 EnsureSpace ensure_space(this);
975 last_pc_ = pc_;
976 EMIT(0x38); // CMP r/m8, r8
977 emit_operand(eax, op); // eax has same code as register al.
978}
979
980
981void Assembler::cmpw_ax(const Operand& op) {
982 EnsureSpace ensure_space(this);
983 last_pc_ = pc_;
984 EMIT(0x66);
985 EMIT(0x39); // CMP r/m16, r16
986 emit_operand(eax, op); // eax has same code as register ax.
987}
988
989
990void Assembler::dec_b(Register dst) {
991 EnsureSpace ensure_space(this);
992 last_pc_ = pc_;
993 EMIT(0xFE);
994 EMIT(0xC8 | dst.code());
995}
996
997
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100998void Assembler::dec_b(const Operand& dst) {
999 EnsureSpace ensure_space(this);
1000 last_pc_ = pc_;
1001 EMIT(0xFE);
1002 emit_operand(ecx, dst);
1003}
1004
1005
Steve Blocka7e24c12009-10-30 11:49:00 +00001006void Assembler::dec(Register dst) {
1007 EnsureSpace ensure_space(this);
1008 last_pc_ = pc_;
1009 EMIT(0x48 | dst.code());
1010}
1011
1012
1013void Assembler::dec(const Operand& dst) {
1014 EnsureSpace ensure_space(this);
1015 last_pc_ = pc_;
1016 EMIT(0xFF);
1017 emit_operand(ecx, dst);
1018}
1019
1020
1021void Assembler::cdq() {
1022 EnsureSpace ensure_space(this);
1023 last_pc_ = pc_;
1024 EMIT(0x99);
1025}
1026
1027
1028void Assembler::idiv(Register src) {
1029 EnsureSpace ensure_space(this);
1030 last_pc_ = pc_;
1031 EMIT(0xF7);
1032 EMIT(0xF8 | src.code());
1033}
1034
1035
1036void Assembler::imul(Register reg) {
1037 EnsureSpace ensure_space(this);
1038 last_pc_ = pc_;
1039 EMIT(0xF7);
1040 EMIT(0xE8 | reg.code());
1041}
1042
1043
1044void Assembler::imul(Register dst, const Operand& src) {
1045 EnsureSpace ensure_space(this);
1046 last_pc_ = pc_;
1047 EMIT(0x0F);
1048 EMIT(0xAF);
1049 emit_operand(dst, src);
1050}
1051
1052
1053void Assembler::imul(Register dst, Register src, int32_t imm32) {
1054 EnsureSpace ensure_space(this);
1055 last_pc_ = pc_;
1056 if (is_int8(imm32)) {
1057 EMIT(0x6B);
1058 EMIT(0xC0 | dst.code() << 3 | src.code());
1059 EMIT(imm32);
1060 } else {
1061 EMIT(0x69);
1062 EMIT(0xC0 | dst.code() << 3 | src.code());
1063 emit(imm32);
1064 }
1065}
1066
1067
1068void Assembler::inc(Register dst) {
1069 EnsureSpace ensure_space(this);
1070 last_pc_ = pc_;
1071 EMIT(0x40 | dst.code());
1072}
1073
1074
1075void Assembler::inc(const Operand& dst) {
1076 EnsureSpace ensure_space(this);
1077 last_pc_ = pc_;
1078 EMIT(0xFF);
1079 emit_operand(eax, dst);
1080}
1081
1082
1083void Assembler::lea(Register dst, const Operand& src) {
1084 EnsureSpace ensure_space(this);
1085 last_pc_ = pc_;
1086 EMIT(0x8D);
1087 emit_operand(dst, src);
1088}
1089
1090
1091void Assembler::mul(Register src) {
1092 EnsureSpace ensure_space(this);
1093 last_pc_ = pc_;
1094 EMIT(0xF7);
1095 EMIT(0xE0 | src.code());
1096}
1097
1098
1099void Assembler::neg(Register dst) {
1100 EnsureSpace ensure_space(this);
1101 last_pc_ = pc_;
1102 EMIT(0xF7);
1103 EMIT(0xD8 | dst.code());
1104}
1105
1106
1107void Assembler::not_(Register dst) {
1108 EnsureSpace ensure_space(this);
1109 last_pc_ = pc_;
1110 EMIT(0xF7);
1111 EMIT(0xD0 | dst.code());
1112}
1113
1114
1115void Assembler::or_(Register dst, int32_t imm32) {
1116 EnsureSpace ensure_space(this);
1117 last_pc_ = pc_;
1118 emit_arith(1, Operand(dst), Immediate(imm32));
1119}
1120
1121
1122void Assembler::or_(Register dst, const Operand& src) {
1123 EnsureSpace ensure_space(this);
1124 last_pc_ = pc_;
1125 EMIT(0x0B);
1126 emit_operand(dst, src);
1127}
1128
1129
1130void Assembler::or_(const Operand& dst, const Immediate& x) {
1131 EnsureSpace ensure_space(this);
1132 last_pc_ = pc_;
1133 emit_arith(1, dst, x);
1134}
1135
1136
1137void Assembler::or_(const Operand& dst, Register src) {
1138 EnsureSpace ensure_space(this);
1139 last_pc_ = pc_;
1140 EMIT(0x09);
1141 emit_operand(src, dst);
1142}
1143
1144
1145void Assembler::rcl(Register dst, uint8_t imm8) {
1146 EnsureSpace ensure_space(this);
1147 last_pc_ = pc_;
1148 ASSERT(is_uint5(imm8)); // illegal shift count
1149 if (imm8 == 1) {
1150 EMIT(0xD1);
1151 EMIT(0xD0 | dst.code());
1152 } else {
1153 EMIT(0xC1);
1154 EMIT(0xD0 | dst.code());
1155 EMIT(imm8);
1156 }
1157}
1158
1159
Iain Merrick75681382010-08-19 15:07:18 +01001160void Assembler::rcr(Register dst, uint8_t imm8) {
1161 EnsureSpace ensure_space(this);
1162 last_pc_ = pc_;
1163 ASSERT(is_uint5(imm8)); // illegal shift count
1164 if (imm8 == 1) {
1165 EMIT(0xD1);
1166 EMIT(0xD8 | dst.code());
1167 } else {
1168 EMIT(0xC1);
1169 EMIT(0xD8 | dst.code());
1170 EMIT(imm8);
1171 }
1172}
1173
1174
Steve Blocka7e24c12009-10-30 11:49:00 +00001175void Assembler::sar(Register dst, uint8_t imm8) {
1176 EnsureSpace ensure_space(this);
1177 last_pc_ = pc_;
1178 ASSERT(is_uint5(imm8)); // illegal shift count
1179 if (imm8 == 1) {
1180 EMIT(0xD1);
1181 EMIT(0xF8 | dst.code());
1182 } else {
1183 EMIT(0xC1);
1184 EMIT(0xF8 | dst.code());
1185 EMIT(imm8);
1186 }
1187}
1188
1189
Steve Blockd0582a62009-12-15 09:54:21 +00001190void Assembler::sar_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001191 EnsureSpace ensure_space(this);
1192 last_pc_ = pc_;
1193 EMIT(0xD3);
1194 EMIT(0xF8 | dst.code());
1195}
1196
1197
1198void Assembler::sbb(Register dst, const Operand& src) {
1199 EnsureSpace ensure_space(this);
1200 last_pc_ = pc_;
1201 EMIT(0x1B);
1202 emit_operand(dst, src);
1203}
1204
1205
1206void Assembler::shld(Register dst, const Operand& src) {
1207 EnsureSpace ensure_space(this);
1208 last_pc_ = pc_;
1209 EMIT(0x0F);
1210 EMIT(0xA5);
1211 emit_operand(dst, src);
1212}
1213
1214
1215void Assembler::shl(Register dst, uint8_t imm8) {
1216 EnsureSpace ensure_space(this);
1217 last_pc_ = pc_;
1218 ASSERT(is_uint5(imm8)); // illegal shift count
1219 if (imm8 == 1) {
1220 EMIT(0xD1);
1221 EMIT(0xE0 | dst.code());
1222 } else {
1223 EMIT(0xC1);
1224 EMIT(0xE0 | dst.code());
1225 EMIT(imm8);
1226 }
1227}
1228
1229
Steve Blockd0582a62009-12-15 09:54:21 +00001230void Assembler::shl_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001231 EnsureSpace ensure_space(this);
1232 last_pc_ = pc_;
1233 EMIT(0xD3);
1234 EMIT(0xE0 | dst.code());
1235}
1236
1237
1238void Assembler::shrd(Register dst, const Operand& src) {
1239 EnsureSpace ensure_space(this);
1240 last_pc_ = pc_;
1241 EMIT(0x0F);
1242 EMIT(0xAD);
1243 emit_operand(dst, src);
1244}
1245
1246
1247void Assembler::shr(Register dst, uint8_t imm8) {
1248 EnsureSpace ensure_space(this);
1249 last_pc_ = pc_;
1250 ASSERT(is_uint5(imm8)); // illegal shift count
Steve Blockd0582a62009-12-15 09:54:21 +00001251 if (imm8 == 1) {
1252 EMIT(0xD1);
1253 EMIT(0xE8 | dst.code());
1254 } else {
1255 EMIT(0xC1);
1256 EMIT(0xE8 | dst.code());
1257 EMIT(imm8);
1258 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001259}
1260
1261
1262void Assembler::shr_cl(Register dst) {
1263 EnsureSpace ensure_space(this);
1264 last_pc_ = pc_;
Steve Blockd0582a62009-12-15 09:54:21 +00001265 EMIT(0xD3);
Steve Blocka7e24c12009-10-30 11:49:00 +00001266 EMIT(0xE8 | dst.code());
1267}
1268
1269
Steve Block3ce2e202009-11-05 08:53:23 +00001270void Assembler::subb(const Operand& op, int8_t imm8) {
1271 EnsureSpace ensure_space(this);
1272 last_pc_ = pc_;
1273 if (op.is_reg(eax)) {
1274 EMIT(0x2c);
1275 } else {
1276 EMIT(0x80);
1277 emit_operand(ebp, op); // ebp == 5
1278 }
1279 EMIT(imm8);
1280}
1281
1282
Steve Blocka7e24c12009-10-30 11:49:00 +00001283void Assembler::sub(const Operand& dst, const Immediate& x) {
1284 EnsureSpace ensure_space(this);
1285 last_pc_ = pc_;
1286 emit_arith(5, dst, x);
1287}
1288
1289
1290void Assembler::sub(Register dst, const Operand& src) {
1291 EnsureSpace ensure_space(this);
1292 last_pc_ = pc_;
1293 EMIT(0x2B);
1294 emit_operand(dst, src);
1295}
1296
1297
Leon Clarkee46be812010-01-19 14:06:41 +00001298void Assembler::subb(Register dst, const Operand& src) {
1299 ASSERT(dst.code() < 4);
1300 EnsureSpace ensure_space(this);
1301 last_pc_ = pc_;
1302 EMIT(0x2A);
1303 emit_operand(dst, src);
1304}
1305
1306
Steve Blocka7e24c12009-10-30 11:49:00 +00001307void Assembler::sub(const Operand& dst, Register src) {
1308 EnsureSpace ensure_space(this);
1309 last_pc_ = pc_;
1310 EMIT(0x29);
1311 emit_operand(src, dst);
1312}
1313
1314
1315void Assembler::test(Register reg, const Immediate& imm) {
1316 EnsureSpace ensure_space(this);
1317 last_pc_ = pc_;
1318 // Only use test against byte for registers that have a byte
1319 // variant: eax, ebx, ecx, and edx.
1320 if (imm.rmode_ == RelocInfo::NONE && is_uint8(imm.x_) && reg.code() < 4) {
1321 uint8_t imm8 = imm.x_;
1322 if (reg.is(eax)) {
1323 EMIT(0xA8);
1324 EMIT(imm8);
1325 } else {
1326 emit_arith_b(0xF6, 0xC0, reg, imm8);
1327 }
1328 } else {
1329 // This is not using emit_arith because test doesn't support
1330 // sign-extension of 8-bit operands.
1331 if (reg.is(eax)) {
1332 EMIT(0xA9);
1333 } else {
1334 EMIT(0xF7);
1335 EMIT(0xC0 | reg.code());
1336 }
1337 emit(imm);
1338 }
1339}
1340
1341
1342void Assembler::test(Register reg, const Operand& op) {
1343 EnsureSpace ensure_space(this);
1344 last_pc_ = pc_;
1345 EMIT(0x85);
1346 emit_operand(reg, op);
1347}
1348
1349
Leon Clarkee46be812010-01-19 14:06:41 +00001350void Assembler::test_b(Register reg, const Operand& op) {
1351 EnsureSpace ensure_space(this);
1352 last_pc_ = pc_;
1353 EMIT(0x84);
1354 emit_operand(reg, op);
1355}
1356
1357
Steve Blocka7e24c12009-10-30 11:49:00 +00001358void Assembler::test(const Operand& op, const Immediate& imm) {
1359 EnsureSpace ensure_space(this);
1360 last_pc_ = pc_;
1361 EMIT(0xF7);
1362 emit_operand(eax, op);
1363 emit(imm);
1364}
1365
1366
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001367void Assembler::test_b(const Operand& op, uint8_t imm8) {
1368 EnsureSpace ensure_space(this);
1369 last_pc_ = pc_;
1370 EMIT(0xF6);
1371 emit_operand(eax, op);
1372 EMIT(imm8);
1373}
1374
1375
Steve Blocka7e24c12009-10-30 11:49:00 +00001376void Assembler::xor_(Register dst, int32_t imm32) {
1377 EnsureSpace ensure_space(this);
1378 last_pc_ = pc_;
1379 emit_arith(6, Operand(dst), Immediate(imm32));
1380}
1381
1382
1383void Assembler::xor_(Register dst, const Operand& src) {
1384 EnsureSpace ensure_space(this);
1385 last_pc_ = pc_;
1386 EMIT(0x33);
1387 emit_operand(dst, src);
1388}
1389
1390
1391void Assembler::xor_(const Operand& src, Register dst) {
1392 EnsureSpace ensure_space(this);
1393 last_pc_ = pc_;
1394 EMIT(0x31);
1395 emit_operand(dst, src);
1396}
1397
1398
1399void Assembler::xor_(const Operand& dst, const Immediate& x) {
1400 EnsureSpace ensure_space(this);
1401 last_pc_ = pc_;
1402 emit_arith(6, dst, x);
1403}
1404
1405
1406void Assembler::bt(const Operand& dst, Register src) {
1407 EnsureSpace ensure_space(this);
1408 last_pc_ = pc_;
1409 EMIT(0x0F);
1410 EMIT(0xA3);
1411 emit_operand(src, dst);
1412}
1413
1414
1415void Assembler::bts(const Operand& dst, Register src) {
1416 EnsureSpace ensure_space(this);
1417 last_pc_ = pc_;
1418 EMIT(0x0F);
1419 EMIT(0xAB);
1420 emit_operand(src, dst);
1421}
1422
1423
1424void Assembler::hlt() {
1425 EnsureSpace ensure_space(this);
1426 last_pc_ = pc_;
1427 EMIT(0xF4);
1428}
1429
1430
1431void Assembler::int3() {
1432 EnsureSpace ensure_space(this);
1433 last_pc_ = pc_;
1434 EMIT(0xCC);
1435}
1436
1437
1438void Assembler::nop() {
1439 EnsureSpace ensure_space(this);
1440 last_pc_ = pc_;
1441 EMIT(0x90);
1442}
1443
1444
1445void Assembler::rdtsc() {
Steve Blockd0582a62009-12-15 09:54:21 +00001446 ASSERT(CpuFeatures::IsEnabled(RDTSC));
Steve Blocka7e24c12009-10-30 11:49:00 +00001447 EnsureSpace ensure_space(this);
1448 last_pc_ = pc_;
1449 EMIT(0x0F);
1450 EMIT(0x31);
1451}
1452
1453
1454void Assembler::ret(int imm16) {
1455 EnsureSpace ensure_space(this);
1456 last_pc_ = pc_;
1457 ASSERT(is_uint16(imm16));
1458 if (imm16 == 0) {
1459 EMIT(0xC3);
1460 } else {
1461 EMIT(0xC2);
1462 EMIT(imm16 & 0xFF);
1463 EMIT((imm16 >> 8) & 0xFF);
1464 }
1465}
1466
1467
1468// Labels refer to positions in the (to be) generated code.
1469// There are bound, linked, and unused labels.
1470//
1471// Bound labels refer to known positions in the already
1472// generated code. pos() is the position the label refers to.
1473//
1474// Linked labels refer to unknown positions in the code
1475// to be generated; pos() is the position of the 32bit
1476// Displacement of the last instruction using the label.
1477
1478
1479void Assembler::print(Label* L) {
1480 if (L->is_unused()) {
1481 PrintF("unused label\n");
1482 } else if (L->is_bound()) {
1483 PrintF("bound label to %d\n", L->pos());
1484 } else if (L->is_linked()) {
1485 Label l = *L;
1486 PrintF("unbound label");
1487 while (l.is_linked()) {
1488 Displacement disp = disp_at(&l);
1489 PrintF("@ %d ", l.pos());
1490 disp.print();
1491 PrintF("\n");
1492 disp.next(&l);
1493 }
1494 } else {
1495 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
1496 }
1497}
1498
1499
1500void Assembler::bind_to(Label* L, int pos) {
1501 EnsureSpace ensure_space(this);
1502 last_pc_ = NULL;
1503 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position
1504 while (L->is_linked()) {
1505 Displacement disp = disp_at(L);
1506 int fixup_pos = L->pos();
1507 if (disp.type() == Displacement::CODE_RELATIVE) {
1508 // Relative to Code* heap object pointer.
1509 long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
1510 } else {
1511 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
1512 ASSERT(byte_at(fixup_pos - 1) == 0xE9); // jmp expected
1513 }
Andrei Popescu31002712010-02-23 13:46:05 +00001514 // Relative address, relative to point after address.
Steve Blocka7e24c12009-10-30 11:49:00 +00001515 int imm32 = pos - (fixup_pos + sizeof(int32_t));
1516 long_at_put(fixup_pos, imm32);
1517 }
1518 disp.next(L);
1519 }
1520 L->bind_to(pos);
1521}
1522
1523
Steve Blocka7e24c12009-10-30 11:49:00 +00001524void Assembler::bind(Label* L) {
1525 EnsureSpace ensure_space(this);
1526 last_pc_ = NULL;
1527 ASSERT(!L->is_bound()); // label can only be bound once
1528 bind_to(L, pc_offset());
1529}
1530
1531
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001532void Assembler::bind(NearLabel* L) {
1533 ASSERT(!L->is_bound());
1534 last_pc_ = NULL;
1535 while (L->unresolved_branches_ > 0) {
1536 int branch_pos = L->unresolved_positions_[L->unresolved_branches_ - 1];
1537 int disp = pc_offset() - branch_pos;
1538 ASSERT(is_int8(disp));
1539 set_byte_at(branch_pos - sizeof(int8_t), disp);
1540 L->unresolved_branches_--;
1541 }
1542 L->bind_to(pc_offset());
1543}
1544
Steve Blocka7e24c12009-10-30 11:49:00 +00001545void Assembler::call(Label* L) {
1546 EnsureSpace ensure_space(this);
1547 last_pc_ = pc_;
1548 if (L->is_bound()) {
1549 const int long_size = 5;
1550 int offs = L->pos() - pc_offset();
1551 ASSERT(offs <= 0);
Andrei Popescu31002712010-02-23 13:46:05 +00001552 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001553 EMIT(0xE8);
1554 emit(offs - long_size);
1555 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001556 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001557 EMIT(0xE8);
1558 emit_disp(L, Displacement::OTHER);
1559 }
1560}
1561
1562
1563void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
1564 EnsureSpace ensure_space(this);
1565 last_pc_ = pc_;
1566 ASSERT(!RelocInfo::IsCodeTarget(rmode));
1567 EMIT(0xE8);
1568 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1569}
1570
1571
1572void Assembler::call(const Operand& adr) {
1573 EnsureSpace ensure_space(this);
1574 last_pc_ = pc_;
1575 EMIT(0xFF);
1576 emit_operand(edx, adr);
1577}
1578
1579
1580void Assembler::call(Handle<Code> code, RelocInfo::Mode rmode) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001581 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001582 EnsureSpace ensure_space(this);
1583 last_pc_ = pc_;
1584 ASSERT(RelocInfo::IsCodeTarget(rmode));
1585 EMIT(0xE8);
1586 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
1587}
1588
1589
1590void Assembler::jmp(Label* L) {
1591 EnsureSpace ensure_space(this);
1592 last_pc_ = pc_;
1593 if (L->is_bound()) {
1594 const int short_size = 2;
1595 const int long_size = 5;
1596 int offs = L->pos() - pc_offset();
1597 ASSERT(offs <= 0);
1598 if (is_int8(offs - short_size)) {
Andrei Popescu31002712010-02-23 13:46:05 +00001599 // 1110 1011 #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001600 EMIT(0xEB);
1601 EMIT((offs - short_size) & 0xFF);
1602 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001603 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001604 EMIT(0xE9);
1605 emit(offs - long_size);
1606 }
1607 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001608 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001609 EMIT(0xE9);
1610 emit_disp(L, Displacement::UNCONDITIONAL_JUMP);
1611 }
1612}
1613
1614
1615void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
1616 EnsureSpace ensure_space(this);
1617 last_pc_ = pc_;
1618 ASSERT(!RelocInfo::IsCodeTarget(rmode));
1619 EMIT(0xE9);
1620 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1621}
1622
1623
1624void Assembler::jmp(const Operand& adr) {
1625 EnsureSpace ensure_space(this);
1626 last_pc_ = pc_;
1627 EMIT(0xFF);
1628 emit_operand(esp, adr);
1629}
1630
1631
1632void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
1633 EnsureSpace ensure_space(this);
1634 last_pc_ = pc_;
1635 ASSERT(RelocInfo::IsCodeTarget(rmode));
1636 EMIT(0xE9);
1637 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
1638}
1639
1640
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001641void Assembler::jmp(NearLabel* L) {
1642 EnsureSpace ensure_space(this);
1643 last_pc_ = pc_;
1644 if (L->is_bound()) {
1645 const int short_size = 2;
1646 int offs = L->pos() - pc_offset();
1647 ASSERT(offs <= 0);
1648 ASSERT(is_int8(offs - short_size));
1649 // 1110 1011 #8-bit disp.
1650 EMIT(0xEB);
1651 EMIT((offs - short_size) & 0xFF);
1652 } else {
1653 EMIT(0xEB);
1654 EMIT(0x00); // The displacement will be resolved later.
1655 L->link_to(pc_offset());
1656 }
1657}
1658
Steve Blocka7e24c12009-10-30 11:49:00 +00001659
1660void Assembler::j(Condition cc, Label* L, Hint hint) {
1661 EnsureSpace ensure_space(this);
1662 last_pc_ = pc_;
1663 ASSERT(0 <= cc && cc < 16);
1664 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1665 if (L->is_bound()) {
1666 const int short_size = 2;
1667 const int long_size = 6;
1668 int offs = L->pos() - pc_offset();
1669 ASSERT(offs <= 0);
1670 if (is_int8(offs - short_size)) {
1671 // 0111 tttn #8-bit disp
1672 EMIT(0x70 | cc);
1673 EMIT((offs - short_size) & 0xFF);
1674 } else {
1675 // 0000 1111 1000 tttn #32-bit disp
1676 EMIT(0x0F);
1677 EMIT(0x80 | cc);
1678 emit(offs - long_size);
1679 }
1680 } else {
1681 // 0000 1111 1000 tttn #32-bit disp
1682 // Note: could eliminate cond. jumps to this jump if condition
1683 // is the same however, seems to be rather unlikely case.
1684 EMIT(0x0F);
1685 EMIT(0x80 | cc);
1686 emit_disp(L, Displacement::OTHER);
1687 }
1688}
1689
1690
1691void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint) {
1692 EnsureSpace ensure_space(this);
1693 last_pc_ = pc_;
1694 ASSERT((0 <= cc) && (cc < 16));
1695 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
Andrei Popescu31002712010-02-23 13:46:05 +00001696 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001697 EMIT(0x0F);
1698 EMIT(0x80 | cc);
1699 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1700}
1701
1702
1703void Assembler::j(Condition cc, Handle<Code> code, Hint hint) {
1704 EnsureSpace ensure_space(this);
1705 last_pc_ = pc_;
1706 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1707 // 0000 1111 1000 tttn #32-bit disp
1708 EMIT(0x0F);
1709 EMIT(0x80 | cc);
1710 emit(reinterpret_cast<intptr_t>(code.location()), RelocInfo::CODE_TARGET);
1711}
1712
1713
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001714void Assembler::j(Condition cc, NearLabel* L, Hint hint) {
1715 EnsureSpace ensure_space(this);
1716 last_pc_ = pc_;
1717 ASSERT(0 <= cc && cc < 16);
1718 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1719 if (L->is_bound()) {
1720 const int short_size = 2;
1721 int offs = L->pos() - pc_offset();
1722 ASSERT(offs <= 0);
1723 ASSERT(is_int8(offs - short_size));
1724 // 0111 tttn #8-bit disp
1725 EMIT(0x70 | cc);
1726 EMIT((offs - short_size) & 0xFF);
1727 } else {
1728 EMIT(0x70 | cc);
1729 EMIT(0x00); // The displacement will be resolved later.
1730 L->link_to(pc_offset());
1731 }
1732}
1733
1734
Andrei Popescu31002712010-02-23 13:46:05 +00001735// FPU instructions.
Steve Blocka7e24c12009-10-30 11:49:00 +00001736
Steve Blocka7e24c12009-10-30 11:49:00 +00001737void Assembler::fld(int i) {
1738 EnsureSpace ensure_space(this);
1739 last_pc_ = pc_;
1740 emit_farith(0xD9, 0xC0, i);
1741}
1742
1743
Andrei Popescu402d9372010-02-26 13:31:12 +00001744void Assembler::fstp(int i) {
1745 EnsureSpace ensure_space(this);
1746 last_pc_ = pc_;
1747 emit_farith(0xDD, 0xD8, i);
1748}
1749
1750
Steve Blocka7e24c12009-10-30 11:49:00 +00001751void Assembler::fld1() {
1752 EnsureSpace ensure_space(this);
1753 last_pc_ = pc_;
1754 EMIT(0xD9);
1755 EMIT(0xE8);
1756}
1757
1758
Andrei Popescu402d9372010-02-26 13:31:12 +00001759void Assembler::fldpi() {
1760 EnsureSpace ensure_space(this);
1761 last_pc_ = pc_;
1762 EMIT(0xD9);
1763 EMIT(0xEB);
1764}
1765
1766
Steve Blocka7e24c12009-10-30 11:49:00 +00001767void Assembler::fldz() {
1768 EnsureSpace ensure_space(this);
1769 last_pc_ = pc_;
1770 EMIT(0xD9);
1771 EMIT(0xEE);
1772}
1773
1774
1775void Assembler::fld_s(const Operand& adr) {
1776 EnsureSpace ensure_space(this);
1777 last_pc_ = pc_;
1778 EMIT(0xD9);
1779 emit_operand(eax, adr);
1780}
1781
1782
1783void Assembler::fld_d(const Operand& adr) {
1784 EnsureSpace ensure_space(this);
1785 last_pc_ = pc_;
1786 EMIT(0xDD);
1787 emit_operand(eax, adr);
1788}
1789
1790
1791void Assembler::fstp_s(const Operand& adr) {
1792 EnsureSpace ensure_space(this);
1793 last_pc_ = pc_;
1794 EMIT(0xD9);
1795 emit_operand(ebx, adr);
1796}
1797
1798
1799void Assembler::fstp_d(const Operand& adr) {
1800 EnsureSpace ensure_space(this);
1801 last_pc_ = pc_;
1802 EMIT(0xDD);
1803 emit_operand(ebx, adr);
1804}
1805
1806
Andrei Popescu402d9372010-02-26 13:31:12 +00001807void Assembler::fst_d(const Operand& adr) {
1808 EnsureSpace ensure_space(this);
1809 last_pc_ = pc_;
1810 EMIT(0xDD);
1811 emit_operand(edx, adr);
1812}
1813
1814
Steve Blocka7e24c12009-10-30 11:49:00 +00001815void Assembler::fild_s(const Operand& adr) {
1816 EnsureSpace ensure_space(this);
1817 last_pc_ = pc_;
1818 EMIT(0xDB);
1819 emit_operand(eax, adr);
1820}
1821
1822
1823void Assembler::fild_d(const Operand& adr) {
1824 EnsureSpace ensure_space(this);
1825 last_pc_ = pc_;
1826 EMIT(0xDF);
1827 emit_operand(ebp, adr);
1828}
1829
1830
1831void Assembler::fistp_s(const Operand& adr) {
1832 EnsureSpace ensure_space(this);
1833 last_pc_ = pc_;
1834 EMIT(0xDB);
1835 emit_operand(ebx, adr);
1836}
1837
1838
1839void Assembler::fisttp_s(const Operand& adr) {
Steve Blockd0582a62009-12-15 09:54:21 +00001840 ASSERT(CpuFeatures::IsEnabled(SSE3));
Steve Blocka7e24c12009-10-30 11:49:00 +00001841 EnsureSpace ensure_space(this);
1842 last_pc_ = pc_;
1843 EMIT(0xDB);
1844 emit_operand(ecx, adr);
1845}
1846
1847
Leon Clarkee46be812010-01-19 14:06:41 +00001848void Assembler::fisttp_d(const Operand& adr) {
1849 ASSERT(CpuFeatures::IsEnabled(SSE3));
1850 EnsureSpace ensure_space(this);
1851 last_pc_ = pc_;
1852 EMIT(0xDD);
1853 emit_operand(ecx, adr);
1854}
1855
1856
Steve Blocka7e24c12009-10-30 11:49:00 +00001857void Assembler::fist_s(const Operand& adr) {
1858 EnsureSpace ensure_space(this);
1859 last_pc_ = pc_;
1860 EMIT(0xDB);
1861 emit_operand(edx, adr);
1862}
1863
1864
1865void Assembler::fistp_d(const Operand& adr) {
1866 EnsureSpace ensure_space(this);
1867 last_pc_ = pc_;
1868 EMIT(0xDF);
1869 emit_operand(edi, adr);
1870}
1871
1872
1873void Assembler::fabs() {
1874 EnsureSpace ensure_space(this);
1875 last_pc_ = pc_;
1876 EMIT(0xD9);
1877 EMIT(0xE1);
1878}
1879
1880
1881void Assembler::fchs() {
1882 EnsureSpace ensure_space(this);
1883 last_pc_ = pc_;
1884 EMIT(0xD9);
1885 EMIT(0xE0);
1886}
1887
1888
1889void Assembler::fcos() {
1890 EnsureSpace ensure_space(this);
1891 last_pc_ = pc_;
1892 EMIT(0xD9);
1893 EMIT(0xFF);
1894}
1895
1896
1897void Assembler::fsin() {
1898 EnsureSpace ensure_space(this);
1899 last_pc_ = pc_;
1900 EMIT(0xD9);
1901 EMIT(0xFE);
1902}
1903
1904
1905void Assembler::fadd(int i) {
1906 EnsureSpace ensure_space(this);
1907 last_pc_ = pc_;
1908 emit_farith(0xDC, 0xC0, i);
1909}
1910
1911
1912void Assembler::fsub(int i) {
1913 EnsureSpace ensure_space(this);
1914 last_pc_ = pc_;
1915 emit_farith(0xDC, 0xE8, i);
1916}
1917
1918
1919void Assembler::fisub_s(const Operand& adr) {
1920 EnsureSpace ensure_space(this);
1921 last_pc_ = pc_;
1922 EMIT(0xDA);
1923 emit_operand(esp, adr);
1924}
1925
1926
1927void Assembler::fmul(int i) {
1928 EnsureSpace ensure_space(this);
1929 last_pc_ = pc_;
1930 emit_farith(0xDC, 0xC8, i);
1931}
1932
1933
1934void Assembler::fdiv(int i) {
1935 EnsureSpace ensure_space(this);
1936 last_pc_ = pc_;
1937 emit_farith(0xDC, 0xF8, i);
1938}
1939
1940
1941void Assembler::faddp(int i) {
1942 EnsureSpace ensure_space(this);
1943 last_pc_ = pc_;
1944 emit_farith(0xDE, 0xC0, i);
1945}
1946
1947
1948void Assembler::fsubp(int i) {
1949 EnsureSpace ensure_space(this);
1950 last_pc_ = pc_;
1951 emit_farith(0xDE, 0xE8, i);
1952}
1953
1954
1955void Assembler::fsubrp(int i) {
1956 EnsureSpace ensure_space(this);
1957 last_pc_ = pc_;
1958 emit_farith(0xDE, 0xE0, i);
1959}
1960
1961
1962void Assembler::fmulp(int i) {
1963 EnsureSpace ensure_space(this);
1964 last_pc_ = pc_;
1965 emit_farith(0xDE, 0xC8, i);
1966}
1967
1968
1969void Assembler::fdivp(int i) {
1970 EnsureSpace ensure_space(this);
1971 last_pc_ = pc_;
1972 emit_farith(0xDE, 0xF8, i);
1973}
1974
1975
1976void Assembler::fprem() {
1977 EnsureSpace ensure_space(this);
1978 last_pc_ = pc_;
1979 EMIT(0xD9);
1980 EMIT(0xF8);
1981}
1982
1983
1984void Assembler::fprem1() {
1985 EnsureSpace ensure_space(this);
1986 last_pc_ = pc_;
1987 EMIT(0xD9);
1988 EMIT(0xF5);
1989}
1990
1991
1992void Assembler::fxch(int i) {
1993 EnsureSpace ensure_space(this);
1994 last_pc_ = pc_;
1995 emit_farith(0xD9, 0xC8, i);
1996}
1997
1998
1999void Assembler::fincstp() {
2000 EnsureSpace ensure_space(this);
2001 last_pc_ = pc_;
2002 EMIT(0xD9);
2003 EMIT(0xF7);
2004}
2005
2006
2007void Assembler::ffree(int i) {
2008 EnsureSpace ensure_space(this);
2009 last_pc_ = pc_;
2010 emit_farith(0xDD, 0xC0, i);
2011}
2012
2013
2014void Assembler::ftst() {
2015 EnsureSpace ensure_space(this);
2016 last_pc_ = pc_;
2017 EMIT(0xD9);
2018 EMIT(0xE4);
2019}
2020
2021
2022void Assembler::fucomp(int i) {
2023 EnsureSpace ensure_space(this);
2024 last_pc_ = pc_;
2025 emit_farith(0xDD, 0xE8, i);
2026}
2027
2028
2029void Assembler::fucompp() {
2030 EnsureSpace ensure_space(this);
2031 last_pc_ = pc_;
2032 EMIT(0xDA);
2033 EMIT(0xE9);
2034}
2035
2036
Steve Block3ce2e202009-11-05 08:53:23 +00002037void Assembler::fucomi(int i) {
2038 EnsureSpace ensure_space(this);
2039 last_pc_ = pc_;
2040 EMIT(0xDB);
2041 EMIT(0xE8 + i);
2042}
2043
2044
2045void Assembler::fucomip() {
2046 EnsureSpace ensure_space(this);
2047 last_pc_ = pc_;
2048 EMIT(0xDF);
2049 EMIT(0xE9);
2050}
2051
2052
Steve Blocka7e24c12009-10-30 11:49:00 +00002053void Assembler::fcompp() {
2054 EnsureSpace ensure_space(this);
2055 last_pc_ = pc_;
2056 EMIT(0xDE);
2057 EMIT(0xD9);
2058}
2059
2060
2061void Assembler::fnstsw_ax() {
2062 EnsureSpace ensure_space(this);
2063 last_pc_ = pc_;
2064 EMIT(0xDF);
2065 EMIT(0xE0);
2066}
2067
2068
2069void Assembler::fwait() {
2070 EnsureSpace ensure_space(this);
2071 last_pc_ = pc_;
2072 EMIT(0x9B);
2073}
2074
2075
2076void Assembler::frndint() {
2077 EnsureSpace ensure_space(this);
2078 last_pc_ = pc_;
2079 EMIT(0xD9);
2080 EMIT(0xFC);
2081}
2082
2083
2084void Assembler::fnclex() {
2085 EnsureSpace ensure_space(this);
2086 last_pc_ = pc_;
2087 EMIT(0xDB);
2088 EMIT(0xE2);
2089}
2090
2091
2092void Assembler::sahf() {
2093 EnsureSpace ensure_space(this);
2094 last_pc_ = pc_;
2095 EMIT(0x9E);
2096}
2097
2098
2099void Assembler::setcc(Condition cc, Register reg) {
2100 ASSERT(reg.is_byte_register());
2101 EnsureSpace ensure_space(this);
2102 last_pc_ = pc_;
2103 EMIT(0x0F);
2104 EMIT(0x90 | cc);
2105 EMIT(0xC0 | reg.code());
2106}
2107
2108
2109void Assembler::cvttss2si(Register dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002110 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002111 EnsureSpace ensure_space(this);
2112 last_pc_ = pc_;
2113 EMIT(0xF3);
2114 EMIT(0x0F);
2115 EMIT(0x2C);
2116 emit_operand(dst, src);
2117}
2118
2119
2120void Assembler::cvttsd2si(Register dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002121 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002122 EnsureSpace ensure_space(this);
2123 last_pc_ = pc_;
2124 EMIT(0xF2);
2125 EMIT(0x0F);
2126 EMIT(0x2C);
2127 emit_operand(dst, src);
2128}
2129
2130
2131void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002132 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002133 EnsureSpace ensure_space(this);
2134 last_pc_ = pc_;
2135 EMIT(0xF2);
2136 EMIT(0x0F);
2137 EMIT(0x2A);
2138 emit_sse_operand(dst, src);
2139}
2140
2141
Steve Block6ded16b2010-05-10 14:33:55 +01002142void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
2143 ASSERT(CpuFeatures::IsEnabled(SSE2));
2144 EnsureSpace ensure_space(this);
2145 last_pc_ = pc_;
2146 EMIT(0xF3);
2147 EMIT(0x0F);
2148 EMIT(0x5A);
2149 emit_sse_operand(dst, src);
2150}
2151
2152
Steve Blocka7e24c12009-10-30 11:49:00 +00002153void Assembler::addsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002154 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002155 EnsureSpace ensure_space(this);
2156 last_pc_ = pc_;
2157 EMIT(0xF2);
2158 EMIT(0x0F);
2159 EMIT(0x58);
2160 emit_sse_operand(dst, src);
2161}
2162
2163
2164void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002165 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002166 EnsureSpace ensure_space(this);
2167 last_pc_ = pc_;
2168 EMIT(0xF2);
2169 EMIT(0x0F);
2170 EMIT(0x59);
2171 emit_sse_operand(dst, src);
2172}
2173
2174
2175void Assembler::subsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002176 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002177 EnsureSpace ensure_space(this);
2178 last_pc_ = pc_;
2179 EMIT(0xF2);
2180 EMIT(0x0F);
2181 EMIT(0x5C);
2182 emit_sse_operand(dst, src);
2183}
2184
2185
2186void Assembler::divsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002187 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002188 EnsureSpace ensure_space(this);
2189 last_pc_ = pc_;
2190 EMIT(0xF2);
2191 EMIT(0x0F);
2192 EMIT(0x5E);
2193 emit_sse_operand(dst, src);
2194}
2195
2196
Leon Clarkee46be812010-01-19 14:06:41 +00002197void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
2198 ASSERT(CpuFeatures::IsEnabled(SSE2));
2199 EnsureSpace ensure_space(this);
2200 last_pc_ = pc_;
2201 EMIT(0x66);
2202 EMIT(0x0F);
2203 EMIT(0x57);
2204 emit_sse_operand(dst, src);
2205}
2206
2207
Steve Block6ded16b2010-05-10 14:33:55 +01002208void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
2209 EnsureSpace ensure_space(this);
2210 last_pc_ = pc_;
2211 EMIT(0xF2);
2212 EMIT(0x0F);
2213 EMIT(0x51);
2214 emit_sse_operand(dst, src);
2215}
2216
2217
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002218void Assembler::andpd(XMMRegister dst, XMMRegister src) {
2219 EnsureSpace ensure_space(this);
2220 last_pc_ = pc_;
2221 EMIT(0x66);
2222 EMIT(0x0F);
2223 EMIT(0x54);
2224 emit_sse_operand(dst, src);
2225}
2226
2227
Steve Block6ded16b2010-05-10 14:33:55 +01002228void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
2229 ASSERT(CpuFeatures::IsEnabled(SSE2));
2230 EnsureSpace ensure_space(this);
2231 last_pc_ = pc_;
2232 EMIT(0x66);
2233 EMIT(0x0F);
2234 EMIT(0x2E);
2235 emit_sse_operand(dst, src);
2236}
2237
2238
2239void Assembler::movmskpd(Register dst, XMMRegister src) {
2240 ASSERT(CpuFeatures::IsEnabled(SSE2));
2241 EnsureSpace ensure_space(this);
2242 last_pc_ = pc_;
2243 EMIT(0x66);
2244 EMIT(0x0F);
2245 EMIT(0x50);
2246 emit_sse_operand(dst, src);
2247}
2248
2249
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002250void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
2251 ASSERT(CpuFeatures::IsEnabled(SSE2));
2252 EnsureSpace ensure_space(this);
2253 last_pc_ = pc_;
2254 EMIT(0xF2);
2255 EMIT(0x0F);
2256 EMIT(0xC2);
2257 emit_sse_operand(dst, src);
2258 EMIT(1); // LT == 1
2259}
2260
2261
2262void Assembler::movaps(XMMRegister dst, XMMRegister src) {
2263 ASSERT(CpuFeatures::IsEnabled(SSE2));
2264 EnsureSpace ensure_space(this);
2265 last_pc_ = pc_;
2266 EMIT(0x0F);
2267 EMIT(0x28);
2268 emit_sse_operand(dst, src);
2269}
2270
2271
2272void Assembler::movdqa(const Operand& dst, XMMRegister src) {
Leon Clarkee46be812010-01-19 14:06:41 +00002273 ASSERT(CpuFeatures::IsEnabled(SSE2));
2274 EnsureSpace ensure_space(this);
2275 last_pc_ = pc_;
2276 EMIT(0x66);
2277 EMIT(0x0F);
2278 EMIT(0x7F);
2279 emit_sse_operand(src, dst);
2280}
2281
2282
2283void Assembler::movdqa(XMMRegister dst, const Operand& src) {
2284 ASSERT(CpuFeatures::IsEnabled(SSE2));
2285 EnsureSpace ensure_space(this);
2286 last_pc_ = pc_;
2287 EMIT(0x66);
2288 EMIT(0x0F);
2289 EMIT(0x6F);
2290 emit_sse_operand(dst, src);
2291}
2292
2293
2294void Assembler::movdqu(const Operand& dst, XMMRegister src ) {
2295 ASSERT(CpuFeatures::IsEnabled(SSE2));
2296 EnsureSpace ensure_space(this);
2297 last_pc_ = pc_;
2298 EMIT(0xF3);
2299 EMIT(0x0F);
2300 EMIT(0x7F);
2301 emit_sse_operand(src, dst);
2302}
2303
2304
2305void Assembler::movdqu(XMMRegister dst, const Operand& src) {
2306 ASSERT(CpuFeatures::IsEnabled(SSE2));
2307 EnsureSpace ensure_space(this);
2308 last_pc_ = pc_;
2309 EMIT(0xF3);
2310 EMIT(0x0F);
2311 EMIT(0x6F);
2312 emit_sse_operand(dst, src);
2313}
2314
2315
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002316void Assembler::movntdqa(XMMRegister dst, const Operand& src) {
2317 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
2318 EnsureSpace ensure_space(this);
2319 last_pc_ = pc_;
2320 EMIT(0x66);
2321 EMIT(0x0F);
2322 EMIT(0x38);
2323 EMIT(0x2A);
2324 emit_sse_operand(dst, src);
2325}
2326
2327
2328void Assembler::movntdq(const Operand& dst, XMMRegister src) {
2329 ASSERT(CpuFeatures::IsEnabled(SSE2));
2330 EnsureSpace ensure_space(this);
2331 last_pc_ = pc_;
2332 EMIT(0x66);
2333 EMIT(0x0F);
2334 EMIT(0xE7);
2335 emit_sse_operand(src, dst);
2336}
2337
2338
2339void Assembler::prefetch(const Operand& src, int level) {
2340 ASSERT(is_uint2(level));
2341 EnsureSpace ensure_space(this);
2342 last_pc_ = pc_;
2343 EMIT(0x0F);
2344 EMIT(0x18);
2345 XMMRegister code = { level }; // Emit hint number in Reg position of RegR/M.
2346 emit_sse_operand(code, src);
2347}
2348
2349
Steve Blocka7e24c12009-10-30 11:49:00 +00002350void Assembler::movdbl(XMMRegister dst, const Operand& src) {
2351 EnsureSpace ensure_space(this);
2352 last_pc_ = pc_;
2353 movsd(dst, src);
2354}
2355
2356
2357void Assembler::movdbl(const Operand& dst, XMMRegister src) {
2358 EnsureSpace ensure_space(this);
2359 last_pc_ = pc_;
2360 movsd(dst, src);
2361}
2362
2363
2364void Assembler::movsd(const Operand& dst, XMMRegister src ) {
Steve Blockd0582a62009-12-15 09:54:21 +00002365 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002366 EnsureSpace ensure_space(this);
2367 last_pc_ = pc_;
2368 EMIT(0xF2); // double
2369 EMIT(0x0F);
2370 EMIT(0x11); // store
2371 emit_sse_operand(src, dst);
2372}
2373
2374
2375void Assembler::movsd(XMMRegister dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002376 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002377 EnsureSpace ensure_space(this);
2378 last_pc_ = pc_;
2379 EMIT(0xF2); // double
2380 EMIT(0x0F);
2381 EMIT(0x10); // load
2382 emit_sse_operand(dst, src);
2383}
2384
Steve Block6ded16b2010-05-10 14:33:55 +01002385void Assembler::movsd(XMMRegister dst, XMMRegister src) {
2386 ASSERT(CpuFeatures::IsEnabled(SSE2));
2387 EnsureSpace ensure_space(this);
2388 last_pc_ = pc_;
2389 EMIT(0xF2);
2390 EMIT(0x0F);
2391 EMIT(0x10);
2392 emit_sse_operand(dst, src);
2393}
2394
2395
2396void Assembler::movd(XMMRegister dst, const Operand& src) {
2397 ASSERT(CpuFeatures::IsEnabled(SSE2));
2398 EnsureSpace ensure_space(this);
2399 last_pc_ = pc_;
2400 EMIT(0x66);
2401 EMIT(0x0F);
2402 EMIT(0x6E);
2403 emit_sse_operand(dst, src);
2404}
2405
2406
2407void Assembler::pxor(XMMRegister dst, XMMRegister src) {
2408 ASSERT(CpuFeatures::IsEnabled(SSE2));
2409 EnsureSpace ensure_space(this);
2410 last_pc_ = pc_;
2411 EMIT(0x66);
2412 EMIT(0x0F);
2413 EMIT(0xEF);
2414 emit_sse_operand(dst, src);
2415}
2416
2417
2418void Assembler::ptest(XMMRegister dst, XMMRegister src) {
Ben Murdochf87a2032010-10-22 12:50:53 +01002419 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
Steve Block6ded16b2010-05-10 14:33:55 +01002420 EnsureSpace ensure_space(this);
2421 last_pc_ = pc_;
2422 EMIT(0x66);
2423 EMIT(0x0F);
2424 EMIT(0x38);
2425 EMIT(0x17);
2426 emit_sse_operand(dst, src);
2427}
2428
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002429
2430void Assembler::psllq(XMMRegister reg, int8_t imm8) {
2431 ASSERT(CpuFeatures::IsEnabled(SSE2));
2432 EnsureSpace ensure_space(this);
2433 last_pc_ = pc_;
2434 EMIT(0x66);
2435 EMIT(0x0F);
2436 EMIT(0x73);
2437 emit_sse_operand(esi, reg); // esi == 6
2438 EMIT(imm8);
2439}
2440
2441
Steve Blocka7e24c12009-10-30 11:49:00 +00002442void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
2443 Register ireg = { reg.code() };
2444 emit_operand(ireg, adr);
2445}
2446
2447
2448void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
2449 EMIT(0xC0 | dst.code() << 3 | src.code());
2450}
2451
2452
Steve Block6ded16b2010-05-10 14:33:55 +01002453void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
2454 EMIT(0xC0 | dst.code() << 3 | src.code());
2455}
2456
2457
Steve Blocka7e24c12009-10-30 11:49:00 +00002458void Assembler::Print() {
2459 Disassembler::Decode(stdout, buffer_, pc_);
2460}
2461
2462
2463void Assembler::RecordJSReturn() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002464 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00002465 EnsureSpace ensure_space(this);
2466 RecordRelocInfo(RelocInfo::JS_RETURN);
2467}
2468
2469
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002470void Assembler::RecordDebugBreakSlot() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002471 positions_recorder()->WriteRecordedPositions();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002472 EnsureSpace ensure_space(this);
2473 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
2474}
2475
2476
Steve Blocka7e24c12009-10-30 11:49:00 +00002477void Assembler::RecordComment(const char* msg) {
2478 if (FLAG_debug_code) {
2479 EnsureSpace ensure_space(this);
2480 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
2481 }
2482}
2483
2484
Steve Blocka7e24c12009-10-30 11:49:00 +00002485void Assembler::GrowBuffer() {
Andrei Popescu31002712010-02-23 13:46:05 +00002486 ASSERT(overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +00002487 if (!own_buffer_) FATAL("external code buffer is too small");
2488
Andrei Popescu31002712010-02-23 13:46:05 +00002489 // Compute new buffer size.
Steve Blocka7e24c12009-10-30 11:49:00 +00002490 CodeDesc desc; // the new buffer
2491 if (buffer_size_ < 4*KB) {
2492 desc.buffer_size = 4*KB;
2493 } else {
2494 desc.buffer_size = 2*buffer_size_;
2495 }
2496 // Some internal data structures overflow for very large buffers,
2497 // they must ensure that kMaximalBufferSize is not too large.
2498 if ((desc.buffer_size > kMaximalBufferSize) ||
Steve Block3ce2e202009-11-05 08:53:23 +00002499 (desc.buffer_size > Heap::MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002500 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
2501 }
2502
Andrei Popescu31002712010-02-23 13:46:05 +00002503 // Setup new buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +00002504 desc.buffer = NewArray<byte>(desc.buffer_size);
2505 desc.instr_size = pc_offset();
2506 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
2507
2508 // Clear the buffer in debug mode. Use 'int3' instructions to make
2509 // sure to get into problems if we ever run uninitialized code.
2510#ifdef DEBUG
2511 memset(desc.buffer, 0xCC, desc.buffer_size);
2512#endif
2513
Andrei Popescu31002712010-02-23 13:46:05 +00002514 // Copy the data.
Steve Blocka7e24c12009-10-30 11:49:00 +00002515 int pc_delta = desc.buffer - buffer_;
2516 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
2517 memmove(desc.buffer, buffer_, desc.instr_size);
2518 memmove(rc_delta + reloc_info_writer.pos(),
2519 reloc_info_writer.pos(), desc.reloc_size);
2520
Andrei Popescu31002712010-02-23 13:46:05 +00002521 // Switch buffers.
Steve Blocka7e24c12009-10-30 11:49:00 +00002522 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
2523 spare_buffer_ = buffer_;
2524 } else {
2525 DeleteArray(buffer_);
2526 }
2527 buffer_ = desc.buffer;
2528 buffer_size_ = desc.buffer_size;
2529 pc_ += pc_delta;
2530 if (last_pc_ != NULL) {
2531 last_pc_ += pc_delta;
2532 }
2533 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2534 reloc_info_writer.last_pc() + pc_delta);
2535
Andrei Popescu31002712010-02-23 13:46:05 +00002536 // Relocate runtime entries.
Steve Blocka7e24c12009-10-30 11:49:00 +00002537 for (RelocIterator it(desc); !it.done(); it.next()) {
2538 RelocInfo::Mode rmode = it.rinfo()->rmode();
2539 if (rmode == RelocInfo::RUNTIME_ENTRY) {
2540 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2541 *p -= pc_delta; // relocate entry
2542 } else if (rmode == RelocInfo::INTERNAL_REFERENCE) {
2543 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2544 if (*p != 0) { // 0 means uninitialized.
2545 *p += pc_delta;
2546 }
2547 }
2548 }
2549
2550 ASSERT(!overflow());
2551}
2552
2553
2554void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
2555 ASSERT(is_uint8(op1) && is_uint8(op2)); // wrong opcode
2556 ASSERT(is_uint8(imm8));
2557 ASSERT((op1 & 0x01) == 0); // should be 8bit operation
2558 EMIT(op1);
2559 EMIT(op2 | dst.code());
2560 EMIT(imm8);
2561}
2562
2563
2564void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
2565 ASSERT((0 <= sel) && (sel <= 7));
2566 Register ireg = { sel };
2567 if (x.is_int8()) {
2568 EMIT(0x83); // using a sign-extended 8-bit immediate.
2569 emit_operand(ireg, dst);
2570 EMIT(x.x_ & 0xFF);
2571 } else if (dst.is_reg(eax)) {
2572 EMIT((sel << 3) | 0x05); // short form if the destination is eax.
2573 emit(x);
2574 } else {
2575 EMIT(0x81); // using a literal 32-bit immediate.
2576 emit_operand(ireg, dst);
2577 emit(x);
2578 }
2579}
2580
2581
2582void Assembler::emit_operand(Register reg, const Operand& adr) {
2583 const unsigned length = adr.len_;
2584 ASSERT(length > 0);
2585
2586 // Emit updated ModRM byte containing the given register.
2587 pc_[0] = (adr.buf_[0] & ~0x38) | (reg.code() << 3);
2588
2589 // Emit the rest of the encoded operand.
2590 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
2591 pc_ += length;
2592
2593 // Emit relocation information if necessary.
2594 if (length >= sizeof(int32_t) && adr.rmode_ != RelocInfo::NONE) {
2595 pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
2596 RecordRelocInfo(adr.rmode_);
2597 pc_ += sizeof(int32_t);
2598 }
2599}
2600
2601
2602void Assembler::emit_farith(int b1, int b2, int i) {
2603 ASSERT(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2604 ASSERT(0 <= i && i < 8); // illegal stack offset
2605 EMIT(b1);
2606 EMIT(b2 + i);
2607}
2608
2609
2610void Assembler::dd(uint32_t data, RelocInfo::Mode reloc_info) {
2611 EnsureSpace ensure_space(this);
2612 emit(data, reloc_info);
2613}
2614
2615
2616void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2617 ASSERT(rmode != RelocInfo::NONE);
2618 // Don't record external references unless the heap will be serialized.
Steve Blockd0582a62009-12-15 09:54:21 +00002619 if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
2620#ifdef DEBUG
2621 if (!Serializer::enabled()) {
2622 Serializer::TooLateToEnableNow();
2623 }
2624#endif
2625 if (!Serializer::enabled() && !FLAG_debug_code) {
2626 return;
2627 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002628 }
2629 RelocInfo rinfo(pc_, rmode, data);
2630 reloc_info_writer.Write(&rinfo);
2631}
2632
2633
2634#ifdef GENERATED_CODE_COVERAGE
2635static FILE* coverage_log = NULL;
2636
2637
2638static void InitCoverageLog() {
2639 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
2640 if (file_name != NULL) {
2641 coverage_log = fopen(file_name, "aw+");
2642 }
2643}
2644
2645
2646void LogGeneratedCodeCoverage(const char* file_line) {
2647 const char* return_address = (&file_line)[-1];
2648 char* push_insn = const_cast<char*>(return_address - 12);
2649 push_insn[0] = 0xeb; // Relative branch insn.
2650 push_insn[1] = 13; // Skip over coverage insns.
2651 if (coverage_log != NULL) {
2652 fprintf(coverage_log, "%s\n", file_line);
2653 fflush(coverage_log);
2654 }
2655}
2656
2657#endif
2658
2659} } // namespace v8::internal
Leon Clarkef7060e22010-06-03 12:02:55 +01002660
2661#endif // V8_TARGET_ARCH_IA32