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, bool fp_return, |
750 ExternalReference::Type type) | |
749 : external_function_(external_function), | 751 : external_function_(external_function), |
750 swi_instruction_((AL << 28) | (0xf << 24) | call_rt_redirected), | 752 swi_instruction_((AL << 28) | (0xf << 24) | call_rt_redirected), |
751 fp_return_(fp_return), | 753 fp_return_(fp_return), |
754 type_(type), | |
752 next_(list_) { | 755 next_(list_) { |
753 Simulator::current()-> | 756 Simulator::current()-> |
754 FlushICache(reinterpret_cast<void*>(&swi_instruction_), | 757 FlushICache(reinterpret_cast<void*>(&swi_instruction_), |
755 Instr::kInstrSize); | 758 Instr::kInstrSize); |
756 list_ = this; | 759 list_ = this; |
757 } | 760 } |
758 | 761 |
759 void* address_of_swi_instruction() { | 762 void* address_of_swi_instruction() { |
760 return reinterpret_cast<void*>(&swi_instruction_); | 763 return reinterpret_cast<void*>(&swi_instruction_); |
761 } | 764 } |
762 | 765 |
763 void* external_function() { return external_function_; } | 766 void* external_function() { return external_function_; } |
764 bool fp_return() { return fp_return_; } | 767 bool fp_return() { return fp_return_; } |
768 ExternalReference::Type type() { return type_; } | |
765 | 769 |
766 static Redirection* Get(void* external_function, bool fp_return) { | 770 static Redirection* Get(void* external_function, bool fp_return, |
771 ExternalReference::Type type) { | |
767 Redirection* current; | 772 Redirection* current; |
768 for (current = list_; current != NULL; current = current->next_) { | 773 for (current = list_; current != NULL; current = current->next_) { |
769 if (current->external_function_ == external_function) return current; | 774 if (current->external_function_ == external_function) return current; |
770 } | 775 } |
771 return new Redirection(external_function, fp_return); | 776 return new Redirection(external_function, fp_return, type); |
772 } | 777 } |
773 | 778 |
774 static Redirection* FromSwiInstruction(Instr* swi_instruction) { | 779 static Redirection* FromSwiInstruction(Instr* swi_instruction) { |
775 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); | 780 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); |
776 char* addr_of_redirection = | 781 char* addr_of_redirection = |
777 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); | 782 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); |
778 return reinterpret_cast<Redirection*>(addr_of_redirection); | 783 return reinterpret_cast<Redirection*>(addr_of_redirection); |
779 } | 784 } |
780 | 785 |
781 private: | 786 private: |
782 void* external_function_; | 787 void* external_function_; |
783 uint32_t swi_instruction_; | 788 uint32_t swi_instruction_; |
784 bool fp_return_; | 789 bool fp_return_; |
790 ExternalReference::Type type_; | |
785 Redirection* next_; | 791 Redirection* next_; |
786 static Redirection* list_; | 792 static Redirection* list_; |
787 }; | 793 }; |
788 | 794 |
789 | 795 |
790 Redirection* Redirection::list_ = NULL; | 796 Redirection* Redirection::list_ = NULL; |
791 | 797 |
792 | 798 |
793 void* Simulator::RedirectExternalReference(void* external_function, | 799 void* Simulator::RedirectExternalReference( |
794 bool fp_return) { | 800 void* external_function, bool fp_return, ExternalReference::Type type) { |
Erik Corry
2011/01/21 14:28:40
You shouldn't need both the bool for the fp_return
Zaheer
2011/01/24 09:43:31
Done.
| |
795 Redirection* redirection = Redirection::Get(external_function, fp_return); | 801 Redirection* redirection = Redirection::Get( |
802 external_function, fp_return, type); | |
796 return redirection->address_of_swi_instruction(); | 803 return redirection->address_of_swi_instruction(); |
797 } | 804 } |
798 | 805 |
799 | 806 |
800 // Get the active Simulator for the current thread. | 807 // Get the active Simulator for the current thread. |
801 Simulator* Simulator::current() { | 808 Simulator* Simulator::current() { |
802 Initialize(); | 809 Initialize(); |
803 Simulator* sim = reinterpret_cast<Simulator*>( | 810 Simulator* sim = reinterpret_cast<Simulator*>( |
804 v8::internal::Thread::GetThreadLocal(simulator_key)); | 811 v8::internal::Thread::GetThreadLocal(simulator_key)); |
805 if (sim == NULL) { | 812 if (sim == NULL) { |
(...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1526 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, | 1533 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, |
1527 int32_t arg1, | 1534 int32_t arg1, |
1528 int32_t arg2, | 1535 int32_t arg2, |
1529 int32_t arg3, | 1536 int32_t arg3, |
1530 int32_t arg4); | 1537 int32_t arg4); |
1531 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, | 1538 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, |
1532 int32_t arg1, | 1539 int32_t arg1, |
1533 int32_t arg2, | 1540 int32_t arg2, |
1534 int32_t arg3); | 1541 int32_t arg3); |
1535 | 1542 |
1543 // This signature supports direct call in to js function native callback | |
antonm
2011/01/21 17:56:36
I'd use API function instead of js function here
Zaheer
2011/01/24 09:43:31
Done.
| |
1544 // (refer to InvocationCallback in v8.h). | |
1545 typedef v8::Handle<v8::Value> (*SimulatorRuntimeApiCall)(int32_t arg0); | |
1536 | 1546 |
1537 // Software interrupt instructions are used by the simulator to call into the | 1547 // Software interrupt instructions are used by the simulator to call into the |
1538 // C-based V8 runtime. | 1548 // C-based V8 runtime. |
1539 void Simulator::SoftwareInterrupt(Instr* instr) { | 1549 void Simulator::SoftwareInterrupt(Instr* instr) { |
1540 int svc = instr->SvcField(); | 1550 int svc = instr->SvcField(); |
1541 switch (svc) { | 1551 switch (svc) { |
1542 case call_rt_redirected: { | 1552 case call_rt_redirected: { |
1543 // Check if stack is aligned. Error if not aligned is reported below to | 1553 // Check if stack is aligned. Error if not aligned is reported below to |
1544 // include information on the function called. | 1554 // include information on the function called. |
1545 bool stack_aligned = | 1555 bool stack_aligned = |
(...skipping 21 matching lines...) Expand all Loading... | |
1567 FUNCTION_ADDR(target), x, y); | 1577 FUNCTION_ADDR(target), x, y); |
1568 if (!stack_aligned) { | 1578 if (!stack_aligned) { |
1569 PrintF(" with unaligned stack %08x\n", get_register(sp)); | 1579 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
1570 } | 1580 } |
1571 PrintF("\n"); | 1581 PrintF("\n"); |
1572 } | 1582 } |
1573 CHECK(stack_aligned); | 1583 CHECK(stack_aligned); |
1574 double result = target(arg0, arg1, arg2, arg3); | 1584 double result = target(arg0, arg1, arg2, arg3); |
1575 SetFpResult(result); | 1585 SetFpResult(result); |
1576 } else { | 1586 } else { |
1577 intptr_t external = | 1587 if (redirection->type() == ExternalReference::DIRECT_CALL) { |
1578 reinterpret_cast<int32_t>(redirection->external_function()); | 1588 intptr_t external = |
1579 SimulatorRuntimeCall target = | 1589 reinterpret_cast<int32_t>(redirection->external_function()); |
1580 reinterpret_cast<SimulatorRuntimeCall>(external); | 1590 SimulatorRuntimeApiCall target = |
antonm
2011/01/21 17:56:36
please, consider refactoring the common logic of l
Zaheer
2011/01/24 09:43:31
The log is unique to each case, the stack alignmen
antonm
2011/01/26 11:36:37
Ok, let's leave it as you have it now.
| |
1581 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1591 reinterpret_cast<SimulatorRuntimeApiCall>(external); |
1582 PrintF( | 1592 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
1583 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", | 1593 PrintF( |
1584 FUNCTION_ADDR(target), | 1594 "Call to host function at %p args %08x", |
1585 arg0, | 1595 FUNCTION_ADDR(target), |
1586 arg1, | 1596 arg0); |
1587 arg2, | 1597 if (!stack_aligned) { |
1588 arg3, | 1598 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
1589 arg4); | 1599 } |
1590 if (!stack_aligned) { | 1600 PrintF("\n"); |
1591 PrintF(" with unaligned stack %08x\n", get_register(sp)); | |
1592 } | 1601 } |
1593 PrintF("\n"); | 1602 CHECK(stack_aligned); |
1603 v8::Handle<v8::Value> result = target(arg0); | |
1604 if (::v8::internal::FLAG_trace_sim) { | |
1605 PrintF("Returned %p\n", reinterpret_cast<void *>(*result)); | |
1606 } | |
1607 set_register(r0, (int32_t) *result); | |
1608 } else { | |
1609 intptr_t external = | |
1610 reinterpret_cast<int32_t>(redirection->external_function()); | |
1611 SimulatorRuntimeCall target = | |
1612 reinterpret_cast<SimulatorRuntimeCall>(external); | |
1613 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | |
1614 PrintF( | |
1615 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", | |
1616 FUNCTION_ADDR(target), | |
1617 arg0, | |
1618 arg1, | |
1619 arg2, | |
1620 arg3, | |
1621 arg4); | |
1622 if (!stack_aligned) { | |
1623 PrintF(" with unaligned stack %08x\n", get_register(sp)); | |
1624 } | |
1625 PrintF("\n"); | |
1626 } | |
1627 CHECK(stack_aligned); | |
1628 int64_t result = target(arg0, arg1, arg2, arg3, arg4); | |
1629 int32_t lo_res = static_cast<int32_t>(result); | |
1630 int32_t hi_res = static_cast<int32_t>(result >> 32); | |
1631 if (::v8::internal::FLAG_trace_sim) { | |
1632 PrintF("Returned %08x\n", lo_res); | |
1633 } | |
1634 set_register(r0, lo_res); | |
1635 set_register(r1, hi_res); | |
1594 } | 1636 } |
1595 CHECK(stack_aligned); | |
1596 int64_t result = target(arg0, arg1, arg2, arg3, arg4); | |
1597 int32_t lo_res = static_cast<int32_t>(result); | |
1598 int32_t hi_res = static_cast<int32_t>(result >> 32); | |
1599 if (::v8::internal::FLAG_trace_sim) { | |
1600 PrintF("Returned %08x\n", lo_res); | |
1601 } | |
1602 set_register(r0, lo_res); | |
1603 set_register(r1, hi_res); | |
1604 } | 1637 } |
1605 set_register(lr, saved_lr); | 1638 set_register(lr, saved_lr); |
1606 set_pc(get_register(lr)); | 1639 set_pc(get_register(lr)); |
1607 break; | 1640 break; |
1608 } | 1641 } |
1609 case break_point: { | 1642 case break_point: { |
1610 Debugger dbg(this); | 1643 Debugger dbg(this); |
1611 dbg.Debug(); | 1644 dbg.Debug(); |
1612 break; | 1645 break; |
1613 } | 1646 } |
(...skipping 1430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3044 uintptr_t address = *stack_slot; | 3077 uintptr_t address = *stack_slot; |
3045 set_register(sp, current_sp + sizeof(uintptr_t)); | 3078 set_register(sp, current_sp + sizeof(uintptr_t)); |
3046 return address; | 3079 return address; |
3047 } | 3080 } |
3048 | 3081 |
3049 } } // namespace assembler::arm | 3082 } } // namespace assembler::arm |
3050 | 3083 |
3051 #endif // USE_SIMULATOR | 3084 #endif // USE_SIMULATOR |
3052 | 3085 |
3053 #endif // V8_TARGET_ARCH_ARM | 3086 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |