Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Unified Diff: src/arm/simulator-arm.cc

Issue 119036: * Modify simulator and ARM code generator to avoid swi... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/arm/simulator-arm.cc
===================================================================
--- src/arm/simulator-arm.cc (revision 2053)
+++ src/arm/simulator-arm.cc (working copy)
@@ -1,4 +1,4 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
+// Copyright 2009 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:
@@ -30,6 +30,7 @@
#include "v8.h"
#include "disasm.h"
+#include "assembler.h"
#include "arm/constants-arm.h"
#include "arm/simulator-arm.h"
@@ -380,7 +381,18 @@
}
+bool Simulator::initialized_ = false;
+
+
+void Simulator::Initialize() {
+ if (initialized_) return;
+ initialized_ = true;
+ ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference);
+}
+
+
Simulator::Simulator() {
+ ASSERT(initialized_);
// 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
@@ -412,10 +424,69 @@
}
+// When the generated code calls an external reference we need to catch that in
+// the simulator. The external reference will be a function compiled for the
+// host architecture. We need to call that function instead of trying to
+// execute it with the simulator. We do that by redirecting the external
+// reference to a swi (software-interrupt) instruction that is handled by
+// the simulator. We write the original destination of the jump just after the
iposva 2009/06/08 21:48:41 Please change the comment to say "We write the ori
+// swi instruction so the simulator knows what to call.
+class Redirection {
+ public:
+ Redirection(void* external_function, bool fp_return)
+ : external_function_(external_function),
+ swi_instruction_((AL << 28) | (0xf << 24) | call_rt_redirected),
+ fp_return_(fp_return),
+ next_(list_) {
+ list_ = this;
+ }
+
+ void* address_of_swi_instruction() {
+ return reinterpret_cast<void*>(&swi_instruction_);
+ }
+
+ void* external_function() { return external_function_; }
+ bool fp_return() { return fp_return_; }
+
+ static Redirection* Get(void* external_function, bool fp_return) {
+ Redirection* current;
+ for (current = list_; current != NULL; current = current->next_) {
+ if (current->external_function_ == external_function) return current;
+ }
+ return new Redirection(external_function, fp_return);
+ }
+
+ static Redirection* FromSwiInstruction(Instr* swi_instruction) {
+ char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
+ char* addr_of_redirection =
+ addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
+ return reinterpret_cast<Redirection*>(addr_of_redirection);
+ }
+
+ private:
+ void* external_function_;
+ uint32_t swi_instruction_;
+ bool fp_return_;
+ Redirection* next_;
+ static Redirection* list_;
+};
+
+
+Redirection* Redirection::list_ = NULL;
+
+
+void* Simulator::RedirectExternalReference(void* external_function,
+ bool fp_return) {
+ Redirection* redirection = Redirection::Get(external_function, fp_return);
+ return redirection->address_of_swi_instruction();
+}
+
+
// Create one simulator per thread and keep it in thread local storage.
static v8::internal::Thread::LocalStorageKey simulator_key =
v8::internal::Thread::CreateThreadLocalKey();
iposva 2009/06/08 21:48:41 Please move this static initializer into the Initi
+
// Get the active Simulator for the current thread.
Simulator* Simulator::current() {
Simulator* sim = reinterpret_cast<Simulator*>(
@@ -921,7 +992,14 @@
// 64-bit value. With the code below we assume that all runtime calls return
// 64 bits of result. If they don't, the r1 result register contains a bogus
// value, which is fine because it is caller-saved.
-typedef int64_t (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1);
+typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
+ int32_t arg1,
+ int32_t arg2,
+ int32_t arg3);
+typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
+ int32_t arg1,
+ int32_t arg2,
+ int32_t arg3);
// Software interrupt instructions are used by the simulator to call into the
@@ -929,61 +1007,58 @@
void Simulator::SoftwareInterrupt(Instr* instr) {
int swi = instr->SwiField();
switch (swi) {
- case call_rt_r5: {
- SimulatorRuntimeCall target =
- reinterpret_cast<SimulatorRuntimeCall>(get_register(r5));
- intptr_t arg0 = get_register(r0);
- intptr_t arg1 = get_register(r1);
- int64_t result = target(arg0, arg1);
- int32_t lo_res = static_cast<int32_t>(result);
- int32_t hi_res = static_cast<int32_t>(result >> 32);
- set_register(r0, lo_res);
- set_register(r1, hi_res);
- set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
+ case call_rt_redirected: {
+ Redirection* redirection = Redirection::FromSwiInstruction(instr);
+ int32_t arg0 = get_register(r0);
+ int32_t arg1 = get_register(r1);
+ int32_t arg2 = get_register(r2);
+ int32_t arg3 = get_register(r3);
+ // 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);
+ if (redirection->fp_return()) {
+ intptr_t external =
+ reinterpret_cast<intptr_t>(redirection->external_function());
+ SimulatorRuntimeFPCall target =
+ reinterpret_cast<SimulatorRuntimeFPCall>(external);
+ if (::v8::internal::FLAG_trace_sim) {
+ double x, y;
+ GetFpArgs(&x, &y);
+ PrintF("Call to host function at %p with args %f, %f\n",
+ FUNCTION_ADDR(target), x, y);
+ }
+ double result = target(arg0, arg1, arg2, arg3);
+ SetFpResult(result);
+ } else {
+ intptr_t external =
+ reinterpret_cast<int32_t>(redirection->external_function());
+ SimulatorRuntimeCall target =
+ reinterpret_cast<SimulatorRuntimeCall>(external);
+ if (::v8::internal::FLAG_trace_sim) {
+ PrintF(
+ "Call to host function at %p with args %08x, %08x, %08x, %08x\n",
+ FUNCTION_ADDR(target),
+ arg0,
+ arg1,
+ arg2,
+ arg3);
+ }
+ int64_t result = target(arg0, arg1, arg2, arg3);
+ int32_t lo_res = static_cast<int32_t>(result);
+ int32_t hi_res = static_cast<int32_t>(result >> 32);
+ set_register(r0, lo_res);
+ set_register(r1, hi_res);
+ set_register(r0, result);
iposva 2009/06/08 21:48:41 Isn't the second write to r0 redundant here? Stran
Erik Corry 2009/06/09 09:27:00 Fixed.
+ }
+ set_register(lr, saved_lr);
+ set_pc(get_register(lr));
break;
}
- case call_rt_r2: {
- SimulatorRuntimeCall target =
- reinterpret_cast<SimulatorRuntimeCall>(get_register(r2));
- intptr_t arg0 = get_register(r0);
- intptr_t arg1 = get_register(r1);
- int64_t result = target(arg0, arg1);
- int32_t lo_res = static_cast<int32_t>(result);
- int32_t hi_res = static_cast<int32_t>(result >> 32);
- set_register(r0, lo_res);
- set_register(r1, hi_res);
- set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
- break;
- }
case break_point: {
Debugger dbg(this);
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;

Powered by Google App Engine
This is Rietveld 408576698