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