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