OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 // Declares a Simulator for ARM instructions if we are not generating a native | |
6 // ARM binary. This Simulator allows us to run and debug ARM code generation on | |
7 // regular desktop machines. | |
8 // Dart calls into generated code by "calling" the InvokeDartCode stub, | |
9 // which will start execution in the Simulator or forwards to the real entry | |
10 // on a ARM HW platform. | |
11 | |
12 #ifndef VM_SIMULATOR_ARM_H_ | |
13 #define VM_SIMULATOR_ARM_H_ | |
14 | |
15 #ifndef VM_SIMULATOR_H_ | |
16 #error Do not include simulator_arm.h directly; use simulator.h. | |
17 #endif | |
18 | |
19 #if !defined(HOST_ARCH_ARM) | |
20 | |
21 #include "vm/allocation.h" | |
22 #include "vm/constants_arm.h" | |
23 #include "vm/object.h" | |
24 | |
25 namespace dart { | |
26 | |
27 class Isolate; | |
28 class SimulatorSetjmpBuffer; | |
29 | |
30 class Simulator { | |
31 public: | |
32 static const size_t kSimulatorStackUnderflowSize = 64; | |
33 | |
34 Simulator(); | |
35 ~Simulator(); | |
36 | |
37 // The currently executing Simulator instance. Potentially there can be one | |
38 // for each isolate. | |
siva
2013/01/24 02:03:09
There should be one for each isolate right, not su
Ivan Posva
2013/01/24 18:25:57
Actually the Simulator should be tied to the threa
regis
2013/01/24 21:47:48
No, there is zero or one simulator per isolate. If
regis
2013/01/24 21:47:48
OK, leaving as is for now.
| |
39 static Simulator* Current(); | |
40 | |
41 // Accessors for register state. Reading the pc value adheres to the ARM | |
42 // architecture specification and is off by 8 from the currently executing | |
43 // instruction. | |
44 void set_register(Register reg, int32_t value); | |
45 int32_t get_register(Register reg) const; | |
46 | |
47 // Special case of set_register and get_register to access the raw PC value. | |
48 void set_pc(int32_t value); | |
49 int32_t get_pc() const; | |
50 | |
51 // Accessors for VFP register state. | |
52 void set_sregister(SRegister reg, float value); | |
53 float get_sregister(SRegister reg) const; | |
54 void set_dregister(DRegister reg, double value); | |
55 double get_dregister(DRegister reg) const; | |
56 | |
57 // Accessor to the internal simulator stack area. | |
58 uintptr_t StackTop() const; | |
59 uintptr_t StackLimit() const; | |
60 | |
61 // Executes ARM instructions until the PC reaches end_sim_pc. | |
62 void Execute(); | |
63 | |
64 // Call on program start. | |
65 static void InitOnce(); | |
66 | |
67 // Dart generally calls into generated code with 5 parameters. This is a | |
68 // convenience function, which sets up the simulator state and grabs the | |
69 // result on return. | |
70 int64_t Call(int32_t entry, | |
71 int32_t parameter0, | |
72 int32_t parameter1, | |
73 int32_t parameter2, | |
74 int32_t parameter3, | |
75 int32_t parameter4); | |
76 | |
77 // Implementation of atomic compare and exchange in the same synchronization | |
78 // domain as other synchronization primitive instructions (e.g. ldrex, strex). | |
79 static uword CompareExchange(uword* address, | |
80 uword compare_value, | |
81 uword new_value); | |
82 | |
83 // Runtime call support. | |
84 static uword RedirectExternalReference(void* function, | |
85 uint32_t argument_count); | |
86 | |
87 void Longjmp(int32_t pc, int32_t sp, int32_t fp, const Instance& object); | |
88 | |
89 private: | |
90 // Known bad pc value to ensure that the simulator does not execute | |
91 // without being properly setup. | |
92 static const uword kBadLR = -1; | |
93 // A pc value used to signal the simulator to stop execution. Generally | |
94 // the lr is set to this value on transition from native C code to | |
95 // simulated execution, so that the simulator can "return" to the native | |
96 // C code. | |
97 static const uword kEndSimulatingPC = -2; | |
98 | |
99 // CPU state. | |
100 int32_t registers_[kNumberOfCpuRegisters]; | |
101 bool n_flag_; | |
102 bool z_flag_; | |
103 bool c_flag_; | |
104 bool v_flag_; | |
105 | |
106 // VFP state. | |
107 union { // S and D register banks are overlapping. | |
108 float sregisters_[kNumberOfSRegisters]; | |
109 double dregisters_[kNumberOfDRegisters]; | |
110 }; | |
111 bool fp_n_flag_; | |
112 bool fp_z_flag_; | |
113 bool fp_c_flag_; | |
114 bool fp_v_flag_; | |
115 | |
116 // Simulator support. | |
117 char* stack_; | |
118 bool pc_modified_; | |
119 int icount_; | |
120 static bool flag_trace_sim_; | |
121 static int32_t flag_stop_sim_at_; | |
122 SimulatorSetjmpBuffer* last_setjmp_buffer_; | |
123 | |
124 // Registered breakpoints. | |
125 Instr* break_pc_; | |
126 int32_t break_instr_; | |
127 | |
128 // Implicit null guard support. | |
129 void HandleNullPageAccess(uword addr, Instr* instr); | |
130 | |
131 // Unsupported instructions use Format to print an error and stop execution. | |
132 void Format(Instr* instr, const char* format); | |
133 | |
134 // Checks if the current instruction should be executed based on its | |
135 // condition bits. | |
136 bool ConditionallyExecute(Instr* instr); | |
137 | |
138 // Helper functions to set the conditional flags in the architecture state. | |
139 void SetNZFlags(int32_t val); | |
140 void SetCFlag(bool val); | |
141 void SetVFlag(bool val); | |
142 bool CarryFrom(int32_t left, int32_t right); | |
143 bool BorrowFrom(int32_t left, int32_t right); | |
144 bool OverflowFrom(int32_t alu_out, | |
145 int32_t left, | |
146 int32_t right, | |
147 bool addition); | |
148 | |
149 // Helper functions to decode common "addressing" modes. | |
150 int32_t GetShiftRm(Instr* instr, bool* carry_out); | |
151 int32_t GetImm(Instr* instr, bool* carry_out); | |
152 void HandleRList(Instr* instr, bool load); | |
153 void SupervisorCall(Instr* instr); | |
154 | |
155 // Read and write memory. | |
156 void UnalignedAccess(const char* msg, uword addr, Instr* instr); | |
157 | |
158 inline uint8_t ReadBU(uword addr); | |
159 inline int8_t ReadB(uword addr); | |
160 inline void WriteB(uword addr, uint8_t value); | |
161 | |
162 inline uint16_t ReadHU(uword addr, Instr* instr); | |
163 inline int16_t ReadH(uword addr, Instr* instr); | |
164 inline void WriteH(uword addr, uint16_t value, Instr* instr); | |
165 | |
166 inline int ReadW(uword addr, Instr* instr); | |
167 inline void WriteW(uword addr, int value, Instr* instr); | |
168 | |
169 // Synchronization primitives support. | |
170 void ClearExclusive(); | |
171 int ReadExclusiveW(uword addr, Instr* instr); | |
172 int WriteExclusiveW(uword addr, int value, Instr* instr); | |
173 | |
174 // In Dart, there is at most one thread per isolate. | |
175 // We keep track of 16 exclusive access address tags across all isolates. | |
176 // Since we cannot simulate a native context switch, which clears | |
177 // the exclusive access state of the local monitor (using the CLREX | |
178 // instruction), we associate the isolate requesting exclusive access to the | |
179 // address tag. Multiple isolates requesting exclusive access (using the LDREX | |
180 // instruction) to the same address will result in multiple address tags being | |
181 // created for the same address, one per isolate. | |
182 // At any given time, each isolate is associated to at most one address tag. | |
183 static Mutex* exclusive_access_lock_; | |
184 static const int kNumAddressTags = 16; | |
185 static struct AddressTag { | |
186 Isolate* isolate; | |
187 uword addr; | |
188 } exclusive_access_state_[kNumAddressTags]; | |
siva
2013/01/24 02:03:09
Not sure if we will require this as there will be
regis
2013/01/24 21:47:48
TODO(regis) added.
| |
189 static int next_address_tag_; | |
190 | |
191 // Set access to given address to 'exclusive state' for current isolate. | |
192 static void SetExclusiveAccess(uword addr); | |
193 | |
194 // Returns true if the current isolate has exclusive access to given address, | |
195 // returns false otherwise. In either case, set access to given address to | |
196 // 'open state' for all isolates. | |
197 // If given addr is NULL, set access to 'open state' for current | |
198 // isolate (CLREX). | |
199 static bool HasExclusiveAccessAndOpen(uword addr); | |
200 | |
201 // Executing is handled based on the instruction type. | |
202 void DecodeType01(Instr* instr); // Both type 0 and type 1 rolled into one. | |
203 void DecodeType2(Instr* instr); | |
204 void DecodeType3(Instr* instr); | |
205 void DecodeType4(Instr* instr); | |
206 void DecodeType5(Instr* instr); | |
207 void DecodeType6(Instr* instr); | |
208 void DecodeType7(Instr* instr); | |
209 | |
210 // Executes one instruction. | |
211 void InstructionDecode(Instr* instr); | |
212 | |
213 // Longjmp support for exceptions. | |
214 SimulatorSetjmpBuffer* last_setjmp_buffer() { | |
215 return last_setjmp_buffer_; | |
216 } | |
217 void set_last_setjmp_buffer(SimulatorSetjmpBuffer* buffer) { | |
218 last_setjmp_buffer_ = buffer; | |
219 } | |
220 | |
221 friend class SimulatorDebugger; | |
222 friend class SimulatorSetjmpBuffer; | |
223 DISALLOW_COPY_AND_ASSIGN(Simulator); | |
224 }; | |
225 | |
226 } // namespace dart | |
227 | |
228 #endif // !defined(HOST_ARCH_ARM) | |
229 | |
230 #endif // VM_SIMULATOR_ARM_H_ | |
OLD | NEW |