Index: src/simulator-arm.cc |
=================================================================== |
--- src/simulator-arm.cc (revision 1707) |
+++ src/simulator-arm.cc (working copy) |
@@ -90,12 +90,44 @@ |
} |
+ |
+#ifdef ARM_GENERATED_CODE_COVERAGE |
+static FILE* coverage_log = NULL; |
+ |
+ |
+static void InitializeCoverage() { |
+ char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); |
+ if (file_name != NULL) { |
+ coverage_log = fopen(file_name, "aw+"); |
+ } |
+} |
+ |
+ |
void Debugger::Stop(Instr* instr) { |
+ char* str = reinterpret_cast<char*>(instr->InstructionBits() & 0x0fffffff); |
+ if (strlen(str) > 0) { |
+ if (coverage_log != NULL) { |
+ fprintf(coverage_log, "Simulator hit %s\n", str); |
+ fflush(coverage_log); |
+ } |
+ instr->SetInstructionBits(0xe1a00000); // Overwrite with nop. |
+ } |
+ sim_->set_pc(sim_->get_pc() + Instr::kInstrSize); |
+} |
+ |
+#else // ndef ARM_GENERATED_CODE_COVERAGE |
+ |
+static void InitializeCoverage() { |
+} |
+ |
+ |
+void Debugger::Stop(Instr* instr) { |
const char* str = (const char*)(instr->InstructionBits() & 0x0fffffff); |
PrintF("Simulator hit %s\n", str); |
sim_->set_pc(sim_->get_pc() + Instr::kInstrSize); |
Debug(); |
} |
+#endif |
static const char* reg_names[] = { "r0", "r1", "r2", "r3", |
@@ -375,6 +407,7 @@ |
// access violation if the simulator ever tries to execute it. |
registers_[pc] = bad_lr; |
registers_[lr] = bad_lr; |
+ InitializeCoverage(); |
} |
@@ -427,6 +460,37 @@ |
} |
+// For use in calls that take two double values, constructed from r0, r1, r2 |
+// and r3. |
+void Simulator::GetFpArgs(double* x, double* 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)); |
+} |
+ |
+ |
+void Simulator::SetFpResult(const double& result) { |
+ char buffer[2 * sizeof(registers_[0])]; |
+ memcpy(buffer, &result, sizeof(buffer)); |
+ // result -> registers 0 and 1. |
+ memcpy(registers_, buffer, sizeof(buffer)); |
+} |
+ |
+ |
+void Simulator::TrashCallerSaveRegisters() { |
+ // We don't trash the registers with the return value. |
+ registers_[2] = 0x50Bad4U; |
+ registers_[3] = 0x50Bad4U; |
+ registers_[12] = 0x50Bad4U; |
+} |
+ |
+ |
// The ARM cannot do unaligned reads and writes. On some ARM platforms an |
// interrupt is caused. On others it does a funky rotation thing. For now we |
// simply disallow unaligned reads, but at some point we may want to move to |
@@ -862,7 +926,8 @@ |
// Software interrupt instructions are used by the simulator to call into the |
// C-based V8 runtime. |
void Simulator::SoftwareInterrupt(Instr* instr) { |
- switch (instr->SwiField()) { |
+ int swi = instr->SwiField(); |
+ switch (swi) { |
case call_rt_r5: { |
SimulatorRuntimeCall target = |
reinterpret_cast<SimulatorRuntimeCall>(get_register(r5)); |
@@ -894,6 +959,30 @@ |
dbg.Debug(); |
break; |
} |
+ { |
+ double x, y, z; |
+ case simulator_fp_add: |
+ GetFpArgs(&x, &y); |
+ z = x + y; |
+ SetFpResult(z); |
+ TrashCallerSaveRegisters(); |
+ set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); |
+ break; |
+ case simulator_fp_sub: |
+ GetFpArgs(&x, &y); |
+ z = x - y; |
+ SetFpResult(z); |
+ TrashCallerSaveRegisters(); |
+ set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); |
+ break; |
+ case simulator_fp_mul: |
+ GetFpArgs(&x, &y); |
+ z = x * y; |
+ SetFpResult(z); |
+ TrashCallerSaveRegisters(); |
+ set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); |
+ break; |
+ } |
default: { |
UNREACHABLE(); |
break; |