vendor/v8/src/arm/simulator-arm.cc in mustang-0.0.1 vs vendor/v8/src/arm/simulator-arm.cc in mustang-0.1.0

- old
+ new

@@ -47,16 +47,16 @@ // SScanF not being implemented in a platform independent way through // ::v8::internal::OS in the same way as SNPrintF is that the // Windows C Run-Time Library does not provide vsscanf. #define SScanF sscanf // NOLINT -// The Debugger class is used by the simulator while debugging simulated ARM +// The ArmDebugger class is used by the simulator while debugging simulated ARM // code. -class Debugger { +class ArmDebugger { public: - explicit Debugger(Simulator* sim); - ~Debugger(); + explicit ArmDebugger(Simulator* sim); + ~ArmDebugger(); void Stop(Instruction* instr); void Debug(); private: @@ -81,16 +81,16 @@ void UndoBreakpoints(); void RedoBreakpoints(); }; -Debugger::Debugger(Simulator* sim) { +ArmDebugger::ArmDebugger(Simulator* sim) { sim_ = sim; } -Debugger::~Debugger() { +ArmDebugger::~ArmDebugger() { } #ifdef GENERATED_CODE_COVERAGE @@ -103,11 +103,11 @@ coverage_log = fopen(file_name, "aw+"); } } -void Debugger::Stop(Instruction* instr) { +void ArmDebugger::Stop(Instruction* instr) { // Get the stop code. uint32_t code = instr->SvcValue() & kStopCodeMask; // Retrieve the encoded address, which comes just after this stop. char** msg_address = reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize); @@ -135,11 +135,11 @@ static void InitializeCoverage() { } -void Debugger::Stop(Instruction* instr) { +void ArmDebugger::Stop(Instruction* instr) { // Get the stop code. uint32_t code = instr->SvcValue() & kStopCodeMask; // Retrieve the encoded address, which comes just after this stop. char* msg = *reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize); @@ -157,25 +157,25 @@ Debug(); } #endif -int32_t Debugger::GetRegisterValue(int regnum) { +int32_t ArmDebugger::GetRegisterValue(int regnum) { if (regnum == kPCRegister) { return sim_->get_pc(); } else { return sim_->get_register(regnum); } } -double Debugger::GetVFPDoubleRegisterValue(int regnum) { +double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) { return sim_->get_double_from_d_register(regnum); } -bool Debugger::GetValue(const char* desc, int32_t* value) { +bool ArmDebugger::GetValue(const char* desc, int32_t* value) { int regnum = Registers::Number(desc); if (regnum != kNoRegister) { *value = GetRegisterValue(regnum); return true; } else { @@ -187,33 +187,33 @@ } return false; } -bool Debugger::GetVFPSingleValue(const char* desc, float* value) { +bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) { bool is_double; int regnum = VFPRegisters::Number(desc, &is_double); if (regnum != kNoRegister && !is_double) { *value = sim_->get_float_from_s_register(regnum); return true; } return false; } -bool Debugger::GetVFPDoubleValue(const char* desc, double* value) { +bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) { bool is_double; int regnum = VFPRegisters::Number(desc, &is_double); if (regnum != kNoRegister && is_double) { *value = sim_->get_double_from_d_register(regnum); return true; } return false; } -bool Debugger::SetBreakpoint(Instruction* breakpc) { +bool ArmDebugger::SetBreakpoint(Instruction* breakpc) { // Check if a breakpoint can be set. If not return without any side-effects. if (sim_->break_pc_ != NULL) { return false; } @@ -224,36 +224,36 @@ // when the debugger shell continues. return true; } -bool Debugger::DeleteBreakpoint(Instruction* breakpc) { +bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) { if (sim_->break_pc_ != NULL) { sim_->break_pc_->SetInstructionBits(sim_->break_instr_); } sim_->break_pc_ = NULL; sim_->break_instr_ = 0; return true; } -void Debugger::UndoBreakpoints() { +void ArmDebugger::UndoBreakpoints() { if (sim_->break_pc_ != NULL) { sim_->break_pc_->SetInstructionBits(sim_->break_instr_); } } -void Debugger::RedoBreakpoints() { +void ArmDebugger::RedoBreakpoints() { if (sim_->break_pc_ != NULL) { sim_->break_pc_->SetInstructionBits(kBreakpointInstr); } } -void Debugger::Debug() { +void ArmDebugger::Debug() { intptr_t last_pc = -1; bool done = false; #define COMMAND_SIZE 63 #define ARG_SIZE 255 @@ -314,20 +314,30 @@ value = GetRegisterValue(i); PrintF("%3s: 0x%08x %10d\n", Registers::Name(i), value, value); } for (int i = 0; i < kNumVFPDoubleRegisters; i++) { dvalue = GetVFPDoubleRegisterValue(i); - PrintF("%3s: %f\n", - VFPRegisters::Name(i, true), dvalue); + uint64_t as_words = BitCast<uint64_t>(dvalue); + PrintF("%3s: %f 0x%08x %08x\n", + VFPRegisters::Name(i, true), + dvalue, + static_cast<uint32_t>(as_words >> 32), + static_cast<uint32_t>(as_words & 0xffffffff)); } } else { if (GetValue(arg1, &value)) { PrintF("%s: 0x%08x %d \n", arg1, value, value); } else if (GetVFPSingleValue(arg1, &svalue)) { - PrintF("%s: %f \n", arg1, svalue); + uint32_t as_word = BitCast<uint32_t>(svalue); + PrintF("%s: %f 0x%08x\n", arg1, svalue, as_word); } else if (GetVFPDoubleValue(arg1, &dvalue)) { - PrintF("%s: %f \n", arg1, dvalue); + uint64_t as_words = BitCast<uint64_t>(dvalue); + PrintF("%s: %f 0x%08x %08x\n", + arg1, + dvalue, + static_cast<uint32_t>(as_words >> 32), + static_cast<uint32_t>(as_words & 0xffffffff)); } else { PrintF("%s unrecognized\n", arg1); } } } else { @@ -378,15 +388,28 @@ } } end = cur + words; while (cur < end) { - PrintF(" 0x%08x: 0x%08x %10d\n", + PrintF(" 0x%08x: 0x%08x %10d", reinterpret_cast<intptr_t>(cur), *cur, *cur); + HeapObject* obj = reinterpret_cast<HeapObject*>(*cur); + int value = *cur; + Heap* current_heap = v8::internal::Isolate::Current()->heap(); + if (current_heap->Contains(obj) || ((value & 1) == 0)) { + PrintF(" ("); + if ((value & 1) == 0) { + PrintF("smi %d", value / 2); + } else { + obj->ShortPrint(); + } + PrintF(")"); + } + PrintF("\n"); cur++; } - } else if (strcmp(cmd, "disasm") == 0) { + } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) { disasm::NameConverter converter; disasm::Disassembler dasm(converter); // use a reasonably large buffer v8::internal::EmbeddedVector<char, 256> buffer; @@ -396,15 +419,27 @@ if (argc == 1) { 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*>(sim_->get_pc()); - // Disassemble <arg1> instructions. - end = cur + (value * Instruction::kInstrSize); + int regnum = Registers::Number(arg1); + if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) { + // The argument is an address or a register name. + int32_t value; + if (GetValue(arg1, &value)) { + cur = reinterpret_cast<byte*>(value); + // Disassemble 10 instructions at <arg1>. + end = cur + (10 * Instruction::kInstrSize); + } + } else { + // The argument is the number of instructions. + int32_t value; + if (GetValue(arg1, &value)) { + cur = reinterpret_cast<byte*>(sim_->get_pc()); + // Disassemble <arg1> instructions. + end = cur + (value * Instruction::kInstrSize); + } } } else { int32_t value1; int32_t value2; if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { @@ -522,12 +557,14 @@ PrintF("stack [<words>]\n"); PrintF(" dump stack content, default dump 10 words)\n"); PrintF("mem <address> [<words>]\n"); PrintF(" dump memory content, default dump 10 words)\n"); PrintF("disasm [<instructions>]\n"); - PrintF("disasm [[<address>] <instructions>]\n"); - PrintF(" disassemble code, default is 10 instructions from pc\n"); + PrintF("disasm [<address/register>]\n"); + PrintF("disasm [[<address/register>] <instructions>]\n"); + PrintF(" disassemble code, default is 10 instructions\n"); + PrintF(" from pc (alias 'di')\n"); PrintF("gdb\n"); PrintF(" enter gdb\n"); PrintF("break <address>\n"); PrintF(" set a break point on the address\n"); PrintF("del\n"); @@ -537,15 +574,15 @@ PrintF("stop feature:\n"); PrintF(" Description:\n"); PrintF(" Stops are debug instructions inserted by\n"); PrintF(" the Assembler::stop() function.\n"); PrintF(" When hitting a stop, the Simulator will\n"); - PrintF(" stop and and give control to the Debugger.\n"); + PrintF(" stop and and give control to the ArmDebugger.\n"); PrintF(" The first %d stop codes are watched:\n", Simulator::kNumOfWatchedStops); PrintF(" - They can be enabled / disabled: the Simulator\n"); - PrintF(" will / won't stop when hitting them.\n"); + PrintF(" will / won't stop when hitting them.\n"); PrintF(" - The Simulator keeps track of how many times they \n"); PrintF(" are met. (See the info command.) Going over a\n"); PrintF(" disabled stop still increases its counter. \n"); PrintF(" Commands:\n"); PrintF(" stop info all/<code> : print infos about number <code>\n"); @@ -591,63 +628,68 @@ intptr_t end_page = ((start + size) & ~CachePage::kPageMask); return start_page == end_page; } -void Simulator::FlushICache(void* start_addr, size_t size) { +void Simulator::FlushICache(v8::internal::HashMap* i_cache, + void* start_addr, + size_t size) { intptr_t start = reinterpret_cast<intptr_t>(start_addr); int intra_line = (start & CachePage::kLineMask); start -= intra_line; size += intra_line; size = ((size - 1) | CachePage::kLineMask) + 1; int offset = (start & CachePage::kPageMask); while (!AllOnOnePage(start, size - 1)) { int bytes_to_flush = CachePage::kPageSize - offset; - FlushOnePage(start, bytes_to_flush); + FlushOnePage(i_cache, start, bytes_to_flush); start += bytes_to_flush; size -= bytes_to_flush; ASSERT_EQ(0, start & CachePage::kPageMask); offset = 0; } if (size != 0) { - FlushOnePage(start, size); + FlushOnePage(i_cache, start, size); } } -CachePage* Simulator::GetCachePage(void* page) { - v8::internal::HashMap::Entry* entry = i_cache_->Lookup(page, - ICacheHash(page), - true); +CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) { + v8::internal::HashMap::Entry* entry = i_cache->Lookup(page, + ICacheHash(page), + true); if (entry->value == NULL) { CachePage* new_page = new CachePage(); entry->value = new_page; } return reinterpret_cast<CachePage*>(entry->value); } // Flush from start up to and not including start + size. -void Simulator::FlushOnePage(intptr_t start, int size) { +void Simulator::FlushOnePage(v8::internal::HashMap* i_cache, + intptr_t start, + int size) { ASSERT(size <= CachePage::kPageSize); ASSERT(AllOnOnePage(start, size - 1)); ASSERT((start & CachePage::kLineMask) == 0); ASSERT((size & CachePage::kLineMask) == 0); void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask)); int offset = (start & CachePage::kPageMask); - CachePage* cache_page = GetCachePage(page); + CachePage* cache_page = GetCachePage(i_cache, page); char* valid_bytemap = cache_page->ValidityByte(offset); memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift); } -void Simulator::CheckICache(Instruction* instr) { +void Simulator::CheckICache(v8::internal::HashMap* i_cache, + Instruction* instr) { intptr_t address = reinterpret_cast<intptr_t>(instr); void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask)); void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask)); int offset = (address & CachePage::kPageMask); - CachePage* cache_page = GetCachePage(page); + CachePage* cache_page = GetCachePage(i_cache, page); char* cache_valid_byte = cache_page->ValidityByte(offset); bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); if (cache_hit) { // Check that the data in memory matches the contents of the I-cache. @@ -660,31 +702,22 @@ *cache_valid_byte = CachePage::LINE_VALID; } } -// Create one simulator per thread and keep it in thread local storage. -static v8::internal::Thread::LocalStorageKey simulator_key; - - -bool Simulator::initialized_ = false; - - void Simulator::Initialize() { - if (initialized_) return; - simulator_key = v8::internal::Thread::CreateThreadLocalKey(); - initialized_ = true; + if (Isolate::Current()->simulator_initialized()) return; + Isolate::Current()->set_simulator_initialized(true); ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference); } -v8::internal::HashMap* Simulator::i_cache_ = NULL; - - -Simulator::Simulator() { +Simulator::Simulator() : isolate_(Isolate::Current()) { + i_cache_ = isolate_->simulator_i_cache(); if (i_cache_ == NULL) { i_cache_ = new v8::internal::HashMap(&ICacheMatch); + isolate_->set_simulator_i_cache(i_cache_); } Initialize(); // Setup simulator support first. Some of this information is needed to // setup the architecture state. size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack @@ -746,15 +779,18 @@ public: Redirection(void* external_function, ExternalReference::Type type) : external_function_(external_function), swi_instruction_(al | (0xf*B24) | kCallRtRedirected), type_(type), - next_(list_) { - Simulator::current()-> - FlushICache(reinterpret_cast<void*>(&swi_instruction_), - Instruction::kInstrSize); - list_ = this; + next_(NULL) { + Isolate* isolate = Isolate::Current(); + next_ = isolate->simulator_redirection(); + Simulator::current(isolate)-> + FlushICache(isolate->simulator_i_cache(), + reinterpret_cast<void*>(&swi_instruction_), + Instruction::kInstrSize); + isolate->set_simulator_redirection(this); } void* address_of_swi_instruction() { return reinterpret_cast<void*>(&swi_instruction_); } @@ -762,12 +798,13 @@ void* external_function() { return external_function_; } ExternalReference::Type type() { return type_; } static Redirection* Get(void* external_function, ExternalReference::Type type) { - Redirection* current; - for (current = list_; current != NULL; current = current->next_) { + Isolate* isolate = Isolate::Current(); + Redirection* current = isolate->simulator_redirection(); + for (; current != NULL; current = current->next_) { if (current->external_function_ == external_function) return current; } return new Redirection(external_function, type); } @@ -781,33 +818,35 @@ private: void* external_function_; uint32_t swi_instruction_; ExternalReference::Type type_; Redirection* next_; - static Redirection* list_; }; -Redirection* Redirection::list_ = NULL; - - void* Simulator::RedirectExternalReference(void* external_function, ExternalReference::Type type) { Redirection* redirection = Redirection::Get(external_function, type); return redirection->address_of_swi_instruction(); } // Get the active Simulator for the current thread. -Simulator* Simulator::current() { - Initialize(); - Simulator* sim = reinterpret_cast<Simulator*>( - v8::internal::Thread::GetThreadLocal(simulator_key)); +Simulator* Simulator::current(Isolate* isolate) { + v8::internal::Isolate::PerIsolateThreadData* isolate_data = + Isolate::CurrentPerIsolateThreadData(); + if (isolate_data == NULL) { + Isolate::EnterDefaultIsolate(); + isolate_data = Isolate::CurrentPerIsolateThreadData(); + } + ASSERT(isolate_data != NULL); + + Simulator* sim = isolate_data->simulator(); if (sim == NULL) { - // TODO(146): delete the simulator object when a thread goes away. + // TODO(146): delete the simulator object when a thread/isolate goes away. sim = new Simulator(); - v8::internal::Thread::SetThreadLocal(simulator_key, sim); + isolate_data->set_simulator(sim); } return sim; } @@ -1003,11 +1042,13 @@ #else if ((addr & 3) == 0) { intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); return *ptr; } - PrintF("Unaligned read at 0x%08x, pc=%p\n", addr, instr); + PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", + addr, + reinterpret_cast<intptr_t>(instr)); UNIMPLEMENTED(); return 0; #endif } @@ -1021,11 +1062,13 @@ if ((addr & 3) == 0) { intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); *ptr = value; return; } - PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr); + PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", + addr, + reinterpret_cast<intptr_t>(instr)); UNIMPLEMENTED(); #endif } @@ -1036,11 +1079,13 @@ #else if ((addr & 1) == 0) { uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); return *ptr; } - PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr, instr); + PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", + addr, + reinterpret_cast<intptr_t>(instr)); UNIMPLEMENTED(); return 0; #endif } @@ -1070,11 +1115,13 @@ if ((addr & 1) == 0) { uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); *ptr = value; return; } - PrintF("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr, instr); + PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", + addr, + reinterpret_cast<intptr_t>(instr)); UNIMPLEMENTED(); #endif } @@ -1087,11 +1134,13 @@ if ((addr & 1) == 0) { int16_t* ptr = reinterpret_cast<int16_t*>(addr); *ptr = value; return; } - PrintF("Unaligned halfword write at 0x%08x, pc=%p\n", addr, instr); + PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", + addr, + reinterpret_cast<intptr_t>(instr)); UNIMPLEMENTED(); #endif } @@ -1521,20 +1570,25 @@ // value, which is fine because it is caller-saved. typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, - int32_t arg4); + int32_t arg4, + int32_t arg5); typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, int32_t arg1, 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); +typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0); +// This signature supports direct call to accessor getter callback. +typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, + int32_t arg1); + // Software interrupt instructions are used by the simulator to call into the // C-based V8 runtime. void Simulator::SoftwareInterrupt(Instruction* instr) { int svc = instr->SvcValue(); switch (svc) { @@ -1548,11 +1602,12 @@ int32_t arg0 = get_register(r0); int32_t arg1 = get_register(r1); int32_t arg2 = get_register(r2); int32_t arg3 = get_register(r3); int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); - int32_t arg4 = *stack_pointer; + int32_t arg4 = stack_pointer[0]; + int32_t arg5 = stack_pointer[1]; // 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_lr = get_register(lr); intptr_t external = reinterpret_cast<intptr_t>(redirection->external_function()); @@ -1570,18 +1625,16 @@ PrintF("\n"); } CHECK(stack_aligned); double result = target(arg0, arg1, arg2, arg3); SetFpResult(result); - } else if (redirection->type() == ExternalReference::DIRECT_CALL) { - SimulatorRuntimeApiCall target = - reinterpret_cast<SimulatorRuntimeApiCall>(external); + } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) { + SimulatorRuntimeDirectApiCall target = + reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); if (::v8::internal::FLAG_trace_sim || !stack_aligned) { - PrintF( - "Call to host function at %p args %08x", - FUNCTION_ADDR(target), - arg0); + PrintF("Call to host function at %p args %08x", + FUNCTION_ADDR(target), arg0); if (!stack_aligned) { PrintF(" with unaligned stack %08x\n", get_register(sp)); } PrintF("\n"); } @@ -1589,31 +1642,50 @@ v8::Handle<v8::Value> result = target(arg0); if (::v8::internal::FLAG_trace_sim) { PrintF("Returned %p\n", reinterpret_cast<void *>(*result)); } set_register(r0, (int32_t) *result); + } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) { + SimulatorRuntimeDirectGetterCall target = + reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external); + if (::v8::internal::FLAG_trace_sim || !stack_aligned) { + PrintF("Call to host function at %p args %08x %08x", + FUNCTION_ADDR(target), arg0, arg1); + if (!stack_aligned) { + PrintF(" with unaligned stack %08x\n", get_register(sp)); + } + PrintF("\n"); + } + CHECK(stack_aligned); + v8::Handle<v8::Value> result = target(arg0, arg1); + if (::v8::internal::FLAG_trace_sim) { + PrintF("Returned %p\n", reinterpret_cast<void *>(*result)); + } + set_register(r0, (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) { PrintF( - "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", + "Call to host function at %p" + "args %08x, %08x, %08x, %08x, %08x, %08x", FUNCTION_ADDR(target), arg0, arg1, arg2, arg3, - arg4); + arg4, + arg5); if (!stack_aligned) { PrintF(" with unaligned stack %08x\n", get_register(sp)); } PrintF("\n"); } CHECK(stack_aligned); - int64_t result = target(arg0, arg1, arg2, arg3, arg4); + int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5); int32_t lo_res = static_cast<int32_t>(result); int32_t hi_res = static_cast<int32_t>(result >> 32); if (::v8::internal::FLAG_trace_sim) { PrintF("Returned %08x\n", lo_res); } @@ -1623,11 +1695,11 @@ set_register(lr, saved_lr); set_pc(get_register(lr)); break; } case kBreakpoint: { - Debugger dbg(this); + ArmDebugger dbg(this); dbg.Debug(); break; } // stop uses all codes greater than 1 << 23. default: { @@ -1637,11 +1709,11 @@ IncreaseStopCounter(code); } // Stop if it is enabled, otherwise go on jumping over the stop // and the message address. if (isEnabledStop(code)) { - Debugger dbg(this); + ArmDebugger dbg(this); dbg.Stop(instr); } else { set_pc(get_pc() + 2 * Instruction::kInstrSize); } } else { @@ -1945,11 +2017,11 @@ set_pc(get_register(rm)); set_register(lr, old_pc + Instruction::kInstrSize); break; } case BKPT: { - Debugger dbg(this); + ArmDebugger dbg(this); PrintF("Simulator hit BKPT.\n"); dbg.Debug(); break; } default: @@ -2436,10 +2508,12 @@ // The Following ARMv7 VFPv instructions are currently supported. // vmov :Sn = Rt // vmov :Rt = Sn // vcvt: Dd = Sm // vcvt: Sd = Dm +// Dd = vabs(Dm) +// Dd = vneg(Dm) // Dd = vadd(Dn, Dm) // Dd = vsub(Dn, Dm) // Dd = vmul(Dn, Dm) // Dd = vdiv(Dn, Dm) // vcmp(Dd, Dm) @@ -2471,10 +2545,15 @@ } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { // vabs double dm_value = get_double_from_d_register(vm); double dd_value = fabs(dm_value); set_d_register_from_double(vd, dd_value); + } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) { + // vneg + double dm_value = get_double_from_d_register(vm); + double dd_value = -dm_value; + set_d_register_from_double(vd, dd_value); } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { DecodeVCVTBetweenDoubleAndSingle(instr); } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { DecodeVCVTBetweenFloatingPointAndInteger(instr); } else if (((instr->Opc2Value() >> 1) == 0x6) && @@ -2533,10 +2612,11 @@ } double dn_value = get_double_from_d_register(vn); double dm_value = get_double_from_d_register(vm); double dd_value = dn_value / dm_value; + div_zero_vfp_flag_ = (dm_value == 0); set_d_register_from_double(vd, dd_value); } else { UNIMPLEMENTED(); // Not used by V8. } } else { @@ -2767,18 +2847,21 @@ int temp = unsigned_integer ? static_cast<uint32_t>(val) : static_cast<int32_t>(val); inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer); + double abs_diff = + unsigned_integer ? fabs(val - static_cast<uint32_t>(temp)) + : fabs(val - temp); + + inexact_vfp_flag_ = (abs_diff != 0); + if (inv_op_vfp_flag_) { temp = VFPConversionSaturate(val, unsigned_integer); } else { switch (mode) { case RN: { - double abs_diff = - unsigned_integer ? fabs(val - static_cast<uint32_t>(temp)) - : fabs(val - temp); int val_sign = (val > 0) ? 1 : -1; if (abs_diff > 0.5) { temp += val_sign; } else if (abs_diff == 0.5) { // Round to even if exactly halfway. @@ -2922,11 +3005,11 @@ // Executes the current instruction. void Simulator::InstructionDecode(Instruction* instr) { if (v8::internal::FLAG_check_icache) { - CheckICache(instr); + CheckICache(isolate_->simulator_i_cache(), instr); } pc_modified_ = false; if (::v8::internal::FLAG_trace_sim) { disasm::NameConverter converter; disasm::Disassembler dasm(converter); @@ -3005,10 +3088,10 @@ // we reach the particular instuction count. while (program_counter != end_sim_pc) { Instruction* instr = reinterpret_cast<Instruction*>(program_counter); icount_++; if (icount_ == ::v8::internal::FLAG_stop_sim_at) { - Debugger dbg(this); + ArmDebugger dbg(this); dbg.Debug(); } else { InstructionDecode(instr); } program_counter = get_pc();