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