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