summaryrefslogtreecommitdiff
path: root/deps/v8/src/arm/simulator-arm.cc
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2011-07-05 14:40:13 -0700
committerRyan Dahl <ry@tinyclouds.org>2011-07-05 14:51:29 -0700
commit149562555c9bf56457dee9a1ad70c53ed670a776 (patch)
treef6217cf3c54ddbee03f37247a3c7c75203f868fd /deps/v8/src/arm/simulator-arm.cc
parentf08720606757577d95bd09b48697c7decbf17f00 (diff)
downloadnode-new-149562555c9bf56457dee9a1ad70c53ed670a776.tar.gz
Downgrade V8 to 3.1.8.25
There are serious performance regressions both in V8 and our own legacy networking stack. Until we correct our own problems we are going back to the old V8.
Diffstat (limited to 'deps/v8/src/arm/simulator-arm.cc')
-rw-r--r--deps/v8/src/arm/simulator-arm.cc555
1 files changed, 148 insertions, 407 deletions
diff --git a/deps/v8/src/arm/simulator-arm.cc b/deps/v8/src/arm/simulator-arm.cc
index 6af535553f..f475a18b09 100644
--- a/deps/v8/src/arm/simulator-arm.cc
+++ b/deps/v8/src/arm/simulator-arm.cc
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2010 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:
@@ -49,12 +49,12 @@ namespace internal {
// Windows C Run-Time Library does not provide vsscanf.
#define SScanF sscanf // NOLINT
-// The ArmDebugger class is used by the simulator while debugging simulated ARM
+// The Debugger class is used by the simulator while debugging simulated ARM
// code.
-class ArmDebugger {
+class Debugger {
public:
- explicit ArmDebugger(Simulator* sim);
- ~ArmDebugger();
+ explicit Debugger(Simulator* sim);
+ ~Debugger();
void Stop(Instruction* instr);
void Debug();
@@ -67,7 +67,6 @@ class ArmDebugger {
Simulator* sim_;
int32_t GetRegisterValue(int regnum);
- double GetRegisterPairDoubleValue(int regnum);
double GetVFPDoubleRegisterValue(int regnum);
bool GetValue(const char* desc, int32_t* value);
bool GetVFPSingleValue(const char* desc, float* value);
@@ -84,12 +83,12 @@ class ArmDebugger {
};
-ArmDebugger::ArmDebugger(Simulator* sim) {
+Debugger::Debugger(Simulator* sim) {
sim_ = sim;
}
-ArmDebugger::~ArmDebugger() {
+Debugger::~Debugger() {
}
@@ -106,7 +105,7 @@ static void InitializeCoverage() {
}
-void ArmDebugger::Stop(Instruction* instr) {
+void Debugger::Stop(Instruction* instr) {
// Get the stop code.
uint32_t code = instr->SvcValue() & kStopCodeMask;
// Retrieve the encoded address, which comes just after this stop.
@@ -138,7 +137,7 @@ static void InitializeCoverage() {
}
-void ArmDebugger::Stop(Instruction* instr) {
+void Debugger::Stop(Instruction* instr) {
// Get the stop code.
uint32_t code = instr->SvcValue() & kStopCodeMask;
// Retrieve the encoded address, which comes just after this stop.
@@ -160,7 +159,7 @@ void ArmDebugger::Stop(Instruction* instr) {
#endif
-int32_t ArmDebugger::GetRegisterValue(int regnum) {
+int32_t Debugger::GetRegisterValue(int regnum) {
if (regnum == kPCRegister) {
return sim_->get_pc();
} else {
@@ -169,17 +168,12 @@ int32_t ArmDebugger::GetRegisterValue(int regnum) {
}
-double ArmDebugger::GetRegisterPairDoubleValue(int regnum) {
- return sim_->get_double_from_register_pair(regnum);
-}
-
-
-double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) {
+double Debugger::GetVFPDoubleRegisterValue(int regnum) {
return sim_->get_double_from_d_register(regnum);
}
-bool ArmDebugger::GetValue(const char* desc, int32_t* value) {
+bool Debugger::GetValue(const char* desc, int32_t* value) {
int regnum = Registers::Number(desc);
if (regnum != kNoRegister) {
*value = GetRegisterValue(regnum);
@@ -195,7 +189,7 @@ bool ArmDebugger::GetValue(const char* desc, int32_t* value) {
}
-bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) {
+bool Debugger::GetVFPSingleValue(const char* desc, float* value) {
bool is_double;
int regnum = VFPRegisters::Number(desc, &is_double);
if (regnum != kNoRegister && !is_double) {
@@ -206,7 +200,7 @@ bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) {
}
-bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) {
+bool Debugger::GetVFPDoubleValue(const char* desc, double* value) {
bool is_double;
int regnum = VFPRegisters::Number(desc, &is_double);
if (regnum != kNoRegister && is_double) {
@@ -217,7 +211,7 @@ bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) {
}
-bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
+bool Debugger::SetBreakpoint(Instruction* breakpc) {
// Check if a breakpoint can be set. If not return without any side-effects.
if (sim_->break_pc_ != NULL) {
return false;
@@ -232,7 +226,7 @@ bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
}
-bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
+bool Debugger::DeleteBreakpoint(Instruction* breakpc) {
if (sim_->break_pc_ != NULL) {
sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
}
@@ -243,21 +237,21 @@ bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
}
-void ArmDebugger::UndoBreakpoints() {
+void Debugger::UndoBreakpoints() {
if (sim_->break_pc_ != NULL) {
sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
}
}
-void ArmDebugger::RedoBreakpoints() {
+void Debugger::RedoBreakpoints() {
if (sim_->break_pc_ != NULL) {
sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
}
}
-void ArmDebugger::Debug() {
+void Debugger::Debug() {
intptr_t last_pc = -1;
bool done = false;
@@ -311,45 +305,27 @@ void ArmDebugger::Debug() {
// Leave the debugger shell.
done = true;
} else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
- if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) {
+ if (argc == 2) {
int32_t value;
float svalue;
double dvalue;
if (strcmp(arg1, "all") == 0) {
for (int i = 0; i < kNumRegisters; i++) {
value = GetRegisterValue(i);
- PrintF("%3s: 0x%08x %10d", Registers::Name(i), value, value);
- if ((argc == 3 && strcmp(arg2, "fp") == 0) &&
- i < 8 &&
- (i % 2) == 0) {
- dvalue = GetRegisterPairDoubleValue(i);
- PrintF(" (%f)\n", dvalue);
- } else {
- PrintF("\n");
- }
+ PrintF("%3s: 0x%08x %10d\n", Registers::Name(i), value, value);
}
for (int i = 0; i < kNumVFPDoubleRegisters; i++) {
dvalue = GetVFPDoubleRegisterValue(i);
- 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));
+ PrintF("%3s: %f\n",
+ VFPRegisters::Name(i, true), dvalue);
}
} else {
if (GetValue(arg1, &value)) {
PrintF("%s: 0x%08x %d \n", arg1, value, value);
} else if (GetVFPSingleValue(arg1, &svalue)) {
- uint32_t as_word = BitCast<uint32_t>(svalue);
- PrintF("%s: %f 0x%08x\n", arg1, svalue, as_word);
+ PrintF("%s: %f \n", arg1, svalue);
} else if (GetVFPDoubleValue(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));
+ PrintF("%s: %f \n", arg1, dvalue);
} else {
PrintF("%s unrecognized\n", arg1);
}
@@ -404,24 +380,11 @@ void ArmDebugger::Debug() {
end = cur + words;
while (cur < end) {
- PrintF(" 0x%08x: 0x%08x %10d",
+ PrintF(" 0x%08x: 0x%08x %10d\n",
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 || strcmp(cmd, "di") == 0) {
+ } else if (strcmp(cmd, "disasm") == 0) {
disasm::NameConverter converter;
disasm::Disassembler dasm(converter);
// use a reasonably large buffer
@@ -435,23 +398,11 @@ void ArmDebugger::Debug() {
cur = reinterpret_cast<byte*>(sim_->get_pc());
end = cur + (10 * Instruction::kInstrSize);
} else if (argc == 2) {
- 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);
- }
+ 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;
@@ -564,7 +515,6 @@ void ArmDebugger::Debug() {
PrintF("print <register>\n");
PrintF(" print register content (alias 'p')\n");
PrintF(" use register name 'all' to print all registers\n");
- PrintF(" add argument 'fp' to print register pair double values\n");
PrintF("printobject <register>\n");
PrintF(" print an object from a register (alias 'po')\n");
PrintF("flags\n");
@@ -574,10 +524,8 @@ void ArmDebugger::Debug() {
PrintF("mem <address> [<words>]\n");
PrintF(" dump memory content, default dump 10 words)\n");
PrintF("disasm [<instructions>]\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("disasm [[<address>] <instructions>]\n");
+ PrintF(" disassemble code, default is 10 instructions from pc\n");
PrintF("gdb\n");
PrintF(" enter gdb\n");
PrintF("break <address>\n");
@@ -591,11 +539,11 @@ void ArmDebugger::Debug() {
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 ArmDebugger.\n");
+ PrintF(" stop and and give control to the Debugger.\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");
@@ -645,9 +593,7 @@ static bool AllOnOnePage(uintptr_t start, int size) {
}
-void Simulator::FlushICache(v8::internal::HashMap* i_cache,
- void* start_addr,
- size_t size) {
+void Simulator::FlushICache(void* start_addr, size_t size) {
intptr_t start = reinterpret_cast<intptr_t>(start_addr);
int intra_line = (start & CachePage::kLineMask);
start -= intra_line;
@@ -656,22 +602,22 @@ void Simulator::FlushICache(v8::internal::HashMap* i_cache,
int offset = (start & CachePage::kPageMask);
while (!AllOnOnePage(start, size - 1)) {
int bytes_to_flush = CachePage::kPageSize - offset;
- FlushOnePage(i_cache, start, bytes_to_flush);
+ FlushOnePage(start, bytes_to_flush);
start += bytes_to_flush;
size -= bytes_to_flush;
ASSERT_EQ(0, start & CachePage::kPageMask);
offset = 0;
}
if (size != 0) {
- FlushOnePage(i_cache, start, size);
+ FlushOnePage(start, size);
}
}
-CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
- v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
- ICacheHash(page),
- true);
+CachePage* Simulator::GetCachePage(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;
@@ -681,28 +627,25 @@ CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
// Flush from start up to and not including start + size.
-void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
- intptr_t start,
- int size) {
+void Simulator::FlushOnePage(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(i_cache, page);
+ CachePage* cache_page = GetCachePage(page);
char* valid_bytemap = cache_page->ValidityByte(offset);
memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
}
-void Simulator::CheckICache(v8::internal::HashMap* i_cache,
- Instruction* instr) {
+void Simulator::CheckICache(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(i_cache, page);
+ CachePage* cache_page = GetCachePage(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);
@@ -719,21 +662,29 @@ void Simulator::CheckICache(v8::internal::HashMap* i_cache,
}
-void Simulator::Initialize(Isolate* isolate) {
- if (isolate->simulator_initialized()) return;
- isolate->set_simulator_initialized(true);
- ::v8::internal::ExternalReference::set_redirector(isolate,
- &RedirectExternalReference);
+// 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;
+ ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference);
}
-Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
- i_cache_ = isolate_->simulator_i_cache();
+v8::internal::HashMap* Simulator::i_cache_ = NULL;
+
+
+Simulator::Simulator() {
if (i_cache_ == NULL) {
i_cache_ = new v8::internal::HashMap(&ICacheMatch);
- isolate_->set_simulator_i_cache(i_cache_);
}
- Initialize(isolate);
+ 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
@@ -797,14 +748,11 @@ class Redirection {
: external_function_(external_function),
swi_instruction_(al | (0xf*B24) | kCallRtRedirected),
type_(type),
- 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);
+ next_(list_) {
+ Simulator::current()->
+ FlushICache(reinterpret_cast<void*>(&swi_instruction_),
+ Instruction::kInstrSize);
+ list_ = this;
}
void* address_of_swi_instruction() {
@@ -816,9 +764,8 @@ class Redirection {
static Redirection* Get(void* external_function,
ExternalReference::Type type) {
- Isolate* isolate = Isolate::Current();
- Redirection* current = isolate->simulator_redirection();
- for (; current != NULL; current = current->next_) {
+ Redirection* current;
+ for (current = list_; current != NULL; current = current->next_) {
if (current->external_function_ == external_function) return current;
}
return new Redirection(external_function, type);
@@ -836,9 +783,13 @@ class Redirection {
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);
@@ -847,16 +798,14 @@ void* Simulator::RedirectExternalReference(void* external_function,
// Get the active Simulator for the current thread.
-Simulator* Simulator::current(Isolate* isolate) {
- v8::internal::Isolate::PerIsolateThreadData* isolate_data =
- isolate->FindOrAllocatePerThreadDataForThisThread();
- ASSERT(isolate_data != NULL);
-
- Simulator* sim = isolate_data->simulator();
+Simulator* Simulator::current() {
+ Initialize();
+ Simulator* sim = reinterpret_cast<Simulator*>(
+ v8::internal::Thread::GetThreadLocal(simulator_key));
if (sim == NULL) {
- // TODO(146): delete the simulator object when a thread/isolate goes away.
- sim = new Simulator(isolate);
- isolate_data->set_simulator(sim);
+ // TODO(146): delete the simulator object when a thread goes away.
+ sim = new Simulator();
+ v8::internal::Thread::SetThreadLocal(simulator_key, sim);
}
return sim;
}
@@ -885,19 +834,6 @@ int32_t Simulator::get_register(int reg) const {
}
-double Simulator::get_double_from_register_pair(int reg) {
- ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
-
- double dm_val = 0.0;
- // Read the bits from the unsigned integer register_[] array
- // into the double precision floating point value and return it.
- char buffer[2 * sizeof(vfp_register[0])];
- memcpy(buffer, &registers_[reg], 2 * sizeof(registers_[0]));
- memcpy(&dm_val, buffer, 2 * sizeof(registers_[0]));
- return(dm_val);
-}
-
-
void Simulator::set_dw_register(int dreg, const int* dbl) {
ASSERT((dreg >= 0) && (dreg < num_d_registers));
registers_[dreg] = dbl[0];
@@ -963,7 +899,12 @@ void Simulator::set_d_register_from_double(int dreg, const double& dbl) {
// 2*sreg and 2*sreg+1.
char buffer[2 * sizeof(vfp_register[0])];
memcpy(buffer, &dbl, 2 * sizeof(vfp_register[0]));
+#ifndef BIG_ENDIAN_FLOATING_POINT
memcpy(&vfp_register[dreg * 2], buffer, 2 * sizeof(vfp_register[0]));
+#else
+ memcpy(&vfp_register[dreg * 2], &buffer[4], sizeof(vfp_register[0]));
+ memcpy(&vfp_register[dreg * 2 + 1], &buffer[0], sizeof(vfp_register[0]));
+#endif
}
@@ -1000,80 +941,37 @@ double Simulator::get_double_from_d_register(int dreg) {
// Read the bits from the unsigned integer vfp_register[] array
// into the double precision floating point value and return it.
char buffer[2 * sizeof(vfp_register[0])];
+#ifdef BIG_ENDIAN_FLOATING_POINT
+ memcpy(&buffer[0], &vfp_register[2 * dreg + 1], sizeof(vfp_register[0]));
+ memcpy(&buffer[4], &vfp_register[2 * dreg], sizeof(vfp_register[0]));
+#else
memcpy(buffer, &vfp_register[2 * dreg], 2 * sizeof(vfp_register[0]));
+#endif
memcpy(&dm_val, buffer, 2 * sizeof(vfp_register[0]));
return(dm_val);
}
-// For use in calls that take two double values, constructed either
-// from r0-r3 or d0 and d1.
+// For use in calls that take two double values, constructed from r0, r1, r2
+// and r3.
void Simulator::GetFpArgs(double* x, double* y) {
- if (use_eabi_hardfloat()) {
- *x = vfp_register[0];
- *y = vfp_register[1];
- } else {
- // We use a char buffer to get around the strict-aliasing rules which
- // otherwise allow the compiler to optimize away the copy.
- char buffer[sizeof(*x)];
- // Registers 0 and 1 -> x.
- memcpy(buffer, registers_, sizeof(*x));
- memcpy(x, buffer, sizeof(*x));
- // Registers 2 and 3 -> y.
- memcpy(buffer, registers_ + 2, sizeof(*y));
- memcpy(y, buffer, sizeof(*y));
- }
-}
-
-// For use in calls that take one double value, constructed either
-// from r0 and r1 or d0.
-void Simulator::GetFpArgs(double* x) {
- if (use_eabi_hardfloat()) {
- *x = vfp_register[0];
- } else {
- // We use a char buffer to get around the strict-aliasing rules which
- // otherwise allow the compiler to optimize away the copy.
- char buffer[sizeof(*x)];
- // Registers 0 and 1 -> x.
- memcpy(buffer, registers_, sizeof(*x));
- memcpy(x, buffer, sizeof(*x));
- }
-}
-
-
-// For use in calls that take one double value constructed either
-// from r0 and r1 or d0 and one integer value.
-void Simulator::GetFpArgs(double* x, int32_t* y) {
- if (use_eabi_hardfloat()) {
- *x = vfp_register[0];
- *y = registers_[1];
- } else {
- // We use a char buffer to get around the strict-aliasing rules which
- // otherwise allow the compiler to optimize away the copy.
- char buffer[sizeof(*x)];
- // Registers 0 and 1 -> x.
- memcpy(buffer, registers_, sizeof(*x));
- memcpy(x, buffer, sizeof(*x));
- // Register 2 -> y.
- memcpy(buffer, registers_ + 2, sizeof(*y));
- memcpy(y, buffer, sizeof(*y));
- }
+ // We use a char buffer to get around the strict-aliasing rules which
+ // otherwise allow the compiler to optimize away the copy.
+ char buffer[2 * sizeof(registers_[0])];
+ // Registers 0 and 1 -> x.
+ memcpy(buffer, registers_, sizeof(buffer));
+ memcpy(x, buffer, sizeof(buffer));
+ // Registers 2 and 3 -> y.
+ memcpy(buffer, registers_ + 2, sizeof(buffer));
+ memcpy(y, buffer, sizeof(buffer));
}
-// The return value is either in r0/r1 or d0.
void Simulator::SetFpResult(const double& result) {
- if (use_eabi_hardfloat()) {
- char buffer[2 * sizeof(vfp_register[0])];
- memcpy(buffer, &result, sizeof(buffer));
- // Copy result to d0.
- memcpy(vfp_register, buffer, sizeof(buffer));
- } else {
- char buffer[2 * sizeof(registers_[0])];
- memcpy(buffer, &result, sizeof(buffer));
- // Copy result to r0 and r1.
- memcpy(registers_, buffer, sizeof(buffer));
- }
+ char buffer[2 * sizeof(registers_[0])];
+ memcpy(buffer, &result, sizeof(buffer));
+ // result -> registers 0 and 1.
+ memcpy(registers_, buffer, sizeof(buffer));
}
@@ -1327,13 +1225,12 @@ void Simulator::SetVFlag(bool val) {
// Calculate C flag value for additions.
-bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
+bool Simulator::CarryFrom(int32_t left, int32_t right) {
uint32_t uleft = static_cast<uint32_t>(left);
uint32_t uright = static_cast<uint32_t>(right);
uint32_t urest = 0xffffffffU - uleft;
- return (uright > urest) ||
- (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
+ return (uright > urest);
}
@@ -1568,34 +1465,36 @@ static int count_bits(int bit_vector) {
}
-void Simulator::ProcessPUW(Instruction* instr,
- int num_regs,
- int reg_size,
- intptr_t* start_address,
- intptr_t* end_address) {
+// Addressing Mode 4 - Load and Store Multiple
+void Simulator::HandleRList(Instruction* instr, bool load) {
int rn = instr->RnValue();
int32_t rn_val = get_register(rn);
+ int rlist = instr->RlistValue();
+ int num_regs = count_bits(rlist);
+
+ intptr_t start_address = 0;
+ intptr_t end_address = 0;
switch (instr->PUField()) {
case da_x: {
UNIMPLEMENTED();
break;
}
case ia_x: {
- *start_address = rn_val;
- *end_address = rn_val + (num_regs * reg_size) - reg_size;
- rn_val = rn_val + (num_regs * reg_size);
+ start_address = rn_val;
+ end_address = rn_val + (num_regs * 4) - 4;
+ rn_val = rn_val + (num_regs * 4);
break;
}
case db_x: {
- *start_address = rn_val - (num_regs * reg_size);
- *end_address = rn_val - reg_size;
- rn_val = *start_address;
+ start_address = rn_val - (num_regs * 4);
+ end_address = rn_val - 4;
+ rn_val = start_address;
break;
}
case ib_x: {
- *start_address = rn_val + reg_size;
- *end_address = rn_val + (num_regs * reg_size);
- rn_val = *end_address;
+ start_address = rn_val + 4;
+ end_address = rn_val + (num_regs * 4);
+ rn_val = end_address;
break;
}
default: {
@@ -1606,17 +1505,6 @@ void Simulator::ProcessPUW(Instruction* instr,
if (instr->HasW()) {
set_register(rn, rn_val);
}
-}
-
-// Addressing Mode 4 - Load and Store Multiple
-void Simulator::HandleRList(Instruction* instr, bool load) {
- int rlist = instr->RlistValue();
- int num_regs = count_bits(rlist);
-
- intptr_t start_address = 0;
- intptr_t end_address = 0;
- ProcessPUW(instr, num_regs, kPointerSize, &start_address, &end_address);
-
intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
int reg = 0;
while (rlist != 0) {
@@ -1635,57 +1523,6 @@ void Simulator::HandleRList(Instruction* instr, bool load) {
}
-// Addressing Mode 6 - Load and Store Multiple Coprocessor registers.
-void Simulator::HandleVList(Instruction* instr) {
- VFPRegPrecision precision =
- (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision;
- int operand_size = (precision == kSinglePrecision) ? 4 : 8;
-
- bool load = (instr->VLValue() == 0x1);
-
- int vd;
- int num_regs;
- vd = instr->VFPDRegValue(precision);
- if (precision == kSinglePrecision) {
- num_regs = instr->Immed8Value();
- } else {
- num_regs = instr->Immed8Value() / 2;
- }
-
- intptr_t start_address = 0;
- intptr_t end_address = 0;
- ProcessPUW(instr, num_regs, operand_size, &start_address, &end_address);
-
- intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
- for (int reg = vd; reg < vd + num_regs; reg++) {
- if (precision == kSinglePrecision) {
- if (load) {
- set_s_register_from_sinteger(
- reg, ReadW(reinterpret_cast<int32_t>(address), instr));
- } else {
- WriteW(reinterpret_cast<int32_t>(address),
- get_sinteger_from_s_register(reg), instr);
- }
- address += 1;
- } else {
- if (load) {
- set_s_register_from_sinteger(
- 2 * reg, ReadW(reinterpret_cast<int32_t>(address), instr));
- set_s_register_from_sinteger(
- 2 * reg + 1, ReadW(reinterpret_cast<int32_t>(address + 1), instr));
- } else {
- WriteW(reinterpret_cast<int32_t>(address),
- get_sinteger_from_s_register(2 * reg), instr);
- WriteW(reinterpret_cast<int32_t>(address + 1),
- get_sinteger_from_s_register(2 * reg + 1), instr);
- }
- address += 2;
- }
- }
- ASSERT(reinterpret_cast<intptr_t>(address) - operand_size == end_address);
-}
-
-
// Calls into the V8 runtime are based on this very simple interface.
// Note: To be able to return two values from some calls the code in runtime.cc
// uses the ObjectPair which is essentially two 32-bit values stuffed into a
@@ -1696,8 +1533,7 @@ typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
int32_t arg1,
int32_t arg2,
int32_t arg3,
- int32_t arg4,
- int32_t arg5);
+ int32_t arg4);
typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
int32_t arg1,
int32_t arg2,
@@ -1728,94 +1564,28 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
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[0];
- int32_t arg5 = stack_pointer[1];
- 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);
- if (use_eabi_hardfloat()) {
- // With the hard floating point calling convention, double
- // arguments are passed in VFP registers. Fetch the arguments
- // from there and call the builtin using soft floating point
- // convention.
- switch (redirection->type()) {
- case ExternalReference::BUILTIN_FP_FP_CALL:
- case ExternalReference::BUILTIN_COMPARE_CALL:
- arg0 = vfp_register[0];
- arg1 = vfp_register[1];
- arg2 = vfp_register[2];
- arg3 = vfp_register[3];
- break;
- case ExternalReference::BUILTIN_FP_CALL:
- arg0 = vfp_register[0];
- arg1 = vfp_register[1];
- break;
- case ExternalReference::BUILTIN_FP_INT_CALL:
- arg0 = vfp_register[0];
- arg1 = vfp_register[1];
- arg2 = get_register(0);
- break;
- default:
- break;
- }
- }
+ int32_t arg4 = *stack_pointer;
// 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());
- if (fp_call) {
+ if (redirection->type() == ExternalReference::FP_RETURN_CALL) {
+ SimulatorRuntimeFPCall target =
+ reinterpret_cast<SimulatorRuntimeFPCall>(external);
if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
- SimulatorRuntimeFPCall target =
- reinterpret_cast<SimulatorRuntimeFPCall>(external);
- double dval0, dval1;
- int32_t ival;
- switch (redirection->type()) {
- case ExternalReference::BUILTIN_FP_FP_CALL:
- case ExternalReference::BUILTIN_COMPARE_CALL:
- GetFpArgs(&dval0, &dval1);
- PrintF("Call to host function at %p with args %f, %f",
- FUNCTION_ADDR(target), dval0, dval1);
- break;
- case ExternalReference::BUILTIN_FP_CALL:
- GetFpArgs(&dval0);
- PrintF("Call to host function at %p with arg %f",
- FUNCTION_ADDR(target), dval0);
- break;
- case ExternalReference::BUILTIN_FP_INT_CALL:
- GetFpArgs(&dval0, &ival);
- PrintF("Call to host function at %p with args %f, %d",
- FUNCTION_ADDR(target), dval0, ival);
- break;
- default:
- UNREACHABLE();
- break;
- }
+ double x, y;
+ GetFpArgs(&x, &y);
+ PrintF("Call to host function at %p with args %f, %f",
+ FUNCTION_ADDR(target), x, y);
if (!stack_aligned) {
PrintF(" with unaligned stack %08x\n", get_register(sp));
}
PrintF("\n");
}
CHECK(stack_aligned);
- if (redirection->type() != ExternalReference::BUILTIN_COMPARE_CALL) {
- SimulatorRuntimeFPCall target =
- reinterpret_cast<SimulatorRuntimeFPCall>(external);
- double result = target(arg0, arg1, arg2, arg3);
- SetFpResult(result);
- } else {
- SimulatorRuntimeCall target =
- reinterpret_cast<SimulatorRuntimeCall>(external);
- 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);
- }
- set_register(r0, lo_res);
- set_register(r1, hi_res);
- }
+ double result = target(arg0, arg1, arg2, arg3);
+ SetFpResult(result);
} else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
SimulatorRuntimeDirectApiCall target =
reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
@@ -1857,22 +1627,20 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
reinterpret_cast<SimulatorRuntimeCall>(external);
if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
PrintF(
- "Call to host function at %p"
- "args %08x, %08x, %08x, %08x, %08x, %08x",
+ "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc",
FUNCTION_ADDR(target),
arg0,
arg1,
arg2,
arg3,
- arg4,
- arg5);
+ arg4);
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, arg5);
+ int64_t result = target(arg0, arg1, arg2, arg3, arg4);
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) {
@@ -1886,7 +1654,7 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
break;
}
case kBreakpoint: {
- ArmDebugger dbg(this);
+ Debugger dbg(this);
dbg.Debug();
break;
}
@@ -1900,7 +1668,7 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
// Stop if it is enabled, otherwise go on jumping over the stop
// and the message address.
if (isEnabledStop(code)) {
- ArmDebugger dbg(this);
+ Debugger dbg(this);
dbg.Stop(instr);
} else {
set_pc(get_pc() + 2 * Instruction::kInstrSize);
@@ -2208,7 +1976,7 @@ void Simulator::DecodeType01(Instruction* instr) {
break;
}
case BKPT: {
- ArmDebugger dbg(this);
+ Debugger dbg(this);
PrintF("Simulator hit BKPT.\n");
dbg.Debug();
break;
@@ -2320,15 +2088,8 @@ void Simulator::DecodeType01(Instruction* instr) {
}
case ADC: {
- // Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
- // Format(instr, "adc'cond's 'rd, 'rn, 'imm");
- alu_out = rn_val + shifter_operand + GetCarry();
- set_register(rd, alu_out);
- if (instr->HasS()) {
- SetNZFlags(alu_out);
- SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
- SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
- }
+ Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
+ Format(instr, "adc'cond's 'rd, 'rn, 'imm");
break;
}
@@ -2706,8 +2467,6 @@ void Simulator::DecodeType7(Instruction* instr) {
// 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)
@@ -2743,11 +2502,6 @@ void Simulator::DecodeTypeVFP(Instruction* instr) {
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)) {
@@ -3141,17 +2895,9 @@ void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
}
break;
}
- case 0x4:
- case 0x5:
- case 0x6:
- case 0x7:
- case 0x9:
- case 0xB:
- // Load/store multiple single from memory: vldm/vstm.
- HandleVList(instr);
- break;
default:
UNIMPLEMENTED(); // Not used by V8.
+ break;
}
} else if (instr->CoprocessorValue() == 0xB) {
switch (instr->OpcodeValue()) {
@@ -3198,14 +2944,9 @@ void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
}
break;
}
- case 0x4:
- case 0x5:
- case 0x9:
- // Load/store multiple double from memory: vldm/vstm.
- HandleVList(instr);
- break;
default:
UNIMPLEMENTED(); // Not used by V8.
+ break;
}
} else {
UNIMPLEMENTED(); // Not used by V8.
@@ -3216,7 +2957,7 @@ void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
// Executes the current instruction.
void Simulator::InstructionDecode(Instruction* instr) {
if (v8::internal::FLAG_check_icache) {
- CheckICache(isolate_->simulator_i_cache(), instr);
+ CheckICache(instr);
}
pc_modified_ = false;
if (::v8::internal::FLAG_trace_sim) {
@@ -3299,7 +3040,7 @@ void Simulator::Execute() {
Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
icount_++;
if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
- ArmDebugger dbg(this);
+ Debugger dbg(this);
dbg.Debug();
} else {
InstructionDecode(instr);