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