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