00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "v8.h"
00038
00039 #include "disassembler.h"
00040 #include "macro-assembler.h"
00041 #include "serialize.h"
00042
00043 namespace v8 { namespace internal {
00044
00045
00046
00047
00048 Register eax = { 0 };
00049 Register ecx = { 1 };
00050 Register edx = { 2 };
00051 Register ebx = { 3 };
00052 Register esp = { 4 };
00053 Register ebp = { 5 };
00054 Register esi = { 6 };
00055 Register edi = { 7 };
00056 Register no_reg = { -1 };
00057
00058 XMMRegister xmm0 = { 0 };
00059 XMMRegister xmm1 = { 1 };
00060 XMMRegister xmm2 = { 2 };
00061 XMMRegister xmm3 = { 3 };
00062 XMMRegister xmm4 = { 4 };
00063 XMMRegister xmm5 = { 5 };
00064 XMMRegister xmm6 = { 6 };
00065 XMMRegister xmm7 = { 7 };
00066
00067
00068
00069
00070
00071
00072 uint32_t CpuFeatures::supported_ = 0;
00073 uint32_t CpuFeatures::enabled_ = 0;
00074
00075
00076 typedef int (*F0)();
00077
00078
00079
00080 void CpuFeatures::Probe() {
00081 supported_ = 0;
00082 if (Serializer::enabled()) return;
00083 Assembler assm(NULL, 0);
00084 Label done;
00085 #define __ assm.
00086
00087 __ push(ebp);
00088 __ pushfd();
00089 __ push(ecx);
00090 __ push(edx);
00091 __ push(ebx);
00092 __ mov(ebp, Operand(esp));
00093
00094 __ pushfd();
00095 __ pop(eax);
00096 __ mov(edx, Operand(eax));
00097 __ xor_(eax, 0x200000);
00098 __ push(eax);
00099 __ popfd();
00100 __ pushfd();
00101 __ pop(eax);
00102 __ xor_(eax, Operand(edx));
00103 __ j(zero, &done);
00104
00105 __ mov(eax, 1);
00106
00107 supported_ = (1 << CPUID);
00108 { Scope fscope(CPUID);
00109 __ cpuid();
00110 }
00111 supported_ = 0;
00112
00113 __ mov(eax, Operand(edx));
00114 __ bind(&done);
00115 __ mov(esp, Operand(ebp));
00116 __ pop(ebx);
00117 __ pop(edx);
00118 __ pop(ecx);
00119 __ popfd();
00120 __ pop(ebp);
00121 __ ret(0);
00122 #undef __
00123 CodeDesc desc;
00124 assm.GetCode(&desc);
00125 Object* code = Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB));
00126 if (!code->IsCode()) return;
00127 F0 f = FUNCTION_CAST<F0>(Code::cast(code)->entry());
00128 uint32_t res = f();
00129 supported_ = (res | (1 << CPUID));
00130 }
00131
00132
00133
00134
00135
00136 void Displacement::init(Label* L, Type type) {
00137 ASSERT(!L->is_bound());
00138 int next = 0;
00139 if (L->is_linked()) {
00140 next = L->pos();
00141 ASSERT(next > 0);
00142 }
00143
00144 ASSERT(NextField::is_valid(Assembler::kMaximalBufferSize));
00145 data_ = NextField::encode(next) | TypeField::encode(type);
00146 }
00147
00148
00149
00150
00151
00152
00153 const int RelocInfo::kApplyMask =
00154 RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
00155 1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE;
00156
00157
00158 void RelocInfo::patch_code(byte* instructions, int instruction_count) {
00159
00160 for (int i = 0; i < instruction_count; i++) {
00161 *(pc_ + i) = *(instructions + i);
00162 }
00163 }
00164
00165
00166
00167
00168 void RelocInfo::patch_code_with_call(Address target, int guard_bytes) {
00169
00170 int code_size = 5 + guard_bytes;
00171
00172
00173 CodePatcher patcher(pc_, code_size);
00174 patcher.masm()->call(target, RelocInfo::NONE);
00175
00176
00177 for (int i = 0; i < guard_bytes; i++) {
00178 patcher.masm()->int3();
00179 }
00180 }
00181
00182
00183
00184
00185
00186 Operand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) {
00187
00188 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
00189
00190 set_modrm(0, base);
00191 if (base.is(esp)) set_sib(times_1, esp, base);
00192 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
00193
00194 set_modrm(1, base);
00195 if (base.is(esp)) set_sib(times_1, esp, base);
00196 set_disp8(disp);
00197 } else {
00198
00199 set_modrm(2, base);
00200 if (base.is(esp)) set_sib(times_1, esp, base);
00201 set_dispr(disp, rmode);
00202 }
00203 }
00204
00205
00206 Operand::Operand(Register base,
00207 Register index,
00208 ScaleFactor scale,
00209 int32_t disp,
00210 RelocInfo::Mode rmode) {
00211 ASSERT(!index.is(esp));
00212
00213 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
00214
00215 set_modrm(0, esp);
00216 set_sib(scale, index, base);
00217 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
00218
00219 set_modrm(1, esp);
00220 set_sib(scale, index, base);
00221 set_disp8(disp);
00222 } else {
00223
00224 set_modrm(2, esp);
00225 set_sib(scale, index, base);
00226 set_dispr(disp, rmode);
00227 }
00228 }
00229
00230
00231 Operand::Operand(Register index,
00232 ScaleFactor scale,
00233 int32_t disp,
00234 RelocInfo::Mode rmode) {
00235 ASSERT(!index.is(esp));
00236
00237 set_modrm(0, esp);
00238 set_sib(scale, index, ebp);
00239 set_dispr(disp, rmode);
00240 }
00241
00242
00243 void Operand::set_sib(ScaleFactor scale, Register index, Register base) {
00244 ASSERT(len_ == 1);
00245 ASSERT((scale & -4) == 0);
00246 buf_[1] = scale << 6 | index.code() << 3 | base.code();
00247 len_ = 2;
00248 }
00249
00250
00251 void Operand::set_disp8(int8_t disp) {
00252 ASSERT(len_ == 1 || len_ == 2);
00253 *reinterpret_cast<int8_t*>(&buf_[len_++]) = disp;
00254 }
00255
00256
00257 void Operand::set_reg(Register reg) const {
00258 ASSERT(len_ > 0);
00259 buf_[0] = (buf_[0] & ~0x38) | static_cast<byte>(reg.code() << 3);
00260 }
00261
00262
00263 bool Operand::is_reg(Register reg) const {
00264 return ((buf_[0] & 0xF8) == 0xC0)
00265 && ((buf_[0] & 0x07) == reg.code());
00266 }
00267
00268
00269
00270
00271
00272 #define EMIT(x) \
00273 *pc_++ = (x)
00274
00275
00276
00277 static byte* spare_buffer_ = NULL;
00278
00279 Assembler::Assembler(void* buffer, int buffer_size) {
00280 if (buffer == NULL) {
00281
00282 if (buffer_size <= kMinimalBufferSize) {
00283 buffer_size = kMinimalBufferSize;
00284
00285 if (spare_buffer_ != NULL) {
00286 buffer = spare_buffer_;
00287 spare_buffer_ = NULL;
00288 }
00289 }
00290 if (buffer == NULL) {
00291 buffer_ = NewArray<byte>(buffer_size);
00292 } else {
00293 buffer_ = static_cast<byte*>(buffer);
00294 }
00295 buffer_size_ = buffer_size;
00296 own_buffer_ = true;
00297
00298 } else {
00299
00300 ASSERT(buffer_size > 0);
00301 buffer_ = static_cast<byte*>(buffer);
00302 buffer_size_ = buffer_size;
00303 own_buffer_ = false;
00304 }
00305
00306
00307
00308
00309 if (kDebug && own_buffer_) {
00310 memset(buffer_, 0xCC, buffer_size);
00311 }
00312
00313
00314 ASSERT(buffer_ != NULL);
00315 pc_ = buffer_;
00316 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
00317
00318 last_pc_ = NULL;
00319 last_position_ = RelocInfo::kNoPosition;
00320 last_statement_position_ = RelocInfo::kNoPosition;
00321 }
00322
00323
00324 Assembler::~Assembler() {
00325 if (own_buffer_) {
00326 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
00327 spare_buffer_ = buffer_;
00328 } else {
00329 DeleteArray(buffer_);
00330 }
00331 }
00332 }
00333
00334
00335 void Assembler::GetCode(CodeDesc* desc) {
00336
00337
00338
00339 ASSERT(pc_ <= reloc_info_writer.pos());
00340
00341 desc->buffer = buffer_;
00342 desc->buffer_size = buffer_size_;
00343 desc->instr_size = pc_offset();
00344 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
00345
00346 Counters::reloc_info_size.Increment(desc->reloc_size);
00347 }
00348
00349
00350 void Assembler::Align(int m) {
00351 ASSERT(IsPowerOf2(m));
00352 while ((pc_offset() & (m - 1)) != 0) {
00353 nop();
00354 }
00355 }
00356
00357
00358 void Assembler::cpuid() {
00359 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CPUID));
00360 EnsureSpace ensure_space(this);
00361 last_pc_ = pc_;
00362 EMIT(0x0F);
00363 EMIT(0xA2);
00364 }
00365
00366
00367 void Assembler::pushad() {
00368 EnsureSpace ensure_space(this);
00369 last_pc_ = pc_;
00370 EMIT(0x60);
00371 }
00372
00373
00374 void Assembler::popad() {
00375 EnsureSpace ensure_space(this);
00376 last_pc_ = pc_;
00377 EMIT(0x61);
00378 }
00379
00380
00381 void Assembler::pushfd() {
00382 EnsureSpace ensure_space(this);
00383 last_pc_ = pc_;
00384 EMIT(0x9C);
00385 }
00386
00387
00388 void Assembler::popfd() {
00389 EnsureSpace ensure_space(this);
00390 last_pc_ = pc_;
00391 EMIT(0x9D);
00392 }
00393
00394
00395 void Assembler::push(const Immediate& x) {
00396 EnsureSpace ensure_space(this);
00397 last_pc_ = pc_;
00398 if (x.is_int8()) {
00399 EMIT(0x6a);
00400 EMIT(x.x_);
00401 } else {
00402 EMIT(0x68);
00403 emit(x);
00404 }
00405 }
00406
00407
00408 void Assembler::push(Register src) {
00409 EnsureSpace ensure_space(this);
00410 last_pc_ = pc_;
00411 EMIT(0x50 | src.code());
00412 }
00413
00414
00415 void Assembler::push(const Operand& src) {
00416 EnsureSpace ensure_space(this);
00417 last_pc_ = pc_;
00418 EMIT(0xFF);
00419 emit_operand(esi, src);
00420 }
00421
00422
00423 void Assembler::pop(Register dst) {
00424 ASSERT(reloc_info_writer.last_pc() != NULL);
00425 if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) {
00426
00427
00428
00429
00430 byte instr = last_pc_[0];
00431 if ((instr & ~0x7) == 0x50) {
00432 int push_reg_code = instr & 0x7;
00433 if (push_reg_code == dst.code()) {
00434 pc_ = last_pc_;
00435 if (FLAG_print_push_pop_elimination) {
00436 PrintF("%d push/pop (same reg) eliminated\n", pc_offset());
00437 }
00438 } else {
00439
00440 last_pc_[0] = 0x8b;
00441 Register src = { push_reg_code };
00442 EnsureSpace ensure_space(this);
00443 emit_operand(dst, Operand(src));
00444 if (FLAG_print_push_pop_elimination) {
00445 PrintF("%d push/pop (reg->reg) eliminated\n", pc_offset());
00446 }
00447 }
00448 last_pc_ = NULL;
00449 return;
00450 } else if (instr == 0xff) {
00451 byte op1 = last_pc_[1];
00452
00453 if ((op1 & 0x38) == (6 << 3)) {
00454 op1 = (op1 & ~0x38) | static_cast<byte>(dst.code() << 3);
00455 last_pc_[0] = 0x8b;
00456 last_pc_[1] = op1;
00457 last_pc_ = NULL;
00458 if (FLAG_print_push_pop_elimination) {
00459 PrintF("%d push/pop (op->reg) eliminated\n", pc_offset());
00460 }
00461 return;
00462 }
00463 } else if ((instr == 0x89) &&
00464 (last_pc_[1] == 0x04) &&
00465 (last_pc_[2] == 0x24)) {
00466
00467
00468 if (dst.is(eax)) {
00469
00470
00471 last_pc_[0] = 0x83;
00472 last_pc_[1] = 0xc4;
00473 last_pc_[2] = 0x04;
00474 last_pc_ = NULL;
00475 if (FLAG_print_push_pop_elimination) {
00476 PrintF("%d push/pop (mov-pop) eliminated\n", pc_offset());
00477 }
00478 return;
00479 }
00480 } else if (instr == 0x6a && dst.is(eax)) {
00481 byte imm8 = last_pc_[1];
00482 if (imm8 == 0) {
00483
00484
00485 last_pc_[0] = 0x31;
00486 last_pc_[1] = 0xc0;
00487
00488
00489 last_pc_ = NULL;
00490 if (FLAG_print_push_pop_elimination) {
00491 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
00492 }
00493 return;
00494 } else {
00495
00496
00497 last_pc_[0] = 0xb8;
00498 EnsureSpace ensure_space(this);
00499 if ((imm8 & 0x80) != 0) {
00500 EMIT(0xff);
00501 EMIT(0xff);
00502 EMIT(0xff);
00503
00504
00505 } else {
00506 EMIT(0x00);
00507 EMIT(0x00);
00508 EMIT(0x00);
00509
00510
00511 }
00512 last_pc_ = NULL;
00513 if (FLAG_print_push_pop_elimination) {
00514 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
00515 }
00516 return;
00517 }
00518 } else if (instr == 0x68 && dst.is(eax)) {
00519
00520
00521 last_pc_[0] = 0xb8;
00522 last_pc_ = NULL;
00523
00524
00525 if (FLAG_print_push_pop_elimination) {
00526 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
00527 }
00528 return;
00529 }
00530
00531
00532
00533
00534 }
00535 EnsureSpace ensure_space(this);
00536 last_pc_ = pc_;
00537 EMIT(0x58 | dst.code());
00538 }
00539
00540
00541 void Assembler::pop(const Operand& dst) {
00542 EnsureSpace ensure_space(this);
00543 last_pc_ = pc_;
00544 EMIT(0x8F);
00545 emit_operand(eax, dst);
00546 }
00547
00548
00549 void Assembler::mov_b(Register dst, const Operand& src) {
00550 EnsureSpace ensure_space(this);
00551 last_pc_ = pc_;
00552 EMIT(0x8A);
00553 emit_operand(dst, src);
00554 }
00555
00556
00557 void Assembler::mov_b(const Operand& dst, int8_t imm8) {
00558 EnsureSpace ensure_space(this);
00559 last_pc_ = pc_;
00560 EMIT(0xC6);
00561 emit_operand(eax, dst);
00562 EMIT(imm8);
00563 }
00564
00565
00566 void Assembler::mov_b(const Operand& dst, Register src) {
00567 EnsureSpace ensure_space(this);
00568 last_pc_ = pc_;
00569 EMIT(0x88);
00570 emit_operand(src, dst);
00571 }
00572
00573
00574 void Assembler::mov_w(Register dst, const Operand& src) {
00575 EnsureSpace ensure_space(this);
00576 last_pc_ = pc_;
00577 EMIT(0x66);
00578 EMIT(0x8B);
00579 emit_operand(dst, src);
00580 }
00581
00582
00583 void Assembler::mov_w(const Operand& dst, Register src) {
00584 EnsureSpace ensure_space(this);
00585 last_pc_ = pc_;
00586 EMIT(0x66);
00587 EMIT(0x89);
00588 emit_operand(src, dst);
00589 }
00590
00591
00592 void Assembler::mov(Register dst, int32_t imm32) {
00593 EnsureSpace ensure_space(this);
00594 last_pc_ = pc_;
00595 EMIT(0xB8 | dst.code());
00596 emit(imm32);
00597 }
00598
00599
00600 void Assembler::mov(Register dst, Handle<Object> handle) {
00601 EnsureSpace ensure_space(this);
00602 last_pc_ = pc_;
00603 EMIT(0xB8 | dst.code());
00604 emit(handle);
00605 }
00606
00607
00608 void Assembler::mov(Register dst, const Operand& src) {
00609 EnsureSpace ensure_space(this);
00610 last_pc_ = pc_;
00611 EMIT(0x8B);
00612 emit_operand(dst, src);
00613 }
00614
00615
00616 void Assembler::mov(const Operand& dst, const Immediate& x) {
00617 EnsureSpace ensure_space(this);
00618 last_pc_ = pc_;
00619 EMIT(0xC7);
00620 emit_operand(eax, dst);
00621 emit(x);
00622 }
00623
00624
00625 void Assembler::mov(const Operand& dst, Handle<Object> handle) {
00626 EnsureSpace ensure_space(this);
00627 last_pc_ = pc_;
00628 EMIT(0xC7);
00629 emit_operand(eax, dst);
00630 emit(handle);
00631 }
00632
00633
00634 void Assembler::mov(const Operand& dst, Register src) {
00635 EnsureSpace ensure_space(this);
00636 last_pc_ = pc_;
00637 EMIT(0x89);
00638 emit_operand(src, dst);
00639 }
00640
00641
00642 void Assembler::movsx_b(Register dst, const Operand& src) {
00643 EnsureSpace ensure_space(this);
00644 last_pc_ = pc_;
00645 EMIT(0x0F);
00646 EMIT(0xBE);
00647 emit_operand(dst, src);
00648 }
00649
00650
00651 void Assembler::movsx_w(Register dst, const Operand& src) {
00652 EnsureSpace ensure_space(this);
00653 last_pc_ = pc_;
00654 EMIT(0x0F);
00655 EMIT(0xBF);
00656 emit_operand(dst, src);
00657 }
00658
00659
00660 void Assembler::movzx_b(Register dst, const Operand& src) {
00661 EnsureSpace ensure_space(this);
00662 last_pc_ = pc_;
00663 EMIT(0x0F);
00664 EMIT(0xB6);
00665 emit_operand(dst, src);
00666 }
00667
00668
00669 void Assembler::movzx_w(Register dst, const Operand& src) {
00670 EnsureSpace ensure_space(this);
00671 last_pc_ = pc_;
00672 EMIT(0x0F);
00673 EMIT(0xB7);
00674 emit_operand(dst, src);
00675 }
00676
00677
00678 void Assembler::cmov(Condition cc, Register dst, int32_t imm32) {
00679 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CMOV));
00680 EnsureSpace ensure_space(this);
00681 last_pc_ = pc_;
00682 UNIMPLEMENTED();
00683 USE(cc);
00684 USE(dst);
00685 USE(imm32);
00686 }
00687
00688
00689 void Assembler::cmov(Condition cc, Register dst, Handle<Object> handle) {
00690 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CMOV));
00691 EnsureSpace ensure_space(this);
00692 last_pc_ = pc_;
00693 UNIMPLEMENTED();
00694 USE(cc);
00695 USE(dst);
00696 USE(handle);
00697 }
00698
00699
00700 void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
00701 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CMOV));
00702 EnsureSpace ensure_space(this);
00703 last_pc_ = pc_;
00704 UNIMPLEMENTED();
00705 USE(cc);
00706 USE(dst);
00707 USE(src);
00708 }
00709
00710
00711 void Assembler::adc(Register dst, int32_t imm32) {
00712 EnsureSpace ensure_space(this);
00713 last_pc_ = pc_;
00714 emit_arith(2, Operand(dst), Immediate(imm32));
00715 }
00716
00717
00718 void Assembler::adc(Register dst, const Operand& src) {
00719 EnsureSpace ensure_space(this);
00720 last_pc_ = pc_;
00721 EMIT(0x13);
00722 emit_operand(dst, src);
00723 }
00724
00725
00726 void Assembler::add(Register dst, const Operand& src) {
00727 EnsureSpace ensure_space(this);
00728 last_pc_ = pc_;
00729 EMIT(0x03);
00730 emit_operand(dst, src);
00731 }
00732
00733
00734 void Assembler::add(const Operand& dst, const Immediate& x) {
00735 ASSERT(reloc_info_writer.last_pc() != NULL);
00736 if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) {
00737 byte instr = last_pc_[0];
00738 if ((instr & 0xf8) == 0x50) {
00739
00740
00741 if ((dst.is_reg(esp)) &&
00742 (x.x_ == kPointerSize) && (x.rmode_ == RelocInfo::NONE)) {
00743 pc_ = last_pc_;
00744 last_pc_ = NULL;
00745 if (FLAG_print_push_pop_elimination) {
00746 PrintF("%d push/pop(noreg) eliminated\n", pc_offset());
00747 }
00748 return;
00749 }
00750 }
00751 }
00752 EnsureSpace ensure_space(this);
00753 last_pc_ = pc_;
00754 emit_arith(0, dst, x);
00755 }
00756
00757
00758 void Assembler::and_(Register dst, int32_t imm32) {
00759 EnsureSpace ensure_space(this);
00760 last_pc_ = pc_;
00761 emit_arith(4, Operand(dst), Immediate(imm32));
00762 }
00763
00764
00765 void Assembler::and_(Register dst, const Operand& src) {
00766 EnsureSpace ensure_space(this);
00767 last_pc_ = pc_;
00768 EMIT(0x23);
00769 emit_operand(dst, src);
00770 }
00771
00772
00773 void Assembler::and_(const Operand& dst, const Immediate& x) {
00774 EnsureSpace ensure_space(this);
00775 last_pc_ = pc_;
00776 emit_arith(4, dst, x);
00777 }
00778
00779
00780 void Assembler::and_(const Operand& dst, Register src) {
00781 EnsureSpace ensure_space(this);
00782 last_pc_ = pc_;
00783 EMIT(0x21);
00784 emit_operand(dst, src);
00785 }
00786
00787
00788 void Assembler::cmp(Register reg, int32_t imm32) {
00789 EnsureSpace ensure_space(this);
00790 last_pc_ = pc_;
00791 emit_arith(7, Operand(reg), Immediate(imm32));
00792 }
00793
00794
00795 void Assembler::cmp(Register reg, Handle<Object> handle) {
00796 EnsureSpace ensure_space(this);
00797 last_pc_ = pc_;
00798 emit_arith(7, Operand(reg), Immediate(handle));
00799 }
00800
00801
00802 void Assembler::cmp(Register reg, const Operand& op) {
00803 EnsureSpace ensure_space(this);
00804 last_pc_ = pc_;
00805 EMIT(0x3B);
00806 emit_operand(reg, op);
00807 }
00808
00809
00810 void Assembler::cmp(const Operand& op, const Immediate& imm) {
00811 EnsureSpace ensure_space(this);
00812 last_pc_ = pc_;
00813 emit_arith(7, op, imm);
00814 }
00815
00816
00817 void Assembler::dec_b(Register dst) {
00818 EnsureSpace ensure_space(this);
00819 last_pc_ = pc_;
00820 EMIT(0xFE);
00821 EMIT(0xC8 | dst.code());
00822 }
00823
00824
00825 void Assembler::dec(Register dst) {
00826 EnsureSpace ensure_space(this);
00827 last_pc_ = pc_;
00828 EMIT(0x48 | dst.code());
00829 }
00830
00831
00832 void Assembler::dec(const Operand& dst) {
00833 EnsureSpace ensure_space(this);
00834 last_pc_ = pc_;
00835 EMIT(0xFF);
00836 emit_operand(ecx, dst);
00837 }
00838
00839
00840 void Assembler::cdq() {
00841 EnsureSpace ensure_space(this);
00842 last_pc_ = pc_;
00843 EMIT(0x99);
00844 }
00845
00846
00847 void Assembler::idiv(Register src) {
00848 EnsureSpace ensure_space(this);
00849 last_pc_ = pc_;
00850 EMIT(0xF7);
00851 EMIT(0xF8 | src.code());
00852 }
00853
00854
00855 void Assembler::imul(Register dst, const Operand& src) {
00856 EnsureSpace ensure_space(this);
00857 last_pc_ = pc_;
00858 EMIT(0x0F);
00859 EMIT(0xAF);
00860 emit_operand(dst, src);
00861 }
00862
00863
00864 void Assembler::imul(Register dst, Register src, int32_t imm32) {
00865 EnsureSpace ensure_space(this);
00866 last_pc_ = pc_;
00867 if (is_int8(imm32)) {
00868 EMIT(0x6B);
00869 EMIT(0xC0 | dst.code() << 3 | src.code());
00870 EMIT(imm32);
00871 } else {
00872 EMIT(0x69);
00873 EMIT(0xC0 | dst.code() << 3 | src.code());
00874 emit(imm32);
00875 }
00876 }
00877
00878
00879 void Assembler::inc(Register dst) {
00880 EnsureSpace ensure_space(this);
00881 last_pc_ = pc_;
00882 EMIT(0x40 | dst.code());
00883 }
00884
00885
00886 void Assembler::inc(const Operand& dst) {
00887 EnsureSpace ensure_space(this);
00888 last_pc_ = pc_;
00889 EMIT(0xFF);
00890 emit_operand(eax, dst);
00891 }
00892
00893
00894 void Assembler::lea(Register dst, const Operand& src) {
00895 EnsureSpace ensure_space(this);
00896 last_pc_ = pc_;
00897 EMIT(0x8D);
00898 emit_operand(dst, src);
00899 }
00900
00901
00902 void Assembler::mul(Register src) {
00903 EnsureSpace ensure_space(this);
00904 last_pc_ = pc_;
00905 EMIT(0xF7);
00906 EMIT(0xE0 | src.code());
00907 }
00908
00909
00910 void Assembler::neg(Register dst) {
00911 EnsureSpace ensure_space(this);
00912 last_pc_ = pc_;
00913 EMIT(0xF7);
00914 EMIT(0xD8 | dst.code());
00915 }
00916
00917
00918 void Assembler::not_(Register dst) {
00919 EnsureSpace ensure_space(this);
00920 last_pc_ = pc_;
00921 EMIT(0xF7);
00922 EMIT(0xD0 | dst.code());
00923 }
00924
00925
00926 void Assembler::or_(Register dst, int32_t imm32) {
00927 EnsureSpace ensure_space(this);
00928 last_pc_ = pc_;
00929 emit_arith(1, Operand(dst), Immediate(imm32));
00930 }
00931
00932
00933 void Assembler::or_(Register dst, const Operand& src) {
00934 EnsureSpace ensure_space(this);
00935 last_pc_ = pc_;
00936 EMIT(0x0B);
00937 emit_operand(dst, src);
00938 }
00939
00940
00941 void Assembler::or_(const Operand& dst, const Immediate& x) {
00942 EnsureSpace ensure_space(this);
00943 last_pc_ = pc_;
00944 emit_arith(1, dst, x);
00945 }
00946
00947
00948 void Assembler::or_(const Operand& dst, Register src) {
00949 EnsureSpace ensure_space(this);
00950 last_pc_ = pc_;
00951 EMIT(0x09);
00952 emit_operand(dst, src);
00953 }
00954
00955
00956 void Assembler::rcl(Register dst, uint8_t imm8) {
00957 EnsureSpace ensure_space(this);
00958 last_pc_ = pc_;
00959 ASSERT(is_uint5(imm8));
00960 if (imm8 == 1) {
00961 EMIT(0xD1);
00962 EMIT(0xD0 | dst.code());
00963 } else {
00964 EMIT(0xC1);
00965 EMIT(0xD0 | dst.code());
00966 EMIT(imm8);
00967 }
00968 }
00969
00970
00971 void Assembler::sar(Register dst, uint8_t imm8) {
00972 EnsureSpace ensure_space(this);
00973 last_pc_ = pc_;
00974 ASSERT(is_uint5(imm8));
00975 if (imm8 == 1) {
00976 EMIT(0xD1);
00977 EMIT(0xF8 | dst.code());
00978 } else {
00979 EMIT(0xC1);
00980 EMIT(0xF8 | dst.code());
00981 EMIT(imm8);
00982 }
00983 }
00984
00985
00986 void Assembler::sar(Register dst) {
00987 EnsureSpace ensure_space(this);
00988 last_pc_ = pc_;
00989 EMIT(0xD3);
00990 EMIT(0xF8 | dst.code());
00991 }
00992
00993
00994 void Assembler::sbb(Register dst, const Operand& src) {
00995 EnsureSpace ensure_space(this);
00996 last_pc_ = pc_;
00997 EMIT(0x1B);
00998 emit_operand(dst, src);
00999 }
01000
01001
01002 void Assembler::shld(Register dst, const Operand& src) {
01003 EnsureSpace ensure_space(this);
01004 last_pc_ = pc_;
01005 EMIT(0x0F);
01006 EMIT(0xA5);
01007 emit_operand(dst, src);
01008 }
01009
01010
01011 void Assembler::shl(Register dst, uint8_t imm8) {
01012 EnsureSpace ensure_space(this);
01013 last_pc_ = pc_;
01014 ASSERT(is_uint5(imm8));
01015 if (imm8 == 1) {
01016 EMIT(0xD1);
01017 EMIT(0xE0 | dst.code());
01018 } else {
01019 EMIT(0xC1);
01020 EMIT(0xE0 | dst.code());
01021 EMIT(imm8);
01022 }
01023 }
01024
01025
01026 void Assembler::shl(Register dst) {
01027 EnsureSpace ensure_space(this);
01028 last_pc_ = pc_;
01029 EMIT(0xD3);
01030 EMIT(0xE0 | dst.code());
01031 }
01032
01033
01034 void Assembler::shrd(Register dst, const Operand& src) {
01035 EnsureSpace ensure_space(this);
01036 last_pc_ = pc_;
01037 EMIT(0x0F);
01038 EMIT(0xAD);
01039 emit_operand(dst, src);
01040 }
01041
01042
01043 void Assembler::shr(Register dst, uint8_t imm8) {
01044 EnsureSpace ensure_space(this);
01045 last_pc_ = pc_;
01046 ASSERT(is_uint5(imm8));
01047 EMIT(0xC1);
01048 EMIT(0xE8 | dst.code());
01049 EMIT(imm8);
01050 }
01051
01052
01053 void Assembler::shr(Register dst) {
01054 EnsureSpace ensure_space(this);
01055 last_pc_ = pc_;
01056 EMIT(0xD3);
01057 EMIT(0xE8 | dst.code());
01058 }
01059
01060
01061 void Assembler::sub(const Operand& dst, const Immediate& x) {
01062 EnsureSpace ensure_space(this);
01063 last_pc_ = pc_;
01064 emit_arith(5, dst, x);
01065 }
01066
01067
01068 void Assembler::sub(Register dst, const Operand& src) {
01069 EnsureSpace ensure_space(this);
01070 last_pc_ = pc_;
01071 EMIT(0x2B);
01072 emit_operand(dst, src);
01073 }
01074
01075
01076 void Assembler::sub(const Operand& dst, Register src) {
01077 EnsureSpace ensure_space(this);
01078 last_pc_ = pc_;
01079 EMIT(0x29);
01080 emit_operand(dst, src);
01081 }
01082
01083
01084 void Assembler::test(Register reg, const Immediate& imm) {
01085 EnsureSpace ensure_space(this);
01086 last_pc_ = pc_;
01087
01088
01089 if (imm.rmode_ == RelocInfo::NONE && is_uint8(imm.x_) && reg.code() < 4) {
01090 uint8_t imm8 = imm.x_;
01091 if (reg.is(eax)) {
01092 EMIT(0xA8);
01093 EMIT(imm8);
01094 } else {
01095 emit_arith_b(0xF6, 0xC0, reg, imm8);
01096 }
01097 } else {
01098
01099
01100 if (reg.is(eax)) {
01101 EMIT(0xA9);
01102 } else {
01103 EMIT(0xF7);
01104 EMIT(0xC0 | reg.code());
01105 }
01106 emit(imm);
01107 }
01108 }
01109
01110
01111 void Assembler::test(Register reg, const Operand& op) {
01112 EnsureSpace ensure_space(this);
01113 last_pc_ = pc_;
01114 EMIT(0x85);
01115 emit_operand(reg, op);
01116 }
01117
01118
01119 void Assembler::test(const Operand& op, const Immediate& imm) {
01120 EnsureSpace ensure_space(this);
01121 last_pc_ = pc_;
01122 EMIT(0xF7);
01123 emit_operand(eax, op);
01124 emit(imm);
01125 }
01126
01127
01128 void Assembler::xor_(Register dst, int32_t imm32) {
01129 EnsureSpace ensure_space(this);
01130 last_pc_ = pc_;
01131 emit_arith(6, Operand(dst), Immediate(imm32));
01132 }
01133
01134
01135 void Assembler::xor_(Register dst, const Operand& src) {
01136 EnsureSpace ensure_space(this);
01137 last_pc_ = pc_;
01138 EMIT(0x33);
01139 emit_operand(dst, src);
01140 }
01141
01142
01143 void Assembler::xor_(const Operand& src, Register dst) {
01144 EnsureSpace ensure_space(this);
01145 last_pc_ = pc_;
01146 EMIT(0x31);
01147 emit_operand(dst, src);
01148 }
01149
01150
01151 void Assembler::xor_(const Operand& dst, const Immediate& x) {
01152 EnsureSpace ensure_space(this);
01153 last_pc_ = pc_;
01154 emit_arith(6, dst, x);
01155 }
01156
01157
01158 void Assembler::bts(const Operand& dst, Register src) {
01159 EnsureSpace ensure_space(this);
01160 last_pc_ = pc_;
01161 EMIT(0x0F);
01162 EMIT(0xAB);
01163 emit_operand(src, dst);
01164 }
01165
01166
01167 void Assembler::hlt() {
01168 EnsureSpace ensure_space(this);
01169 last_pc_ = pc_;
01170 EMIT(0xF4);
01171 }
01172
01173
01174 void Assembler::int3() {
01175 EnsureSpace ensure_space(this);
01176 last_pc_ = pc_;
01177 EMIT(0xCC);
01178 }
01179
01180
01181 void Assembler::nop() {
01182 EnsureSpace ensure_space(this);
01183 last_pc_ = pc_;
01184 EMIT(0x90);
01185 }
01186
01187
01188 void Assembler::rdtsc() {
01189 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::RDTSC));
01190 EnsureSpace ensure_space(this);
01191 last_pc_ = pc_;
01192 EMIT(0x0F);
01193 EMIT(0x31);
01194 }
01195
01196
01197 void Assembler::ret(int imm16) {
01198 EnsureSpace ensure_space(this);
01199 last_pc_ = pc_;
01200 ASSERT(is_uint16(imm16));
01201 if (imm16 == 0) {
01202 EMIT(0xC3);
01203 } else {
01204 EMIT(0xC2);
01205 EMIT(imm16 & 0xFF);
01206 EMIT((imm16 >> 8) & 0xFF);
01207 }
01208 }
01209
01210
01211 void Assembler::leave() {
01212 EnsureSpace ensure_space(this);
01213 last_pc_ = pc_;
01214 EMIT(0xC9);
01215 }
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229 void Assembler::print(Label* L) {
01230 if (L->is_unused()) {
01231 PrintF("unused label\n");
01232 } else if (L->is_bound()) {
01233 PrintF("bound label to %d\n", L->pos());
01234 } else if (L->is_linked()) {
01235 Label l = *L;
01236 PrintF("unbound label");
01237 while (l.is_linked()) {
01238 Displacement disp = disp_at(&l);
01239 PrintF("@ %d ", l.pos());
01240 disp.print();
01241 PrintF("\n");
01242 disp.next(&l);
01243 }
01244 } else {
01245 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
01246 }
01247 }
01248
01249
01250 void Assembler::bind_to(Label* L, int pos) {
01251 EnsureSpace ensure_space(this);
01252 last_pc_ = NULL;
01253 ASSERT(0 <= pos && pos <= pc_offset());
01254 while (L->is_linked()) {
01255 Displacement disp = disp_at(L);
01256 int fixup_pos = L->pos();
01257 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
01258 ASSERT(byte_at(fixup_pos - 1) == 0xE9);
01259 }
01260
01261 int imm32 = pos - (fixup_pos + sizeof(int32_t));
01262 long_at_put(fixup_pos, imm32);
01263 disp.next(L);
01264 }
01265 L->bind_to(pos);
01266 }
01267
01268
01269 void Assembler::link_to(Label* L, Label* appendix) {
01270 EnsureSpace ensure_space(this);
01271 last_pc_ = NULL;
01272 if (appendix->is_linked()) {
01273 if (L->is_linked()) {
01274
01275 Label p;
01276 Label q = *L;
01277 do {
01278 p = q;
01279 Displacement disp = disp_at(&q);
01280 disp.next(&q);
01281 } while (q.is_linked());
01282 Displacement disp = disp_at(&p);
01283 disp.link_to(appendix);
01284 disp_at_put(&p, disp);
01285 p.Unuse();
01286 } else {
01287
01288 *L = *appendix;
01289 }
01290 }
01291 appendix->Unuse();
01292 }
01293
01294
01295 void Assembler::bind(Label* L) {
01296 EnsureSpace ensure_space(this);
01297 last_pc_ = NULL;
01298 ASSERT(!L->is_bound());
01299 bind_to(L, pc_offset());
01300 }
01301
01302
01303 void Assembler::call(Label* L) {
01304 EnsureSpace ensure_space(this);
01305 last_pc_ = pc_;
01306 if (L->is_bound()) {
01307 const int long_size = 5;
01308 int offs = L->pos() - pc_offset();
01309 ASSERT(offs <= 0);
01310
01311 EMIT(0xE8);
01312 emit(offs - long_size);
01313 } else {
01314
01315 EMIT(0xE8);
01316 emit_disp(L, Displacement::OTHER);
01317 }
01318 }
01319
01320
01321 void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
01322 EnsureSpace ensure_space(this);
01323 last_pc_ = pc_;
01324 ASSERT(!RelocInfo::IsCodeTarget(rmode));
01325 EMIT(0xE8);
01326 emit(entry - (pc_ + sizeof(int32_t)), rmode);
01327 }
01328
01329
01330 void Assembler::call(const Operand& adr) {
01331 EnsureSpace ensure_space(this);
01332 last_pc_ = pc_;
01333 EMIT(0xFF);
01334 emit_operand(edx, adr);
01335 }
01336
01337
01338 void Assembler::call(Handle<Code> code, RelocInfo::Mode rmode) {
01339 WriteRecordedPositions();
01340 EnsureSpace ensure_space(this);
01341 last_pc_ = pc_;
01342 ASSERT(RelocInfo::IsCodeTarget(rmode));
01343 EMIT(0xE8);
01344 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
01345 }
01346
01347
01348 void Assembler::jmp(Label* L) {
01349 EnsureSpace ensure_space(this);
01350 last_pc_ = pc_;
01351 if (L->is_bound()) {
01352 const int short_size = 2;
01353 const int long_size = 5;
01354 int offs = L->pos() - pc_offset();
01355 ASSERT(offs <= 0);
01356 if (is_int8(offs - short_size)) {
01357
01358 EMIT(0xEB);
01359 EMIT((offs - short_size) & 0xFF);
01360 } else {
01361
01362 EMIT(0xE9);
01363 emit(offs - long_size);
01364 }
01365 } else {
01366
01367 EMIT(0xE9);
01368 emit_disp(L, Displacement::UNCONDITIONAL_JUMP);
01369 }
01370 }
01371
01372
01373 void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
01374 EnsureSpace ensure_space(this);
01375 last_pc_ = pc_;
01376 ASSERT(!RelocInfo::IsCodeTarget(rmode));
01377 EMIT(0xE9);
01378 emit(entry - (pc_ + sizeof(int32_t)), rmode);
01379 }
01380
01381
01382 void Assembler::jmp(const Operand& adr) {
01383 EnsureSpace ensure_space(this);
01384 last_pc_ = pc_;
01385 EMIT(0xFF);
01386 emit_operand(esp, adr);
01387 }
01388
01389
01390 void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
01391 EnsureSpace ensure_space(this);
01392 last_pc_ = pc_;
01393 ASSERT(RelocInfo::IsCodeTarget(rmode));
01394 EMIT(0xE9);
01395 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
01396 }
01397
01398
01399
01400 void Assembler::j(Condition cc, Label* L, Hint hint) {
01401 EnsureSpace ensure_space(this);
01402 last_pc_ = pc_;
01403 ASSERT(0 <= cc && cc < 16);
01404 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
01405 if (L->is_bound()) {
01406 const int short_size = 2;
01407 const int long_size = 6;
01408 int offs = L->pos() - pc_offset();
01409 ASSERT(offs <= 0);
01410 if (is_int8(offs - short_size)) {
01411
01412 EMIT(0x70 | cc);
01413 EMIT((offs - short_size) & 0xFF);
01414 } else {
01415
01416 EMIT(0x0F);
01417 EMIT(0x80 | cc);
01418 emit(offs - long_size);
01419 }
01420 } else {
01421
01422
01423
01424 EMIT(0x0F);
01425 EMIT(0x80 | cc);
01426 emit_disp(L, Displacement::OTHER);
01427 }
01428 }
01429
01430
01431 void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint) {
01432 EnsureSpace ensure_space(this);
01433 last_pc_ = pc_;
01434 ASSERT((0 <= cc) && (cc < 16));
01435 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
01436
01437 EMIT(0x0F);
01438 EMIT(0x80 | cc);
01439 emit(entry - (pc_ + sizeof(int32_t)), rmode);
01440 }
01441
01442
01443 void Assembler::j(Condition cc, Handle<Code> code, Hint hint) {
01444 EnsureSpace ensure_space(this);
01445 last_pc_ = pc_;
01446 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
01447
01448 EMIT(0x0F);
01449 EMIT(0x80 | cc);
01450 emit(reinterpret_cast<intptr_t>(code.location()), RelocInfo::CODE_TARGET);
01451 }
01452
01453
01454
01455
01456
01457 void Assembler::fld(int i) {
01458 EnsureSpace ensure_space(this);
01459 last_pc_ = pc_;
01460 emit_farith(0xD9, 0xC0, i);
01461 }
01462
01463
01464 void Assembler::fld1() {
01465 EnsureSpace ensure_space(this);
01466 last_pc_ = pc_;
01467 EMIT(0xD9);
01468 EMIT(0xE8);
01469 }
01470
01471
01472 void Assembler::fldz() {
01473 EnsureSpace ensure_space(this);
01474 last_pc_ = pc_;
01475 EMIT(0xD9);
01476 EMIT(0xEE);
01477 }
01478
01479
01480 void Assembler::fld_s(const Operand& adr) {
01481 EnsureSpace ensure_space(this);
01482 last_pc_ = pc_;
01483 EMIT(0xD9);
01484 emit_operand(eax, adr);
01485 }
01486
01487
01488 void Assembler::fld_d(const Operand& adr) {
01489 EnsureSpace ensure_space(this);
01490 last_pc_ = pc_;
01491 EMIT(0xDD);
01492 emit_operand(eax, adr);
01493 }
01494
01495
01496 void Assembler::fstp_s(const Operand& adr) {
01497 EnsureSpace ensure_space(this);
01498 last_pc_ = pc_;
01499 EMIT(0xD9);
01500 emit_operand(ebx, adr);
01501 }
01502
01503
01504 void Assembler::fstp_d(const Operand& adr) {
01505 EnsureSpace ensure_space(this);
01506 last_pc_ = pc_;
01507 EMIT(0xDD);
01508 emit_operand(ebx, adr);
01509 }
01510
01511
01512 void Assembler::fild_s(const Operand& adr) {
01513 EnsureSpace ensure_space(this);
01514 last_pc_ = pc_;
01515 EMIT(0xDB);
01516 emit_operand(eax, adr);
01517 }
01518
01519
01520 void Assembler::fild_d(const Operand& adr) {
01521 EnsureSpace ensure_space(this);
01522 last_pc_ = pc_;
01523 EMIT(0xDF);
01524 emit_operand(ebp, adr);
01525 }
01526
01527
01528 void Assembler::fistp_s(const Operand& adr) {
01529 EnsureSpace ensure_space(this);
01530 last_pc_ = pc_;
01531 EMIT(0xDB);
01532 emit_operand(ebx, adr);
01533 }
01534
01535
01536 void Assembler::fist_s(const Operand& adr) {
01537 EnsureSpace ensure_space(this);
01538 last_pc_ = pc_;
01539 EMIT(0xDB);
01540 emit_operand(edx, adr);
01541 }
01542
01543
01544 void Assembler::fistp_d(const Operand& adr) {
01545 EnsureSpace ensure_space(this);
01546 last_pc_ = pc_;
01547 EMIT(0xDF);
01548 emit_operand(edi, adr);
01549 }
01550
01551
01552 void Assembler::fabs() {
01553 EnsureSpace ensure_space(this);
01554 last_pc_ = pc_;
01555 EMIT(0xD9);
01556 EMIT(0xE1);
01557 }
01558
01559
01560 void Assembler::fchs() {
01561 EnsureSpace ensure_space(this);
01562 last_pc_ = pc_;
01563 EMIT(0xD9);
01564 EMIT(0xE0);
01565 }
01566
01567
01568 void Assembler::fadd(int i) {
01569 EnsureSpace ensure_space(this);
01570 last_pc_ = pc_;
01571 emit_farith(0xDC, 0xC0, i);
01572 }
01573
01574
01575 void Assembler::fsub(int i) {
01576 EnsureSpace ensure_space(this);
01577 last_pc_ = pc_;
01578 emit_farith(0xDC, 0xE8, i);
01579 }
01580
01581
01582 void Assembler::fisub_s(const Operand& adr) {
01583 EnsureSpace ensure_space(this);
01584 last_pc_ = pc_;
01585 EMIT(0xDA);
01586 emit_operand(esp, adr);
01587 }
01588
01589
01590 void Assembler::fmul(int i) {
01591 EnsureSpace ensure_space(this);
01592 last_pc_ = pc_;
01593 emit_farith(0xDC, 0xC8, i);
01594 }
01595
01596
01597 void Assembler::fdiv(int i) {
01598 EnsureSpace ensure_space(this);
01599 last_pc_ = pc_;
01600 emit_farith(0xDC, 0xF8, i);
01601 }
01602
01603
01604 void Assembler::faddp(int i) {
01605 EnsureSpace ensure_space(this);
01606 last_pc_ = pc_;
01607 emit_farith(0xDE, 0xC0, i);
01608 }
01609
01610
01611 void Assembler::fsubp(int i) {
01612 EnsureSpace ensure_space(this);
01613 last_pc_ = pc_;
01614 emit_farith(0xDE, 0xE8, i);
01615 }
01616
01617
01618 void Assembler::fsubrp(int i) {
01619 EnsureSpace ensure_space(this);
01620 last_pc_ = pc_;
01621 emit_farith(0xDE, 0xE0, i);
01622 }
01623
01624
01625 void Assembler::fmulp(int i) {
01626 EnsureSpace ensure_space(this);
01627 last_pc_ = pc_;
01628 emit_farith(0xDE, 0xC8, i);
01629 }
01630
01631
01632 void Assembler::fdivp(int i) {
01633 EnsureSpace ensure_space(this);
01634 last_pc_ = pc_;
01635 emit_farith(0xDE, 0xF8, i);
01636 }
01637
01638
01639 void Assembler::fprem() {
01640 EnsureSpace ensure_space(this);
01641 last_pc_ = pc_;
01642 EMIT(0xD9);
01643 EMIT(0xF8);
01644 }
01645
01646
01647 void Assembler::fprem1() {
01648 EnsureSpace ensure_space(this);
01649 last_pc_ = pc_;
01650 EMIT(0xD9);
01651 EMIT(0xF5);
01652 }
01653
01654
01655 void Assembler::fxch(int i) {
01656 EnsureSpace ensure_space(this);
01657 last_pc_ = pc_;
01658 emit_farith(0xD9, 0xC8, i);
01659 }
01660
01661
01662 void Assembler::fincstp() {
01663 EnsureSpace ensure_space(this);
01664 last_pc_ = pc_;
01665 EMIT(0xD9);
01666 EMIT(0xF7);
01667 }
01668
01669
01670 void Assembler::ffree(int i) {
01671 EnsureSpace ensure_space(this);
01672 last_pc_ = pc_;
01673 emit_farith(0xDD, 0xC0, i);
01674 }
01675
01676
01677 void Assembler::ftst() {
01678 EnsureSpace ensure_space(this);
01679 last_pc_ = pc_;
01680 EMIT(0xD9);
01681 EMIT(0xE4);
01682 }
01683
01684
01685 void Assembler::fucomp(int i) {
01686 EnsureSpace ensure_space(this);
01687 last_pc_ = pc_;
01688 emit_farith(0xDD, 0xE8, i);
01689 }
01690
01691
01692 void Assembler::fucompp() {
01693 EnsureSpace ensure_space(this);
01694 last_pc_ = pc_;
01695 EMIT(0xDA);
01696 EMIT(0xE9);
01697 }
01698
01699
01700 void Assembler::fcompp() {
01701 EnsureSpace ensure_space(this);
01702 last_pc_ = pc_;
01703 EMIT(0xDE);
01704 EMIT(0xD9);
01705 }
01706
01707
01708 void Assembler::fnstsw_ax() {
01709 EnsureSpace ensure_space(this);
01710 last_pc_ = pc_;
01711 EMIT(0xdF);
01712 EMIT(0xE0);
01713 }
01714
01715
01716 void Assembler::fwait() {
01717 EnsureSpace ensure_space(this);
01718 last_pc_ = pc_;
01719 EMIT(0x9B);
01720 }
01721
01722
01723 void Assembler::frndint() {
01724 EnsureSpace ensure_space(this);
01725 last_pc_ = pc_;
01726 EMIT(0xD9);
01727 EMIT(0xFC);
01728 }
01729
01730
01731 void Assembler::sahf() {
01732 EnsureSpace ensure_space(this);
01733 last_pc_ = pc_;
01734 EMIT(0x9E);
01735 }
01736
01737
01738 void Assembler::cvttss2si(Register dst, const Operand& src) {
01739 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
01740 EnsureSpace ensure_space(this);
01741 last_pc_ = pc_;
01742 EMIT(0xF3);
01743 EMIT(0x0F);
01744 EMIT(0x2C);
01745 emit_operand(dst, src);
01746 }
01747
01748
01749 void Assembler::cvttsd2si(Register dst, const Operand& src) {
01750 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
01751 EnsureSpace ensure_space(this);
01752 last_pc_ = pc_;
01753 EMIT(0xF2);
01754 EMIT(0x0F);
01755 EMIT(0x2C);
01756 emit_operand(dst, src);
01757 }
01758
01759
01760 void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
01761 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
01762 EnsureSpace ensure_space(this);
01763 last_pc_ = pc_;
01764 EMIT(0xF2);
01765 EMIT(0x0F);
01766 EMIT(0x2A);
01767 emit_sse_operand(dst, src);
01768 }
01769
01770
01771 void Assembler::addsd(XMMRegister dst, XMMRegister src) {
01772 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
01773 EnsureSpace ensure_space(this);
01774 last_pc_ = pc_;
01775 EMIT(0xF2);
01776 EMIT(0x0F);
01777 EMIT(0x58);
01778 emit_sse_operand(dst, src);
01779 }
01780
01781
01782 void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
01783 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
01784 EnsureSpace ensure_space(this);
01785 last_pc_ = pc_;
01786 EMIT(0xF2);
01787 EMIT(0x0F);
01788 EMIT(0x59);
01789 emit_sse_operand(dst, src);
01790 }
01791
01792
01793 void Assembler::subsd(XMMRegister dst, XMMRegister src) {
01794 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
01795 EnsureSpace ensure_space(this);
01796 last_pc_ = pc_;
01797 EMIT(0xF2);
01798 EMIT(0x0F);
01799 EMIT(0x5C);
01800 emit_sse_operand(dst, src);
01801 }
01802
01803
01804 void Assembler::divsd(XMMRegister dst, XMMRegister src) {
01805 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
01806 EnsureSpace ensure_space(this);
01807 last_pc_ = pc_;
01808 EMIT(0xF2);
01809 EMIT(0x0F);
01810 EMIT(0x5E);
01811 emit_sse_operand(dst, src);
01812 }
01813
01814
01815 void Assembler::movdbl(XMMRegister dst, const Operand& src) {
01816 EnsureSpace ensure_space(this);
01817 last_pc_ = pc_;
01818 movsd(dst, src);
01819 }
01820
01821
01822 void Assembler::movdbl(const Operand& dst, XMMRegister src) {
01823 EnsureSpace ensure_space(this);
01824 last_pc_ = pc_;
01825 movsd(dst, src);
01826 }
01827
01828
01829 void Assembler::movsd(const Operand& dst, XMMRegister src ) {
01830 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
01831 EnsureSpace ensure_space(this);
01832 last_pc_ = pc_;
01833 EMIT(0xF2);
01834 EMIT(0x0F);
01835 EMIT(0x11);
01836 emit_sse_operand(src, dst);
01837 }
01838
01839
01840 void Assembler::movsd(XMMRegister dst, const Operand& src) {
01841 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
01842 EnsureSpace ensure_space(this);
01843 last_pc_ = pc_;
01844 EMIT(0xF2);
01845 EMIT(0x0F);
01846 EMIT(0x10);
01847 emit_sse_operand(dst, src);
01848 }
01849
01850
01851 void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
01852 Register ireg = { reg.code() };
01853 emit_operand(ireg, adr);
01854 }
01855
01856
01857 void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
01858 EMIT(0xC0 | dst.code() << 3 | src.code());
01859 }
01860
01861
01862 void Assembler::Print() {
01863 Disassembler::Decode(stdout, buffer_, pc_);
01864 }
01865
01866
01867 void Assembler::RecordJSReturn() {
01868 WriteRecordedPositions();
01869 EnsureSpace ensure_space(this);
01870 RecordRelocInfo(RelocInfo::JS_RETURN);
01871 }
01872
01873
01874 void Assembler::RecordComment(const char* msg) {
01875 if (FLAG_debug_code) {
01876 EnsureSpace ensure_space(this);
01877 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
01878 }
01879 }
01880
01881
01882 void Assembler::RecordPosition(int pos) {
01883 if (pos == RelocInfo::kNoPosition) return;
01884 ASSERT(pos >= 0);
01885 last_position_ = pos;
01886 }
01887
01888
01889 void Assembler::RecordStatementPosition(int pos) {
01890 if (pos == RelocInfo::kNoPosition) return;
01891 ASSERT(pos >= 0);
01892 last_statement_position_ = pos;
01893 }
01894
01895
01896 void Assembler::WriteRecordedPositions() {
01897 if (last_statement_position_ != RelocInfo::kNoPosition) {
01898 EnsureSpace ensure_space(this);
01899 RecordRelocInfo(RelocInfo::STATEMENT_POSITION, last_statement_position_);
01900 }
01901 if ((last_position_ != RelocInfo::kNoPosition) &&
01902 (last_position_ != last_statement_position_)) {
01903 EnsureSpace ensure_space(this);
01904 RecordRelocInfo(RelocInfo::POSITION, last_position_);
01905 }
01906 last_statement_position_ = RelocInfo::kNoPosition;
01907 last_position_ = RelocInfo::kNoPosition;
01908 }
01909
01910
01911 void Assembler::GrowBuffer() {
01912 ASSERT(overflow());
01913 if (!own_buffer_) FATAL("external code buffer is too small");
01914
01915
01916 CodeDesc desc;
01917 if (buffer_size_ < 4*KB) {
01918 desc.buffer_size = 4*KB;
01919 } else {
01920 desc.buffer_size = 2*buffer_size_;
01921 }
01922
01923
01924 if ((desc.buffer_size > kMaximalBufferSize) ||
01925 (desc.buffer_size > Heap::OldGenerationSize())) {
01926 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
01927 }
01928
01929
01930 desc.buffer = NewArray<byte>(desc.buffer_size);
01931 desc.instr_size = pc_offset();
01932 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
01933
01934
01935
01936 if (kDebug) {
01937 memset(desc.buffer, 0xCC, desc.buffer_size);
01938 }
01939
01940
01941 int pc_delta = desc.buffer - buffer_;
01942 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
01943 memmove(desc.buffer, buffer_, desc.instr_size);
01944 memmove(rc_delta + reloc_info_writer.pos(),
01945 reloc_info_writer.pos(), desc.reloc_size);
01946
01947
01948 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
01949 spare_buffer_ = buffer_;
01950 } else {
01951 DeleteArray(buffer_);
01952 }
01953 buffer_ = desc.buffer;
01954 buffer_size_ = desc.buffer_size;
01955 pc_ += pc_delta;
01956 if (last_pc_ != NULL) {
01957 last_pc_ += pc_delta;
01958 }
01959 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
01960 reloc_info_writer.last_pc() + pc_delta);
01961
01962
01963 for (RelocIterator it(desc); !it.done(); it.next()) {
01964 RelocInfo::Mode rmode = it.rinfo()->rmode();
01965 if (rmode == RelocInfo::RUNTIME_ENTRY) {
01966 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
01967 *p -= pc_delta;
01968 } else if (rmode == RelocInfo::INTERNAL_REFERENCE) {
01969 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
01970 if (*p != 0) {
01971 *p += pc_delta;
01972 }
01973 }
01974 }
01975
01976 ASSERT(!overflow());
01977 }
01978
01979
01980 void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
01981 ASSERT(is_uint8(op1) && is_uint8(op2));
01982 ASSERT(is_uint8(imm8));
01983 ASSERT((op1 & 0x01) == 0);
01984 EMIT(op1);
01985 EMIT(op2 | dst.code());
01986 EMIT(imm8);
01987 }
01988
01989
01990 void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
01991 ASSERT((0 <= sel) && (sel <= 7));
01992 Register ireg = { sel };
01993 if (x.is_int8()) {
01994 EMIT(0x83);
01995 emit_operand(ireg, dst);
01996 EMIT(x.x_ & 0xFF);
01997 } else if (dst.is_reg(eax)) {
01998 EMIT((sel << 3) | 0x05);
01999 emit(x);
02000 } else {
02001 EMIT(0x81);
02002 emit_operand(ireg, dst);
02003 emit(x);
02004 }
02005 }
02006
02007
02008 void Assembler::emit_operand(Register reg, const Operand& adr) {
02009 adr.set_reg(reg);
02010 memmove(pc_, adr.buf_, adr.len_);
02011 pc_ += adr.len_;
02012 if (adr.len_ >= sizeof(int32_t) && adr.rmode_ != RelocInfo::NONE) {
02013 pc_ -= sizeof(int32_t);
02014 RecordRelocInfo(adr.rmode_);
02015 pc_ += sizeof(int32_t);
02016 }
02017 }
02018
02019
02020 void Assembler::emit_operand(const Operand& adr, Register reg) {
02021 adr.set_reg(reg);
02022 memmove(pc_, adr.buf_, adr.len_);
02023 pc_ += adr.len_;
02024 if (adr.len_ >= sizeof(int32_t) && adr.rmode_ != RelocInfo::NONE) {
02025 pc_ -= sizeof(int32_t);
02026 RecordRelocInfo(adr.rmode_);
02027 pc_ += sizeof(int32_t);
02028 }
02029 }
02030
02031
02032 void Assembler::emit_farith(int b1, int b2, int i) {
02033 ASSERT(is_uint8(b1) && is_uint8(b2));
02034 ASSERT(0 <= i && i < 8);
02035 EMIT(b1);
02036 EMIT(b2 + i);
02037 }
02038
02039
02040 void Assembler::dd(uint32_t data, RelocInfo::Mode reloc_info) {
02041 EnsureSpace ensure_space(this);
02042 emit(data, reloc_info);
02043 }
02044
02045
02046 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
02047 ASSERT(rmode != RelocInfo::NONE);
02048
02049 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
02050 !Serializer::enabled() &&
02051 !FLAG_debug_code) {
02052 return;
02053 }
02054 RelocInfo rinfo(pc_, rmode, data);
02055 reloc_info_writer.Write(&rinfo);
02056 }
02057
02058
02059 void Assembler::WriteInternalReference(int position, const Label& bound_label) {
02060 ASSERT(bound_label.is_bound());
02061 ASSERT(0 <= position);
02062 ASSERT(position + static_cast<int>(sizeof(uint32_t)) <= pc_offset());
02063 ASSERT(long_at(position) == 0);
02064
02065 uint32_t label_loc = reinterpret_cast<uint32_t>(addr_at(bound_label.pos()));
02066 long_at_put(position, label_loc);
02067 }
02068
02069 } }