112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Copyright 2011 the V8 project authors. All rights reserved.
212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be
312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// found in the LICENSE file.
412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include <limits.h>
612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include <stdarg.h>
712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include <stdlib.h>
812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include <cmath>
912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
1012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/v8.h"
1112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
1212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#if V8_TARGET_ARCH_MIPS64
1312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
1412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/assembler.h"
15e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org#include "src/base/bits.h"
1612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/disasm.h"
1712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/mips64/constants-mips64.h"
1812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#include "src/mips64/simulator-mips64.h"
197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/ostreams.h"
2012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
2112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Only build the simulator if not compiling for real MIPS hardware.
2212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#if defined(USE_SIMULATOR)
2312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
2412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgnamespace v8 {
2512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgnamespace internal {
2612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
2712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Utils functions.
2812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool HaveSameSign(int64_t a, int64_t b) {
2912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return ((a ^ b) >= 0);
3012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
3112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
3212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
3312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orguint32_t get_fcsr_condition_bit(uint32_t cc) {
3412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (cc == 0) {
3512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return 23;
3612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
3712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return 24 + cc;
3812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
3912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
4012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
4112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
4212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic int64_t MultiplyHighSigned(int64_t u, int64_t v) {
4312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uint64_t u0, v0, w0;
4412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t u1, v1, w1, w2, t;
4512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
4612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  u0 = u & 0xffffffffL;
4712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  u1 = u >> 32;
4812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  v0 = v & 0xffffffffL;
4912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  v1 = v >> 32;
5012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
5112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  w0 = u0 * v0;
5212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  t = u1 * v0 + (w0 >> 32);
5312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  w1 = t & 0xffffffffL;
5412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  w2 = t >> 32;
5512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  w1 = u0 * v1 + w1;
5612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
5712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return u1 * v1 + w2 + (w1 >> 32);
5812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
5912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
6012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
6112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// This macro provides a platform independent use of sscanf. The reason for
6212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// SScanF not being implemented in a platform independent was through
6312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
6412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Library does not provide vsscanf.
6512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define SScanF sscanf  // NOLINT
6612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
6712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// The MipsDebugger class is used by the simulator while debugging simulated
6812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// code.
6912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgclass MipsDebugger {
7012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org public:
7112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  explicit MipsDebugger(Simulator* sim) : sim_(sim) { }
7212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  ~MipsDebugger();
7312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
7412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  void Stop(Instruction* instr);
7512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  void Debug();
7612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Print all registers with a nice formatting.
7712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  void PrintAllRegs();
7812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  void PrintAllRegsIncludingFPU();
7912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
8012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org private:
8112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // We set the breakpoint code to 0xfffff to easily recognize it.
8212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6;
8312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  static const Instr kNopInstr =  0x0;
8412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
8512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Simulator* sim_;
8612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
8712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t GetRegisterValue(int regnum);
8812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t GetFPURegisterValue(int regnum);
8912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  float GetFPURegisterValueFloat(int regnum);
9012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  double GetFPURegisterValueDouble(int regnum);
9112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  bool GetValue(const char* desc, int64_t* value);
9212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
9312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Set or delete a breakpoint. Returns true if successful.
9412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  bool SetBreakpoint(Instruction* breakpc);
9512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  bool DeleteBreakpoint(Instruction* breakpc);
9612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
9712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Undo and redo all breakpoints. This is needed to bracket disassembly and
9812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // execution to skip past breakpoints when run from the debugger.
9912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  void UndoBreakpoints();
10012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  void RedoBreakpoints();
10112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org};
10212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
10312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
10412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgMipsDebugger::~MipsDebugger() {
10512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
10612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
10712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
10812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#ifdef GENERATED_CODE_COVERAGE
10912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic FILE* coverage_log = NULL;
11012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
11112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
11212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void InitializeCoverage() {
11312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
11412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (file_name != NULL) {
11512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    coverage_log = fopen(file_name, "aw+");
11612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
11712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
11812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
11912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
12012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid MipsDebugger::Stop(Instruction* instr) {
12112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Get the stop code.
12212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uint32_t code = instr->Bits(25, 6);
12312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Retrieve the encoded address, which comes just after this stop.
12412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  char** msg_address =
12512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize);
12612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  char* msg = *msg_address;
127e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(msg != NULL);
12812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
12912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Update this stop description.
13012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (!watched_stops_[code].desc) {
13112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    watched_stops_[code].desc = msg;
13212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
13312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
13412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (strlen(msg) > 0) {
13512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (coverage_log != NULL) {
13612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      fprintf(coverage_log, "%s\n", str);
13712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      fflush(coverage_log);
13812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
13912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // Overwrite the instruction and address with nops.
14012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    instr->SetInstructionBits(kNopInstr);
14112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr);
14212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
14312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // TODO(yuyin): 2 -> 3?
14412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  sim_->set_pc(sim_->get_pc() + 3 * Instruction::kInstructionSize);
14512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
14612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
14712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
14812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#else  // GENERATED_CODE_COVERAGE
14912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
15012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define UNSUPPORTED() printf("Unsupported instruction.\n");
15112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
15212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic void InitializeCoverage() {}
15312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
15412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
15512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid MipsDebugger::Stop(Instruction* instr) {
15612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Get the stop code.
15712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uint32_t code = instr->Bits(25, 6);
15812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Retrieve the encoded address, which comes just after this stop.
15912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  char* msg = *reinterpret_cast<char**>(sim_->get_pc() +
16012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      Instruction::kInstrSize);
16112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Update this stop description.
16212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (!sim_->watched_stops_[code].desc) {
16312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    sim_->watched_stops_[code].desc = msg;
16412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
16512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("Simulator hit %s (%u)\n", msg, code);
16612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // TODO(yuyin): 2 -> 3?
16712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  sim_->set_pc(sim_->get_pc() + 3 * Instruction::kInstrSize);
16812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Debug();
16912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
17012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#endif  // GENERATED_CODE_COVERAGE
17112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
17212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
17312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint64_t MipsDebugger::GetRegisterValue(int regnum) {
17412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (regnum == kNumSimuRegisters) {
17512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return sim_->get_pc();
17612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
17712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return sim_->get_register(regnum);
17812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
17912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
18012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
18112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
18212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint64_t MipsDebugger::GetFPURegisterValue(int regnum) {
18312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (regnum == kNumFPURegisters) {
18412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return sim_->get_pc();
18512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
18612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return sim_->get_fpu_register(regnum);
18712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
18812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
18912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
19012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
19112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgfloat MipsDebugger::GetFPURegisterValueFloat(int regnum) {
19212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (regnum == kNumFPURegisters) {
19312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return sim_->get_pc();
19412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
19512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return sim_->get_fpu_register_float(regnum);
19612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
19712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
19812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
19912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
20012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgdouble MipsDebugger::GetFPURegisterValueDouble(int regnum) {
20112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (regnum == kNumFPURegisters) {
20212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return sim_->get_pc();
20312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
20412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return sim_->get_fpu_register_double(regnum);
20512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
20612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
20712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
20812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
20912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool MipsDebugger::GetValue(const char* desc, int64_t* value) {
21012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int regnum = Registers::Number(desc);
21112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int fpuregnum = FPURegisters::Number(desc);
21212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
21312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (regnum != kInvalidRegister) {
21412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    *value = GetRegisterValue(regnum);
21512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return true;
21612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else if (fpuregnum != kInvalidFPURegister) {
21712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    *value = GetFPURegisterValue(fpuregnum);
21812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return true;
21912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else if (strncmp(desc, "0x", 2) == 0) {
22012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return SScanF(desc + 2, "%" SCNx64,
22112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                  reinterpret_cast<uint64_t*>(value)) == 1;
22212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
22312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return SScanF(desc, "%" SCNu64, reinterpret_cast<uint64_t*>(value)) == 1;
22412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
22512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return false;
22612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
22712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
22812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
22912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
23012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Check if a breakpoint can be set. If not return without any side-effects.
23112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (sim_->break_pc_ != NULL) {
23212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return false;
23312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
23412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
23512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Set the breakpoint.
23612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  sim_->break_pc_ = breakpc;
23712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  sim_->break_instr_ = breakpc->InstructionBits();
23812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Not setting the breakpoint instruction in the code itself. It will be set
23912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // when the debugger shell continues.
24012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return true;
24112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
24212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
24312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
24412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
24512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (sim_->break_pc_ != NULL) {
24612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
24712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
24812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
24912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  sim_->break_pc_ = NULL;
25012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  sim_->break_instr_ = 0;
25112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return true;
25212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
25312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
25412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
25512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid MipsDebugger::UndoBreakpoints() {
25612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (sim_->break_pc_ != NULL) {
25712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
25812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
25912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
26012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
26112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
26212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid MipsDebugger::RedoBreakpoints() {
26312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (sim_->break_pc_ != NULL) {
26412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
26512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
26612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
26712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
26812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
26912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid MipsDebugger::PrintAllRegs() {
27012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
27112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
27212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("\n");
27312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // at, v0, a0.
27412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
27512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         REG_INFO(1), REG_INFO(2), REG_INFO(4));
27612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // v1, a1.
27712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%34s\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
27812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         "", REG_INFO(3), REG_INFO(5));
27912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // a2.
28012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%34s\t%34s\t%3s: 0x%016lx %14ld\n", "", "", REG_INFO(6));
28112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // a3.
28212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%34s\t%34s\t%3s: 0x%016lx %14ld\n", "", "", REG_INFO(7));
28312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("\n");
28412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // a4-t3, s0-s7
28512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  for (int i = 0; i < 8; i++) {
28612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
28712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org           REG_INFO(8+i), REG_INFO(16+i));
28812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
28912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("\n");
29012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // t8, k0, LO.
29112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
29212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         REG_INFO(24), REG_INFO(26), REG_INFO(32));
29312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // t9, k1, HI.
29412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
29512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         REG_INFO(25), REG_INFO(27), REG_INFO(33));
29612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // sp, fp, gp.
29712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
29812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         REG_INFO(29), REG_INFO(30), REG_INFO(28));
29912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // pc.
30012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
30112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         REG_INFO(31), REG_INFO(34));
30212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
30312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef REG_INFO
30412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef FPU_REG_INFO
30512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
30612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
30712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
30812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid MipsDebugger::PrintAllRegsIncludingFPU() {
30912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define FPU_REG_INFO(n) FPURegisters::Name(n), \
31012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        GetFPURegisterValue(n), \
31112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        GetFPURegisterValueDouble(n)
31212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
31312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintAllRegs();
31412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
31512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("\n\n");
31612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // f0, f1, f2, ... f31.
31712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // TODO(plind): consider printing 2 columns for space efficiency.
31812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(0) );
31912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(1) );
32012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(2) );
32112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(3) );
32212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(4) );
32312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(5) );
32412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(6) );
32512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(7) );
32612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(8) );
32712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(9) );
32812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(10));
32912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(11));
33012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(12));
33112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(13));
33212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(14));
33312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(15));
33412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(16));
33512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(17));
33612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(18));
33712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(19));
33812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(20));
33912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(21));
34012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(22));
34112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(23));
34212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(24));
34312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(25));
34412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(26));
34512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(27));
34612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(28));
34712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(29));
34812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(30));
34912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(31));
35012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
35112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef REG_INFO
35212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef FPU_REG_INFO
35312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
35412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
35512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
35612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid MipsDebugger::Debug() {
35712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  intptr_t last_pc = -1;
35812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  bool done = false;
35912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
36012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define COMMAND_SIZE 63
36112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define ARG_SIZE 255
36212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
36312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define STR(a) #a
36412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#define XSTR(a) STR(a)
36512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
36612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  char cmd[COMMAND_SIZE + 1];
36712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  char arg1[ARG_SIZE + 1];
36812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  char arg2[ARG_SIZE + 1];
36912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  char* argv[3] = { cmd, arg1, arg2 };
37012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
37112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Make sure to have a proper terminating character if reaching the limit.
37212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  cmd[COMMAND_SIZE] = 0;
37312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  arg1[ARG_SIZE] = 0;
37412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  arg2[ARG_SIZE] = 0;
37512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
37612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Undo all set breakpoints while running in the debugger shell. This will
37712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // make them invisible to all commands.
37812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  UndoBreakpoints();
37912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
38012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
38112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (last_pc != sim_->get_pc()) {
38212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      disasm::NameConverter converter;
38312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      disasm::Disassembler dasm(converter);
38412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // Use a reasonably large buffer.
38512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      v8::internal::EmbeddedVector<char, 256> buffer;
38612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      dasm.InstructionDecode(buffer,
38712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                             reinterpret_cast<byte*>(sim_->get_pc()));
38812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      PrintF("  0x%016lx  %s\n", sim_->get_pc(), buffer.start());
38912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      last_pc = sim_->get_pc();
39012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
39112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    char* line = ReadLine("sim> ");
39212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (line == NULL) {
39312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
39412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else {
39512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      char* last_input = sim_->last_debugger_input();
39612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (strcmp(line, "\n") == 0 && last_input != NULL) {
39712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        line = last_input;
39812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else {
39912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        // Ownership is transferred to sim_;
40012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        sim_->set_last_debugger_input(line);
40112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
40212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // Use sscanf to parse the individual parts of the command line. At the
40312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // moment no command expects more than two parameters.
40412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      int argc = SScanF(line,
40512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                        "%" XSTR(COMMAND_SIZE) "s "
40612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                        "%" XSTR(ARG_SIZE) "s "
40712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                        "%" XSTR(ARG_SIZE) "s",
40812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                        cmd, arg1, arg2);
40912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
41012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc());
41112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        if (!(instr->IsTrap()) ||
41212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            instr->InstructionBits() == rtCallRedirInstr) {
41312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          sim_->InstructionDecode(
41412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              reinterpret_cast<Instruction*>(sim_->get_pc()));
41512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        } else {
41612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Allow si to jump over generated breakpoints.
41712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          PrintF("/!\\ Jumping over generated breakpoint.\n");
41812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
41912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
42012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
42112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        // Execute the one instruction we broke at with breakpoints disabled.
42212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
42312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        // Leave the debugger shell.
42412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        done = true;
42512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
42612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        if (argc == 2) {
42712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          int64_t value;
42812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          double dvalue;
42912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (strcmp(arg1, "all") == 0) {
43012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            PrintAllRegs();
43112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          } else if (strcmp(arg1, "allf") == 0) {
43212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            PrintAllRegsIncludingFPU();
43312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          } else {
43412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            int regnum = Registers::Number(arg1);
43512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            int fpuregnum = FPURegisters::Number(arg1);
43612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
43712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            if (regnum != kInvalidRegister) {
43812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              value = GetRegisterValue(regnum);
43912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              PrintF("%s: 0x%08lx %ld \n", arg1, value, value);
44012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            } else if (fpuregnum != kInvalidFPURegister) {
44112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              value = GetFPURegisterValue(fpuregnum);
44212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              dvalue = GetFPURegisterValueDouble(fpuregnum);
44312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              PrintF("%3s: 0x%016lx %16.4e\n",
44412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                     FPURegisters::Name(fpuregnum), value, dvalue);
44512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            } else {
44612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              PrintF("%s unrecognized\n", arg1);
44712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
44812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
44912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        } else {
45012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (argc == 3) {
45112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            if (strcmp(arg2, "single") == 0) {
45212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              int64_t value;
45312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              float fvalue;
45412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              int fpuregnum = FPURegisters::Number(arg1);
45512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
45612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              if (fpuregnum != kInvalidFPURegister) {
45712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                value = GetFPURegisterValue(fpuregnum);
45812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                value &= 0xffffffffUL;
45912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                fvalue = GetFPURegisterValueFloat(fpuregnum);
46012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                PrintF("%s: 0x%08lx %11.4e\n", arg1, value, fvalue);
46112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              } else {
46212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                PrintF("%s unrecognized\n", arg1);
46312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              }
46412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            } else {
46512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              PrintF("print <fpu register> single\n");
46612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
46712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          } else {
46812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            PrintF("print <register> or print <fpu register> single\n");
46912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
47012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
47112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else if ((strcmp(cmd, "po") == 0)
47212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                 || (strcmp(cmd, "printobject") == 0)) {
47312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        if (argc == 2) {
47412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          int64_t value;
47512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          OFStream os(stdout);
47612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (GetValue(arg1, &value)) {
47712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            Object* obj = reinterpret_cast<Object*>(value);
47812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            os << arg1 << ": \n";
47912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#ifdef DEBUG
48012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            obj->Print(os);
48112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            os << "\n";
48212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#else
48312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            os << Brief(obj) << "\n";
48412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#endif
48512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          } else {
48612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            os << arg1 << " unrecognized\n";
48712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
48812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        } else {
48912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          PrintF("printobject <value>\n");
49012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
49112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
49212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        int64_t* cur = NULL;
49312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        int64_t* end = NULL;
49412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        int next_arg = 1;
49512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
49612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        if (strcmp(cmd, "stack") == 0) {
49712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          cur = reinterpret_cast<int64_t*>(sim_->get_register(Simulator::sp));
49812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        } else {  // Command "mem".
49912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          int64_t value;
50012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (!GetValue(arg1, &value)) {
50112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            PrintF("%s unrecognized\n", arg1);
50212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            continue;
50312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
50412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          cur = reinterpret_cast<int64_t*>(value);
50512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          next_arg++;
50612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
50712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
50812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        int64_t words;
50912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        if (argc == next_arg) {
51012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          words = 10;
51112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        } else {
51212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (!GetValue(argv[next_arg], &words)) {
51312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            words = 10;
51412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
51512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
51612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        end = cur + words;
51712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
51812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        while (cur < end) {
51912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          PrintF("  0x%012lx:  0x%016lx %14ld",
52012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                 reinterpret_cast<intptr_t>(cur), *cur, *cur);
52112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
52212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          int64_t value = *cur;
52312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          Heap* current_heap = v8::internal::Isolate::Current()->heap();
52412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (((value & 1) == 0) || current_heap->Contains(obj)) {
52512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            PrintF(" (");
52612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            if ((value & 1) == 0) {
52712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              PrintF("smi %d", static_cast<int>(value >> 32));
52812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            } else {
52912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              obj->ShortPrint();
53012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
53112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            PrintF(")");
53212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
53312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          PrintF("\n");
53412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          cur++;
53512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
53612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
53712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else if ((strcmp(cmd, "disasm") == 0) ||
53812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                 (strcmp(cmd, "dpc") == 0) ||
53912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                 (strcmp(cmd, "di") == 0)) {
54012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        disasm::NameConverter converter;
54112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        disasm::Disassembler dasm(converter);
54212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        // Use a reasonably large buffer.
54312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        v8::internal::EmbeddedVector<char, 256> buffer;
54412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
54512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        byte* cur = NULL;
54612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        byte* end = NULL;
54712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
54812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        if (argc == 1) {
54912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          cur = reinterpret_cast<byte*>(sim_->get_pc());
55012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          end = cur + (10 * Instruction::kInstrSize);
55112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        } else if (argc == 2) {
55212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          int regnum = Registers::Number(arg1);
55312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (regnum != kInvalidRegister || strncmp(arg1, "0x", 2) == 0) {
55412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // The argument is an address or a register name.
55512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            int64_t value;
55612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            if (GetValue(arg1, &value)) {
55712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              cur = reinterpret_cast<byte*>(value);
55812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              // Disassemble 10 instructions at <arg1>.
55912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              end = cur + (10 * Instruction::kInstrSize);
56012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
56112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          } else {
56212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // The argument is the number of instructions.
56312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            int64_t value;
56412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            if (GetValue(arg1, &value)) {
56512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              cur = reinterpret_cast<byte*>(sim_->get_pc());
56612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              // Disassemble <arg1> instructions.
56712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              end = cur + (value * Instruction::kInstrSize);
56812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
56912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
57012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        } else {
57112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          int64_t value1;
57212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          int64_t value2;
57312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
57412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            cur = reinterpret_cast<byte*>(value1);
57512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            end = cur + (value2 * Instruction::kInstrSize);
57612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
57712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
57812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
57912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        while (cur < end) {
58012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          dasm.InstructionDecode(buffer, cur);
58112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          PrintF("  0x%08lx  %s\n",
58212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              reinterpret_cast<intptr_t>(cur), buffer.start());
58312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          cur += Instruction::kInstrSize;
58412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
58512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else if (strcmp(cmd, "gdb") == 0) {
58612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("relinquishing control to gdb\n");
58712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        v8::base::OS::DebugBreak();
58812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("regaining control from gdb\n");
58912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else if (strcmp(cmd, "break") == 0) {
59012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        if (argc == 2) {
59112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          int64_t value;
59212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (GetValue(arg1, &value)) {
59312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
59412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              PrintF("setting breakpoint failed\n");
59512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
59612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          } else {
59712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            PrintF("%s unrecognized\n", arg1);
59812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
59912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        } else {
60012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          PrintF("break <address>\n");
60112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
60212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else if (strcmp(cmd, "del") == 0) {
60312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        if (!DeleteBreakpoint(NULL)) {
60412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          PrintF("deleting breakpoint failed\n");
60512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
60612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else if (strcmp(cmd, "flags") == 0) {
60712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("No flags on MIPS !\n");
60812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else if (strcmp(cmd, "stop") == 0) {
60912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        int64_t value;
61012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        intptr_t stop_pc = sim_->get_pc() -
61112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            2 * Instruction::kInstrSize;
61212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
61312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        Instruction* msg_address =
61412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          reinterpret_cast<Instruction*>(stop_pc +
61512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              Instruction::kInstrSize);
61612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
61712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Remove the current stop.
61812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (sim_->IsStopInstruction(stop_instr)) {
61912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            stop_instr->SetInstructionBits(kNopInstr);
62012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            msg_address->SetInstructionBits(kNopInstr);
62112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          } else {
62212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            PrintF("Not at debugger stop.\n");
62312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
62412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        } else if (argc == 3) {
62512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Print information about all/the specified breakpoint(s).
62612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (strcmp(arg1, "info") == 0) {
62712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            if (strcmp(arg2, "all") == 0) {
62812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              PrintF("Stop information:\n");
62912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              for (uint32_t i = kMaxWatchpointCode + 1;
63012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                   i <= kMaxStopCode;
63112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                   i++) {
63212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                sim_->PrintStopInfo(i);
63312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              }
63412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            } else if (GetValue(arg2, &value)) {
63512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              sim_->PrintStopInfo(value);
63612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            } else {
63712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              PrintF("Unrecognized argument.\n");
63812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
63912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          } else if (strcmp(arg1, "enable") == 0) {
64012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // Enable all/the specified breakpoint(s).
64112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            if (strcmp(arg2, "all") == 0) {
64212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              for (uint32_t i = kMaxWatchpointCode + 1;
64312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                   i <= kMaxStopCode;
64412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                   i++) {
64512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                sim_->EnableStop(i);
64612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              }
64712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            } else if (GetValue(arg2, &value)) {
64812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              sim_->EnableStop(value);
64912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            } else {
65012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              PrintF("Unrecognized argument.\n");
65112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
65212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          } else if (strcmp(arg1, "disable") == 0) {
65312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // Disable all/the specified breakpoint(s).
65412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            if (strcmp(arg2, "all") == 0) {
65512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              for (uint32_t i = kMaxWatchpointCode + 1;
65612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                   i <= kMaxStopCode;
65712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                   i++) {
65812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                sim_->DisableStop(i);
65912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              }
66012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            } else if (GetValue(arg2, &value)) {
66112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              sim_->DisableStop(value);
66212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            } else {
66312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              PrintF("Unrecognized argument.\n");
66412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
66512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
66612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        } else {
66712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          PrintF("Wrong usage. Use help command for more information.\n");
66812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
66912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) {
67012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        // Print registers and disassemble.
67112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintAllRegs();
67212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("\n");
67312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
67412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        disasm::NameConverter converter;
67512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        disasm::Disassembler dasm(converter);
67612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        // Use a reasonably large buffer.
67712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        v8::internal::EmbeddedVector<char, 256> buffer;
67812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
67912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        byte* cur = NULL;
68012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        byte* end = NULL;
68112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
68212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        if (argc == 1) {
68312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          cur = reinterpret_cast<byte*>(sim_->get_pc());
68412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          end = cur + (10 * Instruction::kInstrSize);
68512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        } else if (argc == 2) {
68612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          int64_t value;
68712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (GetValue(arg1, &value)) {
68812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            cur = reinterpret_cast<byte*>(value);
68912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // no length parameter passed, assume 10 instructions
69012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            end = cur + (10 * Instruction::kInstrSize);
69112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
69212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        } else {
69312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          int64_t value1;
69412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          int64_t value2;
69512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
69612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            cur = reinterpret_cast<byte*>(value1);
69712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            end = cur + (value2 * Instruction::kInstrSize);
69812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
69912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
70012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
70112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        while (cur < end) {
70212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          dasm.InstructionDecode(buffer, cur);
70312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          PrintF("  0x%08lx  %s\n",
70412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                 reinterpret_cast<intptr_t>(cur), buffer.start());
70512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          cur += Instruction::kInstrSize;
70612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
70712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
70812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("cont\n");
70912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("  continue execution (alias 'c')\n");
71012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("stepi\n");
71112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("  step one instruction (alias 'si')\n");
71212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("print <register>\n");
71312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("  print register content (alias 'p')\n");
71412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("  use register name 'all' to print all registers\n");
71512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("printobject <register>\n");
71612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("  print an object from a register (alias 'po')\n");
71712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("stack [<words>]\n");
71812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("  dump stack content, default dump 10 words)\n");
71912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("mem <address> [<words>]\n");
72012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("  dump memory content, default dump 10 words)\n");
72112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("flags\n");
72212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("  print flags\n");
72312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("disasm [<instructions>]\n");
72412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("disasm [<address/register>]\n");
72512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("disasm [[<address/register>] <instructions>]\n");
72612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("  disassemble code, default is 10 instructions\n");
72712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("  from pc (alias 'di')\n");
72812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("gdb\n");
72912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("  enter gdb\n");
73012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("break <address>\n");
73112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("  set a break point on the address\n");
73212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("del\n");
73312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("  delete the breakpoint\n");
73412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("stop feature:\n");
73512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("  Description:\n");
73612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("    Stops are debug instructions inserted by\n");
73712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("    the Assembler::stop() function.\n");
73812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("    When hitting a stop, the Simulator will\n");
73912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("    stop and and give control to the Debugger.\n");
74012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("    All stop codes are watched:\n");
74112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("    - They can be enabled / disabled: the Simulator\n");
74212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("       will / won't stop when hitting them.\n");
74312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("    - The Simulator keeps track of how many times they \n");
74412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("      are met. (See the info command.) Going over a\n");
74512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("      disabled stop still increases its counter. \n");
74612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("  Commands:\n");
74712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("    stop info all/<code> : print infos about number <code>\n");
74812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("      or all stop(s).\n");
74912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("    stop enable/disable all/<code> : enables / disables\n");
75012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("      all or number <code> stop(s)\n");
75112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("    stop unstop\n");
75212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("      ignore the stop instruction at the current location\n");
75312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("      from now on\n");
75412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else {
75512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("Unknown command: %s\n", cmd);
75612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
75712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
75812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
75912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
76012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Add all the breakpoints back to stop execution and enter the debugger
76112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // shell when hit.
76212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  RedoBreakpoints();
76312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
76412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef COMMAND_SIZE
76512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef ARG_SIZE
76612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
76712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef STR
76812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef XSTR
76912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
77012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
77112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
77212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic bool ICacheMatch(void* one, void* two) {
773e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
774e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
77512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return one == two;
77612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
77712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
77812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
77912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic uint32_t ICacheHash(void* key) {
78012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
78112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
78212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
78312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
78412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstatic bool AllOnOnePage(uintptr_t start, int size) {
78512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  intptr_t start_page = (start & ~CachePage::kPageMask);
78612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
78712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return start_page == end_page;
78812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
78912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
79012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
79112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_last_debugger_input(char* input) {
79212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  DeleteArray(last_debugger_input_);
79312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  last_debugger_input_ = input;
79412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
79512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
79612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
79712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::FlushICache(v8::internal::HashMap* i_cache,
79812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                            void* start_addr,
79912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                            size_t size) {
80012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t start = reinterpret_cast<int64_t>(start_addr);
80112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t intra_line = (start & CachePage::kLineMask);
80212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  start -= intra_line;
80312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  size += intra_line;
80412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  size = ((size - 1) | CachePage::kLineMask) + 1;
80512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int offset = (start & CachePage::kPageMask);
80612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  while (!AllOnOnePage(start, size - 1)) {
80712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int bytes_to_flush = CachePage::kPageSize - offset;
80812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    FlushOnePage(i_cache, start, bytes_to_flush);
80912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    start += bytes_to_flush;
81012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    size -= bytes_to_flush;
811e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ((uint64_t)0, start & CachePage::kPageMask);
81212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    offset = 0;
81312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
81412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (size != 0) {
81512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    FlushOnePage(i_cache, start, size);
81612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
81712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
81812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
81912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
82012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgCachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
82112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
82212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                                        ICacheHash(page),
82312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                                        true);
82412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (entry->value == NULL) {
82512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    CachePage* new_page = new CachePage();
82612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    entry->value = new_page;
82712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
82812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return reinterpret_cast<CachePage*>(entry->value);
82912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
83012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
83112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
83212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Flush from start up to and not including start + size.
83312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
83412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                             intptr_t start,
83512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                             int size) {
836e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(size <= CachePage::kPageSize);
837e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(AllOnOnePage(start, size - 1));
838e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((start & CachePage::kLineMask) == 0);
839e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((size & CachePage::kLineMask) == 0);
84012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
84112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int offset = (start & CachePage::kPageMask);
84212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  CachePage* cache_page = GetCachePage(i_cache, page);
84312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  char* valid_bytemap = cache_page->ValidityByte(offset);
84412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
84512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
84612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
84712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
84812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::CheckICache(v8::internal::HashMap* i_cache,
84912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                            Instruction* instr) {
85012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t address = reinterpret_cast<int64_t>(instr);
85112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
85212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
85312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int offset = (address & CachePage::kPageMask);
85412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  CachePage* cache_page = GetCachePage(i_cache, page);
85512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  char* cache_valid_byte = cache_page->ValidityByte(offset);
85612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
85712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
85812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (cache_hit) {
85912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // Check that the data in memory matches the contents of the I-cache.
86012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    CHECK_EQ(0, memcmp(reinterpret_cast<void*>(instr),
86112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       cache_page->CachedData(offset),
86212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       Instruction::kInstrSize));
86312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
86412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // Cache miss.  Load memory into the cache.
86512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    memcpy(cached_line, line, CachePage::kLineLength);
86612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    *cache_valid_byte = CachePage::LINE_VALID;
86712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
86812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
86912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
87012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
87112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::Initialize(Isolate* isolate) {
87212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (isolate->simulator_initialized()) return;
87312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  isolate->set_simulator_initialized(true);
87412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  ::v8::internal::ExternalReference::set_redirector(isolate,
87512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                                    &RedirectExternalReference);
87612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
87712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
87812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
87912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgSimulator::Simulator(Isolate* isolate) : isolate_(isolate) {
88012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  i_cache_ = isolate_->simulator_i_cache();
88112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (i_cache_ == NULL) {
88212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    i_cache_ = new v8::internal::HashMap(&ICacheMatch);
88312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    isolate_->set_simulator_i_cache(i_cache_);
88412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
88512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Initialize(isolate);
88612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Set up simulator support first. Some of this information is needed to
88712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // setup the architecture state.
88812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  stack_size_ = FLAG_sim_stack_size * KB;
88912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  stack_ = reinterpret_cast<char*>(malloc(stack_size_));
89012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  pc_modified_ = false;
89112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  icount_ = 0;
89212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  break_count_ = 0;
89312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  break_pc_ = NULL;
89412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  break_instr_ = 0;
89512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
89612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Set up architecture state.
89712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // All registers are initialized to zero to start with.
89812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  for (int i = 0; i < kNumSimuRegisters; i++) {
89912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    registers_[i] = 0;
90012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
90112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  for (int i = 0; i < kNumFPURegisters; i++) {
90212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    FPUregisters_[i] = 0;
90312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
90412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  FCSR_ = 0;
90512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
90612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // The sp is initialized to point to the bottom (high address) of the
90712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // allocated stack area. To be safe in potential stack underflows we leave
90812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // some buffer below.
90912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  registers_[sp] = reinterpret_cast<int64_t>(stack_) + stack_size_ - 64;
91012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // The ra and pc are initialized to a known bad value that will cause an
91112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // access violation if the simulator ever tries to execute it.
91212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  registers_[pc] = bad_ra;
91312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  registers_[ra] = bad_ra;
91412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  InitializeCoverage();
91512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  for (int i = 0; i < kNumExceptions; i++) {
91612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    exceptions[i] = 0;
91712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
91812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
91912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  last_debugger_input_ = NULL;
92012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
92112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
92212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
92312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgSimulator::~Simulator() {
92412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
92512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
92612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
92712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// When the generated code calls an external reference we need to catch that in
92812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// the simulator.  The external reference will be a function compiled for the
92912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// host architecture.  We need to call that function instead of trying to
93012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// execute it with the simulator.  We do that by redirecting the external
93112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// reference to a swi (software-interrupt) instruction that is handled by
93212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// the simulator.  We write the original destination of the jump just at a known
93312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// offset from the swi instruction so the simulator knows what to call.
93412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgclass Redirection {
93512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org public:
93612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Redirection(void* external_function, ExternalReference::Type type)
93712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      : external_function_(external_function),
93812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        swi_instruction_(rtCallRedirInstr),
93912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        type_(type),
94012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        next_(NULL) {
94112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    Isolate* isolate = Isolate::Current();
94212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    next_ = isolate->simulator_redirection();
94312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    Simulator::current(isolate)->
94412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        FlushICache(isolate->simulator_i_cache(),
94512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                    reinterpret_cast<void*>(&swi_instruction_),
94612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                    Instruction::kInstrSize);
94712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    isolate->set_simulator_redirection(this);
94812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
94912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
95012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  void* address_of_swi_instruction() {
95112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return reinterpret_cast<void*>(&swi_instruction_);
95212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
95312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
95412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  void* external_function() { return external_function_; }
95512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  ExternalReference::Type type() { return type_; }
95612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
95712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  static Redirection* Get(void* external_function,
95812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                          ExternalReference::Type type) {
95912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    Isolate* isolate = Isolate::Current();
96012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    Redirection* current = isolate->simulator_redirection();
96112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    for (; current != NULL; current = current->next_) {
96212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (current->external_function_ == external_function) return current;
96312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
96412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return new Redirection(external_function, type);
96512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
96612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
96712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
96812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
96912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    char* addr_of_redirection =
97012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
97112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return reinterpret_cast<Redirection*>(addr_of_redirection);
97212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
97312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
97412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  static void* ReverseRedirection(int64_t reg) {
97512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    Redirection* redirection = FromSwiInstruction(
97612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg)));
97712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return redirection->external_function();
97812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
97912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
98012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org private:
98112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  void* external_function_;
98212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uint32_t swi_instruction_;
98312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  ExternalReference::Type type_;
98412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Redirection* next_;
98512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org};
98612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
98712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
98812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid* Simulator::RedirectExternalReference(void* external_function,
98912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                           ExternalReference::Type type) {
99012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Redirection* redirection = Redirection::Get(external_function, type);
99112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return redirection->address_of_swi_instruction();
99212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
99312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
99412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
99512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Get the active Simulator for the current thread.
99612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgSimulator* Simulator::current(Isolate* isolate) {
99712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  v8::internal::Isolate::PerIsolateThreadData* isolate_data =
99812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org       isolate->FindOrAllocatePerThreadDataForThisThread();
999e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(isolate_data != NULL);
1000e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(isolate_data != NULL);
100112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
100212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Simulator* sim = isolate_data->simulator();
100312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (sim == NULL) {
100412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // TODO(146): delete the simulator object when a thread/isolate goes away.
100512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    sim = new Simulator(isolate);
100612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    isolate_data->set_simulator(sim);
100712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
100812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return sim;
100912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
101012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
101112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
101212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Sets the register in the architecture state. It will also deal with updating
101312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Simulator internal state for special registers such as PC.
101412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_register(int reg, int64_t value) {
1015e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
101612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (reg == pc) {
101712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    pc_modified_ = true;
101812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
101912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
102012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Zero register always holds 0.
102112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  registers_[reg] = (reg == 0) ? 0 : value;
102212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
102312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
102412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
102512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_dw_register(int reg, const int* dbl) {
1026e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
102712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  registers_[reg] = dbl[1];
102812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  registers_[reg] = registers_[reg] << 32;
102912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  registers_[reg] += dbl[0];
103012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
103112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
103212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
103312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_fpu_register(int fpureg, int64_t value) {
1034e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
103512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  FPUregisters_[fpureg] = value;
103612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
103712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
103812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
103912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_fpu_register_word(int fpureg, int32_t value) {
104012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Set ONLY lower 32-bits, leaving upper bits untouched.
104112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // TODO(plind): big endian issue.
1042e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
104312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int32_t *pword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg]);
104412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  *pword = value;
104512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
104612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
104712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
104812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_fpu_register_hi_word(int fpureg, int32_t value) {
104912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Set ONLY upper 32-bits, leaving lower bits untouched.
105012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // TODO(plind): big endian issue.
1051e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
105212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int32_t *phiword = (reinterpret_cast<int32_t*>(&FPUregisters_[fpureg])) + 1;
105312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  *phiword = value;
105412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
105512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
105612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
105712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_fpu_register_float(int fpureg, float value) {
1058e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1059e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org  *bit_cast<float*>(&FPUregisters_[fpureg]) = value;
106012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
106112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
106212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
106312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_fpu_register_double(int fpureg, double value) {
1064e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1065e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org  *bit_cast<double*>(&FPUregisters_[fpureg]) = value;
106612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
106712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
106812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
106912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Get the register from the architecture state. This function does handle
107012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// the special case of accessing the PC register.
107112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint64_t Simulator::get_register(int reg) const {
1072e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((reg >= 0) && (reg < kNumSimuRegisters));
107312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (reg == 0)
107412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return 0;
107512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  else
107612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
107712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
107812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
107912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
108012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgdouble Simulator::get_double_from_register_pair(int reg) {
108112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // TODO(plind): bad ABI stuff, refactor or remove.
1082e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0));
108312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
108412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  double dm_val = 0.0;
108512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Read the bits from the unsigned integer register_[] array
108612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // into the double precision floating point value and return it.
108712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  char buffer[sizeof(registers_[0])];
108812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  memcpy(buffer, &registers_[reg], sizeof(registers_[0]));
108912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  memcpy(&dm_val, buffer, sizeof(registers_[0]));
109012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return(dm_val);
109112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
109212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
109312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
109412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint64_t Simulator::get_fpu_register(int fpureg) const {
1095e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
109612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return FPUregisters_[fpureg];
109712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
109812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
109912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
110012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint32_t Simulator::get_fpu_register_word(int fpureg) const {
1101e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
110212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff);
110312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
110412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
110512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
110612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint32_t Simulator::get_fpu_register_signed_word(int fpureg) const {
1107e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
110812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff);
110912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
111012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
111112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
1112a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgint32_t Simulator::get_fpu_register_hi_word(int fpureg) const {
1113e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1114a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  return static_cast<int32_t>((FPUregisters_[fpureg] >> 32) & 0xffffffff);
111512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
111612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
111712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
111812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgfloat Simulator::get_fpu_register_float(int fpureg) const {
1119e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1120e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org  return *bit_cast<float*>(const_cast<int64_t*>(&FPUregisters_[fpureg]));
112112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
112212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
112312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
112412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgdouble Simulator::get_fpu_register_double(int fpureg) const {
1125e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters));
1126e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org  return *bit_cast<double*>(&FPUregisters_[fpureg]);
112712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
112812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
112912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
113012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Runtime FP routines take up to two double arguments and zero
113112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// or one integer arguments. All are constructed here,
113212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// from a0-a3 or f12 and f13 (n64), or f14 (O32).
113312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
113412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (!IsMipsSoftFloatABI) {
113512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    const int fparg2 = (kMipsAbi == kN64) ? 13 : 14;
113612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    *x = get_fpu_register_double(12);
113712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    *y = get_fpu_register_double(fparg2);
113812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    *z = get_register(a2);
113912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
114012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // TODO(plind): bad ABI stuff, refactor or remove.
114112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // We use a char buffer to get around the strict-aliasing rules which
114212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // otherwise allow the compiler to optimize away the copy.
114312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    char buffer[sizeof(*x)];
114412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
114512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
114612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // Registers a0 and a1 -> x.
114712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    reg_buffer[0] = get_register(a0);
114812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    reg_buffer[1] = get_register(a1);
114912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    memcpy(x, buffer, sizeof(buffer));
115012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // Registers a2 and a3 -> y.
115112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    reg_buffer[0] = get_register(a2);
115212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    reg_buffer[1] = get_register(a3);
115312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    memcpy(y, buffer, sizeof(buffer));
115412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // Register 2 -> z.
115512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    reg_buffer[0] = get_register(a2);
115612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    memcpy(z, buffer, sizeof(*z));
115712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
115812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
115912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
116012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
116112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// The return value is either in v0/v1 or f0.
116212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::SetFpResult(const double& result) {
116312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (!IsMipsSoftFloatABI) {
116412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_fpu_register_double(0, result);
116512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
116612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    char buffer[2 * sizeof(registers_[0])];
116712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int64_t* reg_buffer = reinterpret_cast<int64_t*>(buffer);
116812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    memcpy(buffer, &result, sizeof(buffer));
116912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // Copy result to v0 and v1.
117012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_register(v0, reg_buffer[0]);
117112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_register(v1, reg_buffer[1]);
117212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
117312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
117412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
117512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
117612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Helper functions for setting and testing the FCSR register's bits.
117712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_fcsr_bit(uint32_t cc, bool value) {
117812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (value) {
117912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    FCSR_ |= (1 << cc);
118012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
118112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    FCSR_ &= ~(1 << cc);
118212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
118312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
118412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
118512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
118612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool Simulator::test_fcsr_bit(uint32_t cc) {
118712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return FCSR_ & (1 << cc);
118812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
118912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
119012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
119112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Sets the rounding error codes in FCSR based on the result of the rounding.
119212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Returns true if the operation was invalid.
119312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool Simulator::set_fcsr_round_error(double original, double rounded) {
119412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  bool ret = false;
119512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  double max_int32 = std::numeric_limits<int32_t>::max();
119612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  double min_int32 = std::numeric_limits<int32_t>::min();
119712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
119812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (!std::isfinite(original) || !std::isfinite(rounded)) {
119912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
120012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    ret = true;
120112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
120212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
120312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (original != rounded) {
120412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_fcsr_bit(kFCSRInexactFlagBit, true);
120512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
120612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
120712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
120812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_fcsr_bit(kFCSRUnderflowFlagBit, true);
120912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    ret = true;
121012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
121112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
121212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (rounded > max_int32 || rounded < min_int32) {
121312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_fcsr_bit(kFCSROverflowFlagBit, true);
121412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // The reference is not really clear but it seems this is required:
121512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
121612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    ret = true;
121712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
121812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
121912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return ret;
122012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
122112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
122212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
122312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Sets the rounding error codes in FCSR based on the result of the rounding.
122412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Returns true if the operation was invalid.
122512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool Simulator::set_fcsr_round64_error(double original, double rounded) {
122612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  bool ret = false;
122712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  double max_int64 = std::numeric_limits<int64_t>::max();
122812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  double min_int64 = std::numeric_limits<int64_t>::min();
122912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
123012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (!std::isfinite(original) || !std::isfinite(rounded)) {
123112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
123212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    ret = true;
123312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
123412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
123512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (original != rounded) {
123612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_fcsr_bit(kFCSRInexactFlagBit, true);
123712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
123812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
123912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
124012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_fcsr_bit(kFCSRUnderflowFlagBit, true);
124112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    ret = true;
124212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
124312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
124412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (rounded > max_int64 || rounded < min_int64) {
124512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_fcsr_bit(kFCSROverflowFlagBit, true);
124612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // The reference is not really clear but it seems this is required:
124712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
124812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    ret = true;
124912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
125012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
125112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return ret;
125212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
125312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
125412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
125512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Raw access to the PC register.
125612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::set_pc(int64_t value) {
125712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  pc_modified_ = true;
125812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  registers_[pc] = value;
125912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
126012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
126112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
126212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool Simulator::has_bad_pc() const {
126312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
126412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
126512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
126612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
126712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Raw access to the PC register without the special adjustment when reading.
126812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint64_t Simulator::get_pc() const {
126912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return registers_[pc];
127012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
127112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
127212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
127312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// The MIPS cannot do unaligned reads and writes.  On some MIPS platforms an
127412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// interrupt is caused.  On others it does a funky rotation thing.  For now we
127512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// simply disallow unaligned reads, but at some point we may want to move to
127612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// emulating the rotate behaviour.  Note that simulator runs have the runtime
127712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// system running directly on the host system and only generated code is
127812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// executed in the simulator.  Since the host is typically IA32 we will not
127912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// get the correct MIPS-like behaviour on unaligned accesses.
128012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
128112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// TODO(plind): refactor this messy debug code when we do unaligned access.
128212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::DieOrDebug() {
128312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (1) {  // Flag for this was removed.
128412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    MipsDebugger dbg(this);
128512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    dbg.Debug();
128612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
128712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    base::OS::Abort();
128812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
128912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
129012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
129112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
129212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::TraceRegWr(int64_t value) {
129312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (::v8::internal::FLAG_trace_sim) {
129412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    SNPrintF(trace_buf_, "%016lx", value);
129512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
129612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
129712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
129812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
129912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// TODO(plind): consider making icount_ printing a flag option.
130012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::TraceMemRd(int64_t addr, int64_t value) {
130112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (::v8::internal::FLAG_trace_sim) {
130212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    SNPrintF(trace_buf_, "%016lx <-- [%016lx]    (%ld)",
130312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org             value, addr, icount_);
130412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
130512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
130612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
130712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
130812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::TraceMemWr(int64_t addr, int64_t value, TraceType t) {
130912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (::v8::internal::FLAG_trace_sim) {
131012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    switch (t) {
131112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      case BYTE:
131212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        SNPrintF(trace_buf_, "               %02x --> [%016lx]",
131312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                 static_cast<int8_t>(value), addr);
131412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        break;
131512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      case HALF:
131612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        SNPrintF(trace_buf_, "            %04x --> [%016lx]",
131712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                 static_cast<int16_t>(value), addr);
131812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        break;
131912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      case WORD:
132012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        SNPrintF(trace_buf_, "        %08x --> [%016lx]",
132112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                 static_cast<int32_t>(value), addr);
132212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        break;
132312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      case DWORD:
132412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        SNPrintF(trace_buf_, "%016lx --> [%016lx]    (%ld)",
132512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                 value, addr, icount_);
132612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        break;
132712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
132812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
132912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
133012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
133112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
133212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// TODO(plind): sign-extend and zero-extend not implmented properly
133312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// on all the ReadXX functions, I don't think re-interpret cast does it.
133412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint32_t Simulator::ReadW(int64_t addr, Instruction* instr) {
133512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (addr >=0 && addr < 0x400) {
133612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // This has to be a NULL-dereference, drop into debugger.
133712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    PrintF("Memory read from bad address: 0x%08lx, pc=0x%08lx\n",
133812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org           addr, reinterpret_cast<intptr_t>(instr));
133912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    DieOrDebug();
134012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
134112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if ((addr & 0x3) == 0) {
134212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int32_t* ptr = reinterpret_cast<int32_t*>(addr);
134312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    TraceMemRd(addr, static_cast<int64_t>(*ptr));
134412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return *ptr;
134512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
134612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("Unaligned read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
134712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         addr,
134812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         reinterpret_cast<intptr_t>(instr));
134912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  DieOrDebug();
135012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return 0;
135112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
135212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
135312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
135412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orguint32_t Simulator::ReadWU(int64_t addr, Instruction* instr) {
135512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (addr >=0 && addr < 0x400) {
135612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // This has to be a NULL-dereference, drop into debugger.
135712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    PrintF("Memory read from bad address: 0x%08lx, pc=0x%08lx\n",
135812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org           addr, reinterpret_cast<intptr_t>(instr));
135912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    DieOrDebug();
136012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
136112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if ((addr & 0x3) == 0) {
136212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
136312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    TraceMemRd(addr, static_cast<int64_t>(*ptr));
136412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return *ptr;
136512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
136612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("Unaligned read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
136712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         addr,
136812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         reinterpret_cast<intptr_t>(instr));
136912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  DieOrDebug();
137012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return 0;
137112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
137212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
137312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
137412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::WriteW(int64_t addr, int value, Instruction* instr) {
137512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (addr >= 0 && addr < 0x400) {
137612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // This has to be a NULL-dereference, drop into debugger.
137712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    PrintF("Memory write to bad address: 0x%08lx, pc=0x%08lx\n",
137812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org           addr, reinterpret_cast<intptr_t>(instr));
137912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    DieOrDebug();
138012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
138112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if ((addr & 0x3) == 0) {
138212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    TraceMemWr(addr, value, WORD);
138312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int* ptr = reinterpret_cast<int*>(addr);
138412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    *ptr = value;
138512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return;
138612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
138712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("Unaligned write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
138812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         addr,
138912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         reinterpret_cast<intptr_t>(instr));
139012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  DieOrDebug();
139112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
139212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
139312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
139412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint64_t Simulator::Read2W(int64_t addr, Instruction* instr) {
139512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (addr >=0 && addr < 0x400) {
139612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // This has to be a NULL-dereference, drop into debugger.
139712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    PrintF("Memory read from bad address: 0x%08lx, pc=0x%08lx\n",
139812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org           addr, reinterpret_cast<intptr_t>(instr));
139912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    DieOrDebug();
140012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
140112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if ((addr & kPointerAlignmentMask) == 0) {
140212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int64_t* ptr = reinterpret_cast<int64_t*>(addr);
140312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    TraceMemRd(addr, *ptr);
140412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return *ptr;
140512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
140612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("Unaligned read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
140712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         addr,
140812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         reinterpret_cast<intptr_t>(instr));
140912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  DieOrDebug();
141012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return 0;
141112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
141212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
141312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
141412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::Write2W(int64_t addr, int64_t value, Instruction* instr) {
141512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (addr >= 0 && addr < 0x400) {
141612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // This has to be a NULL-dereference, drop into debugger.
141712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    PrintF("Memory write to bad address: 0x%08lx, pc=0x%08lx\n",
141812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org           addr, reinterpret_cast<intptr_t>(instr));
141912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    DieOrDebug();
142012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
142112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if ((addr & kPointerAlignmentMask) == 0) {
142212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    TraceMemWr(addr, value, DWORD);
142312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int64_t* ptr = reinterpret_cast<int64_t*>(addr);
142412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    *ptr = value;
142512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return;
142612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
142712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("Unaligned write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
142812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         addr,
142912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         reinterpret_cast<intptr_t>(instr));
143012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  DieOrDebug();
143112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
143212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
143312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
143412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgdouble Simulator::ReadD(int64_t addr, Instruction* instr) {
143512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if ((addr & kDoubleAlignmentMask) == 0) {
143612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    double* ptr = reinterpret_cast<double*>(addr);
143712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return *ptr;
143812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
143912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("Unaligned (double) read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
144012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         addr,
144112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         reinterpret_cast<intptr_t>(instr));
144212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  base::OS::Abort();
144312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return 0;
144412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
144512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
144612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
144712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::WriteD(int64_t addr, double value, Instruction* instr) {
144812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if ((addr & kDoubleAlignmentMask) == 0) {
144912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    double* ptr = reinterpret_cast<double*>(addr);
145012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    *ptr = value;
145112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return;
145212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
145312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("Unaligned (double) write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
145412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         addr,
145512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         reinterpret_cast<intptr_t>(instr));
145612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  DieOrDebug();
145712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
145812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
145912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
146012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orguint16_t Simulator::ReadHU(int64_t addr, Instruction* instr) {
146112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if ((addr & 1) == 0) {
146212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
146312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    TraceMemRd(addr, static_cast<int64_t>(*ptr));
146412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return *ptr;
146512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
146612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("Unaligned unsigned halfword read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
146712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         addr,
146812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         reinterpret_cast<intptr_t>(instr));
146912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  DieOrDebug();
147012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return 0;
147112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
147212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
147312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
147412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint16_t Simulator::ReadH(int64_t addr, Instruction* instr) {
147512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if ((addr & 1) == 0) {
147612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int16_t* ptr = reinterpret_cast<int16_t*>(addr);
147712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    TraceMemRd(addr, static_cast<int64_t>(*ptr));
147812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return *ptr;
147912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
148012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("Unaligned signed halfword read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
148112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         addr,
148212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         reinterpret_cast<intptr_t>(instr));
148312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  DieOrDebug();
148412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return 0;
148512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
148612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
148712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
148812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::WriteH(int64_t addr, uint16_t value, Instruction* instr) {
148912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if ((addr & 1) == 0) {
149012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    TraceMemWr(addr, value, HALF);
149112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
149212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    *ptr = value;
149312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return;
149412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
149512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF(
149612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      "Unaligned unsigned halfword write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
149712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr,
149812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      reinterpret_cast<intptr_t>(instr));
149912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  DieOrDebug();
150012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
150112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
150212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
150312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::WriteH(int64_t addr, int16_t value, Instruction* instr) {
150412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if ((addr & 1) == 0) {
150512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    TraceMemWr(addr, value, HALF);
150612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int16_t* ptr = reinterpret_cast<int16_t*>(addr);
150712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    *ptr = value;
150812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return;
150912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
151012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("Unaligned halfword write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
151112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         addr,
151212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         reinterpret_cast<intptr_t>(instr));
151312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  DieOrDebug();
151412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
151512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
151612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
151712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orguint32_t Simulator::ReadBU(int64_t addr) {
151812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
151912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  TraceMemRd(addr, static_cast<int64_t>(*ptr));
152012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return *ptr & 0xff;
152112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
152212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
152312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
152412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint32_t Simulator::ReadB(int64_t addr) {
152512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
152612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  TraceMemRd(addr, static_cast<int64_t>(*ptr));
152712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return *ptr;
152812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
152912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
153012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
153112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::WriteB(int64_t addr, uint8_t value) {
153212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  TraceMemWr(addr, value, BYTE);
153312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
153412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  *ptr = value;
153512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
153612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
153712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
153812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::WriteB(int64_t addr, int8_t value) {
153912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  TraceMemWr(addr, value, BYTE);
154012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
154112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  *ptr = value;
154212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
154312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
154412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
154512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Returns the limit of the stack area to enable checking for stack overflows.
154612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orguintptr_t Simulator::StackLimit() const {
154712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Leave a safety margin of 1024 bytes to prevent overrunning the stack when
154812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // pushing values.
154912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return reinterpret_cast<uintptr_t>(stack_) + 1024;
155012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
155112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
155212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
155312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Unsupported instructions use Format to print an error and stop execution.
155412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::Format(Instruction* instr, const char* format) {
155512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("Simulator found unsupported instruction:\n 0x%08lx: %s\n",
155612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         reinterpret_cast<intptr_t>(instr), format);
155712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  UNIMPLEMENTED_MIPS();
155812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
155912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
156012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
156112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Calls into the V8 runtime are based on this very simple interface.
156212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Note: To be able to return two values from some calls the code in runtime.cc
156312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// uses the ObjectPair which is essentially two 32-bit values stuffed into a
156412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// 64-bit value. With the code below we assume that all runtime calls return
156512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// 64 bits of result. If they don't, the v1 result register contains a bogus
156612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// value, which is fine because it is caller-saved.
156712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
156812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgstruct ObjectPair {
156912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Object* x;
157012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Object* y;
157112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org};
157212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
157312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0,
157412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                        int64_t arg1,
157512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                        int64_t arg2,
157612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                        int64_t arg3,
157712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                        int64_t arg4,
157812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                        int64_t arg5);
157912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
158012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
158112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// These prototypes handle the four types of FP calls.
158212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
158312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
158412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef double (*SimulatorRuntimeFPCall)(double darg0);
158512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
158612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
158712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// This signature supports direct call in to API function native callback
158812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// (refer to InvocationCallback in v8.h).
158912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0);
159012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1);
159112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
159212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// This signature supports direct call to accessor getter callback.
159312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1);
159412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgtypedef void (*SimulatorRuntimeProfilingGetterCall)(
159512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int64_t arg0, int64_t arg1, void* arg2);
159612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
159712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Software interrupt instructions are used by the simulator to call into the
159812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// C-based V8 runtime. They are also used for debugging with simulator.
159912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::SoftwareInterrupt(Instruction* instr) {
160012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // There are several instructions that could get us here,
160112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // the break_ instruction, or several variants of traps. All
160212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Are "SPECIAL" class opcode, and are distinuished by function.
160312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int32_t func = instr->FunctionFieldRaw();
160412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uint32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1;
160512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // We first check if we met a call_rt_redirected.
160612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (instr->InstructionBits() == rtCallRedirInstr) {
160712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    Redirection* redirection = Redirection::FromSwiInstruction(instr);
160812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int64_t arg0 = get_register(a0);
160912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int64_t arg1 = get_register(a1);
161012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int64_t arg2 = get_register(a2);
161112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int64_t arg3 = get_register(a3);
161212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int64_t arg4, arg5;
161312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
161412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (kMipsAbi == kN64) {
161512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      arg4 = get_register(a4);  // Abi n64 register a4.
161612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      arg5 = get_register(a5);  // Abi n64 register a5.
161712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else {  // Abi O32.
161812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      int64_t* stack_pointer = reinterpret_cast<int64_t*>(get_register(sp));
161912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // Args 4 and 5 are on the stack after the reserved space for args 0..3.
162012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      arg4 = stack_pointer[4];
162112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      arg5 = stack_pointer[5];
162212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
162312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    bool fp_call =
162412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
162512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
162612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
162712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
162812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
162912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (!IsMipsSoftFloatABI) {
163012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // With the hard floating point calling convention, double
163112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // arguments are passed in FPU registers. Fetch the arguments
163212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // from there and call the builtin using soft floating point
163312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // convention.
163412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      switch (redirection->type()) {
163512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      case ExternalReference::BUILTIN_FP_FP_CALL:
163612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      case ExternalReference::BUILTIN_COMPARE_CALL:
163712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        arg0 = get_fpu_register(f12);
163812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        arg1 = get_fpu_register(f13);
163912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        arg2 = get_fpu_register(f14);
164012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        arg3 = get_fpu_register(f15);
164112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        break;
164212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      case ExternalReference::BUILTIN_FP_CALL:
164312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        arg0 = get_fpu_register(f12);
164412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        arg1 = get_fpu_register(f13);
164512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        break;
164612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      case ExternalReference::BUILTIN_FP_INT_CALL:
164712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        arg0 = get_fpu_register(f12);
164812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        arg1 = get_fpu_register(f13);
164912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        arg2 = get_register(a2);
165012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        break;
165112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      default:
165212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        break;
165312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
165412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
165512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
165612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // This is dodgy but it works because the C entry stubs are never moved.
165712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // See comment in codegen-arm.cc and bug 1242173.
165812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int64_t saved_ra = get_register(ra);
165912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
166012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    intptr_t external =
166112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          reinterpret_cast<intptr_t>(redirection->external_function());
166212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
166312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware
166412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // FPU, or gcc soft-float routines. Hardware FPU is simulated in this
166512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // simulator. Soft-float has additional abstraction of ExternalReference,
166612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // to support serialization.
166712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (fp_call) {
166812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      double dval0, dval1;  // one or two double parameters
166912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      int32_t ival;         // zero or one integer parameters
167012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      int64_t iresult = 0;  // integer return value
167112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      double dresult = 0;   // double return value
167212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      GetFpArgs(&dval0, &dval1, &ival);
167312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      SimulatorRuntimeCall generic_target =
167412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          reinterpret_cast<SimulatorRuntimeCall>(external);
167512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (::v8::internal::FLAG_trace_sim) {
167612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        switch (redirection->type()) {
167712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          case ExternalReference::BUILTIN_FP_FP_CALL:
167812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          case ExternalReference::BUILTIN_COMPARE_CALL:
167912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            PrintF("Call to host function at %p with args %f, %f",
168012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                   FUNCTION_ADDR(generic_target), dval0, dval1);
168112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            break;
168212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          case ExternalReference::BUILTIN_FP_CALL:
168312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            PrintF("Call to host function at %p with arg %f",
168412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                FUNCTION_ADDR(generic_target), dval0);
168512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            break;
168612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          case ExternalReference::BUILTIN_FP_INT_CALL:
168712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            PrintF("Call to host function at %p with args %f, %d",
168812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                   FUNCTION_ADDR(generic_target), dval0, ival);
168912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            break;
169012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          default:
169112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            UNREACHABLE();
169212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            break;
169312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
169412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
169512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      switch (redirection->type()) {
169612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      case ExternalReference::BUILTIN_COMPARE_CALL: {
169712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        SimulatorRuntimeCompareCall target =
169812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          reinterpret_cast<SimulatorRuntimeCompareCall>(external);
169912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        iresult = target(dval0, dval1);
170012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        set_register(v0, static_cast<int64_t>(iresult));
170112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      //  set_register(v1, static_cast<int64_t>(iresult >> 32));
170212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        break;
170312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
170412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      case ExternalReference::BUILTIN_FP_FP_CALL: {
170512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        SimulatorRuntimeFPFPCall target =
170612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
170712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        dresult = target(dval0, dval1);
170812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        SetFpResult(dresult);
170912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        break;
171012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
171112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      case ExternalReference::BUILTIN_FP_CALL: {
171212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        SimulatorRuntimeFPCall target =
171312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          reinterpret_cast<SimulatorRuntimeFPCall>(external);
171412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        dresult = target(dval0);
171512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        SetFpResult(dresult);
171612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        break;
171712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
171812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      case ExternalReference::BUILTIN_FP_INT_CALL: {
171912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        SimulatorRuntimeFPIntCall target =
172012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
172112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        dresult = target(dval0, ival);
172212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        SetFpResult(dresult);
172312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        break;
172412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
172512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      default:
172612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        UNREACHABLE();
172712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        break;
172812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
172912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (::v8::internal::FLAG_trace_sim) {
173012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        switch (redirection->type()) {
173112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case ExternalReference::BUILTIN_COMPARE_CALL:
173212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
173312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
173412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case ExternalReference::BUILTIN_FP_FP_CALL:
173512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case ExternalReference::BUILTIN_FP_CALL:
173612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case ExternalReference::BUILTIN_FP_INT_CALL:
173712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          PrintF("Returned %f\n", dresult);
173812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
173912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        default:
174012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          UNREACHABLE();
174112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
174212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
174312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
174412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
174512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (::v8::internal::FLAG_trace_sim) {
174612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("Call to host function at %p args %08lx\n",
174712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            reinterpret_cast<void*>(external), arg0);
174812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
174912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      SimulatorRuntimeDirectApiCall target =
175012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
175112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      target(arg0);
175212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else if (
175312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        redirection->type() == ExternalReference::PROFILING_API_CALL) {
175412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (::v8::internal::FLAG_trace_sim) {
175512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("Call to host function at %p args %08lx %08lx\n",
175612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            reinterpret_cast<void*>(external), arg0, arg1);
175712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
175812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      SimulatorRuntimeProfilingApiCall target =
175912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
176012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      target(arg0, Redirection::ReverseRedirection(arg1));
176112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else if (
176212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
176312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (::v8::internal::FLAG_trace_sim) {
176412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("Call to host function at %p args %08lx %08lx\n",
176512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            reinterpret_cast<void*>(external), arg0, arg1);
176612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
176712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      SimulatorRuntimeDirectGetterCall target =
176812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
176912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      target(arg0, arg1);
177012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else if (
177112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
177212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (::v8::internal::FLAG_trace_sim) {
177312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF("Call to host function at %p args %08lx %08lx %08lx\n",
177412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            reinterpret_cast<void*>(external), arg0, arg1, arg2);
177512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
177612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      SimulatorRuntimeProfilingGetterCall target =
177712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
177812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      target(arg0, arg1, Redirection::ReverseRedirection(arg2));
177912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else {
178012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      SimulatorRuntimeCall target =
178112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                  reinterpret_cast<SimulatorRuntimeCall>(external);
178212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (::v8::internal::FLAG_trace_sim) {
178312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        PrintF(
178412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            "Call to host function at %p "
178512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            "args %08lx, %08lx, %08lx, %08lx, %08lx, %08lx\n",
178612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            FUNCTION_ADDR(target),
178712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            arg0,
178812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            arg1,
178912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            arg2,
179012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            arg3,
179112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            arg4,
179212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            arg5);
179312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
179412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
179512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // set_register(v0, static_cast<int32_t>(result));
179612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // set_register(v1, static_cast<int32_t>(result >> 32));
179712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      ObjectPair result = target(arg0, arg1, arg2, arg3, arg4, arg5);
179812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      set_register(v0, (int64_t)(result.x));
179912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      set_register(v1, (int64_t)(result.y));
180012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
180112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org     if (::v8::internal::FLAG_trace_sim) {
180212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      PrintF("Returned %08lx : %08lx\n", get_register(v1), get_register(v0));
180312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
180412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_register(ra, saved_ra);
180512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_pc(get_register(ra));
180612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
180712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else if (func == BREAK && code <= kMaxStopCode) {
180812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (IsWatchpoint(code)) {
180912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      PrintWatchpoint(code);
181012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else {
181112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      IncreaseStopCounter(code);
181212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      HandleStop(code, instr);
181312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
181412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
181512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // All remaining break_ codes, and all traps are handled here.
181612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    MipsDebugger dbg(this);
181712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    dbg.Debug();
181812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
181912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
182012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
182112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
182212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Stop helper functions.
182312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool Simulator::IsWatchpoint(uint64_t code) {
182412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return (code <= kMaxWatchpointCode);
182512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
182612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
182712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
182812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::PrintWatchpoint(uint64_t code) {
182912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  MipsDebugger dbg(this);
183012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  ++break_count_;
183112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  PrintF("\n---- break %ld marker: %3d  (instr count: %8ld) ----------"
183212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         "----------------------------------",
183312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org         code, break_count_, icount_);
183412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  dbg.PrintAllRegs();  // Print registers and continue running.
183512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
183612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
183712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
183812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::HandleStop(uint64_t code, Instruction* instr) {
183912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Stop if it is enabled, otherwise go on jumping over the stop
184012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // and the message address.
184112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (IsEnabledStop(code)) {
184212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    MipsDebugger dbg(this);
184312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    dbg.Stop(instr);
184412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
184512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_pc(get_pc() + 2 * Instruction::kInstrSize);
184612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
184712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
184812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
184912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
185012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool Simulator::IsStopInstruction(Instruction* instr) {
185112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int32_t func = instr->FunctionFieldRaw();
185212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uint32_t code = static_cast<uint32_t>(instr->Bits(25, 6));
185312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode;
185412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
185512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
185612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
185712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgbool Simulator::IsEnabledStop(uint64_t code) {
1858e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(code <= kMaxStopCode);
1859e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(code > kMaxWatchpointCode);
186012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return !(watched_stops_[code].count & kStopDisabledBit);
186112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
186212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
186312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
186412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::EnableStop(uint64_t code) {
186512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (!IsEnabledStop(code)) {
186612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    watched_stops_[code].count &= ~kStopDisabledBit;
186712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
186812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
186912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
187012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
187112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::DisableStop(uint64_t code) {
187212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (IsEnabledStop(code)) {
187312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    watched_stops_[code].count |= kStopDisabledBit;
187412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
187512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
187612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
187712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
187812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::IncreaseStopCounter(uint64_t code) {
1879e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(code <= kMaxStopCode);
188012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
188112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    PrintF("Stop counter for code %ld has overflowed.\n"
188212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org           "Enabling this code and reseting the counter to 0.\n", code);
188312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    watched_stops_[code].count = 0;
188412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    EnableStop(code);
188512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
188612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    watched_stops_[code].count++;
188712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
188812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
188912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
189012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
189112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Print a stop status.
189212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::PrintStopInfo(uint64_t code) {
189312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (code <= kMaxWatchpointCode) {
189412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    PrintF("That is a watchpoint, not a stop.\n");
189512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return;
189612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else if (code > kMaxStopCode) {
189712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    PrintF("Code too large, only %u stops can be used\n", kMaxStopCode + 1);
189812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return;
189912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
190012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const char* state = IsEnabledStop(code) ? "Enabled" : "Disabled";
190112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
190212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Don't print the state of unused breakpoints.
190312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (count != 0) {
190412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (watched_stops_[code].desc) {
190512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      PrintF("stop %ld - 0x%lx: \t%s, \tcounter = %i, \t%s\n",
190612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org             code, code, state, count, watched_stops_[code].desc);
190712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else {
190812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      PrintF("stop %ld - 0x%lx: \t%s, \tcounter = %i\n",
190912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org             code, code, state, count);
191012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
191112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
191212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
191312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
191412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
191512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::SignalExceptions() {
191612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  for (int i = 1; i < kNumExceptions; i++) {
191712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (exceptions[i] != 0) {
191812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i);
191912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
192012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
192112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
192212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
192312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
192412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Handle execution based on instruction types.
192512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
192612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::ConfigureTypeRegister(Instruction* instr,
192712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                      int64_t* alu_out,
192812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                      int64_t* i64hilo,
192912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                      uint64_t* u64hilo,
193012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                      int64_t* next_pc,
193112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                      int64_t* return_addr_reg,
193212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                      bool* do_interrupt,
193312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                      int64_t* i128resultH,
193412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                                      int64_t* i128resultL) {
193512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Every local variable declared here needs to be const.
193612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // This is to make sure that changed values are sent back to
193712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // DecodeTypeRegister correctly.
193812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
193912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Instruction fields.
194012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const Opcode   op     = instr->OpcodeFieldRaw();
194112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int64_t  rs_reg = instr->RsValue();
194212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int64_t  rs     = get_register(rs_reg);
194312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const uint64_t rs_u   = static_cast<uint64_t>(rs);
194412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int64_t  rt_reg = instr->RtValue();
194512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int64_t  rt     = get_register(rt_reg);
194612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const uint64_t rt_u   = static_cast<uint64_t>(rt);
194712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int64_t  rd_reg = instr->RdValue();
194812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const uint64_t sa     = instr->SaValue();
194912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
195012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int32_t  fs_reg = instr->FsValue();
195112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
195212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
195312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // ---------- Configuration.
195412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  switch (op) {
195512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case COP1:    // Coprocessor instructions.
195612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      switch (instr->RsFieldRaw()) {
195712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case CFC1:
195812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // At the moment only FCSR is supported.
1959e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org          DCHECK(fs_reg == kFCSRRegister);
196012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = FCSR_;
196112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
196212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MFC1:
196312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = static_cast<int64_t>(get_fpu_register_word(fs_reg));
196412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
196512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DMFC1:
196612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = get_fpu_register(fs_reg);
196712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
196812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MFHC1:
196912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = get_fpu_register_hi_word(fs_reg);
197012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
197112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case CTC1:
197212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MTC1:
197312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DMTC1:
197412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MTHC1:
197512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case S:
197612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case D:
197712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case W:
197812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case L:
197912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case PS:
198012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Do everything in the execution step.
198112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
198212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        default:
1983dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org        // BC1 BC1EQZ BC1NEZ handled in DecodeTypeImmed, should never come here.
1984dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org           UNREACHABLE();
198512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
198612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
198712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case COP1X:
198812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
198912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SPECIAL:
199012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      switch (instr->FunctionFieldRaw()) {
199112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case JR:
199212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case JALR:
199312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *next_pc = get_register(instr->RsValue());
199412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *return_addr_reg = instr->RdValue();
199512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
199612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case SLL:
199712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = (int32_t)rt << sa;
199812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
199912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DSLL:
200012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rt << sa;
200112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
200212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DSLL32:
200312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rt << sa << 32;
200412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
200512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case SRL:
200612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (rs_reg == 0) {
200712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // Regular logical right shift of a word by a fixed number of
200812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // bits instruction. RS field is always equal to 0.
200912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            *alu_out = (uint32_t)rt_u >> sa;
201012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          } else {
201112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // Logical right-rotate of a word by a fixed number of bits. This
201212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // is special case of SRL instruction, added in MIPS32 Release 2.
201312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // RS field is equal to 00001.
201412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            *alu_out = ((uint32_t)rt_u >> sa) | ((uint32_t)rt_u << (32 - sa));
201512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
201612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
201712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DSRL:
201812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rt_u >> sa;
201912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
202012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DSRL32:
202112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rt_u >> sa >> 32;
202212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
202312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case SRA:
202412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = (int32_t)rt >> sa;
202512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
202612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DSRA:
202712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rt >> sa;
202812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
202912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DSRA32:
203012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rt >> sa >> 32;
203112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
203212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case SLLV:
203312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = (int32_t)rt << rs;
203412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
203512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DSLLV:
203612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rt << rs;
203712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
203812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case SRLV:
203912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (sa == 0) {
204012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // Regular logical right-shift of a word by a variable number of
204112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // bits instruction. SA field is always equal to 0.
204212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            *alu_out = (uint32_t)rt_u >> rs;
204312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          } else {
204412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // Logical right-rotate of a word by a variable number of bits.
204512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // This is special case od SRLV instruction, added in MIPS32
204612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // Release 2. SA field is equal to 00001.
204712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            *alu_out =
204812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                ((uint32_t)rt_u >> rs_u) | ((uint32_t)rt_u << (32 - rs_u));
204912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
205012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
205112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DSRLV:
205212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (sa == 0) {
205312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // Regular logical right-shift of a word by a variable number of
205412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // bits instruction. SA field is always equal to 0.
205512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            *alu_out = rt_u >> rs;
205612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          } else {
205712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // Logical right-rotate of a word by a variable number of bits.
205812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // This is special case od SRLV instruction, added in MIPS32
205912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // Release 2. SA field is equal to 00001.
206012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            *alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u));
206112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
206212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
206312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case SRAV:
206412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = (int32_t)rt >> rs;
206512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
206612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DSRAV:
206712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rt >> rs;
206812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
2069dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org        case MFHI:  // MFHI == CLZ on R6.
2070dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          if (kArchVariant != kMips64r6) {
2071e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org            DCHECK(instr->SaValue() == 0);
2072dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            *alu_out = get_register(HI);
2073dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          } else {
2074dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            // MIPS spec: If no bits were set in GPR rs, the result written to
2075dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            // GPR rd is 32.
2076e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org            DCHECK(instr->SaValue() == 1);
2077e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org            *alu_out = base::bits::CountLeadingZeros32(rs_u);
2078dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          }
207912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
208012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MFLO:
208112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = get_register(LO);
208212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
2083dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org        case MULT:  // MULT == D_MUL_MUH.
208412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // TODO(plind) - Unify MULT/DMULT with single set of 64-bit HI/Lo
208512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // regs.
208612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // TODO(plind) - make the 32-bit MULT ops conform to spec regarding
208712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          //   checking of 32-bit input values, and un-define operations of HW.
208812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *i64hilo = static_cast<int64_t>((int32_t)rs) *
208912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              static_cast<int64_t>((int32_t)rt);
209012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
209112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MULTU:
209212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u);
209312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
2094dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org        case DMULT:  // DMULT == D_MUL_MUH.
2095dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          if (kArchVariant != kMips64r6) {
2096dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            *i128resultH = MultiplyHighSigned(rs, rt);
2097dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            *i128resultL = rs * rt;
2098dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          } else {
2099dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            switch (instr->SaValue()) {
2100dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              case MUL_OP:
2101dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                *i128resultL = rs * rt;
2102dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                break;
2103dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              case MUH_OP:
2104dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                *i128resultH = MultiplyHighSigned(rs, rt);
2105dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                break;
2106dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              default:
2107dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                UNIMPLEMENTED_MIPS();
2108dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                break;
2109dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            }
2110dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          }
211112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
211212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DMULTU:
211312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          UNIMPLEMENTED_MIPS();
211412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
211512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case ADD:
211612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DADD:
211712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (HaveSameSign(rs, rt)) {
211812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            if (rs > 0) {
211912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt);
212012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            } else if (rs < 0) {
212112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt);
212212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
212312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
212412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rs + rt;
212512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
212612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case ADDU: {
212712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            int32_t alu32_out = rs + rt;
212812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // Sign-extend result of 32bit operation into 64bit register.
212912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            *alu_out = static_cast<int64_t>(alu32_out);
213012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
213112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
213212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DADDU:
213312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rs + rt;
213412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
213512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case SUB:
213612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DSUB:
213712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (!HaveSameSign(rs, rt)) {
213812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            if (rs > 0) {
213912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt);
214012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            } else if (rs < 0) {
214112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt);
214212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
214312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
214412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rs - rt;
214512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
214612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case SUBU: {
214712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            int32_t alu32_out = rs - rt;
214812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            // Sign-extend result of 32bit operation into 64bit register.
214912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            *alu_out = static_cast<int64_t>(alu32_out);
215012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
215112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
215212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DSUBU:
215312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rs - rt;
215412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
215512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case AND:
215612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rs & rt;
215712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
215812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case OR:
215912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rs | rt;
216012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
216112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case XOR:
216212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rs ^ rt;
216312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
216412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case NOR:
216512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = ~(rs | rt);
216612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
216712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case SLT:
216812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rs < rt ? 1 : 0;
216912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
217012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case SLTU:
217112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = rs_u < rt_u ? 1 : 0;
217212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
217312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        // Break and trap instructions.
217412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case BREAK:
217512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
217612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *do_interrupt = true;
217712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
217812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case TGE:
217912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *do_interrupt = rs >= rt;
218012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
218112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case TGEU:
218212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *do_interrupt = rs_u >= rt_u;
218312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
218412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case TLT:
218512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *do_interrupt = rs < rt;
218612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
218712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case TLTU:
218812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *do_interrupt = rs_u < rt_u;
218912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
219012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case TEQ:
219112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *do_interrupt = rs == rt;
219212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
219312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case TNE:
219412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *do_interrupt = rs != rt;
219512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
219612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MOVN:
219712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MOVZ:
219812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MOVCI:
219912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // No action taken on decode.
220012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
220112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DIV:
220212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DIVU:
220312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DDIV:
220412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DDIVU:
220512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // div and divu never raise exceptions.
220612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
220712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        default:
220812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          UNREACHABLE();
220912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
221012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
221112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SPECIAL2:
221212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      switch (instr->FunctionFieldRaw()) {
221312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MUL:
221412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Only the lower 32 bits are kept.
221512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = (int32_t)rs_u * (int32_t)rt_u;
221612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
221712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case CLZ:
221812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // MIPS32 spec: If no bits were set in GPR rs, the result written to
221912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // GPR rd is 32.
2220e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org          *alu_out = base::bits::CountLeadingZeros32(rs_u);
222112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
222212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        default:
222312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          UNREACHABLE();
222412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
222512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
222612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SPECIAL3:
222712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      switch (instr->FunctionFieldRaw()) {
222812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case INS: {   // Mips32r2 instruction.
222912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Interpret rd field as 5-bit msb of insert.
223012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          uint16_t msb = rd_reg;
223112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Interpret sa field as 5-bit lsb of insert.
223212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          uint16_t lsb = sa;
223312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          uint16_t size = msb - lsb + 1;
223412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          uint32_t mask = (1 << size) - 1;
223512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
223612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
223712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
223812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case EXT: {   // Mips32r2 instruction.
223912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Interpret rd field as 5-bit msb of extract.
224012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          uint16_t msb = rd_reg;
224112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Interpret sa field as 5-bit lsb of extract.
224212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          uint16_t lsb = sa;
224312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          uint16_t size = msb + 1;
224412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          uint32_t mask = (1 << size) - 1;
224512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          *alu_out = (rs_u & (mask << lsb)) >> lsb;
224612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
224712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
224812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        default:
224912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          UNREACHABLE();
225012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
225112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
225212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    default:
225312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      UNREACHABLE();
225412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
225512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
225612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
225712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
225812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::DecodeTypeRegister(Instruction* instr) {
225912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Instruction fields.
226012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const Opcode   op     = instr->OpcodeFieldRaw();
226112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int64_t  rs_reg = instr->RsValue();
226212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int64_t  rs     = get_register(rs_reg);
226312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const uint64_t rs_u   = static_cast<uint32_t>(rs);
226412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int64_t  rt_reg = instr->RtValue();
226512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int64_t  rt     = get_register(rt_reg);
226612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const uint64_t rt_u   = static_cast<uint32_t>(rt);
226712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int64_t  rd_reg = instr->RdValue();
226812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
226912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int32_t  fr_reg = instr->FrValue();
227012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int32_t  fs_reg = instr->FsValue();
227112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int32_t  ft_reg = instr->FtValue();
227212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int64_t  fd_reg = instr->FdValue();
227312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t  i64hilo = 0;
227412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uint64_t u64hilo = 0;
227512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
227612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // ALU output.
227712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // It should not be used as is. Instructions using it should always
227812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // initialize it first.
227912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t alu_out = 0x12345678;
228012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
228112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // For break and trap instructions.
228212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  bool do_interrupt = false;
228312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
228412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // For jr and jalr.
228512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Get current pc.
228612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t current_pc = get_pc();
228712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Next pc
228812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t next_pc = 0;
228912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t return_addr_reg = 31;
229012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
229112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t i128resultH;
229212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t i128resultL;
229312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
229412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Set up the variables if needed before executing the instruction.
229512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  ConfigureTypeRegister(instr,
229612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                        &alu_out,
229712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                        &i64hilo,
229812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                        &u64hilo,
229912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                        &next_pc,
230012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                        &return_addr_reg,
230112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                        &do_interrupt,
230212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                        &i128resultH,
230312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                        &i128resultL);
230412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
230512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // ---------- Raise exceptions triggered.
230612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  SignalExceptions();
230712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
230812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // ---------- Execution.
230912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  switch (op) {
231012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case COP1:
231112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      switch (instr->RsFieldRaw()) {
231212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case BC1:   // Branch on coprocessor condition.
2313dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org        case BC1EQZ:
2314dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org        case BC1NEZ:
231512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          UNREACHABLE();
231612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
231712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case CFC1:
231812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_register(rt_reg, alu_out);
231912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
232012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MFC1:
232112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DMFC1:
232212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MFHC1:
232312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_register(rt_reg, alu_out);
232412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
232512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case CTC1:
232612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // At the moment only FCSR is supported.
2327e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org          DCHECK(fs_reg == kFCSRRegister);
232812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          FCSR_ = registers_[rt_reg];
232912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
233012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MTC1:
233112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Hardware writes upper 32-bits to zero on mtc1.
233212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_fpu_register_hi_word(fs_reg, 0);
233312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_fpu_register_word(fs_reg, registers_[rt_reg]);
233412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
233512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DMTC1:
233612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_fpu_register(fs_reg, registers_[rt_reg]);
233712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
233812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MTHC1:
233912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_fpu_register_hi_word(fs_reg, registers_[rt_reg]);
234012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
234112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case S:
234212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          float f;
234312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          switch (instr->FunctionFieldRaw()) {
234412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case CVT_D_S:
234512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              f = get_fpu_register_float(fs_reg);
234612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register_double(fd_reg, static_cast<double>(f));
234712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
234812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            default:
2349dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
2350dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
235112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              UNREACHABLE();
235212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
235312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
235412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case D:
235512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          double ft, fs;
235612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          uint32_t cc, fcsr_cc;
235712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          int64_t  i64;
235812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          fs = get_fpu_register_double(fs_reg);
235912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          ft = get_fpu_register_double(ft_reg);
236012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          cc = instr->FCccValue();
236112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          fcsr_cc = get_fcsr_condition_bit(cc);
236212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          switch (instr->FunctionFieldRaw()) {
236312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case ADD_D:
236412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register_double(fd_reg, fs + ft);
236512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
236612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case SUB_D:
236712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register_double(fd_reg, fs - ft);
236812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
236912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case MUL_D:
237012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register_double(fd_reg, fs * ft);
237112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
237212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case DIV_D:
237312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register_double(fd_reg, fs / ft);
237412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
237512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case ABS_D:
237612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register_double(fd_reg, fabs(fs));
237712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
237812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case MOV_D:
237912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register_double(fd_reg, fs);
238012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
238112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case NEG_D:
238212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register_double(fd_reg, -fs);
238312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
238412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case SQRT_D:
238512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register_double(fd_reg, sqrt(fs));
238612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
238712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case C_UN_D:
238812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
238912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
239012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case C_EQ_D:
239112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fcsr_bit(fcsr_cc, (fs == ft));
239212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
239312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case C_UEQ_D:
239412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fcsr_bit(fcsr_cc,
239512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                           (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
239612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
239712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case C_OLT_D:
239812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fcsr_bit(fcsr_cc, (fs < ft));
239912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
240012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case C_ULT_D:
240112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fcsr_bit(fcsr_cc,
240212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                           (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
240312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
240412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case C_OLE_D:
240512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fcsr_bit(fcsr_cc, (fs <= ft));
240612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
240712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case C_ULE_D:
240812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fcsr_bit(fcsr_cc,
240912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                           (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
241012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
241112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case CVT_W_D:   // Convert double to word.
241212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              // Rounding modes are not yet supported.
2413e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org              DCHECK((FCSR_ & 3) == 0);
241412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              // In rounding mode 0 it should behave like ROUND.
241512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              // No break.
241612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case ROUND_W_D:  // Round double to word (round half to even).
241712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              {
241812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                double rounded = std::floor(fs + 0.5);
241912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                int32_t result = static_cast<int32_t>(rounded);
242012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                if ((result & 1) != 0 && result - fs == 0.5) {
242112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                  // If the number is halfway between two integers,
242212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                  // round to the even one.
242312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                  result--;
242412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                }
242512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                set_fpu_register_word(fd_reg, result);
242612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                if (set_fcsr_round_error(fs, rounded)) {
242712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                  set_fpu_register(fd_reg, kFPUInvalidResult);
242812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                }
242912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              }
243012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
243112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case TRUNC_W_D:  // Truncate double to word (round towards 0).
243212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              {
243312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                double rounded = trunc(fs);
243412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                int32_t result = static_cast<int32_t>(rounded);
243512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                set_fpu_register_word(fd_reg, result);
243612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                if (set_fcsr_round_error(fs, rounded)) {
243712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                  set_fpu_register(fd_reg, kFPUInvalidResult);
243812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                }
243912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              }
244012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
244112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case FLOOR_W_D:  // Round double to word towards negative infinity.
244212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              {
244312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                double rounded = std::floor(fs);
244412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                int32_t result = static_cast<int32_t>(rounded);
244512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                set_fpu_register_word(fd_reg, result);
244612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                if (set_fcsr_round_error(fs, rounded)) {
244712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                  set_fpu_register(fd_reg, kFPUInvalidResult);
244812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                }
244912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              }
245012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
245112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case CEIL_W_D:  // Round double to word towards positive infinity.
245212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              {
245312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                double rounded = std::ceil(fs);
245412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                int32_t result = static_cast<int32_t>(rounded);
245512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                set_fpu_register_word(fd_reg, result);
245612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                if (set_fcsr_round_error(fs, rounded)) {
245712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                  set_fpu_register(fd_reg, kFPUInvalidResult);
245812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                }
245912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              }
246012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
246112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case CVT_S_D:  // Convert double to float (single).
246212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register_float(fd_reg, static_cast<float>(fs));
246312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
246412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case CVT_L_D:   // Mips64r2: Truncate double to 64-bit long-word.
246512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              // Rounding modes are not yet supported.
2466e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org              DCHECK((FCSR_ & 3) == 0);
246712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              // In rounding mode 0 it should behave like ROUND.
246812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              // No break.
246912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case ROUND_L_D: {  // Mips64r2 instruction.
247012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              // check error cases
247112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
247212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              int64_t result = static_cast<int64_t>(rounded);
247312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register(fd_reg, result);
247412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              if (set_fcsr_round64_error(fs, rounded)) {
247512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                set_fpu_register(fd_reg, kFPU64InvalidResult);
247612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              }
247712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
247812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
247912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case TRUNC_L_D: {  // Mips64r2 instruction.
248012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              double rounded = trunc(fs);
248112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              int64_t result = static_cast<int64_t>(rounded);
248212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register(fd_reg, result);
248312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              if (set_fcsr_round64_error(fs, rounded)) {
248412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                set_fpu_register(fd_reg, kFPU64InvalidResult);
248512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              }
248612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
248712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
248812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case FLOOR_L_D: {  // Mips64r2 instruction.
248912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              double rounded = floor(fs);
249012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              int64_t result = static_cast<int64_t>(rounded);
249112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register(fd_reg, result);
249212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              if (set_fcsr_round64_error(fs, rounded)) {
249312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                set_fpu_register(fd_reg, kFPU64InvalidResult);
249412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              }
249512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
249612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
249712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case CEIL_L_D: {  // Mips64r2 instruction.
249812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              double rounded = ceil(fs);
249912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              int64_t result = static_cast<int64_t>(rounded);
250012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register(fd_reg, result);
250112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              if (set_fcsr_round64_error(fs, rounded)) {
250212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                set_fpu_register(fd_reg, kFPU64InvalidResult);
250312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              }
250412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
250512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
250612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case C_F_D:
250712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              UNIMPLEMENTED_MIPS();
250812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
250912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            default:
251012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              UNREACHABLE();
251112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
251212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
251312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case W:
251412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          switch (instr->FunctionFieldRaw()) {
251512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case CVT_S_W:   // Convert word to float (single).
251612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              alu_out = get_fpu_register_signed_word(fs_reg);
251712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
251812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
251912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case CVT_D_W:   // Convert word to double.
252012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              alu_out = get_fpu_register_signed_word(fs_reg);
252112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
252212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
2523dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            default:  // Mips64r6 CMP.S instructions unimplemented.
252412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              UNREACHABLE();
252512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
252612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
252712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case L:
2528dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          fs = get_fpu_register_double(fs_reg);
2529dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          ft = get_fpu_register_double(ft_reg);
253012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          switch (instr->FunctionFieldRaw()) {
2531dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            case CVT_D_L:  // Mips32r2 instruction.
2532dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              i64 = get_fpu_register(fs_reg);
2533dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              set_fpu_register_double(fd_reg, static_cast<double>(i64));
2534dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              break;
253512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            case CVT_S_L:
253612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              UNIMPLEMENTED_MIPS();
253712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              break;
2538dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            case CMP_AF:  // Mips64r6 CMP.D instructions.
2539dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              UNIMPLEMENTED_MIPS();
2540dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              break;
2541dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            case CMP_UN:
2542dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              if (std::isnan(fs) || std::isnan(ft)) {
2543dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_fpu_register(fd_reg, -1);
2544dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              } else {
2545dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_fpu_register(fd_reg, 0);
2546dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              }
2547dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              break;
2548dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            case CMP_EQ:
2549dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              if (fs == ft) {
2550dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_fpu_register(fd_reg, -1);
2551dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              } else {
2552dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_fpu_register(fd_reg, 0);
2553dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              }
2554dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              break;
2555dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            case CMP_UEQ:
2556dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
2557dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_fpu_register(fd_reg, -1);
2558dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              } else {
2559dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_fpu_register(fd_reg, 0);
2560dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              }
2561dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              break;
2562dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            case CMP_LT:
2563dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              if (fs < ft) {
2564dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_fpu_register(fd_reg, -1);
2565dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              } else {
2566dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_fpu_register(fd_reg, 0);
2567dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              }
2568dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              break;
2569dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            case CMP_ULT:
2570dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
2571dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_fpu_register(fd_reg, -1);
2572dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              } else {
2573dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_fpu_register(fd_reg, 0);
2574dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              }
2575dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              break;
2576dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            case CMP_LE:
2577dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              if (fs <= ft) {
2578dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_fpu_register(fd_reg, -1);
2579dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              } else {
2580dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_fpu_register(fd_reg, 0);
2581dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              }
2582dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              break;
2583dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            case CMP_ULE:
2584dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
2585dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_fpu_register(fd_reg, -1);
2586dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              } else {
2587dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_fpu_register(fd_reg, 0);
2588dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              }
2589dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              break;
2590dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            default:  // CMP_OR CMP_UNE CMP_NE UNIMPLEMENTED
259112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              UNREACHABLE();
259212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
259312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
259412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        default:
259512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          UNREACHABLE();
259612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
259712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
259812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case COP1X:
259912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      switch (instr->FunctionFieldRaw()) {
260012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MADD_D:
260112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          double fr, ft, fs;
260212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          fr = get_fpu_register_double(fr_reg);
260312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          fs = get_fpu_register_double(fs_reg);
260412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          ft = get_fpu_register_double(ft_reg);
260512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_fpu_register_double(fd_reg, fs * ft + fr);
260612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
260712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        default:
260812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          UNREACHABLE();
260912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
261012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
261112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SPECIAL:
261212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      switch (instr->FunctionFieldRaw()) {
261312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case JR: {
261412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
261512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              current_pc+Instruction::kInstrSize);
261612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          BranchDelayInstructionDecode(branch_delay_instr);
261712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_pc(next_pc);
261812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          pc_modified_ = true;
261912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
262012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
262112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case JALR: {
262212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
262312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              current_pc+Instruction::kInstrSize);
262412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          BranchDelayInstructionDecode(branch_delay_instr);
262512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_register(return_addr_reg,
262612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                       current_pc + 2 * Instruction::kInstrSize);
262712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_pc(next_pc);
262812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          pc_modified_ = true;
262912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
263012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
263112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        // Instructions using HI and LO registers.
263212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MULT:
2633dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          if (kArchVariant != kMips64r6) {
2634dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
2635dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            set_register(HI, static_cast<int32_t>(i64hilo >> 32));
2636dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          } else {
2637dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            switch (instr->SaValue()) {
2638dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              case MUL_OP:
2639dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_register(rd_reg,
2640dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                    static_cast<int32_t>(i64hilo & 0xffffffff));
2641dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                break;
2642dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              case MUH_OP:
2643dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_register(rd_reg, static_cast<int32_t>(i64hilo >> 32));
2644dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                break;
2645dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              default:
2646dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                UNIMPLEMENTED_MIPS();
2647dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                break;
2648dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            }
2649dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          }
265012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
265112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MULTU:
265212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
265312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_register(HI, static_cast<int32_t>(u64hilo >> 32));
265412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
2655dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org        case DMULT:  // DMULT == D_MUL_MUH.
2656dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          if (kArchVariant != kMips64r6) {
2657dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            set_register(LO, static_cast<int64_t>(i128resultL));
2658dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            set_register(HI, static_cast<int64_t>(i128resultH));
2659dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          } else {
2660dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            switch (instr->SaValue()) {
2661dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              case MUL_OP:
2662dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_register(rd_reg, static_cast<int64_t>(i128resultL));
2663dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                break;
2664dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              case MUH_OP:
2665dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_register(rd_reg, static_cast<int64_t>(i128resultH));
2666dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                break;
2667dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              default:
2668dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                UNIMPLEMENTED_MIPS();
2669dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                break;
2670dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            }
2671dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          }
267212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
267312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DMULTU:
267412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          UNIMPLEMENTED_MIPS();
267512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
2676dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org        case DSLL:
2677dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          set_register(rd_reg, alu_out);
2678dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          break;
267912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DIV:
268012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DDIV:
2681dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          switch (kArchVariant) {
2682dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            case kMips64r2:
2683dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              // Divide by zero and overflow was not checked in the
2684dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              // configuration step - div and divu do not raise exceptions. On
2685dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              // division by 0 the result will be UNPREDICTABLE. On overflow
2686dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              // (INT_MIN/-1), return INT_MIN which is what the hardware does.
2687dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              if (rs == INT_MIN && rt == -1) {
2688dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_register(LO, INT_MIN);
2689dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_register(HI, 0);
2690dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              } else if (rt != 0) {
2691dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_register(LO, rs / rt);
2692dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                set_register(HI, rs % rt);
2693dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              }
2694dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              break;
2695dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            case kMips64r6:
2696dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              switch (instr->SaValue()) {
2697dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                case DIV_OP:
2698dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                  if (rs == INT_MIN && rt == -1) {
2699dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                    set_register(rd_reg, INT_MIN);
2700dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                  } else if (rt != 0) {
2701dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                    set_register(rd_reg, rs / rt);
2702dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                  }
2703dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                  break;
2704dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                case MOD_OP:
2705dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                  if (rs == INT_MIN && rt == -1) {
2706dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                    set_register(rd_reg, 0);
2707dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                  } else if (rt != 0) {
2708dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                    set_register(rd_reg, rs % rt);
2709dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                  }
2710dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                  break;
2711dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                default:
2712dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                  UNIMPLEMENTED_MIPS();
2713dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org                  break;
2714dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              }
2715dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              break;
2716dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            default:
2717dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org              break;
271812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
271912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
272012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case DIVU:
272112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (rt_u != 0) {
272212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            set_register(LO, rs_u / rt_u);
272312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            set_register(HI, rs_u % rt_u);
272412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
272512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
272612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        // Break and trap instructions.
272712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case BREAK:
272812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case TGE:
272912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case TGEU:
273012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case TLT:
273112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case TLTU:
273212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case TEQ:
273312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case TNE:
273412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (do_interrupt) {
273512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            SoftwareInterrupt(instr);
273612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
273712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
273812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        // Conditional moves.
273912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MOVN:
274012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (rt) {
274112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            set_register(rd_reg, rs);
274212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            TraceRegWr(rs);
274312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
274412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
274512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MOVCI: {
274612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          uint32_t cc = instr->FBccValue();
274712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
274812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (instr->Bit(16)) {  // Read Tf bit.
274912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
275012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          } else {
275112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
275212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
275312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
275412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
275512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MOVZ:
275612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (!rt) {
275712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            set_register(rd_reg, rs);
275812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            TraceRegWr(rs);
275912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
276012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
276112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        default:  // For other special opcodes we do the default operation.
276212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_register(rd_reg, alu_out);
276312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          TraceRegWr(alu_out);
276412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
276512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
276612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SPECIAL2:
276712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      switch (instr->FunctionFieldRaw()) {
276812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case MUL:
276912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_register(rd_reg, alu_out);
277012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          TraceRegWr(alu_out);
277112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // HI and LO are UNPREDICTABLE after the operation.
277212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_register(LO, Unpredictable);
277312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_register(HI, Unpredictable);
277412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
277512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        default:  // For other special2 opcodes we do the default operation.
277612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_register(rd_reg, alu_out);
277712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
277812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
277912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SPECIAL3:
278012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      switch (instr->FunctionFieldRaw()) {
278112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case INS:
278212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Ins instr leaves result in Rt, rather than Rd.
278312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_register(rt_reg, alu_out);
278412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          TraceRegWr(alu_out);
278512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
278612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case EXT:
278712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Ext instr leaves result in Rt, rather than Rd.
278812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_register(rt_reg, alu_out);
278912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          TraceRegWr(alu_out);
279012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
279112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        default:
279212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          UNREACHABLE();
279312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
279412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
279512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // Unimplemented opcodes raised an error in the configuration step before,
279612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // so we can use the default here to set the destination register in common
279712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // cases.
279812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    default:
279912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      set_register(rd_reg, alu_out);
280012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      TraceRegWr(alu_out);
280112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
280212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
280312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
280412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
280512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq).
280612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::DecodeTypeImmediate(Instruction* instr) {
280712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Instruction fields.
280812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Opcode   op     = instr->OpcodeFieldRaw();
280912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t  rs     = get_register(instr->RsValue());
281012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uint64_t rs_u   = static_cast<uint64_t>(rs);
281112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t  rt_reg = instr->RtValue();  // Destination register.
281212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t  rt     = get_register(rt_reg);
281312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int16_t  imm16  = instr->Imm16Value();
281412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
281512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int32_t  ft_reg = instr->FtValue();  // Destination register.
2816dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org  int64_t  ft     = get_fpu_register(ft_reg);
281712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
281812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Zero extended immediate.
281912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uint32_t  oe_imm16 = 0xffff & imm16;
282012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Sign extended immediate.
282112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int32_t   se_imm16 = imm16;
282212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
282312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Get current pc.
282412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t current_pc = get_pc();
282512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Next pc.
282612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t next_pc = bad_ra;
282712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
282812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Used for conditional branch instructions.
282912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  bool do_branch = false;
283012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  bool execute_branch_delay_instruction = false;
283112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
283212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Used for arithmetic instructions.
283312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t alu_out = 0;
283412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Floating point.
283512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  double fp_out = 0.0;
283612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uint32_t cc, cc_value, fcsr_cc;
283712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
283812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Used for memory instructions.
283912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t addr = 0x0;
284012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Value to be written in memory.
284112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uint64_t mem_value = 0x0;
284212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Alignment for 32-bit integers used in LWL, LWR, etc.
284312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int kInt32AlignmentMask = sizeof(uint32_t) - 1;
284412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
284512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // ---------- Configuration (and execution for REGIMM).
284612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  switch (op) {
284712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // ------------- COP1. Coprocessor instructions.
284812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case COP1:
284912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      switch (instr->RsFieldRaw()) {
285012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case BC1:   // Branch on coprocessor condition.
285112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          cc = instr->FBccValue();
285212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          fcsr_cc = get_fcsr_condition_bit(cc);
285312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          cc_value = test_fcsr_bit(fcsr_cc);
285412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
285512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          execute_branch_delay_instruction = true;
285612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Set next_pc.
285712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (do_branch) {
285812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
285912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          } else {
286012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            next_pc = current_pc + kBranchReturnOffset;
286112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
286212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
2863dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org        case BC1EQZ:
2864dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          do_branch = (ft & 0x1) ? false : true;
2865dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          execute_branch_delay_instruction = true;
2866dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          // Set next_pc.
2867dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          if (do_branch) {
2868dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2869dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          } else {
2870dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            next_pc = current_pc + kBranchReturnOffset;
2871dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          }
2872dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          break;
2873dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org        case BC1NEZ:
2874dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          do_branch = (ft & 0x1) ? true : false;
2875dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          execute_branch_delay_instruction = true;
2876dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          // Set next_pc.
2877dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          if (do_branch) {
2878dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2879dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          } else {
2880dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org            next_pc = current_pc + kBranchReturnOffset;
2881dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          }
2882dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org          break;
288312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        default:
288412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          UNREACHABLE();
288512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
288612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
288712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // ------------- REGIMM class.
288812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case REGIMM:
288912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      switch (instr->RtFieldRaw()) {
289012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case BLTZ:
289112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          do_branch = (rs  < 0);
289212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
289312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case BLTZAL:
289412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          do_branch = rs  < 0;
289512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
289612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case BGEZ:
289712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          do_branch = rs >= 0;
289812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
289912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case BGEZAL:
290012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          do_branch = rs >= 0;
290112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
290212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        default:
290312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          UNREACHABLE();
290412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
290512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      switch (instr->RtFieldRaw()) {
290612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case BLTZ:
290712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case BLTZAL:
290812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case BGEZ:
290912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        case BGEZAL:
291012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Branch instructions common part.
291112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          execute_branch_delay_instruction = true;
291212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          // Set next_pc.
291312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          if (do_branch) {
291412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
291512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            if (instr->IsLinkingInstruction()) {
291612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              set_register(31, current_pc + kBranchReturnOffset);
291712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            }
291812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          } else {
291912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org            next_pc = current_pc + kBranchReturnOffset;
292012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          }
292112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        default:
292212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          break;
292312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
292412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    break;  // case REGIMM.
292512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // ------------- Branch instructions.
292612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // When comparing to zero, the encoding of rt field is always 0, so we don't
292712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // need to replace rt with zero.
292812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case BEQ:
292912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      do_branch = (rs == rt);
293012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
293112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case BNE:
293212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      do_branch = rs != rt;
293312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
293412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case BLEZ:
293512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      do_branch = rs <= 0;
293612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
293712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case BGTZ:
293812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      do_branch = rs  > 0;
293912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
294012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // ------------- Arithmetic instructions.
294112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case ADDI:
294212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case DADDI:
294312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (HaveSameSign(rs, se_imm16)) {
294412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        if (rs > 0) {
294512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16);
294612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        } else if (rs < 0) {
294712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          exceptions[kIntegerUnderflow] =
294812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org              rs < (Registers::kMinValue - se_imm16);
294912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
295012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
295112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out = rs + se_imm16;
295212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
295312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case ADDIU: {
295412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        int32_t alu32_out = rs + se_imm16;
295512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        // Sign-extend result of 32bit operation into 64bit register.
295612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        alu_out = static_cast<int64_t>(alu32_out);
295712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
295812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
295912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case DADDIU:
296012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out = rs + se_imm16;
296112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
296212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SLTI:
296312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out = (rs < se_imm16) ? 1 : 0;
296412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
296512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SLTIU:
296612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
296712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
296812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case ANDI:
296912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        alu_out = rs & oe_imm16;
297012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
297112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case ORI:
297212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        alu_out = rs | oe_imm16;
297312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
297412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case XORI:
297512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        alu_out = rs ^ oe_imm16;
297612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
297712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LUI: {
297812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        int32_t alu32_out = (oe_imm16 << 16);
297912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        // Sign-extend result of 32bit operation into 64bit register.
298012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        alu_out = static_cast<int64_t>(alu32_out);
298112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
298212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
298312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // ------------- Memory instructions.
298412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LB:
298512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16;
298612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out = ReadB(addr);
298712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
298812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LH:
298912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16;
299012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out = ReadH(addr, instr);
299112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
299212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LWL: {
299312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // al_offset is offset of the effective address within an aligned word.
299412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
299512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      uint8_t byte_shift = kInt32AlignmentMask - al_offset;
299612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      uint32_t mask = (1 << byte_shift * 8) - 1;
299712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16 - al_offset;
299812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out = ReadW(addr, instr);
299912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out <<= byte_shift * 8;
300012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out |= rt & mask;
300112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
300212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
300312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LW:
300412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16;
300512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out = ReadW(addr, instr);
300612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
300712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LWU:
300812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16;
300912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out = ReadWU(addr, instr);
301012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
301112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LD:
301212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16;
301312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out = Read2W(addr, instr);
301412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
301512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LBU:
301612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16;
301712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out = ReadBU(addr);
301812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
301912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LHU:
302012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16;
302112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out = ReadHU(addr, instr);
302212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
302312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LWR: {
302412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // al_offset is offset of the effective address within an aligned word.
302512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
302612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      uint8_t byte_shift = kInt32AlignmentMask - al_offset;
302712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
302812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16 - al_offset;
302912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out = ReadW(addr, instr);
303012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
303112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out |= rt & mask;
303212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
303312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
303412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SB:
303512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16;
303612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
303712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SH:
303812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16;
303912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
304012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SWL: {
304112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
304212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      uint8_t byte_shift = kInt32AlignmentMask - al_offset;
304312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
304412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16 - al_offset;
304512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      mem_value = ReadW(addr, instr) & mask;
304612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
304712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
304812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
304912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SW:
305012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SD:
305112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16;
305212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
305312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SWR: {
305412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      uint8_t al_offset = (rs + se_imm16) & kInt32AlignmentMask;
305512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      uint32_t mask = (1 << al_offset * 8) - 1;
305612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16 - al_offset;
305712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      mem_value = ReadW(addr, instr);
305812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      mem_value = (rt << al_offset * 8) | (mem_value & mask);
305912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
306012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
306112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LWC1:
306212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16;
306312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      alu_out = ReadW(addr, instr);
306412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
306512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LDC1:
306612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16;
306712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      fp_out = ReadD(addr, instr);
306812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
306912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SWC1:
307012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SDC1:
307112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16;
307212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
307312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    default:
307412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      UNREACHABLE();
307512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
307612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
307712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // ---------- Raise exceptions triggered.
307812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  SignalExceptions();
307912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
308012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // ---------- Execution.
308112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  switch (op) {
308212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // ------------- Branch instructions.
308312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case BEQ:
308412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case BNE:
308512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case BLEZ:
308612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case BGTZ:
308712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // Branch instructions common part.
308812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      execute_branch_delay_instruction = true;
308912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // Set next_pc.
309012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (do_branch) {
309112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
309212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        if (instr->IsLinkingInstruction()) {
309312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          set_register(31, current_pc + 2* Instruction::kInstrSize);
309412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        }
309512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else {
309612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        next_pc = current_pc + 2 * Instruction::kInstrSize;
309712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
309812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
309912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // ------------- Arithmetic instructions.
310012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case ADDI:
310112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case DADDI:
310212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case ADDIU:
310312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case DADDIU:
310412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SLTI:
310512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SLTIU:
310612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case ANDI:
310712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case ORI:
310812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case XORI:
310912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LUI:
311012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      set_register(rt_reg, alu_out);
311112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      TraceRegWr(alu_out);
311212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
311312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // ------------- Memory instructions.
311412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LB:
311512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LH:
311612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LWL:
311712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LW:
311812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LWU:
311912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LD:
312012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LBU:
312112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LHU:
312212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LWR:
312312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      set_register(rt_reg, alu_out);
312412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
312512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SB:
312612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      WriteB(addr, static_cast<int8_t>(rt));
312712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
312812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SH:
312912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      WriteH(addr, static_cast<uint16_t>(rt), instr);
313012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
313112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SWL:
313212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      WriteW(addr, mem_value, instr);
313312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
313412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SW:
313512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      WriteW(addr, rt, instr);
313612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
313712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SD:
313812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      Write2W(addr, rt, instr);
313912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
314012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SWR:
314112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      WriteW(addr, mem_value, instr);
314212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
314312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LWC1:
314412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      set_fpu_register(ft_reg, kFPUInvalidResult);  // Trash upper 32 bits.
314512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      set_fpu_register_word(ft_reg, static_cast<int32_t>(alu_out));
314612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
314712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case LDC1:
314812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      set_fpu_register_double(ft_reg, fp_out);
314912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
315012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SWC1:
315112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16;
315212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      WriteW(addr, get_fpu_register(ft_reg), instr);
315312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
315412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case SDC1:
315512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      addr = rs + se_imm16;
315612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      WriteD(addr, get_fpu_register_double(ft_reg), instr);
315712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
315812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    default:
315912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
316012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
316112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
316212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
316312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (execute_branch_delay_instruction) {
316412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // Execute branch delay slot
316512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // We don't check for end_sim_pc. First it should not be met as the current
316612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // pc is valid. Secondly a jump should always execute its branch delay slot.
316712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    Instruction* branch_delay_instr =
316812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
316912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    BranchDelayInstructionDecode(branch_delay_instr);
317012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
317112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
317212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // If needed update pc after the branch delay execution.
317312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (next_pc != bad_ra) {
317412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_pc(next_pc);
317512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
317612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
317712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
317812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
317912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Type 3: instructions using a 26 bytes immediate. (e.g. j, jal).
318012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::DecodeTypeJump(Instruction* instr) {
318112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Get current pc.
318212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int32_t current_pc = get_pc();
318312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Get unchanged bits of pc.
318412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int32_t pc_high_bits = current_pc & 0xf0000000;
318512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Next pc.
318612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
318712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
318812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Execute branch delay slot.
318912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // We don't check for end_sim_pc. First it should not be met as the current pc
319012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // is valid. Secondly a jump should always execute its branch delay slot.
319112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Instruction* branch_delay_instr =
319212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
319312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  BranchDelayInstructionDecode(branch_delay_instr);
319412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
319512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Update pc and ra if necessary.
319612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Do this after the branch delay execution.
319712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (instr->IsLinkingInstruction()) {
319812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_register(31, current_pc + 2 * Instruction::kInstrSize);
319912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
320012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_pc(next_pc);
320112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  pc_modified_ = true;
320212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
320312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
320412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
320512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org// Executes the current instruction.
320612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::InstructionDecode(Instruction* instr) {
320712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (v8::internal::FLAG_check_icache) {
320812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    CheckICache(isolate_->simulator_i_cache(), instr);
320912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
321012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  pc_modified_ = false;
321112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
321212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  v8::internal::EmbeddedVector<char, 256> buffer;
321312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
321412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (::v8::internal::FLAG_trace_sim) {
321512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    SNPrintF(trace_buf_, " ");
321612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    disasm::NameConverter converter;
321712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    disasm::Disassembler dasm(converter);
321812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // Use a reasonably large buffer.
321912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
322012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
322112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
322212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  switch (instr->InstructionType()) {
322312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case Instruction::kRegisterType:
322412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      DecodeTypeRegister(instr);
322512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
322612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case Instruction::kImmediateType:
322712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      DecodeTypeImmediate(instr);
322812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
322912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    case Instruction::kJumpType:
323012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      DecodeTypeJump(instr);
323112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      break;
323212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    default:
323312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      UNSUPPORTED();
323412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
323512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
323612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (::v8::internal::FLAG_trace_sim) {
323712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    PrintF("  0x%08lx  %-44s   %s\n", reinterpret_cast<intptr_t>(instr),
323812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        buffer.start(), trace_buf_.start());
323912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
324012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
324112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (!pc_modified_) {
324212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_register(pc, reinterpret_cast<int64_t>(instr) +
324312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                 Instruction::kInstrSize);
324412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
324512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
324612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
324712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
324812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
324912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::Execute() {
325012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Get the PC to simulate. Cannot use the accessor here as we need the
325112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // raw PC value and not the one used as input to arithmetic instructions.
325212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t program_counter = get_pc();
325312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (::v8::internal::FLAG_stop_sim_at == 0) {
325412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // Fast version of the dispatch loop without checking whether the simulator
325512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // should be stopping at a particular executed instruction.
325612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    while (program_counter != end_sim_pc) {
325712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
325812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      icount_++;
325912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      InstructionDecode(instr);
326012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      program_counter = get_pc();
326112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
326212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
326312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
326412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // we reach the particular instuction count.
326512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    while (program_counter != end_sim_pc) {
326612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
326712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      icount_++;
326812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      if (icount_ == static_cast<int64_t>(::v8::internal::FLAG_stop_sim_at)) {
326912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        MipsDebugger dbg(this);
327012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        dbg.Debug();
327112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      } else {
327212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org        InstructionDecode(instr);
327312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      }
327412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      program_counter = get_pc();
327512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
327612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
327712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
327812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
327912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
328012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgvoid Simulator::CallInternal(byte* entry) {
328112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Prepare to execute the code at entry.
328212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(pc, reinterpret_cast<int64_t>(entry));
328312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Put down marker for end of simulation. The simulator will stop simulation
328412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // when the PC reaches this value. By saving the "end simulation" value into
328512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // the LR the simulation stops when returning to this call point.
328612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(ra, end_sim_pc);
328712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
328812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Remember the values of callee-saved registers.
328912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // The code below assumes that r9 is not used as sb (static base) in
329012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // simulator code and therefore is regarded as a callee-saved register.
329112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t s0_val = get_register(s0);
329212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t s1_val = get_register(s1);
329312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t s2_val = get_register(s2);
329412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t s3_val = get_register(s3);
329512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t s4_val = get_register(s4);
329612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t s5_val = get_register(s5);
329712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t s6_val = get_register(s6);
329812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t s7_val = get_register(s7);
329912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t gp_val = get_register(gp);
330012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t sp_val = get_register(sp);
330112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t fp_val = get_register(fp);
330212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
330312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Set up the callee-saved registers with a known value. To be able to check
330412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // that they are preserved properly across JS execution.
330512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t callee_saved_value = icount_;
330612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s0, callee_saved_value);
330712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s1, callee_saved_value);
330812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s2, callee_saved_value);
330912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s3, callee_saved_value);
331012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s4, callee_saved_value);
331112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s5, callee_saved_value);
331212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s6, callee_saved_value);
331312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s7, callee_saved_value);
331412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(gp, callee_saved_value);
331512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(fp, callee_saved_value);
331612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
331712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Start the simulation.
331812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  Execute();
331912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
332012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Check that the callee-saved registers have been preserved.
332112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  CHECK_EQ(callee_saved_value, get_register(s0));
332212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  CHECK_EQ(callee_saved_value, get_register(s1));
332312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  CHECK_EQ(callee_saved_value, get_register(s2));
332412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  CHECK_EQ(callee_saved_value, get_register(s3));
332512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  CHECK_EQ(callee_saved_value, get_register(s4));
332612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  CHECK_EQ(callee_saved_value, get_register(s5));
332712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  CHECK_EQ(callee_saved_value, get_register(s6));
332812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  CHECK_EQ(callee_saved_value, get_register(s7));
332912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  CHECK_EQ(callee_saved_value, get_register(gp));
333012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  CHECK_EQ(callee_saved_value, get_register(fp));
333112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
333212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Restore callee-saved registers with the original value.
333312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s0, s0_val);
333412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s1, s1_val);
333512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s2, s2_val);
333612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s3, s3_val);
333712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s4, s4_val);
333812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s5, s5_val);
333912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s6, s6_val);
334012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(s7, s7_val);
334112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(gp, gp_val);
334212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(sp, sp_val);
334312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(fp, fp_val);
334412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
334512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
334612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
334712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgint64_t Simulator::Call(byte* entry, int argument_count, ...) {
334812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  const int kRegisterPassedArguments = (kMipsAbi == kN64) ? 8 : 4;
334912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  va_list parameters;
335012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  va_start(parameters, argument_count);
335112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Set up arguments.
335212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
335312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // First four arguments passed in registers in both ABI's.
3354e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(argument_count >= 4);
335512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(a0, va_arg(parameters, int64_t));
335612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(a1, va_arg(parameters, int64_t));
335712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(a2, va_arg(parameters, int64_t));
335812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(a3, va_arg(parameters, int64_t));
335912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
336012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (kMipsAbi == kN64) {
336112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // Up to eight arguments passed in registers in N64 ABI.
336212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // TODO(plind): N64 ABI calls these regs a4 - a7. Clarify this.
336312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (argument_count >= 5) set_register(a4, va_arg(parameters, int64_t));
336412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (argument_count >= 6) set_register(a5, va_arg(parameters, int64_t));
336512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (argument_count >= 7) set_register(a6, va_arg(parameters, int64_t));
336612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (argument_count >= 8) set_register(a7, va_arg(parameters, int64_t));
336712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
336812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
336912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Remaining arguments passed on stack.
337012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t original_stack = get_register(sp);
337112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Compute position of stack on entry to generated code.
337212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int stack_args_count = (argument_count > kRegisterPassedArguments) ?
337312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                         (argument_count - kRegisterPassedArguments) : 0;
337412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int stack_args_size = stack_args_count * sizeof(int64_t) + kCArgsSlotsSize;
337512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t entry_stack = original_stack - stack_args_size;
337612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
337712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (base::OS::ActivationFrameAlignment() != 0) {
337812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    entry_stack &= -base::OS::ActivationFrameAlignment();
337912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
338012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Store remaining arguments on stack, from low to high memory.
338112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
338212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  for (int i = kRegisterPassedArguments; i < argument_count; i++) {
338312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int stack_index = i - kRegisterPassedArguments + kCArgSlotCount;
338412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    stack_argument[stack_index] = va_arg(parameters, int64_t);
338512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
338612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  va_end(parameters);
338712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(sp, entry_stack);
338812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
338912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  CallInternal(entry);
339012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
339112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // Pop stack passed arguments.
339212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  CHECK_EQ(entry_stack, get_register(sp));
339312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(sp, original_stack);
339412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
339512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t result = get_register(v0);
339612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return result;
339712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
339812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
339912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
340012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orgdouble Simulator::CallFP(byte* entry, double d0, double d1) {
340112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (!IsMipsSoftFloatABI) {
340212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    const FPURegister fparg2 = (kMipsAbi == kN64) ? f13 : f14;
340312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_fpu_register_double(f12, d0);
340412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_fpu_register_double(fparg2, d1);
340512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
340612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    int buffer[2];
3407e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(sizeof(buffer[0]) * 2 == sizeof(d0));
340812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    memcpy(buffer, &d0, sizeof(d0));
340912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_dw_register(a0, buffer);
341012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    memcpy(buffer, &d1, sizeof(d1));
341112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    set_dw_register(a2, buffer);
341212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
341312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  CallInternal(entry);
341412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (!IsMipsSoftFloatABI) {
341512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return get_fpu_register_double(f0);
341612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  } else {
341712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    return get_double_from_register_pair(v0);
341812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  }
341912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
342012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
342112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
342212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orguintptr_t Simulator::PushAddress(uintptr_t address) {
342312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t new_sp = get_register(sp) - sizeof(uintptr_t);
342412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
342512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  *stack_slot = address;
342612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(sp, new_sp);
342712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return new_sp;
342812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
342912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
343012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
343112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.orguintptr_t Simulator::PopAddress() {
343212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  int64_t current_sp = get_register(sp);
343312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
343412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  uintptr_t address = *stack_slot;
343512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  set_register(sp, current_sp + sizeof(uintptr_t));
343612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  return address;
343712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org}
343812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
343912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
344012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#undef UNSUPPORTED
344112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
344212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org} }  // namespace v8::internal
344312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
344412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#endif  // USE_SIMULATOR
344512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org
344612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org#endif  // V8_TARGET_ARCH_MIPS64
3447