V8 Project
assembler-x87.cc
Go to the documentation of this file.
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 
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 
61 void CpuFeatures::PrintTarget() { }
63 
64 
65 // -----------------------------------------------------------------------------
66 // Implementation of Displacement
67 
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 =
89 
90 
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 
101  return false;
102 }
103 
104 
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.
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 
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 
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 
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 
207 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 
213 bool Operand::is_reg_only() const {
214  return (buf_[0] & 0xF8) == 0xC0; // Addressing mode is register only.
215 }
216 
217 
218 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 
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 
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 
269 void Assembler::Align(int m) {
271  int mask = m - 1;
272  int addr = pc_offset();
273  Nop((m - (addr & mask)) & mask);
274 }
275 
276 
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 
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 
298 void Assembler::CodeTargetAlign() {
299  Align(16); // Preferred alignment of jump targets on ia32.
300 }
301 
302 
303 void Assembler::cpuid() {
304  EnsureSpace ensure_space(this);
305  EMIT(0x0F);
306  EMIT(0xA2);
307 }
308 
309 
310 void Assembler::pushad() {
311  EnsureSpace ensure_space(this);
312  EMIT(0x60);
313 }
314 
315 
316 void Assembler::popad() {
317  EnsureSpace ensure_space(this);
318  EMIT(0x61);
319 }
320 
321 
322 void Assembler::pushfd() {
323  EnsureSpace ensure_space(this);
324  EMIT(0x9C);
325 }
326 
327 
328 void Assembler::popfd() {
329  EnsureSpace ensure_space(this);
330  EMIT(0x9D);
331 }
332 
333 
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 
346 void Assembler::push_imm32(int32_t imm32) {
347  EnsureSpace ensure_space(this);
348  EMIT(0x68);
349  emit(imm32);
350 }
351 
352 
353 void Assembler::push(Register src) {
354  EnsureSpace ensure_space(this);
355  EMIT(0x50 | src.code());
356 }
357 
358 
359 void Assembler::push(const Operand& src) {
360  EnsureSpace ensure_space(this);
361  EMIT(0xFF);
362  emit_operand(esi, src);
363 }
364 
365 
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 
373 void Assembler::pop(const Operand& dst) {
374  EnsureSpace ensure_space(this);
375  EMIT(0x8F);
376  emit_operand(eax, dst);
377 }
378 
379 
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 
388 void Assembler::leave() {
389  EnsureSpace ensure_space(this);
390  EMIT(0xC9);
391 }
392 
393 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
534 void Assembler::cld() {
535  EnsureSpace ensure_space(this);
536  EMIT(0xFC);
537 }
538 
539 
540 void Assembler::rep_movs() {
541  EnsureSpace ensure_space(this);
542  EMIT(0xF3);
543  EMIT(0xA5);
544 }
545 
546 
547 void Assembler::rep_stos() {
548  EnsureSpace ensure_space(this);
549  EMIT(0xF3);
550  EMIT(0xAB);
551 }
552 
553 
554 void Assembler::stos() {
555  EnsureSpace ensure_space(this);
556  EMIT(0xAB);
557 }
558 
559 
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 
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 
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 
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 
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 
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 
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 
612 void Assembler::and_(Register dst, int32_t imm32) {
613  and_(dst, Immediate(imm32));
614 }
615 
616 
617 void Assembler::and_(Register dst, const Immediate& x) {
618  EnsureSpace ensure_space(this);
619  emit_arith(4, Operand(dst), x);
620 }
621 
622 
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 
630 void Assembler::and_(const Operand& dst, const Immediate& x) {
631  EnsureSpace ensure_space(this);
632  emit_arith(4, dst, x);
633 }
634 
635 
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 
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 
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 
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 
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 
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 
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 
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 
700 void Assembler::cmp(const Operand& op, const Immediate& imm) {
701  EnsureSpace ensure_space(this);
702  emit_arith(7, op, imm);
703 }
704 
705 
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 
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 
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 
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 
735 void Assembler::dec_b(const Operand& dst) {
736  EnsureSpace ensure_space(this);
737  EMIT(0xFE);
738  emit_operand(ecx, dst);
739 }
740 
741 
742 void Assembler::dec(Register dst) {
743  EnsureSpace ensure_space(this);
744  EMIT(0x48 | dst.code());
745 }
746 
747 
748 void Assembler::dec(const Operand& dst) {
749  EnsureSpace ensure_space(this);
750  EMIT(0xFF);
751  emit_operand(ecx, dst);
752 }
753 
754 
755 void Assembler::cdq() {
756  EnsureSpace ensure_space(this);
757  EMIT(0x99);
758 }
759 
760 
761 void Assembler::idiv(const Operand& src) {
762  EnsureSpace ensure_space(this);
763  EMIT(0xF7);
764  emit_operand(edi, src);
765 }
766 
767 
768 void Assembler::div(const Operand& src) {
769  EnsureSpace ensure_space(this);
770  EMIT(0xF7);
771  emit_operand(esi, src);
772 }
773 
774 
775 void Assembler::imul(Register reg) {
776  EnsureSpace ensure_space(this);
777  EMIT(0xF7);
778  EMIT(0xE8 | reg.code());
779 }
780 
781 
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 
790 void Assembler::imul(Register dst, Register src, int32_t imm32) {
791  imul(dst, Operand(src), imm32);
792 }
793 
794 
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 
809 void Assembler::inc(Register dst) {
810  EnsureSpace ensure_space(this);
811  EMIT(0x40 | dst.code());
812 }
813 
814 
815 void Assembler::inc(const Operand& dst) {
816  EnsureSpace ensure_space(this);
817  EMIT(0xFF);
818  emit_operand(eax, dst);
819 }
820 
821 
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 
829 void Assembler::mul(Register src) {
830  EnsureSpace ensure_space(this);
831  EMIT(0xF7);
832  EMIT(0xE0 | src.code());
833 }
834 
835 
836 void Assembler::neg(Register dst) {
837  EnsureSpace ensure_space(this);
838  EMIT(0xF7);
839  EMIT(0xD8 | dst.code());
840 }
841 
842 
843 void Assembler::neg(const Operand& dst) {
844  EnsureSpace ensure_space(this);
845  EMIT(0xF7);
846  emit_operand(ebx, dst);
847 }
848 
849 
850 void Assembler::not_(Register dst) {
851  EnsureSpace ensure_space(this);
852  EMIT(0xF7);
853  EMIT(0xD0 | dst.code());
854 }
855 
856 
857 void Assembler::not_(const Operand& dst) {
858  EnsureSpace ensure_space(this);
859  EMIT(0xF7);
860  emit_operand(edx, dst);
861 }
862 
863 
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 
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 
877 void Assembler::or_(const Operand& dst, const Immediate& x) {
878  EnsureSpace ensure_space(this);
879  emit_arith(1, dst, x);
880 }
881 
882 
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 
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 
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 
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 
932 void Assembler::ror_cl(Register dst) {
933  EnsureSpace ensure_space(this);
934  EMIT(0xD3);
935  EMIT(0xC8 | dst.code());
936 }
937 
938 
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 
953 void Assembler::sar_cl(const Operand& dst) {
954  EnsureSpace ensure_space(this);
955  EMIT(0xD3);
956  emit_operand(edi, dst);
957 }
958 
959 
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 
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 
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 
989 void Assembler::shl_cl(const Operand& dst) {
990  EnsureSpace ensure_space(this);
991  EMIT(0xD3);
992  emit_operand(esp, dst);
993 }
994 
995 
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 
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 
1018 void Assembler::shr_cl(const Operand& dst) {
1019  EnsureSpace ensure_space(this);
1020  EMIT(0xD3);
1021  emit_operand(ebp, dst);
1022 }
1023 
1024 
1025 void Assembler::sub(const Operand& dst, const Immediate& x) {
1026  EnsureSpace ensure_space(this);
1027  emit_arith(5, dst, x);
1028 }
1029 
1030 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
1143 void Assembler::xor_(const Operand& dst, const Immediate& x) {
1144  EnsureSpace ensure_space(this);
1145  emit_arith(6, dst, x);
1146 }
1147 
1148 
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 
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 
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 
1173 void Assembler::hlt() {
1174  EnsureSpace ensure_space(this);
1175  EMIT(0xF4);
1176 }
1177 
1178 
1179 void Assembler::int3() {
1180  EnsureSpace ensure_space(this);
1181  EMIT(0xCC);
1182 }
1183 
1184 
1185 void Assembler::nop() {
1186  EnsureSpace ensure_space(this);
1187  EMIT(0x90);
1188 }
1189 
1190 
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 
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 
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 
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 
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 
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 
1312 int Assembler::CallSize(const Operand& adr) {
1313  // Call size is 1 (opcode) + adr.len_ (operand).
1314  return 1 + adr.len_;
1315 }
1316 
1317 
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 
1326 int Assembler::CallSize(Handle<Code> code, RelocInfo::Mode rmode) {
1327  return 1 /* EMIT */ + sizeof(uint32_t) /* emit */;
1328 }
1329 
1330 
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 
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 
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 
1382 void Assembler::jmp(const Operand& adr) {
1383  EnsureSpace ensure_space(this);
1384  EMIT(0xFF);
1385  emit_operand(esp, adr);
1386 }
1387 
1388 
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 
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 
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 
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 
1454 void Assembler::fld(int i) {
1455  EnsureSpace ensure_space(this);
1456  emit_farith(0xD9, 0xC0, i);
1457 }
1458 
1459 
1460 void Assembler::fstp(int i) {
1461  EnsureSpace ensure_space(this);
1462  emit_farith(0xDD, 0xD8, i);
1463 }
1464 
1465 
1466 void Assembler::fld1() {
1467  EnsureSpace ensure_space(this);
1468  EMIT(0xD9);
1469  EMIT(0xE8);
1470 }
1471 
1472 
1473 void Assembler::fldpi() {
1474  EnsureSpace ensure_space(this);
1475  EMIT(0xD9);
1476  EMIT(0xEB);
1477 }
1478 
1479 
1480 void Assembler::fldz() {
1481  EnsureSpace ensure_space(this);
1482  EMIT(0xD9);
1483  EMIT(0xEE);
1484 }
1485 
1486 
1487 void Assembler::fldln2() {
1488  EnsureSpace ensure_space(this);
1489  EMIT(0xD9);
1490  EMIT(0xED);
1491 }
1492 
1493 
1494 void Assembler::fld_s(const Operand& adr) {
1495  EnsureSpace ensure_space(this);
1496  EMIT(0xD9);
1497  emit_operand(eax, adr);
1498 }
1499 
1500 
1501 void Assembler::fld_d(const Operand& adr) {
1502  EnsureSpace ensure_space(this);
1503  EMIT(0xDD);
1504  emit_operand(eax, adr);
1505 }
1506 
1507 
1508 void Assembler::fstp_s(const Operand& adr) {
1509  EnsureSpace ensure_space(this);
1510  EMIT(0xD9);
1511  emit_operand(ebx, adr);
1512 }
1513 
1514 
1515 void Assembler::fst_s(const Operand& adr) {
1516  EnsureSpace ensure_space(this);
1517  EMIT(0xD9);
1518  emit_operand(edx, adr);
1519 }
1520 
1521 
1522 void Assembler::fldcw(const Operand& adr) {
1523  EnsureSpace ensure_space(this);
1524  EMIT(0xD9);
1525  emit_operand(ebp, adr);
1526 }
1527 
1528 
1529 void Assembler::fnstcw(const Operand& adr) {
1530  EnsureSpace ensure_space(this);
1531  EMIT(0xD9);
1532  emit_operand(edi, adr);
1533 }
1534 
1535 
1536 void Assembler::fstp_d(const Operand& adr) {
1537  EnsureSpace ensure_space(this);
1538  EMIT(0xDD);
1539  emit_operand(ebx, adr);
1540 }
1541 
1542 
1543 void Assembler::fst_d(const Operand& adr) {
1544  EnsureSpace ensure_space(this);
1545  EMIT(0xDD);
1546  emit_operand(edx, adr);
1547 }
1548 
1549 
1550 void Assembler::fild_s(const Operand& adr) {
1551  EnsureSpace ensure_space(this);
1552  EMIT(0xDB);
1553  emit_operand(eax, adr);
1554 }
1555 
1556 
1557 void Assembler::fild_d(const Operand& adr) {
1558  EnsureSpace ensure_space(this);
1559  EMIT(0xDF);
1560  emit_operand(ebp, adr);
1561 }
1562 
1563 
1564 void Assembler::fistp_s(const Operand& adr) {
1565  EnsureSpace ensure_space(this);
1566  EMIT(0xDB);
1567  emit_operand(ebx, adr);
1568 }
1569 
1570 
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 
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 
1587 void Assembler::fist_s(const Operand& adr) {
1588  EnsureSpace ensure_space(this);
1589  EMIT(0xDB);
1590  emit_operand(edx, adr);
1591 }
1592 
1593 
1594 void Assembler::fistp_d(const Operand& adr) {
1595  EnsureSpace ensure_space(this);
1596  EMIT(0xDF);
1597  emit_operand(edi, adr);
1598 }
1599 
1600 
1601 void Assembler::fabs() {
1602  EnsureSpace ensure_space(this);
1603  EMIT(0xD9);
1604  EMIT(0xE1);
1605 }
1606 
1607 
1608 void Assembler::fchs() {
1609  EnsureSpace ensure_space(this);
1610  EMIT(0xD9);
1611  EMIT(0xE0);
1612 }
1613 
1614 
1615 void Assembler::fsqrt() {
1616  EnsureSpace ensure_space(this);
1617  EMIT(0xD9);
1618  EMIT(0xFA);
1619 }
1620 
1621 
1622 void Assembler::fcos() {
1623  EnsureSpace ensure_space(this);
1624  EMIT(0xD9);
1625  EMIT(0xFF);
1626 }
1627 
1628 
1629 void Assembler::fsin() {
1630  EnsureSpace ensure_space(this);
1631  EMIT(0xD9);
1632  EMIT(0xFE);
1633 }
1634 
1635 
1636 void Assembler::fptan() {
1637  EnsureSpace ensure_space(this);
1638  EMIT(0xD9);
1639  EMIT(0xF2);
1640 }
1641 
1642 
1643 void Assembler::fyl2x() {
1644  EnsureSpace ensure_space(this);
1645  EMIT(0xD9);
1646  EMIT(0xF1);
1647 }
1648 
1649 
1650 void Assembler::f2xm1() {
1651  EnsureSpace ensure_space(this);
1652  EMIT(0xD9);
1653  EMIT(0xF0);
1654 }
1655 
1656 
1657 void Assembler::fscale() {
1658  EnsureSpace ensure_space(this);
1659  EMIT(0xD9);
1660  EMIT(0xFD);
1661 }
1662 
1663 
1664 void Assembler::fninit() {
1665  EnsureSpace ensure_space(this);
1666  EMIT(0xDB);
1667  EMIT(0xE3);
1668 }
1669 
1670 
1671 void Assembler::fadd(int i) {
1672  EnsureSpace ensure_space(this);
1673  emit_farith(0xDC, 0xC0, i);
1674 }
1675 
1676 
1677 void Assembler::fadd_i(int i) {
1678  EnsureSpace ensure_space(this);
1679  emit_farith(0xD8, 0xC0, i);
1680 }
1681 
1682 
1683 void Assembler::fadd_d(const Operand& adr) {
1684  EnsureSpace ensure_space(this);
1685  EMIT(0xDC);
1686  emit_operand(eax, adr);
1687 }
1688 
1689 
1690 void Assembler::fsub(int i) {
1691  EnsureSpace ensure_space(this);
1692  emit_farith(0xDC, 0xE8, i);
1693 }
1694 
1695 
1696 void Assembler::fsub_i(int i) {
1697  EnsureSpace ensure_space(this);
1698  emit_farith(0xD8, 0xE0, i);
1699 }
1700 
1701 
1702 void Assembler::fisub_s(const Operand& adr) {
1703  EnsureSpace ensure_space(this);
1704  EMIT(0xDA);
1705  emit_operand(esp, adr);
1706 }
1707 
1708 
1709 void Assembler::fmul_i(int i) {
1710  EnsureSpace ensure_space(this);
1711  emit_farith(0xD8, 0xC8, i);
1712 }
1713 
1714 
1715 void Assembler::fmul(int i) {
1716  EnsureSpace ensure_space(this);
1717  emit_farith(0xDC, 0xC8, i);
1718 }
1719 
1720 
1721 void Assembler::fdiv(int i) {
1722  EnsureSpace ensure_space(this);
1723  emit_farith(0xDC, 0xF8, i);
1724 }
1725 
1726 
1727 void Assembler::fdiv_i(int i) {
1728  EnsureSpace ensure_space(this);
1729  emit_farith(0xD8, 0xF0, i);
1730 }
1731 
1732 
1733 void Assembler::faddp(int i) {
1734  EnsureSpace ensure_space(this);
1735  emit_farith(0xDE, 0xC0, i);
1736 }
1737 
1738 
1739 void Assembler::fsubp(int i) {
1740  EnsureSpace ensure_space(this);
1741  emit_farith(0xDE, 0xE8, i);
1742 }
1743 
1744 
1745 void Assembler::fsubrp(int i) {
1746  EnsureSpace ensure_space(this);
1747  emit_farith(0xDE, 0xE0, i);
1748 }
1749 
1750 
1751 void Assembler::fmulp(int i) {
1752  EnsureSpace ensure_space(this);
1753  emit_farith(0xDE, 0xC8, i);
1754 }
1755 
1756 
1757 void Assembler::fdivp(int i) {
1758  EnsureSpace ensure_space(this);
1759  emit_farith(0xDE, 0xF8, i);
1760 }
1761 
1762 
1763 void Assembler::fprem() {
1764  EnsureSpace ensure_space(this);
1765  EMIT(0xD9);
1766  EMIT(0xF8);
1767 }
1768 
1769 
1770 void Assembler::fprem1() {
1771  EnsureSpace ensure_space(this);
1772  EMIT(0xD9);
1773  EMIT(0xF5);
1774 }
1775 
1776 
1777 void Assembler::fxch(int i) {
1778  EnsureSpace ensure_space(this);
1779  emit_farith(0xD9, 0xC8, i);
1780 }
1781 
1782 
1783 void Assembler::fincstp() {
1784  EnsureSpace ensure_space(this);
1785  EMIT(0xD9);
1786  EMIT(0xF7);
1787 }
1788 
1789 
1790 void Assembler::ffree(int i) {
1791  EnsureSpace ensure_space(this);
1792  emit_farith(0xDD, 0xC0, i);
1793 }
1794 
1795 
1796 void Assembler::ftst() {
1797  EnsureSpace ensure_space(this);
1798  EMIT(0xD9);
1799  EMIT(0xE4);
1800 }
1801 
1802 
1803 void Assembler::fxam() {
1804  EnsureSpace ensure_space(this);
1805  EMIT(0xD9);
1806  EMIT(0xE5);
1807 }
1808 
1809 
1810 void Assembler::fucomp(int i) {
1811  EnsureSpace ensure_space(this);
1812  emit_farith(0xDD, 0xE8, i);
1813 }
1814 
1815 
1816 void Assembler::fucompp() {
1817  EnsureSpace ensure_space(this);
1818  EMIT(0xDA);
1819  EMIT(0xE9);
1820 }
1821 
1822 
1823 void Assembler::fucomi(int i) {
1824  EnsureSpace ensure_space(this);
1825  EMIT(0xDB);
1826  EMIT(0xE8 + i);
1827 }
1828 
1829 
1830 void Assembler::fucomip() {
1831  EnsureSpace ensure_space(this);
1832  EMIT(0xDF);
1833  EMIT(0xE9);
1834 }
1835 
1836 
1837 void Assembler::fcompp() {
1838  EnsureSpace ensure_space(this);
1839  EMIT(0xDE);
1840  EMIT(0xD9);
1841 }
1842 
1843 
1844 void Assembler::fnstsw_ax() {
1845  EnsureSpace ensure_space(this);
1846  EMIT(0xDF);
1847  EMIT(0xE0);
1848 }
1849 
1850 
1851 void Assembler::fwait() {
1852  EnsureSpace ensure_space(this);
1853  EMIT(0x9B);
1854 }
1855 
1856 
1857 void Assembler::frndint() {
1858  EnsureSpace ensure_space(this);
1859  EMIT(0xD9);
1860  EMIT(0xFC);
1861 }
1862 
1863 
1864 void Assembler::fnclex() {
1865  EnsureSpace ensure_space(this);
1866  EMIT(0xDB);
1867  EMIT(0xE2);
1868 }
1869 
1870 
1871 void Assembler::fnsave(const Operand& adr) {
1872  EnsureSpace ensure_space(this);
1873  EMIT(0xDD);
1874  emit_operand(esi, adr);
1875 }
1876 
1877 
1878 void Assembler::frstor(const Operand& adr) {
1879  EnsureSpace ensure_space(this);
1880  EMIT(0xDD);
1881  emit_operand(esp, adr);
1882 }
1883 
1884 
1885 void Assembler::sahf() {
1886  EnsureSpace ensure_space(this);
1887  EMIT(0x9E);
1888 }
1889 
1890 
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 
1900 void Assembler::RecordJSReturn() {
1901  positions_recorder()->WriteRecordedPositions();
1902  EnsureSpace ensure_space(this);
1903  RecordRelocInfo(RelocInfo::JS_RETURN);
1904 }
1905 
1906 
1907 void Assembler::RecordDebugBreakSlot() {
1908  positions_recorder()->WriteRecordedPositions();
1909  EnsureSpace ensure_space(this);
1910  RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
1911 }
1912 
1913 
1914 void Assembler::RecordComment(const char* msg, bool force) {
1915  if (FLAG_code_comments || force) {
1916  EnsureSpace ensure_space(this);
1917  RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
1918  }
1919 }
1920 
1921 
1922 void Assembler::GrowBuffer() {
1923  DCHECK(buffer_overflow());
1924  if (!own_buffer_) FATAL("external code buffer is too small");
1925 
1926  // Compute new buffer size.
1927  CodeDesc desc; // the new buffer
1928  desc.buffer_size = 2 * buffer_size_;
1929 
1930  // Some internal data structures overflow for very large buffers,
1931  // they must ensure that kMaximalBufferSize is not too large.
1932  if ((desc.buffer_size > kMaximalBufferSize) ||
1933  (desc.buffer_size > isolate()->heap()->MaxOldGenerationSize())) {
1934  V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
1935  }
1936 
1937  // Set up new buffer.
1938  desc.buffer = NewArray<byte>(desc.buffer_size);
1939  desc.instr_size = pc_offset();
1940  desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
1941 
1942  // Clear the buffer in debug mode. Use 'int3' instructions to make
1943  // sure to get into problems if we ever run uninitialized code.
1944 #ifdef DEBUG
1945  memset(desc.buffer, 0xCC, desc.buffer_size);
1946 #endif
1947 
1948  // Copy the data.
1949  int pc_delta = desc.buffer - buffer_;
1950  int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
1951  MemMove(desc.buffer, buffer_, desc.instr_size);
1952  MemMove(rc_delta + reloc_info_writer.pos(), reloc_info_writer.pos(),
1953  desc.reloc_size);
1954 
1955  DeleteArray(buffer_);
1956  buffer_ = desc.buffer;
1957  buffer_size_ = desc.buffer_size;
1958  pc_ += pc_delta;
1959  reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
1960  reloc_info_writer.last_pc() + pc_delta);
1961 
1962  // Relocate runtime entries.
1963  for (RelocIterator it(desc); !it.done(); it.next()) {
1964  RelocInfo::Mode rmode = it.rinfo()->rmode();
1965  if (rmode == RelocInfo::INTERNAL_REFERENCE) {
1966  int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
1967  if (*p != 0) { // 0 means uninitialized.
1968  *p += pc_delta;
1969  }
1970  }
1971  }
1972 
1973  DCHECK(!buffer_overflow());
1974 }
1975 
1976 
1977 void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
1978  DCHECK(is_uint8(op1) && is_uint8(op2)); // wrong opcode
1979  DCHECK(is_uint8(imm8));
1980  DCHECK((op1 & 0x01) == 0); // should be 8bit operation
1981  EMIT(op1);
1982  EMIT(op2 | dst.code());
1983  EMIT(imm8);
1984 }
1985 
1986 
1987 void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
1988  DCHECK((0 <= sel) && (sel <= 7));
1989  Register ireg = { sel };
1990  if (x.is_int8()) {
1991  EMIT(0x83); // using a sign-extended 8-bit immediate.
1992  emit_operand(ireg, dst);
1993  EMIT(x.x_ & 0xFF);
1994  } else if (dst.is_reg(eax)) {
1995  EMIT((sel << 3) | 0x05); // short form if the destination is eax.
1996  emit(x);
1997  } else {
1998  EMIT(0x81); // using a literal 32-bit immediate.
1999  emit_operand(ireg, dst);
2000  emit(x);
2001  }
2002 }
2003 
2004 
2005 void Assembler::emit_operand(Register reg, const Operand& adr) {
2006  const unsigned length = adr.len_;
2007  DCHECK(length > 0);
2008 
2009  // Emit updated ModRM byte containing the given register.
2010  pc_[0] = (adr.buf_[0] & ~0x38) | (reg.code() << 3);
2011 
2012  // Emit the rest of the encoded operand.
2013  for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
2014  pc_ += length;
2015 
2016  // Emit relocation information if necessary.
2017  if (length >= sizeof(int32_t) && !RelocInfo::IsNone(adr.rmode_)) {
2018  pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
2019  RecordRelocInfo(adr.rmode_);
2020  pc_ += sizeof(int32_t);
2021  }
2022 }
2023 
2024 
2025 void Assembler::emit_farith(int b1, int b2, int i) {
2026  DCHECK(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2027  DCHECK(0 <= i && i < 8); // illegal stack offset
2028  EMIT(b1);
2029  EMIT(b2 + i);
2030 }
2031 
2032 
2033 void Assembler::db(uint8_t data) {
2034  EnsureSpace ensure_space(this);
2035  EMIT(data);
2036 }
2037 
2038 
2039 void Assembler::dd(uint32_t data) {
2040  EnsureSpace ensure_space(this);
2041  emit(data);
2042 }
2043 
2044 
2045 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2046  DCHECK(!RelocInfo::IsNone(rmode));
2047  // Don't record external references unless the heap will be serialized.
2048  if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
2049  !serializer_enabled() && !emit_debug_code()) {
2050  return;
2051  }
2052  RelocInfo rinfo(pc_, rmode, data, NULL);
2053  reloc_info_writer.Write(&rinfo);
2054 }
2055 
2056 
2057 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
2058  // No out-of-line constant pool support.
2059  DCHECK(!FLAG_enable_ool_constant_pool);
2060  return isolate->factory()->empty_constant_pool_array();
2061 }
2062 
2063 
2064 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
2065  // No out-of-line constant pool support.
2066  DCHECK(!FLAG_enable_ool_constant_pool);
2067  return;
2068 }
2069 
2070 
2071 #ifdef GENERATED_CODE_COVERAGE
2072 static FILE* coverage_log = NULL;
2073 
2074 
2075 static void InitCoverageLog() {
2076  char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
2077  if (file_name != NULL) {
2078  coverage_log = fopen(file_name, "aw+");
2079  }
2080 }
2081 
2082 
2083 void LogGeneratedCodeCoverage(const char* file_line) {
2084  const char* return_address = (&file_line)[-1];
2085  char* push_insn = const_cast<char*>(return_address - 12);
2086  push_insn[0] = 0xeb; // Relative branch insn.
2087  push_insn[1] = 13; // Skip over coverage insns.
2088  if (coverage_log != NULL) {
2089  fprintf(coverage_log, "%s\n", file_line);
2090  fflush(coverage_log);
2091  }
2092 }
2093 
2094 #endif
2095 
2096 } } // namespace v8::internal
2097 
2098 #endif // V8_TARGET_ARCH_X87
static const int kMaximalBufferSize
Assembler(Isolate *isolate, void *buffer, int buffer_size)
static void FlushICache(void *start, size_t size)
static void PrintFeatures()
static void ProbeImpl(bool cross_compile)
Operand(Register reg, Shift shift=LSL, unsigned shift_amount=0)
static const int kCodeTargetMask
Definition: assembler.h:587
static const int kApplyMask
Definition: assembler.h:591
static bool IsNone(Mode mode)
Definition: assembler.h:439
void PatchCode(byte *instructions, int instruction_count)
void PatchCodeWithCall(Address target, int guard_bytes)
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define CHECK(condition)
Definition: logging.h:36
#define FATAL(msg)
Definition: logging.h:26
#define DCHECK_GE(v1, v2)
Definition: logging.h:208
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
signed short int16_t
Definition: unicode.cc:22
int int32_t
Definition: unicode.cc:24
bool IsPowerOfTwo32(uint32_t value)
Definition: bits.h:77
void DeleteArray(T *array)
Definition: allocation.h:68
const Register edx
const Register edi
const Register esp
TypeImpl< ZoneTypeConfig > Type
void MemMove(void *dest, const void *src, size_t size)
Definition: utils.h:353
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146
const Register esi
const Register eax
const Register ebx
byte * Address
Definition: globals.h:101
void PrintF(const char *format,...)
Definition: utils.cc:80
OStream & dec(OStream &os)
Definition: ostreams.cc:122
const int kHeapObjectTag
Definition: v8.h:5737
const Register ebp
void FatalProcessOutOfMemory(const char *message)
const Register ecx
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
static const uint16_t * Align(const uint16_t *chars)
Definition: api.cc:4266
static Register from_code(int code)