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