blob: 698377a0c8363ad841ebc7aa8278a04185b210ba [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
39#include "disassembler.h"
40#include "macro-assembler.h"
41#include "serialize.h"
42
43namespace v8 {
44namespace internal {
45
46// -----------------------------------------------------------------------------
47// Implementation of CpuFeatures
48
49// Safe default is no features.
50uint64_t CpuFeatures::supported_ = 0;
51uint64_t CpuFeatures::enabled_ = 0;
52
53
54// The Probe method needs executable memory, so it uses Heap::CreateCode.
55// Allocation failure is silent and leads to safe default.
56void CpuFeatures::Probe() {
57 ASSERT(Heap::HasBeenSetup());
58 ASSERT(supported_ == 0);
59 if (Serializer::enabled()) return; // No features if we might serialize.
60
61 Assembler assm(NULL, 0);
62 Label cpuid, done;
63#define __ assm.
64 // Save old esp, since we are going to modify the stack.
65 __ push(ebp);
66 __ pushfd();
67 __ push(ecx);
68 __ push(ebx);
69 __ mov(ebp, Operand(esp));
70
71 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
72 __ pushfd();
73 __ pop(eax);
74 __ mov(edx, Operand(eax));
75 __ xor_(eax, 0x200000); // Flip bit 21.
76 __ push(eax);
77 __ popfd();
78 __ pushfd();
79 __ pop(eax);
80 __ xor_(eax, Operand(edx)); // Different if CPUID is supported.
81 __ j(not_zero, &cpuid);
82
83 // CPUID not supported. Clear the supported features in edx:eax.
84 __ xor_(eax, Operand(eax));
85 __ xor_(edx, Operand(edx));
86 __ jmp(&done);
87
88 // Invoke CPUID with 1 in eax to get feature information in
89 // ecx:edx. Temporarily enable CPUID support because we know it's
90 // safe here.
91 __ bind(&cpuid);
92 __ mov(eax, 1);
93 supported_ = (1 << CPUID);
94 { Scope fscope(CPUID);
95 __ cpuid();
96 }
97 supported_ = 0;
98
99 // Move the result from ecx:edx to edx:eax and make sure to mark the
100 // CPUID feature as supported.
101 __ mov(eax, Operand(edx));
102 __ or_(eax, 1 << CPUID);
103 __ mov(edx, Operand(ecx));
104
105 // Done.
106 __ bind(&done);
107 __ mov(esp, Operand(ebp));
108 __ pop(ebx);
109 __ pop(ecx);
110 __ popfd();
111 __ pop(ebp);
112 __ ret(0);
113#undef __
114
115 CodeDesc desc;
116 assm.GetCode(&desc);
117 Object* code = Heap::CreateCode(desc,
118 NULL,
119 Code::ComputeFlags(Code::STUB),
120 Handle<Code>::null());
121 if (!code->IsCode()) return;
122 LOG(CodeCreateEvent(Logger::BUILTIN_TAG,
123 Code::cast(code), "CpuFeatures::Probe"));
124 typedef uint64_t (*F0)();
125 F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry());
126 supported_ = probe();
127}
128
129
130// -----------------------------------------------------------------------------
131// Implementation of Displacement
132
133void Displacement::init(Label* L, Type type) {
134 ASSERT(!L->is_bound());
135 int next = 0;
136 if (L->is_linked()) {
137 next = L->pos();
138 ASSERT(next > 0); // Displacements must be at positions > 0
139 }
140 // Ensure that we _never_ overflow the next field.
141 ASSERT(NextField::is_valid(Assembler::kMaximalBufferSize));
142 data_ = NextField::encode(next) | TypeField::encode(type);
143}
144
145
146// -----------------------------------------------------------------------------
147// Implementation of RelocInfo
148
149
150const int RelocInfo::kApplyMask =
151 RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
152 1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE;
153
154
155void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
156 // Patch the code at the current address with the supplied instructions.
157 for (int i = 0; i < instruction_count; i++) {
158 *(pc_ + i) = *(instructions + i);
159 }
160
161 // Indicate that code has changed.
162 CPU::FlushICache(pc_, instruction_count);
163}
164
165
166// Patch the code at the current PC with a call to the target address.
167// Additional guard int3 instructions can be added if required.
168void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
169 // Call instruction takes up 5 bytes and int3 takes up one byte.
170 static const int kCallCodeSize = 5;
171 int code_size = kCallCodeSize + guard_bytes;
172
173 // Create a code patcher.
174 CodePatcher patcher(pc_, code_size);
175
176 // Add a label for checking the size of the code used for returning.
177#ifdef DEBUG
178 Label check_codesize;
179 patcher.masm()->bind(&check_codesize);
180#endif
181
182 // Patch the code.
183 patcher.masm()->call(target, RelocInfo::NONE);
184
185 // Check that the size of the code generated is as expected.
186 ASSERT_EQ(kCallCodeSize,
187 patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
188
189 // Add the requested number of int3 instructions after the call.
190 for (int i = 0; i < guard_bytes; i++) {
191 patcher.masm()->int3();
192 }
193}
194
195
196// -----------------------------------------------------------------------------
197// Implementation of Operand
198
199Operand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) {
200 // [base + disp/r]
201 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
202 // [base]
203 set_modrm(0, base);
204 if (base.is(esp)) set_sib(times_1, esp, base);
205 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
206 // [base + disp8]
207 set_modrm(1, base);
208 if (base.is(esp)) set_sib(times_1, esp, base);
209 set_disp8(disp);
210 } else {
211 // [base + disp/r]
212 set_modrm(2, base);
213 if (base.is(esp)) set_sib(times_1, esp, base);
214 set_dispr(disp, rmode);
215 }
216}
217
218
219Operand::Operand(Register base,
220 Register index,
221 ScaleFactor scale,
222 int32_t disp,
223 RelocInfo::Mode rmode) {
224 ASSERT(!index.is(esp)); // illegal addressing mode
225 // [base + index*scale + disp/r]
226 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
227 // [base + index*scale]
228 set_modrm(0, esp);
229 set_sib(scale, index, base);
230 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
231 // [base + index*scale + disp8]
232 set_modrm(1, esp);
233 set_sib(scale, index, base);
234 set_disp8(disp);
235 } else {
236 // [base + index*scale + disp/r]
237 set_modrm(2, esp);
238 set_sib(scale, index, base);
239 set_dispr(disp, rmode);
240 }
241}
242
243
244Operand::Operand(Register index,
245 ScaleFactor scale,
246 int32_t disp,
247 RelocInfo::Mode rmode) {
248 ASSERT(!index.is(esp)); // illegal addressing mode
249 // [index*scale + disp/r]
250 set_modrm(0, esp);
251 set_sib(scale, index, ebp);
252 set_dispr(disp, rmode);
253}
254
255
256bool Operand::is_reg(Register reg) const {
257 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only.
258 && ((buf_[0] & 0x07) == reg.code()); // register codes match.
259}
260
261// -----------------------------------------------------------------------------
262// Implementation of Assembler
263
264// Emit a single byte. Must always be inlined.
265#define EMIT(x) \
266 *pc_++ = (x)
267
268
269#ifdef GENERATED_CODE_COVERAGE
270static void InitCoverageLog();
271#endif
272
273// spare_buffer_
274byte* Assembler::spare_buffer_ = NULL;
275
276Assembler::Assembler(void* buffer, int buffer_size) {
277 if (buffer == NULL) {
278 // do our own buffer management
279 if (buffer_size <= kMinimalBufferSize) {
280 buffer_size = kMinimalBufferSize;
281
282 if (spare_buffer_ != NULL) {
283 buffer = spare_buffer_;
284 spare_buffer_ = NULL;
285 }
286 }
287 if (buffer == NULL) {
288 buffer_ = NewArray<byte>(buffer_size);
289 } else {
290 buffer_ = static_cast<byte*>(buffer);
291 }
292 buffer_size_ = buffer_size;
293 own_buffer_ = true;
294 } else {
295 // use externally provided buffer instead
296 ASSERT(buffer_size > 0);
297 buffer_ = static_cast<byte*>(buffer);
298 buffer_size_ = buffer_size;
299 own_buffer_ = false;
300 }
301
302 // Clear the buffer in debug mode unless it was provided by the
303 // caller in which case we can't be sure it's okay to overwrite
304 // existing code in it; see CodePatcher::CodePatcher(...).
305#ifdef DEBUG
306 if (own_buffer_) {
307 memset(buffer_, 0xCC, buffer_size); // int3
308 }
309#endif
310
311 // setup buffer pointers
312 ASSERT(buffer_ != NULL);
313 pc_ = buffer_;
314 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
315
316 last_pc_ = NULL;
317 current_statement_position_ = RelocInfo::kNoPosition;
318 current_position_ = RelocInfo::kNoPosition;
319 written_statement_position_ = current_statement_position_;
320 written_position_ = current_position_;
321#ifdef GENERATED_CODE_COVERAGE
322 InitCoverageLog();
323#endif
324}
325
326
327Assembler::~Assembler() {
328 if (own_buffer_) {
329 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
330 spare_buffer_ = buffer_;
331 } else {
332 DeleteArray(buffer_);
333 }
334 }
335}
336
337
338void Assembler::GetCode(CodeDesc* desc) {
339 // finalize code
340 // (at this point overflow() may be true, but the gap ensures that
341 // we are still not overlapping instructions and relocation info)
342 ASSERT(pc_ <= reloc_info_writer.pos()); // no overlap
343 // setup desc
344 desc->buffer = buffer_;
345 desc->buffer_size = buffer_size_;
346 desc->instr_size = pc_offset();
347 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
348 desc->origin = this;
349
350 Counters::reloc_info_size.Increment(desc->reloc_size);
351}
352
353
354void Assembler::Align(int m) {
355 ASSERT(IsPowerOf2(m));
356 while ((pc_offset() & (m - 1)) != 0) {
357 nop();
358 }
359}
360
361
362void Assembler::cpuid() {
363 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CPUID));
364 EnsureSpace ensure_space(this);
365 last_pc_ = pc_;
366 EMIT(0x0F);
367 EMIT(0xA2);
368}
369
370
371void Assembler::pushad() {
372 EnsureSpace ensure_space(this);
373 last_pc_ = pc_;
374 EMIT(0x60);
375}
376
377
378void Assembler::popad() {
379 EnsureSpace ensure_space(this);
380 last_pc_ = pc_;
381 EMIT(0x61);
382}
383
384
385void Assembler::pushfd() {
386 EnsureSpace ensure_space(this);
387 last_pc_ = pc_;
388 EMIT(0x9C);
389}
390
391
392void Assembler::popfd() {
393 EnsureSpace ensure_space(this);
394 last_pc_ = pc_;
395 EMIT(0x9D);
396}
397
398
399void Assembler::push(const Immediate& x) {
400 EnsureSpace ensure_space(this);
401 last_pc_ = pc_;
402 if (x.is_int8()) {
403 EMIT(0x6a);
404 EMIT(x.x_);
405 } else {
406 EMIT(0x68);
407 emit(x);
408 }
409}
410
411
412void Assembler::push(Register src) {
413 EnsureSpace ensure_space(this);
414 last_pc_ = pc_;
415 EMIT(0x50 | src.code());
416}
417
418
419void Assembler::push(const Operand& src) {
420 EnsureSpace ensure_space(this);
421 last_pc_ = pc_;
422 EMIT(0xFF);
423 emit_operand(esi, src);
424}
425
426
427void Assembler::pop(Register dst) {
428 ASSERT(reloc_info_writer.last_pc() != NULL);
429 if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) {
430 // (last_pc_ != NULL) is rolled into the above check
431 // If a last_pc_ is set, we need to make sure that there has not been any
432 // relocation information generated between the last instruction and this
433 // pop instruction.
434 byte instr = last_pc_[0];
435 if ((instr & ~0x7) == 0x50) {
436 int push_reg_code = instr & 0x7;
437 if (push_reg_code == dst.code()) {
438 pc_ = last_pc_;
439 if (FLAG_print_push_pop_elimination) {
440 PrintF("%d push/pop (same reg) eliminated\n", pc_offset());
441 }
442 } else {
443 // Convert 'push src; pop dst' to 'mov dst, src'.
444 last_pc_[0] = 0x8b;
445 Register src = { push_reg_code };
446 EnsureSpace ensure_space(this);
447 emit_operand(dst, Operand(src));
448 if (FLAG_print_push_pop_elimination) {
449 PrintF("%d push/pop (reg->reg) eliminated\n", pc_offset());
450 }
451 }
452 last_pc_ = NULL;
453 return;
454 } else if (instr == 0xff) { // push of an operand, convert to a move
455 byte op1 = last_pc_[1];
456 // Check if the operation is really a push
457 if ((op1 & 0x38) == (6 << 3)) {
458 op1 = (op1 & ~0x38) | static_cast<byte>(dst.code() << 3);
459 last_pc_[0] = 0x8b;
460 last_pc_[1] = op1;
461 last_pc_ = NULL;
462 if (FLAG_print_push_pop_elimination) {
463 PrintF("%d push/pop (op->reg) eliminated\n", pc_offset());
464 }
465 return;
466 }
467 } else if ((instr == 0x89) &&
468 (last_pc_[1] == 0x04) &&
469 (last_pc_[2] == 0x24)) {
470 // 0x71283c 396 890424 mov [esp],eax
471 // 0x71283f 399 58 pop eax
472 if (dst.is(eax)) {
473 // change to
474 // 0x710fac 216 83c404 add esp,0x4
475 last_pc_[0] = 0x83;
476 last_pc_[1] = 0xc4;
477 last_pc_[2] = 0x04;
478 last_pc_ = NULL;
479 if (FLAG_print_push_pop_elimination) {
480 PrintF("%d push/pop (mov-pop) eliminated\n", pc_offset());
481 }
482 return;
483 }
484 } else if (instr == 0x6a && dst.is(eax)) { // push of immediate 8 bit
485 byte imm8 = last_pc_[1];
486 if (imm8 == 0) {
487 // 6a00 push 0x0
488 // 58 pop eax
489 last_pc_[0] = 0x31;
490 last_pc_[1] = 0xc0;
491 // change to
492 // 31c0 xor eax,eax
493 last_pc_ = NULL;
494 if (FLAG_print_push_pop_elimination) {
495 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
496 }
497 return;
498 } else {
499 // 6a00 push 0xXX
500 // 58 pop eax
501 last_pc_[0] = 0xb8;
502 EnsureSpace ensure_space(this);
503 if ((imm8 & 0x80) != 0) {
504 EMIT(0xff);
505 EMIT(0xff);
506 EMIT(0xff);
507 // change to
508 // b8XXffffff mov eax,0xffffffXX
509 } else {
510 EMIT(0x00);
511 EMIT(0x00);
512 EMIT(0x00);
513 // change to
514 // b8XX000000 mov eax,0x000000XX
515 }
516 last_pc_ = NULL;
517 if (FLAG_print_push_pop_elimination) {
518 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
519 }
520 return;
521 }
522 } else if (instr == 0x68 && dst.is(eax)) { // push of immediate 32 bit
523 // 68XXXXXXXX push 0xXXXXXXXX
524 // 58 pop eax
525 last_pc_[0] = 0xb8;
526 last_pc_ = NULL;
527 // change to
528 // b8XXXXXXXX mov eax,0xXXXXXXXX
529 if (FLAG_print_push_pop_elimination) {
530 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
531 }
532 return;
533 }
534
535 // Other potential patterns for peephole:
536 // 0x712716 102 890424 mov [esp], eax
537 // 0x712719 105 8b1424 mov edx, [esp]
538 }
539 EnsureSpace ensure_space(this);
540 last_pc_ = pc_;
541 EMIT(0x58 | dst.code());
542}
543
544
545void Assembler::pop(const Operand& dst) {
546 EnsureSpace ensure_space(this);
547 last_pc_ = pc_;
548 EMIT(0x8F);
549 emit_operand(eax, dst);
550}
551
552
553void Assembler::enter(const Immediate& size) {
554 EnsureSpace ensure_space(this);
555 last_pc_ = pc_;
556 EMIT(0xC8);
557 emit_w(size);
558 EMIT(0);
559}
560
561
562void Assembler::leave() {
563 EnsureSpace ensure_space(this);
564 last_pc_ = pc_;
565 EMIT(0xC9);
566}
567
568
569void Assembler::mov_b(Register dst, const Operand& src) {
570 EnsureSpace ensure_space(this);
571 last_pc_ = pc_;
572 EMIT(0x8A);
573 emit_operand(dst, src);
574}
575
576
577void Assembler::mov_b(const Operand& dst, int8_t imm8) {
578 EnsureSpace ensure_space(this);
579 last_pc_ = pc_;
580 EMIT(0xC6);
581 emit_operand(eax, dst);
582 EMIT(imm8);
583}
584
585
586void Assembler::mov_b(const Operand& dst, Register src) {
587 EnsureSpace ensure_space(this);
588 last_pc_ = pc_;
589 EMIT(0x88);
590 emit_operand(src, dst);
591}
592
593
594void Assembler::mov_w(Register dst, const Operand& src) {
595 EnsureSpace ensure_space(this);
596 last_pc_ = pc_;
597 EMIT(0x66);
598 EMIT(0x8B);
599 emit_operand(dst, src);
600}
601
602
603void Assembler::mov_w(const Operand& dst, Register src) {
604 EnsureSpace ensure_space(this);
605 last_pc_ = pc_;
606 EMIT(0x66);
607 EMIT(0x89);
608 emit_operand(src, dst);
609}
610
611
612void Assembler::mov(Register dst, int32_t imm32) {
613 EnsureSpace ensure_space(this);
614 last_pc_ = pc_;
615 EMIT(0xB8 | dst.code());
616 emit(imm32);
617}
618
619
620void Assembler::mov(Register dst, const Immediate& x) {
621 EnsureSpace ensure_space(this);
622 last_pc_ = pc_;
623 EMIT(0xB8 | dst.code());
624 emit(x);
625}
626
627
628void Assembler::mov(Register dst, Handle<Object> handle) {
629 EnsureSpace ensure_space(this);
630 last_pc_ = pc_;
631 EMIT(0xB8 | dst.code());
632 emit(handle);
633}
634
635
636void Assembler::mov(Register dst, const Operand& src) {
637 EnsureSpace ensure_space(this);
638 last_pc_ = pc_;
639 EMIT(0x8B);
640 emit_operand(dst, src);
641}
642
643
644void Assembler::mov(Register dst, Register src) {
645 EnsureSpace ensure_space(this);
646 last_pc_ = pc_;
647 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);
654 last_pc_ = pc_;
655 EMIT(0xC7);
656 emit_operand(eax, dst);
657 emit(x);
658}
659
660
661void Assembler::mov(const Operand& dst, Handle<Object> handle) {
662 EnsureSpace ensure_space(this);
663 last_pc_ = pc_;
664 EMIT(0xC7);
665 emit_operand(eax, dst);
666 emit(handle);
667}
668
669
670void Assembler::mov(const Operand& dst, Register src) {
671 EnsureSpace ensure_space(this);
672 last_pc_ = pc_;
673 EMIT(0x89);
674 emit_operand(src, dst);
675}
676
677
678void Assembler::movsx_b(Register dst, const Operand& src) {
679 EnsureSpace ensure_space(this);
680 last_pc_ = pc_;
681 EMIT(0x0F);
682 EMIT(0xBE);
683 emit_operand(dst, src);
684}
685
686
687void Assembler::movsx_w(Register dst, const Operand& src) {
688 EnsureSpace ensure_space(this);
689 last_pc_ = pc_;
690 EMIT(0x0F);
691 EMIT(0xBF);
692 emit_operand(dst, src);
693}
694
695
696void Assembler::movzx_b(Register dst, const Operand& src) {
697 EnsureSpace ensure_space(this);
698 last_pc_ = pc_;
699 EMIT(0x0F);
700 EMIT(0xB6);
701 emit_operand(dst, src);
702}
703
704
705void Assembler::movzx_w(Register dst, const Operand& src) {
706 EnsureSpace ensure_space(this);
707 last_pc_ = pc_;
708 EMIT(0x0F);
709 EMIT(0xB7);
710 emit_operand(dst, src);
711}
712
713
714void Assembler::cmov(Condition cc, Register dst, int32_t imm32) {
715 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CMOV));
716 EnsureSpace ensure_space(this);
717 last_pc_ = pc_;
718 UNIMPLEMENTED();
719 USE(cc);
720 USE(dst);
721 USE(imm32);
722}
723
724
725void Assembler::cmov(Condition cc, Register dst, Handle<Object> handle) {
726 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CMOV));
727 EnsureSpace ensure_space(this);
728 last_pc_ = pc_;
729 UNIMPLEMENTED();
730 USE(cc);
731 USE(dst);
732 USE(handle);
733}
734
735
736void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
737 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CMOV));
738 EnsureSpace ensure_space(this);
739 last_pc_ = pc_;
740 // Opcode: 0f 40 + cc /r
741 EMIT(0x0F);
742 EMIT(0x40 + cc);
743 emit_operand(dst, src);
744}
745
746
747void Assembler::xchg(Register dst, Register src) {
748 EnsureSpace ensure_space(this);
749 last_pc_ = pc_;
750 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding
751 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code()));
752 } else {
753 EMIT(0x87);
754 EMIT(0xC0 | src.code() << 3 | dst.code());
755 }
756}
757
758
759void Assembler::adc(Register dst, int32_t imm32) {
760 EnsureSpace ensure_space(this);
761 last_pc_ = pc_;
762 emit_arith(2, Operand(dst), Immediate(imm32));
763}
764
765
766void Assembler::adc(Register dst, const Operand& src) {
767 EnsureSpace ensure_space(this);
768 last_pc_ = pc_;
769 EMIT(0x13);
770 emit_operand(dst, src);
771}
772
773
774void Assembler::add(Register dst, const Operand& src) {
775 EnsureSpace ensure_space(this);
776 last_pc_ = pc_;
777 EMIT(0x03);
778 emit_operand(dst, src);
779}
780
781
782void Assembler::add(const Operand& dst, const Immediate& x) {
783 ASSERT(reloc_info_writer.last_pc() != NULL);
784 if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) {
785 byte instr = last_pc_[0];
786 if ((instr & 0xf8) == 0x50) {
787 // Last instruction was a push. Check whether this is a pop without a
788 // result.
789 if ((dst.is_reg(esp)) &&
790 (x.x_ == kPointerSize) && (x.rmode_ == RelocInfo::NONE)) {
791 pc_ = last_pc_;
792 last_pc_ = NULL;
793 if (FLAG_print_push_pop_elimination) {
794 PrintF("%d push/pop(noreg) eliminated\n", pc_offset());
795 }
796 return;
797 }
798 }
799 }
800 EnsureSpace ensure_space(this);
801 last_pc_ = pc_;
802 emit_arith(0, dst, x);
803}
804
805
806void Assembler::and_(Register dst, int32_t imm32) {
807 EnsureSpace ensure_space(this);
808 last_pc_ = pc_;
809 emit_arith(4, Operand(dst), Immediate(imm32));
810}
811
812
813void Assembler::and_(Register dst, const Operand& src) {
814 EnsureSpace ensure_space(this);
815 last_pc_ = pc_;
816 EMIT(0x23);
817 emit_operand(dst, src);
818}
819
820
821void Assembler::and_(const Operand& dst, const Immediate& x) {
822 EnsureSpace ensure_space(this);
823 last_pc_ = pc_;
824 emit_arith(4, dst, x);
825}
826
827
828void Assembler::and_(const Operand& dst, Register src) {
829 EnsureSpace ensure_space(this);
830 last_pc_ = pc_;
831 EMIT(0x21);
832 emit_operand(src, dst);
833}
834
835
836void Assembler::cmpb(const Operand& op, int8_t imm8) {
837 EnsureSpace ensure_space(this);
838 last_pc_ = pc_;
839 EMIT(0x80);
840 emit_operand(edi, op); // edi == 7
841 EMIT(imm8);
842}
843
844
845void Assembler::cmpw(const Operand& op, Immediate imm16) {
846 ASSERT(imm16.is_int16());
847 EnsureSpace ensure_space(this);
848 last_pc_ = pc_;
849 EMIT(0x66);
850 EMIT(0x81);
851 emit_operand(edi, op);
852 emit_w(imm16);
853}
854
855
856void Assembler::cmp(Register reg, int32_t imm32) {
857 EnsureSpace ensure_space(this);
858 last_pc_ = pc_;
859 emit_arith(7, Operand(reg), Immediate(imm32));
860}
861
862
863void Assembler::cmp(Register reg, Handle<Object> handle) {
864 EnsureSpace ensure_space(this);
865 last_pc_ = pc_;
866 emit_arith(7, Operand(reg), Immediate(handle));
867}
868
869
870void Assembler::cmp(Register reg, const Operand& op) {
871 EnsureSpace ensure_space(this);
872 last_pc_ = pc_;
873 EMIT(0x3B);
874 emit_operand(reg, op);
875}
876
877
878void Assembler::cmp(const Operand& op, const Immediate& imm) {
879 EnsureSpace ensure_space(this);
880 last_pc_ = pc_;
881 emit_arith(7, op, imm);
882}
883
884
885void Assembler::cmp(const Operand& op, Handle<Object> handle) {
886 EnsureSpace ensure_space(this);
887 last_pc_ = pc_;
888 emit_arith(7, op, Immediate(handle));
889}
890
891
892void Assembler::cmpb_al(const Operand& op) {
893 EnsureSpace ensure_space(this);
894 last_pc_ = pc_;
895 EMIT(0x38); // CMP r/m8, r8
896 emit_operand(eax, op); // eax has same code as register al.
897}
898
899
900void Assembler::cmpw_ax(const Operand& op) {
901 EnsureSpace ensure_space(this);
902 last_pc_ = pc_;
903 EMIT(0x66);
904 EMIT(0x39); // CMP r/m16, r16
905 emit_operand(eax, op); // eax has same code as register ax.
906}
907
908
909void Assembler::dec_b(Register dst) {
910 EnsureSpace ensure_space(this);
911 last_pc_ = pc_;
912 EMIT(0xFE);
913 EMIT(0xC8 | dst.code());
914}
915
916
917void Assembler::dec(Register dst) {
918 EnsureSpace ensure_space(this);
919 last_pc_ = pc_;
920 EMIT(0x48 | dst.code());
921}
922
923
924void Assembler::dec(const Operand& dst) {
925 EnsureSpace ensure_space(this);
926 last_pc_ = pc_;
927 EMIT(0xFF);
928 emit_operand(ecx, dst);
929}
930
931
932void Assembler::cdq() {
933 EnsureSpace ensure_space(this);
934 last_pc_ = pc_;
935 EMIT(0x99);
936}
937
938
939void Assembler::idiv(Register src) {
940 EnsureSpace ensure_space(this);
941 last_pc_ = pc_;
942 EMIT(0xF7);
943 EMIT(0xF8 | src.code());
944}
945
946
947void Assembler::imul(Register reg) {
948 EnsureSpace ensure_space(this);
949 last_pc_ = pc_;
950 EMIT(0xF7);
951 EMIT(0xE8 | reg.code());
952}
953
954
955void Assembler::imul(Register dst, const Operand& src) {
956 EnsureSpace ensure_space(this);
957 last_pc_ = pc_;
958 EMIT(0x0F);
959 EMIT(0xAF);
960 emit_operand(dst, src);
961}
962
963
964void Assembler::imul(Register dst, Register src, int32_t imm32) {
965 EnsureSpace ensure_space(this);
966 last_pc_ = pc_;
967 if (is_int8(imm32)) {
968 EMIT(0x6B);
969 EMIT(0xC0 | dst.code() << 3 | src.code());
970 EMIT(imm32);
971 } else {
972 EMIT(0x69);
973 EMIT(0xC0 | dst.code() << 3 | src.code());
974 emit(imm32);
975 }
976}
977
978
979void Assembler::inc(Register dst) {
980 EnsureSpace ensure_space(this);
981 last_pc_ = pc_;
982 EMIT(0x40 | dst.code());
983}
984
985
986void Assembler::inc(const Operand& dst) {
987 EnsureSpace ensure_space(this);
988 last_pc_ = pc_;
989 EMIT(0xFF);
990 emit_operand(eax, dst);
991}
992
993
994void Assembler::lea(Register dst, const Operand& src) {
995 EnsureSpace ensure_space(this);
996 last_pc_ = pc_;
997 EMIT(0x8D);
998 emit_operand(dst, src);
999}
1000
1001
1002void Assembler::mul(Register src) {
1003 EnsureSpace ensure_space(this);
1004 last_pc_ = pc_;
1005 EMIT(0xF7);
1006 EMIT(0xE0 | src.code());
1007}
1008
1009
1010void Assembler::neg(Register dst) {
1011 EnsureSpace ensure_space(this);
1012 last_pc_ = pc_;
1013 EMIT(0xF7);
1014 EMIT(0xD8 | dst.code());
1015}
1016
1017
1018void Assembler::not_(Register dst) {
1019 EnsureSpace ensure_space(this);
1020 last_pc_ = pc_;
1021 EMIT(0xF7);
1022 EMIT(0xD0 | dst.code());
1023}
1024
1025
1026void Assembler::or_(Register dst, int32_t imm32) {
1027 EnsureSpace ensure_space(this);
1028 last_pc_ = pc_;
1029 emit_arith(1, Operand(dst), Immediate(imm32));
1030}
1031
1032
1033void Assembler::or_(Register dst, const Operand& src) {
1034 EnsureSpace ensure_space(this);
1035 last_pc_ = pc_;
1036 EMIT(0x0B);
1037 emit_operand(dst, src);
1038}
1039
1040
1041void Assembler::or_(const Operand& dst, const Immediate& x) {
1042 EnsureSpace ensure_space(this);
1043 last_pc_ = pc_;
1044 emit_arith(1, dst, x);
1045}
1046
1047
1048void Assembler::or_(const Operand& dst, Register src) {
1049 EnsureSpace ensure_space(this);
1050 last_pc_ = pc_;
1051 EMIT(0x09);
1052 emit_operand(src, dst);
1053}
1054
1055
1056void Assembler::rcl(Register dst, uint8_t imm8) {
1057 EnsureSpace ensure_space(this);
1058 last_pc_ = pc_;
1059 ASSERT(is_uint5(imm8)); // illegal shift count
1060 if (imm8 == 1) {
1061 EMIT(0xD1);
1062 EMIT(0xD0 | dst.code());
1063 } else {
1064 EMIT(0xC1);
1065 EMIT(0xD0 | dst.code());
1066 EMIT(imm8);
1067 }
1068}
1069
1070
1071void Assembler::sar(Register dst, uint8_t imm8) {
1072 EnsureSpace ensure_space(this);
1073 last_pc_ = pc_;
1074 ASSERT(is_uint5(imm8)); // illegal shift count
1075 if (imm8 == 1) {
1076 EMIT(0xD1);
1077 EMIT(0xF8 | dst.code());
1078 } else {
1079 EMIT(0xC1);
1080 EMIT(0xF8 | dst.code());
1081 EMIT(imm8);
1082 }
1083}
1084
1085
1086void Assembler::sar(Register dst) {
1087 EnsureSpace ensure_space(this);
1088 last_pc_ = pc_;
1089 EMIT(0xD3);
1090 EMIT(0xF8 | dst.code());
1091}
1092
1093
1094void Assembler::sbb(Register dst, const Operand& src) {
1095 EnsureSpace ensure_space(this);
1096 last_pc_ = pc_;
1097 EMIT(0x1B);
1098 emit_operand(dst, src);
1099}
1100
1101
1102void Assembler::shld(Register dst, const Operand& src) {
1103 EnsureSpace ensure_space(this);
1104 last_pc_ = pc_;
1105 EMIT(0x0F);
1106 EMIT(0xA5);
1107 emit_operand(dst, src);
1108}
1109
1110
1111void Assembler::shl(Register dst, uint8_t imm8) {
1112 EnsureSpace ensure_space(this);
1113 last_pc_ = pc_;
1114 ASSERT(is_uint5(imm8)); // illegal shift count
1115 if (imm8 == 1) {
1116 EMIT(0xD1);
1117 EMIT(0xE0 | dst.code());
1118 } else {
1119 EMIT(0xC1);
1120 EMIT(0xE0 | dst.code());
1121 EMIT(imm8);
1122 }
1123}
1124
1125
1126void Assembler::shl(Register dst) {
1127 EnsureSpace ensure_space(this);
1128 last_pc_ = pc_;
1129 EMIT(0xD3);
1130 EMIT(0xE0 | dst.code());
1131}
1132
1133
1134void Assembler::shrd(Register dst, const Operand& src) {
1135 EnsureSpace ensure_space(this);
1136 last_pc_ = pc_;
1137 EMIT(0x0F);
1138 EMIT(0xAD);
1139 emit_operand(dst, src);
1140}
1141
1142
1143void Assembler::shr(Register dst, uint8_t imm8) {
1144 EnsureSpace ensure_space(this);
1145 last_pc_ = pc_;
1146 ASSERT(is_uint5(imm8)); // illegal shift count
1147 EMIT(0xC1);
1148 EMIT(0xE8 | dst.code());
1149 EMIT(imm8);
1150}
1151
1152
1153void Assembler::shr(Register dst) {
1154 EnsureSpace ensure_space(this);
1155 last_pc_ = pc_;
1156 EMIT(0xD3);
1157 EMIT(0xE8 | dst.code());
1158}
1159
1160
1161void Assembler::shr_cl(Register dst) {
1162 EnsureSpace ensure_space(this);
1163 last_pc_ = pc_;
1164 EMIT(0xD1);
1165 EMIT(0xE8 | dst.code());
1166}
1167
1168
Steve Block3ce2e202009-11-05 08:53:23 +00001169void Assembler::subb(const Operand& op, int8_t imm8) {
1170 EnsureSpace ensure_space(this);
1171 last_pc_ = pc_;
1172 if (op.is_reg(eax)) {
1173 EMIT(0x2c);
1174 } else {
1175 EMIT(0x80);
1176 emit_operand(ebp, op); // ebp == 5
1177 }
1178 EMIT(imm8);
1179}
1180
1181
Steve Blocka7e24c12009-10-30 11:49:00 +00001182void Assembler::sub(const Operand& dst, const Immediate& x) {
1183 EnsureSpace ensure_space(this);
1184 last_pc_ = pc_;
1185 emit_arith(5, dst, x);
1186}
1187
1188
1189void Assembler::sub(Register dst, const Operand& src) {
1190 EnsureSpace ensure_space(this);
1191 last_pc_ = pc_;
1192 EMIT(0x2B);
1193 emit_operand(dst, src);
1194}
1195
1196
1197void Assembler::sub(const Operand& dst, Register src) {
1198 EnsureSpace ensure_space(this);
1199 last_pc_ = pc_;
1200 EMIT(0x29);
1201 emit_operand(src, dst);
1202}
1203
1204
1205void Assembler::test(Register reg, const Immediate& imm) {
1206 EnsureSpace ensure_space(this);
1207 last_pc_ = pc_;
1208 // Only use test against byte for registers that have a byte
1209 // variant: eax, ebx, ecx, and edx.
1210 if (imm.rmode_ == RelocInfo::NONE && is_uint8(imm.x_) && reg.code() < 4) {
1211 uint8_t imm8 = imm.x_;
1212 if (reg.is(eax)) {
1213 EMIT(0xA8);
1214 EMIT(imm8);
1215 } else {
1216 emit_arith_b(0xF6, 0xC0, reg, imm8);
1217 }
1218 } else {
1219 // This is not using emit_arith because test doesn't support
1220 // sign-extension of 8-bit operands.
1221 if (reg.is(eax)) {
1222 EMIT(0xA9);
1223 } else {
1224 EMIT(0xF7);
1225 EMIT(0xC0 | reg.code());
1226 }
1227 emit(imm);
1228 }
1229}
1230
1231
1232void Assembler::test(Register reg, const Operand& op) {
1233 EnsureSpace ensure_space(this);
1234 last_pc_ = pc_;
1235 EMIT(0x85);
1236 emit_operand(reg, op);
1237}
1238
1239
1240void Assembler::test(const Operand& op, const Immediate& imm) {
1241 EnsureSpace ensure_space(this);
1242 last_pc_ = pc_;
1243 EMIT(0xF7);
1244 emit_operand(eax, op);
1245 emit(imm);
1246}
1247
1248
1249void Assembler::xor_(Register dst, int32_t imm32) {
1250 EnsureSpace ensure_space(this);
1251 last_pc_ = pc_;
1252 emit_arith(6, Operand(dst), Immediate(imm32));
1253}
1254
1255
1256void Assembler::xor_(Register dst, const Operand& src) {
1257 EnsureSpace ensure_space(this);
1258 last_pc_ = pc_;
1259 EMIT(0x33);
1260 emit_operand(dst, src);
1261}
1262
1263
1264void Assembler::xor_(const Operand& src, Register dst) {
1265 EnsureSpace ensure_space(this);
1266 last_pc_ = pc_;
1267 EMIT(0x31);
1268 emit_operand(dst, src);
1269}
1270
1271
1272void Assembler::xor_(const Operand& dst, const Immediate& x) {
1273 EnsureSpace ensure_space(this);
1274 last_pc_ = pc_;
1275 emit_arith(6, dst, x);
1276}
1277
1278
1279void Assembler::bt(const Operand& dst, Register src) {
1280 EnsureSpace ensure_space(this);
1281 last_pc_ = pc_;
1282 EMIT(0x0F);
1283 EMIT(0xA3);
1284 emit_operand(src, dst);
1285}
1286
1287
1288void Assembler::bts(const Operand& dst, Register src) {
1289 EnsureSpace ensure_space(this);
1290 last_pc_ = pc_;
1291 EMIT(0x0F);
1292 EMIT(0xAB);
1293 emit_operand(src, dst);
1294}
1295
1296
1297void Assembler::hlt() {
1298 EnsureSpace ensure_space(this);
1299 last_pc_ = pc_;
1300 EMIT(0xF4);
1301}
1302
1303
1304void Assembler::int3() {
1305 EnsureSpace ensure_space(this);
1306 last_pc_ = pc_;
1307 EMIT(0xCC);
1308}
1309
1310
1311void Assembler::nop() {
1312 EnsureSpace ensure_space(this);
1313 last_pc_ = pc_;
1314 EMIT(0x90);
1315}
1316
1317
1318void Assembler::rdtsc() {
1319 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::RDTSC));
1320 EnsureSpace ensure_space(this);
1321 last_pc_ = pc_;
1322 EMIT(0x0F);
1323 EMIT(0x31);
1324}
1325
1326
1327void Assembler::ret(int imm16) {
1328 EnsureSpace ensure_space(this);
1329 last_pc_ = pc_;
1330 ASSERT(is_uint16(imm16));
1331 if (imm16 == 0) {
1332 EMIT(0xC3);
1333 } else {
1334 EMIT(0xC2);
1335 EMIT(imm16 & 0xFF);
1336 EMIT((imm16 >> 8) & 0xFF);
1337 }
1338}
1339
1340
1341// Labels refer to positions in the (to be) generated code.
1342// There are bound, linked, and unused labels.
1343//
1344// Bound labels refer to known positions in the already
1345// generated code. pos() is the position the label refers to.
1346//
1347// Linked labels refer to unknown positions in the code
1348// to be generated; pos() is the position of the 32bit
1349// Displacement of the last instruction using the label.
1350
1351
1352void Assembler::print(Label* L) {
1353 if (L->is_unused()) {
1354 PrintF("unused label\n");
1355 } else if (L->is_bound()) {
1356 PrintF("bound label to %d\n", L->pos());
1357 } else if (L->is_linked()) {
1358 Label l = *L;
1359 PrintF("unbound label");
1360 while (l.is_linked()) {
1361 Displacement disp = disp_at(&l);
1362 PrintF("@ %d ", l.pos());
1363 disp.print();
1364 PrintF("\n");
1365 disp.next(&l);
1366 }
1367 } else {
1368 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
1369 }
1370}
1371
1372
1373void Assembler::bind_to(Label* L, int pos) {
1374 EnsureSpace ensure_space(this);
1375 last_pc_ = NULL;
1376 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position
1377 while (L->is_linked()) {
1378 Displacement disp = disp_at(L);
1379 int fixup_pos = L->pos();
1380 if (disp.type() == Displacement::CODE_RELATIVE) {
1381 // Relative to Code* heap object pointer.
1382 long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
1383 } else {
1384 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
1385 ASSERT(byte_at(fixup_pos - 1) == 0xE9); // jmp expected
1386 }
1387 // relative address, relative to point after address
1388 int imm32 = pos - (fixup_pos + sizeof(int32_t));
1389 long_at_put(fixup_pos, imm32);
1390 }
1391 disp.next(L);
1392 }
1393 L->bind_to(pos);
1394}
1395
1396
1397void Assembler::link_to(Label* L, Label* appendix) {
1398 EnsureSpace ensure_space(this);
1399 last_pc_ = NULL;
1400 if (appendix->is_linked()) {
1401 if (L->is_linked()) {
1402 // append appendix to L's list
1403 Label p;
1404 Label q = *L;
1405 do {
1406 p = q;
1407 Displacement disp = disp_at(&q);
1408 disp.next(&q);
1409 } while (q.is_linked());
1410 Displacement disp = disp_at(&p);
1411 disp.link_to(appendix);
1412 disp_at_put(&p, disp);
1413 p.Unuse(); // to avoid assertion failure in ~Label
1414 } else {
1415 // L is empty, simply use appendix
1416 *L = *appendix;
1417 }
1418 }
1419 appendix->Unuse(); // appendix should not be used anymore
1420}
1421
1422
1423void Assembler::bind(Label* L) {
1424 EnsureSpace ensure_space(this);
1425 last_pc_ = NULL;
1426 ASSERT(!L->is_bound()); // label can only be bound once
1427 bind_to(L, pc_offset());
1428}
1429
1430
1431void Assembler::call(Label* L) {
1432 EnsureSpace ensure_space(this);
1433 last_pc_ = pc_;
1434 if (L->is_bound()) {
1435 const int long_size = 5;
1436 int offs = L->pos() - pc_offset();
1437 ASSERT(offs <= 0);
1438 // 1110 1000 #32-bit disp
1439 EMIT(0xE8);
1440 emit(offs - long_size);
1441 } else {
1442 // 1110 1000 #32-bit disp
1443 EMIT(0xE8);
1444 emit_disp(L, Displacement::OTHER);
1445 }
1446}
1447
1448
1449void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
1450 EnsureSpace ensure_space(this);
1451 last_pc_ = pc_;
1452 ASSERT(!RelocInfo::IsCodeTarget(rmode));
1453 EMIT(0xE8);
1454 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1455}
1456
1457
1458void Assembler::call(const Operand& adr) {
1459 EnsureSpace ensure_space(this);
1460 last_pc_ = pc_;
1461 EMIT(0xFF);
1462 emit_operand(edx, adr);
1463}
1464
1465
1466void Assembler::call(Handle<Code> code, RelocInfo::Mode rmode) {
1467 WriteRecordedPositions();
1468 EnsureSpace ensure_space(this);
1469 last_pc_ = pc_;
1470 ASSERT(RelocInfo::IsCodeTarget(rmode));
1471 EMIT(0xE8);
1472 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
1473}
1474
1475
1476void Assembler::jmp(Label* L) {
1477 EnsureSpace ensure_space(this);
1478 last_pc_ = pc_;
1479 if (L->is_bound()) {
1480 const int short_size = 2;
1481 const int long_size = 5;
1482 int offs = L->pos() - pc_offset();
1483 ASSERT(offs <= 0);
1484 if (is_int8(offs - short_size)) {
1485 // 1110 1011 #8-bit disp
1486 EMIT(0xEB);
1487 EMIT((offs - short_size) & 0xFF);
1488 } else {
1489 // 1110 1001 #32-bit disp
1490 EMIT(0xE9);
1491 emit(offs - long_size);
1492 }
1493 } else {
1494 // 1110 1001 #32-bit disp
1495 EMIT(0xE9);
1496 emit_disp(L, Displacement::UNCONDITIONAL_JUMP);
1497 }
1498}
1499
1500
1501void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
1502 EnsureSpace ensure_space(this);
1503 last_pc_ = pc_;
1504 ASSERT(!RelocInfo::IsCodeTarget(rmode));
1505 EMIT(0xE9);
1506 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1507}
1508
1509
1510void Assembler::jmp(const Operand& adr) {
1511 EnsureSpace ensure_space(this);
1512 last_pc_ = pc_;
1513 EMIT(0xFF);
1514 emit_operand(esp, adr);
1515}
1516
1517
1518void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
1519 EnsureSpace ensure_space(this);
1520 last_pc_ = pc_;
1521 ASSERT(RelocInfo::IsCodeTarget(rmode));
1522 EMIT(0xE9);
1523 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
1524}
1525
1526
1527
1528void Assembler::j(Condition cc, Label* L, Hint hint) {
1529 EnsureSpace ensure_space(this);
1530 last_pc_ = pc_;
1531 ASSERT(0 <= cc && cc < 16);
1532 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1533 if (L->is_bound()) {
1534 const int short_size = 2;
1535 const int long_size = 6;
1536 int offs = L->pos() - pc_offset();
1537 ASSERT(offs <= 0);
1538 if (is_int8(offs - short_size)) {
1539 // 0111 tttn #8-bit disp
1540 EMIT(0x70 | cc);
1541 EMIT((offs - short_size) & 0xFF);
1542 } else {
1543 // 0000 1111 1000 tttn #32-bit disp
1544 EMIT(0x0F);
1545 EMIT(0x80 | cc);
1546 emit(offs - long_size);
1547 }
1548 } else {
1549 // 0000 1111 1000 tttn #32-bit disp
1550 // Note: could eliminate cond. jumps to this jump if condition
1551 // is the same however, seems to be rather unlikely case.
1552 EMIT(0x0F);
1553 EMIT(0x80 | cc);
1554 emit_disp(L, Displacement::OTHER);
1555 }
1556}
1557
1558
1559void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint) {
1560 EnsureSpace ensure_space(this);
1561 last_pc_ = pc_;
1562 ASSERT((0 <= cc) && (cc < 16));
1563 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1564 // 0000 1111 1000 tttn #32-bit disp
1565 EMIT(0x0F);
1566 EMIT(0x80 | cc);
1567 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1568}
1569
1570
1571void Assembler::j(Condition cc, Handle<Code> code, Hint hint) {
1572 EnsureSpace ensure_space(this);
1573 last_pc_ = pc_;
1574 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1575 // 0000 1111 1000 tttn #32-bit disp
1576 EMIT(0x0F);
1577 EMIT(0x80 | cc);
1578 emit(reinterpret_cast<intptr_t>(code.location()), RelocInfo::CODE_TARGET);
1579}
1580
1581
1582// FPU instructions
1583
1584
1585void Assembler::fld(int i) {
1586 EnsureSpace ensure_space(this);
1587 last_pc_ = pc_;
1588 emit_farith(0xD9, 0xC0, i);
1589}
1590
1591
1592void Assembler::fld1() {
1593 EnsureSpace ensure_space(this);
1594 last_pc_ = pc_;
1595 EMIT(0xD9);
1596 EMIT(0xE8);
1597}
1598
1599
1600void Assembler::fldz() {
1601 EnsureSpace ensure_space(this);
1602 last_pc_ = pc_;
1603 EMIT(0xD9);
1604 EMIT(0xEE);
1605}
1606
1607
1608void Assembler::fld_s(const Operand& adr) {
1609 EnsureSpace ensure_space(this);
1610 last_pc_ = pc_;
1611 EMIT(0xD9);
1612 emit_operand(eax, adr);
1613}
1614
1615
1616void Assembler::fld_d(const Operand& adr) {
1617 EnsureSpace ensure_space(this);
1618 last_pc_ = pc_;
1619 EMIT(0xDD);
1620 emit_operand(eax, adr);
1621}
1622
1623
1624void Assembler::fstp_s(const Operand& adr) {
1625 EnsureSpace ensure_space(this);
1626 last_pc_ = pc_;
1627 EMIT(0xD9);
1628 emit_operand(ebx, adr);
1629}
1630
1631
1632void Assembler::fstp_d(const Operand& adr) {
1633 EnsureSpace ensure_space(this);
1634 last_pc_ = pc_;
1635 EMIT(0xDD);
1636 emit_operand(ebx, adr);
1637}
1638
1639
1640void Assembler::fild_s(const Operand& adr) {
1641 EnsureSpace ensure_space(this);
1642 last_pc_ = pc_;
1643 EMIT(0xDB);
1644 emit_operand(eax, adr);
1645}
1646
1647
1648void Assembler::fild_d(const Operand& adr) {
1649 EnsureSpace ensure_space(this);
1650 last_pc_ = pc_;
1651 EMIT(0xDF);
1652 emit_operand(ebp, adr);
1653}
1654
1655
1656void Assembler::fistp_s(const Operand& adr) {
1657 EnsureSpace ensure_space(this);
1658 last_pc_ = pc_;
1659 EMIT(0xDB);
1660 emit_operand(ebx, adr);
1661}
1662
1663
1664void Assembler::fisttp_s(const Operand& adr) {
1665 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE3));
1666 EnsureSpace ensure_space(this);
1667 last_pc_ = pc_;
1668 EMIT(0xDB);
1669 emit_operand(ecx, adr);
1670}
1671
1672
1673void Assembler::fist_s(const Operand& adr) {
1674 EnsureSpace ensure_space(this);
1675 last_pc_ = pc_;
1676 EMIT(0xDB);
1677 emit_operand(edx, adr);
1678}
1679
1680
1681void Assembler::fistp_d(const Operand& adr) {
1682 EnsureSpace ensure_space(this);
1683 last_pc_ = pc_;
1684 EMIT(0xDF);
1685 emit_operand(edi, adr);
1686}
1687
1688
1689void Assembler::fabs() {
1690 EnsureSpace ensure_space(this);
1691 last_pc_ = pc_;
1692 EMIT(0xD9);
1693 EMIT(0xE1);
1694}
1695
1696
1697void Assembler::fchs() {
1698 EnsureSpace ensure_space(this);
1699 last_pc_ = pc_;
1700 EMIT(0xD9);
1701 EMIT(0xE0);
1702}
1703
1704
1705void Assembler::fcos() {
1706 EnsureSpace ensure_space(this);
1707 last_pc_ = pc_;
1708 EMIT(0xD9);
1709 EMIT(0xFF);
1710}
1711
1712
1713void Assembler::fsin() {
1714 EnsureSpace ensure_space(this);
1715 last_pc_ = pc_;
1716 EMIT(0xD9);
1717 EMIT(0xFE);
1718}
1719
1720
1721void Assembler::fadd(int i) {
1722 EnsureSpace ensure_space(this);
1723 last_pc_ = pc_;
1724 emit_farith(0xDC, 0xC0, i);
1725}
1726
1727
1728void Assembler::fsub(int i) {
1729 EnsureSpace ensure_space(this);
1730 last_pc_ = pc_;
1731 emit_farith(0xDC, 0xE8, i);
1732}
1733
1734
1735void Assembler::fisub_s(const Operand& adr) {
1736 EnsureSpace ensure_space(this);
1737 last_pc_ = pc_;
1738 EMIT(0xDA);
1739 emit_operand(esp, adr);
1740}
1741
1742
1743void Assembler::fmul(int i) {
1744 EnsureSpace ensure_space(this);
1745 last_pc_ = pc_;
1746 emit_farith(0xDC, 0xC8, i);
1747}
1748
1749
1750void Assembler::fdiv(int i) {
1751 EnsureSpace ensure_space(this);
1752 last_pc_ = pc_;
1753 emit_farith(0xDC, 0xF8, i);
1754}
1755
1756
1757void Assembler::faddp(int i) {
1758 EnsureSpace ensure_space(this);
1759 last_pc_ = pc_;
1760 emit_farith(0xDE, 0xC0, i);
1761}
1762
1763
1764void Assembler::fsubp(int i) {
1765 EnsureSpace ensure_space(this);
1766 last_pc_ = pc_;
1767 emit_farith(0xDE, 0xE8, i);
1768}
1769
1770
1771void Assembler::fsubrp(int i) {
1772 EnsureSpace ensure_space(this);
1773 last_pc_ = pc_;
1774 emit_farith(0xDE, 0xE0, i);
1775}
1776
1777
1778void Assembler::fmulp(int i) {
1779 EnsureSpace ensure_space(this);
1780 last_pc_ = pc_;
1781 emit_farith(0xDE, 0xC8, i);
1782}
1783
1784
1785void Assembler::fdivp(int i) {
1786 EnsureSpace ensure_space(this);
1787 last_pc_ = pc_;
1788 emit_farith(0xDE, 0xF8, i);
1789}
1790
1791
1792void Assembler::fprem() {
1793 EnsureSpace ensure_space(this);
1794 last_pc_ = pc_;
1795 EMIT(0xD9);
1796 EMIT(0xF8);
1797}
1798
1799
1800void Assembler::fprem1() {
1801 EnsureSpace ensure_space(this);
1802 last_pc_ = pc_;
1803 EMIT(0xD9);
1804 EMIT(0xF5);
1805}
1806
1807
1808void Assembler::fxch(int i) {
1809 EnsureSpace ensure_space(this);
1810 last_pc_ = pc_;
1811 emit_farith(0xD9, 0xC8, i);
1812}
1813
1814
1815void Assembler::fincstp() {
1816 EnsureSpace ensure_space(this);
1817 last_pc_ = pc_;
1818 EMIT(0xD9);
1819 EMIT(0xF7);
1820}
1821
1822
1823void Assembler::ffree(int i) {
1824 EnsureSpace ensure_space(this);
1825 last_pc_ = pc_;
1826 emit_farith(0xDD, 0xC0, i);
1827}
1828
1829
1830void Assembler::ftst() {
1831 EnsureSpace ensure_space(this);
1832 last_pc_ = pc_;
1833 EMIT(0xD9);
1834 EMIT(0xE4);
1835}
1836
1837
1838void Assembler::fucomp(int i) {
1839 EnsureSpace ensure_space(this);
1840 last_pc_ = pc_;
1841 emit_farith(0xDD, 0xE8, i);
1842}
1843
1844
1845void Assembler::fucompp() {
1846 EnsureSpace ensure_space(this);
1847 last_pc_ = pc_;
1848 EMIT(0xDA);
1849 EMIT(0xE9);
1850}
1851
1852
Steve Block3ce2e202009-11-05 08:53:23 +00001853void Assembler::fucomi(int i) {
1854 EnsureSpace ensure_space(this);
1855 last_pc_ = pc_;
1856 EMIT(0xDB);
1857 EMIT(0xE8 + i);
1858}
1859
1860
1861void Assembler::fucomip() {
1862 EnsureSpace ensure_space(this);
1863 last_pc_ = pc_;
1864 EMIT(0xDF);
1865 EMIT(0xE9);
1866}
1867
1868
Steve Blocka7e24c12009-10-30 11:49:00 +00001869void Assembler::fcompp() {
1870 EnsureSpace ensure_space(this);
1871 last_pc_ = pc_;
1872 EMIT(0xDE);
1873 EMIT(0xD9);
1874}
1875
1876
1877void Assembler::fnstsw_ax() {
1878 EnsureSpace ensure_space(this);
1879 last_pc_ = pc_;
1880 EMIT(0xDF);
1881 EMIT(0xE0);
1882}
1883
1884
1885void Assembler::fwait() {
1886 EnsureSpace ensure_space(this);
1887 last_pc_ = pc_;
1888 EMIT(0x9B);
1889}
1890
1891
1892void Assembler::frndint() {
1893 EnsureSpace ensure_space(this);
1894 last_pc_ = pc_;
1895 EMIT(0xD9);
1896 EMIT(0xFC);
1897}
1898
1899
1900void Assembler::fnclex() {
1901 EnsureSpace ensure_space(this);
1902 last_pc_ = pc_;
1903 EMIT(0xDB);
1904 EMIT(0xE2);
1905}
1906
1907
1908void Assembler::sahf() {
1909 EnsureSpace ensure_space(this);
1910 last_pc_ = pc_;
1911 EMIT(0x9E);
1912}
1913
1914
1915void Assembler::setcc(Condition cc, Register reg) {
1916 ASSERT(reg.is_byte_register());
1917 EnsureSpace ensure_space(this);
1918 last_pc_ = pc_;
1919 EMIT(0x0F);
1920 EMIT(0x90 | cc);
1921 EMIT(0xC0 | reg.code());
1922}
1923
1924
1925void Assembler::cvttss2si(Register dst, const Operand& src) {
1926 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1927 EnsureSpace ensure_space(this);
1928 last_pc_ = pc_;
1929 EMIT(0xF3);
1930 EMIT(0x0F);
1931 EMIT(0x2C);
1932 emit_operand(dst, src);
1933}
1934
1935
1936void Assembler::cvttsd2si(Register dst, const Operand& src) {
1937 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1938 EnsureSpace ensure_space(this);
1939 last_pc_ = pc_;
1940 EMIT(0xF2);
1941 EMIT(0x0F);
1942 EMIT(0x2C);
1943 emit_operand(dst, src);
1944}
1945
1946
1947void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
1948 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1949 EnsureSpace ensure_space(this);
1950 last_pc_ = pc_;
1951 EMIT(0xF2);
1952 EMIT(0x0F);
1953 EMIT(0x2A);
1954 emit_sse_operand(dst, src);
1955}
1956
1957
1958void Assembler::addsd(XMMRegister dst, XMMRegister src) {
1959 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1960 EnsureSpace ensure_space(this);
1961 last_pc_ = pc_;
1962 EMIT(0xF2);
1963 EMIT(0x0F);
1964 EMIT(0x58);
1965 emit_sse_operand(dst, src);
1966}
1967
1968
1969void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
1970 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1971 EnsureSpace ensure_space(this);
1972 last_pc_ = pc_;
1973 EMIT(0xF2);
1974 EMIT(0x0F);
1975 EMIT(0x59);
1976 emit_sse_operand(dst, src);
1977}
1978
1979
1980void Assembler::subsd(XMMRegister dst, XMMRegister src) {
1981 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1982 EnsureSpace ensure_space(this);
1983 last_pc_ = pc_;
1984 EMIT(0xF2);
1985 EMIT(0x0F);
1986 EMIT(0x5C);
1987 emit_sse_operand(dst, src);
1988}
1989
1990
1991void Assembler::divsd(XMMRegister dst, XMMRegister src) {
1992 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1993 EnsureSpace ensure_space(this);
1994 last_pc_ = pc_;
1995 EMIT(0xF2);
1996 EMIT(0x0F);
1997 EMIT(0x5E);
1998 emit_sse_operand(dst, src);
1999}
2000
2001
2002void Assembler::comisd(XMMRegister dst, XMMRegister src) {
2003 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
2004 EnsureSpace ensure_space(this);
2005 last_pc_ = pc_;
2006 EMIT(0x66);
2007 EMIT(0x0F);
2008 EMIT(0x2F);
2009 emit_sse_operand(dst, src);
2010}
2011
2012
2013void Assembler::movdbl(XMMRegister dst, const Operand& src) {
2014 EnsureSpace ensure_space(this);
2015 last_pc_ = pc_;
2016 movsd(dst, src);
2017}
2018
2019
2020void Assembler::movdbl(const Operand& dst, XMMRegister src) {
2021 EnsureSpace ensure_space(this);
2022 last_pc_ = pc_;
2023 movsd(dst, src);
2024}
2025
2026
2027void Assembler::movsd(const Operand& dst, XMMRegister src ) {
2028 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
2029 EnsureSpace ensure_space(this);
2030 last_pc_ = pc_;
2031 EMIT(0xF2); // double
2032 EMIT(0x0F);
2033 EMIT(0x11); // store
2034 emit_sse_operand(src, dst);
2035}
2036
2037
2038void Assembler::movsd(XMMRegister dst, const Operand& src) {
2039 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
2040 EnsureSpace ensure_space(this);
2041 last_pc_ = pc_;
2042 EMIT(0xF2); // double
2043 EMIT(0x0F);
2044 EMIT(0x10); // load
2045 emit_sse_operand(dst, src);
2046}
2047
2048
2049void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
2050 Register ireg = { reg.code() };
2051 emit_operand(ireg, adr);
2052}
2053
2054
2055void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
2056 EMIT(0xC0 | dst.code() << 3 | src.code());
2057}
2058
2059
2060void Assembler::Print() {
2061 Disassembler::Decode(stdout, buffer_, pc_);
2062}
2063
2064
2065void Assembler::RecordJSReturn() {
2066 WriteRecordedPositions();
2067 EnsureSpace ensure_space(this);
2068 RecordRelocInfo(RelocInfo::JS_RETURN);
2069}
2070
2071
2072void Assembler::RecordComment(const char* msg) {
2073 if (FLAG_debug_code) {
2074 EnsureSpace ensure_space(this);
2075 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
2076 }
2077}
2078
2079
2080void Assembler::RecordPosition(int pos) {
2081 ASSERT(pos != RelocInfo::kNoPosition);
2082 ASSERT(pos >= 0);
2083 current_position_ = pos;
2084}
2085
2086
2087void Assembler::RecordStatementPosition(int pos) {
2088 ASSERT(pos != RelocInfo::kNoPosition);
2089 ASSERT(pos >= 0);
2090 current_statement_position_ = pos;
2091}
2092
2093
2094void Assembler::WriteRecordedPositions() {
2095 // Write the statement position if it is different from what was written last
2096 // time.
2097 if (current_statement_position_ != written_statement_position_) {
2098 EnsureSpace ensure_space(this);
2099 RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
2100 written_statement_position_ = current_statement_position_;
2101 }
2102
2103 // Write the position if it is different from what was written last time and
2104 // also different from the written statement position.
2105 if (current_position_ != written_position_ &&
2106 current_position_ != written_statement_position_) {
2107 EnsureSpace ensure_space(this);
2108 RecordRelocInfo(RelocInfo::POSITION, current_position_);
2109 written_position_ = current_position_;
2110 }
2111}
2112
2113
2114void Assembler::GrowBuffer() {
2115 ASSERT(overflow()); // should not call this otherwise
2116 if (!own_buffer_) FATAL("external code buffer is too small");
2117
2118 // compute new buffer size
2119 CodeDesc desc; // the new buffer
2120 if (buffer_size_ < 4*KB) {
2121 desc.buffer_size = 4*KB;
2122 } else {
2123 desc.buffer_size = 2*buffer_size_;
2124 }
2125 // Some internal data structures overflow for very large buffers,
2126 // they must ensure that kMaximalBufferSize is not too large.
2127 if ((desc.buffer_size > kMaximalBufferSize) ||
Steve Block3ce2e202009-11-05 08:53:23 +00002128 (desc.buffer_size > Heap::MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002129 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
2130 }
2131
2132 // setup new buffer
2133 desc.buffer = NewArray<byte>(desc.buffer_size);
2134 desc.instr_size = pc_offset();
2135 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
2136
2137 // Clear the buffer in debug mode. Use 'int3' instructions to make
2138 // sure to get into problems if we ever run uninitialized code.
2139#ifdef DEBUG
2140 memset(desc.buffer, 0xCC, desc.buffer_size);
2141#endif
2142
2143 // copy the data
2144 int pc_delta = desc.buffer - buffer_;
2145 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
2146 memmove(desc.buffer, buffer_, desc.instr_size);
2147 memmove(rc_delta + reloc_info_writer.pos(),
2148 reloc_info_writer.pos(), desc.reloc_size);
2149
2150 // switch buffers
2151 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
2152 spare_buffer_ = buffer_;
2153 } else {
2154 DeleteArray(buffer_);
2155 }
2156 buffer_ = desc.buffer;
2157 buffer_size_ = desc.buffer_size;
2158 pc_ += pc_delta;
2159 if (last_pc_ != NULL) {
2160 last_pc_ += pc_delta;
2161 }
2162 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2163 reloc_info_writer.last_pc() + pc_delta);
2164
2165 // relocate runtime entries
2166 for (RelocIterator it(desc); !it.done(); it.next()) {
2167 RelocInfo::Mode rmode = it.rinfo()->rmode();
2168 if (rmode == RelocInfo::RUNTIME_ENTRY) {
2169 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2170 *p -= pc_delta; // relocate entry
2171 } else if (rmode == RelocInfo::INTERNAL_REFERENCE) {
2172 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2173 if (*p != 0) { // 0 means uninitialized.
2174 *p += pc_delta;
2175 }
2176 }
2177 }
2178
2179 ASSERT(!overflow());
2180}
2181
2182
2183void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
2184 ASSERT(is_uint8(op1) && is_uint8(op2)); // wrong opcode
2185 ASSERT(is_uint8(imm8));
2186 ASSERT((op1 & 0x01) == 0); // should be 8bit operation
2187 EMIT(op1);
2188 EMIT(op2 | dst.code());
2189 EMIT(imm8);
2190}
2191
2192
2193void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
2194 ASSERT((0 <= sel) && (sel <= 7));
2195 Register ireg = { sel };
2196 if (x.is_int8()) {
2197 EMIT(0x83); // using a sign-extended 8-bit immediate.
2198 emit_operand(ireg, dst);
2199 EMIT(x.x_ & 0xFF);
2200 } else if (dst.is_reg(eax)) {
2201 EMIT((sel << 3) | 0x05); // short form if the destination is eax.
2202 emit(x);
2203 } else {
2204 EMIT(0x81); // using a literal 32-bit immediate.
2205 emit_operand(ireg, dst);
2206 emit(x);
2207 }
2208}
2209
2210
2211void Assembler::emit_operand(Register reg, const Operand& adr) {
2212 const unsigned length = adr.len_;
2213 ASSERT(length > 0);
2214
2215 // Emit updated ModRM byte containing the given register.
2216 pc_[0] = (adr.buf_[0] & ~0x38) | (reg.code() << 3);
2217
2218 // Emit the rest of the encoded operand.
2219 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
2220 pc_ += length;
2221
2222 // Emit relocation information if necessary.
2223 if (length >= sizeof(int32_t) && adr.rmode_ != RelocInfo::NONE) {
2224 pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
2225 RecordRelocInfo(adr.rmode_);
2226 pc_ += sizeof(int32_t);
2227 }
2228}
2229
2230
2231void Assembler::emit_farith(int b1, int b2, int i) {
2232 ASSERT(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2233 ASSERT(0 <= i && i < 8); // illegal stack offset
2234 EMIT(b1);
2235 EMIT(b2 + i);
2236}
2237
2238
2239void Assembler::dd(uint32_t data, RelocInfo::Mode reloc_info) {
2240 EnsureSpace ensure_space(this);
2241 emit(data, reloc_info);
2242}
2243
2244
2245void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2246 ASSERT(rmode != RelocInfo::NONE);
2247 // Don't record external references unless the heap will be serialized.
2248 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
2249 !Serializer::enabled() &&
2250 !FLAG_debug_code) {
2251 return;
2252 }
2253 RelocInfo rinfo(pc_, rmode, data);
2254 reloc_info_writer.Write(&rinfo);
2255}
2256
2257
2258#ifdef GENERATED_CODE_COVERAGE
2259static FILE* coverage_log = NULL;
2260
2261
2262static void InitCoverageLog() {
2263 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
2264 if (file_name != NULL) {
2265 coverage_log = fopen(file_name, "aw+");
2266 }
2267}
2268
2269
2270void LogGeneratedCodeCoverage(const char* file_line) {
2271 const char* return_address = (&file_line)[-1];
2272 char* push_insn = const_cast<char*>(return_address - 12);
2273 push_insn[0] = 0xeb; // Relative branch insn.
2274 push_insn[1] = 13; // Skip over coverage insns.
2275 if (coverage_log != NULL) {
2276 fprintf(coverage_log, "%s\n", file_line);
2277 fflush(coverage_log);
2278 }
2279}
2280
2281#endif
2282
2283} } // namespace v8::internal