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