| Index: src/mips/simulator-mips.cc
|
| diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
|
| index 803cd9eb1a50bf28a3ac297c1e94d387a8a0d181..f9ee00fb2731ec9123f6d1bd698d412526bbe056 100644
|
| --- a/src/mips/simulator-mips.cc
|
| +++ b/src/mips/simulator-mips.cc
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2010 the V8 project authors. All rights reserved.
|
| +// Copyright 2011 the V8 project authors. All rights reserved.
|
| // Redistribution and use in source and binary forms, with or without
|
| // modification, are permitted provided that the following conditions are
|
| // met:
|
| @@ -35,7 +35,7 @@
|
|
|
| #include "disasm.h"
|
| #include "assembler.h"
|
| -#include "globals.h" // Need the BitCast
|
| +#include "globals.h" // Need the BitCast.
|
| #include "mips/constants-mips.h"
|
| #include "mips/simulator-mips.h"
|
|
|
| @@ -46,7 +46,7 @@
|
| namespace v8 {
|
| namespace internal {
|
|
|
| -// Utils functions
|
| +// Utils functions.
|
| bool HaveSameSign(int32_t a, int32_t b) {
|
| return ((a ^ b) >= 0);
|
| }
|
| @@ -139,7 +139,7 @@ void MipsDebugger::Stop(Instruction* instr) {
|
| }
|
|
|
|
|
| -#else // ndef GENERATED_CODE_COVERAGE
|
| +#else // GENERATED_CODE_COVERAGE
|
|
|
| #define UNSUPPORTED() printf("Unsupported instruction.\n");
|
|
|
| @@ -263,15 +263,15 @@ void MipsDebugger::PrintAllRegs() {
|
| #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
|
|
|
| PrintF("\n");
|
| - // at, v0, a0
|
| + // at, v0, a0.
|
| PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
|
| REG_INFO(1), REG_INFO(2), REG_INFO(4));
|
| - // v1, a1
|
| + // v1, a1.
|
| PrintF("%26s\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
|
| "", REG_INFO(3), REG_INFO(5));
|
| - // a2
|
| + // a2.
|
| PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(6));
|
| - // a3
|
| + // a3.
|
| PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(7));
|
| PrintF("\n");
|
| // t0-t7, s0-s7
|
| @@ -280,16 +280,16 @@ void MipsDebugger::PrintAllRegs() {
|
| REG_INFO(8+i), REG_INFO(16+i));
|
| }
|
| PrintF("\n");
|
| - // t8, k0, LO
|
| + // t8, k0, LO.
|
| PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
|
| REG_INFO(24), REG_INFO(26), REG_INFO(32));
|
| - // t9, k1, HI
|
| + // t9, k1, HI.
|
| PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
|
| REG_INFO(25), REG_INFO(27), REG_INFO(33));
|
| - // sp, fp, gp
|
| + // sp, fp, gp.
|
| PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
|
| REG_INFO(29), REG_INFO(30), REG_INFO(28));
|
| - // pc
|
| + // pc.
|
| PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
|
| REG_INFO(31), REG_INFO(34));
|
|
|
| @@ -307,7 +307,7 @@ void MipsDebugger::PrintAllRegsIncludingFPU() {
|
| PrintAllRegs();
|
|
|
| PrintF("\n\n");
|
| - // f0, f1, f2, ... f31
|
| + // f0, f1, f2, ... f31.
|
| PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(0) );
|
| PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(2) );
|
| PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(4) );
|
| @@ -345,7 +345,7 @@ void MipsDebugger::Debug() {
|
| char arg2[ARG_SIZE + 1];
|
| char* argv[3] = { cmd, arg1, arg2 };
|
|
|
| - // make sure to have a proper terminating character if reaching the limit
|
| + // Make sure to have a proper terminating character if reaching the limit.
|
| cmd[COMMAND_SIZE] = 0;
|
| arg1[ARG_SIZE] = 0;
|
| arg2[ARG_SIZE] = 0;
|
| @@ -358,10 +358,10 @@ void MipsDebugger::Debug() {
|
| if (last_pc != sim_->get_pc()) {
|
| disasm::NameConverter converter;
|
| disasm::Disassembler dasm(converter);
|
| - // use a reasonably large buffer
|
| + // Use a reasonably large buffer.
|
| v8::internal::EmbeddedVector<char, 256> buffer;
|
| dasm.InstructionDecode(buffer,
|
| - reinterpret_cast<byte_*>(sim_->get_pc()));
|
| + reinterpret_cast<byte*>(sim_->get_pc()));
|
| PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.start());
|
| last_pc = sim_->get_pc();
|
| }
|
| @@ -475,7 +475,7 @@ void MipsDebugger::Debug() {
|
|
|
| if (strcmp(cmd, "stack") == 0) {
|
| cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
|
| - } else { // "mem"
|
| + } else { // Command "mem".
|
| int32_t value;
|
| if (!GetValue(arg1, &value)) {
|
| PrintF("%s unrecognized\n", arg1);
|
| @@ -504,27 +504,27 @@ void MipsDebugger::Debug() {
|
| } else if ((strcmp(cmd, "disasm") == 0) || (strcmp(cmd, "dpc") == 0)) {
|
| disasm::NameConverter converter;
|
| disasm::Disassembler dasm(converter);
|
| - // use a reasonably large buffer
|
| + // Use a reasonably large buffer.
|
| v8::internal::EmbeddedVector<char, 256> buffer;
|
|
|
| - byte_* cur = NULL;
|
| - byte_* end = NULL;
|
| + byte* cur = NULL;
|
| + byte* end = NULL;
|
|
|
| if (argc == 1) {
|
| - cur = reinterpret_cast<byte_*>(sim_->get_pc());
|
| + cur = reinterpret_cast<byte*>(sim_->get_pc());
|
| end = cur + (10 * Instruction::kInstrSize);
|
| } else if (argc == 2) {
|
| int32_t value;
|
| if (GetValue(arg1, &value)) {
|
| - cur = reinterpret_cast<byte_*>(value);
|
| - // no length parameter passed, assume 10 instructions
|
| + cur = reinterpret_cast<byte*>(value);
|
| + // No length parameter passed, assume 10 instructions.
|
| end = cur + (10 * Instruction::kInstrSize);
|
| }
|
| } else {
|
| int32_t value1;
|
| int32_t value2;
|
| if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
|
| - cur = reinterpret_cast<byte_*>(value1);
|
| + cur = reinterpret_cast<byte*>(value1);
|
| end = cur + (value2 * Instruction::kInstrSize);
|
| }
|
| }
|
| @@ -561,25 +561,25 @@ void MipsDebugger::Debug() {
|
| } else if (strcmp(cmd, "unstop") == 0) {
|
| PrintF("Unstop command not implemented on MIPS.");
|
| } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) {
|
| - // Print registers and disassemble
|
| + // Print registers and disassemble.
|
| PrintAllRegs();
|
| PrintF("\n");
|
|
|
| disasm::NameConverter converter;
|
| disasm::Disassembler dasm(converter);
|
| - // use a reasonably large buffer
|
| + // Use a reasonably large buffer.
|
| v8::internal::EmbeddedVector<char, 256> buffer;
|
|
|
| - byte_* cur = NULL;
|
| - byte_* end = NULL;
|
| + byte* cur = NULL;
|
| + byte* end = NULL;
|
|
|
| if (argc == 1) {
|
| - cur = reinterpret_cast<byte_*>(sim_->get_pc());
|
| + cur = reinterpret_cast<byte*>(sim_->get_pc());
|
| end = cur + (10 * Instruction::kInstrSize);
|
| } else if (argc == 2) {
|
| int32_t value;
|
| if (GetValue(arg1, &value)) {
|
| - cur = reinterpret_cast<byte_*>(value);
|
| + cur = reinterpret_cast<byte*>(value);
|
| // no length parameter passed, assume 10 instructions
|
| end = cur + (10 * Instruction::kInstrSize);
|
| }
|
| @@ -587,7 +587,7 @@ void MipsDebugger::Debug() {
|
| int32_t value1;
|
| int32_t value2;
|
| if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
|
| - cur = reinterpret_cast<byte_*>(value1);
|
| + cur = reinterpret_cast<byte*>(value1);
|
| end = cur + (value2 * Instruction::kInstrSize);
|
| }
|
| }
|
| @@ -689,8 +689,8 @@ void Simulator::FlushICache(v8::internal::HashMap* i_cache,
|
|
|
| CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
|
| v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
|
| - ICacheHash(page),
|
| - true);
|
| + ICacheHash(page),
|
| + true);
|
| if (entry->value == NULL) {
|
| CachePage* new_page = new CachePage();
|
| entry->value = new_page;
|
| @@ -755,7 +755,6 @@ Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
|
| Initialize(isolate);
|
| // Setup simulator support first. Some of this information is needed to
|
| // setup the architecture state.
|
| - stack_size_ = 1 * 1024*1024; // allocate 1MB for stack
|
| stack_ = reinterpret_cast<char*>(malloc(stack_size_));
|
| pc_modified_ = false;
|
| icount_ = 0;
|
| @@ -875,7 +874,7 @@ void Simulator::set_register(int reg, int32_t value) {
|
| pc_modified_ = true;
|
| }
|
|
|
| - // zero register always hold 0.
|
| + // Zero register always holds 0.
|
| registers_[reg] = (reg == 0) ? 0 : value;
|
| }
|
|
|
| @@ -993,7 +992,7 @@ int32_t Simulator::get_pc() const {
|
|
|
| int Simulator::ReadW(int32_t addr, Instruction* instr) {
|
| if (addr >=0 && addr < 0x400) {
|
| - // this has to be a NULL-dereference
|
| + // This has to be a NULL-dereference, drop into debugger.
|
| MipsDebugger dbg(this);
|
| dbg.Debug();
|
| }
|
| @@ -1001,8 +1000,9 @@ int Simulator::ReadW(int32_t addr, Instruction* instr) {
|
| intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
|
| return *ptr;
|
| }
|
| - PrintF("Unaligned read at 0x%08x, pc=%p\n", addr,
|
| - reinterpret_cast<void*>(instr));
|
| + PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
|
| + addr,
|
| + reinterpret_cast<intptr_t>(instr));
|
| MipsDebugger dbg(this);
|
| dbg.Debug();
|
| return 0;
|
| @@ -1011,7 +1011,7 @@ int Simulator::ReadW(int32_t addr, Instruction* instr) {
|
|
|
| void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
|
| if (addr >= 0 && addr < 0x400) {
|
| - // this has to be a NULL-dereference
|
| + // This has to be a NULL-dereference, drop into debugger.
|
| MipsDebugger dbg(this);
|
| dbg.Debug();
|
| }
|
| @@ -1020,8 +1020,9 @@ void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
|
| *ptr = value;
|
| return;
|
| }
|
| - PrintF("Unaligned write at 0x%08x, pc=%p\n", addr,
|
| - reinterpret_cast<void*>(instr));
|
| + PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
|
| + addr,
|
| + reinterpret_cast<intptr_t>(instr));
|
| MipsDebugger dbg(this);
|
| dbg.Debug();
|
| }
|
| @@ -1032,8 +1033,9 @@ double Simulator::ReadD(int32_t addr, Instruction* instr) {
|
| double* ptr = reinterpret_cast<double*>(addr);
|
| return *ptr;
|
| }
|
| - PrintF("Unaligned (double) read at 0x%08x, pc=%p\n", addr,
|
| - reinterpret_cast<void*>(instr));
|
| + PrintF("Unaligned (double) read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
|
| + addr,
|
| + reinterpret_cast<intptr_t>(instr));
|
| OS::Abort();
|
| return 0;
|
| }
|
| @@ -1045,8 +1047,9 @@ void Simulator::WriteD(int32_t addr, double value, Instruction* instr) {
|
| *ptr = value;
|
| return;
|
| }
|
| - PrintF("Unaligned (double) write at 0x%08x, pc=%p\n", addr,
|
| - reinterpret_cast<void*>(instr));
|
| + PrintF("Unaligned (double) write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
|
| + addr,
|
| + reinterpret_cast<intptr_t>(instr));
|
| OS::Abort();
|
| }
|
|
|
| @@ -1056,8 +1059,9 @@ uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
|
| uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
|
| return *ptr;
|
| }
|
| - PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr,
|
| - reinterpret_cast<void*>(instr));
|
| + PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
|
| + addr,
|
| + reinterpret_cast<intptr_t>(instr));
|
| OS::Abort();
|
| return 0;
|
| }
|
| @@ -1068,8 +1072,9 @@ int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
|
| int16_t* ptr = reinterpret_cast<int16_t*>(addr);
|
| return *ptr;
|
| }
|
| - PrintF("Unaligned signed halfword read at 0x%08x, pc=%p\n", addr,
|
| - reinterpret_cast<void*>(instr));
|
| + PrintF("Unaligned signed halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
|
| + addr,
|
| + reinterpret_cast<intptr_t>(instr));
|
| OS::Abort();
|
| return 0;
|
| }
|
| @@ -1081,8 +1086,9 @@ void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
|
| *ptr = value;
|
| return;
|
| }
|
| - PrintF("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr,
|
| - reinterpret_cast<void*>(instr));
|
| + PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
|
| + addr,
|
| + reinterpret_cast<intptr_t>(instr));
|
| OS::Abort();
|
| }
|
|
|
| @@ -1093,8 +1099,9 @@ void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
|
| *ptr = value;
|
| return;
|
| }
|
| - PrintF("Unaligned halfword write at 0x%08x, pc=%p\n", addr,
|
| - reinterpret_cast<void*>(instr));
|
| + PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
|
| + addr,
|
| + reinterpret_cast<intptr_t>(instr));
|
| OS::Abort();
|
| }
|
|
|
| @@ -1156,6 +1163,10 @@ typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
|
| int32_t arg2,
|
| int32_t arg3);
|
|
|
| +// This signature supports direct call in to API function native callback
|
| +// (refer to InvocationCallback in v8.h).
|
| +typedef v8::Handle<v8::Value> (*SimulatorRuntimeApiCall)(int32_t arg0);
|
| +
|
| // Software interrupt instructions are used by the simulator to call into the
|
| // C-based V8 runtime. They are also used for debugging with simulator.
|
| void Simulator::SoftwareInterrupt(Instruction* instr) {
|
| @@ -1167,11 +1178,6 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
|
|
|
| // We first check if we met a call_rt_redirected.
|
| if (instr->InstructionBits() == rtCallRedirInstr) {
|
| - // Check if stack is aligned. Error if not aligned is reported below to
|
| - // include information on the function called.
|
| - bool stack_aligned =
|
| - (get_register(sp)
|
| - & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
|
| Redirection* redirection = Redirection::FromSwiInstruction(instr);
|
| int32_t arg0 = get_register(a0);
|
| int32_t arg1 = get_register(a1);
|
| @@ -1186,16 +1192,24 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
|
| // stack check here.
|
| int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
|
| int32_t* stack = reinterpret_cast<int32_t*>(stack_);
|
| - if (stack_pointer >= stack && stack_pointer < stack + stack_size_) {
|
| - arg4 = stack_pointer[0];
|
| - arg5 = stack_pointer[1];
|
| + if (stack_pointer >= stack && stack_pointer < stack + stack_size_ - 5) {
|
| + // Args 4 and 5 are on the stack after the reserved space for args 0..3.
|
| + arg4 = stack_pointer[4];
|
| + arg5 = stack_pointer[5];
|
| }
|
| +
|
| + bool fp_call =
|
| + (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
|
| + (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
|
| + (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
|
| + (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
|
| +
|
| // This is dodgy but it works because the C entry stubs are never moved.
|
| // See comment in codegen-arm.cc and bug 1242173.
|
| int32_t saved_ra = get_register(ra);
|
|
|
| intptr_t external =
|
| - reinterpret_cast<int32_t>(redirection->external_function());
|
| + reinterpret_cast<intptr_t>(redirection->external_function());
|
|
|
| // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware
|
| // FPU, or gcc soft-float routines. Hardware FPU is simulated in this
|
| @@ -1207,17 +1221,18 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
|
| // than the usual int64_t return. The data is returned in different
|
| // registers and cannot be cast from one type to the other. However, the
|
| // calling arguments are passed the same way in both cases.
|
| - if (redirection->type() == ExternalReference::FP_RETURN_CALL) {
|
| + if (fp_call) {
|
| SimulatorRuntimeFPCall target =
|
| - reinterpret_cast<SimulatorRuntimeFPCall>(external);
|
| - if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
|
| - PrintF("Call to host function at %p with args %08x:%08x %08x:%08x",
|
| - FUNCTION_ADDR(target), arg0, arg1, arg2, arg3);
|
| - if (!stack_aligned) {
|
| - PrintF(" with unaligned stack %08x\n", get_register(sp));
|
| - }
|
| - PrintF("\n");
|
| - }
|
| + reinterpret_cast<SimulatorRuntimeFPCall>(external);
|
| + if (::v8::internal::FLAG_trace_sim) {
|
| + PrintF(
|
| + "Call to host function at %p args %08x, %08x, %08x, %08x\n",
|
| + FUNCTION_ADDR(target),
|
| + arg0,
|
| + arg1,
|
| + arg2,
|
| + arg3);
|
| + }
|
| double result = target(arg0, arg1, arg2, arg3);
|
| // fp result -> registers v0 and v1.
|
| int32_t gpreg_pair[2];
|
| @@ -1225,19 +1240,22 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
|
| set_register(v0, gpreg_pair[0]);
|
| set_register(v1, gpreg_pair[1]);
|
| } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
|
| - PrintF("Mips does not yet support ExternalReference::DIRECT_API_CALL\n");
|
| - ASSERT(redirection->type() != ExternalReference::DIRECT_API_CALL);
|
| - } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
|
| - PrintF("Mips does not support ExternalReference::DIRECT_GETTER_CALL\n");
|
| - ASSERT(redirection->type() != ExternalReference::DIRECT_GETTER_CALL);
|
| + SimulatorRuntimeApiCall target =
|
| + reinterpret_cast<SimulatorRuntimeApiCall>(external);
|
| + if (::v8::internal::FLAG_trace_sim) {
|
| + PrintF("Call to host function at %p args %08x\n",
|
| + FUNCTION_ADDR(target),
|
| + arg0);
|
| + }
|
| + v8::Handle<v8::Value> result = target(arg0);
|
| + set_register(v0, (int32_t) *result);
|
| } else {
|
| - // Builtin call.
|
| - ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);
|
| SimulatorRuntimeCall target =
|
| - reinterpret_cast<SimulatorRuntimeCall>(external);
|
| - if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
|
| + reinterpret_cast<SimulatorRuntimeCall>(external);
|
| + if (::v8::internal::FLAG_trace_sim) {
|
| PrintF(
|
| - "Call to host function at %p: %08x, %08x, %08x, %08x, %08x, %08x",
|
| + "Call to host function at %p "
|
| + "args %08x, %08x, %08x, %08x, %08x, %08x\n",
|
| FUNCTION_ADDR(target),
|
| arg0,
|
| arg1,
|
| @@ -1245,12 +1263,7 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
|
| arg3,
|
| arg4,
|
| arg5);
|
| - if (!stack_aligned) {
|
| - PrintF(" with unaligned stack %08x\n", get_register(sp));
|
| - }
|
| - PrintF("\n");
|
| }
|
| -
|
| int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
|
| set_register(v0, static_cast<int32_t>(result));
|
| set_register(v1, static_cast<int32_t>(result >> 32));
|
| @@ -1261,8 +1274,8 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
|
| set_register(ra, saved_ra);
|
| set_pc(get_register(ra));
|
|
|
| - } else if (func == BREAK && code >= 0 && code < 16) {
|
| - // First 16 break_ codes interpreted as debug markers.
|
| + } else if (func == BREAK && code >= 0 && code < 32) {
|
| + // First 32 break_ codes interpreted as debug-markers/watchpoints.
|
| MipsDebugger dbg(this);
|
| ++break_count_;
|
| PrintF("\n---- break %d marker: %3d (instr count: %8d) ----------"
|
| @@ -1312,9 +1325,9 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
|
| const int32_t fs_reg = instr->FsValue();
|
|
|
|
|
| - // ---------- Configuration
|
| + // ---------- Configuration.
|
| switch (op) {
|
| - case COP1: // Coprocessor instructions
|
| + case COP1: // Coprocessor instructions.
|
| switch (instr->RsFieldRaw()) {
|
| case BC1: // Handled in DecodeTypeImmed, should never come here.
|
| UNREACHABLE();
|
| @@ -1363,7 +1376,7 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
|
| } else {
|
| // Logical right-rotate of a word by a fixed number of bits. This
|
| // is special case of SRL instruction, added in MIPS32 Release 2.
|
| - // RS field is equal to 00001
|
| + // RS field is equal to 00001.
|
| alu_out = (rt_u >> sa) | (rt_u << (32 - sa));
|
| }
|
| break;
|
| @@ -1381,7 +1394,7 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
|
| } else {
|
| // Logical right-rotate of a word by a variable number of bits.
|
| // This is special case od SRLV instruction, added in MIPS32
|
| - // Release 2. SA field is equal to 00001
|
| + // Release 2. SA field is equal to 00001.
|
| alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u));
|
| }
|
| break;
|
| @@ -1400,10 +1413,6 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
|
| case MULTU:
|
| u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u);
|
| break;
|
| - case DIV:
|
| - case DIVU:
|
| - exceptions[kDivideByZero] = rt == 0;
|
| - break;
|
| case ADD:
|
| if (HaveSameSign(rs, rt)) {
|
| if (rs > 0) {
|
| @@ -1448,7 +1457,7 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
|
| case SLTU:
|
| alu_out = rs_u < rt_u ? 1 : 0;
|
| break;
|
| - // Break and trap instructions
|
| + // Break and trap instructions.
|
| case BREAK:
|
|
|
| do_interrupt = true;
|
| @@ -1476,6 +1485,10 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
|
| case MOVCI:
|
| // No action taken on decode.
|
| break;
|
| + case DIV:
|
| + case DIVU:
|
| + // div and divu never raise exceptions.
|
| + break;
|
| default:
|
| UNREACHABLE();
|
| };
|
| @@ -1495,7 +1508,7 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
|
| case SPECIAL3:
|
| switch (instr->FunctionFieldRaw()) {
|
| case INS: { // Mips32r2 instruction.
|
| - // Interpret Rd field as 5-bit msb of insert.
|
| + // Interpret rd field as 5-bit msb of insert.
|
| uint16_t msb = rd_reg;
|
| // Interpret sa field as 5-bit lsb of insert.
|
| uint16_t lsb = sa;
|
| @@ -1505,7 +1518,7 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
|
| break;
|
| }
|
| case EXT: { // Mips32r2 instruction.
|
| - // Interpret Rd field as 5-bit msb of extract.
|
| + // Interpret rd field as 5-bit msb of extract.
|
| uint16_t msb = rd_reg;
|
| // Interpret sa field as 5-bit lsb of extract.
|
| uint16_t lsb = sa;
|
| @@ -1541,7 +1554,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
|
| int64_t i64hilo = 0;
|
| uint64_t u64hilo = 0;
|
|
|
| - // ALU output
|
| + // ALU output.
|
| // It should not be used as is. Instructions using it should always
|
| // initialize it first.
|
| int32_t alu_out = 0x12345678;
|
| @@ -1549,7 +1562,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
|
| // For break and trap instructions.
|
| bool do_interrupt = false;
|
|
|
| - // For jr and jalr
|
| + // For jr and jalr.
|
| // Get current pc.
|
| int32_t current_pc = get_pc();
|
| // Next pc
|
| @@ -1566,11 +1579,11 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
|
| // ---------- Raise exceptions triggered.
|
| SignalExceptions();
|
|
|
| - // ---------- Execution
|
| + // ---------- Execution.
|
| switch (op) {
|
| case COP1:
|
| switch (instr->RsFieldRaw()) {
|
| - case BC1: // branch on coprocessor condition
|
| + case BC1: // Branch on coprocessor condition.
|
| UNREACHABLE();
|
| break;
|
| case CFC1:
|
| @@ -1800,7 +1813,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
|
| Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
|
| current_pc+Instruction::kInstrSize);
|
| BranchDelayInstructionDecode(branch_delay_instr);
|
| - set_register(31, current_pc + 2* Instruction::kInstrSize);
|
| + set_register(31, current_pc + 2 * Instruction::kInstrSize);
|
| set_pc(next_pc);
|
| pc_modified_ = true;
|
| break;
|
| @@ -1815,13 +1828,19 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
|
| set_register(HI, static_cast<int32_t>(u64hilo >> 32));
|
| break;
|
| case DIV:
|
| - // Divide by zero was checked in the configuration step.
|
| - set_register(LO, rs / rt);
|
| - set_register(HI, rs % rt);
|
| + // Divide by zero was not checked in the configuration step - div and
|
| + // divu do not raise exceptions. On division by 0, the result will
|
| + // be UNPREDICTABLE.
|
| + if (rt != 0) {
|
| + set_register(LO, rs / rt);
|
| + set_register(HI, rs % rt);
|
| + }
|
| break;
|
| case DIVU:
|
| - set_register(LO, rs_u / rt_u);
|
| - set_register(HI, rs_u % rt_u);
|
| + if (rt_u != 0) {
|
| + set_register(LO, rs_u / rt_u);
|
| + set_register(HI, rs_u % rt_u);
|
| + }
|
| break;
|
| // Break and trap instructions.
|
| case BREAK:
|
| @@ -1840,9 +1859,9 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
|
| if (rt) set_register(rd_reg, rs);
|
| break;
|
| case MOVCI: {
|
| - uint32_t cc = instr->FCccValue();
|
| + uint32_t cc = instr->FBccValue();
|
| uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
|
| - if (instr->Bit(16)) { // Read Tf bit
|
| + if (instr->Bit(16)) { // Read Tf bit.
|
| if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
|
| } else {
|
| if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
|
| @@ -1891,17 +1910,17 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
|
| }
|
|
|
|
|
| -// Type 2: instructions using a 16 bytes immediate. (eg: addi, beq)
|
| +// Type 2: instructions using a 16 bytes immediate. (eg: addi, beq).
|
| void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| // Instruction fields.
|
| Opcode op = instr->OpcodeFieldRaw();
|
| int32_t rs = get_register(instr->RsValue());
|
| uint32_t rs_u = static_cast<uint32_t>(rs);
|
| - int32_t rt_reg = instr->RtValue(); // destination register
|
| + int32_t rt_reg = instr->RtValue(); // Destination register.
|
| int32_t rt = get_register(rt_reg);
|
| int16_t imm16 = instr->Imm16Value();
|
|
|
| - int32_t ft_reg = instr->FtValue(); // destination register
|
| + int32_t ft_reg = instr->FtValue(); // Destination register.
|
|
|
| // Zero extended immediate.
|
| uint32_t oe_imm16 = 0xffff & imm16;
|
| @@ -1925,10 +1944,10 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
|
|
| // Used for memory instructions.
|
| int32_t addr = 0x0;
|
| - // Value to be written in memory
|
| + // Value to be written in memory.
|
| uint32_t mem_value = 0x0;
|
|
|
| - // ---------- Configuration (and execution for REGIMM)
|
| + // ---------- Configuration (and execution for REGIMM).
|
| switch (op) {
|
| // ------------- COP1. Coprocessor instructions.
|
| case COP1:
|
| @@ -1939,7 +1958,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| cc_value = test_fcsr_bit(fcsr_cc);
|
| do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
|
| execute_branch_delay_instruction = true;
|
| - // Set next_pc
|
| + // Set next_pc.
|
| if (do_branch) {
|
| next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
|
| } else {
|
| @@ -1950,7 +1969,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| UNREACHABLE();
|
| };
|
| break;
|
| - // ------------- REGIMM class
|
| + // ------------- REGIMM class.
|
| case REGIMM:
|
| switch (instr->RtFieldRaw()) {
|
| case BLTZ:
|
| @@ -1975,7 +1994,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| case BGEZAL:
|
| // Branch instructions common part.
|
| execute_branch_delay_instruction = true;
|
| - // Set next_pc
|
| + // Set next_pc.
|
| if (do_branch) {
|
| next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
|
| if (instr->IsLinkingInstruction()) {
|
| @@ -1987,8 +2006,8 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| default:
|
| break;
|
| };
|
| - break; // case REGIMM
|
| - // ------------- Branch instructions
|
| + break; // case REGIMM.
|
| + // ------------- Branch instructions.
|
| // When comparing to zero, the encoding of rt field is always 0, so we don't
|
| // need to replace rt with zero.
|
| case BEQ:
|
| @@ -2003,7 +2022,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| case BGTZ:
|
| do_branch = rs > 0;
|
| break;
|
| - // ------------- Arithmetic instructions
|
| + // ------------- Arithmetic instructions.
|
| case ADDI:
|
| if (HaveSameSign(rs, se_imm16)) {
|
| if (rs > 0) {
|
| @@ -2036,7 +2055,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| case LUI:
|
| alu_out = (oe_imm16 << 16);
|
| break;
|
| - // ------------- Memory instructions
|
| + // ------------- Memory instructions.
|
| case LB:
|
| addr = rs + se_imm16;
|
| alu_out = ReadB(addr);
|
| @@ -2046,7 +2065,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| alu_out = ReadH(addr, instr);
|
| break;
|
| case LWL: {
|
| - // al_offset is an offset of the effective address within an aligned word
|
| + // al_offset is offset of the effective address within an aligned word.
|
| uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
|
| uint8_t byte_shift = kPointerAlignmentMask - al_offset;
|
| uint32_t mask = (1 << byte_shift * 8) - 1;
|
| @@ -2069,7 +2088,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| alu_out = ReadHU(addr, instr);
|
| break;
|
| case LWR: {
|
| - // al_offset is an offset of the effective address within an aligned word
|
| + // al_offset is offset of the effective address within an aligned word.
|
| uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
|
| uint8_t byte_shift = kPointerAlignmentMask - al_offset;
|
| uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
|
| @@ -2124,16 +2143,16 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| // ---------- Raise exceptions triggered.
|
| SignalExceptions();
|
|
|
| - // ---------- Execution
|
| + // ---------- Execution.
|
| switch (op) {
|
| - // ------------- Branch instructions
|
| + // ------------- Branch instructions.
|
| case BEQ:
|
| case BNE:
|
| case BLEZ:
|
| case BGTZ:
|
| // Branch instructions common part.
|
| execute_branch_delay_instruction = true;
|
| - // Set next_pc
|
| + // Set next_pc.
|
| if (do_branch) {
|
| next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
|
| if (instr->IsLinkingInstruction()) {
|
| @@ -2143,7 +2162,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| next_pc = current_pc + 2 * Instruction::kInstrSize;
|
| }
|
| break;
|
| - // ------------- Arithmetic instructions
|
| + // ------------- Arithmetic instructions.
|
| case ADDI:
|
| case ADDIU:
|
| case SLTI:
|
| @@ -2154,7 +2173,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| case LUI:
|
| set_register(rt_reg, alu_out);
|
| break;
|
| - // ------------- Memory instructions
|
| + // ------------- Memory instructions.
|
| case LB:
|
| case LH:
|
| case LWL:
|
| @@ -2214,26 +2233,26 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| }
|
|
|
|
|
| -// Type 3: instructions using a 26 bytes immediate. (eg: j, jal)
|
| +// Type 3: instructions using a 26 bytes immediate. (eg: j, jal).
|
| void Simulator::DecodeTypeJump(Instruction* instr) {
|
| // Get current pc.
|
| int32_t current_pc = get_pc();
|
| // Get unchanged bits of pc.
|
| int32_t pc_high_bits = current_pc & 0xf0000000;
|
| - // Next pc
|
| + // Next pc.
|
| int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
|
|
|
| - // Execute branch delay slot
|
| + // Execute branch delay slot.
|
| // We don't check for end_sim_pc. First it should not be met as the current pc
|
| // is valid. Secondly a jump should always execute its branch delay slot.
|
| Instruction* branch_delay_instr =
|
| - reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
|
| + reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
|
| BranchDelayInstructionDecode(branch_delay_instr);
|
|
|
| // Update pc and ra if necessary.
|
| // Do this after the branch delay execution.
|
| if (instr->IsLinkingInstruction()) {
|
| - set_register(31, current_pc + 2* Instruction::kInstrSize);
|
| + set_register(31, current_pc + 2 * Instruction::kInstrSize);
|
| }
|
| set_pc(next_pc);
|
| pc_modified_ = true;
|
| @@ -2249,11 +2268,11 @@ void Simulator::InstructionDecode(Instruction* instr) {
|
| if (::v8::internal::FLAG_trace_sim) {
|
| disasm::NameConverter converter;
|
| disasm::Disassembler dasm(converter);
|
| - // use a reasonably large buffer
|
| + // Use a reasonably large buffer.
|
| v8::internal::EmbeddedVector<char, 256> buffer;
|
| - dasm.InstructionDecode(buffer, reinterpret_cast<byte_*>(instr));
|
| + dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
|
| PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr),
|
| - buffer.start());
|
| + buffer.start());
|
| }
|
|
|
| switch (instr->InstructionType()) {
|
| @@ -2308,10 +2327,10 @@ void Simulator::Execute() {
|
| }
|
|
|
|
|
| -int32_t Simulator::Call(byte_* entry, int argument_count, ...) {
|
| +int32_t Simulator::Call(byte* entry, int argument_count, ...) {
|
| va_list parameters;
|
| va_start(parameters, argument_count);
|
| - // Setup arguments
|
| + // Setup arguments.
|
|
|
| // First four arguments passed in registers.
|
| ASSERT(argument_count >= 4);
|
| @@ -2336,7 +2355,7 @@ int32_t Simulator::Call(byte_* entry, int argument_count, ...) {
|
| va_end(parameters);
|
| set_register(sp, entry_stack);
|
|
|
| - // Prepare to execute the code at entry
|
| + // Prepare to execute the code at entry.
|
| set_register(pc, reinterpret_cast<int32_t>(entry));
|
| // Put down marker for end of simulation. The simulator will stop simulation
|
| // when the PC reaches this value. By saving the "end simulation" value into
|
| @@ -2372,7 +2391,7 @@ int32_t Simulator::Call(byte_* entry, int argument_count, ...) {
|
| set_register(gp, callee_saved_value);
|
| set_register(fp, callee_saved_value);
|
|
|
| - // Start the simulation
|
| + // Start the simulation.
|
| Execute();
|
|
|
| // Check that the callee-saved registers have been preserved.
|
|
|