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

📄 simulator-arm.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
// Copyright 2008 the V8 project authors. 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.//     * Redistributions 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 Google Inc. nor the names of its//       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.#include <stdlib.h>#include "v8.h"#include "disasm.h"#include "constants-arm.h"#include "simulator-arm.h"#if !defined(__arm__)// Only build the simulator if not compiling for real ARM hardware.namespace assembler { namespace arm {using ::v8::internal::Object;using ::v8::internal::PrintF;using ::v8::internal::OS;using ::v8::internal::ReadLine;using ::v8::internal::DeleteArray;// This macro provides a platform independent use of sscanf. The reason for// SScanF not beeing implemented in a platform independent was through// ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time// Library does not provide vsscanf.#ifdef WIN32#define SScanF sscanf_s#else#define SScanF sscanf  // NOLINT#endif// The Debugger class is used by the simulator while debugging simulated ARM// code.class Debugger { public:  explicit Debugger(Simulator* sim);  ~Debugger();  void Stop(Instr* instr);  void Debug(); private:  static const instr_t kBreakpointInstr =      ((AL << 28) | (7 << 25) | (1 << 24) | break_point);  static const instr_t kNopInstr =      ((AL << 28) | (13 << 21));  Simulator* sim_;  bool GetValue(char* desc, int32_t* value);  // Set or delete a breakpoint. Returns true if successful.  bool SetBreakpoint(Instr* breakpc);  bool DeleteBreakpoint(Instr* breakpc);  // Undo and redo all breakpoints. This is needed to bracket disassembly and  // execution to skip past breakpoints when run from the debugger.  void UndoBreakpoints();  void RedoBreakpoints();};Debugger::Debugger(Simulator* sim) {  sim_ = sim;}Debugger::~Debugger() {}void Debugger::Stop(Instr* instr) {  const char* str = (const char*)(instr->InstructionBits() & 0x0fffffff);  PrintF("Simulator hit %s\n", str);  sim_->set_pc(sim_->get_pc() + Instr::kInstrSize);  Debug();}static const char* reg_names[] = {  "r0",  "r1",  "r2",  "r3",                                    "r4",  "r5",  "r6",  "r7",                                    "r8",  "r9", "r10", "r11",                                   "r12", "r13", "r14", "r15",                                    "pc",  "lr",  "sp",  "ip",                                    "fp",  "sl", ""};static int   reg_nums[]  = {           0,     1,     2,     3,                                       4,     5,     6,     7,                                       8,     9,    10,    11,                                      12,    13,    14,    15,                                      15,    14,    13,    12,                                      11,    10};static int RegNameToRegNum(char* name) {  int reg = 0;  while (*reg_names[reg] != 0) {    if (strcmp(reg_names[reg], name) == 0) {      return reg_nums[reg];    }    reg++;  }  return -1;}bool Debugger::GetValue(char* desc, int32_t* value) {  int regnum = RegNameToRegNum(desc);  if (regnum >= 0) {    if (regnum == 15) {      *value = sim_->get_pc();    } else {      *value = sim_->get_register(regnum);    }    return true;  } else {    return SScanF(desc, "%i", value) == 1;  }  return false;}bool Debugger::SetBreakpoint(Instr* breakpc) {  // Check if a breakpoint can be set. If not return without any side-effects.  if (sim_->break_pc_ != NULL) {    return false;  }  // Set the breakpoint.  sim_->break_pc_ = breakpc;  sim_->break_instr_ = breakpc->InstructionBits();  // Not setting the breakpoint instruction in the code itself. It will be set  // when the debugger shell continues.  return true;}bool Debugger::DeleteBreakpoint(Instr* breakpc) {  if (sim_->break_pc_ != NULL) {    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);  }  sim_->break_pc_ = NULL;  sim_->break_instr_ = 0;  return true;}void Debugger::UndoBreakpoints() {  if (sim_->break_pc_ != NULL) {    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);  }}void Debugger::RedoBreakpoints() {  if (sim_->break_pc_ != NULL) {    sim_->break_pc_->SetInstructionBits(kBreakpointInstr);  }}void Debugger::Debug() {  intptr_t last_pc = -1;  bool done = false;#define COMMAND_SIZE 63#define ARG_SIZE 255#define STR(a) #a#define XSTR(a) STR(a)  char cmd[COMMAND_SIZE + 1];  char arg1[ARG_SIZE + 1];  char arg2[ARG_SIZE + 1];  // make sure to have a proper terminating character if reaching the limit  cmd[COMMAND_SIZE] = 0;  arg1[ARG_SIZE] = 0;  arg2[ARG_SIZE] = 0;  // Undo all set breakpoints while running in the debugger shell. This will  // make them invisible to all commands.  UndoBreakpoints();  while (!done) {    if (last_pc != sim_->get_pc()) {      disasm::Disassembler dasm;      // use a reasonably large buffer      v8::internal::EmbeddedVector<char, 256> buffer;      dasm.InstructionDecode(buffer,                             reinterpret_cast<byte*>(sim_->get_pc()));      PrintF("  0x%x  %s\n", sim_->get_pc(), buffer.start());      last_pc = sim_->get_pc();    }    char* line = ReadLine("sim> ");    if (line == NULL) {      break;    } else {      // Use sscanf to parse the individual parts of the command line. At the      // moment no command expects more than two parameters.      int args = SScanF(line,                        "%" XSTR(COMMAND_SIZE) "s "                        "%" XSTR(ARG_SIZE) "s "                        "%" XSTR(ARG_SIZE) "s",                        cmd, arg1, arg2);      if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {        sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));      } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {        // Execute the one instruction we broke at with breakpoints disabled.        sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));        // Leave the debugger shell.        done = true;      } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {        if (args == 2) {          int32_t value;          if (GetValue(arg1, &value)) {            PrintF("%s: %d 0x%x\n", arg1, value, value);          } else {            PrintF("%s unrecognized\n", arg1);          }        } else {          PrintF("print value\n");        }      } else if ((strcmp(cmd, "po") == 0)                 || (strcmp(cmd, "printobject") == 0)) {        if (args == 2) {          int32_t value;          if (GetValue(arg1, &value)) {            Object* obj = reinterpret_cast<Object*>(value);            USE(obj);            PrintF("%s: \n", arg1);#if defined(DEBUG)            obj->PrintLn();#endif  // defined(DEBUG)          } else {            PrintF("%s unrecognized\n", arg1);          }        } else {          PrintF("printobject value\n");        }      } else if (strcmp(cmd, "disasm") == 0) {        disasm::Disassembler dasm;        // use a reasonably large buffer        v8::internal::EmbeddedVector<char, 256> buffer;        byte* cur = NULL;        byte* end = NULL;        if (args == 1) {          cur = reinterpret_cast<byte*>(sim_->get_pc());          end = cur + (10 * Instr::kInstrSize);        } else if (args == 2) {          int32_t value;          if (GetValue(arg1, &value)) {            cur = reinterpret_cast<byte*>(value);            // no length parameter passed, assume 10 instructions            end = cur + (10 * Instr::kInstrSize);          }        } else {          int32_t value1;          int32_t value2;          if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {            cur = reinterpret_cast<byte*>(value1);            end = cur + (value2 * Instr::kInstrSize);          }        }        while (cur < end) {          dasm.InstructionDecode(buffer, cur);          PrintF("  0x%x  %s\n", cur, buffer.start());          cur += Instr::kInstrSize;        }      } else if (strcmp(cmd, "gdb") == 0) {        PrintF("relinquishing control to gdb\n");        v8::internal::OS::DebugBreak();        PrintF("regaining control from gdb\n");      } else if (strcmp(cmd, "break") == 0) {        if (args == 2) {          int32_t value;          if (GetValue(arg1, &value)) {            if (!SetBreakpoint(reinterpret_cast<Instr*>(value))) {              PrintF("setting breakpoint failed\n");            }          } else {            PrintF("%s unrecognized\n", arg1);          }        } else {          PrintF("break addr\n");        }      } else if (strcmp(cmd, "del") == 0) {        if (!DeleteBreakpoint(NULL)) {          PrintF("deleting breakpoint failed\n");        }      } else if (strcmp(cmd, "flags") == 0) {        PrintF("N flag: %d; ", sim_->n_flag_);        PrintF("Z flag: %d; ", sim_->z_flag_);        PrintF("C flag: %d; ", sim_->c_flag_);        PrintF("V flag: %d\n", sim_->v_flag_);      } else if (strcmp(cmd, "unstop") == 0) {        intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize;        Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc);        if (stop_instr->ConditionField() == special_condition) {          stop_instr->SetInstructionBits(kNopInstr);        } else {          PrintF("Not at debugger stop.");        }      } else {        PrintF("Unknown command: %s\n", cmd);      }    }    DeleteArray(line);  }  // Add all the breakpoints back to stop execution and enter the debugger  // shell when hit.  RedoBreakpoints();#undef COMMAND_SIZE#undef ARG_SIZE#undef STR#undef XSTR}Simulator::Simulator() {  // Setup simulator support first. Some of this information is needed to  // setup the architecture state.  size_t stack_size = 1 * 1024*1024;  // allocate 1MB for stack  stack_ = reinterpret_cast<char*>(malloc(stack_size));  pc_modified_ = false;  icount_ = 0;  break_pc_ = NULL;  break_instr_ = 0;  // Setup architecture state.  // All registers are initialized to zero to start with.  for (int i = 0; i < num_registers; i++) {    registers_[i] = 0;  }  n_flag_ = false;  z_flag_ = false;  c_flag_ = false;  v_flag_ = false;  // The sp is initialized to point to the bottom (high address) of the  // allocated stack area. To be safe in potential stack underflows we leave  // some buffer below.  registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64;  // The lr and pc are initialized to a known bad value that will cause an  // access violation if the simulator ever tries to execute it.  registers_[pc] = bad_lr;  registers_[lr] = bad_lr;}// This is the Simulator singleton. Currently only one thread is supported by// V8. If we had multiple threads, then we should have a Simulator instance on// a per thread basis.static Simulator* the_sim = NULL;// Get the active Simulator for the current thread. See comment above about// using a singleton currently.Simulator* Simulator::current() {  if (the_sim == NULL) {    the_sim = new Simulator();  }  return the_sim;}// Sets the register in the architecture state. It will also deal with updating// Simulator internal state for special registers such as PC.void Simulator::set_register(int reg, int32_t value) {  ASSERT((reg >= 0) && (reg < num_registers));  if (reg == pc) {    pc_modified_ = true;  }  registers_[reg] = value;}// Get the register from the architecture state. This function does handle// the special case of accessing the PC register.int32_t Simulator::get_register(int reg) const {  ASSERT((reg >= 0) && (reg < num_registers));  return registers_[reg] + ((reg == pc) ? Instr::kPCReadOffset : 0);}// Raw access to the PC register.void Simulator::set_pc(int32_t value) {  pc_modified_ = true;  registers_[pc] = value;}// Raw access to the PC register without the special adjustment when reading.int32_t Simulator::get_pc() const {  return registers_[pc];}// Returns the limit of the stack area to enable checking for stack overflows.uintptr_t Simulator::StackLimit() const {  // Leave a safety margin of 256 bytes to prevent overrunning the stack when  // pushing values.  return reinterpret_cast<uintptr_t>(stack_) + 256;}// Unsupported instructions use Format to print an error and stop execution.void Simulator::Format(Instr* instr, const char* format) {  PrintF("Simulator found unsupported instruction:\n 0x%x: %s\n",         instr, format);  UNIMPLEMENTED();}// Checks if the current instruction should be executed based on its// condition bits.bool Simulator::ConditionallyExecute(Instr* instr) {  switch (instr->ConditionField()) {    case EQ: return z_flag_;    case NE: return !z_flag_;    case CS: return c_flag_;    case CC: return !c_flag_;    case MI: return n_flag_;    case PL: return !n_flag_;    case VS: return v_flag_;    case VC: return !v_flag_;    case HI: return c_flag_ && !z_flag_;    case LS: return !c_flag_ || z_flag_;    case GE: return n_flag_ == v_flag_;    case LT: return n_flag_ != v_flag_;    case GT: return !z_flag_ && (n_flag_ == v_flag_);    case LE: return z_flag_ || (n_flag_ != v_flag_);    case AL: return true;    default: UNREACHABLE();  }  return false;}// Calculate and set the Negative and Zero flags.void Simulator::SetNZFlags(int32_t val) {  n_flag_ = (val < 0);  z_flag_ = (val == 0);}// Set the Carry flag.void Simulator::SetCFlag(bool val) {  c_flag_ = val;}// Set the oVerflow flag.void Simulator::SetVFlag(bool val) {  v_flag_ = val;}// Calculate C flag value for additions.bool Simulator::CarryFrom(int32_t left, int32_t right) {  uint32_t uleft = static_cast<uint32_t>(left);  uint32_t uright = static_cast<uint32_t>(right);  uint32_t urest  = 0xffffffffU - uleft;  return (uright > urest);}// Calculate C flag value for subtractions.bool Simulator::BorrowFrom(int32_t left, int32_t right) {  uint32_t uleft = static_cast<uint32_t>(left);

⌨️ 快捷键说明

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