Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(398)

Side by Side Diff: src/assembler-ia32.cc

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

Powered by Google App Engine
This is Rietveld 408576698