OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 |
(...skipping 30 matching lines...) Expand all Loading... | |
41 | 41 |
42 // Only build the simulator if not compiling for real ARM hardware. | 42 // Only build the simulator if not compiling for real ARM hardware. |
43 namespace assembler { | 43 namespace assembler { |
44 namespace arm { | 44 namespace arm { |
45 | 45 |
46 using ::v8::internal::Object; | 46 using ::v8::internal::Object; |
47 using ::v8::internal::PrintF; | 47 using ::v8::internal::PrintF; |
48 using ::v8::internal::OS; | 48 using ::v8::internal::OS; |
49 using ::v8::internal::ReadLine; | 49 using ::v8::internal::ReadLine; |
50 using ::v8::internal::DeleteArray; | 50 using ::v8::internal::DeleteArray; |
51 using ::v8::internal::ExternalReference; | |
51 | 52 |
52 // This macro provides a platform independent use of sscanf. The reason for | 53 // This macro provides a platform independent use of sscanf. The reason for |
53 // SScanF not being implemented in a platform independent way through | 54 // SScanF not being implemented in a platform independent way through |
54 // ::v8::internal::OS in the same way as SNPrintF is that the | 55 // ::v8::internal::OS in the same way as SNPrintF is that the |
55 // Windows C Run-Time Library does not provide vsscanf. | 56 // Windows C Run-Time Library does not provide vsscanf. |
56 #define SScanF sscanf // NOLINT | 57 #define SScanF sscanf // NOLINT |
57 | 58 |
58 // The Debugger class is used by the simulator while debugging simulated ARM | 59 // The Debugger class is used by the simulator while debugging simulated ARM |
59 // code. | 60 // code. |
60 class Debugger { | 61 class Debugger { |
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
738 | 739 |
739 // When the generated code calls an external reference we need to catch that in | 740 // When the generated code calls an external reference we need to catch that in |
740 // the simulator. The external reference will be a function compiled for the | 741 // the simulator. The external reference will be a function compiled for the |
741 // host architecture. We need to call that function instead of trying to | 742 // host architecture. We need to call that function instead of trying to |
742 // execute it with the simulator. We do that by redirecting the external | 743 // execute it with the simulator. We do that by redirecting the external |
743 // reference to a svc (Supervisor Call) instruction that is handled by | 744 // reference to a svc (Supervisor Call) instruction that is handled by |
744 // the simulator. We write the original destination of the jump just at a known | 745 // the simulator. We write the original destination of the jump just at a known |
745 // offset from the svc instruction so the simulator knows what to call. | 746 // offset from the svc instruction so the simulator knows what to call. |
746 class Redirection { | 747 class Redirection { |
747 public: | 748 public: |
748 Redirection(void* external_function, bool fp_return) | 749 Redirection(void* external_function, ExternalReference::Type type) |
749 : external_function_(external_function), | 750 : external_function_(external_function), |
750 swi_instruction_((AL << 28) | (0xf << 24) | call_rt_redirected), | 751 swi_instruction_((AL << 28) | (0xf << 24) | call_rt_redirected), |
751 fp_return_(fp_return), | 752 type_(type), |
752 next_(list_) { | 753 next_(list_) { |
753 Simulator::current()-> | 754 Simulator::current()-> |
754 FlushICache(reinterpret_cast<void*>(&swi_instruction_), | 755 FlushICache(reinterpret_cast<void*>(&swi_instruction_), |
755 Instr::kInstrSize); | 756 Instr::kInstrSize); |
756 list_ = this; | 757 list_ = this; |
757 } | 758 } |
758 | 759 |
759 void* address_of_swi_instruction() { | 760 void* address_of_swi_instruction() { |
760 return reinterpret_cast<void*>(&swi_instruction_); | 761 return reinterpret_cast<void*>(&swi_instruction_); |
761 } | 762 } |
762 | 763 |
763 void* external_function() { return external_function_; } | 764 void* external_function() { return external_function_; } |
764 bool fp_return() { return fp_return_; } | 765 ExternalReference::Type type() { return type_; } |
765 | 766 |
766 static Redirection* Get(void* external_function, bool fp_return) { | 767 static Redirection* Get(void* external_function, |
768 ExternalReference::Type type) { | |
767 Redirection* current; | 769 Redirection* current; |
768 for (current = list_; current != NULL; current = current->next_) { | 770 for (current = list_; current != NULL; current = current->next_) { |
769 if (current->external_function_ == external_function) return current; | 771 if (current->external_function_ == external_function) return current; |
770 } | 772 } |
771 return new Redirection(external_function, fp_return); | 773 return new Redirection(external_function, type); |
772 } | 774 } |
773 | 775 |
774 static Redirection* FromSwiInstruction(Instr* swi_instruction) { | 776 static Redirection* FromSwiInstruction(Instr* swi_instruction) { |
775 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); | 777 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); |
776 char* addr_of_redirection = | 778 char* addr_of_redirection = |
777 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); | 779 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); |
778 return reinterpret_cast<Redirection*>(addr_of_redirection); | 780 return reinterpret_cast<Redirection*>(addr_of_redirection); |
779 } | 781 } |
780 | 782 |
781 private: | 783 private: |
782 void* external_function_; | 784 void* external_function_; |
783 uint32_t swi_instruction_; | 785 uint32_t swi_instruction_; |
784 bool fp_return_; | 786 ExternalReference::Type type_; |
785 Redirection* next_; | 787 Redirection* next_; |
786 static Redirection* list_; | 788 static Redirection* list_; |
787 }; | 789 }; |
788 | 790 |
789 | 791 |
790 Redirection* Redirection::list_ = NULL; | 792 Redirection* Redirection::list_ = NULL; |
791 | 793 |
792 | 794 |
793 void* Simulator::RedirectExternalReference(void* external_function, | 795 void* Simulator::RedirectExternalReference(void* external_function, |
794 bool fp_return) { | 796 ExternalReference::Type type) { |
795 Redirection* redirection = Redirection::Get(external_function, fp_return); | 797 Redirection* redirection = Redirection::Get(external_function, type); |
796 return redirection->address_of_swi_instruction(); | 798 return redirection->address_of_swi_instruction(); |
797 } | 799 } |
798 | 800 |
799 | 801 |
800 // Get the active Simulator for the current thread. | 802 // Get the active Simulator for the current thread. |
801 Simulator* Simulator::current() { | 803 Simulator* Simulator::current() { |
802 Initialize(); | 804 Initialize(); |
803 Simulator* sim = reinterpret_cast<Simulator*>( | 805 Simulator* sim = reinterpret_cast<Simulator*>( |
804 v8::internal::Thread::GetThreadLocal(simulator_key)); | 806 v8::internal::Thread::GetThreadLocal(simulator_key)); |
805 if (sim == NULL) { | 807 if (sim == NULL) { |
(...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1526 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, | 1528 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, |
1527 int32_t arg1, | 1529 int32_t arg1, |
1528 int32_t arg2, | 1530 int32_t arg2, |
1529 int32_t arg3, | 1531 int32_t arg3, |
1530 int32_t arg4); | 1532 int32_t arg4); |
1531 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, | 1533 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, |
1532 int32_t arg1, | 1534 int32_t arg1, |
1533 int32_t arg2, | 1535 int32_t arg2, |
1534 int32_t arg3); | 1536 int32_t arg3); |
1535 | 1537 |
1538 // This signature supports direct call in to API function native callback | |
1539 // (refer to InvocationCallback in v8.h). | |
1540 typedef v8::Handle<v8::Value> (*SimulatorRuntimeApiCall)(int32_t arg0); | |
1536 | 1541 |
1537 // Software interrupt instructions are used by the simulator to call into the | 1542 // Software interrupt instructions are used by the simulator to call into the |
1538 // C-based V8 runtime. | 1543 // C-based V8 runtime. |
1539 void Simulator::SoftwareInterrupt(Instr* instr) { | 1544 void Simulator::SoftwareInterrupt(Instr* instr) { |
1540 int svc = instr->SvcField(); | 1545 int svc = instr->SvcField(); |
1541 switch (svc) { | 1546 switch (svc) { |
1542 case call_rt_redirected: { | 1547 case call_rt_redirected: { |
1543 // Check if stack is aligned. Error if not aligned is reported below to | 1548 // Check if stack is aligned. Error if not aligned is reported below to |
1544 // include information on the function called. | 1549 // include information on the function called. |
1545 bool stack_aligned = | 1550 bool stack_aligned = |
1546 (get_register(sp) | 1551 (get_register(sp) |
1547 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; | 1552 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; |
1548 Redirection* redirection = Redirection::FromSwiInstruction(instr); | 1553 Redirection* redirection = Redirection::FromSwiInstruction(instr); |
1549 int32_t arg0 = get_register(r0); | 1554 int32_t arg0 = get_register(r0); |
1550 int32_t arg1 = get_register(r1); | 1555 int32_t arg1 = get_register(r1); |
1551 int32_t arg2 = get_register(r2); | 1556 int32_t arg2 = get_register(r2); |
1552 int32_t arg3 = get_register(r3); | 1557 int32_t arg3 = get_register(r3); |
1553 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); | 1558 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); |
1554 int32_t arg4 = *stack_pointer; | 1559 int32_t arg4 = *stack_pointer; |
1555 // This is dodgy but it works because the C entry stubs are never moved. | 1560 // This is dodgy but it works because the C entry stubs are never moved. |
1556 // See comment in codegen-arm.cc and bug 1242173. | 1561 // See comment in codegen-arm.cc and bug 1242173. |
1557 int32_t saved_lr = get_register(lr); | 1562 int32_t saved_lr = get_register(lr); |
1558 if (redirection->fp_return()) { | 1563 intptr_t external = |
1559 intptr_t external = | 1564 reinterpret_cast<intptr_t>(redirection->external_function()); |
1560 reinterpret_cast<intptr_t>(redirection->external_function()); | 1565 if (redirection->type() == ExternalReference::FP_RETURN_CALL) { |
1561 SimulatorRuntimeFPCall target = | 1566 SimulatorRuntimeFPCall target = |
1562 reinterpret_cast<SimulatorRuntimeFPCall>(external); | 1567 reinterpret_cast<SimulatorRuntimeFPCall>(external); |
1563 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1568 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
1564 double x, y; | 1569 double x, y; |
1565 GetFpArgs(&x, &y); | 1570 GetFpArgs(&x, &y); |
1566 PrintF("Call to host function at %p with args %f, %f", | 1571 PrintF("Call to host function at %p with args %f, %f", |
1567 FUNCTION_ADDR(target), x, y); | 1572 FUNCTION_ADDR(target), x, y); |
1568 if (!stack_aligned) { | 1573 if (!stack_aligned) { |
1569 PrintF(" with unaligned stack %08x\n", get_register(sp)); | 1574 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
1570 } | 1575 } |
1571 PrintF("\n"); | 1576 PrintF("\n"); |
1572 } | 1577 } |
1573 CHECK(stack_aligned); | 1578 CHECK(stack_aligned); |
1574 double result = target(arg0, arg1, arg2, arg3); | 1579 double result = target(arg0, arg1, arg2, arg3); |
1575 SetFpResult(result); | 1580 SetFpResult(result); |
1581 } else if (redirection->type() == ExternalReference::DIRECT_CALL) { | |
1582 SimulatorRuntimeApiCall target = | |
1583 reinterpret_cast<SimulatorRuntimeApiCall>(external); | |
1584 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | |
1585 PrintF( | |
1586 "Call to host function at %p args %08x", | |
1587 FUNCTION_ADDR(target), | |
1588 arg0); | |
1589 if (!stack_aligned) { | |
1590 PrintF(" with unaligned stack %08x\n", get_register(sp)); | |
1591 } | |
1592 PrintF("\n"); | |
1593 } | |
1594 CHECK(stack_aligned); | |
1595 v8::Handle<v8::Value> result = target(arg0); | |
1596 if (::v8::internal::FLAG_trace_sim) { | |
1597 PrintF("Returned %p\n", reinterpret_cast<void *>(*result)); | |
1598 } | |
1599 set_register(r0, (int32_t) *result); | |
1576 } else { | 1600 } else { |
1577 intptr_t external = | 1601 // builtin/runtime call |
antonm
2011/01/26 11:36:38
nit: add a dot please.
v8 style is to end comment
Zaheer
2011/02/02 10:05:59
Done.
| |
1578 reinterpret_cast<int32_t>(redirection->external_function()); | 1602 ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL); |
1579 SimulatorRuntimeCall target = | 1603 SimulatorRuntimeCall target = |
1580 reinterpret_cast<SimulatorRuntimeCall>(external); | 1604 reinterpret_cast<SimulatorRuntimeCall>(external); |
1581 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1605 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
1582 PrintF( | 1606 PrintF( |
1583 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", | 1607 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", |
1584 FUNCTION_ADDR(target), | 1608 FUNCTION_ADDR(target), |
1585 arg0, | 1609 arg0, |
1586 arg1, | 1610 arg1, |
1587 arg2, | 1611 arg2, |
1588 arg3, | 1612 arg3, |
(...skipping 1455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3044 uintptr_t address = *stack_slot; | 3068 uintptr_t address = *stack_slot; |
3045 set_register(sp, current_sp + sizeof(uintptr_t)); | 3069 set_register(sp, current_sp + sizeof(uintptr_t)); |
3046 return address; | 3070 return address; |
3047 } | 3071 } |
3048 | 3072 |
3049 } } // namespace assembler::arm | 3073 } } // namespace assembler::arm |
3050 | 3074 |
3051 #endif // USE_SIMULATOR | 3075 #endif // USE_SIMULATOR |
3052 | 3076 |
3053 #endif // V8_TARGET_ARCH_ARM | 3077 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |