| 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;
|
|
|