OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 <setjmp.h> // NOLINT | 5 #include <setjmp.h> // NOLINT |
6 #include <stdlib.h> | 6 #include <stdlib.h> |
7 | 7 |
8 #include "vm/globals.h" | 8 #include "vm/globals.h" |
9 #if defined(TARGET_ARCH_ARM64) | 9 #if defined(TARGET_ARCH_ARM64) |
10 | 10 |
11 // Only build the simulator if not compiling for real ARM hardware. | 11 // Only build the simulator if not compiling for real ARM hardware. |
12 #if defined(USING_SIMULATOR) | 12 #if defined(USING_SIMULATOR) |
13 | 13 |
14 #include "vm/simulator.h" | 14 #include "vm/simulator.h" |
15 | 15 |
16 #include "vm/assembler.h" | 16 #include "vm/assembler.h" |
17 #include "vm/constants_arm64.h" | 17 #include "vm/constants_arm64.h" |
18 #include "vm/disassembler.h" | 18 #include "vm/disassembler.h" |
19 #include "vm/lockers.h" | 19 #include "vm/lockers.h" |
20 #include "vm/native_arguments.h" | 20 #include "vm/native_arguments.h" |
| 21 #include "vm/os_thread.h" |
21 #include "vm/stack_frame.h" | 22 #include "vm/stack_frame.h" |
22 #include "vm/os_thread.h" | |
23 | 23 |
24 namespace dart { | 24 namespace dart { |
25 | 25 |
26 DEFINE_FLAG(uint64_t, | 26 DEFINE_FLAG(uint64_t, |
27 trace_sim_after, | 27 trace_sim_after, |
28 ULLONG_MAX, | 28 ULLONG_MAX, |
29 "Trace simulator execution after instruction count reached."); | 29 "Trace simulator execution after instruction count reached."); |
30 DEFINE_FLAG(uint64_t, | 30 DEFINE_FLAG(uint64_t, |
31 stop_sim_at, | 31 stop_sim_at, |
32 ULLONG_MAX, | 32 ULLONG_MAX, |
33 "Instruction address or instruction count to stop simulator at."); | 33 "Instruction address or instruction count to stop simulator at."); |
34 | 34 |
35 | |
36 // This macro provides a platform independent use of sscanf. The reason for | 35 // This macro provides a platform independent use of sscanf. The reason for |
37 // SScanF not being implemented in a platform independent way through | 36 // SScanF not being implemented in a platform independent way through |
38 // OS in the same way as SNPrint is that the Windows C Run-Time | 37 // OS in the same way as SNPrint is that the Windows C Run-Time |
39 // Library does not provide vsscanf. | 38 // Library does not provide vsscanf. |
40 #define SScanF sscanf // NOLINT | 39 #define SScanF sscanf // NOLINT |
41 | 40 |
42 | |
43 // SimulatorSetjmpBuffer are linked together, and the last created one | 41 // SimulatorSetjmpBuffer are linked together, and the last created one |
44 // is referenced by the Simulator. When an exception is thrown, the exception | 42 // is referenced by the Simulator. When an exception is thrown, the exception |
45 // runtime looks at where to jump and finds the corresponding | 43 // runtime looks at where to jump and finds the corresponding |
46 // SimulatorSetjmpBuffer based on the stack pointer of the exception handler. | 44 // SimulatorSetjmpBuffer based on the stack pointer of the exception handler. |
47 // The runtime then does a Longjmp on that buffer to return to the simulator. | 45 // The runtime then does a Longjmp on that buffer to return to the simulator. |
48 class SimulatorSetjmpBuffer { | 46 class SimulatorSetjmpBuffer { |
49 public: | 47 public: |
50 void Longjmp() { | 48 void Longjmp() { |
51 // "This" is now the last setjmp buffer. | 49 // "This" is now the last setjmp buffer. |
52 simulator_->set_last_setjmp_buffer(this); | 50 simulator_->set_last_setjmp_buffer(this); |
(...skipping 18 matching lines...) Expand all Loading... |
71 | 69 |
72 private: | 70 private: |
73 uword sp_; | 71 uword sp_; |
74 Simulator* simulator_; | 72 Simulator* simulator_; |
75 SimulatorSetjmpBuffer* link_; | 73 SimulatorSetjmpBuffer* link_; |
76 jmp_buf buffer_; | 74 jmp_buf buffer_; |
77 | 75 |
78 friend class Simulator; | 76 friend class Simulator; |
79 }; | 77 }; |
80 | 78 |
81 | |
82 // The SimulatorDebugger class is used by the simulator while debugging | 79 // The SimulatorDebugger class is used by the simulator while debugging |
83 // simulated ARM64 code. | 80 // simulated ARM64 code. |
84 class SimulatorDebugger { | 81 class SimulatorDebugger { |
85 public: | 82 public: |
86 explicit SimulatorDebugger(Simulator* sim); | 83 explicit SimulatorDebugger(Simulator* sim); |
87 ~SimulatorDebugger(); | 84 ~SimulatorDebugger(); |
88 | 85 |
89 void Stop(Instr* instr, const char* message); | 86 void Stop(Instr* instr, const char* message); |
90 void Debug(); | 87 void Debug(); |
91 char* ReadLine(const char* prompt); | 88 char* ReadLine(const char* prompt); |
(...skipping 20 matching lines...) Expand all Loading... |
112 // Set or delete a breakpoint. Returns true if successful. | 109 // Set or delete a breakpoint. Returns true if successful. |
113 bool SetBreakpoint(Instr* breakpc); | 110 bool SetBreakpoint(Instr* breakpc); |
114 bool DeleteBreakpoint(Instr* breakpc); | 111 bool DeleteBreakpoint(Instr* breakpc); |
115 | 112 |
116 // Undo and redo all breakpoints. This is needed to bracket disassembly and | 113 // Undo and redo all breakpoints. This is needed to bracket disassembly and |
117 // execution to skip past breakpoints when run from the debugger. | 114 // execution to skip past breakpoints when run from the debugger. |
118 void UndoBreakpoints(); | 115 void UndoBreakpoints(); |
119 void RedoBreakpoints(); | 116 void RedoBreakpoints(); |
120 }; | 117 }; |
121 | 118 |
122 | |
123 SimulatorDebugger::SimulatorDebugger(Simulator* sim) { | 119 SimulatorDebugger::SimulatorDebugger(Simulator* sim) { |
124 sim_ = sim; | 120 sim_ = sim; |
125 } | 121 } |
126 | 122 |
127 | |
128 SimulatorDebugger::~SimulatorDebugger() {} | 123 SimulatorDebugger::~SimulatorDebugger() {} |
129 | 124 |
130 | |
131 void SimulatorDebugger::Stop(Instr* instr, const char* message) { | 125 void SimulatorDebugger::Stop(Instr* instr, const char* message) { |
132 OS::Print("Simulator hit %s\n", message); | 126 OS::Print("Simulator hit %s\n", message); |
133 Debug(); | 127 Debug(); |
134 } | 128 } |
135 | 129 |
136 | |
137 static Register LookupCpuRegisterByName(const char* name) { | 130 static Register LookupCpuRegisterByName(const char* name) { |
138 static const char* kNames[] = { | 131 static const char* kNames[] = { |
139 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", | 132 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", |
140 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", | 133 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", |
141 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", | 134 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", |
142 "r24", "r25", "r26", "r27", "r28", "r29", "r30", | 135 "r24", "r25", "r26", "r27", "r28", "r29", "r30", |
143 | 136 |
144 "ip0", "ip1", "pp", "ctx", "fp", "lr", "sp", "zr", | 137 "ip0", "ip1", "pp", "ctx", "fp", "lr", "sp", "zr", |
145 }; | 138 }; |
146 static const Register kRegisters[] = { | 139 static const Register kRegisters[] = { |
147 R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, | 140 R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, |
148 R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, | 141 R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, |
149 R22, R23, R24, R25, R26, R27, R28, R29, R30, | 142 R22, R23, R24, R25, R26, R27, R28, R29, R30, |
150 | 143 |
151 IP0, IP1, PP, CTX, FP, LR, R31, ZR, | 144 IP0, IP1, PP, CTX, FP, LR, R31, ZR, |
152 }; | 145 }; |
153 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters)); | 146 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters)); |
154 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) { | 147 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) { |
155 if (strcmp(kNames[i], name) == 0) { | 148 if (strcmp(kNames[i], name) == 0) { |
156 return kRegisters[i]; | 149 return kRegisters[i]; |
157 } | 150 } |
158 } | 151 } |
159 return kNoRegister; | 152 return kNoRegister; |
160 } | 153 } |
161 | 154 |
162 | |
163 static VRegister LookupVRegisterByName(const char* name) { | 155 static VRegister LookupVRegisterByName(const char* name) { |
164 int reg_nr = -1; | 156 int reg_nr = -1; |
165 bool ok = SScanF(name, "v%d", ®_nr); | 157 bool ok = SScanF(name, "v%d", ®_nr); |
166 if (ok && (0 <= reg_nr) && (reg_nr < kNumberOfVRegisters)) { | 158 if (ok && (0 <= reg_nr) && (reg_nr < kNumberOfVRegisters)) { |
167 return static_cast<VRegister>(reg_nr); | 159 return static_cast<VRegister>(reg_nr); |
168 } | 160 } |
169 return kNoVRegister; | 161 return kNoVRegister; |
170 } | 162 } |
171 | 163 |
172 | |
173 bool SimulatorDebugger::GetValue(char* desc, uint64_t* value) { | 164 bool SimulatorDebugger::GetValue(char* desc, uint64_t* value) { |
174 Register reg = LookupCpuRegisterByName(desc); | 165 Register reg = LookupCpuRegisterByName(desc); |
175 if (reg != kNoRegister) { | 166 if (reg != kNoRegister) { |
176 if (reg == ZR) { | 167 if (reg == ZR) { |
177 *value = 0; | 168 *value = 0; |
178 return true; | 169 return true; |
179 } | 170 } |
180 *value = sim_->get_register(reg); | 171 *value = sim_->get_register(reg); |
181 return true; | 172 return true; |
182 } | 173 } |
(...skipping 11 matching lines...) Expand all Loading... |
194 *value = sim_->get_pc(); | 185 *value = sim_->get_pc(); |
195 return true; | 186 return true; |
196 } | 187 } |
197 bool retval = SScanF(desc, "0x%" Px64, value) == 1; | 188 bool retval = SScanF(desc, "0x%" Px64, value) == 1; |
198 if (!retval) { | 189 if (!retval) { |
199 retval = SScanF(desc, "%" Px64, value) == 1; | 190 retval = SScanF(desc, "%" Px64, value) == 1; |
200 } | 191 } |
201 return retval; | 192 return retval; |
202 } | 193 } |
203 | 194 |
204 | |
205 bool SimulatorDebugger::GetSValue(char* desc, uint32_t* value) { | 195 bool SimulatorDebugger::GetSValue(char* desc, uint32_t* value) { |
206 VRegister vreg = LookupVRegisterByName(desc); | 196 VRegister vreg = LookupVRegisterByName(desc); |
207 if (vreg != kNoVRegister) { | 197 if (vreg != kNoVRegister) { |
208 *value = sim_->get_vregisters(vreg, 0); | 198 *value = sim_->get_vregisters(vreg, 0); |
209 return true; | 199 return true; |
210 } | 200 } |
211 if (desc[0] == '*') { | 201 if (desc[0] == '*') { |
212 uint64_t addr; | 202 uint64_t addr; |
213 if (GetValue(desc + 1, &addr)) { | 203 if (GetValue(desc + 1, &addr)) { |
214 if (Simulator::IsIllegalAddress(addr)) { | 204 if (Simulator::IsIllegalAddress(addr)) { |
215 return false; | 205 return false; |
216 } | 206 } |
217 *value = *(reinterpret_cast<uint32_t*>(addr)); | 207 *value = *(reinterpret_cast<uint32_t*>(addr)); |
218 return true; | 208 return true; |
219 } | 209 } |
220 } | 210 } |
221 return false; | 211 return false; |
222 } | 212 } |
223 | 213 |
224 | |
225 bool SimulatorDebugger::GetDValue(char* desc, uint64_t* value) { | 214 bool SimulatorDebugger::GetDValue(char* desc, uint64_t* value) { |
226 VRegister vreg = LookupVRegisterByName(desc); | 215 VRegister vreg = LookupVRegisterByName(desc); |
227 if (vreg != kNoVRegister) { | 216 if (vreg != kNoVRegister) { |
228 *value = sim_->get_vregisterd(vreg, 0); | 217 *value = sim_->get_vregisterd(vreg, 0); |
229 return true; | 218 return true; |
230 } | 219 } |
231 if (desc[0] == '*') { | 220 if (desc[0] == '*') { |
232 uint64_t addr; | 221 uint64_t addr; |
233 if (GetValue(desc + 1, &addr)) { | 222 if (GetValue(desc + 1, &addr)) { |
234 if (Simulator::IsIllegalAddress(addr)) { | 223 if (Simulator::IsIllegalAddress(addr)) { |
235 return false; | 224 return false; |
236 } | 225 } |
237 *value = *(reinterpret_cast<uint64_t*>(addr)); | 226 *value = *(reinterpret_cast<uint64_t*>(addr)); |
238 return true; | 227 return true; |
239 } | 228 } |
240 } | 229 } |
241 return false; | 230 return false; |
242 } | 231 } |
243 | 232 |
244 | |
245 bool SimulatorDebugger::GetQValue(char* desc, simd_value_t* value) { | 233 bool SimulatorDebugger::GetQValue(char* desc, simd_value_t* value) { |
246 VRegister vreg = LookupVRegisterByName(desc); | 234 VRegister vreg = LookupVRegisterByName(desc); |
247 if (vreg != kNoVRegister) { | 235 if (vreg != kNoVRegister) { |
248 sim_->get_vregister(vreg, value); | 236 sim_->get_vregister(vreg, value); |
249 return true; | 237 return true; |
250 } | 238 } |
251 if (desc[0] == '*') { | 239 if (desc[0] == '*') { |
252 uint64_t addr; | 240 uint64_t addr; |
253 if (GetValue(desc + 1, &addr)) { | 241 if (GetValue(desc + 1, &addr)) { |
254 if (Simulator::IsIllegalAddress(addr)) { | 242 if (Simulator::IsIllegalAddress(addr)) { |
255 return false; | 243 return false; |
256 } | 244 } |
257 *value = *(reinterpret_cast<simd_value_t*>(addr)); | 245 *value = *(reinterpret_cast<simd_value_t*>(addr)); |
258 return true; | 246 return true; |
259 } | 247 } |
260 } | 248 } |
261 return false; | 249 return false; |
262 } | 250 } |
263 | 251 |
264 | |
265 TokenPosition SimulatorDebugger::GetApproximateTokenIndex(const Code& code, | 252 TokenPosition SimulatorDebugger::GetApproximateTokenIndex(const Code& code, |
266 uword pc) { | 253 uword pc) { |
267 TokenPosition token_pos = TokenPosition::kNoSource; | 254 TokenPosition token_pos = TokenPosition::kNoSource; |
268 uword pc_offset = pc - code.PayloadStart(); | 255 uword pc_offset = pc - code.PayloadStart(); |
269 const PcDescriptors& descriptors = | 256 const PcDescriptors& descriptors = |
270 PcDescriptors::Handle(code.pc_descriptors()); | 257 PcDescriptors::Handle(code.pc_descriptors()); |
271 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind); | 258 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind); |
272 while (iter.MoveNext()) { | 259 while (iter.MoveNext()) { |
273 if (iter.PcOffset() == pc_offset) { | 260 if (iter.PcOffset() == pc_offset) { |
274 return iter.TokenPos(); | 261 return iter.TokenPos(); |
275 } else if (!token_pos.IsReal() && (iter.PcOffset() > pc_offset)) { | 262 } else if (!token_pos.IsReal() && (iter.PcOffset() > pc_offset)) { |
276 token_pos = iter.TokenPos(); | 263 token_pos = iter.TokenPos(); |
277 } | 264 } |
278 } | 265 } |
279 return token_pos; | 266 return token_pos; |
280 } | 267 } |
281 | 268 |
282 | |
283 void SimulatorDebugger::PrintDartFrame(uword pc, | 269 void SimulatorDebugger::PrintDartFrame(uword pc, |
284 uword fp, | 270 uword fp, |
285 uword sp, | 271 uword sp, |
286 const Function& function, | 272 const Function& function, |
287 TokenPosition token_pos, | 273 TokenPosition token_pos, |
288 bool is_optimized, | 274 bool is_optimized, |
289 bool is_inlined) { | 275 bool is_inlined) { |
290 const Script& script = Script::Handle(function.script()); | 276 const Script& script = Script::Handle(function.script()); |
291 const String& func_name = String::Handle(function.QualifiedScrubbedName()); | 277 const String& func_name = String::Handle(function.QualifiedScrubbedName()); |
292 const String& url = String::Handle(script.url()); | 278 const String& url = String::Handle(script.url()); |
293 intptr_t line = -1; | 279 intptr_t line = -1; |
294 intptr_t column = -1; | 280 intptr_t column = -1; |
295 if (token_pos.IsReal()) { | 281 if (token_pos.IsReal()) { |
296 script.GetTokenLocation(token_pos, &line, &column); | 282 script.GetTokenLocation(token_pos, &line, &column); |
297 } | 283 } |
298 OS::Print( | 284 OS::Print( |
299 "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")\n", pc, | 285 "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")\n", pc, |
300 fp, sp, is_optimized ? (is_inlined ? "inlined " : "optimized ") : "", | 286 fp, sp, is_optimized ? (is_inlined ? "inlined " : "optimized ") : "", |
301 func_name.ToCString(), url.ToCString(), line, column); | 287 func_name.ToCString(), url.ToCString(), line, column); |
302 } | 288 } |
303 | 289 |
304 | |
305 void SimulatorDebugger::PrintBacktrace() { | 290 void SimulatorDebugger::PrintBacktrace() { |
306 StackFrameIterator frames( | 291 StackFrameIterator frames( |
307 sim_->get_register(FP), sim_->get_register(SP), sim_->get_pc(), | 292 sim_->get_register(FP), sim_->get_register(SP), sim_->get_pc(), |
308 StackFrameIterator::kDontValidateFrames, Thread::Current(), | 293 StackFrameIterator::kDontValidateFrames, Thread::Current(), |
309 StackFrameIterator::kNoCrossThreadIteration); | 294 StackFrameIterator::kNoCrossThreadIteration); |
310 StackFrame* frame = frames.NextFrame(); | 295 StackFrame* frame = frames.NextFrame(); |
311 ASSERT(frame != NULL); | 296 ASSERT(frame != NULL); |
312 Function& function = Function::Handle(); | 297 Function& function = Function::Handle(); |
313 Function& inlined_function = Function::Handle(); | 298 Function& inlined_function = Function::Handle(); |
314 Code& code = Code::Handle(); | 299 Code& code = Code::Handle(); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 frame->IsEntryFrame() | 331 frame->IsEntryFrame() |
347 ? "entry" | 332 ? "entry" |
348 : frame->IsExitFrame() | 333 : frame->IsExitFrame() |
349 ? "exit" | 334 ? "exit" |
350 : frame->IsStubFrame() ? "stub" : "invalid"); | 335 : frame->IsStubFrame() ? "stub" : "invalid"); |
351 } | 336 } |
352 frame = frames.NextFrame(); | 337 frame = frames.NextFrame(); |
353 } | 338 } |
354 } | 339 } |
355 | 340 |
356 | |
357 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { | 341 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { |
358 // Check if a breakpoint can be set. If not return without any side-effects. | 342 // Check if a breakpoint can be set. If not return without any side-effects. |
359 if (sim_->break_pc_ != NULL) { | 343 if (sim_->break_pc_ != NULL) { |
360 return false; | 344 return false; |
361 } | 345 } |
362 | 346 |
363 // Set the breakpoint. | 347 // Set the breakpoint. |
364 sim_->break_pc_ = breakpc; | 348 sim_->break_pc_ = breakpc; |
365 sim_->break_instr_ = breakpc->InstructionBits(); | 349 sim_->break_instr_ = breakpc->InstructionBits(); |
366 // Not setting the breakpoint instruction in the code itself. It will be set | 350 // Not setting the breakpoint instruction in the code itself. It will be set |
367 // when the debugger shell continues. | 351 // when the debugger shell continues. |
368 return true; | 352 return true; |
369 } | 353 } |
370 | 354 |
371 | |
372 bool SimulatorDebugger::DeleteBreakpoint(Instr* breakpc) { | 355 bool SimulatorDebugger::DeleteBreakpoint(Instr* breakpc) { |
373 if (sim_->break_pc_ != NULL) { | 356 if (sim_->break_pc_ != NULL) { |
374 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); | 357 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); |
375 } | 358 } |
376 | 359 |
377 sim_->break_pc_ = NULL; | 360 sim_->break_pc_ = NULL; |
378 sim_->break_instr_ = 0; | 361 sim_->break_instr_ = 0; |
379 return true; | 362 return true; |
380 } | 363 } |
381 | 364 |
382 | |
383 void SimulatorDebugger::UndoBreakpoints() { | 365 void SimulatorDebugger::UndoBreakpoints() { |
384 if (sim_->break_pc_ != NULL) { | 366 if (sim_->break_pc_ != NULL) { |
385 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); | 367 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); |
386 } | 368 } |
387 } | 369 } |
388 | 370 |
389 | |
390 void SimulatorDebugger::RedoBreakpoints() { | 371 void SimulatorDebugger::RedoBreakpoints() { |
391 if (sim_->break_pc_ != NULL) { | 372 if (sim_->break_pc_ != NULL) { |
392 sim_->break_pc_->SetInstructionBits(Instr::kSimulatorBreakpointInstruction); | 373 sim_->break_pc_->SetInstructionBits(Instr::kSimulatorBreakpointInstruction); |
393 } | 374 } |
394 } | 375 } |
395 | 376 |
396 | |
397 void SimulatorDebugger::Debug() { | 377 void SimulatorDebugger::Debug() { |
398 intptr_t last_pc = -1; | 378 intptr_t last_pc = -1; |
399 bool done = false; | 379 bool done = false; |
400 | 380 |
401 #define COMMAND_SIZE 63 | 381 #define COMMAND_SIZE 63 |
402 #define ARG_SIZE 255 | 382 #define ARG_SIZE 255 |
403 | 383 |
404 #define STR(a) #a | 384 #define STR(a) #a |
405 #define XSTR(a) STR(a) | 385 #define XSTR(a) STR(a) |
406 | 386 |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
661 // shell when hit. | 641 // shell when hit. |
662 RedoBreakpoints(); | 642 RedoBreakpoints(); |
663 | 643 |
664 #undef COMMAND_SIZE | 644 #undef COMMAND_SIZE |
665 #undef ARG_SIZE | 645 #undef ARG_SIZE |
666 | 646 |
667 #undef STR | 647 #undef STR |
668 #undef XSTR | 648 #undef XSTR |
669 } | 649 } |
670 | 650 |
671 | |
672 char* SimulatorDebugger::ReadLine(const char* prompt) { | 651 char* SimulatorDebugger::ReadLine(const char* prompt) { |
673 char* result = NULL; | 652 char* result = NULL; |
674 char line_buf[256]; | 653 char line_buf[256]; |
675 intptr_t offset = 0; | 654 intptr_t offset = 0; |
676 bool keep_going = true; | 655 bool keep_going = true; |
677 OS::Print("%s", prompt); | 656 OS::Print("%s", prompt); |
678 while (keep_going) { | 657 while (keep_going) { |
679 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) { | 658 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) { |
680 // fgets got an error. Just give up. | 659 // fgets got an error. Just give up. |
681 if (result != NULL) { | 660 if (result != NULL) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
720 } | 699 } |
721 // Copy the newly read line into the result. | 700 // Copy the newly read line into the result. |
722 memmove(result + offset, line_buf, len); | 701 memmove(result + offset, line_buf, len); |
723 offset += len; | 702 offset += len; |
724 } | 703 } |
725 ASSERT(result != NULL); | 704 ASSERT(result != NULL); |
726 result[offset] = '\0'; | 705 result[offset] = '\0'; |
727 return result; | 706 return result; |
728 } | 707 } |
729 | 708 |
730 | |
731 // Synchronization primitives support. | 709 // Synchronization primitives support. |
732 Mutex* Simulator::exclusive_access_lock_ = NULL; | 710 Mutex* Simulator::exclusive_access_lock_ = NULL; |
733 Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags] = { | 711 Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags] = { |
734 {NULL, 0}}; | 712 {NULL, 0}}; |
735 int Simulator::next_address_tag_ = 0; | 713 int Simulator::next_address_tag_ = 0; |
736 | 714 |
737 | |
738 void Simulator::InitOnce() { | 715 void Simulator::InitOnce() { |
739 // Setup exclusive access state lock. | 716 // Setup exclusive access state lock. |
740 exclusive_access_lock_ = new Mutex(); | 717 exclusive_access_lock_ = new Mutex(); |
741 } | 718 } |
742 | 719 |
743 | |
744 Simulator::Simulator() { | 720 Simulator::Simulator() { |
745 // Setup simulator support first. Some of this information is needed to | 721 // Setup simulator support first. Some of this information is needed to |
746 // setup the architecture state. | 722 // setup the architecture state. |
747 // We allocate the stack here, the size is computed as the sum of | 723 // We allocate the stack here, the size is computed as the sum of |
748 // the size specified by the user and the buffer space needed for | 724 // the size specified by the user and the buffer space needed for |
749 // handling stack overflow exceptions. To be safe in potential | 725 // handling stack overflow exceptions. To be safe in potential |
750 // stack underflows we also add some underflow buffer space. | 726 // stack underflows we also add some underflow buffer space. |
751 stack_ = | 727 stack_ = |
752 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer + | 728 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer + |
753 kSimulatorStackUnderflowSize)]; | 729 kSimulatorStackUnderflowSize)]; |
(...skipping 21 matching lines...) Expand all Loading... |
775 | 751 |
776 // The sp is initialized to point to the bottom (high address) of the | 752 // The sp is initialized to point to the bottom (high address) of the |
777 // allocated stack area. | 753 // allocated stack area. |
778 registers_[R31] = StackTop(); | 754 registers_[R31] = StackTop(); |
779 // The lr and pc are initialized to a known bad value that will cause an | 755 // The lr and pc are initialized to a known bad value that will cause an |
780 // access violation if the simulator ever tries to execute it. | 756 // access violation if the simulator ever tries to execute it. |
781 registers_[LR] = kBadLR; | 757 registers_[LR] = kBadLR; |
782 pc_ = kBadLR; | 758 pc_ = kBadLR; |
783 } | 759 } |
784 | 760 |
785 | |
786 Simulator::~Simulator() { | 761 Simulator::~Simulator() { |
787 delete[] stack_; | 762 delete[] stack_; |
788 Isolate* isolate = Isolate::Current(); | 763 Isolate* isolate = Isolate::Current(); |
789 if (isolate != NULL) { | 764 if (isolate != NULL) { |
790 isolate->set_simulator(NULL); | 765 isolate->set_simulator(NULL); |
791 } | 766 } |
792 } | 767 } |
793 | 768 |
794 | |
795 // When the generated code calls an external reference we need to catch that in | 769 // When the generated code calls an external reference we need to catch that in |
796 // the simulator. The external reference will be a function compiled for the | 770 // the simulator. The external reference will be a function compiled for the |
797 // host architecture. We need to call that function instead of trying to | 771 // host architecture. We need to call that function instead of trying to |
798 // execute it with the simulator. We do that by redirecting the external | 772 // execute it with the simulator. We do that by redirecting the external |
799 // reference to a svc (supervisor call) instruction that is handled by | 773 // reference to a svc (supervisor call) instruction that is handled by |
800 // the simulator. We write the original destination of the jump just at a known | 774 // the simulator. We write the original destination of the jump just at a known |
801 // offset from the svc instruction so the simulator knows what to call. | 775 // offset from the svc instruction so the simulator knows what to call. |
802 class Redirection { | 776 class Redirection { |
803 public: | 777 public: |
804 uword address_of_hlt_instruction() { | 778 uword address_of_hlt_instruction() { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 } | 834 } |
861 | 835 |
862 uword external_function_; | 836 uword external_function_; |
863 Simulator::CallKind call_kind_; | 837 Simulator::CallKind call_kind_; |
864 int argument_count_; | 838 int argument_count_; |
865 uint32_t hlt_instruction_; | 839 uint32_t hlt_instruction_; |
866 Redirection* next_; | 840 Redirection* next_; |
867 static Redirection* list_; | 841 static Redirection* list_; |
868 }; | 842 }; |
869 | 843 |
870 | |
871 Redirection* Redirection::list_ = NULL; | 844 Redirection* Redirection::list_ = NULL; |
872 | 845 |
873 | |
874 uword Simulator::RedirectExternalReference(uword function, | 846 uword Simulator::RedirectExternalReference(uword function, |
875 CallKind call_kind, | 847 CallKind call_kind, |
876 int argument_count) { | 848 int argument_count) { |
877 Redirection* redirection = | 849 Redirection* redirection = |
878 Redirection::Get(function, call_kind, argument_count); | 850 Redirection::Get(function, call_kind, argument_count); |
879 return redirection->address_of_hlt_instruction(); | 851 return redirection->address_of_hlt_instruction(); |
880 } | 852 } |
881 | 853 |
882 | |
883 uword Simulator::FunctionForRedirect(uword redirect) { | 854 uword Simulator::FunctionForRedirect(uword redirect) { |
884 return Redirection::FunctionForRedirect(redirect); | 855 return Redirection::FunctionForRedirect(redirect); |
885 } | 856 } |
886 | 857 |
887 | |
888 // Get the active Simulator for the current isolate. | 858 // Get the active Simulator for the current isolate. |
889 Simulator* Simulator::Current() { | 859 Simulator* Simulator::Current() { |
890 Simulator* simulator = Isolate::Current()->simulator(); | 860 Simulator* simulator = Isolate::Current()->simulator(); |
891 if (simulator == NULL) { | 861 if (simulator == NULL) { |
892 simulator = new Simulator(); | 862 simulator = new Simulator(); |
893 Isolate::Current()->set_simulator(simulator); | 863 Isolate::Current()->set_simulator(simulator); |
894 } | 864 } |
895 return simulator; | 865 return simulator; |
896 } | 866 } |
897 | 867 |
898 | |
899 // Sets the register in the architecture state. | 868 // Sets the register in the architecture state. |
900 void Simulator::set_register(Instr* instr, | 869 void Simulator::set_register(Instr* instr, |
901 Register reg, | 870 Register reg, |
902 int64_t value, | 871 int64_t value, |
903 R31Type r31t) { | 872 R31Type r31t) { |
904 // Register is in range. | 873 // Register is in range. |
905 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 874 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
906 ASSERT(instr == NULL || reg != R18); // R18 is globally reserved on iOS. | 875 ASSERT(instr == NULL || reg != R18); // R18 is globally reserved on iOS. |
907 if ((reg != R31) || (r31t != R31IsZR)) { | 876 if ((reg != R31) || (r31t != R31IsZR)) { |
908 registers_[reg] = value; | 877 registers_[reg] = value; |
909 // If we're setting CSP, make sure it is 16-byte aligned. In truth, CSP | 878 // If we're setting CSP, make sure it is 16-byte aligned. In truth, CSP |
910 // can store addresses that are not 16-byte aligned, but loads and stores | 879 // can store addresses that are not 16-byte aligned, but loads and stores |
911 // are not allowed through CSP when it is not aligned. Thus, this check is | 880 // are not allowed through CSP when it is not aligned. Thus, this check is |
912 // more conservative that necessary. However, it will likely be more | 881 // more conservative that necessary. However, it will likely be more |
913 // useful to find the program locations where CSP is set to a bad value, | 882 // useful to find the program locations where CSP is set to a bad value, |
914 // than to find only the resulting loads/stores that would cause a fault on | 883 // than to find only the resulting loads/stores that would cause a fault on |
915 // hardware. | 884 // hardware. |
916 if ((instr != NULL) && (reg == R31) && !Utils::IsAligned(value, 16)) { | 885 if ((instr != NULL) && (reg == R31) && !Utils::IsAligned(value, 16)) { |
917 UnalignedAccess("CSP set", value, instr); | 886 UnalignedAccess("CSP set", value, instr); |
918 } | 887 } |
919 } | 888 } |
920 } | 889 } |
921 | 890 |
922 | |
923 // Get the register from the architecture state. | 891 // Get the register from the architecture state. |
924 int64_t Simulator::get_register(Register reg, R31Type r31t) const { | 892 int64_t Simulator::get_register(Register reg, R31Type r31t) const { |
925 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 893 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
926 if ((reg == R31) && (r31t == R31IsZR)) { | 894 if ((reg == R31) && (r31t == R31IsZR)) { |
927 return 0; | 895 return 0; |
928 } else { | 896 } else { |
929 return registers_[reg]; | 897 return registers_[reg]; |
930 } | 898 } |
931 } | 899 } |
932 | 900 |
933 | |
934 void Simulator::set_wregister(Register reg, int32_t value, R31Type r31t) { | 901 void Simulator::set_wregister(Register reg, int32_t value, R31Type r31t) { |
935 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 902 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
936 // When setting in W mode, clear the high bits. | 903 // When setting in W mode, clear the high bits. |
937 if ((reg != R31) || (r31t != R31IsZR)) { | 904 if ((reg != R31) || (r31t != R31IsZR)) { |
938 registers_[reg] = Utils::LowHighTo64Bits(static_cast<uint32_t>(value), 0); | 905 registers_[reg] = Utils::LowHighTo64Bits(static_cast<uint32_t>(value), 0); |
939 } | 906 } |
940 } | 907 } |
941 | 908 |
942 | |
943 // Get the register from the architecture state. | 909 // Get the register from the architecture state. |
944 int32_t Simulator::get_wregister(Register reg, R31Type r31t) const { | 910 int32_t Simulator::get_wregister(Register reg, R31Type r31t) const { |
945 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 911 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
946 if ((reg == R31) && (r31t == R31IsZR)) { | 912 if ((reg == R31) && (r31t == R31IsZR)) { |
947 return 0; | 913 return 0; |
948 } else { | 914 } else { |
949 return static_cast<int32_t>(registers_[reg]); | 915 return static_cast<int32_t>(registers_[reg]); |
950 } | 916 } |
951 } | 917 } |
952 | 918 |
953 | |
954 int32_t Simulator::get_vregisters(VRegister reg, int idx) const { | 919 int32_t Simulator::get_vregisters(VRegister reg, int idx) const { |
955 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); | 920 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); |
956 ASSERT((idx >= 0) && (idx <= 3)); | 921 ASSERT((idx >= 0) && (idx <= 3)); |
957 return vregisters_[reg].bits.i32[idx]; | 922 return vregisters_[reg].bits.i32[idx]; |
958 } | 923 } |
959 | 924 |
960 | |
961 void Simulator::set_vregisters(VRegister reg, int idx, int32_t value) { | 925 void Simulator::set_vregisters(VRegister reg, int idx, int32_t value) { |
962 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); | 926 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); |
963 ASSERT((idx >= 0) && (idx <= 3)); | 927 ASSERT((idx >= 0) && (idx <= 3)); |
964 vregisters_[reg].bits.i32[idx] = value; | 928 vregisters_[reg].bits.i32[idx] = value; |
965 } | 929 } |
966 | 930 |
967 | |
968 int64_t Simulator::get_vregisterd(VRegister reg, int idx) const { | 931 int64_t Simulator::get_vregisterd(VRegister reg, int idx) const { |
969 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); | 932 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); |
970 ASSERT((idx == 0) || (idx == 1)); | 933 ASSERT((idx == 0) || (idx == 1)); |
971 return vregisters_[reg].bits.i64[idx]; | 934 return vregisters_[reg].bits.i64[idx]; |
972 } | 935 } |
973 | 936 |
974 | |
975 void Simulator::set_vregisterd(VRegister reg, int idx, int64_t value) { | 937 void Simulator::set_vregisterd(VRegister reg, int idx, int64_t value) { |
976 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); | 938 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); |
977 ASSERT((idx == 0) || (idx == 1)); | 939 ASSERT((idx == 0) || (idx == 1)); |
978 vregisters_[reg].bits.i64[idx] = value; | 940 vregisters_[reg].bits.i64[idx] = value; |
979 } | 941 } |
980 | 942 |
981 | |
982 void Simulator::get_vregister(VRegister reg, simd_value_t* value) const { | 943 void Simulator::get_vregister(VRegister reg, simd_value_t* value) const { |
983 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); | 944 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); |
984 value->bits.i64[0] = vregisters_[reg].bits.i64[0]; | 945 value->bits.i64[0] = vregisters_[reg].bits.i64[0]; |
985 value->bits.i64[1] = vregisters_[reg].bits.i64[1]; | 946 value->bits.i64[1] = vregisters_[reg].bits.i64[1]; |
986 } | 947 } |
987 | 948 |
988 | |
989 void Simulator::set_vregister(VRegister reg, const simd_value_t& value) { | 949 void Simulator::set_vregister(VRegister reg, const simd_value_t& value) { |
990 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); | 950 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); |
991 vregisters_[reg].bits.i64[0] = value.bits.i64[0]; | 951 vregisters_[reg].bits.i64[0] = value.bits.i64[0]; |
992 vregisters_[reg].bits.i64[1] = value.bits.i64[1]; | 952 vregisters_[reg].bits.i64[1] = value.bits.i64[1]; |
993 } | 953 } |
994 | 954 |
995 | |
996 // Raw access to the PC register. | 955 // Raw access to the PC register. |
997 void Simulator::set_pc(int64_t value) { | 956 void Simulator::set_pc(int64_t value) { |
998 pc_modified_ = true; | 957 pc_modified_ = true; |
999 last_pc_ = pc_; | 958 last_pc_ = pc_; |
1000 pc_ = value; | 959 pc_ = value; |
1001 } | 960 } |
1002 | 961 |
1003 | |
1004 // Raw access to the pc. | 962 // Raw access to the pc. |
1005 int64_t Simulator::get_pc() const { | 963 int64_t Simulator::get_pc() const { |
1006 return pc_; | 964 return pc_; |
1007 } | 965 } |
1008 | 966 |
1009 | |
1010 int64_t Simulator::get_last_pc() const { | 967 int64_t Simulator::get_last_pc() const { |
1011 return last_pc_; | 968 return last_pc_; |
1012 } | 969 } |
1013 | 970 |
1014 | |
1015 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { | 971 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { |
1016 uword fault_pc = get_pc(); | 972 uword fault_pc = get_pc(); |
1017 uword last_pc = get_last_pc(); | 973 uword last_pc = get_last_pc(); |
1018 char buffer[128]; | 974 char buffer[128]; |
1019 snprintf(buffer, sizeof(buffer), "illegal memory access at 0x%" Px | 975 snprintf(buffer, sizeof(buffer), |
1020 ", pc=0x%" Px ", last_pc=0x%" Px "\n", | 976 "illegal memory access at 0x%" Px ", pc=0x%" Px ", last_pc=0x%" Px |
| 977 "\n", |
1021 addr, fault_pc, last_pc); | 978 addr, fault_pc, last_pc); |
1022 SimulatorDebugger dbg(this); | 979 SimulatorDebugger dbg(this); |
1023 dbg.Stop(instr, buffer); | 980 dbg.Stop(instr, buffer); |
1024 // The debugger will return control in non-interactive mode. | 981 // The debugger will return control in non-interactive mode. |
1025 FATAL("Cannot continue execution after illegal memory access."); | 982 FATAL("Cannot continue execution after illegal memory access."); |
1026 } | 983 } |
1027 | 984 |
1028 | |
1029 // The ARMv8 manual advises that an unaligned access may generate a fault, | 985 // The ARMv8 manual advises that an unaligned access may generate a fault, |
1030 // and if not, will likely take a number of additional cycles to execute, | 986 // and if not, will likely take a number of additional cycles to execute, |
1031 // so let's just not generate any. | 987 // so let's just not generate any. |
1032 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { | 988 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { |
1033 char buffer[128]; | 989 char buffer[128]; |
1034 snprintf(buffer, sizeof(buffer), "unaligned %s at 0x%" Px ", pc=%p\n", msg, | 990 snprintf(buffer, sizeof(buffer), "unaligned %s at 0x%" Px ", pc=%p\n", msg, |
1035 addr, instr); | 991 addr, instr); |
1036 SimulatorDebugger dbg(this); | 992 SimulatorDebugger dbg(this); |
1037 dbg.Stop(instr, buffer); | 993 dbg.Stop(instr, buffer); |
1038 // The debugger will not be able to single step past this instruction, but | 994 // The debugger will not be able to single step past this instruction, but |
1039 // it will be possible to disassemble the code and inspect registers. | 995 // it will be possible to disassemble the code and inspect registers. |
1040 FATAL("Cannot continue execution after unaligned access."); | 996 FATAL("Cannot continue execution after unaligned access."); |
1041 } | 997 } |
1042 | 998 |
1043 | |
1044 void Simulator::UnimplementedInstruction(Instr* instr) { | 999 void Simulator::UnimplementedInstruction(Instr* instr) { |
1045 char buffer[128]; | 1000 char buffer[128]; |
1046 snprintf(buffer, sizeof(buffer), | 1001 snprintf(buffer, sizeof(buffer), |
1047 "Unimplemented instruction: at %p, last_pc=0x%" Px64 "\n", instr, | 1002 "Unimplemented instruction: at %p, last_pc=0x%" Px64 "\n", instr, |
1048 get_last_pc()); | 1003 get_last_pc()); |
1049 SimulatorDebugger dbg(this); | 1004 SimulatorDebugger dbg(this); |
1050 dbg.Stop(instr, buffer); | 1005 dbg.Stop(instr, buffer); |
1051 FATAL("Cannot continue execution after unimplemented instruction."); | 1006 FATAL("Cannot continue execution after unimplemented instruction."); |
1052 } | 1007 } |
1053 | 1008 |
1054 | |
1055 // Returns the top of the stack area to enable checking for stack pointer | 1009 // Returns the top of the stack area to enable checking for stack pointer |
1056 // validity. | 1010 // validity. |
1057 uword Simulator::StackTop() const { | 1011 uword Simulator::StackTop() const { |
1058 // To be safe in potential stack underflows we leave some buffer above and | 1012 // To be safe in potential stack underflows we leave some buffer above and |
1059 // set the stack top. | 1013 // set the stack top. |
1060 return StackBase() + | 1014 return StackBase() + |
1061 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); | 1015 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); |
1062 } | 1016 } |
1063 | 1017 |
1064 | |
1065 bool Simulator::IsTracingExecution() const { | 1018 bool Simulator::IsTracingExecution() const { |
1066 return icount_ > FLAG_trace_sim_after; | 1019 return icount_ > FLAG_trace_sim_after; |
1067 } | 1020 } |
1068 | 1021 |
1069 | |
1070 intptr_t Simulator::ReadX(uword addr, Instr* instr) { | 1022 intptr_t Simulator::ReadX(uword addr, Instr* instr) { |
1071 if ((addr & 7) == 0) { | 1023 if ((addr & 7) == 0) { |
1072 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 1024 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
1073 return *ptr; | 1025 return *ptr; |
1074 } | 1026 } |
1075 UnalignedAccess("read", addr, instr); | 1027 UnalignedAccess("read", addr, instr); |
1076 return 0; | 1028 return 0; |
1077 } | 1029 } |
1078 | 1030 |
1079 | |
1080 void Simulator::WriteX(uword addr, intptr_t value, Instr* instr) { | 1031 void Simulator::WriteX(uword addr, intptr_t value, Instr* instr) { |
1081 if ((addr & 7) == 0) { | 1032 if ((addr & 7) == 0) { |
1082 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 1033 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
1083 *ptr = value; | 1034 *ptr = value; |
1084 return; | 1035 return; |
1085 } | 1036 } |
1086 UnalignedAccess("write", addr, instr); | 1037 UnalignedAccess("write", addr, instr); |
1087 } | 1038 } |
1088 | 1039 |
1089 | |
1090 uint32_t Simulator::ReadWU(uword addr, Instr* instr) { | 1040 uint32_t Simulator::ReadWU(uword addr, Instr* instr) { |
1091 if ((addr & 3) == 0) { | 1041 if ((addr & 3) == 0) { |
1092 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); | 1042 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); |
1093 return *ptr; | 1043 return *ptr; |
1094 } | 1044 } |
1095 UnalignedAccess("read unsigned single word", addr, instr); | 1045 UnalignedAccess("read unsigned single word", addr, instr); |
1096 return 0; | 1046 return 0; |
1097 } | 1047 } |
1098 | 1048 |
1099 | |
1100 int32_t Simulator::ReadW(uword addr, Instr* instr) { | 1049 int32_t Simulator::ReadW(uword addr, Instr* instr) { |
1101 if ((addr & 3) == 0) { | 1050 if ((addr & 3) == 0) { |
1102 int32_t* ptr = reinterpret_cast<int32_t*>(addr); | 1051 int32_t* ptr = reinterpret_cast<int32_t*>(addr); |
1103 return *ptr; | 1052 return *ptr; |
1104 } | 1053 } |
1105 UnalignedAccess("read single word", addr, instr); | 1054 UnalignedAccess("read single word", addr, instr); |
1106 return 0; | 1055 return 0; |
1107 } | 1056 } |
1108 | 1057 |
1109 | |
1110 void Simulator::WriteW(uword addr, uint32_t value, Instr* instr) { | 1058 void Simulator::WriteW(uword addr, uint32_t value, Instr* instr) { |
1111 if ((addr & 3) == 0) { | 1059 if ((addr & 3) == 0) { |
1112 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); | 1060 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); |
1113 *ptr = value; | 1061 *ptr = value; |
1114 return; | 1062 return; |
1115 } | 1063 } |
1116 UnalignedAccess("write single word", addr, instr); | 1064 UnalignedAccess("write single word", addr, instr); |
1117 } | 1065 } |
1118 | 1066 |
1119 | |
1120 uint16_t Simulator::ReadHU(uword addr, Instr* instr) { | 1067 uint16_t Simulator::ReadHU(uword addr, Instr* instr) { |
1121 if ((addr & 1) == 0) { | 1068 if ((addr & 1) == 0) { |
1122 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); | 1069 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); |
1123 return *ptr; | 1070 return *ptr; |
1124 } | 1071 } |
1125 UnalignedAccess("unsigned halfword read", addr, instr); | 1072 UnalignedAccess("unsigned halfword read", addr, instr); |
1126 return 0; | 1073 return 0; |
1127 } | 1074 } |
1128 | 1075 |
1129 | |
1130 int16_t Simulator::ReadH(uword addr, Instr* instr) { | 1076 int16_t Simulator::ReadH(uword addr, Instr* instr) { |
1131 if ((addr & 1) == 0) { | 1077 if ((addr & 1) == 0) { |
1132 int16_t* ptr = reinterpret_cast<int16_t*>(addr); | 1078 int16_t* ptr = reinterpret_cast<int16_t*>(addr); |
1133 return *ptr; | 1079 return *ptr; |
1134 } | 1080 } |
1135 UnalignedAccess("signed halfword read", addr, instr); | 1081 UnalignedAccess("signed halfword read", addr, instr); |
1136 return 0; | 1082 return 0; |
1137 } | 1083 } |
1138 | 1084 |
1139 | |
1140 void Simulator::WriteH(uword addr, uint16_t value, Instr* instr) { | 1085 void Simulator::WriteH(uword addr, uint16_t value, Instr* instr) { |
1141 if ((addr & 1) == 0) { | 1086 if ((addr & 1) == 0) { |
1142 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); | 1087 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); |
1143 *ptr = value; | 1088 *ptr = value; |
1144 return; | 1089 return; |
1145 } | 1090 } |
1146 UnalignedAccess("halfword write", addr, instr); | 1091 UnalignedAccess("halfword write", addr, instr); |
1147 } | 1092 } |
1148 | 1093 |
1149 | |
1150 uint8_t Simulator::ReadBU(uword addr) { | 1094 uint8_t Simulator::ReadBU(uword addr) { |
1151 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); | 1095 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); |
1152 return *ptr; | 1096 return *ptr; |
1153 } | 1097 } |
1154 | 1098 |
1155 | |
1156 int8_t Simulator::ReadB(uword addr) { | 1099 int8_t Simulator::ReadB(uword addr) { |
1157 int8_t* ptr = reinterpret_cast<int8_t*>(addr); | 1100 int8_t* ptr = reinterpret_cast<int8_t*>(addr); |
1158 return *ptr; | 1101 return *ptr; |
1159 } | 1102 } |
1160 | 1103 |
1161 | |
1162 void Simulator::WriteB(uword addr, uint8_t value) { | 1104 void Simulator::WriteB(uword addr, uint8_t value) { |
1163 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); | 1105 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); |
1164 *ptr = value; | 1106 *ptr = value; |
1165 } | 1107 } |
1166 | 1108 |
1167 | |
1168 // Synchronization primitives support. | 1109 // Synchronization primitives support. |
1169 void Simulator::SetExclusiveAccess(uword addr) { | 1110 void Simulator::SetExclusiveAccess(uword addr) { |
1170 Thread* thread = Thread::Current(); | 1111 Thread* thread = Thread::Current(); |
1171 ASSERT(thread != NULL); | 1112 ASSERT(thread != NULL); |
1172 DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread()); | 1113 DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread()); |
1173 int i = 0; | 1114 int i = 0; |
1174 // Find an entry for this thread in the exclusive access state. | 1115 // Find an entry for this thread in the exclusive access state. |
1175 while ((i < kNumAddressTags) && | 1116 while ((i < kNumAddressTags) && |
1176 (exclusive_access_state_[i].thread != thread)) { | 1117 (exclusive_access_state_[i].thread != thread)) { |
1177 i++; | 1118 i++; |
1178 } | 1119 } |
1179 // Round-robin replacement of previously used entries. | 1120 // Round-robin replacement of previously used entries. |
1180 if (i == kNumAddressTags) { | 1121 if (i == kNumAddressTags) { |
1181 i = next_address_tag_; | 1122 i = next_address_tag_; |
1182 if (++next_address_tag_ == kNumAddressTags) { | 1123 if (++next_address_tag_ == kNumAddressTags) { |
1183 next_address_tag_ = 0; | 1124 next_address_tag_ = 0; |
1184 } | 1125 } |
1185 exclusive_access_state_[i].thread = thread; | 1126 exclusive_access_state_[i].thread = thread; |
1186 } | 1127 } |
1187 // Remember the address being reserved. | 1128 // Remember the address being reserved. |
1188 exclusive_access_state_[i].addr = addr; | 1129 exclusive_access_state_[i].addr = addr; |
1189 } | 1130 } |
1190 | 1131 |
1191 | |
1192 bool Simulator::HasExclusiveAccessAndOpen(uword addr) { | 1132 bool Simulator::HasExclusiveAccessAndOpen(uword addr) { |
1193 Thread* thread = Thread::Current(); | 1133 Thread* thread = Thread::Current(); |
1194 ASSERT(thread != NULL); | 1134 ASSERT(thread != NULL); |
1195 ASSERT(addr != 0); | 1135 ASSERT(addr != 0); |
1196 DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread()); | 1136 DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread()); |
1197 bool result = false; | 1137 bool result = false; |
1198 for (int i = 0; i < kNumAddressTags; i++) { | 1138 for (int i = 0; i < kNumAddressTags; i++) { |
1199 if (exclusive_access_state_[i].thread == thread) { | 1139 if (exclusive_access_state_[i].thread == thread) { |
1200 // Check whether the current threads address reservation matches. | 1140 // Check whether the current threads address reservation matches. |
1201 if (exclusive_access_state_[i].addr == addr) { | 1141 if (exclusive_access_state_[i].addr == addr) { |
1202 result = true; | 1142 result = true; |
1203 } | 1143 } |
1204 exclusive_access_state_[i].addr = 0; | 1144 exclusive_access_state_[i].addr = 0; |
1205 } else if (exclusive_access_state_[i].addr == addr) { | 1145 } else if (exclusive_access_state_[i].addr == addr) { |
1206 // Other threads with matching address lose their reservations. | 1146 // Other threads with matching address lose their reservations. |
1207 exclusive_access_state_[i].addr = 0; | 1147 exclusive_access_state_[i].addr = 0; |
1208 } | 1148 } |
1209 } | 1149 } |
1210 return result; | 1150 return result; |
1211 } | 1151 } |
1212 | 1152 |
1213 | |
1214 void Simulator::ClearExclusive() { | 1153 void Simulator::ClearExclusive() { |
1215 MutexLocker ml(exclusive_access_lock_); | 1154 MutexLocker ml(exclusive_access_lock_); |
1216 // Remove the reservation for this thread. | 1155 // Remove the reservation for this thread. |
1217 SetExclusiveAccess(0); | 1156 SetExclusiveAccess(0); |
1218 } | 1157 } |
1219 | 1158 |
1220 | |
1221 intptr_t Simulator::ReadExclusiveX(uword addr, Instr* instr) { | 1159 intptr_t Simulator::ReadExclusiveX(uword addr, Instr* instr) { |
1222 MutexLocker ml(exclusive_access_lock_); | 1160 MutexLocker ml(exclusive_access_lock_); |
1223 SetExclusiveAccess(addr); | 1161 SetExclusiveAccess(addr); |
1224 return ReadX(addr, instr); | 1162 return ReadX(addr, instr); |
1225 } | 1163 } |
1226 | 1164 |
1227 | |
1228 intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) { | 1165 intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) { |
1229 MutexLocker ml(exclusive_access_lock_); | 1166 MutexLocker ml(exclusive_access_lock_); |
1230 SetExclusiveAccess(addr); | 1167 SetExclusiveAccess(addr); |
1231 return ReadWU(addr, instr); | 1168 return ReadWU(addr, instr); |
1232 } | 1169 } |
1233 | 1170 |
1234 | |
1235 intptr_t Simulator::WriteExclusiveX(uword addr, intptr_t value, Instr* instr) { | 1171 intptr_t Simulator::WriteExclusiveX(uword addr, intptr_t value, Instr* instr) { |
1236 MutexLocker ml(exclusive_access_lock_); | 1172 MutexLocker ml(exclusive_access_lock_); |
1237 bool write_allowed = HasExclusiveAccessAndOpen(addr); | 1173 bool write_allowed = HasExclusiveAccessAndOpen(addr); |
1238 if (write_allowed) { | 1174 if (write_allowed) { |
1239 WriteX(addr, value, instr); | 1175 WriteX(addr, value, instr); |
1240 return 0; // Success. | 1176 return 0; // Success. |
1241 } | 1177 } |
1242 return 1; // Failure. | 1178 return 1; // Failure. |
1243 } | 1179 } |
1244 | 1180 |
1245 | |
1246 intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) { | 1181 intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) { |
1247 MutexLocker ml(exclusive_access_lock_); | 1182 MutexLocker ml(exclusive_access_lock_); |
1248 bool write_allowed = HasExclusiveAccessAndOpen(addr); | 1183 bool write_allowed = HasExclusiveAccessAndOpen(addr); |
1249 if (write_allowed) { | 1184 if (write_allowed) { |
1250 WriteW(addr, value, instr); | 1185 WriteW(addr, value, instr); |
1251 return 0; // Success. | 1186 return 0; // Success. |
1252 } | 1187 } |
1253 return 1; // Failure. | 1188 return 1; // Failure. |
1254 } | 1189 } |
1255 | 1190 |
1256 | |
1257 uword Simulator::CompareExchange(uword* address, | 1191 uword Simulator::CompareExchange(uword* address, |
1258 uword compare_value, | 1192 uword compare_value, |
1259 uword new_value) { | 1193 uword new_value) { |
1260 MutexLocker ml(exclusive_access_lock_); | 1194 MutexLocker ml(exclusive_access_lock_); |
1261 // We do not get a reservation as it would be guaranteed to be found when | 1195 // We do not get a reservation as it would be guaranteed to be found when |
1262 // writing below. No other thread is able to make a reservation while we | 1196 // writing below. No other thread is able to make a reservation while we |
1263 // hold the lock. | 1197 // hold the lock. |
1264 uword value = *address; | 1198 uword value = *address; |
1265 if (value == compare_value) { | 1199 if (value == compare_value) { |
1266 *address = new_value; | 1200 *address = new_value; |
1267 // Same effect on exclusive access state as a successful STREX. | 1201 // Same effect on exclusive access state as a successful STREX. |
1268 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address)); | 1202 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address)); |
1269 } else { | 1203 } else { |
1270 // Same effect on exclusive access state as an LDREX. | 1204 // Same effect on exclusive access state as an LDREX. |
1271 SetExclusiveAccess(reinterpret_cast<uword>(address)); | 1205 SetExclusiveAccess(reinterpret_cast<uword>(address)); |
1272 } | 1206 } |
1273 return value; | 1207 return value; |
1274 } | 1208 } |
1275 | 1209 |
1276 | |
1277 uint32_t Simulator::CompareExchangeUint32(uint32_t* address, | 1210 uint32_t Simulator::CompareExchangeUint32(uint32_t* address, |
1278 uint32_t compare_value, | 1211 uint32_t compare_value, |
1279 uint32_t new_value) { | 1212 uint32_t new_value) { |
1280 MutexLocker ml(exclusive_access_lock_); | 1213 MutexLocker ml(exclusive_access_lock_); |
1281 // We do not get a reservation as it would be guaranteed to be found when | 1214 // We do not get a reservation as it would be guaranteed to be found when |
1282 // writing below. No other thread is able to make a reservation while we | 1215 // writing below. No other thread is able to make a reservation while we |
1283 // hold the lock. | 1216 // hold the lock. |
1284 uint32_t value = *address; | 1217 uint32_t value = *address; |
1285 if (value == compare_value) { | 1218 if (value == compare_value) { |
1286 *address = new_value; | 1219 *address = new_value; |
1287 // Same effect on exclusive access state as a successful STREX. | 1220 // Same effect on exclusive access state as a successful STREX. |
1288 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address)); | 1221 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address)); |
1289 } else { | 1222 } else { |
1290 // Same effect on exclusive access state as an LDREX. | 1223 // Same effect on exclusive access state as an LDREX. |
1291 SetExclusiveAccess(reinterpret_cast<uword>(address)); | 1224 SetExclusiveAccess(reinterpret_cast<uword>(address)); |
1292 } | 1225 } |
1293 return value; | 1226 return value; |
1294 } | 1227 } |
1295 | 1228 |
1296 | |
1297 // Unsupported instructions use Format to print an error and stop execution. | 1229 // Unsupported instructions use Format to print an error and stop execution. |
1298 void Simulator::Format(Instr* instr, const char* format) { | 1230 void Simulator::Format(Instr* instr, const char* format) { |
1299 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", instr, | 1231 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", instr, |
1300 format); | 1232 format); |
1301 UNIMPLEMENTED(); | 1233 UNIMPLEMENTED(); |
1302 } | 1234 } |
1303 | 1235 |
1304 | |
1305 // Calculate and set the Negative and Zero flags. | 1236 // Calculate and set the Negative and Zero flags. |
1306 void Simulator::SetNZFlagsW(int32_t val) { | 1237 void Simulator::SetNZFlagsW(int32_t val) { |
1307 n_flag_ = (val < 0); | 1238 n_flag_ = (val < 0); |
1308 z_flag_ = (val == 0); | 1239 z_flag_ = (val == 0); |
1309 } | 1240 } |
1310 | 1241 |
1311 | |
1312 // Calculate C flag value for additions (and subtractions with adjusted args). | 1242 // Calculate C flag value for additions (and subtractions with adjusted args). |
1313 bool Simulator::CarryFromW(int32_t left, int32_t right, int32_t carry) { | 1243 bool Simulator::CarryFromW(int32_t left, int32_t right, int32_t carry) { |
1314 uint64_t uleft = static_cast<uint32_t>(left); | 1244 uint64_t uleft = static_cast<uint32_t>(left); |
1315 uint64_t uright = static_cast<uint32_t>(right); | 1245 uint64_t uright = static_cast<uint32_t>(right); |
1316 uint64_t ucarry = static_cast<uint32_t>(carry); | 1246 uint64_t ucarry = static_cast<uint32_t>(carry); |
1317 return ((uleft + uright + ucarry) >> 32) != 0; | 1247 return ((uleft + uright + ucarry) >> 32) != 0; |
1318 } | 1248 } |
1319 | 1249 |
1320 | |
1321 // Calculate V flag value for additions (and subtractions with adjusted args). | 1250 // Calculate V flag value for additions (and subtractions with adjusted args). |
1322 bool Simulator::OverflowFromW(int32_t left, int32_t right, int32_t carry) { | 1251 bool Simulator::OverflowFromW(int32_t left, int32_t right, int32_t carry) { |
1323 int64_t result = static_cast<int64_t>(left) + right + carry; | 1252 int64_t result = static_cast<int64_t>(left) + right + carry; |
1324 return (result >> 31) != (result >> 32); | 1253 return (result >> 31) != (result >> 32); |
1325 } | 1254 } |
1326 | 1255 |
1327 | |
1328 // Calculate and set the Negative and Zero flags. | 1256 // Calculate and set the Negative and Zero flags. |
1329 void Simulator::SetNZFlagsX(int64_t val) { | 1257 void Simulator::SetNZFlagsX(int64_t val) { |
1330 n_flag_ = (val < 0); | 1258 n_flag_ = (val < 0); |
1331 z_flag_ = (val == 0); | 1259 z_flag_ = (val == 0); |
1332 } | 1260 } |
1333 | 1261 |
1334 | |
1335 // Calculate C flag value for additions and subtractions. | 1262 // Calculate C flag value for additions and subtractions. |
1336 bool Simulator::CarryFromX(int64_t alu_out, | 1263 bool Simulator::CarryFromX(int64_t alu_out, |
1337 int64_t left, | 1264 int64_t left, |
1338 int64_t right, | 1265 int64_t right, |
1339 bool addition) { | 1266 bool addition) { |
1340 if (addition) { | 1267 if (addition) { |
1341 return (((left & right) | ((left | right) & ~alu_out)) >> 63) != 0; | 1268 return (((left & right) | ((left | right) & ~alu_out)) >> 63) != 0; |
1342 } else { | 1269 } else { |
1343 return (((~left & right) | ((~left | right) & alu_out)) >> 63) == 0; | 1270 return (((~left & right) | ((~left | right) & alu_out)) >> 63) == 0; |
1344 } | 1271 } |
1345 } | 1272 } |
1346 | 1273 |
1347 | |
1348 // Calculate V flag value for additions and subtractions. | 1274 // Calculate V flag value for additions and subtractions. |
1349 bool Simulator::OverflowFromX(int64_t alu_out, | 1275 bool Simulator::OverflowFromX(int64_t alu_out, |
1350 int64_t left, | 1276 int64_t left, |
1351 int64_t right, | 1277 int64_t right, |
1352 bool addition) { | 1278 bool addition) { |
1353 if (addition) { | 1279 if (addition) { |
1354 return (((alu_out ^ left) & (alu_out ^ right)) >> 63) != 0; | 1280 return (((alu_out ^ left) & (alu_out ^ right)) >> 63) != 0; |
1355 } else { | 1281 } else { |
1356 return (((left ^ right) & (alu_out ^ left)) >> 63) != 0; | 1282 return (((left ^ right) & (alu_out ^ left)) >> 63) != 0; |
1357 } | 1283 } |
1358 } | 1284 } |
1359 | 1285 |
1360 | |
1361 // Set the Carry flag. | 1286 // Set the Carry flag. |
1362 void Simulator::SetCFlag(bool val) { | 1287 void Simulator::SetCFlag(bool val) { |
1363 c_flag_ = val; | 1288 c_flag_ = val; |
1364 } | 1289 } |
1365 | 1290 |
1366 | |
1367 // Set the oVerflow flag. | 1291 // Set the oVerflow flag. |
1368 void Simulator::SetVFlag(bool val) { | 1292 void Simulator::SetVFlag(bool val) { |
1369 v_flag_ = val; | 1293 v_flag_ = val; |
1370 } | 1294 } |
1371 | 1295 |
1372 | |
1373 void Simulator::DecodeMoveWide(Instr* instr) { | 1296 void Simulator::DecodeMoveWide(Instr* instr) { |
1374 const Register rd = instr->RdField(); | 1297 const Register rd = instr->RdField(); |
1375 const int hw = instr->HWField(); | 1298 const int hw = instr->HWField(); |
1376 const int64_t shift = hw << 4; | 1299 const int64_t shift = hw << 4; |
1377 const int64_t shifted_imm = static_cast<int64_t>(instr->Imm16Field()) | 1300 const int64_t shifted_imm = static_cast<int64_t>(instr->Imm16Field()) |
1378 << shift; | 1301 << shift; |
1379 | 1302 |
1380 if (instr->SFField()) { | 1303 if (instr->SFField()) { |
1381 if (instr->Bits(29, 2) == 0) { | 1304 if (instr->Bits(29, 2) == 0) { |
1382 // Format(instr, "movn'sf 'rd, 'imm16 'hw"); | 1305 // Format(instr, "movn'sf 'rd, 'imm16 'hw"); |
(...skipping 23 matching lines...) Expand all Loading... |
1406 set_wregister(rd, result, instr->RdMode()); | 1329 set_wregister(rd, result, instr->RdMode()); |
1407 } else { | 1330 } else { |
1408 UnimplementedInstruction(instr); | 1331 UnimplementedInstruction(instr); |
1409 } | 1332 } |
1410 } else { | 1333 } else { |
1411 // Dest is 32 bits, but shift is more than 32. | 1334 // Dest is 32 bits, but shift is more than 32. |
1412 UnimplementedInstruction(instr); | 1335 UnimplementedInstruction(instr); |
1413 } | 1336 } |
1414 } | 1337 } |
1415 | 1338 |
1416 | |
1417 void Simulator::DecodeAddSubImm(Instr* instr) { | 1339 void Simulator::DecodeAddSubImm(Instr* instr) { |
1418 const bool addition = (instr->Bit(30) == 0); | 1340 const bool addition = (instr->Bit(30) == 0); |
1419 // Format(instr, "addi'sf's 'rd, 'rn, 'imm12s"); | 1341 // Format(instr, "addi'sf's 'rd, 'rn, 'imm12s"); |
1420 // Format(instr, "subi'sf's 'rd, 'rn, 'imm12s"); | 1342 // Format(instr, "subi'sf's 'rd, 'rn, 'imm12s"); |
1421 const Register rd = instr->RdField(); | 1343 const Register rd = instr->RdField(); |
1422 const Register rn = instr->RnField(); | 1344 const Register rn = instr->RnField(); |
1423 uint32_t imm = (instr->Bit(22) == 1) ? (instr->Imm12Field() << 12) | 1345 uint32_t imm = (instr->Bit(22) == 1) ? (instr->Imm12Field() << 12) |
1424 : (instr->Imm12Field()); | 1346 : (instr->Imm12Field()); |
1425 if (instr->SFField()) { | 1347 if (instr->SFField()) { |
1426 // 64-bit add. | 1348 // 64-bit add. |
(...skipping 16 matching lines...) Expand all Loading... |
1443 const int32_t alu_out = rn_val + imm + carry_in; | 1365 const int32_t alu_out = rn_val + imm + carry_in; |
1444 set_wregister(rd, alu_out, instr->RdMode()); | 1366 set_wregister(rd, alu_out, instr->RdMode()); |
1445 if (instr->HasS()) { | 1367 if (instr->HasS()) { |
1446 SetNZFlagsW(alu_out); | 1368 SetNZFlagsW(alu_out); |
1447 SetCFlag(CarryFromW(rn_val, imm, carry_in)); | 1369 SetCFlag(CarryFromW(rn_val, imm, carry_in)); |
1448 SetVFlag(OverflowFromW(rn_val, imm, carry_in)); | 1370 SetVFlag(OverflowFromW(rn_val, imm, carry_in)); |
1449 } | 1371 } |
1450 } | 1372 } |
1451 } | 1373 } |
1452 | 1374 |
1453 | |
1454 void Simulator::DecodeLogicalImm(Instr* instr) { | 1375 void Simulator::DecodeLogicalImm(Instr* instr) { |
1455 const int op = instr->Bits(29, 2); | 1376 const int op = instr->Bits(29, 2); |
1456 const bool set_flags = op == 3; | 1377 const bool set_flags = op == 3; |
1457 const int out_size = ((instr->SFField() == 0) && (instr->NField() == 0)) | 1378 const int out_size = ((instr->SFField() == 0) && (instr->NField() == 0)) |
1458 ? kWRegSizeInBits | 1379 ? kWRegSizeInBits |
1459 : kXRegSizeInBits; | 1380 : kXRegSizeInBits; |
1460 const Register rn = instr->RnField(); | 1381 const Register rn = instr->RnField(); |
1461 const Register rd = instr->RdField(); | 1382 const Register rd = instr->RdField(); |
1462 const int64_t rn_val = get_register(rn, instr->RnMode()); | 1383 const int64_t rn_val = get_register(rn, instr->RnMode()); |
1463 const uint64_t imm = instr->ImmLogical(); | 1384 const uint64_t imm = instr->ImmLogical(); |
(...skipping 30 matching lines...) Expand all Loading... |
1494 SetVFlag(false); | 1415 SetVFlag(false); |
1495 } | 1416 } |
1496 | 1417 |
1497 if (out_size == kXRegSizeInBits) { | 1418 if (out_size == kXRegSizeInBits) { |
1498 set_register(instr, rd, alu_out, instr->RdMode()); | 1419 set_register(instr, rd, alu_out, instr->RdMode()); |
1499 } else { | 1420 } else { |
1500 set_wregister(rd, alu_out, instr->RdMode()); | 1421 set_wregister(rd, alu_out, instr->RdMode()); |
1501 } | 1422 } |
1502 } | 1423 } |
1503 | 1424 |
1504 | |
1505 void Simulator::DecodePCRel(Instr* instr) { | 1425 void Simulator::DecodePCRel(Instr* instr) { |
1506 const int op = instr->Bit(31); | 1426 const int op = instr->Bit(31); |
1507 if (op == 0) { | 1427 if (op == 0) { |
1508 // Format(instr, "adr 'rd, 'pcrel") | 1428 // Format(instr, "adr 'rd, 'pcrel") |
1509 const Register rd = instr->RdField(); | 1429 const Register rd = instr->RdField(); |
1510 const int64_t immhi = instr->SImm19Field(); | 1430 const int64_t immhi = instr->SImm19Field(); |
1511 const int64_t immlo = instr->Bits(29, 2); | 1431 const int64_t immlo = instr->Bits(29, 2); |
1512 const int64_t off = (immhi << 2) | immlo; | 1432 const int64_t off = (immhi << 2) | immlo; |
1513 const int64_t dest = get_pc() + off; | 1433 const int64_t dest = get_pc() + off; |
1514 set_register(instr, rd, dest, instr->RdMode()); | 1434 set_register(instr, rd, dest, instr->RdMode()); |
1515 } else { | 1435 } else { |
1516 UnimplementedInstruction(instr); | 1436 UnimplementedInstruction(instr); |
1517 } | 1437 } |
1518 } | 1438 } |
1519 | 1439 |
1520 | |
1521 void Simulator::DecodeDPImmediate(Instr* instr) { | 1440 void Simulator::DecodeDPImmediate(Instr* instr) { |
1522 if (instr->IsMoveWideOp()) { | 1441 if (instr->IsMoveWideOp()) { |
1523 DecodeMoveWide(instr); | 1442 DecodeMoveWide(instr); |
1524 } else if (instr->IsAddSubImmOp()) { | 1443 } else if (instr->IsAddSubImmOp()) { |
1525 DecodeAddSubImm(instr); | 1444 DecodeAddSubImm(instr); |
1526 } else if (instr->IsLogicalImmOp()) { | 1445 } else if (instr->IsLogicalImmOp()) { |
1527 DecodeLogicalImm(instr); | 1446 DecodeLogicalImm(instr); |
1528 } else if (instr->IsPCRelOp()) { | 1447 } else if (instr->IsPCRelOp()) { |
1529 DecodePCRel(instr); | 1448 DecodePCRel(instr); |
1530 } else { | 1449 } else { |
1531 UnimplementedInstruction(instr); | 1450 UnimplementedInstruction(instr); |
1532 } | 1451 } |
1533 } | 1452 } |
1534 | 1453 |
1535 | |
1536 void Simulator::DecodeCompareAndBranch(Instr* instr) { | 1454 void Simulator::DecodeCompareAndBranch(Instr* instr) { |
1537 const int op = instr->Bit(24); | 1455 const int op = instr->Bit(24); |
1538 const Register rt = instr->RtField(); | 1456 const Register rt = instr->RtField(); |
1539 const int64_t imm19 = instr->SImm19Field(); | 1457 const int64_t imm19 = instr->SImm19Field(); |
1540 const int64_t dest = get_pc() + (imm19 << 2); | 1458 const int64_t dest = get_pc() + (imm19 << 2); |
1541 const int64_t mask = instr->SFField() == 1 ? kXRegMask : kWRegMask; | 1459 const int64_t mask = instr->SFField() == 1 ? kXRegMask : kWRegMask; |
1542 const int64_t rt_val = get_register(rt, R31IsZR) & mask; | 1460 const int64_t rt_val = get_register(rt, R31IsZR) & mask; |
1543 if (op == 0) { | 1461 if (op == 0) { |
1544 // Format(instr, "cbz'sf 'rt, 'dest19"); | 1462 // Format(instr, "cbz'sf 'rt, 'dest19"); |
1545 if (rt_val == 0) { | 1463 if (rt_val == 0) { |
1546 set_pc(dest); | 1464 set_pc(dest); |
1547 } | 1465 } |
1548 } else { | 1466 } else { |
1549 // Format(instr, "cbnz'sf 'rt, 'dest19"); | 1467 // Format(instr, "cbnz'sf 'rt, 'dest19"); |
1550 if (rt_val != 0) { | 1468 if (rt_val != 0) { |
1551 set_pc(dest); | 1469 set_pc(dest); |
1552 } | 1470 } |
1553 } | 1471 } |
1554 } | 1472 } |
1555 | 1473 |
1556 | |
1557 bool Simulator::ConditionallyExecute(Instr* instr) { | 1474 bool Simulator::ConditionallyExecute(Instr* instr) { |
1558 Condition cond; | 1475 Condition cond; |
1559 if (instr->IsConditionalSelectOp()) { | 1476 if (instr->IsConditionalSelectOp()) { |
1560 cond = instr->SelectConditionField(); | 1477 cond = instr->SelectConditionField(); |
1561 } else { | 1478 } else { |
1562 cond = instr->ConditionField(); | 1479 cond = instr->ConditionField(); |
1563 } | 1480 } |
1564 switch (cond) { | 1481 switch (cond) { |
1565 case EQ: | 1482 case EQ: |
1566 return z_flag_; | 1483 return z_flag_; |
(...skipping 24 matching lines...) Expand all Loading... |
1591 case LE: | 1508 case LE: |
1592 return z_flag_ || (n_flag_ != v_flag_); | 1509 return z_flag_ || (n_flag_ != v_flag_); |
1593 case AL: | 1510 case AL: |
1594 return true; | 1511 return true; |
1595 default: | 1512 default: |
1596 UNREACHABLE(); | 1513 UNREACHABLE(); |
1597 } | 1514 } |
1598 return false; | 1515 return false; |
1599 } | 1516 } |
1600 | 1517 |
1601 | |
1602 void Simulator::DecodeConditionalBranch(Instr* instr) { | 1518 void Simulator::DecodeConditionalBranch(Instr* instr) { |
1603 // Format(instr, "b'cond 'dest19"); | 1519 // Format(instr, "b'cond 'dest19"); |
1604 if ((instr->Bit(24) != 0) || (instr->Bit(4) != 0)) { | 1520 if ((instr->Bit(24) != 0) || (instr->Bit(4) != 0)) { |
1605 UnimplementedInstruction(instr); | 1521 UnimplementedInstruction(instr); |
1606 } | 1522 } |
1607 const int64_t imm19 = instr->SImm19Field(); | 1523 const int64_t imm19 = instr->SImm19Field(); |
1608 const int64_t dest = get_pc() + (imm19 << 2); | 1524 const int64_t dest = get_pc() + (imm19 << 2); |
1609 if (ConditionallyExecute(instr)) { | 1525 if (ConditionallyExecute(instr)) { |
1610 set_pc(dest); | 1526 set_pc(dest); |
1611 } | 1527 } |
1612 } | 1528 } |
1613 | 1529 |
1614 | |
1615 // Calls into the Dart runtime are based on this interface. | 1530 // Calls into the Dart runtime are based on this interface. |
1616 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); | 1531 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); |
1617 | 1532 |
1618 // Calls to leaf Dart runtime functions are based on this interface. | 1533 // Calls to leaf Dart runtime functions are based on this interface. |
1619 typedef int64_t (*SimulatorLeafRuntimeCall)(int64_t r0, | 1534 typedef int64_t (*SimulatorLeafRuntimeCall)(int64_t r0, |
1620 int64_t r1, | 1535 int64_t r1, |
1621 int64_t r2, | 1536 int64_t r2, |
1622 int64_t r3, | 1537 int64_t r3, |
1623 int64_t r4, | 1538 int64_t r4, |
1624 int64_t r5, | 1539 int64_t r5, |
1625 int64_t r6, | 1540 int64_t r6, |
1626 int64_t r7); | 1541 int64_t r7); |
1627 | 1542 |
1628 // Calls to leaf float Dart runtime functions are based on this interface. | 1543 // Calls to leaf float Dart runtime functions are based on this interface. |
1629 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, | 1544 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, |
1630 double d1, | 1545 double d1, |
1631 double d2, | 1546 double d2, |
1632 double d3, | 1547 double d3, |
1633 double d4, | 1548 double d4, |
1634 double d5, | 1549 double d5, |
1635 double d6, | 1550 double d6, |
1636 double d7); | 1551 double d7); |
1637 | 1552 |
1638 // Calls to native Dart functions are based on this interface. | 1553 // Calls to native Dart functions are based on this interface. |
1639 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); | 1554 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); |
1640 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); | 1555 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); |
1641 | 1556 |
1642 | |
1643 void Simulator::DoRedirectedCall(Instr* instr) { | 1557 void Simulator::DoRedirectedCall(Instr* instr) { |
1644 SimulatorSetjmpBuffer buffer(this); | 1558 SimulatorSetjmpBuffer buffer(this); |
1645 if (!setjmp(buffer.buffer_)) { | 1559 if (!setjmp(buffer.buffer_)) { |
1646 int64_t saved_lr = get_register(LR); | 1560 int64_t saved_lr = get_register(LR); |
1647 Redirection* redirection = Redirection::FromHltInstruction(instr); | 1561 Redirection* redirection = Redirection::FromHltInstruction(instr); |
1648 uword external = redirection->external_function(); | 1562 uword external = redirection->external_function(); |
1649 if (IsTracingExecution()) { | 1563 if (IsTracingExecution()) { |
1650 THR_Print("Call to host function at 0x%" Pd "\n", external); | 1564 THR_Print("Call to host function at 0x%" Pd "\n", external); |
1651 } | 1565 } |
1652 | 1566 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1744 // TODO(zra): Zap caller-saved fpu registers. | 1658 // TODO(zra): Zap caller-saved fpu registers. |
1745 | 1659 |
1746 // Return. | 1660 // Return. |
1747 set_pc(saved_lr); | 1661 set_pc(saved_lr); |
1748 } else { | 1662 } else { |
1749 // Coming via long jump from a throw. Continue to exception handler. | 1663 // Coming via long jump from a throw. Continue to exception handler. |
1750 set_top_exit_frame_info(0); | 1664 set_top_exit_frame_info(0); |
1751 } | 1665 } |
1752 } | 1666 } |
1753 | 1667 |
1754 | |
1755 void Simulator::DecodeExceptionGen(Instr* instr) { | 1668 void Simulator::DecodeExceptionGen(Instr* instr) { |
1756 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) && | 1669 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) && |
1757 (instr->Bits(21, 3) == 0)) { | 1670 (instr->Bits(21, 3) == 0)) { |
1758 // Format(instr, "svc 'imm16"); | 1671 // Format(instr, "svc 'imm16"); |
1759 UnimplementedInstruction(instr); | 1672 UnimplementedInstruction(instr); |
1760 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && | 1673 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && |
1761 (instr->Bits(21, 3) == 1)) { | 1674 (instr->Bits(21, 3) == 1)) { |
1762 // Format(instr, "brk 'imm16"); | 1675 // Format(instr, "brk 'imm16"); |
1763 SimulatorDebugger dbg(this); | 1676 SimulatorDebugger dbg(this); |
1764 int32_t imm = instr->Imm16Field(); | 1677 int32_t imm = instr->Imm16Field(); |
(...skipping 18 matching lines...) Expand all Loading... |
1783 } else if (imm == Instr::kSimulatorRedirectCode) { | 1696 } else if (imm == Instr::kSimulatorRedirectCode) { |
1784 DoRedirectedCall(instr); | 1697 DoRedirectedCall(instr); |
1785 } else { | 1698 } else { |
1786 UnimplementedInstruction(instr); | 1699 UnimplementedInstruction(instr); |
1787 } | 1700 } |
1788 } else { | 1701 } else { |
1789 UnimplementedInstruction(instr); | 1702 UnimplementedInstruction(instr); |
1790 } | 1703 } |
1791 } | 1704 } |
1792 | 1705 |
1793 | |
1794 void Simulator::DecodeSystem(Instr* instr) { | 1706 void Simulator::DecodeSystem(Instr* instr) { |
1795 if (instr->InstructionBits() == CLREX) { | 1707 if (instr->InstructionBits() == CLREX) { |
1796 // Format(instr, "clrex"); | 1708 // Format(instr, "clrex"); |
1797 ClearExclusive(); | 1709 ClearExclusive(); |
1798 return; | 1710 return; |
1799 } | 1711 } |
1800 | 1712 |
1801 if ((instr->Bits(0, 8) == 0x1f) && (instr->Bits(12, 4) == 2) && | 1713 if ((instr->Bits(0, 8) == 0x1f) && (instr->Bits(12, 4) == 2) && |
1802 (instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) && | 1714 (instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) && |
1803 (instr->Bit(21) == 0)) { | 1715 (instr->Bit(21) == 0)) { |
1804 if (instr->Bits(8, 4) == 0) { | 1716 if (instr->Bits(8, 4) == 0) { |
1805 // Format(instr, "nop"); | 1717 // Format(instr, "nop"); |
1806 } else { | 1718 } else { |
1807 UnimplementedInstruction(instr); | 1719 UnimplementedInstruction(instr); |
1808 } | 1720 } |
1809 } else { | 1721 } else { |
1810 UnimplementedInstruction(instr); | 1722 UnimplementedInstruction(instr); |
1811 } | 1723 } |
1812 } | 1724 } |
1813 | 1725 |
1814 | |
1815 void Simulator::DecodeTestAndBranch(Instr* instr) { | 1726 void Simulator::DecodeTestAndBranch(Instr* instr) { |
1816 const int op = instr->Bit(24); | 1727 const int op = instr->Bit(24); |
1817 const int bitpos = instr->Bits(19, 4) | (instr->Bit(31) << 5); | 1728 const int bitpos = instr->Bits(19, 4) | (instr->Bit(31) << 5); |
1818 const int64_t imm14 = instr->SImm14Field(); | 1729 const int64_t imm14 = instr->SImm14Field(); |
1819 const int64_t dest = get_pc() + (imm14 << 2); | 1730 const int64_t dest = get_pc() + (imm14 << 2); |
1820 const Register rt = instr->RtField(); | 1731 const Register rt = instr->RtField(); |
1821 const int64_t rt_val = get_register(rt, R31IsZR); | 1732 const int64_t rt_val = get_register(rt, R31IsZR); |
1822 if (op == 0) { | 1733 if (op == 0) { |
1823 // Format(instr, "tbz'sf 'rt, 'bitpos, 'dest14"); | 1734 // Format(instr, "tbz'sf 'rt, 'bitpos, 'dest14"); |
1824 if ((rt_val & (1 << bitpos)) == 0) { | 1735 if ((rt_val & (1 << bitpos)) == 0) { |
1825 set_pc(dest); | 1736 set_pc(dest); |
1826 } | 1737 } |
1827 } else { | 1738 } else { |
1828 // Format(instr, "tbnz'sf 'rt, 'bitpos, 'dest14"); | 1739 // Format(instr, "tbnz'sf 'rt, 'bitpos, 'dest14"); |
1829 if ((rt_val & (1 << bitpos)) != 0) { | 1740 if ((rt_val & (1 << bitpos)) != 0) { |
1830 set_pc(dest); | 1741 set_pc(dest); |
1831 } | 1742 } |
1832 } | 1743 } |
1833 } | 1744 } |
1834 | 1745 |
1835 | |
1836 void Simulator::DecodeUnconditionalBranch(Instr* instr) { | 1746 void Simulator::DecodeUnconditionalBranch(Instr* instr) { |
1837 const bool link = instr->Bit(31) == 1; | 1747 const bool link = instr->Bit(31) == 1; |
1838 const int64_t imm26 = instr->SImm26Field(); | 1748 const int64_t imm26 = instr->SImm26Field(); |
1839 const int64_t dest = get_pc() + (imm26 << 2); | 1749 const int64_t dest = get_pc() + (imm26 << 2); |
1840 const int64_t ret = get_pc() + Instr::kInstrSize; | 1750 const int64_t ret = get_pc() + Instr::kInstrSize; |
1841 set_pc(dest); | 1751 set_pc(dest); |
1842 if (link) { | 1752 if (link) { |
1843 set_register(instr, LR, ret); | 1753 set_register(instr, LR, ret); |
1844 } | 1754 } |
1845 } | 1755 } |
1846 | 1756 |
1847 | |
1848 void Simulator::DecodeUnconditionalBranchReg(Instr* instr) { | 1757 void Simulator::DecodeUnconditionalBranchReg(Instr* instr) { |
1849 if ((instr->Bits(0, 5) == 0) && (instr->Bits(10, 6) == 0) && | 1758 if ((instr->Bits(0, 5) == 0) && (instr->Bits(10, 6) == 0) && |
1850 (instr->Bits(16, 5) == 0x1f)) { | 1759 (instr->Bits(16, 5) == 0x1f)) { |
1851 switch (instr->Bits(21, 4)) { | 1760 switch (instr->Bits(21, 4)) { |
1852 case 0: { | 1761 case 0: { |
1853 // Format(instr, "br 'rn"); | 1762 // Format(instr, "br 'rn"); |
1854 const Register rn = instr->RnField(); | 1763 const Register rn = instr->RnField(); |
1855 const int64_t dest = get_register(rn, instr->RnMode()); | 1764 const int64_t dest = get_register(rn, instr->RnMode()); |
1856 set_pc(dest); | 1765 set_pc(dest); |
1857 break; | 1766 break; |
(...skipping 16 matching lines...) Expand all Loading... |
1874 } | 1783 } |
1875 default: | 1784 default: |
1876 UnimplementedInstruction(instr); | 1785 UnimplementedInstruction(instr); |
1877 break; | 1786 break; |
1878 } | 1787 } |
1879 } else { | 1788 } else { |
1880 UnimplementedInstruction(instr); | 1789 UnimplementedInstruction(instr); |
1881 } | 1790 } |
1882 } | 1791 } |
1883 | 1792 |
1884 | |
1885 void Simulator::DecodeCompareBranch(Instr* instr) { | 1793 void Simulator::DecodeCompareBranch(Instr* instr) { |
1886 if (instr->IsCompareAndBranchOp()) { | 1794 if (instr->IsCompareAndBranchOp()) { |
1887 DecodeCompareAndBranch(instr); | 1795 DecodeCompareAndBranch(instr); |
1888 } else if (instr->IsConditionalBranchOp()) { | 1796 } else if (instr->IsConditionalBranchOp()) { |
1889 DecodeConditionalBranch(instr); | 1797 DecodeConditionalBranch(instr); |
1890 } else if (instr->IsExceptionGenOp()) { | 1798 } else if (instr->IsExceptionGenOp()) { |
1891 DecodeExceptionGen(instr); | 1799 DecodeExceptionGen(instr); |
1892 } else if (instr->IsSystemOp()) { | 1800 } else if (instr->IsSystemOp()) { |
1893 DecodeSystem(instr); | 1801 DecodeSystem(instr); |
1894 } else if (instr->IsTestAndBranchOp()) { | 1802 } else if (instr->IsTestAndBranchOp()) { |
1895 DecodeTestAndBranch(instr); | 1803 DecodeTestAndBranch(instr); |
1896 } else if (instr->IsUnconditionalBranchOp()) { | 1804 } else if (instr->IsUnconditionalBranchOp()) { |
1897 DecodeUnconditionalBranch(instr); | 1805 DecodeUnconditionalBranch(instr); |
1898 } else if (instr->IsUnconditionalBranchRegOp()) { | 1806 } else if (instr->IsUnconditionalBranchRegOp()) { |
1899 DecodeUnconditionalBranchReg(instr); | 1807 DecodeUnconditionalBranchReg(instr); |
1900 } else { | 1808 } else { |
1901 UnimplementedInstruction(instr); | 1809 UnimplementedInstruction(instr); |
1902 } | 1810 } |
1903 } | 1811 } |
1904 | 1812 |
1905 | |
1906 void Simulator::DecodeLoadStoreReg(Instr* instr) { | 1813 void Simulator::DecodeLoadStoreReg(Instr* instr) { |
1907 // Calculate the address. | 1814 // Calculate the address. |
1908 const Register rn = instr->RnField(); | 1815 const Register rn = instr->RnField(); |
1909 const Register rt = instr->RtField(); | 1816 const Register rt = instr->RtField(); |
1910 const VRegister vt = instr->VtField(); | 1817 const VRegister vt = instr->VtField(); |
1911 const int64_t rn_val = get_register(rn, R31IsSP); | 1818 const int64_t rn_val = get_register(rn, R31IsSP); |
1912 const uint32_t size = (instr->Bit(26) == 1) | 1819 const uint32_t size = (instr->Bit(26) == 1) |
1913 ? ((instr->Bit(23) << 2) | instr->SzField()) | 1820 ? ((instr->Bit(23) << 2) | instr->SzField()) |
1914 : instr->SzField(); | 1821 : instr->SzField(); |
1915 uword address = 0; | 1822 uword address = 0; |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2089 } | 1996 } |
2090 } | 1997 } |
2091 } | 1998 } |
2092 | 1999 |
2093 // Do writeback. | 2000 // Do writeback. |
2094 if (wb) { | 2001 if (wb) { |
2095 set_register(instr, rn, wb_address, R31IsSP); | 2002 set_register(instr, rn, wb_address, R31IsSP); |
2096 } | 2003 } |
2097 } | 2004 } |
2098 | 2005 |
2099 | |
2100 void Simulator::DecodeLoadStoreRegPair(Instr* instr) { | 2006 void Simulator::DecodeLoadStoreRegPair(Instr* instr) { |
2101 const int32_t opc = instr->Bits(23, 3); | 2007 const int32_t opc = instr->Bits(23, 3); |
2102 const Register rn = instr->RnField(); | 2008 const Register rn = instr->RnField(); |
2103 const Register rt = instr->RtField(); | 2009 const Register rt = instr->RtField(); |
2104 const Register rt2 = instr->Rt2Field(); | 2010 const Register rt2 = instr->Rt2Field(); |
2105 const int64_t rn_val = get_register(rn, R31IsSP); | 2011 const int64_t rn_val = get_register(rn, R31IsSP); |
2106 const intptr_t shift = 2 + instr->SFField(); | 2012 const intptr_t shift = 2 + instr->SFField(); |
2107 const intptr_t size = 1 << shift; | 2013 const intptr_t size = 1 << shift; |
2108 const int32_t offset = (instr->SImm7Field() << shift); | 2014 const int32_t offset = (instr->SImm7Field() << shift); |
2109 uword address = 0; | 2015 uword address = 0; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2183 WriteW(address + size, val2, instr); | 2089 WriteW(address + size, val2, instr); |
2184 } | 2090 } |
2185 } | 2091 } |
2186 | 2092 |
2187 // Do writeback. | 2093 // Do writeback. |
2188 if (wb) { | 2094 if (wb) { |
2189 set_register(instr, rn, wb_address, R31IsSP); | 2095 set_register(instr, rn, wb_address, R31IsSP); |
2190 } | 2096 } |
2191 } | 2097 } |
2192 | 2098 |
2193 | |
2194 void Simulator::DecodeLoadRegLiteral(Instr* instr) { | 2099 void Simulator::DecodeLoadRegLiteral(Instr* instr) { |
2195 if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) || | 2100 if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) || |
2196 (instr->Bits(24, 3) != 0)) { | 2101 (instr->Bits(24, 3) != 0)) { |
2197 UnimplementedInstruction(instr); | 2102 UnimplementedInstruction(instr); |
2198 } | 2103 } |
2199 | 2104 |
2200 const Register rt = instr->RtField(); | 2105 const Register rt = instr->RtField(); |
2201 const int64_t off = instr->SImm19Field() << 2; | 2106 const int64_t off = instr->SImm19Field() << 2; |
2202 const int64_t pc = reinterpret_cast<int64_t>(instr); | 2107 const int64_t pc = reinterpret_cast<int64_t>(instr); |
2203 const int64_t address = pc + off; | 2108 const int64_t address = pc + off; |
2204 const int64_t val = ReadX(address, instr); | 2109 const int64_t val = ReadX(address, instr); |
2205 if (instr->Bit(30)) { | 2110 if (instr->Bit(30)) { |
2206 // Format(instr, "ldrx 'rt, 'pcldr"); | 2111 // Format(instr, "ldrx 'rt, 'pcldr"); |
2207 set_register(instr, rt, val, R31IsZR); | 2112 set_register(instr, rt, val, R31IsZR); |
2208 } else { | 2113 } else { |
2209 // Format(instr, "ldrw 'rt, 'pcldr"); | 2114 // Format(instr, "ldrw 'rt, 'pcldr"); |
2210 set_wregister(rt, static_cast<int32_t>(val), R31IsZR); | 2115 set_wregister(rt, static_cast<int32_t>(val), R31IsZR); |
2211 } | 2116 } |
2212 } | 2117 } |
2213 | 2118 |
2214 | |
2215 void Simulator::DecodeLoadStoreExclusive(Instr* instr) { | 2119 void Simulator::DecodeLoadStoreExclusive(Instr* instr) { |
2216 if ((instr->Bit(23) != 0) || (instr->Bit(21) != 0) || (instr->Bit(15) != 0)) { | 2120 if ((instr->Bit(23) != 0) || (instr->Bit(21) != 0) || (instr->Bit(15) != 0)) { |
2217 UNIMPLEMENTED(); | 2121 UNIMPLEMENTED(); |
2218 } | 2122 } |
2219 const int32_t size = instr->Bits(30, 2); | 2123 const int32_t size = instr->Bits(30, 2); |
2220 if (size != 3 && size != 2) { | 2124 if (size != 3 && size != 2) { |
2221 UNIMPLEMENTED(); | 2125 UNIMPLEMENTED(); |
2222 } | 2126 } |
2223 const Register rs = instr->RsField(); | 2127 const Register rs = instr->RsField(); |
2224 const Register rn = instr->RnField(); | 2128 const Register rn = instr->RnField(); |
(...skipping 19 matching lines...) Expand all Loading... |
2244 set_register(instr, rs, status, R31IsSP); | 2148 set_register(instr, rs, status, R31IsSP); |
2245 } else { | 2149 } else { |
2246 uint32_t value = get_register(rt, R31IsSP); | 2150 uint32_t value = get_register(rt, R31IsSP); |
2247 uword addr = get_register(rn, R31IsSP); | 2151 uword addr = get_register(rn, R31IsSP); |
2248 intptr_t status = WriteExclusiveW(addr, value, instr); | 2152 intptr_t status = WriteExclusiveW(addr, value, instr); |
2249 set_register(instr, rs, status, R31IsSP); | 2153 set_register(instr, rs, status, R31IsSP); |
2250 } | 2154 } |
2251 } | 2155 } |
2252 } | 2156 } |
2253 | 2157 |
2254 | |
2255 void Simulator::DecodeLoadStore(Instr* instr) { | 2158 void Simulator::DecodeLoadStore(Instr* instr) { |
2256 if (instr->IsLoadStoreRegOp()) { | 2159 if (instr->IsLoadStoreRegOp()) { |
2257 DecodeLoadStoreReg(instr); | 2160 DecodeLoadStoreReg(instr); |
2258 } else if (instr->IsLoadStoreRegPairOp()) { | 2161 } else if (instr->IsLoadStoreRegPairOp()) { |
2259 DecodeLoadStoreRegPair(instr); | 2162 DecodeLoadStoreRegPair(instr); |
2260 } else if (instr->IsLoadRegLiteralOp()) { | 2163 } else if (instr->IsLoadRegLiteralOp()) { |
2261 DecodeLoadRegLiteral(instr); | 2164 DecodeLoadRegLiteral(instr); |
2262 } else if (instr->IsLoadStoreExclusiveOp()) { | 2165 } else if (instr->IsLoadStoreExclusiveOp()) { |
2263 DecodeLoadStoreExclusive(instr); | 2166 DecodeLoadStoreExclusive(instr); |
2264 } else { | 2167 } else { |
2265 UnimplementedInstruction(instr); | 2168 UnimplementedInstruction(instr); |
2266 } | 2169 } |
2267 } | 2170 } |
2268 | 2171 |
2269 | |
2270 int64_t Simulator::ShiftOperand(uint8_t reg_size, | 2172 int64_t Simulator::ShiftOperand(uint8_t reg_size, |
2271 int64_t value, | 2173 int64_t value, |
2272 Shift shift_type, | 2174 Shift shift_type, |
2273 uint8_t amount) { | 2175 uint8_t amount) { |
2274 if (amount == 0) { | 2176 if (amount == 0) { |
2275 return value; | 2177 return value; |
2276 } | 2178 } |
2277 int64_t mask = reg_size == kXRegSizeInBits ? kXRegMask : kWRegMask; | 2179 int64_t mask = reg_size == kXRegSizeInBits ? kXRegMask : kWRegMask; |
2278 switch (shift_type) { | 2180 switch (shift_type) { |
2279 case LSL: | 2181 case LSL: |
(...skipping 14 matching lines...) Expand all Loading... |
2294 return (static_cast<uint64_t>(value) >> amount) | | 2196 return (static_cast<uint64_t>(value) >> amount) | |
2295 ((static_cast<uint64_t>(value) & ((1ULL << amount) - 1ULL)) | 2197 ((static_cast<uint64_t>(value) & ((1ULL << amount) - 1ULL)) |
2296 << (reg_size - amount)); | 2198 << (reg_size - amount)); |
2297 } | 2199 } |
2298 default: | 2200 default: |
2299 UNIMPLEMENTED(); | 2201 UNIMPLEMENTED(); |
2300 return 0; | 2202 return 0; |
2301 } | 2203 } |
2302 } | 2204 } |
2303 | 2205 |
2304 | |
2305 int64_t Simulator::ExtendOperand(uint8_t reg_size, | 2206 int64_t Simulator::ExtendOperand(uint8_t reg_size, |
2306 int64_t value, | 2207 int64_t value, |
2307 Extend extend_type, | 2208 Extend extend_type, |
2308 uint8_t amount) { | 2209 uint8_t amount) { |
2309 switch (extend_type) { | 2210 switch (extend_type) { |
2310 case UXTB: | 2211 case UXTB: |
2311 value &= 0xff; | 2212 value &= 0xff; |
2312 break; | 2213 break; |
2313 case UXTH: | 2214 case UXTH: |
2314 value &= 0xffff; | 2215 value &= 0xffff; |
(...skipping 14 matching lines...) Expand all Loading... |
2329 case SXTX: | 2230 case SXTX: |
2330 break; | 2231 break; |
2331 default: | 2232 default: |
2332 UNREACHABLE(); | 2233 UNREACHABLE(); |
2333 break; | 2234 break; |
2334 } | 2235 } |
2335 int64_t mask = (reg_size == kXRegSizeInBits) ? kXRegMask : kWRegMask; | 2236 int64_t mask = (reg_size == kXRegSizeInBits) ? kXRegMask : kWRegMask; |
2336 return (value << amount) & mask; | 2237 return (value << amount) & mask; |
2337 } | 2238 } |
2338 | 2239 |
2339 | |
2340 int64_t Simulator::DecodeShiftExtendOperand(Instr* instr) { | 2240 int64_t Simulator::DecodeShiftExtendOperand(Instr* instr) { |
2341 const Register rm = instr->RmField(); | 2241 const Register rm = instr->RmField(); |
2342 const int64_t rm_val = get_register(rm, R31IsZR); | 2242 const int64_t rm_val = get_register(rm, R31IsZR); |
2343 const uint8_t size = instr->SFField() ? kXRegSizeInBits : kWRegSizeInBits; | 2243 const uint8_t size = instr->SFField() ? kXRegSizeInBits : kWRegSizeInBits; |
2344 if (instr->IsShift()) { | 2244 if (instr->IsShift()) { |
2345 const Shift shift_type = instr->ShiftTypeField(); | 2245 const Shift shift_type = instr->ShiftTypeField(); |
2346 const uint8_t shift_amount = instr->Imm6Field(); | 2246 const uint8_t shift_amount = instr->Imm6Field(); |
2347 return ShiftOperand(size, rm_val, shift_type, shift_amount); | 2247 return ShiftOperand(size, rm_val, shift_type, shift_amount); |
2348 } else { | 2248 } else { |
2349 ASSERT(instr->IsExtend()); | 2249 ASSERT(instr->IsExtend()); |
2350 const Extend extend_type = instr->ExtendTypeField(); | 2250 const Extend extend_type = instr->ExtendTypeField(); |
2351 const uint8_t shift_amount = instr->Imm3Field(); | 2251 const uint8_t shift_amount = instr->Imm3Field(); |
2352 return ExtendOperand(size, rm_val, extend_type, shift_amount); | 2252 return ExtendOperand(size, rm_val, extend_type, shift_amount); |
2353 } | 2253 } |
2354 UNREACHABLE(); | 2254 UNREACHABLE(); |
2355 return -1; | 2255 return -1; |
2356 } | 2256 } |
2357 | 2257 |
2358 | |
2359 void Simulator::DecodeAddSubShiftExt(Instr* instr) { | 2258 void Simulator::DecodeAddSubShiftExt(Instr* instr) { |
2360 // Format(instr, "add'sf's 'rd, 'rn, 'shift_op"); | 2259 // Format(instr, "add'sf's 'rd, 'rn, 'shift_op"); |
2361 // also, sub, cmp, etc. | 2260 // also, sub, cmp, etc. |
2362 const bool addition = (instr->Bit(30) == 0); | 2261 const bool addition = (instr->Bit(30) == 0); |
2363 const Register rd = instr->RdField(); | 2262 const Register rd = instr->RdField(); |
2364 const Register rn = instr->RnField(); | 2263 const Register rn = instr->RnField(); |
2365 const int64_t rm_val = DecodeShiftExtendOperand(instr); | 2264 const int64_t rm_val = DecodeShiftExtendOperand(instr); |
2366 if (instr->SFField()) { | 2265 if (instr->SFField()) { |
2367 // 64-bit add. | 2266 // 64-bit add. |
2368 const int64_t rn_val = get_register(rn, instr->RnMode()); | 2267 const int64_t rn_val = get_register(rn, instr->RnMode()); |
(...skipping 16 matching lines...) Expand all Loading... |
2385 const int32_t alu_out = rn_val + rm_val32 + carry_in; | 2284 const int32_t alu_out = rn_val + rm_val32 + carry_in; |
2386 set_wregister(rd, alu_out, instr->RdMode()); | 2285 set_wregister(rd, alu_out, instr->RdMode()); |
2387 if (instr->HasS()) { | 2286 if (instr->HasS()) { |
2388 SetNZFlagsW(alu_out); | 2287 SetNZFlagsW(alu_out); |
2389 SetCFlag(CarryFromW(rn_val, rm_val32, carry_in)); | 2288 SetCFlag(CarryFromW(rn_val, rm_val32, carry_in)); |
2390 SetVFlag(OverflowFromW(rn_val, rm_val32, carry_in)); | 2289 SetVFlag(OverflowFromW(rn_val, rm_val32, carry_in)); |
2391 } | 2290 } |
2392 } | 2291 } |
2393 } | 2292 } |
2394 | 2293 |
2395 | |
2396 void Simulator::DecodeAddSubWithCarry(Instr* instr) { | 2294 void Simulator::DecodeAddSubWithCarry(Instr* instr) { |
2397 // Format(instr, "adc'sf's 'rd, 'rn, 'rm"); | 2295 // Format(instr, "adc'sf's 'rd, 'rn, 'rm"); |
2398 // Format(instr, "sbc'sf's 'rd, 'rn, 'rm"); | 2296 // Format(instr, "sbc'sf's 'rd, 'rn, 'rm"); |
2399 const bool addition = (instr->Bit(30) == 0); | 2297 const bool addition = (instr->Bit(30) == 0); |
2400 const Register rd = instr->RdField(); | 2298 const Register rd = instr->RdField(); |
2401 const Register rn = instr->RnField(); | 2299 const Register rn = instr->RnField(); |
2402 const Register rm = instr->RmField(); | 2300 const Register rm = instr->RmField(); |
2403 const int64_t rn_val64 = get_register(rn, R31IsZR); | 2301 const int64_t rn_val64 = get_register(rn, R31IsZR); |
2404 const int32_t rn_val32 = get_wregister(rn, R31IsZR); | 2302 const int32_t rn_val32 = get_wregister(rn, R31IsZR); |
2405 const int64_t rm_val64 = get_register(rm, R31IsZR); | 2303 const int64_t rm_val64 = get_register(rm, R31IsZR); |
(...skipping 17 matching lines...) Expand all Loading... |
2423 const int32_t alu_out = rn_val32 + rm_val32 + carry_in; | 2321 const int32_t alu_out = rn_val32 + rm_val32 + carry_in; |
2424 set_wregister(rd, alu_out, R31IsZR); | 2322 set_wregister(rd, alu_out, R31IsZR); |
2425 if (instr->HasS()) { | 2323 if (instr->HasS()) { |
2426 SetNZFlagsW(alu_out); | 2324 SetNZFlagsW(alu_out); |
2427 SetCFlag(CarryFromW(rn_val32, rm_val32, carry_in)); | 2325 SetCFlag(CarryFromW(rn_val32, rm_val32, carry_in)); |
2428 SetVFlag(OverflowFromW(rn_val32, rm_val32, carry_in)); | 2326 SetVFlag(OverflowFromW(rn_val32, rm_val32, carry_in)); |
2429 } | 2327 } |
2430 } | 2328 } |
2431 } | 2329 } |
2432 | 2330 |
2433 | |
2434 void Simulator::DecodeLogicalShift(Instr* instr) { | 2331 void Simulator::DecodeLogicalShift(Instr* instr) { |
2435 const int op = (instr->Bits(29, 2) << 1) | instr->Bit(21); | 2332 const int op = (instr->Bits(29, 2) << 1) | instr->Bit(21); |
2436 const Register rd = instr->RdField(); | 2333 const Register rd = instr->RdField(); |
2437 const Register rn = instr->RnField(); | 2334 const Register rn = instr->RnField(); |
2438 const int64_t rn_val = get_register(rn, instr->RnMode()); | 2335 const int64_t rn_val = get_register(rn, instr->RnMode()); |
2439 const int64_t rm_val = DecodeShiftExtendOperand(instr); | 2336 const int64_t rm_val = DecodeShiftExtendOperand(instr); |
2440 int64_t alu_out = 0; | 2337 int64_t alu_out = 0; |
2441 switch (op) { | 2338 switch (op) { |
2442 case 0: | 2339 case 0: |
2443 // Format(instr, "and'sf 'rd, 'rn, 'shift_op"); | 2340 // Format(instr, "and'sf 'rd, 'rn, 'shift_op"); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2487 SetVFlag(false); | 2384 SetVFlag(false); |
2488 } | 2385 } |
2489 | 2386 |
2490 if (instr->SFField() == 1) { | 2387 if (instr->SFField() == 1) { |
2491 set_register(instr, rd, alu_out, instr->RdMode()); | 2388 set_register(instr, rd, alu_out, instr->RdMode()); |
2492 } else { | 2389 } else { |
2493 set_wregister(rd, alu_out & kWRegMask, instr->RdMode()); | 2390 set_wregister(rd, alu_out & kWRegMask, instr->RdMode()); |
2494 } | 2391 } |
2495 } | 2392 } |
2496 | 2393 |
2497 | |
2498 static int64_t divide64(int64_t top, int64_t bottom, bool signd) { | 2394 static int64_t divide64(int64_t top, int64_t bottom, bool signd) { |
2499 // ARM64 does not trap on integer division by zero. The destination register | 2395 // ARM64 does not trap on integer division by zero. The destination register |
2500 // is instead set to 0. | 2396 // is instead set to 0. |
2501 if (bottom == 0) { | 2397 if (bottom == 0) { |
2502 return 0; | 2398 return 0; |
2503 } | 2399 } |
2504 | 2400 |
2505 if (signd) { | 2401 if (signd) { |
2506 // INT_MIN / -1 = INT_MIN. | 2402 // INT_MIN / -1 = INT_MIN. |
2507 if ((top == static_cast<int64_t>(0x8000000000000000LL)) && | 2403 if ((top == static_cast<int64_t>(0x8000000000000000LL)) && |
2508 (bottom == static_cast<int64_t>(0xffffffffffffffffLL))) { | 2404 (bottom == static_cast<int64_t>(0xffffffffffffffffLL))) { |
2509 return static_cast<int64_t>(0x8000000000000000LL); | 2405 return static_cast<int64_t>(0x8000000000000000LL); |
2510 } else { | 2406 } else { |
2511 return top / bottom; | 2407 return top / bottom; |
2512 } | 2408 } |
2513 } else { | 2409 } else { |
2514 const uint64_t utop = static_cast<uint64_t>(top); | 2410 const uint64_t utop = static_cast<uint64_t>(top); |
2515 const uint64_t ubottom = static_cast<uint64_t>(bottom); | 2411 const uint64_t ubottom = static_cast<uint64_t>(bottom); |
2516 return static_cast<int64_t>(utop / ubottom); | 2412 return static_cast<int64_t>(utop / ubottom); |
2517 } | 2413 } |
2518 } | 2414 } |
2519 | 2415 |
2520 | |
2521 static int32_t divide32(int32_t top, int32_t bottom, bool signd) { | 2416 static int32_t divide32(int32_t top, int32_t bottom, bool signd) { |
2522 // ARM64 does not trap on integer division by zero. The destination register | 2417 // ARM64 does not trap on integer division by zero. The destination register |
2523 // is instead set to 0. | 2418 // is instead set to 0. |
2524 if (bottom == 0) { | 2419 if (bottom == 0) { |
2525 return 0; | 2420 return 0; |
2526 } | 2421 } |
2527 | 2422 |
2528 if (signd) { | 2423 if (signd) { |
2529 // INT_MIN / -1 = INT_MIN. | 2424 // INT_MIN / -1 = INT_MIN. |
2530 if ((top == static_cast<int32_t>(0x80000000)) && | 2425 if ((top == static_cast<int32_t>(0x80000000)) && |
2531 (bottom == static_cast<int32_t>(0xffffffff))) { | 2426 (bottom == static_cast<int32_t>(0xffffffff))) { |
2532 return static_cast<int32_t>(0x80000000); | 2427 return static_cast<int32_t>(0x80000000); |
2533 } else { | 2428 } else { |
2534 return top / bottom; | 2429 return top / bottom; |
2535 } | 2430 } |
2536 } else { | 2431 } else { |
2537 const uint32_t utop = static_cast<uint32_t>(top); | 2432 const uint32_t utop = static_cast<uint32_t>(top); |
2538 const uint32_t ubottom = static_cast<uint32_t>(bottom); | 2433 const uint32_t ubottom = static_cast<uint32_t>(bottom); |
2539 return static_cast<int32_t>(utop / ubottom); | 2434 return static_cast<int32_t>(utop / ubottom); |
2540 } | 2435 } |
2541 } | 2436 } |
2542 | 2437 |
2543 | |
2544 void Simulator::DecodeMiscDP1Source(Instr* instr) { | 2438 void Simulator::DecodeMiscDP1Source(Instr* instr) { |
2545 if (instr->Bit(29) != 0) { | 2439 if (instr->Bit(29) != 0) { |
2546 UnimplementedInstruction(instr); | 2440 UnimplementedInstruction(instr); |
2547 } | 2441 } |
2548 | 2442 |
2549 const Register rd = instr->RdField(); | 2443 const Register rd = instr->RdField(); |
2550 const Register rn = instr->RnField(); | 2444 const Register rn = instr->RnField(); |
2551 const int op = instr->Bits(10, 10); | 2445 const int op = instr->Bits(10, 10); |
2552 const int64_t rn_val64 = get_register(rn, R31IsZR); | 2446 const int64_t rn_val64 = get_register(rn, R31IsZR); |
2553 const int32_t rn_val32 = get_wregister(rn, R31IsZR); | 2447 const int32_t rn_val32 = get_wregister(rn, R31IsZR); |
(...skipping 16 matching lines...) Expand all Loading... |
2570 set_wregister(rd, rd_val, R31IsZR); | 2464 set_wregister(rd, rd_val, R31IsZR); |
2571 } | 2465 } |
2572 break; | 2466 break; |
2573 } | 2467 } |
2574 default: | 2468 default: |
2575 UnimplementedInstruction(instr); | 2469 UnimplementedInstruction(instr); |
2576 break; | 2470 break; |
2577 } | 2471 } |
2578 } | 2472 } |
2579 | 2473 |
2580 | |
2581 void Simulator::DecodeMiscDP2Source(Instr* instr) { | 2474 void Simulator::DecodeMiscDP2Source(Instr* instr) { |
2582 if (instr->Bit(29) != 0) { | 2475 if (instr->Bit(29) != 0) { |
2583 UnimplementedInstruction(instr); | 2476 UnimplementedInstruction(instr); |
2584 } | 2477 } |
2585 | 2478 |
2586 const Register rd = instr->RdField(); | 2479 const Register rd = instr->RdField(); |
2587 const Register rn = instr->RnField(); | 2480 const Register rn = instr->RnField(); |
2588 const Register rm = instr->RmField(); | 2481 const Register rm = instr->RmField(); |
2589 const int op = instr->Bits(10, 5); | 2482 const int op = instr->Bits(10, 5); |
2590 const int64_t rn_val64 = get_register(rn, R31IsZR); | 2483 const int64_t rn_val64 = get_register(rn, R31IsZR); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2638 set_wregister(rd, alu_out, R31IsZR); | 2531 set_wregister(rd, alu_out, R31IsZR); |
2639 } | 2532 } |
2640 break; | 2533 break; |
2641 } | 2534 } |
2642 default: | 2535 default: |
2643 UnimplementedInstruction(instr); | 2536 UnimplementedInstruction(instr); |
2644 break; | 2537 break; |
2645 } | 2538 } |
2646 } | 2539 } |
2647 | 2540 |
2648 | |
2649 void Simulator::DecodeMiscDP3Source(Instr* instr) { | 2541 void Simulator::DecodeMiscDP3Source(Instr* instr) { |
2650 const Register rd = instr->RdField(); | 2542 const Register rd = instr->RdField(); |
2651 const Register rn = instr->RnField(); | 2543 const Register rn = instr->RnField(); |
2652 const Register rm = instr->RmField(); | 2544 const Register rm = instr->RmField(); |
2653 const Register ra = instr->RaField(); | 2545 const Register ra = instr->RaField(); |
2654 if ((instr->Bits(29, 2) == 0) && (instr->Bits(21, 3) == 0) && | 2546 if ((instr->Bits(29, 2) == 0) && (instr->Bits(21, 3) == 0) && |
2655 (instr->Bit(15) == 0)) { | 2547 (instr->Bit(15) == 0)) { |
2656 // Format(instr, "madd'sf 'rd, 'rn, 'rm, 'ra"); | 2548 // Format(instr, "madd'sf 'rd, 'rn, 'rm, 'ra"); |
2657 if (instr->SFField() == 1) { | 2549 if (instr->SFField() == 1) { |
2658 const int64_t rn_val = get_register(rn, R31IsZR); | 2550 const int64_t rn_val = get_register(rn, R31IsZR); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2719 const uint64_t rn_val = static_cast<uint32_t>(get_wregister(rn, R31IsZR)); | 2611 const uint64_t rn_val = static_cast<uint32_t>(get_wregister(rn, R31IsZR)); |
2720 const uint64_t rm_val = static_cast<uint32_t>(get_wregister(rm, R31IsZR)); | 2612 const uint64_t rm_val = static_cast<uint32_t>(get_wregister(rm, R31IsZR)); |
2721 const uint64_t ra_val = get_register(ra, R31IsZR); | 2613 const uint64_t ra_val = get_register(ra, R31IsZR); |
2722 const uint64_t alu_out = ra_val + (rn_val * rm_val); | 2614 const uint64_t alu_out = ra_val + (rn_val * rm_val); |
2723 set_register(instr, rd, alu_out, R31IsZR); | 2615 set_register(instr, rd, alu_out, R31IsZR); |
2724 } else { | 2616 } else { |
2725 UnimplementedInstruction(instr); | 2617 UnimplementedInstruction(instr); |
2726 } | 2618 } |
2727 } | 2619 } |
2728 | 2620 |
2729 | |
2730 void Simulator::DecodeConditionalSelect(Instr* instr) { | 2621 void Simulator::DecodeConditionalSelect(Instr* instr) { |
2731 const Register rd = instr->RdField(); | 2622 const Register rd = instr->RdField(); |
2732 const Register rn = instr->RnField(); | 2623 const Register rn = instr->RnField(); |
2733 const Register rm = instr->RmField(); | 2624 const Register rm = instr->RmField(); |
2734 const int64_t rm_val64 = get_register(rm, R31IsZR); | 2625 const int64_t rm_val64 = get_register(rm, R31IsZR); |
2735 const int32_t rm_val32 = get_wregister(rm, R31IsZR); | 2626 const int32_t rm_val32 = get_wregister(rm, R31IsZR); |
2736 const int64_t rn_val64 = get_register(rn, instr->RnMode()); | 2627 const int64_t rn_val64 = get_register(rn, instr->RnMode()); |
2737 const int32_t rn_val32 = get_wregister(rn, instr->RnMode()); | 2628 const int32_t rn_val32 = get_wregister(rn, instr->RnMode()); |
2738 int64_t result64 = 0; | 2629 int64_t result64 = 0; |
2739 int32_t result32 = 0; | 2630 int32_t result32 = 0; |
(...skipping 27 matching lines...) Expand all Loading... |
2767 return; | 2658 return; |
2768 } | 2659 } |
2769 | 2660 |
2770 if (instr->SFField() == 1) { | 2661 if (instr->SFField() == 1) { |
2771 set_register(instr, rd, result64, instr->RdMode()); | 2662 set_register(instr, rd, result64, instr->RdMode()); |
2772 } else { | 2663 } else { |
2773 set_wregister(rd, result32, instr->RdMode()); | 2664 set_wregister(rd, result32, instr->RdMode()); |
2774 } | 2665 } |
2775 } | 2666 } |
2776 | 2667 |
2777 | |
2778 void Simulator::DecodeDPRegister(Instr* instr) { | 2668 void Simulator::DecodeDPRegister(Instr* instr) { |
2779 if (instr->IsAddSubShiftExtOp()) { | 2669 if (instr->IsAddSubShiftExtOp()) { |
2780 DecodeAddSubShiftExt(instr); | 2670 DecodeAddSubShiftExt(instr); |
2781 } else if (instr->IsAddSubWithCarryOp()) { | 2671 } else if (instr->IsAddSubWithCarryOp()) { |
2782 DecodeAddSubWithCarry(instr); | 2672 DecodeAddSubWithCarry(instr); |
2783 } else if (instr->IsLogicalShiftOp()) { | 2673 } else if (instr->IsLogicalShiftOp()) { |
2784 DecodeLogicalShift(instr); | 2674 DecodeLogicalShift(instr); |
2785 } else if (instr->IsMiscDP1SourceOp()) { | 2675 } else if (instr->IsMiscDP1SourceOp()) { |
2786 DecodeMiscDP1Source(instr); | 2676 DecodeMiscDP1Source(instr); |
2787 } else if (instr->IsMiscDP2SourceOp()) { | 2677 } else if (instr->IsMiscDP2SourceOp()) { |
2788 DecodeMiscDP2Source(instr); | 2678 DecodeMiscDP2Source(instr); |
2789 } else if (instr->IsMiscDP3SourceOp()) { | 2679 } else if (instr->IsMiscDP3SourceOp()) { |
2790 DecodeMiscDP3Source(instr); | 2680 DecodeMiscDP3Source(instr); |
2791 } else if (instr->IsConditionalSelectOp()) { | 2681 } else if (instr->IsConditionalSelectOp()) { |
2792 DecodeConditionalSelect(instr); | 2682 DecodeConditionalSelect(instr); |
2793 } else { | 2683 } else { |
2794 UnimplementedInstruction(instr); | 2684 UnimplementedInstruction(instr); |
2795 } | 2685 } |
2796 } | 2686 } |
2797 | 2687 |
2798 | |
2799 void Simulator::DecodeSIMDCopy(Instr* instr) { | 2688 void Simulator::DecodeSIMDCopy(Instr* instr) { |
2800 const int32_t Q = instr->Bit(30); | 2689 const int32_t Q = instr->Bit(30); |
2801 const int32_t op = instr->Bit(29); | 2690 const int32_t op = instr->Bit(29); |
2802 const int32_t imm4 = instr->Bits(11, 4); | 2691 const int32_t imm4 = instr->Bits(11, 4); |
2803 const int32_t imm5 = instr->Bits(16, 5); | 2692 const int32_t imm5 = instr->Bits(16, 5); |
2804 | 2693 |
2805 int32_t idx4 = -1; | 2694 int32_t idx4 = -1; |
2806 int32_t idx5 = -1; | 2695 int32_t idx5 = -1; |
2807 int32_t element_bytes; | 2696 int32_t element_bytes; |
2808 if (imm5 & 0x1) { | 2697 if (imm5 & 0x1) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2883 } else if (element_bytes == 8) { | 2772 } else if (element_bytes == 8) { |
2884 set_vregisterd(vd, idx5, get_vregisterd(vn, idx4)); | 2773 set_vregisterd(vd, idx5, get_vregisterd(vn, idx4)); |
2885 } else { | 2774 } else { |
2886 UnimplementedInstruction(instr); | 2775 UnimplementedInstruction(instr); |
2887 } | 2776 } |
2888 } else { | 2777 } else { |
2889 UnimplementedInstruction(instr); | 2778 UnimplementedInstruction(instr); |
2890 } | 2779 } |
2891 } | 2780 } |
2892 | 2781 |
2893 | |
2894 void Simulator::DecodeSIMDThreeSame(Instr* instr) { | 2782 void Simulator::DecodeSIMDThreeSame(Instr* instr) { |
2895 const int Q = instr->Bit(30); | 2783 const int Q = instr->Bit(30); |
2896 const int U = instr->Bit(29); | 2784 const int U = instr->Bit(29); |
2897 const int opcode = instr->Bits(11, 5); | 2785 const int opcode = instr->Bits(11, 5); |
2898 | 2786 |
2899 if (Q == 0) { | 2787 if (Q == 0) { |
2900 UnimplementedInstruction(instr); | 2788 UnimplementedInstruction(instr); |
2901 return; | 2789 return; |
2902 } | 2790 } |
2903 | 2791 |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3040 } | 2928 } |
3041 } else { | 2929 } else { |
3042 UnimplementedInstruction(instr); | 2930 UnimplementedInstruction(instr); |
3043 return; | 2931 return; |
3044 } | 2932 } |
3045 set_vregisterd(vd, idx, res); | 2933 set_vregisterd(vd, idx, res); |
3046 } | 2934 } |
3047 } | 2935 } |
3048 } | 2936 } |
3049 | 2937 |
3050 | |
3051 static float arm_reciprocal_sqrt_estimate(float a) { | 2938 static float arm_reciprocal_sqrt_estimate(float a) { |
3052 // From the ARM Architecture Reference Manual A2-87. | 2939 // From the ARM Architecture Reference Manual A2-87. |
3053 if (isinf(a) || (fabs(a) >= exp2f(126))) | 2940 if (isinf(a) || (fabs(a) >= exp2f(126))) |
3054 return 0.0; | 2941 return 0.0; |
3055 else if (a == 0.0) | 2942 else if (a == 0.0) |
3056 return kPosInfinity; | 2943 return kPosInfinity; |
3057 else if (isnan(a)) | 2944 else if (isnan(a)) |
3058 return a; | 2945 return a; |
3059 | 2946 |
3060 uint32_t a_bits = bit_cast<uint32_t, float>(a); | 2947 uint32_t a_bits = bit_cast<uint32_t, float>(a); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3095 double estimate = static_cast<double>(s) / 256.0; | 2982 double estimate = static_cast<double>(s) / 256.0; |
3096 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0))); | 2983 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0))); |
3097 | 2984 |
3098 // result = 0 : result_exp<7:0> : estimate<51:29> | 2985 // result = 0 : result_exp<7:0> : estimate<51:29> |
3099 int32_t result_bits = | 2986 int32_t result_bits = |
3100 ((result_exp & 0xff) << 23) | | 2987 ((result_exp & 0xff) << 23) | |
3101 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); | 2988 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); |
3102 return bit_cast<float, int32_t>(result_bits); | 2989 return bit_cast<float, int32_t>(result_bits); |
3103 } | 2990 } |
3104 | 2991 |
3105 | |
3106 static float arm_recip_estimate(float a) { | 2992 static float arm_recip_estimate(float a) { |
3107 // From the ARM Architecture Reference Manual A2-85. | 2993 // From the ARM Architecture Reference Manual A2-85. |
3108 if (isinf(a) || (fabs(a) >= exp2f(126))) | 2994 if (isinf(a) || (fabs(a) >= exp2f(126))) |
3109 return 0.0; | 2995 return 0.0; |
3110 else if (a == 0.0) | 2996 else if (a == 0.0) |
3111 return kPosInfinity; | 2997 return kPosInfinity; |
3112 else if (isnan(a)) | 2998 else if (isnan(a)) |
3113 return a; | 2999 return a; |
3114 | 3000 |
3115 uint32_t a_bits = bit_cast<uint32_t, float>(a); | 3001 uint32_t a_bits = bit_cast<uint32_t, float>(a); |
(...skipping 16 matching lines...) Expand all Loading... |
3132 double estimate = static_cast<double>(s) / 256.0; | 3018 double estimate = static_cast<double>(s) / 256.0; |
3133 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0))); | 3019 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0))); |
3134 | 3020 |
3135 // result = sign : result_exp<7:0> : estimate<51:29> | 3021 // result = sign : result_exp<7:0> : estimate<51:29> |
3136 int32_t result_bits = | 3022 int32_t result_bits = |
3137 (a_bits & 0x80000000) | ((result_exp & 0xff) << 23) | | 3023 (a_bits & 0x80000000) | ((result_exp & 0xff) << 23) | |
3138 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); | 3024 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); |
3139 return bit_cast<float, int32_t>(result_bits); | 3025 return bit_cast<float, int32_t>(result_bits); |
3140 } | 3026 } |
3141 | 3027 |
3142 | |
3143 void Simulator::DecodeSIMDTwoReg(Instr* instr) { | 3028 void Simulator::DecodeSIMDTwoReg(Instr* instr) { |
3144 const int32_t Q = instr->Bit(30); | 3029 const int32_t Q = instr->Bit(30); |
3145 const int32_t U = instr->Bit(29); | 3030 const int32_t U = instr->Bit(29); |
3146 const int32_t op = instr->Bits(12, 5); | 3031 const int32_t op = instr->Bits(12, 5); |
3147 const int32_t sz = instr->Bits(22, 2); | 3032 const int32_t sz = instr->Bits(22, 2); |
3148 const VRegister vd = instr->VdField(); | 3033 const VRegister vd = instr->VdField(); |
3149 const VRegister vn = instr->VnField(); | 3034 const VRegister vn = instr->VnField(); |
3150 | 3035 |
3151 if (Q != 1) { | 3036 if (Q != 1) { |
3152 UnimplementedInstruction(instr); | 3037 UnimplementedInstruction(instr); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3234 const int32_t vn_val = get_vregisters(vn, i); | 3119 const int32_t vn_val = get_vregisters(vn, i); |
3235 const float vn_flt = bit_cast<float, int32_t>(vn_val); | 3120 const float vn_flt = bit_cast<float, int32_t>(vn_val); |
3236 const float re = arm_reciprocal_sqrt_estimate(vn_flt); | 3121 const float re = arm_reciprocal_sqrt_estimate(vn_flt); |
3237 set_vregisters(vd, i, bit_cast<int32_t, float>(re)); | 3122 set_vregisters(vd, i, bit_cast<int32_t, float>(re)); |
3238 } | 3123 } |
3239 } else { | 3124 } else { |
3240 UnimplementedInstruction(instr); | 3125 UnimplementedInstruction(instr); |
3241 } | 3126 } |
3242 } | 3127 } |
3243 | 3128 |
3244 | |
3245 void Simulator::DecodeDPSimd1(Instr* instr) { | 3129 void Simulator::DecodeDPSimd1(Instr* instr) { |
3246 if (instr->IsSIMDCopyOp()) { | 3130 if (instr->IsSIMDCopyOp()) { |
3247 DecodeSIMDCopy(instr); | 3131 DecodeSIMDCopy(instr); |
3248 } else if (instr->IsSIMDThreeSameOp()) { | 3132 } else if (instr->IsSIMDThreeSameOp()) { |
3249 DecodeSIMDThreeSame(instr); | 3133 DecodeSIMDThreeSame(instr); |
3250 } else if (instr->IsSIMDTwoRegOp()) { | 3134 } else if (instr->IsSIMDTwoRegOp()) { |
3251 DecodeSIMDTwoReg(instr); | 3135 DecodeSIMDTwoReg(instr); |
3252 } else { | 3136 } else { |
3253 UnimplementedInstruction(instr); | 3137 UnimplementedInstruction(instr); |
3254 } | 3138 } |
3255 } | 3139 } |
3256 | 3140 |
3257 | |
3258 void Simulator::DecodeFPImm(Instr* instr) { | 3141 void Simulator::DecodeFPImm(Instr* instr) { |
3259 if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) || (instr->Bit(23) != 0) || | 3142 if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) || (instr->Bit(23) != 0) || |
3260 (instr->Bits(5, 5) != 0)) { | 3143 (instr->Bits(5, 5) != 0)) { |
3261 UnimplementedInstruction(instr); | 3144 UnimplementedInstruction(instr); |
3262 return; | 3145 return; |
3263 } | 3146 } |
3264 if (instr->Bit(22) == 1) { | 3147 if (instr->Bit(22) == 1) { |
3265 // Double. | 3148 // Double. |
3266 // Format(instr, "fmovd 'vd, #'immd"); | 3149 // Format(instr, "fmovd 'vd, #'immd"); |
3267 const VRegister vd = instr->VdField(); | 3150 const VRegister vd = instr->VdField(); |
3268 const int64_t immd = Instr::VFPExpandImm(instr->Imm8Field()); | 3151 const int64_t immd = Instr::VFPExpandImm(instr->Imm8Field()); |
3269 set_vregisterd(vd, 0, immd); | 3152 set_vregisterd(vd, 0, immd); |
3270 set_vregisterd(vd, 1, 0); | 3153 set_vregisterd(vd, 1, 0); |
3271 } else { | 3154 } else { |
3272 // Single. | 3155 // Single. |
3273 UnimplementedInstruction(instr); | 3156 UnimplementedInstruction(instr); |
3274 } | 3157 } |
3275 } | 3158 } |
3276 | 3159 |
3277 | |
3278 void Simulator::DecodeFPIntCvt(Instr* instr) { | 3160 void Simulator::DecodeFPIntCvt(Instr* instr) { |
3279 const VRegister vd = instr->VdField(); | 3161 const VRegister vd = instr->VdField(); |
3280 const VRegister vn = instr->VnField(); | 3162 const VRegister vn = instr->VnField(); |
3281 const Register rd = instr->RdField(); | 3163 const Register rd = instr->RdField(); |
3282 const Register rn = instr->RnField(); | 3164 const Register rn = instr->RnField(); |
3283 | 3165 |
3284 if (instr->Bit(29) != 0) { | 3166 if (instr->Bit(29) != 0) { |
3285 UnimplementedInstruction(instr); | 3167 UnimplementedInstruction(instr); |
3286 return; | 3168 return; |
3287 } | 3169 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3325 const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0)); | 3207 const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0)); |
3326 set_register(instr, rd, static_cast<int64_t>(vn_val), instr->RdMode()); | 3208 set_register(instr, rd, static_cast<int64_t>(vn_val), instr->RdMode()); |
3327 } else { | 3209 } else { |
3328 UnimplementedInstruction(instr); | 3210 UnimplementedInstruction(instr); |
3329 } | 3211 } |
3330 } else { | 3212 } else { |
3331 UnimplementedInstruction(instr); | 3213 UnimplementedInstruction(instr); |
3332 } | 3214 } |
3333 } | 3215 } |
3334 | 3216 |
3335 | |
3336 void Simulator::DecodeFPOneSource(Instr* instr) { | 3217 void Simulator::DecodeFPOneSource(Instr* instr) { |
3337 const int opc = instr->Bits(15, 6); | 3218 const int opc = instr->Bits(15, 6); |
3338 const VRegister vd = instr->VdField(); | 3219 const VRegister vd = instr->VdField(); |
3339 const VRegister vn = instr->VnField(); | 3220 const VRegister vn = instr->VnField(); |
3340 const int64_t vn_val = get_vregisterd(vn, 0); | 3221 const int64_t vn_val = get_vregisterd(vn, 0); |
3341 const int32_t vn_val32 = vn_val & kWRegMask; | 3222 const int32_t vn_val32 = vn_val & kWRegMask; |
3342 const double vn_dbl = bit_cast<double, int64_t>(vn_val); | 3223 const double vn_dbl = bit_cast<double, int64_t>(vn_val); |
3343 const float vn_flt = bit_cast<float, int32_t>(vn_val32); | 3224 const float vn_flt = bit_cast<float, int32_t>(vn_val32); |
3344 | 3225 |
3345 if ((opc != 5) && (instr->Bit(22) != 1)) { | 3226 if ((opc != 5) && (instr->Bit(22) != 1)) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3380 break; | 3261 break; |
3381 default: | 3262 default: |
3382 UnimplementedInstruction(instr); | 3263 UnimplementedInstruction(instr); |
3383 break; | 3264 break; |
3384 } | 3265 } |
3385 | 3266 |
3386 set_vregisterd(vd, 0, res_val); | 3267 set_vregisterd(vd, 0, res_val); |
3387 set_vregisterd(vd, 1, 0); | 3268 set_vregisterd(vd, 1, 0); |
3388 } | 3269 } |
3389 | 3270 |
3390 | |
3391 void Simulator::DecodeFPTwoSource(Instr* instr) { | 3271 void Simulator::DecodeFPTwoSource(Instr* instr) { |
3392 if (instr->Bits(22, 2) != 1) { | 3272 if (instr->Bits(22, 2) != 1) { |
3393 UnimplementedInstruction(instr); | 3273 UnimplementedInstruction(instr); |
3394 return; | 3274 return; |
3395 } | 3275 } |
3396 const VRegister vd = instr->VdField(); | 3276 const VRegister vd = instr->VdField(); |
3397 const VRegister vn = instr->VnField(); | 3277 const VRegister vn = instr->VnField(); |
3398 const VRegister vm = instr->VmField(); | 3278 const VRegister vm = instr->VmField(); |
3399 const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0)); | 3279 const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0)); |
3400 const double vm_val = bit_cast<double, int64_t>(get_vregisterd(vm, 0)); | 3280 const double vm_val = bit_cast<double, int64_t>(get_vregisterd(vm, 0)); |
(...skipping 19 matching lines...) Expand all Loading... |
3420 break; | 3300 break; |
3421 default: | 3301 default: |
3422 UnimplementedInstruction(instr); | 3302 UnimplementedInstruction(instr); |
3423 return; | 3303 return; |
3424 } | 3304 } |
3425 | 3305 |
3426 set_vregisterd(vd, 0, bit_cast<int64_t, double>(result)); | 3306 set_vregisterd(vd, 0, bit_cast<int64_t, double>(result)); |
3427 set_vregisterd(vd, 1, 0); | 3307 set_vregisterd(vd, 1, 0); |
3428 } | 3308 } |
3429 | 3309 |
3430 | |
3431 void Simulator::DecodeFPCompare(Instr* instr) { | 3310 void Simulator::DecodeFPCompare(Instr* instr) { |
3432 const VRegister vn = instr->VnField(); | 3311 const VRegister vn = instr->VnField(); |
3433 const VRegister vm = instr->VmField(); | 3312 const VRegister vm = instr->VmField(); |
3434 const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0)); | 3313 const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0)); |
3435 double vm_val; | 3314 double vm_val; |
3436 | 3315 |
3437 if ((instr->Bit(22) == 1) && (instr->Bits(3, 2) == 0)) { | 3316 if ((instr->Bit(22) == 1) && (instr->Bits(3, 2) == 0)) { |
3438 // Format(instr, "fcmpd 'vn, 'vm"); | 3317 // Format(instr, "fcmpd 'vn, 'vm"); |
3439 vm_val = bit_cast<double, int64_t>(get_vregisterd(vm, 0)); | 3318 vm_val = bit_cast<double, int64_t>(get_vregisterd(vm, 0)); |
3440 } else if ((instr->Bit(22) == 1) && (instr->Bits(3, 2) == 1)) { | 3319 } else if ((instr->Bit(22) == 1) && (instr->Bits(3, 2) == 1)) { |
(...skipping 20 matching lines...) Expand all Loading... |
3461 } else if (vn_val == vm_val) { | 3340 } else if (vn_val == vm_val) { |
3462 z_flag_ = true; | 3341 z_flag_ = true; |
3463 c_flag_ = true; | 3342 c_flag_ = true; |
3464 } else if (vn_val < vm_val) { | 3343 } else if (vn_val < vm_val) { |
3465 n_flag_ = true; | 3344 n_flag_ = true; |
3466 } else { | 3345 } else { |
3467 c_flag_ = true; | 3346 c_flag_ = true; |
3468 } | 3347 } |
3469 } | 3348 } |
3470 | 3349 |
3471 | |
3472 void Simulator::DecodeFP(Instr* instr) { | 3350 void Simulator::DecodeFP(Instr* instr) { |
3473 if (instr->IsFPImmOp()) { | 3351 if (instr->IsFPImmOp()) { |
3474 DecodeFPImm(instr); | 3352 DecodeFPImm(instr); |
3475 } else if (instr->IsFPIntCvtOp()) { | 3353 } else if (instr->IsFPIntCvtOp()) { |
3476 DecodeFPIntCvt(instr); | 3354 DecodeFPIntCvt(instr); |
3477 } else if (instr->IsFPOneSourceOp()) { | 3355 } else if (instr->IsFPOneSourceOp()) { |
3478 DecodeFPOneSource(instr); | 3356 DecodeFPOneSource(instr); |
3479 } else if (instr->IsFPTwoSourceOp()) { | 3357 } else if (instr->IsFPTwoSourceOp()) { |
3480 DecodeFPTwoSource(instr); | 3358 DecodeFPTwoSource(instr); |
3481 } else if (instr->IsFPCompareOp()) { | 3359 } else if (instr->IsFPCompareOp()) { |
3482 DecodeFPCompare(instr); | 3360 DecodeFPCompare(instr); |
3483 } else { | 3361 } else { |
3484 UnimplementedInstruction(instr); | 3362 UnimplementedInstruction(instr); |
3485 } | 3363 } |
3486 } | 3364 } |
3487 | 3365 |
3488 | |
3489 void Simulator::DecodeDPSimd2(Instr* instr) { | 3366 void Simulator::DecodeDPSimd2(Instr* instr) { |
3490 if (instr->IsFPOp()) { | 3367 if (instr->IsFPOp()) { |
3491 DecodeFP(instr); | 3368 DecodeFP(instr); |
3492 } else { | 3369 } else { |
3493 UnimplementedInstruction(instr); | 3370 UnimplementedInstruction(instr); |
3494 } | 3371 } |
3495 } | 3372 } |
3496 | 3373 |
3497 | |
3498 // Executes the current instruction. | 3374 // Executes the current instruction. |
3499 void Simulator::InstructionDecode(Instr* instr) { | 3375 void Simulator::InstructionDecode(Instr* instr) { |
3500 pc_modified_ = false; | 3376 pc_modified_ = false; |
3501 if (IsTracingExecution()) { | 3377 if (IsTracingExecution()) { |
3502 THR_Print("%" Pu64 " ", icount_); | 3378 THR_Print("%" Pu64 " ", icount_); |
3503 const uword start = reinterpret_cast<uword>(instr); | 3379 const uword start = reinterpret_cast<uword>(instr); |
3504 const uword end = start + Instr::kInstrSize; | 3380 const uword end = start + Instr::kInstrSize; |
3505 if (FLAG_support_disassembler) { | 3381 if (FLAG_support_disassembler) { |
3506 Disassembler::Disassemble(start, end); | 3382 Disassembler::Disassemble(start, end); |
3507 } else { | 3383 } else { |
(...skipping 15 matching lines...) Expand all Loading... |
3523 DecodeDPSimd2(instr); | 3399 DecodeDPSimd2(instr); |
3524 } else { | 3400 } else { |
3525 UnimplementedInstruction(instr); | 3401 UnimplementedInstruction(instr); |
3526 } | 3402 } |
3527 | 3403 |
3528 if (!pc_modified_) { | 3404 if (!pc_modified_) { |
3529 set_pc(reinterpret_cast<int64_t>(instr) + Instr::kInstrSize); | 3405 set_pc(reinterpret_cast<int64_t>(instr) + Instr::kInstrSize); |
3530 } | 3406 } |
3531 } | 3407 } |
3532 | 3408 |
3533 | |
3534 void Simulator::Execute() { | 3409 void Simulator::Execute() { |
3535 // Get the PC to simulate. Cannot use the accessor here as we need the | 3410 // Get the PC to simulate. Cannot use the accessor here as we need the |
3536 // raw PC value and not the one used as input to arithmetic instructions. | 3411 // raw PC value and not the one used as input to arithmetic instructions. |
3537 uword program_counter = get_pc(); | 3412 uword program_counter = get_pc(); |
3538 | 3413 |
3539 if (FLAG_stop_sim_at == ULLONG_MAX) { | 3414 if (FLAG_stop_sim_at == ULLONG_MAX) { |
3540 // Fast version of the dispatch loop without checking whether the simulator | 3415 // Fast version of the dispatch loop without checking whether the simulator |
3541 // should be stopping at a particular executed instruction. | 3416 // should be stopping at a particular executed instruction. |
3542 while (program_counter != kEndSimulatingPC) { | 3417 while (program_counter != kEndSimulatingPC) { |
3543 Instr* instr = reinterpret_cast<Instr*>(program_counter); | 3418 Instr* instr = reinterpret_cast<Instr*>(program_counter); |
(...skipping 20 matching lines...) Expand all Loading... |
3564 } else if (IsIllegalAddress(program_counter)) { | 3439 } else if (IsIllegalAddress(program_counter)) { |
3565 HandleIllegalAccess(program_counter, instr); | 3440 HandleIllegalAccess(program_counter, instr); |
3566 } else { | 3441 } else { |
3567 InstructionDecode(instr); | 3442 InstructionDecode(instr); |
3568 } | 3443 } |
3569 program_counter = get_pc(); | 3444 program_counter = get_pc(); |
3570 } | 3445 } |
3571 } | 3446 } |
3572 } | 3447 } |
3573 | 3448 |
3574 | |
3575 int64_t Simulator::Call(int64_t entry, | 3449 int64_t Simulator::Call(int64_t entry, |
3576 int64_t parameter0, | 3450 int64_t parameter0, |
3577 int64_t parameter1, | 3451 int64_t parameter1, |
3578 int64_t parameter2, | 3452 int64_t parameter2, |
3579 int64_t parameter3, | 3453 int64_t parameter3, |
3580 bool fp_return, | 3454 bool fp_return, |
3581 bool fp_args) { | 3455 bool fp_args) { |
3582 // Save the SP register before the call so we can restore it. | 3456 // Save the SP register before the call so we can restore it. |
3583 const intptr_t sp_before_call = get_register(R31, R31IsSP); | 3457 const intptr_t sp_before_call = get_register(R31, R31IsSP); |
3584 | 3458 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3657 set_register(NULL, R31, sp_before_call, R31IsSP); | 3531 set_register(NULL, R31, sp_before_call, R31IsSP); |
3658 int64_t return_value; | 3532 int64_t return_value; |
3659 if (fp_return) { | 3533 if (fp_return) { |
3660 return_value = get_vregisterd(V0, 0); | 3534 return_value = get_vregisterd(V0, 0); |
3661 } else { | 3535 } else { |
3662 return_value = get_register(R0); | 3536 return_value = get_register(R0); |
3663 } | 3537 } |
3664 return return_value; | 3538 return return_value; |
3665 } | 3539 } |
3666 | 3540 |
3667 | |
3668 void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) { | 3541 void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) { |
3669 // Walk over all setjmp buffers (simulated --> C++ transitions) | 3542 // Walk over all setjmp buffers (simulated --> C++ transitions) |
3670 // and try to find the setjmp associated with the simulated stack pointer. | 3543 // and try to find the setjmp associated with the simulated stack pointer. |
3671 SimulatorSetjmpBuffer* buf = last_setjmp_buffer(); | 3544 SimulatorSetjmpBuffer* buf = last_setjmp_buffer(); |
3672 while (buf->link() != NULL && buf->link()->sp() <= sp) { | 3545 while (buf->link() != NULL && buf->link()->sp() <= sp) { |
3673 buf = buf->link(); | 3546 buf = buf->link(); |
3674 } | 3547 } |
3675 ASSERT(buf != NULL); | 3548 ASSERT(buf != NULL); |
3676 | 3549 |
3677 // The C++ caller has not cleaned up the stack memory of C++ frames. | 3550 // The C++ caller has not cleaned up the stack memory of C++ frames. |
(...skipping 19 matching lines...) Expand all Loading... |
3697 set_register(NULL, CODE_REG, code); | 3570 set_register(NULL, CODE_REG, code); |
3698 set_register(NULL, PP, pp); | 3571 set_register(NULL, PP, pp); |
3699 buf->Longjmp(); | 3572 buf->Longjmp(); |
3700 } | 3573 } |
3701 | 3574 |
3702 } // namespace dart | 3575 } // namespace dart |
3703 | 3576 |
3704 #endif // !defined(USING_SIMULATOR) | 3577 #endif // !defined(USING_SIMULATOR) |
3705 | 3578 |
3706 #endif // defined TARGET_ARCH_ARM64 | 3579 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |