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