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

Side by Side Diff: runtime/vm/simulator_mips.cc

Issue 13407003: Third codegen test passing for simulated MIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 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
« no previous file with comments | « runtime/vm/simulator_mips.h ('k') | runtime/vm/stack_frame_mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include <math.h> // for isnan.
6 #include <setjmp.h>
7 #include <stdlib.h>
8
5 #include "vm/globals.h" 9 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_MIPS) 10 #if defined(TARGET_ARCH_MIPS)
7 11
8 // Only build the simulator if not compiling for real MIPS hardware. 12 // Only build the simulator if not compiling for real MIPS hardware.
9 #if !defined(HOST_ARCH_MIPS) 13 #if !defined(HOST_ARCH_MIPS)
10 14
11 #include "vm/simulator.h" 15 #include "vm/simulator.h"
12 16
13 #include "vm/assembler.h" 17 #include "vm/assembler.h"
14 #include "vm/constants_mips.h" 18 #include "vm/constants_mips.h"
15 #include "vm/disassembler.h" 19 #include "vm/disassembler.h"
20 #include "vm/native_arguments.h"
21 #include "vm/thread.h"
16 22
17 namespace dart { 23 namespace dart {
18 24
25 DEFINE_FLAG(bool, trace_sim, false, "Trace simulator execution.");
19 DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at."); 26 DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at.");
20 27
21 28
22 // This macro provides a platform independent use of sscanf. The reason for 29 // This macro provides a platform independent use of sscanf. The reason for
23 // SScanF not being implemented in a platform independent way through 30 // SScanF not being implemented in a platform independent way through
24 // OS in the same way as SNPrint is that the Windows C Run-Time 31 // OS in the same way as SNPrint is that the Windows C Run-Time
25 // Library does not provide vsscanf. 32 // Library does not provide vsscanf.
26 #define SScanF sscanf // NOLINT 33 #define SScanF sscanf // NOLINT
27 34
28 35
36 // SimulatorSetjmpBuffer are linked together, and the last created one
37 // is referenced by the Simulator. When an exception is thrown, the exception
38 // runtime looks at where to jump and finds the corresponding
39 // SimulatorSetjmpBuffer based on the stack pointer of the exception handler.
40 // The runtime then does a Longjmp on that buffer to return to the simulator.
41 class SimulatorSetjmpBuffer {
42 public:
43 int Setjmp() { return setjmp(buffer_); }
44 void Longjmp() {
45 // "This" is now the last setjmp buffer.
46 simulator_->set_last_setjmp_buffer(this);
47 longjmp(buffer_, 1);
48 }
49
50 explicit SimulatorSetjmpBuffer(Simulator* sim) {
51 simulator_ = sim;
52 link_ = sim->last_setjmp_buffer();
53 sim->set_last_setjmp_buffer(this);
54 sp_ = sim->get_register(SP);
55 }
56
57 ~SimulatorSetjmpBuffer() {
58 ASSERT(simulator_->last_setjmp_buffer() == this);
59 simulator_->set_last_setjmp_buffer(link_);
60 }
61
62 SimulatorSetjmpBuffer* link() { return link_; }
63
64 int32_t sp() { return sp_; }
65
66 private:
67 int32_t sp_;
68 Simulator* simulator_;
69 SimulatorSetjmpBuffer* link_;
70 jmp_buf buffer_;
71
72 friend class Simulator;
73 };
74
75
29 // The SimulatorDebugger class is used by the simulator while debugging 76 // The SimulatorDebugger class is used by the simulator while debugging
30 // simulated MIPS code. 77 // simulated MIPS code.
31 class SimulatorDebugger { 78 class SimulatorDebugger {
32 public: 79 public:
33 explicit SimulatorDebugger(Simulator* sim); 80 explicit SimulatorDebugger(Simulator* sim);
34 ~SimulatorDebugger(); 81 ~SimulatorDebugger();
35 82
36 void Stop(Instr* instr, const char* message); 83 void Stop(Instr* instr, const char* message);
37 void Debug(); 84 void Debug();
38 char* ReadLine(const char* prompt); 85 char* ReadLine(const char* prompt);
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 550
504 551
505 Simulator::~Simulator() { 552 Simulator::~Simulator() {
506 Isolate* isolate = Isolate::Current(); 553 Isolate* isolate = Isolate::Current();
507 if (isolate != NULL) { 554 if (isolate != NULL) {
508 isolate->set_simulator(NULL); 555 isolate->set_simulator(NULL);
509 } 556 }
510 } 557 }
511 558
512 559
560 // When the generated code calls an external reference we need to catch that in
561 // the simulator. The external reference will be a function compiled for the
562 // host architecture. We need to call that function instead of trying to
563 // execute it with the simulator. We do that by redirecting the external
564 // reference to a break instruction with code 2 that is handled by
565 // the simulator. We write the original destination of the jump just at a known
566 // offset from the break instruction so the simulator knows what to call.
567 class Redirection {
568 public:
569 uword address_of_break_instruction() {
570 return reinterpret_cast<uword>(&break_instruction_);
571 }
572
573 uword external_function() const { return external_function_; }
574
575 Simulator::CallKind call_kind() const { return call_kind_; }
576
577 static Redirection* Get(uword external_function,
578 Simulator::CallKind call_kind) {
579 Redirection* current;
580 for (current = list_; current != NULL; current = current->next_) {
581 if (current->external_function_ == external_function) return current;
582 }
583 return new Redirection(external_function, call_kind);
584 }
585
586 static Redirection* FromBreakInstruction(Instr* break_instruction) {
587 char* addr_of_break = reinterpret_cast<char*>(break_instruction);
588 char* addr_of_redirection =
589 addr_of_break - OFFSET_OF(Redirection, break_instruction_);
590 return reinterpret_cast<Redirection*>(addr_of_redirection);
591 }
592
593 private:
594 static const int32_t kRedirectInstruction =
595 Instr::kBreakPointInstruction | (Instr::kRedirectCode << kBreakCodeShift);
596
597 Redirection(uword external_function, Simulator::CallKind call_kind)
598 : external_function_(external_function),
599 call_kind_(call_kind),
600 break_instruction_(kRedirectInstruction),
601 next_(list_) {
602 list_ = this;
603 }
604
605 uword external_function_;
606 Simulator::CallKind call_kind_;
607 uint32_t break_instruction_;
608 Redirection* next_;
609 static Redirection* list_;
610 };
611
612
613 Redirection* Redirection::list_ = NULL;
614
615
616 uword Simulator::RedirectExternalReference(uword function, CallKind call_kind) {
617 Redirection* redirection = Redirection::Get(function, call_kind);
618 return redirection->address_of_break_instruction();
619 }
620
621
513 // Get the active Simulator for the current isolate. 622 // Get the active Simulator for the current isolate.
514 Simulator* Simulator::Current() { 623 Simulator* Simulator::Current() {
515 Simulator* simulator = Isolate::Current()->simulator(); 624 Simulator* simulator = Isolate::Current()->simulator();
516 if (simulator == NULL) { 625 if (simulator == NULL) {
517 simulator = new Simulator(); 626 simulator = new Simulator();
518 Isolate::Current()->set_simulator(simulator); 627 Isolate::Current()->set_simulator(simulator);
519 } 628 }
520 return simulator; 629 return simulator;
521 } 630 }
522 631
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 } else { 793 } else {
685 // Operands have different signs. 794 // Operands have different signs.
686 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0)) 795 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
687 // And first operand and result have different signs. 796 // And first operand and result have different signs.
688 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); 797 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
689 } 798 }
690 return overflow; 799 return overflow;
691 } 800 }
692 801
693 802
803 // Calls into the Dart runtime are based on this interface.
804 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments);
805
806 // Calls to leaf Dart runtime functions are based on this interface.
807 typedef int32_t (*SimulatorLeafRuntimeCall)(
808 int32_t r0, int32_t r1, int32_t r2, int32_t r3);
809
810 // Calls to native Dart functions are based on this interface.
811 typedef void (*SimulatorNativeCall)(NativeArguments* arguments);
812
813
814 void Simulator::DoBreak(Instr *instr) {
815 ASSERT(instr->OpcodeField() == SPECIAL);
816 ASSERT(instr->FunctionField() == BREAK);
817 if (instr->BreakCodeField() == Instr::kStopMessageCode) {
818 SimulatorDebugger dbg(this);
819 const char* message = *reinterpret_cast<const char**>(
820 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize);
821 set_pc(get_pc() + Instr::kInstrSize);
822 dbg.Stop(instr, message);
823 } else if (instr->BreakCodeField() == Instr::kRedirectCode) {
824 SimulatorSetjmpBuffer buffer(this);
825
826 if (!setjmp(buffer.buffer_)) {
827 int32_t saved_ra = get_register(RA);
828 Redirection* redirection = Redirection::FromBreakInstruction(instr);
829 uword external = redirection->external_function();
830 if (FLAG_trace_sim) {
831 OS::Print("Call to host function at 0x%"Pd"\n", external);
832 }
833 if (redirection->call_kind() == kRuntimeCall) {
834 NativeArguments arguments;
835 ASSERT(sizeof(NativeArguments) == 4*kWordSize);
836 arguments.isolate_ = reinterpret_cast<Isolate*>(get_register(A0));
837 arguments.argc_tag_ = get_register(A1);
838 arguments.argv_ = reinterpret_cast<RawObject*(*)[]>(get_register(A2));
839 arguments.retval_ = reinterpret_cast<RawObject**>(get_register(A3));
840 SimulatorRuntimeCall target =
841 reinterpret_cast<SimulatorRuntimeCall>(external);
842 target(arguments);
843 set_register(V0, icount_); // Zap result register from void function.
844 } else if (redirection->call_kind() == kLeafRuntimeCall) {
845 int32_t a0 = get_register(A0);
846 int32_t a1 = get_register(A1);
847 int32_t a2 = get_register(A2);
848 int32_t a3 = get_register(A3);
849 SimulatorLeafRuntimeCall target =
850 reinterpret_cast<SimulatorLeafRuntimeCall>(external);
851 a0 = target(a0, a1, a2, a3);
852 set_register(V0, a0); // Set returned result from function.
853 } else {
854 ASSERT(redirection->call_kind() == kNativeCall);
855 NativeArguments* arguments;
856 arguments = reinterpret_cast<NativeArguments*>(get_register(A0));
857 SimulatorNativeCall target =
858 reinterpret_cast<SimulatorNativeCall>(external);
859 target(arguments);
860 set_register(V0, icount_); // Zap result register from void function.
861 }
862
863 // Zap caller-saved registers, since the actual runtime call could have
864 // used them.
865 set_register(T0, icount_);
866 set_register(T1, icount_);
867 set_register(T2, icount_);
868 set_register(T3, icount_);
869 set_register(T4, icount_);
870 set_register(T5, icount_);
871 set_register(T6, icount_);
872 set_register(T7, icount_);
873 set_register(T8, icount_);
874 set_register(T9, icount_);
875
876 set_register(A0, icount_);
877 set_register(A1, icount_);
878 set_register(A2, icount_);
879 set_register(A3, icount_);
880 set_register(TMP, icount_);
881 set_register(RA, icount_);
882
883 // Zap floating point registers.
884 double zap_dvalue = static_cast<double>(icount_);
885 for (int i = F0; i <= F31; i++) {
886 set_fregister(static_cast<FRegister>(i), zap_dvalue);
887 }
888
889 // Return.
890 set_pc(saved_ra);
891 }
892 } else {
893 SimulatorDebugger dbg(this);
894 dbg.Stop(instr, "breakpoint");
895 }
896 }
897
898
694 void Simulator::DecodeSpecial(Instr* instr) { 899 void Simulator::DecodeSpecial(Instr* instr) {
695 ASSERT(instr->OpcodeField() == SPECIAL); 900 ASSERT(instr->OpcodeField() == SPECIAL);
696 switch (instr->FunctionField()) { 901 switch (instr->FunctionField()) {
697 case ADDU: { 902 case ADDU: {
698 ASSERT(instr->SaField() == 0); 903 ASSERT(instr->SaField() == 0);
699 // Format(instr, "addu 'rd, 'rs, 'rt"); 904 // Format(instr, "addu 'rd, 'rs, 'rt");
700 int32_t rs_val = get_register(instr->RsField()); 905 int32_t rs_val = get_register(instr->RsField());
701 int32_t rt_val = get_register(instr->RtField()); 906 int32_t rt_val = get_register(instr->RtField());
702 set_register(instr->RdField(), rs_val + rt_val); 907 set_register(instr->RdField(), rs_val + rt_val);
703 break; 908 break;
704 } 909 }
705 case AND: { 910 case AND: {
706 ASSERT(instr->SaField() == 0); 911 ASSERT(instr->SaField() == 0);
707 // Format(instr, "and 'rd, 'rs, 'rt"); 912 // Format(instr, "and 'rd, 'rs, 'rt");
708 int32_t rs_val = get_register(instr->RsField()); 913 int32_t rs_val = get_register(instr->RsField());
709 int32_t rt_val = get_register(instr->RtField()); 914 int32_t rt_val = get_register(instr->RtField());
710 set_register(instr->RdField(), rs_val & rt_val); 915 set_register(instr->RdField(), rs_val & rt_val);
711 break; 916 break;
712 } 917 }
713 case BREAK: { 918 case BREAK: {
714 if (instr->BreakCodeField() == Instr::kStopMessageCode) { 919 DoBreak(instr);
715 SimulatorDebugger dbg(this);
716 const char* message = *reinterpret_cast<const char**>(
717 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize);
718 set_pc(get_pc() + Instr::kInstrSize);
719 dbg.Stop(instr, message);
720 } else {
721 SimulatorDebugger dbg(this);
722 dbg.Stop(instr, "breakpoint");
723 }
724 break; 920 break;
725 } 921 }
726 case DIV: { 922 case DIV: {
727 ASSERT(instr->RdField() == 0); 923 ASSERT(instr->RdField() == 0);
728 ASSERT(instr->SaField() == 0); 924 ASSERT(instr->SaField() == 0);
729 // Format(instr, "div 'rs, 'rt"); 925 // Format(instr, "div 'rs, 'rt");
730 int32_t rs_val = get_register(instr->RsField()); 926 int32_t rs_val = get_register(instr->RsField());
731 int32_t rt_val = get_register(instr->RtField()); 927 int32_t rt_val = get_register(instr->RtField());
732 if (rt_val == 0) { 928 if (rt_val == 0) {
733 // Results are unpredictable. 929 // Results are unpredictable.
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after
1402 // Restore the SP register and return R1:R0. 1598 // Restore the SP register and return R1:R0.
1403 set_register(SP, sp_before_call); 1599 set_register(SP, sp_before_call);
1404 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); 1600 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1));
1405 } 1601 }
1406 1602
1407 } // namespace dart 1603 } // namespace dart
1408 1604
1409 #endif // !defined(HOST_ARCH_MIPS) 1605 #endif // !defined(HOST_ARCH_MIPS)
1410 1606
1411 #endif // defined TARGET_ARCH_MIPS 1607 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/simulator_mips.h ('k') | runtime/vm/stack_frame_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698