⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 assembler-ia32.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 4 页
字号:
// Copyright (c) 1994-2006 Sun Microsystems Inc.// All Rights Reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions// are met://// - Redistributions of source code must retain the above copyright notice,// this list of conditions and the following disclaimer.//// - Redistribution in binary form must reproduce the above copyright// notice, this list of conditions and the following disclaimer in the// documentation and/or other materials provided with the// distribution.//// - Neither the name of Sun Microsystems or the names of contributors may// be used to endorse or promote products derived from this software without// specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED// OF THE POSSIBILITY OF SUCH DAMAGE.// The original source code covered by the above license above has been modified// significantly by Google Inc.// Copyright 2006-2008 the V8 project authors. All rights reserved.#include "v8.h"#include "disassembler.h"#include "macro-assembler.h"#include "serialize.h"namespace v8 { namespace internal {// -----------------------------------------------------------------------------// Implementation of RegisterRegister eax = { 0 };Register ecx = { 1 };Register edx = { 2 };Register ebx = { 3 };Register esp = { 4 };Register ebp = { 5 };Register esi = { 6 };Register edi = { 7 };Register no_reg = { -1 };XMMRegister xmm0 = { 0 };XMMRegister xmm1 = { 1 };XMMRegister xmm2 = { 2 };XMMRegister xmm3 = { 3 };XMMRegister xmm4 = { 4 };XMMRegister xmm5 = { 5 };XMMRegister xmm6 = { 6 };XMMRegister xmm7 = { 7 };// -----------------------------------------------------------------------------// Implementation of CpuFeatures// Safe default is no features.uint32_t CpuFeatures::supported_ = 0;uint32_t CpuFeatures::enabled_ = 0;typedef int (*F0)();// The Probe method needs executable memory, so it uses Heap::CreateCode.// Allocation failure is silent and leads to safe default.void CpuFeatures::Probe() {  supported_ = 0;  if (Serializer::enabled()) return;  // No features if we might serialize.  Assembler assm(NULL, 0);  Label done;#define __ assm.  // Save old esp, since we are going to modify the stack.  __ push(ebp);  __ pushfd();  __ push(ecx);  __ push(edx);  __ push(ebx);  __ mov(ebp, Operand(esp));  // If we can modify bit 21 of the EFLAGS register, then CPUID is supported.  __ pushfd();  __ pop(eax);  __ mov(edx, Operand(eax));  __ xor_(eax, 0x200000);  // Flip bit 21.  __ push(eax);  __ popfd();  __ pushfd();  __ pop(eax);  __ xor_(eax, Operand(edx));  // Different if CPUID is supported.  __ j(zero, &done);  // Invoke CPUID with 1 in eax to get feature information in edx.  __ mov(eax, 1);  // Temporarily force CPUID support, since we know it is safe here.  supported_ = (1 << CPUID);  { Scope fscope(CPUID);    __ cpuid();  }  supported_ = 0;  // Return result in eax.  __ mov(eax, Operand(edx));  __ bind(&done);  __ mov(esp, Operand(ebp));  __ pop(ebx);  __ pop(edx);  __ pop(ecx);  __ popfd();  __ pop(ebp);  __ ret(0);#undef __  CodeDesc desc;  assm.GetCode(&desc);  Object* code = Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB));  if (!code->IsCode()) return;  F0 f = FUNCTION_CAST<F0>(Code::cast(code)->entry());  uint32_t res = f();  supported_ = (res | (1 << CPUID));}// -----------------------------------------------------------------------------// Implementation of Displacementvoid Displacement::init(Label* L, Type type) {  ASSERT(!L->is_bound());  int next = 0;  if (L->is_linked()) {    next = L->pos();    ASSERT(next > 0);  // Displacements must be at positions > 0  }  // Ensure that we _never_ overflow the next field.  ASSERT(NextField::is_valid(Assembler::kMaximalBufferSize));  data_ = NextField::encode(next) | TypeField::encode(type);}// -----------------------------------------------------------------------------// Implementation of RelocInfoconst int RelocInfo::kApplyMask =  RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |    1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE;void RelocInfo::patch_code(byte* instructions, int instruction_count) {  // Patch the code at the current address with the supplied instructions.  for (int i = 0; i < instruction_count; i++) {    *(pc_ + i) = *(instructions + i);  }}// Patch the code at the current PC with a call to the target address.// Additional guard int3 instructions can be added if required.void RelocInfo::patch_code_with_call(Address target, int guard_bytes) {  // Call instruction takes up 5 bytes and int3 takes up one byte.  int code_size = 5 + guard_bytes;  // Patch the code.  CodePatcher patcher(pc_, code_size);  patcher.masm()->call(target, RelocInfo::NONE);  // Add the requested number of int3 instructions after the call.  for (int i = 0; i < guard_bytes; i++) {    patcher.masm()->int3();  }}// -----------------------------------------------------------------------------// Implementation of OperandOperand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) {  // [base + disp/r]  if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {    // [base]    set_modrm(0, base);    if (base.is(esp)) set_sib(times_1, esp, base);  } else if (is_int8(disp) && rmode == RelocInfo::NONE) {    // [base + disp8]    set_modrm(1, base);    if (base.is(esp)) set_sib(times_1, esp, base);    set_disp8(disp);  } else {    // [base + disp/r]    set_modrm(2, base);    if (base.is(esp)) set_sib(times_1, esp, base);    set_dispr(disp, rmode);  }}Operand::Operand(Register base,                 Register index,                 ScaleFactor scale,                 int32_t disp,                 RelocInfo::Mode rmode) {  ASSERT(!index.is(esp));  // illegal addressing mode  // [base + index*scale + disp/r]  if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {    // [base + index*scale]    set_modrm(0, esp);    set_sib(scale, index, base);  } else if (is_int8(disp) && rmode == RelocInfo::NONE) {    // [base + index*scale + disp8]    set_modrm(1, esp);    set_sib(scale, index, base);    set_disp8(disp);  } else {    // [base + index*scale + disp/r]    set_modrm(2, esp);    set_sib(scale, index, base);    set_dispr(disp, rmode);  }}Operand::Operand(Register index,                 ScaleFactor scale,                 int32_t disp,                 RelocInfo::Mode rmode) {  ASSERT(!index.is(esp));  // illegal addressing mode  // [index*scale + disp/r]  set_modrm(0, esp);  set_sib(scale, index, ebp);  set_dispr(disp, rmode);}void Operand::set_sib(ScaleFactor scale, Register index, Register base) {  ASSERT(len_ == 1);  ASSERT((scale & -4) == 0);  buf_[1] = scale << 6 | index.code() << 3 | base.code();  len_ = 2;}void Operand::set_disp8(int8_t disp) {  ASSERT(len_ == 1 || len_ == 2);  *reinterpret_cast<int8_t*>(&buf_[len_++]) = disp;}void Operand::set_reg(Register reg) const {  ASSERT(len_ > 0);  buf_[0] = (buf_[0] & ~0x38) | static_cast<byte>(reg.code() << 3);}bool Operand::is_reg(Register reg) const {  return ((buf_[0] & 0xF8) == 0xC0)  // addressing mode is register only.      && ((buf_[0] & 0x07) == reg.code());  // register codes match.}// -----------------------------------------------------------------------------// Implementation of Assembler// Emit a single byte. Must always be inlined.#define EMIT(x)                                 \  *pc_++ = (x)// spare_buffer_static byte* spare_buffer_ = NULL;Assembler::Assembler(void* buffer, int buffer_size) {  if (buffer == NULL) {    // do our own buffer management    if (buffer_size <= kMinimalBufferSize) {      buffer_size = kMinimalBufferSize;      if (spare_buffer_ != NULL) {        buffer = spare_buffer_;        spare_buffer_ = NULL;      }    }    if (buffer == NULL) {      buffer_ = NewArray<byte>(buffer_size);    } else {      buffer_ = static_cast<byte*>(buffer);    }    buffer_size_ = buffer_size;    own_buffer_ = true;  } else {    // use externally provided buffer instead    ASSERT(buffer_size > 0);    buffer_ = static_cast<byte*>(buffer);    buffer_size_ = buffer_size;    own_buffer_ = false;  }  // Clear the buffer in debug mode unless it was provided by the  // caller in which case we can't be sure it's okay to overwrite  // existing code in it; see CodePatcher::CodePatcher(...).  if (kDebug && own_buffer_) {    memset(buffer_, 0xCC, buffer_size);  // int3  }  // setup buffer pointers  ASSERT(buffer_ != NULL);  pc_ = buffer_;  reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);  last_pc_ = NULL;  last_bound_pos_ = 0;  last_position_ = RelocInfo::kNoPosition;  last_statement_position_ = RelocInfo::kNoPosition;}Assembler::~Assembler() {  if (own_buffer_) {    if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {      spare_buffer_ = buffer_;    } else {      DeleteArray(buffer_);    }  }}void Assembler::GetCode(CodeDesc* desc) {  // finalize code  if (unbound_label_.is_linked())    bind_to(&unbound_label_, binding_pos_);  // (at this point overflow() may be true, but the gap ensures that  // we are still not overlapping instructions and relocation info)  ASSERT(pc_ <= reloc_info_writer.pos());  // no overlap  // setup desc  desc->buffer = buffer_;  desc->buffer_size = buffer_size_;  desc->instr_size = pc_offset();  desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();  Counters::reloc_info_size.Increment(desc->reloc_size);}void Assembler::Align(int m) {  ASSERT(IsPowerOf2(m));  while ((pc_offset() & (m - 1)) != 0) {    nop();  }}void Assembler::cpuid() {  ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CPUID));  EnsureSpace ensure_space(this);  last_pc_ = pc_;  EMIT(0x0F);  EMIT(0xA2);}void Assembler::pushad() {  EnsureSpace ensure_space(this);  last_pc_ = pc_;  EMIT(0x60);}void Assembler::popad() {  EnsureSpace ensure_space(this);  last_pc_ = pc_;  EMIT(0x61);}void Assembler::pushfd() {  EnsureSpace ensure_space(this);  last_pc_ = pc_;  EMIT(0x9C);}void Assembler::popfd() {  EnsureSpace ensure_space(this);  last_pc_ = pc_;  EMIT(0x9D);}void Assembler::push(const Immediate& x) {  EnsureSpace ensure_space(this);  last_pc_ = pc_;  if (x.is_int8()) {    EMIT(0x6a);    EMIT(x.x_);  } else {    EMIT(0x68);    emit(x);  }}void Assembler::push(Register src) {  EnsureSpace ensure_space(this);  last_pc_ = pc_;  EMIT(0x50 | src.code());}void Assembler::push(const Operand& src) {  EnsureSpace ensure_space(this);  last_pc_ = pc_;  EMIT(0xFF);  emit_operand(esi, src);}void Assembler::pop(Register dst) {  ASSERT(reloc_info_writer.last_pc() != NULL);  if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) {    // (last_pc_ != NULL) is rolled into the above check    // If a last_pc_ is set, we need to make sure that there has not been any    // relocation information generated between the last instruction and this    // pop instruction.    byte instr = last_pc_[0];    if (instr == (0x50 | dst.code())) {      pc_ = last_pc_;      last_pc_ = NULL;      if (FLAG_print_push_pop_elimination) {        PrintF("%d push/pop (same reg) eliminated\n", pc_offset());      }      return;    } else if (instr == 0xff) {  // push of an operand, convert to a move      byte op1 = last_pc_[1];      // Check if the operation is really a push      if ((op1 & 0x38) == (6 << 3)) {        op1 = (op1 & ~0x38) | static_cast<byte>(dst.code() << 3);        last_pc_[0] = 0x8b;        last_pc_[1] = op1;        last_pc_ = NULL;        if (FLAG_print_push_pop_elimination) {          PrintF("%d push/pop (op->reg) eliminated\n", pc_offset());        }        return;      }    } else if ((instr == 0x89) &&               (last_pc_[1] == 0x04) &&               (last_pc_[2] == 0x24)) {      // 0x71283c   396  890424         mov [esp],eax      // 0x71283f   399  58             pop eax      if (dst.is(eax)) {        // change to        // 0x710fac   216  83c404         add esp,0x4        last_pc_[0] = 0x83;        last_pc_[1] = 0xc4;        last_pc_[2] = 0x04;        last_pc_ = NULL;        if (FLAG_print_push_pop_elimination) {          PrintF("%d push/pop (mov-pop) eliminated\n", pc_offset());        }        return;      }    } else if (instr == 0x6a && dst.is(eax)) {  // push of immediate 8 bit      byte imm8 = last_pc_[1];      if (imm8 == 0) {        // 6a00         push 0x0        // 58           pop eax        last_pc_[0] = 0x31;        last_pc_[1] = 0xc0;        // change to        // 31c0         xor eax,eax        last_pc_ = NULL;        return;      } else {        // 6a00         push 0xXX        // 58           pop eax        last_pc_[0] = 0xb8;        EnsureSpace ensure_space(this);        if ((imm8 & 0x80) != 0) {          EMIT(0xff);          EMIT(0xff);          EMIT(0xff);          // change to          // b8XXffffff   mov eax,0xffffffXX        } else {          EMIT(0x00);          EMIT(0x00);          EMIT(0x00);          // change to          // b8XX000000   mov eax,0x000000XX        }        last_pc_ = NULL;        return;      }    } else if (instr == 0x68 && dst.is(eax)) {  // push of immediate 32 bit      // 68XXXXXXXX   push 0xXXXXXXXX      // 58           pop eax      last_pc_[0] = 0xb8;      last_pc_ = NULL;      // change to      // b8XXXXXXXX   mov eax,0xXXXXXXXX      return;    }    // Other potential patterns for peephole:    // 0x712716   102  890424         mov [esp], eax    // 0x712719   105  8b1424         mov edx, [esp]  }  EnsureSpace ensure_space(this);  last_pc_ = pc_;  EMIT(0x58 | dst.code());}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -