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