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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2008 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
(...skipping 11 matching lines...) Expand all
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include <stdlib.h> 28 #include <stdlib.h>
29 29
30 #include "v8.h" 30 #include "v8.h"
31 31
32 #include "disasm.h" 32 #include "disasm.h"
33 #include "assembler.h"
33 #include "arm/constants-arm.h" 34 #include "arm/constants-arm.h"
34 #include "arm/simulator-arm.h" 35 #include "arm/simulator-arm.h"
35 36
36 #if !defined(__arm__) 37 #if !defined(__arm__)
37 38
38 // Only build the simulator if not compiling for real ARM hardware. 39 // Only build the simulator if not compiling for real ARM hardware.
39 namespace assembler { 40 namespace assembler {
40 namespace arm { 41 namespace arm {
41 42
42 using ::v8::internal::Object; 43 using ::v8::internal::Object;
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 RedoBreakpoints(); 374 RedoBreakpoints();
374 375
375 #undef COMMAND_SIZE 376 #undef COMMAND_SIZE
376 #undef ARG_SIZE 377 #undef ARG_SIZE
377 378
378 #undef STR 379 #undef STR
379 #undef XSTR 380 #undef XSTR
380 } 381 }
381 382
382 383
384 bool Simulator::initialized_ = false;
385
386
387 void Simulator::Initialize() {
388 if (initialized_) return;
389 initialized_ = true;
390 ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference);
391 }
392
393
383 Simulator::Simulator() { 394 Simulator::Simulator() {
395 ASSERT(initialized_);
384 // Setup simulator support first. Some of this information is needed to 396 // Setup simulator support first. Some of this information is needed to
385 // setup the architecture state. 397 // setup the architecture state.
386 size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack 398 size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack
387 stack_ = reinterpret_cast<char*>(malloc(stack_size)); 399 stack_ = reinterpret_cast<char*>(malloc(stack_size));
388 pc_modified_ = false; 400 pc_modified_ = false;
389 icount_ = 0; 401 icount_ = 0;
390 break_pc_ = NULL; 402 break_pc_ = NULL;
391 break_instr_ = 0; 403 break_instr_ = 0;
392 404
393 // Setup architecture state. 405 // Setup architecture state.
(...skipping 11 matching lines...) Expand all
405 // some buffer below. 417 // some buffer below.
406 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; 418 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64;
407 // The lr and pc are initialized to a known bad value that will cause an 419 // The lr and pc are initialized to a known bad value that will cause an
408 // access violation if the simulator ever tries to execute it. 420 // access violation if the simulator ever tries to execute it.
409 registers_[pc] = bad_lr; 421 registers_[pc] = bad_lr;
410 registers_[lr] = bad_lr; 422 registers_[lr] = bad_lr;
411 InitializeCoverage(); 423 InitializeCoverage();
412 } 424 }
413 425
414 426
427 // When the generated code calls an external reference we need to catch that in
428 // the simulator. The external reference will be a function compiled for the
429 // host architecture. We need to call that function instead of trying to
430 // execute it with the simulator. We do that by redirecting the external
431 // reference to a swi (software-interrupt) instruction that is handled by
432 // 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
433 // swi instruction so the simulator knows what to call.
434 class Redirection {
435 public:
436 Redirection(void* external_function, bool fp_return)
437 : external_function_(external_function),
438 swi_instruction_((AL << 28) | (0xf << 24) | call_rt_redirected),
439 fp_return_(fp_return),
440 next_(list_) {
441 list_ = this;
442 }
443
444 void* address_of_swi_instruction() {
445 return reinterpret_cast<void*>(&swi_instruction_);
446 }
447
448 void* external_function() { return external_function_; }
449 bool fp_return() { return fp_return_; }
450
451 static Redirection* Get(void* external_function, bool fp_return) {
452 Redirection* current;
453 for (current = list_; current != NULL; current = current->next_) {
454 if (current->external_function_ == external_function) return current;
455 }
456 return new Redirection(external_function, fp_return);
457 }
458
459 static Redirection* FromSwiInstruction(Instr* swi_instruction) {
460 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
461 char* addr_of_redirection =
462 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
463 return reinterpret_cast<Redirection*>(addr_of_redirection);
464 }
465
466 private:
467 void* external_function_;
468 uint32_t swi_instruction_;
469 bool fp_return_;
470 Redirection* next_;
471 static Redirection* list_;
472 };
473
474
475 Redirection* Redirection::list_ = NULL;
476
477
478 void* Simulator::RedirectExternalReference(void* external_function,
479 bool fp_return) {
480 Redirection* redirection = Redirection::Get(external_function, fp_return);
481 return redirection->address_of_swi_instruction();
482 }
483
484
415 // Create one simulator per thread and keep it in thread local storage. 485 // Create one simulator per thread and keep it in thread local storage.
416 static v8::internal::Thread::LocalStorageKey simulator_key = 486 static v8::internal::Thread::LocalStorageKey simulator_key =
417 v8::internal::Thread::CreateThreadLocalKey(); 487 v8::internal::Thread::CreateThreadLocalKey();
iposva 2009/06/08 21:48:41 Please move this static initializer into the Initi
418 488
489
419 // Get the active Simulator for the current thread. 490 // Get the active Simulator for the current thread.
420 Simulator* Simulator::current() { 491 Simulator* Simulator::current() {
421 Simulator* sim = reinterpret_cast<Simulator*>( 492 Simulator* sim = reinterpret_cast<Simulator*>(
422 v8::internal::Thread::GetThreadLocal(simulator_key)); 493 v8::internal::Thread::GetThreadLocal(simulator_key));
423 if (sim == NULL) { 494 if (sim == NULL) {
424 // TODO(146): delete the simulator object when a thread goes away. 495 // TODO(146): delete the simulator object when a thread goes away.
425 sim = new Simulator(); 496 sim = new Simulator();
426 v8::internal::Thread::SetThreadLocal(simulator_key, sim); 497 v8::internal::Thread::SetThreadLocal(simulator_key, sim);
427 } 498 }
428 return sim; 499 return sim;
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 ASSERT(end_address == ((intptr_t)address) - 4); 985 ASSERT(end_address == ((intptr_t)address) - 4);
915 } 986 }
916 987
917 988
918 // Calls into the V8 runtime are based on this very simple interface. 989 // Calls into the V8 runtime are based on this very simple interface.
919 // Note: To be able to return two values from some calls the code in runtime.cc 990 // Note: To be able to return two values from some calls the code in runtime.cc
920 // uses the ObjectPair which is essentially two 32-bit values stuffed into a 991 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
921 // 64-bit value. With the code below we assume that all runtime calls return 992 // 64-bit value. With the code below we assume that all runtime calls return
922 // 64 bits of result. If they don't, the r1 result register contains a bogus 993 // 64 bits of result. If they don't, the r1 result register contains a bogus
923 // value, which is fine because it is caller-saved. 994 // value, which is fine because it is caller-saved.
924 typedef int64_t (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1); 995 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
996 int32_t arg1,
997 int32_t arg2,
998 int32_t arg3);
999 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
1000 int32_t arg1,
1001 int32_t arg2,
1002 int32_t arg3);
925 1003
926 1004
927 // Software interrupt instructions are used by the simulator to call into the 1005 // Software interrupt instructions are used by the simulator to call into the
928 // C-based V8 runtime. 1006 // C-based V8 runtime.
929 void Simulator::SoftwareInterrupt(Instr* instr) { 1007 void Simulator::SoftwareInterrupt(Instr* instr) {
930 int swi = instr->SwiField(); 1008 int swi = instr->SwiField();
931 switch (swi) { 1009 switch (swi) {
932 case call_rt_r5: { 1010 case call_rt_redirected: {
933 SimulatorRuntimeCall target = 1011 Redirection* redirection = Redirection::FromSwiInstruction(instr);
934 reinterpret_cast<SimulatorRuntimeCall>(get_register(r5)); 1012 int32_t arg0 = get_register(r0);
935 intptr_t arg0 = get_register(r0); 1013 int32_t arg1 = get_register(r1);
936 intptr_t arg1 = get_register(r1); 1014 int32_t arg2 = get_register(r2);
937 int64_t result = target(arg0, arg1); 1015 int32_t arg3 = get_register(r3);
938 int32_t lo_res = static_cast<int32_t>(result); 1016 // This is dodgy but it works because the C entry stubs are never moved.
939 int32_t hi_res = static_cast<int32_t>(result >> 32); 1017 // See comment in codegen-arm.cc and bug 1242173.
940 set_register(r0, lo_res); 1018 int32_t saved_lr = get_register(lr);
941 set_register(r1, hi_res); 1019 if (redirection->fp_return()) {
942 set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); 1020 intptr_t external =
943 break; 1021 reinterpret_cast<intptr_t>(redirection->external_function());
944 } 1022 SimulatorRuntimeFPCall target =
945 case call_rt_r2: { 1023 reinterpret_cast<SimulatorRuntimeFPCall>(external);
946 SimulatorRuntimeCall target = 1024 if (::v8::internal::FLAG_trace_sim) {
947 reinterpret_cast<SimulatorRuntimeCall>(get_register(r2)); 1025 double x, y;
948 intptr_t arg0 = get_register(r0); 1026 GetFpArgs(&x, &y);
949 intptr_t arg1 = get_register(r1); 1027 PrintF("Call to host function at %p with args %f, %f\n",
950 int64_t result = target(arg0, arg1); 1028 FUNCTION_ADDR(target), x, y);
951 int32_t lo_res = static_cast<int32_t>(result); 1029 }
952 int32_t hi_res = static_cast<int32_t>(result >> 32); 1030 double result = target(arg0, arg1, arg2, arg3);
953 set_register(r0, lo_res); 1031 SetFpResult(result);
954 set_register(r1, hi_res); 1032 } else {
955 set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); 1033 intptr_t external =
1034 reinterpret_cast<int32_t>(redirection->external_function());
1035 SimulatorRuntimeCall target =
1036 reinterpret_cast<SimulatorRuntimeCall>(external);
1037 if (::v8::internal::FLAG_trace_sim) {
1038 PrintF(
1039 "Call to host function at %p with args %08x, %08x, %08x, %08x\n",
1040 FUNCTION_ADDR(target),
1041 arg0,
1042 arg1,
1043 arg2,
1044 arg3);
1045 }
1046 int64_t result = target(arg0, arg1, arg2, arg3);
1047 int32_t lo_res = static_cast<int32_t>(result);
1048 int32_t hi_res = static_cast<int32_t>(result >> 32);
1049 set_register(r0, lo_res);
1050 set_register(r1, hi_res);
1051 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.
1052 }
1053 set_register(lr, saved_lr);
1054 set_pc(get_register(lr));
956 break; 1055 break;
957 } 1056 }
958 case break_point: { 1057 case break_point: {
959 Debugger dbg(this); 1058 Debugger dbg(this);
960 dbg.Debug(); 1059 dbg.Debug();
961 break; 1060 break;
962 } 1061 }
963 {
964 double x, y, z;
965 case simulator_fp_add:
966 GetFpArgs(&x, &y);
967 z = x + y;
968 SetFpResult(z);
969 TrashCallerSaveRegisters();
970 set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
971 break;
972 case simulator_fp_sub:
973 GetFpArgs(&x, &y);
974 z = x - y;
975 SetFpResult(z);
976 TrashCallerSaveRegisters();
977 set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
978 break;
979 case simulator_fp_mul:
980 GetFpArgs(&x, &y);
981 z = x * y;
982 SetFpResult(z);
983 TrashCallerSaveRegisters();
984 set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
985 break;
986 }
987 default: { 1062 default: {
988 UNREACHABLE(); 1063 UNREACHABLE();
989 break; 1064 break;
990 } 1065 }
991 } 1066 }
992 } 1067 }
993 1068
994 1069
995 // Handle execution based on instruction types. 1070 // Handle execution based on instruction types.
996 1071
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after
1679 set_register(r10, r10_val); 1754 set_register(r10, r10_val);
1680 set_register(r11, r11_val); 1755 set_register(r11, r11_val);
1681 1756
1682 int result = get_register(r0); 1757 int result = get_register(r0);
1683 return reinterpret_cast<Object*>(result); 1758 return reinterpret_cast<Object*>(result);
1684 } 1759 }
1685 1760
1686 } } // namespace assembler::arm 1761 } } // namespace assembler::arm
1687 1762
1688 #endif // !defined(__arm__) 1763 #endif // !defined(__arm__)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698