| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include <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_ARM) | 9 #if defined(TARGET_ARCH_ARM) |
| 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_arm.h" | 17 #include "vm/constants_arm.h" |
| 18 #include "vm/cpu.h" | 18 #include "vm/cpu.h" |
| 19 #include "vm/disassembler.h" | 19 #include "vm/disassembler.h" |
| 20 #include "vm/lockers.h" | 20 #include "vm/lockers.h" |
| 21 #include "vm/native_arguments.h" | 21 #include "vm/native_arguments.h" |
| 22 #include "vm/os_thread.h" |
| 22 #include "vm/stack_frame.h" | 23 #include "vm/stack_frame.h" |
| 23 #include "vm/os_thread.h" | |
| 24 | 24 |
| 25 namespace dart { | 25 namespace dart { |
| 26 | 26 |
| 27 DEFINE_FLAG(uint64_t, | 27 DEFINE_FLAG(uint64_t, |
| 28 trace_sim_after, | 28 trace_sim_after, |
| 29 ULLONG_MAX, | 29 ULLONG_MAX, |
| 30 "Trace simulator execution after instruction count reached."); | 30 "Trace simulator execution after instruction count reached."); |
| 31 DEFINE_FLAG(uint64_t, | 31 DEFINE_FLAG(uint64_t, |
| 32 stop_sim_at, | 32 stop_sim_at, |
| 33 ULLONG_MAX, | 33 ULLONG_MAX, |
| 34 "Instruction address or instruction count to stop simulator at."); | 34 "Instruction address or instruction count to stop simulator at."); |
| 35 | 35 |
| 36 | |
| 37 // This macro provides a platform independent use of sscanf. The reason for | 36 // This macro provides a platform independent use of sscanf. The reason for |
| 38 // SScanF not being implemented in a platform independent way through | 37 // SScanF not being implemented in a platform independent way through |
| 39 // OS in the same way as SNPrint is that the Windows C Run-Time | 38 // OS in the same way as SNPrint is that the Windows C Run-Time |
| 40 // Library does not provide vsscanf. | 39 // Library does not provide vsscanf. |
| 41 #define SScanF sscanf // NOLINT | 40 #define SScanF sscanf // NOLINT |
| 42 | 41 |
| 43 | |
| 44 // SimulatorSetjmpBuffer are linked together, and the last created one | 42 // SimulatorSetjmpBuffer are linked together, and the last created one |
| 45 // is referenced by the Simulator. When an exception is thrown, the exception | 43 // is referenced by the Simulator. When an exception is thrown, the exception |
| 46 // runtime looks at where to jump and finds the corresponding | 44 // runtime looks at where to jump and finds the corresponding |
| 47 // SimulatorSetjmpBuffer based on the stack pointer of the exception handler. | 45 // SimulatorSetjmpBuffer based on the stack pointer of the exception handler. |
| 48 // The runtime then does a Longjmp on that buffer to return to the simulator. | 46 // The runtime then does a Longjmp on that buffer to return to the simulator. |
| 49 class SimulatorSetjmpBuffer { | 47 class SimulatorSetjmpBuffer { |
| 50 public: | 48 public: |
| 51 void Longjmp() { | 49 void Longjmp() { |
| 52 // "This" is now the last setjmp buffer. | 50 // "This" is now the last setjmp buffer. |
| 53 simulator_->set_last_setjmp_buffer(this); | 51 simulator_->set_last_setjmp_buffer(this); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 72 | 70 |
| 73 private: | 71 private: |
| 74 uword sp_; | 72 uword sp_; |
| 75 Simulator* simulator_; | 73 Simulator* simulator_; |
| 76 SimulatorSetjmpBuffer* link_; | 74 SimulatorSetjmpBuffer* link_; |
| 77 jmp_buf buffer_; | 75 jmp_buf buffer_; |
| 78 | 76 |
| 79 friend class Simulator; | 77 friend class Simulator; |
| 80 }; | 78 }; |
| 81 | 79 |
| 82 | |
| 83 // The SimulatorDebugger class is used by the simulator while debugging | 80 // The SimulatorDebugger class is used by the simulator while debugging |
| 84 // simulated ARM code. | 81 // simulated ARM code. |
| 85 class SimulatorDebugger { | 82 class SimulatorDebugger { |
| 86 public: | 83 public: |
| 87 explicit SimulatorDebugger(Simulator* sim); | 84 explicit SimulatorDebugger(Simulator* sim); |
| 88 ~SimulatorDebugger(); | 85 ~SimulatorDebugger(); |
| 89 | 86 |
| 90 void Stop(Instr* instr, const char* message); | 87 void Stop(Instr* instr, const char* message); |
| 91 void Debug(); | 88 void Debug(); |
| 92 char* ReadLine(const char* prompt); | 89 char* ReadLine(const char* prompt); |
| (...skipping 19 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[] = {"r0", "r1", "r2", "r3", "r4", "r5", | 131 static const char* kNames[] = {"r0", "r1", "r2", "r3", "r4", "r5", |
| 139 "r6", "r7", "r8", "r9", "r10", "r11", | 132 "r6", "r7", "r8", "r9", "r10", "r11", |
| 140 "r12", "r13", "r14", "r15", "pc", "lr", | 133 "r12", "r13", "r14", "r15", "pc", "lr", |
| 141 "sp", "ip", "fp", "pp", "ctx"}; | 134 "sp", "ip", "fp", "pp", "ctx"}; |
| 142 static const Register kRegisters[] = {R0, R1, R2, R3, R4, R5, R6, R7, | 135 static const Register kRegisters[] = {R0, R1, R2, R3, R4, R5, R6, R7, |
| 143 R8, R9, R10, R11, R12, R13, R14, R15, | 136 R8, R9, R10, R11, R12, R13, R14, R15, |
| 144 PC, LR, SP, IP, FP, PP, CTX}; | 137 PC, LR, SP, IP, FP, PP, CTX}; |
| 145 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters)); | 138 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters)); |
| 146 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) { | 139 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) { |
| 147 if (strcmp(kNames[i], name) == 0) { | 140 if (strcmp(kNames[i], name) == 0) { |
| 148 return kRegisters[i]; | 141 return kRegisters[i]; |
| 149 } | 142 } |
| 150 } | 143 } |
| 151 return kNoRegister; | 144 return kNoRegister; |
| 152 } | 145 } |
| 153 | 146 |
| 154 | |
| 155 static SRegister LookupSRegisterByName(const char* name) { | 147 static SRegister LookupSRegisterByName(const char* name) { |
| 156 int reg_nr = -1; | 148 int reg_nr = -1; |
| 157 bool ok = SScanF(name, "s%d", ®_nr); | 149 bool ok = SScanF(name, "s%d", ®_nr); |
| 158 if (ok && (0 <= reg_nr) && (reg_nr < kNumberOfSRegisters)) { | 150 if (ok && (0 <= reg_nr) && (reg_nr < kNumberOfSRegisters)) { |
| 159 return static_cast<SRegister>(reg_nr); | 151 return static_cast<SRegister>(reg_nr); |
| 160 } | 152 } |
| 161 return kNoSRegister; | 153 return kNoSRegister; |
| 162 } | 154 } |
| 163 | 155 |
| 164 | |
| 165 static DRegister LookupDRegisterByName(const char* name) { | 156 static DRegister LookupDRegisterByName(const char* name) { |
| 166 int reg_nr = -1; | 157 int reg_nr = -1; |
| 167 bool ok = SScanF(name, "d%d", ®_nr); | 158 bool ok = SScanF(name, "d%d", ®_nr); |
| 168 if (ok && (0 <= reg_nr) && (reg_nr < kNumberOfDRegisters)) { | 159 if (ok && (0 <= reg_nr) && (reg_nr < kNumberOfDRegisters)) { |
| 169 return static_cast<DRegister>(reg_nr); | 160 return static_cast<DRegister>(reg_nr); |
| 170 } | 161 } |
| 171 return kNoDRegister; | 162 return kNoDRegister; |
| 172 } | 163 } |
| 173 | 164 |
| 174 | |
| 175 bool SimulatorDebugger::GetValue(char* desc, uint32_t* value) { | 165 bool SimulatorDebugger::GetValue(char* desc, uint32_t* value) { |
| 176 Register reg = LookupCpuRegisterByName(desc); | 166 Register reg = LookupCpuRegisterByName(desc); |
| 177 if (reg != kNoRegister) { | 167 if (reg != kNoRegister) { |
| 178 if (reg == PC) { | 168 if (reg == PC) { |
| 179 *value = sim_->get_pc(); | 169 *value = sim_->get_pc(); |
| 180 } else { | 170 } else { |
| 181 *value = sim_->get_register(reg); | 171 *value = sim_->get_register(reg); |
| 182 } | 172 } |
| 183 return true; | 173 return true; |
| 184 } | 174 } |
| 185 if (desc[0] == '*') { | 175 if (desc[0] == '*') { |
| 186 uint32_t addr; | 176 uint32_t addr; |
| 187 if (GetValue(desc + 1, &addr)) { | 177 if (GetValue(desc + 1, &addr)) { |
| 188 if (Simulator::IsIllegalAddress(addr)) { | 178 if (Simulator::IsIllegalAddress(addr)) { |
| 189 return false; | 179 return false; |
| 190 } | 180 } |
| 191 *value = *(reinterpret_cast<uint32_t*>(addr)); | 181 *value = *(reinterpret_cast<uint32_t*>(addr)); |
| 192 return true; | 182 return true; |
| 193 } | 183 } |
| 194 } | 184 } |
| 195 bool retval = SScanF(desc, "0x%x", value) == 1; | 185 bool retval = SScanF(desc, "0x%x", value) == 1; |
| 196 if (!retval) { | 186 if (!retval) { |
| 197 retval = SScanF(desc, "%x", value) == 1; | 187 retval = SScanF(desc, "%x", value) == 1; |
| 198 } | 188 } |
| 199 return retval; | 189 return retval; |
| 200 } | 190 } |
| 201 | 191 |
| 202 | |
| 203 bool SimulatorDebugger::GetFValue(char* desc, float* value) { | 192 bool SimulatorDebugger::GetFValue(char* desc, float* value) { |
| 204 SRegister sreg = LookupSRegisterByName(desc); | 193 SRegister sreg = LookupSRegisterByName(desc); |
| 205 if (sreg != kNoSRegister) { | 194 if (sreg != kNoSRegister) { |
| 206 *value = sim_->get_sregister(sreg); | 195 *value = sim_->get_sregister(sreg); |
| 207 return true; | 196 return true; |
| 208 } | 197 } |
| 209 if (desc[0] == '*') { | 198 if (desc[0] == '*') { |
| 210 uint32_t addr; | 199 uint32_t addr; |
| 211 if (GetValue(desc + 1, &addr)) { | 200 if (GetValue(desc + 1, &addr)) { |
| 212 if (Simulator::IsIllegalAddress(addr)) { | 201 if (Simulator::IsIllegalAddress(addr)) { |
| 213 return false; | 202 return false; |
| 214 } | 203 } |
| 215 *value = *(reinterpret_cast<float*>(addr)); | 204 *value = *(reinterpret_cast<float*>(addr)); |
| 216 return true; | 205 return true; |
| 217 } | 206 } |
| 218 } | 207 } |
| 219 return false; | 208 return false; |
| 220 } | 209 } |
| 221 | 210 |
| 222 | |
| 223 bool SimulatorDebugger::GetDValue(char* desc, double* value) { | 211 bool SimulatorDebugger::GetDValue(char* desc, double* value) { |
| 224 DRegister dreg = LookupDRegisterByName(desc); | 212 DRegister dreg = LookupDRegisterByName(desc); |
| 225 if (dreg != kNoDRegister) { | 213 if (dreg != kNoDRegister) { |
| 226 *value = sim_->get_dregister(dreg); | 214 *value = sim_->get_dregister(dreg); |
| 227 return true; | 215 return true; |
| 228 } | 216 } |
| 229 if (desc[0] == '*') { | 217 if (desc[0] == '*') { |
| 230 uint32_t addr; | 218 uint32_t addr; |
| 231 if (GetValue(desc + 1, &addr)) { | 219 if (GetValue(desc + 1, &addr)) { |
| 232 if (Simulator::IsIllegalAddress(addr)) { | 220 if (Simulator::IsIllegalAddress(addr)) { |
| 233 return false; | 221 return false; |
| 234 } | 222 } |
| 235 *value = *(reinterpret_cast<double*>(addr)); | 223 *value = *(reinterpret_cast<double*>(addr)); |
| 236 return true; | 224 return true; |
| 237 } | 225 } |
| 238 } | 226 } |
| 239 return false; | 227 return false; |
| 240 } | 228 } |
| 241 | 229 |
| 242 | |
| 243 TokenPosition SimulatorDebugger::GetApproximateTokenIndex(const Code& code, | 230 TokenPosition SimulatorDebugger::GetApproximateTokenIndex(const Code& code, |
| 244 uword pc) { | 231 uword pc) { |
| 245 TokenPosition token_pos = TokenPosition::kNoSource; | 232 TokenPosition token_pos = TokenPosition::kNoSource; |
| 246 uword pc_offset = pc - code.PayloadStart(); | 233 uword pc_offset = pc - code.PayloadStart(); |
| 247 const PcDescriptors& descriptors = | 234 const PcDescriptors& descriptors = |
| 248 PcDescriptors::Handle(code.pc_descriptors()); | 235 PcDescriptors::Handle(code.pc_descriptors()); |
| 249 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind); | 236 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind); |
| 250 while (iter.MoveNext()) { | 237 while (iter.MoveNext()) { |
| 251 if (iter.PcOffset() == pc_offset) { | 238 if (iter.PcOffset() == pc_offset) { |
| 252 return iter.TokenPos(); | 239 return iter.TokenPos(); |
| 253 } else if (!token_pos.IsReal() && (iter.PcOffset() > pc_offset)) { | 240 } else if (!token_pos.IsReal() && (iter.PcOffset() > pc_offset)) { |
| 254 token_pos = iter.TokenPos(); | 241 token_pos = iter.TokenPos(); |
| 255 } | 242 } |
| 256 } | 243 } |
| 257 return token_pos; | 244 return token_pos; |
| 258 } | 245 } |
| 259 | 246 |
| 260 | |
| 261 void SimulatorDebugger::PrintDartFrame(uword pc, | 247 void SimulatorDebugger::PrintDartFrame(uword pc, |
| 262 uword fp, | 248 uword fp, |
| 263 uword sp, | 249 uword sp, |
| 264 const Function& function, | 250 const Function& function, |
| 265 TokenPosition token_pos, | 251 TokenPosition token_pos, |
| 266 bool is_optimized, | 252 bool is_optimized, |
| 267 bool is_inlined) { | 253 bool is_inlined) { |
| 268 const Script& script = Script::Handle(function.script()); | 254 const Script& script = Script::Handle(function.script()); |
| 269 const String& func_name = String::Handle(function.QualifiedScrubbedName()); | 255 const String& func_name = String::Handle(function.QualifiedScrubbedName()); |
| 270 const String& url = String::Handle(script.url()); | 256 const String& url = String::Handle(script.url()); |
| 271 intptr_t line = -1; | 257 intptr_t line = -1; |
| 272 intptr_t column = -1; | 258 intptr_t column = -1; |
| 273 if (token_pos.IsReal()) { | 259 if (token_pos.IsReal()) { |
| 274 script.GetTokenLocation(token_pos, &line, &column); | 260 script.GetTokenLocation(token_pos, &line, &column); |
| 275 } | 261 } |
| 276 OS::Print( | 262 OS::Print( |
| 277 "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")\n", pc, | 263 "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")\n", pc, |
| 278 fp, sp, is_optimized ? (is_inlined ? "inlined " : "optimized ") : "", | 264 fp, sp, is_optimized ? (is_inlined ? "inlined " : "optimized ") : "", |
| 279 func_name.ToCString(), url.ToCString(), line, column); | 265 func_name.ToCString(), url.ToCString(), line, column); |
| 280 } | 266 } |
| 281 | 267 |
| 282 | |
| 283 void SimulatorDebugger::PrintBacktrace() { | 268 void SimulatorDebugger::PrintBacktrace() { |
| 284 StackFrameIterator frames( | 269 StackFrameIterator frames( |
| 285 sim_->get_register(FP), sim_->get_register(SP), sim_->get_pc(), | 270 sim_->get_register(FP), sim_->get_register(SP), sim_->get_pc(), |
| 286 StackFrameIterator::kDontValidateFrames, Thread::Current(), | 271 StackFrameIterator::kDontValidateFrames, Thread::Current(), |
| 287 StackFrameIterator::kNoCrossThreadIteration); | 272 StackFrameIterator::kNoCrossThreadIteration); |
| 288 StackFrame* frame = frames.NextFrame(); | 273 StackFrame* frame = frames.NextFrame(); |
| 289 ASSERT(frame != NULL); | 274 ASSERT(frame != NULL); |
| 290 Function& function = Function::Handle(); | 275 Function& function = Function::Handle(); |
| 291 Function& inlined_function = Function::Handle(); | 276 Function& inlined_function = Function::Handle(); |
| 292 Code& code = Code::Handle(); | 277 Code& code = Code::Handle(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 frame->IsEntryFrame() | 309 frame->IsEntryFrame() |
| 325 ? "entry" | 310 ? "entry" |
| 326 : frame->IsExitFrame() | 311 : frame->IsExitFrame() |
| 327 ? "exit" | 312 ? "exit" |
| 328 : frame->IsStubFrame() ? "stub" : "invalid"); | 313 : frame->IsStubFrame() ? "stub" : "invalid"); |
| 329 } | 314 } |
| 330 frame = frames.NextFrame(); | 315 frame = frames.NextFrame(); |
| 331 } | 316 } |
| 332 } | 317 } |
| 333 | 318 |
| 334 | |
| 335 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { | 319 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { |
| 336 // Check if a breakpoint can be set. If not return without any side-effects. | 320 // Check if a breakpoint can be set. If not return without any side-effects. |
| 337 if (sim_->break_pc_ != NULL) { | 321 if (sim_->break_pc_ != NULL) { |
| 338 return false; | 322 return false; |
| 339 } | 323 } |
| 340 | 324 |
| 341 // Set the breakpoint. | 325 // Set the breakpoint. |
| 342 sim_->break_pc_ = breakpc; | 326 sim_->break_pc_ = breakpc; |
| 343 sim_->break_instr_ = breakpc->InstructionBits(); | 327 sim_->break_instr_ = breakpc->InstructionBits(); |
| 344 // Not setting the breakpoint instruction in the code itself. It will be set | 328 // Not setting the breakpoint instruction in the code itself. It will be set |
| 345 // when the debugger shell continues. | 329 // when the debugger shell continues. |
| 346 return true; | 330 return true; |
| 347 } | 331 } |
| 348 | 332 |
| 349 | |
| 350 bool SimulatorDebugger::DeleteBreakpoint(Instr* breakpc) { | 333 bool SimulatorDebugger::DeleteBreakpoint(Instr* breakpc) { |
| 351 if (sim_->break_pc_ != NULL) { | 334 if (sim_->break_pc_ != NULL) { |
| 352 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); | 335 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); |
| 353 } | 336 } |
| 354 | 337 |
| 355 sim_->break_pc_ = NULL; | 338 sim_->break_pc_ = NULL; |
| 356 sim_->break_instr_ = 0; | 339 sim_->break_instr_ = 0; |
| 357 return true; | 340 return true; |
| 358 } | 341 } |
| 359 | 342 |
| 360 | |
| 361 void SimulatorDebugger::UndoBreakpoints() { | 343 void SimulatorDebugger::UndoBreakpoints() { |
| 362 if (sim_->break_pc_ != NULL) { | 344 if (sim_->break_pc_ != NULL) { |
| 363 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); | 345 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); |
| 364 } | 346 } |
| 365 } | 347 } |
| 366 | 348 |
| 367 | |
| 368 void SimulatorDebugger::RedoBreakpoints() { | 349 void SimulatorDebugger::RedoBreakpoints() { |
| 369 if (sim_->break_pc_ != NULL) { | 350 if (sim_->break_pc_ != NULL) { |
| 370 sim_->break_pc_->SetInstructionBits(Instr::kSimulatorBreakpointInstruction); | 351 sim_->break_pc_->SetInstructionBits(Instr::kSimulatorBreakpointInstruction); |
| 371 } | 352 } |
| 372 } | 353 } |
| 373 | 354 |
| 374 | |
| 375 void SimulatorDebugger::Debug() { | 355 void SimulatorDebugger::Debug() { |
| 376 intptr_t last_pc = -1; | 356 intptr_t last_pc = -1; |
| 377 bool done = false; | 357 bool done = false; |
| 378 | 358 |
| 379 #define COMMAND_SIZE 63 | 359 #define COMMAND_SIZE 63 |
| 380 #define ARG_SIZE 255 | 360 #define ARG_SIZE 255 |
| 381 | 361 |
| 382 #define STR(a) #a | 362 #define STR(a) #a |
| 383 #define XSTR(a) STR(a) | 363 #define XSTR(a) STR(a) |
| 384 | 364 |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 614 // shell when hit. | 594 // shell when hit. |
| 615 RedoBreakpoints(); | 595 RedoBreakpoints(); |
| 616 | 596 |
| 617 #undef COMMAND_SIZE | 597 #undef COMMAND_SIZE |
| 618 #undef ARG_SIZE | 598 #undef ARG_SIZE |
| 619 | 599 |
| 620 #undef STR | 600 #undef STR |
| 621 #undef XSTR | 601 #undef XSTR |
| 622 } | 602 } |
| 623 | 603 |
| 624 | |
| 625 char* SimulatorDebugger::ReadLine(const char* prompt) { | 604 char* SimulatorDebugger::ReadLine(const char* prompt) { |
| 626 char* result = NULL; | 605 char* result = NULL; |
| 627 char line_buf[256]; | 606 char line_buf[256]; |
| 628 intptr_t offset = 0; | 607 intptr_t offset = 0; |
| 629 bool keep_going = true; | 608 bool keep_going = true; |
| 630 OS::Print("%s", prompt); | 609 OS::Print("%s", prompt); |
| 631 while (keep_going) { | 610 while (keep_going) { |
| 632 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) { | 611 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) { |
| 633 // fgets got an error. Just give up. | 612 // fgets got an error. Just give up. |
| 634 if (result != NULL) { | 613 if (result != NULL) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 673 } | 652 } |
| 674 // Copy the newly read line into the result. | 653 // Copy the newly read line into the result. |
| 675 memmove(result + offset, line_buf, len); | 654 memmove(result + offset, line_buf, len); |
| 676 offset += len; | 655 offset += len; |
| 677 } | 656 } |
| 678 ASSERT(result != NULL); | 657 ASSERT(result != NULL); |
| 679 result[offset] = '\0'; | 658 result[offset] = '\0'; |
| 680 return result; | 659 return result; |
| 681 } | 660 } |
| 682 | 661 |
| 683 | |
| 684 // Synchronization primitives support. | 662 // Synchronization primitives support. |
| 685 Mutex* Simulator::exclusive_access_lock_ = NULL; | 663 Mutex* Simulator::exclusive_access_lock_ = NULL; |
| 686 Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags] = { | 664 Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags] = { |
| 687 {NULL, 0}}; | 665 {NULL, 0}}; |
| 688 int Simulator::next_address_tag_ = 0; | 666 int Simulator::next_address_tag_ = 0; |
| 689 | 667 |
| 690 | |
| 691 void Simulator::InitOnce() { | 668 void Simulator::InitOnce() { |
| 692 // Setup exclusive access state lock. | 669 // Setup exclusive access state lock. |
| 693 exclusive_access_lock_ = new Mutex(); | 670 exclusive_access_lock_ = new Mutex(); |
| 694 } | 671 } |
| 695 | 672 |
| 696 | |
| 697 Simulator::Simulator() { | 673 Simulator::Simulator() { |
| 698 // Setup simulator support first. Some of this information is needed to | 674 // Setup simulator support first. Some of this information is needed to |
| 699 // setup the architecture state. | 675 // setup the architecture state. |
| 700 // We allocate the stack here, the size is computed as the sum of | 676 // We allocate the stack here, the size is computed as the sum of |
| 701 // the size specified by the user and the buffer space needed for | 677 // the size specified by the user and the buffer space needed for |
| 702 // handling stack overflow exceptions. To be safe in potential | 678 // handling stack overflow exceptions. To be safe in potential |
| 703 // stack underflows we also add some underflow buffer space. | 679 // stack underflows we also add some underflow buffer space. |
| 704 stack_ = | 680 stack_ = |
| 705 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer + | 681 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer + |
| 706 kSimulatorStackUnderflowSize)]; | 682 kSimulatorStackUnderflowSize)]; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 ASSERT(2 * kNumberOfDRegisters >= kNumberOfSRegisters); | 714 ASSERT(2 * kNumberOfDRegisters >= kNumberOfSRegisters); |
| 739 for (int i = 0; i < kNumberOfSRegisters; i++) { | 715 for (int i = 0; i < kNumberOfSRegisters; i++) { |
| 740 ASSERT(sregisters_[i] == 0.0); | 716 ASSERT(sregisters_[i] == 0.0); |
| 741 } | 717 } |
| 742 fp_n_flag_ = false; | 718 fp_n_flag_ = false; |
| 743 fp_z_flag_ = false; | 719 fp_z_flag_ = false; |
| 744 fp_c_flag_ = false; | 720 fp_c_flag_ = false; |
| 745 fp_v_flag_ = false; | 721 fp_v_flag_ = false; |
| 746 } | 722 } |
| 747 | 723 |
| 748 | |
| 749 Simulator::~Simulator() { | 724 Simulator::~Simulator() { |
| 750 delete[] stack_; | 725 delete[] stack_; |
| 751 Isolate* isolate = Isolate::Current(); | 726 Isolate* isolate = Isolate::Current(); |
| 752 if (isolate != NULL) { | 727 if (isolate != NULL) { |
| 753 isolate->set_simulator(NULL); | 728 isolate->set_simulator(NULL); |
| 754 } | 729 } |
| 755 } | 730 } |
| 756 | 731 |
| 757 | |
| 758 // When the generated code calls an external reference we need to catch that in | 732 // When the generated code calls an external reference we need to catch that in |
| 759 // the simulator. The external reference will be a function compiled for the | 733 // the simulator. The external reference will be a function compiled for the |
| 760 // host architecture. We need to call that function instead of trying to | 734 // host architecture. We need to call that function instead of trying to |
| 761 // execute it with the simulator. We do that by redirecting the external | 735 // execute it with the simulator. We do that by redirecting the external |
| 762 // reference to a svc (supervisor call) instruction that is handled by | 736 // reference to a svc (supervisor call) instruction that is handled by |
| 763 // the simulator. We write the original destination of the jump just at a known | 737 // the simulator. We write the original destination of the jump just at a known |
| 764 // offset from the svc instruction so the simulator knows what to call. | 738 // offset from the svc instruction so the simulator knows what to call. |
| 765 class Redirection { | 739 class Redirection { |
| 766 public: | 740 public: |
| 767 uword address_of_svc_instruction() { | 741 uword address_of_svc_instruction() { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 822 } | 796 } |
| 823 | 797 |
| 824 uword external_function_; | 798 uword external_function_; |
| 825 Simulator::CallKind call_kind_; | 799 Simulator::CallKind call_kind_; |
| 826 int argument_count_; | 800 int argument_count_; |
| 827 uint32_t svc_instruction_; | 801 uint32_t svc_instruction_; |
| 828 Redirection* next_; | 802 Redirection* next_; |
| 829 static Redirection* list_; | 803 static Redirection* list_; |
| 830 }; | 804 }; |
| 831 | 805 |
| 832 | |
| 833 Redirection* Redirection::list_ = NULL; | 806 Redirection* Redirection::list_ = NULL; |
| 834 | 807 |
| 835 | |
| 836 uword Simulator::RedirectExternalReference(uword function, | 808 uword Simulator::RedirectExternalReference(uword function, |
| 837 CallKind call_kind, | 809 CallKind call_kind, |
| 838 int argument_count) { | 810 int argument_count) { |
| 839 Redirection* redirection = | 811 Redirection* redirection = |
| 840 Redirection::Get(function, call_kind, argument_count); | 812 Redirection::Get(function, call_kind, argument_count); |
| 841 return redirection->address_of_svc_instruction(); | 813 return redirection->address_of_svc_instruction(); |
| 842 } | 814 } |
| 843 | 815 |
| 844 | |
| 845 uword Simulator::FunctionForRedirect(uword redirect) { | 816 uword Simulator::FunctionForRedirect(uword redirect) { |
| 846 return Redirection::FunctionForRedirect(redirect); | 817 return Redirection::FunctionForRedirect(redirect); |
| 847 } | 818 } |
| 848 | 819 |
| 849 | |
| 850 // Get the active Simulator for the current isolate. | 820 // Get the active Simulator for the current isolate. |
| 851 Simulator* Simulator::Current() { | 821 Simulator* Simulator::Current() { |
| 852 Simulator* simulator = Isolate::Current()->simulator(); | 822 Simulator* simulator = Isolate::Current()->simulator(); |
| 853 if (simulator == NULL) { | 823 if (simulator == NULL) { |
| 854 simulator = new Simulator(); | 824 simulator = new Simulator(); |
| 855 Isolate::Current()->set_simulator(simulator); | 825 Isolate::Current()->set_simulator(simulator); |
| 856 } | 826 } |
| 857 return simulator; | 827 return simulator; |
| 858 } | 828 } |
| 859 | 829 |
| 860 | |
| 861 // Sets the register in the architecture state. It will also deal with updating | 830 // Sets the register in the architecture state. It will also deal with updating |
| 862 // Simulator internal state for special registers such as PC. | 831 // Simulator internal state for special registers such as PC. |
| 863 void Simulator::set_register(Register reg, int32_t value) { | 832 void Simulator::set_register(Register reg, int32_t value) { |
| 864 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 833 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
| 865 if (reg == PC) { | 834 if (reg == PC) { |
| 866 pc_modified_ = true; | 835 pc_modified_ = true; |
| 867 } | 836 } |
| 868 registers_[reg] = value; | 837 registers_[reg] = value; |
| 869 } | 838 } |
| 870 | 839 |
| 871 | |
| 872 // Get the register from the architecture state. This function does handle | 840 // Get the register from the architecture state. This function does handle |
| 873 // the special case of accessing the PC register. | 841 // the special case of accessing the PC register. |
| 874 int32_t Simulator::get_register(Register reg) const { | 842 int32_t Simulator::get_register(Register reg) const { |
| 875 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); | 843 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); |
| 876 return registers_[reg] + ((reg == PC) ? Instr::kPCReadOffset : 0); | 844 return registers_[reg] + ((reg == PC) ? Instr::kPCReadOffset : 0); |
| 877 } | 845 } |
| 878 | 846 |
| 879 | |
| 880 // Raw access to the PC register. | 847 // Raw access to the PC register. |
| 881 void Simulator::set_pc(int32_t value) { | 848 void Simulator::set_pc(int32_t value) { |
| 882 pc_modified_ = true; | 849 pc_modified_ = true; |
| 883 registers_[PC] = value; | 850 registers_[PC] = value; |
| 884 } | 851 } |
| 885 | 852 |
| 886 | |
| 887 // Raw access to the PC register without the special adjustment when reading. | 853 // Raw access to the PC register without the special adjustment when reading. |
| 888 int32_t Simulator::get_pc() const { | 854 int32_t Simulator::get_pc() const { |
| 889 return registers_[PC]; | 855 return registers_[PC]; |
| 890 } | 856 } |
| 891 | 857 |
| 892 | |
| 893 // Accessors for VFP register state. | 858 // Accessors for VFP register state. |
| 894 void Simulator::set_sregister(SRegister reg, float value) { | 859 void Simulator::set_sregister(SRegister reg, float value) { |
| 895 ASSERT(TargetCPUFeatures::vfp_supported()); | 860 ASSERT(TargetCPUFeatures::vfp_supported()); |
| 896 ASSERT((reg >= 0) && (reg < kNumberOfSRegisters)); | 861 ASSERT((reg >= 0) && (reg < kNumberOfSRegisters)); |
| 897 sregisters_[reg] = bit_cast<int32_t, float>(value); | 862 sregisters_[reg] = bit_cast<int32_t, float>(value); |
| 898 } | 863 } |
| 899 | 864 |
| 900 | |
| 901 float Simulator::get_sregister(SRegister reg) const { | 865 float Simulator::get_sregister(SRegister reg) const { |
| 902 ASSERT(TargetCPUFeatures::vfp_supported()); | 866 ASSERT(TargetCPUFeatures::vfp_supported()); |
| 903 ASSERT((reg >= 0) && (reg < kNumberOfSRegisters)); | 867 ASSERT((reg >= 0) && (reg < kNumberOfSRegisters)); |
| 904 return bit_cast<float, int32_t>(sregisters_[reg]); | 868 return bit_cast<float, int32_t>(sregisters_[reg]); |
| 905 } | 869 } |
| 906 | 870 |
| 907 | |
| 908 void Simulator::set_dregister(DRegister reg, double value) { | 871 void Simulator::set_dregister(DRegister reg, double value) { |
| 909 ASSERT(TargetCPUFeatures::vfp_supported()); | 872 ASSERT(TargetCPUFeatures::vfp_supported()); |
| 910 ASSERT((reg >= 0) && (reg < kNumberOfDRegisters)); | 873 ASSERT((reg >= 0) && (reg < kNumberOfDRegisters)); |
| 911 dregisters_[reg] = bit_cast<int64_t, double>(value); | 874 dregisters_[reg] = bit_cast<int64_t, double>(value); |
| 912 } | 875 } |
| 913 | 876 |
| 914 | |
| 915 double Simulator::get_dregister(DRegister reg) const { | 877 double Simulator::get_dregister(DRegister reg) const { |
| 916 ASSERT(TargetCPUFeatures::vfp_supported()); | 878 ASSERT(TargetCPUFeatures::vfp_supported()); |
| 917 ASSERT((reg >= 0) && (reg < kNumberOfDRegisters)); | 879 ASSERT((reg >= 0) && (reg < kNumberOfDRegisters)); |
| 918 return bit_cast<double, int64_t>(dregisters_[reg]); | 880 return bit_cast<double, int64_t>(dregisters_[reg]); |
| 919 } | 881 } |
| 920 | 882 |
| 921 | |
| 922 void Simulator::set_qregister(QRegister reg, const simd_value_t& value) { | 883 void Simulator::set_qregister(QRegister reg, const simd_value_t& value) { |
| 923 ASSERT(TargetCPUFeatures::neon_supported()); | 884 ASSERT(TargetCPUFeatures::neon_supported()); |
| 924 ASSERT((reg >= 0) && (reg < kNumberOfQRegisters)); | 885 ASSERT((reg >= 0) && (reg < kNumberOfQRegisters)); |
| 925 qregisters_[reg].data_[0] = value.data_[0]; | 886 qregisters_[reg].data_[0] = value.data_[0]; |
| 926 qregisters_[reg].data_[1] = value.data_[1]; | 887 qregisters_[reg].data_[1] = value.data_[1]; |
| 927 qregisters_[reg].data_[2] = value.data_[2]; | 888 qregisters_[reg].data_[2] = value.data_[2]; |
| 928 qregisters_[reg].data_[3] = value.data_[3]; | 889 qregisters_[reg].data_[3] = value.data_[3]; |
| 929 } | 890 } |
| 930 | 891 |
| 931 | |
| 932 void Simulator::get_qregister(QRegister reg, simd_value_t* value) const { | 892 void Simulator::get_qregister(QRegister reg, simd_value_t* value) const { |
| 933 ASSERT(TargetCPUFeatures::neon_supported()); | 893 ASSERT(TargetCPUFeatures::neon_supported()); |
| 934 // TODO(zra): Replace this test with an assert after we support | 894 // TODO(zra): Replace this test with an assert after we support |
| 935 // 16 Q registers. | 895 // 16 Q registers. |
| 936 if ((reg >= 0) && (reg < kNumberOfQRegisters)) { | 896 if ((reg >= 0) && (reg < kNumberOfQRegisters)) { |
| 937 *value = qregisters_[reg]; | 897 *value = qregisters_[reg]; |
| 938 } | 898 } |
| 939 } | 899 } |
| 940 | 900 |
| 941 | |
| 942 void Simulator::set_sregister_bits(SRegister reg, int32_t value) { | 901 void Simulator::set_sregister_bits(SRegister reg, int32_t value) { |
| 943 ASSERT(TargetCPUFeatures::vfp_supported()); | 902 ASSERT(TargetCPUFeatures::vfp_supported()); |
| 944 ASSERT((reg >= 0) && (reg < kNumberOfSRegisters)); | 903 ASSERT((reg >= 0) && (reg < kNumberOfSRegisters)); |
| 945 sregisters_[reg] = value; | 904 sregisters_[reg] = value; |
| 946 } | 905 } |
| 947 | 906 |
| 948 | |
| 949 int32_t Simulator::get_sregister_bits(SRegister reg) const { | 907 int32_t Simulator::get_sregister_bits(SRegister reg) const { |
| 950 ASSERT(TargetCPUFeatures::vfp_supported()); | 908 ASSERT(TargetCPUFeatures::vfp_supported()); |
| 951 ASSERT((reg >= 0) && (reg < kNumberOfSRegisters)); | 909 ASSERT((reg >= 0) && (reg < kNumberOfSRegisters)); |
| 952 return sregisters_[reg]; | 910 return sregisters_[reg]; |
| 953 } | 911 } |
| 954 | 912 |
| 955 | |
| 956 void Simulator::set_dregister_bits(DRegister reg, int64_t value) { | 913 void Simulator::set_dregister_bits(DRegister reg, int64_t value) { |
| 957 ASSERT(TargetCPUFeatures::vfp_supported()); | 914 ASSERT(TargetCPUFeatures::vfp_supported()); |
| 958 ASSERT((reg >= 0) && (reg < kNumberOfDRegisters)); | 915 ASSERT((reg >= 0) && (reg < kNumberOfDRegisters)); |
| 959 dregisters_[reg] = value; | 916 dregisters_[reg] = value; |
| 960 } | 917 } |
| 961 | 918 |
| 962 | |
| 963 int64_t Simulator::get_dregister_bits(DRegister reg) const { | 919 int64_t Simulator::get_dregister_bits(DRegister reg) const { |
| 964 ASSERT(TargetCPUFeatures::vfp_supported()); | 920 ASSERT(TargetCPUFeatures::vfp_supported()); |
| 965 ASSERT((reg >= 0) && (reg < kNumberOfDRegisters)); | 921 ASSERT((reg >= 0) && (reg < kNumberOfDRegisters)); |
| 966 return dregisters_[reg]; | 922 return dregisters_[reg]; |
| 967 } | 923 } |
| 968 | 924 |
| 969 | |
| 970 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { | 925 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { |
| 971 uword fault_pc = get_pc(); | 926 uword fault_pc = get_pc(); |
| 972 // The debugger will not be able to single step past this instruction, but | 927 // The debugger will not be able to single step past this instruction, but |
| 973 // it will be possible to disassemble the code and inspect registers. | 928 // it will be possible to disassemble the code and inspect registers. |
| 974 char buffer[128]; | 929 char buffer[128]; |
| 975 snprintf(buffer, sizeof(buffer), | 930 snprintf(buffer, sizeof(buffer), |
| 976 "illegal memory access at 0x%" Px ", pc=0x%" Px "\n", addr, | 931 "illegal memory access at 0x%" Px ", pc=0x%" Px "\n", addr, |
| 977 fault_pc); | 932 fault_pc); |
| 978 SimulatorDebugger dbg(this); | 933 SimulatorDebugger dbg(this); |
| 979 dbg.Stop(instr, buffer); | 934 dbg.Stop(instr, buffer); |
| 980 // The debugger will return control in non-interactive mode. | 935 // The debugger will return control in non-interactive mode. |
| 981 FATAL("Cannot continue execution after illegal memory access."); | 936 FATAL("Cannot continue execution after illegal memory access."); |
| 982 } | 937 } |
| 983 | 938 |
| 984 | |
| 985 // Processor versions prior to ARMv7 could not do unaligned reads and writes. | 939 // Processor versions prior to ARMv7 could not do unaligned reads and writes. |
| 986 // On some ARM platforms an interrupt is caused. On others it does a funky | 940 // On some ARM platforms an interrupt is caused. On others it does a funky |
| 987 // rotation thing. However, from version v7, unaligned access is supported. | 941 // rotation thing. However, from version v7, unaligned access is supported. |
| 988 // Note that simulator runs have the runtime system running directly on the host | 942 // Note that simulator runs have the runtime system running directly on the host |
| 989 // system and only generated code is executed in the simulator. Since the host | 943 // system and only generated code is executed in the simulator. Since the host |
| 990 // is typically IA32 we will get the correct ARMv7-like behaviour on unaligned | 944 // is typically IA32 we will get the correct ARMv7-like behaviour on unaligned |
| 991 // accesses, but we should actually not generate code accessing unaligned data, | 945 // accesses, but we should actually not generate code accessing unaligned data, |
| 992 // so we still want to know and abort if we encounter such code. | 946 // so we still want to know and abort if we encounter such code. |
| 993 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { | 947 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { |
| 994 // The debugger will not be able to single step past this instruction, but | 948 // The debugger will not be able to single step past this instruction, but |
| 995 // it will be possible to disassemble the code and inspect registers. | 949 // it will be possible to disassemble the code and inspect registers. |
| 996 char buffer[64]; | 950 char buffer[64]; |
| 997 snprintf(buffer, sizeof(buffer), "unaligned %s at 0x%" Px ", pc=%p\n", msg, | 951 snprintf(buffer, sizeof(buffer), "unaligned %s at 0x%" Px ", pc=%p\n", msg, |
| 998 addr, instr); | 952 addr, instr); |
| 999 SimulatorDebugger dbg(this); | 953 SimulatorDebugger dbg(this); |
| 1000 dbg.Stop(instr, buffer); | 954 dbg.Stop(instr, buffer); |
| 1001 // The debugger will return control in non-interactive mode. | 955 // The debugger will return control in non-interactive mode. |
| 1002 FATAL("Cannot continue execution after unaligned access."); | 956 FATAL("Cannot continue execution after unaligned access."); |
| 1003 } | 957 } |
| 1004 | 958 |
| 1005 | |
| 1006 void Simulator::UnimplementedInstruction(Instr* instr) { | 959 void Simulator::UnimplementedInstruction(Instr* instr) { |
| 1007 char buffer[64]; | 960 char buffer[64]; |
| 1008 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); | 961 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); |
| 1009 SimulatorDebugger dbg(this); | 962 SimulatorDebugger dbg(this); |
| 1010 dbg.Stop(instr, buffer); | 963 dbg.Stop(instr, buffer); |
| 1011 FATAL("Cannot continue execution after unimplemented instruction."); | 964 FATAL("Cannot continue execution after unimplemented instruction."); |
| 1012 } | 965 } |
| 1013 | 966 |
| 1014 | |
| 1015 intptr_t Simulator::ReadW(uword addr, Instr* instr) { | 967 intptr_t Simulator::ReadW(uword addr, Instr* instr) { |
| 1016 if ((addr & 3) == 0) { | 968 if ((addr & 3) == 0) { |
| 1017 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 969 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
| 1018 return *ptr; | 970 return *ptr; |
| 1019 } | 971 } |
| 1020 UnalignedAccess("read", addr, instr); | 972 UnalignedAccess("read", addr, instr); |
| 1021 return 0; | 973 return 0; |
| 1022 } | 974 } |
| 1023 | 975 |
| 1024 | |
| 1025 void Simulator::WriteW(uword addr, intptr_t value, Instr* instr) { | 976 void Simulator::WriteW(uword addr, intptr_t value, Instr* instr) { |
| 1026 if ((addr & 3) == 0) { | 977 if ((addr & 3) == 0) { |
| 1027 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 978 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
| 1028 *ptr = value; | 979 *ptr = value; |
| 1029 return; | 980 return; |
| 1030 } | 981 } |
| 1031 UnalignedAccess("write", addr, instr); | 982 UnalignedAccess("write", addr, instr); |
| 1032 } | 983 } |
| 1033 | 984 |
| 1034 | |
| 1035 uint16_t Simulator::ReadHU(uword addr, Instr* instr) { | 985 uint16_t Simulator::ReadHU(uword addr, Instr* instr) { |
| 1036 if ((addr & 1) == 0) { | 986 if ((addr & 1) == 0) { |
| 1037 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); | 987 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); |
| 1038 return *ptr; | 988 return *ptr; |
| 1039 } | 989 } |
| 1040 UnalignedAccess("unsigned halfword read", addr, instr); | 990 UnalignedAccess("unsigned halfword read", addr, instr); |
| 1041 return 0; | 991 return 0; |
| 1042 } | 992 } |
| 1043 | 993 |
| 1044 | |
| 1045 int16_t Simulator::ReadH(uword addr, Instr* instr) { | 994 int16_t Simulator::ReadH(uword addr, Instr* instr) { |
| 1046 if ((addr & 1) == 0) { | 995 if ((addr & 1) == 0) { |
| 1047 int16_t* ptr = reinterpret_cast<int16_t*>(addr); | 996 int16_t* ptr = reinterpret_cast<int16_t*>(addr); |
| 1048 return *ptr; | 997 return *ptr; |
| 1049 } | 998 } |
| 1050 UnalignedAccess("signed halfword read", addr, instr); | 999 UnalignedAccess("signed halfword read", addr, instr); |
| 1051 return 0; | 1000 return 0; |
| 1052 } | 1001 } |
| 1053 | 1002 |
| 1054 | |
| 1055 void Simulator::WriteH(uword addr, uint16_t value, Instr* instr) { | 1003 void Simulator::WriteH(uword addr, uint16_t value, Instr* instr) { |
| 1056 if ((addr & 1) == 0) { | 1004 if ((addr & 1) == 0) { |
| 1057 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); | 1005 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); |
| 1058 *ptr = value; | 1006 *ptr = value; |
| 1059 return; | 1007 return; |
| 1060 } | 1008 } |
| 1061 UnalignedAccess("halfword write", addr, instr); | 1009 UnalignedAccess("halfword write", addr, instr); |
| 1062 } | 1010 } |
| 1063 | 1011 |
| 1064 | |
| 1065 uint8_t Simulator::ReadBU(uword addr) { | 1012 uint8_t Simulator::ReadBU(uword addr) { |
| 1066 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); | 1013 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); |
| 1067 return *ptr; | 1014 return *ptr; |
| 1068 } | 1015 } |
| 1069 | 1016 |
| 1070 | |
| 1071 int8_t Simulator::ReadB(uword addr) { | 1017 int8_t Simulator::ReadB(uword addr) { |
| 1072 int8_t* ptr = reinterpret_cast<int8_t*>(addr); | 1018 int8_t* ptr = reinterpret_cast<int8_t*>(addr); |
| 1073 return *ptr; | 1019 return *ptr; |
| 1074 } | 1020 } |
| 1075 | 1021 |
| 1076 | |
| 1077 void Simulator::WriteB(uword addr, uint8_t value) { | 1022 void Simulator::WriteB(uword addr, uint8_t value) { |
| 1078 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); | 1023 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); |
| 1079 *ptr = value; | 1024 *ptr = value; |
| 1080 } | 1025 } |
| 1081 | 1026 |
| 1082 | |
| 1083 // Synchronization primitives support. | 1027 // Synchronization primitives support. |
| 1084 void Simulator::SetExclusiveAccess(uword addr) { | 1028 void Simulator::SetExclusiveAccess(uword addr) { |
| 1085 Thread* thread = Thread::Current(); | 1029 Thread* thread = Thread::Current(); |
| 1086 ASSERT(thread != NULL); | 1030 ASSERT(thread != NULL); |
| 1087 DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread()); | 1031 DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread()); |
| 1088 int i = 0; | 1032 int i = 0; |
| 1089 // Find an entry for this thread in the exclusive access state. | 1033 // Find an entry for this thread in the exclusive access state. |
| 1090 while ((i < kNumAddressTags) && | 1034 while ((i < kNumAddressTags) && |
| 1091 (exclusive_access_state_[i].thread != thread)) { | 1035 (exclusive_access_state_[i].thread != thread)) { |
| 1092 i++; | 1036 i++; |
| 1093 } | 1037 } |
| 1094 // Round-robin replacement of previously used entries. | 1038 // Round-robin replacement of previously used entries. |
| 1095 if (i == kNumAddressTags) { | 1039 if (i == kNumAddressTags) { |
| 1096 i = next_address_tag_; | 1040 i = next_address_tag_; |
| 1097 if (++next_address_tag_ == kNumAddressTags) { | 1041 if (++next_address_tag_ == kNumAddressTags) { |
| 1098 next_address_tag_ = 0; | 1042 next_address_tag_ = 0; |
| 1099 } | 1043 } |
| 1100 exclusive_access_state_[i].thread = thread; | 1044 exclusive_access_state_[i].thread = thread; |
| 1101 } | 1045 } |
| 1102 // Remember the address being reserved. | 1046 // Remember the address being reserved. |
| 1103 exclusive_access_state_[i].addr = addr; | 1047 exclusive_access_state_[i].addr = addr; |
| 1104 } | 1048 } |
| 1105 | 1049 |
| 1106 | |
| 1107 bool Simulator::HasExclusiveAccessAndOpen(uword addr) { | 1050 bool Simulator::HasExclusiveAccessAndOpen(uword addr) { |
| 1108 Thread* thread = Thread::Current(); | 1051 Thread* thread = Thread::Current(); |
| 1109 ASSERT(thread != NULL); | 1052 ASSERT(thread != NULL); |
| 1110 ASSERT(addr != 0); | 1053 ASSERT(addr != 0); |
| 1111 DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread()); | 1054 DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread()); |
| 1112 bool result = false; | 1055 bool result = false; |
| 1113 for (int i = 0; i < kNumAddressTags; i++) { | 1056 for (int i = 0; i < kNumAddressTags; i++) { |
| 1114 if (exclusive_access_state_[i].thread == thread) { | 1057 if (exclusive_access_state_[i].thread == thread) { |
| 1115 // Check whether the current thread's address reservation matches. | 1058 // Check whether the current thread's address reservation matches. |
| 1116 if (exclusive_access_state_[i].addr == addr) { | 1059 if (exclusive_access_state_[i].addr == addr) { |
| 1117 result = true; | 1060 result = true; |
| 1118 } | 1061 } |
| 1119 exclusive_access_state_[i].addr = 0; | 1062 exclusive_access_state_[i].addr = 0; |
| 1120 } else if (exclusive_access_state_[i].addr == addr) { | 1063 } else if (exclusive_access_state_[i].addr == addr) { |
| 1121 // Other threads with matching address lose their reservations. | 1064 // Other threads with matching address lose their reservations. |
| 1122 exclusive_access_state_[i].addr = 0; | 1065 exclusive_access_state_[i].addr = 0; |
| 1123 } | 1066 } |
| 1124 } | 1067 } |
| 1125 return result; | 1068 return result; |
| 1126 } | 1069 } |
| 1127 | 1070 |
| 1128 | |
| 1129 void Simulator::ClearExclusive() { | 1071 void Simulator::ClearExclusive() { |
| 1130 MutexLocker ml(exclusive_access_lock_); | 1072 MutexLocker ml(exclusive_access_lock_); |
| 1131 // Remove the reservation for this thread. | 1073 // Remove the reservation for this thread. |
| 1132 SetExclusiveAccess(0); | 1074 SetExclusiveAccess(0); |
| 1133 } | 1075 } |
| 1134 | 1076 |
| 1135 | |
| 1136 intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) { | 1077 intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) { |
| 1137 MutexLocker ml(exclusive_access_lock_); | 1078 MutexLocker ml(exclusive_access_lock_); |
| 1138 SetExclusiveAccess(addr); | 1079 SetExclusiveAccess(addr); |
| 1139 return ReadW(addr, instr); | 1080 return ReadW(addr, instr); |
| 1140 } | 1081 } |
| 1141 | 1082 |
| 1142 | |
| 1143 intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) { | 1083 intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) { |
| 1144 MutexLocker ml(exclusive_access_lock_); | 1084 MutexLocker ml(exclusive_access_lock_); |
| 1145 bool write_allowed = HasExclusiveAccessAndOpen(addr); | 1085 bool write_allowed = HasExclusiveAccessAndOpen(addr); |
| 1146 if (write_allowed) { | 1086 if (write_allowed) { |
| 1147 WriteW(addr, value, instr); | 1087 WriteW(addr, value, instr); |
| 1148 return 0; // Success. | 1088 return 0; // Success. |
| 1149 } | 1089 } |
| 1150 return 1; // Failure. | 1090 return 1; // Failure. |
| 1151 } | 1091 } |
| 1152 | 1092 |
| 1153 | |
| 1154 uword Simulator::CompareExchange(uword* address, | 1093 uword Simulator::CompareExchange(uword* address, |
| 1155 uword compare_value, | 1094 uword compare_value, |
| 1156 uword new_value) { | 1095 uword new_value) { |
| 1157 MutexLocker ml(exclusive_access_lock_); | 1096 MutexLocker ml(exclusive_access_lock_); |
| 1158 // We do not get a reservation as it would be guaranteed to be found when | 1097 // We do not get a reservation as it would be guaranteed to be found when |
| 1159 // writing below. No other thread is able to make a reservation while we | 1098 // writing below. No other thread is able to make a reservation while we |
| 1160 // hold the lock. | 1099 // hold the lock. |
| 1161 uword value = *address; | 1100 uword value = *address; |
| 1162 if (value == compare_value) { | 1101 if (value == compare_value) { |
| 1163 *address = new_value; | 1102 *address = new_value; |
| 1164 // Same effect on exclusive access state as a successful STREX. | 1103 // Same effect on exclusive access state as a successful STREX. |
| 1165 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address)); | 1104 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address)); |
| 1166 } else { | 1105 } else { |
| 1167 // Same effect on exclusive access state as an LDREX. | 1106 // Same effect on exclusive access state as an LDREX. |
| 1168 SetExclusiveAccess(reinterpret_cast<uword>(address)); | 1107 SetExclusiveAccess(reinterpret_cast<uword>(address)); |
| 1169 } | 1108 } |
| 1170 return value; | 1109 return value; |
| 1171 } | 1110 } |
| 1172 | 1111 |
| 1173 | |
| 1174 uint32_t Simulator::CompareExchangeUint32(uint32_t* address, | 1112 uint32_t Simulator::CompareExchangeUint32(uint32_t* address, |
| 1175 uint32_t compare_value, | 1113 uint32_t compare_value, |
| 1176 uint32_t new_value) { | 1114 uint32_t new_value) { |
| 1177 COMPILE_ASSERT(sizeof(uword) == sizeof(uint32_t)); | 1115 COMPILE_ASSERT(sizeof(uword) == sizeof(uint32_t)); |
| 1178 return CompareExchange(reinterpret_cast<uword*>(address), | 1116 return CompareExchange(reinterpret_cast<uword*>(address), |
| 1179 static_cast<uword>(compare_value), | 1117 static_cast<uword>(compare_value), |
| 1180 static_cast<uword>(new_value)); | 1118 static_cast<uword>(new_value)); |
| 1181 } | 1119 } |
| 1182 | 1120 |
| 1183 | |
| 1184 // Returns the top of the stack area to enable checking for stack pointer | 1121 // Returns the top of the stack area to enable checking for stack pointer |
| 1185 // validity. | 1122 // validity. |
| 1186 uword Simulator::StackTop() const { | 1123 uword Simulator::StackTop() const { |
| 1187 // To be safe in potential stack underflows we leave some buffer above and | 1124 // To be safe in potential stack underflows we leave some buffer above and |
| 1188 // set the stack top. | 1125 // set the stack top. |
| 1189 return StackBase() + | 1126 return StackBase() + |
| 1190 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); | 1127 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); |
| 1191 } | 1128 } |
| 1192 | 1129 |
| 1193 | |
| 1194 bool Simulator::IsTracingExecution() const { | 1130 bool Simulator::IsTracingExecution() const { |
| 1195 return icount_ > FLAG_trace_sim_after; | 1131 return icount_ > FLAG_trace_sim_after; |
| 1196 } | 1132 } |
| 1197 | 1133 |
| 1198 | |
| 1199 // Unsupported instructions use Format to print an error and stop execution. | 1134 // Unsupported instructions use Format to print an error and stop execution. |
| 1200 void Simulator::Format(Instr* instr, const char* format) { | 1135 void Simulator::Format(Instr* instr, const char* format) { |
| 1201 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", instr, | 1136 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", instr, |
| 1202 format); | 1137 format); |
| 1203 UNIMPLEMENTED(); | 1138 UNIMPLEMENTED(); |
| 1204 } | 1139 } |
| 1205 | 1140 |
| 1206 | |
| 1207 // Checks if the current instruction should be executed based on its | 1141 // Checks if the current instruction should be executed based on its |
| 1208 // condition bits. | 1142 // condition bits. |
| 1209 bool Simulator::ConditionallyExecute(Instr* instr) { | 1143 bool Simulator::ConditionallyExecute(Instr* instr) { |
| 1210 switch (instr->ConditionField()) { | 1144 switch (instr->ConditionField()) { |
| 1211 case EQ: | 1145 case EQ: |
| 1212 return z_flag_; | 1146 return z_flag_; |
| 1213 case NE: | 1147 case NE: |
| 1214 return !z_flag_; | 1148 return !z_flag_; |
| 1215 case CS: | 1149 case CS: |
| 1216 return c_flag_; | 1150 return c_flag_; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1237 case LE: | 1171 case LE: |
| 1238 return z_flag_ || (n_flag_ != v_flag_); | 1172 return z_flag_ || (n_flag_ != v_flag_); |
| 1239 case AL: | 1173 case AL: |
| 1240 return true; | 1174 return true; |
| 1241 default: | 1175 default: |
| 1242 UNREACHABLE(); | 1176 UNREACHABLE(); |
| 1243 } | 1177 } |
| 1244 return false; | 1178 return false; |
| 1245 } | 1179 } |
| 1246 | 1180 |
| 1247 | |
| 1248 // Calculate and set the Negative and Zero flags. | 1181 // Calculate and set the Negative and Zero flags. |
| 1249 void Simulator::SetNZFlags(int32_t val) { | 1182 void Simulator::SetNZFlags(int32_t val) { |
| 1250 n_flag_ = (val < 0); | 1183 n_flag_ = (val < 0); |
| 1251 z_flag_ = (val == 0); | 1184 z_flag_ = (val == 0); |
| 1252 } | 1185 } |
| 1253 | 1186 |
| 1254 | |
| 1255 // Set the Carry flag. | 1187 // Set the Carry flag. |
| 1256 void Simulator::SetCFlag(bool val) { | 1188 void Simulator::SetCFlag(bool val) { |
| 1257 c_flag_ = val; | 1189 c_flag_ = val; |
| 1258 } | 1190 } |
| 1259 | 1191 |
| 1260 | |
| 1261 // Set the oVerflow flag. | 1192 // Set the oVerflow flag. |
| 1262 void Simulator::SetVFlag(bool val) { | 1193 void Simulator::SetVFlag(bool val) { |
| 1263 v_flag_ = val; | 1194 v_flag_ = val; |
| 1264 } | 1195 } |
| 1265 | 1196 |
| 1266 | |
| 1267 // Calculate C flag value for additions (and subtractions with adjusted args). | 1197 // Calculate C flag value for additions (and subtractions with adjusted args). |
| 1268 bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) { | 1198 bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) { |
| 1269 uint64_t uleft = static_cast<uint32_t>(left); | 1199 uint64_t uleft = static_cast<uint32_t>(left); |
| 1270 uint64_t uright = static_cast<uint32_t>(right); | 1200 uint64_t uright = static_cast<uint32_t>(right); |
| 1271 uint64_t ucarry = static_cast<uint32_t>(carry); | 1201 uint64_t ucarry = static_cast<uint32_t>(carry); |
| 1272 return ((uleft + uright + ucarry) >> 32) != 0; | 1202 return ((uleft + uright + ucarry) >> 32) != 0; |
| 1273 } | 1203 } |
| 1274 | 1204 |
| 1275 | |
| 1276 // Calculate V flag value for additions (and subtractions with adjusted args). | 1205 // Calculate V flag value for additions (and subtractions with adjusted args). |
| 1277 bool Simulator::OverflowFrom(int32_t left, int32_t right, int32_t carry) { | 1206 bool Simulator::OverflowFrom(int32_t left, int32_t right, int32_t carry) { |
| 1278 int64_t result = static_cast<int64_t>(left) + right + carry; | 1207 int64_t result = static_cast<int64_t>(left) + right + carry; |
| 1279 return (result >> 31) != (result >> 32); | 1208 return (result >> 31) != (result >> 32); |
| 1280 } | 1209 } |
| 1281 | 1210 |
| 1282 | |
| 1283 // Addressing Mode 1 - Data-processing operands: | 1211 // Addressing Mode 1 - Data-processing operands: |
| 1284 // Get the value based on the shifter_operand with register. | 1212 // Get the value based on the shifter_operand with register. |
| 1285 int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) { | 1213 int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) { |
| 1286 Shift shift = instr->ShiftField(); | 1214 Shift shift = instr->ShiftField(); |
| 1287 int shift_amount = instr->ShiftAmountField(); | 1215 int shift_amount = instr->ShiftAmountField(); |
| 1288 int32_t result = get_register(instr->RmField()); | 1216 int32_t result = get_register(instr->RmField()); |
| 1289 if (instr->Bit(4) == 0) { | 1217 if (instr->Bit(4) == 0) { |
| 1290 // by immediate | 1218 // by immediate |
| 1291 if ((shift == ROR) && (shift_amount == 0)) { | 1219 if ((shift == ROR) && (shift_amount == 0)) { |
| 1292 UnimplementedInstruction(instr); | 1220 UnimplementedInstruction(instr); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1415 | 1343 |
| 1416 default: { | 1344 default: { |
| 1417 UNREACHABLE(); | 1345 UNREACHABLE(); |
| 1418 break; | 1346 break; |
| 1419 } | 1347 } |
| 1420 } | 1348 } |
| 1421 } | 1349 } |
| 1422 return result; | 1350 return result; |
| 1423 } | 1351 } |
| 1424 | 1352 |
| 1425 | |
| 1426 // Addressing Mode 1 - Data-processing operands: | 1353 // Addressing Mode 1 - Data-processing operands: |
| 1427 // Get the value based on the shifter_operand with immediate. | 1354 // Get the value based on the shifter_operand with immediate. |
| 1428 int32_t Simulator::GetImm(Instr* instr, bool* carry_out) { | 1355 int32_t Simulator::GetImm(Instr* instr, bool* carry_out) { |
| 1429 int rotate = instr->RotateField() * 2; | 1356 int rotate = instr->RotateField() * 2; |
| 1430 int immed8 = instr->Immed8Field(); | 1357 int immed8 = instr->Immed8Field(); |
| 1431 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); | 1358 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); |
| 1432 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0); | 1359 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0); |
| 1433 return imm; | 1360 return imm; |
| 1434 } | 1361 } |
| 1435 | 1362 |
| 1436 | |
| 1437 static int count_bits(int bit_vector) { | 1363 static int count_bits(int bit_vector) { |
| 1438 int count = 0; | 1364 int count = 0; |
| 1439 while (bit_vector != 0) { | 1365 while (bit_vector != 0) { |
| 1440 if ((bit_vector & 1) != 0) { | 1366 if ((bit_vector & 1) != 0) { |
| 1441 count++; | 1367 count++; |
| 1442 } | 1368 } |
| 1443 bit_vector >>= 1; | 1369 bit_vector >>= 1; |
| 1444 } | 1370 } |
| 1445 return count; | 1371 return count; |
| 1446 } | 1372 } |
| 1447 | 1373 |
| 1448 | |
| 1449 // Addressing Mode 4 - Load and Store Multiple | 1374 // Addressing Mode 4 - Load and Store Multiple |
| 1450 void Simulator::HandleRList(Instr* instr, bool load) { | 1375 void Simulator::HandleRList(Instr* instr, bool load) { |
| 1451 Register rn = instr->RnField(); | 1376 Register rn = instr->RnField(); |
| 1452 int32_t rn_val = get_register(rn); | 1377 int32_t rn_val = get_register(rn); |
| 1453 int rlist = instr->RlistField(); | 1378 int rlist = instr->RlistField(); |
| 1454 int num_regs = count_bits(rlist); | 1379 int num_regs = count_bits(rlist); |
| 1455 | 1380 |
| 1456 uword address = 0; | 1381 uword address = 0; |
| 1457 uword end_address = 0; | 1382 uword end_address = 0; |
| 1458 switch (instr->PUField()) { | 1383 switch (instr->PUField()) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1505 } | 1430 } |
| 1506 address += 4; | 1431 address += 4; |
| 1507 } | 1432 } |
| 1508 reg++; | 1433 reg++; |
| 1509 rlist >>= 1; | 1434 rlist >>= 1; |
| 1510 } | 1435 } |
| 1511 ASSERT(end_address == address); | 1436 ASSERT(end_address == address); |
| 1512 } | 1437 } |
| 1513 } | 1438 } |
| 1514 | 1439 |
| 1515 | |
| 1516 // Calls into the Dart runtime are based on this interface. | 1440 // Calls into the Dart runtime are based on this interface. |
| 1517 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); | 1441 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); |
| 1518 | 1442 |
| 1519 // Calls to leaf Dart runtime functions are based on this interface. | 1443 // Calls to leaf Dart runtime functions are based on this interface. |
| 1520 typedef int32_t (*SimulatorLeafRuntimeCall)(int32_t r0, | 1444 typedef int32_t (*SimulatorLeafRuntimeCall)(int32_t r0, |
| 1521 int32_t r1, | 1445 int32_t r1, |
| 1522 int32_t r2, | 1446 int32_t r2, |
| 1523 int32_t r3); | 1447 int32_t r3); |
| 1524 | 1448 |
| 1525 // Calls to leaf float Dart runtime functions are based on this interface. | 1449 // Calls to leaf float Dart runtime functions are based on this interface. |
| 1526 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); | 1450 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); |
| 1527 | 1451 |
| 1528 // Calls to native Dart functions are based on this interface. | 1452 // Calls to native Dart functions are based on this interface. |
| 1529 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); | 1453 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); |
| 1530 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); | 1454 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); |
| 1531 | 1455 |
| 1532 | |
| 1533 void Simulator::SupervisorCall(Instr* instr) { | 1456 void Simulator::SupervisorCall(Instr* instr) { |
| 1534 int svc = instr->SvcField(); | 1457 int svc = instr->SvcField(); |
| 1535 switch (svc) { | 1458 switch (svc) { |
| 1536 case Instr::kSimulatorRedirectCode: { | 1459 case Instr::kSimulatorRedirectCode: { |
| 1537 SimulatorSetjmpBuffer buffer(this); | 1460 SimulatorSetjmpBuffer buffer(this); |
| 1538 | 1461 |
| 1539 if (!setjmp(buffer.buffer_)) { | 1462 if (!setjmp(buffer.buffer_)) { |
| 1540 int32_t saved_lr = get_register(LR); | 1463 int32_t saved_lr = get_register(LR); |
| 1541 Redirection* redirection = Redirection::FromSvcInstruction(instr); | 1464 Redirection* redirection = Redirection::FromSvcInstruction(instr); |
| 1542 uword external = redirection->external_function(); | 1465 uword external = redirection->external_function(); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1660 dbg.Stop(instr, "breakpoint"); | 1583 dbg.Stop(instr, "breakpoint"); |
| 1661 break; | 1584 break; |
| 1662 } | 1585 } |
| 1663 default: { | 1586 default: { |
| 1664 UNREACHABLE(); | 1587 UNREACHABLE(); |
| 1665 break; | 1588 break; |
| 1666 } | 1589 } |
| 1667 } | 1590 } |
| 1668 } | 1591 } |
| 1669 | 1592 |
| 1670 | |
| 1671 // Handle execution based on instruction types. | 1593 // Handle execution based on instruction types. |
| 1672 | 1594 |
| 1673 // Instruction types 0 and 1 are both rolled into one function because they | 1595 // Instruction types 0 and 1 are both rolled into one function because they |
| 1674 // only differ in the handling of the shifter_operand. | 1596 // only differ in the handling of the shifter_operand. |
| 1675 void Simulator::DecodeType01(Instr* instr) { | 1597 void Simulator::DecodeType01(Instr* instr) { |
| 1676 if (!instr->IsDataProcessing()) { | 1598 if (!instr->IsDataProcessing()) { |
| 1677 // miscellaneous, multiply, sync primitives, extra loads and stores. | 1599 // miscellaneous, multiply, sync primitives, extra loads and stores. |
| 1678 if (instr->IsMiscellaneous()) { | 1600 if (instr->IsMiscellaneous()) { |
| 1679 switch (instr->Bits(4, 3)) { | 1601 switch (instr->Bits(4, 3)) { |
| 1680 case 1: { | 1602 case 1: { |
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2285 } | 2207 } |
| 2286 | 2208 |
| 2287 default: { | 2209 default: { |
| 2288 UNREACHABLE(); | 2210 UNREACHABLE(); |
| 2289 break; | 2211 break; |
| 2290 } | 2212 } |
| 2291 } | 2213 } |
| 2292 } | 2214 } |
| 2293 } | 2215 } |
| 2294 | 2216 |
| 2295 | |
| 2296 void Simulator::DecodeType2(Instr* instr) { | 2217 void Simulator::DecodeType2(Instr* instr) { |
| 2297 Register rd = instr->RdField(); | 2218 Register rd = instr->RdField(); |
| 2298 Register rn = instr->RnField(); | 2219 Register rn = instr->RnField(); |
| 2299 int32_t rn_val = get_register(rn); | 2220 int32_t rn_val = get_register(rn); |
| 2300 int32_t im_val = instr->Offset12Field(); | 2221 int32_t im_val = instr->Offset12Field(); |
| 2301 uword addr = 0; | 2222 uword addr = 0; |
| 2302 bool write_back = false; | 2223 bool write_back = false; |
| 2303 switch (instr->PUField()) { | 2224 switch (instr->PUField()) { |
| 2304 case 0: { | 2225 case 0: { |
| 2305 // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); | 2226 // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2354 } else { | 2275 } else { |
| 2355 if (instr->HasL()) { | 2276 if (instr->HasL()) { |
| 2356 set_register(rd, ReadW(addr, instr)); | 2277 set_register(rd, ReadW(addr, instr)); |
| 2357 } else { | 2278 } else { |
| 2358 WriteW(addr, get_register(rd), instr); | 2279 WriteW(addr, get_register(rd), instr); |
| 2359 } | 2280 } |
| 2360 } | 2281 } |
| 2361 } | 2282 } |
| 2362 } | 2283 } |
| 2363 | 2284 |
| 2364 | |
| 2365 void Simulator::DoDivision(Instr* instr) { | 2285 void Simulator::DoDivision(Instr* instr) { |
| 2366 const Register rd = instr->DivRdField(); | 2286 const Register rd = instr->DivRdField(); |
| 2367 const Register rn = instr->DivRnField(); | 2287 const Register rn = instr->DivRnField(); |
| 2368 const Register rm = instr->DivRmField(); | 2288 const Register rm = instr->DivRmField(); |
| 2369 | 2289 |
| 2370 if (!TargetCPUFeatures::integer_division_supported()) { | 2290 if (!TargetCPUFeatures::integer_division_supported()) { |
| 2371 UnimplementedInstruction(instr); | 2291 UnimplementedInstruction(instr); |
| 2372 return; | 2292 return; |
| 2373 } | 2293 } |
| 2374 | 2294 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2393 if ((rn_val == static_cast<int32_t>(0x80000000)) && | 2313 if ((rn_val == static_cast<int32_t>(0x80000000)) && |
| 2394 (rm_val == static_cast<int32_t>(0xffffffff))) { | 2314 (rm_val == static_cast<int32_t>(0xffffffff))) { |
| 2395 result = 0x80000000; | 2315 result = 0x80000000; |
| 2396 } else { | 2316 } else { |
| 2397 result = rn_val / rm_val; | 2317 result = rn_val / rm_val; |
| 2398 } | 2318 } |
| 2399 set_register(rd, result); | 2319 set_register(rd, result); |
| 2400 } | 2320 } |
| 2401 } | 2321 } |
| 2402 | 2322 |
| 2403 | |
| 2404 void Simulator::DecodeType3(Instr* instr) { | 2323 void Simulator::DecodeType3(Instr* instr) { |
| 2405 if (instr->IsDivision()) { | 2324 if (instr->IsDivision()) { |
| 2406 DoDivision(instr); | 2325 DoDivision(instr); |
| 2407 return; | 2326 return; |
| 2408 } | 2327 } |
| 2409 Register rd = instr->RdField(); | 2328 Register rd = instr->RdField(); |
| 2410 Register rn = instr->RnField(); | 2329 Register rn = instr->RnField(); |
| 2411 int32_t rn_val = get_register(rn); | 2330 int32_t rn_val = get_register(rn); |
| 2412 bool shifter_carry_out = 0; | 2331 bool shifter_carry_out = 0; |
| 2413 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out); | 2332 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2467 } else { | 2386 } else { |
| 2468 if (instr->HasL()) { | 2387 if (instr->HasL()) { |
| 2469 set_register(rd, ReadW(addr, instr)); | 2388 set_register(rd, ReadW(addr, instr)); |
| 2470 } else { | 2389 } else { |
| 2471 WriteW(addr, get_register(rd), instr); | 2390 WriteW(addr, get_register(rd), instr); |
| 2472 } | 2391 } |
| 2473 } | 2392 } |
| 2474 } | 2393 } |
| 2475 } | 2394 } |
| 2476 | 2395 |
| 2477 | |
| 2478 void Simulator::DecodeType4(Instr* instr) { | 2396 void Simulator::DecodeType4(Instr* instr) { |
| 2479 ASSERT(instr->Bit(22) == 0); // only allowed to be set in privileged mode | 2397 ASSERT(instr->Bit(22) == 0); // only allowed to be set in privileged mode |
| 2480 if (instr->HasL()) { | 2398 if (instr->HasL()) { |
| 2481 // Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); | 2399 // Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); |
| 2482 HandleRList(instr, true); | 2400 HandleRList(instr, true); |
| 2483 } else { | 2401 } else { |
| 2484 // Format(instr, "stm'cond'pu 'rn'w, 'rlist"); | 2402 // Format(instr, "stm'cond'pu 'rn'w, 'rlist"); |
| 2485 HandleRList(instr, false); | 2403 HandleRList(instr, false); |
| 2486 } | 2404 } |
| 2487 } | 2405 } |
| 2488 | 2406 |
| 2489 | |
| 2490 void Simulator::DecodeType5(Instr* instr) { | 2407 void Simulator::DecodeType5(Instr* instr) { |
| 2491 // Format(instr, "b'l'cond 'target"); | 2408 // Format(instr, "b'l'cond 'target"); |
| 2492 int off = (instr->SImmed24Field() << 2) + 8; | 2409 int off = (instr->SImmed24Field() << 2) + 8; |
| 2493 intptr_t pc = get_pc(); | 2410 intptr_t pc = get_pc(); |
| 2494 if (instr->HasLink()) { | 2411 if (instr->HasLink()) { |
| 2495 set_register(LR, pc + Instr::kInstrSize); | 2412 set_register(LR, pc + Instr::kInstrSize); |
| 2496 } | 2413 } |
| 2497 set_pc(pc + off); | 2414 set_pc(pc + off); |
| 2498 } | 2415 } |
| 2499 | 2416 |
| 2500 | |
| 2501 void Simulator::DecodeType6(Instr* instr) { | 2417 void Simulator::DecodeType6(Instr* instr) { |
| 2502 if (instr->IsVFPDoubleTransfer()) { | 2418 if (instr->IsVFPDoubleTransfer()) { |
| 2503 Register rd = instr->RdField(); | 2419 Register rd = instr->RdField(); |
| 2504 Register rn = instr->RnField(); | 2420 Register rn = instr->RnField(); |
| 2505 if (instr->Bit(8) == 0) { | 2421 if (instr->Bit(8) == 0) { |
| 2506 SRegister sm = instr->SmField(); | 2422 SRegister sm = instr->SmField(); |
| 2507 SRegister sm1 = static_cast<SRegister>(sm + 1); | 2423 SRegister sm1 = static_cast<SRegister>(sm + 1); |
| 2508 ASSERT(sm1 < kNumberOfSRegisters); | 2424 ASSERT(sm1 < kNumberOfSRegisters); |
| 2509 if (instr->Bit(20) == 1) { | 2425 if (instr->Bit(20) == 1) { |
| 2510 // Format(instr, "vmovrrs'cond 'rd, 'rn, {'sm', 'sm1}"); | 2426 // Format(instr, "vmovrrs'cond 'rd, 'rn, {'sm', 'sm1}"); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2622 } else { | 2538 } else { |
| 2623 UnimplementedInstruction(instr); | 2539 UnimplementedInstruction(instr); |
| 2624 } | 2540 } |
| 2625 } | 2541 } |
| 2626 } | 2542 } |
| 2627 } else { | 2543 } else { |
| 2628 UnimplementedInstruction(instr); | 2544 UnimplementedInstruction(instr); |
| 2629 } | 2545 } |
| 2630 } | 2546 } |
| 2631 | 2547 |
| 2632 | |
| 2633 void Simulator::DecodeType7(Instr* instr) { | 2548 void Simulator::DecodeType7(Instr* instr) { |
| 2634 if (instr->Bit(24) == 1) { | 2549 if (instr->Bit(24) == 1) { |
| 2635 // Format(instr, "svc #'svc"); | 2550 // Format(instr, "svc #'svc"); |
| 2636 SupervisorCall(instr); | 2551 SupervisorCall(instr); |
| 2637 } else if (instr->IsVFPDataProcessingOrSingleTransfer()) { | 2552 } else if (instr->IsVFPDataProcessingOrSingleTransfer()) { |
| 2638 if (instr->Bit(4) == 0) { | 2553 if (instr->Bit(4) == 0) { |
| 2639 // VFP Data Processing | 2554 // VFP Data Processing |
| 2640 SRegister sd; | 2555 SRegister sd; |
| 2641 SRegister sn; | 2556 SRegister sn; |
| 2642 SRegister sm; | 2557 SRegister sm; |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3018 } | 2933 } |
| 3019 } else { | 2934 } else { |
| 3020 UnimplementedInstruction(instr); | 2935 UnimplementedInstruction(instr); |
| 3021 } | 2936 } |
| 3022 } | 2937 } |
| 3023 } else { | 2938 } else { |
| 3024 UnimplementedInstruction(instr); | 2939 UnimplementedInstruction(instr); |
| 3025 } | 2940 } |
| 3026 } | 2941 } |
| 3027 | 2942 |
| 3028 | |
| 3029 static float arm_reciprocal_sqrt_estimate(float a) { | 2943 static float arm_reciprocal_sqrt_estimate(float a) { |
| 3030 // From the ARM Architecture Reference Manual A2-87. | 2944 // From the ARM Architecture Reference Manual A2-87. |
| 3031 if (isinf(a) || (fabs(a) >= exp2f(126))) | 2945 if (isinf(a) || (fabs(a) >= exp2f(126))) |
| 3032 return 0.0; | 2946 return 0.0; |
| 3033 else if (a == 0.0) | 2947 else if (a == 0.0) |
| 3034 return kPosInfinity; | 2948 return kPosInfinity; |
| 3035 else if (isnan(a)) | 2949 else if (isnan(a)) |
| 3036 return a; | 2950 return a; |
| 3037 | 2951 |
| 3038 uint32_t a_bits = bit_cast<uint32_t, float>(a); | 2952 uint32_t a_bits = bit_cast<uint32_t, float>(a); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3073 double estimate = static_cast<double>(s) / 256.0; | 2987 double estimate = static_cast<double>(s) / 256.0; |
| 3074 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0))); | 2988 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0))); |
| 3075 | 2989 |
| 3076 // result = 0 : result_exp<7:0> : estimate<51:29> | 2990 // result = 0 : result_exp<7:0> : estimate<51:29> |
| 3077 int32_t result_bits = | 2991 int32_t result_bits = |
| 3078 ((result_exp & 0xff) << 23) | | 2992 ((result_exp & 0xff) << 23) | |
| 3079 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); | 2993 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); |
| 3080 return bit_cast<float, int32_t>(result_bits); | 2994 return bit_cast<float, int32_t>(result_bits); |
| 3081 } | 2995 } |
| 3082 | 2996 |
| 3083 | |
| 3084 static float arm_recip_estimate(float a) { | 2997 static float arm_recip_estimate(float a) { |
| 3085 // From the ARM Architecture Reference Manual A2-85. | 2998 // From the ARM Architecture Reference Manual A2-85. |
| 3086 if (isinf(a) || (fabs(a) >= exp2f(126))) | 2999 if (isinf(a) || (fabs(a) >= exp2f(126))) |
| 3087 return 0.0; | 3000 return 0.0; |
| 3088 else if (a == 0.0) | 3001 else if (a == 0.0) |
| 3089 return kPosInfinity; | 3002 return kPosInfinity; |
| 3090 else if (isnan(a)) | 3003 else if (isnan(a)) |
| 3091 return a; | 3004 return a; |
| 3092 | 3005 |
| 3093 uint32_t a_bits = bit_cast<uint32_t, float>(a); | 3006 uint32_t a_bits = bit_cast<uint32_t, float>(a); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3110 double estimate = static_cast<double>(s) / 256.0; | 3023 double estimate = static_cast<double>(s) / 256.0; |
| 3111 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0))); | 3024 ASSERT((estimate >= 1.0) && (estimate <= (511.0 / 256.0))); |
| 3112 | 3025 |
| 3113 // result = sign : result_exp<7:0> : estimate<51:29> | 3026 // result = sign : result_exp<7:0> : estimate<51:29> |
| 3114 int32_t result_bits = | 3027 int32_t result_bits = |
| 3115 (a_bits & 0x80000000) | ((result_exp & 0xff) << 23) | | 3028 (a_bits & 0x80000000) | ((result_exp & 0xff) << 23) | |
| 3116 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); | 3029 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); |
| 3117 return bit_cast<float, int32_t>(result_bits); | 3030 return bit_cast<float, int32_t>(result_bits); |
| 3118 } | 3031 } |
| 3119 | 3032 |
| 3120 | |
| 3121 static void simd_value_swap(simd_value_t* s1, | 3033 static void simd_value_swap(simd_value_t* s1, |
| 3122 int i1, | 3034 int i1, |
| 3123 simd_value_t* s2, | 3035 simd_value_t* s2, |
| 3124 int i2) { | 3036 int i2) { |
| 3125 uint32_t tmp; | 3037 uint32_t tmp; |
| 3126 tmp = s1->data_[i1].u; | 3038 tmp = s1->data_[i1].u; |
| 3127 s1->data_[i1].u = s2->data_[i2].u; | 3039 s1->data_[i1].u = s2->data_[i2].u; |
| 3128 s2->data_[i2].u = tmp; | 3040 s2->data_[i2].u = tmp; |
| 3129 } | 3041 } |
| 3130 | 3042 |
| 3131 | |
| 3132 void Simulator::DecodeSIMDDataProcessing(Instr* instr) { | 3043 void Simulator::DecodeSIMDDataProcessing(Instr* instr) { |
| 3133 ASSERT(instr->ConditionField() == kSpecialCondition); | 3044 ASSERT(instr->ConditionField() == kSpecialCondition); |
| 3134 | 3045 |
| 3135 if (instr->Bit(6) == 1) { | 3046 if (instr->Bit(6) == 1) { |
| 3136 // Q = 1, Using 128-bit Q registers. | 3047 // Q = 1, Using 128-bit Q registers. |
| 3137 const QRegister qd = instr->QdField(); | 3048 const QRegister qd = instr->QdField(); |
| 3138 const QRegister qn = instr->QnField(); | 3049 const QRegister qn = instr->QnField(); |
| 3139 const QRegister qm = instr->QmField(); | 3050 const QRegister qm = instr->QmField(); |
| 3140 simd_value_t s8d; | 3051 simd_value_t s8d; |
| 3141 simd_value_t s8n; | 3052 simd_value_t s8n; |
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3613 } | 3524 } |
| 3614 } | 3525 } |
| 3615 | 3526 |
| 3616 set_dregister_bits(dd, result); | 3527 set_dregister_bits(dd, result); |
| 3617 } else { | 3528 } else { |
| 3618 UnimplementedInstruction(instr); | 3529 UnimplementedInstruction(instr); |
| 3619 } | 3530 } |
| 3620 } | 3531 } |
| 3621 } | 3532 } |
| 3622 | 3533 |
| 3623 | |
| 3624 // Executes the current instruction. | 3534 // Executes the current instruction. |
| 3625 void Simulator::InstructionDecode(Instr* instr) { | 3535 void Simulator::InstructionDecode(Instr* instr) { |
| 3626 pc_modified_ = false; | 3536 pc_modified_ = false; |
| 3627 if (IsTracingExecution()) { | 3537 if (IsTracingExecution()) { |
| 3628 THR_Print("%" Pu64 " ", icount_); | 3538 THR_Print("%" Pu64 " ", icount_); |
| 3629 const uword start = reinterpret_cast<uword>(instr); | 3539 const uword start = reinterpret_cast<uword>(instr); |
| 3630 const uword end = start + Instr::kInstrSize; | 3540 const uword end = start + Instr::kInstrSize; |
| 3631 if (FLAG_support_disassembler) { | 3541 if (FLAG_support_disassembler) { |
| 3632 Disassembler::Disassemble(start, end); | 3542 Disassembler::Disassemble(start, end); |
| 3633 } else { | 3543 } else { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3681 UNREACHABLE(); | 3591 UNREACHABLE(); |
| 3682 break; | 3592 break; |
| 3683 } | 3593 } |
| 3684 } | 3594 } |
| 3685 } | 3595 } |
| 3686 if (!pc_modified_) { | 3596 if (!pc_modified_) { |
| 3687 set_register(PC, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); | 3597 set_register(PC, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); |
| 3688 } | 3598 } |
| 3689 } | 3599 } |
| 3690 | 3600 |
| 3691 | |
| 3692 void Simulator::Execute() { | 3601 void Simulator::Execute() { |
| 3693 // Get the PC to simulate. Cannot use the accessor here as we need the | 3602 // Get the PC to simulate. Cannot use the accessor here as we need the |
| 3694 // raw PC value and not the one used as input to arithmetic instructions. | 3603 // raw PC value and not the one used as input to arithmetic instructions. |
| 3695 uword program_counter = get_pc(); | 3604 uword program_counter = get_pc(); |
| 3696 | 3605 |
| 3697 if (FLAG_stop_sim_at == ULLONG_MAX) { | 3606 if (FLAG_stop_sim_at == ULLONG_MAX) { |
| 3698 // Fast version of the dispatch loop without checking whether the simulator | 3607 // Fast version of the dispatch loop without checking whether the simulator |
| 3699 // should be stopping at a particular executed instruction. | 3608 // should be stopping at a particular executed instruction. |
| 3700 while (program_counter != kEndSimulatingPC) { | 3609 while (program_counter != kEndSimulatingPC) { |
| 3701 Instr* instr = reinterpret_cast<Instr*>(program_counter); | 3610 Instr* instr = reinterpret_cast<Instr*>(program_counter); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3722 } else if (IsIllegalAddress(program_counter)) { | 3631 } else if (IsIllegalAddress(program_counter)) { |
| 3723 HandleIllegalAccess(program_counter, instr); | 3632 HandleIllegalAccess(program_counter, instr); |
| 3724 } else { | 3633 } else { |
| 3725 InstructionDecode(instr); | 3634 InstructionDecode(instr); |
| 3726 } | 3635 } |
| 3727 program_counter = get_pc(); | 3636 program_counter = get_pc(); |
| 3728 } | 3637 } |
| 3729 } | 3638 } |
| 3730 } | 3639 } |
| 3731 | 3640 |
| 3732 | |
| 3733 int64_t Simulator::Call(int32_t entry, | 3641 int64_t Simulator::Call(int32_t entry, |
| 3734 int32_t parameter0, | 3642 int32_t parameter0, |
| 3735 int32_t parameter1, | 3643 int32_t parameter1, |
| 3736 int32_t parameter2, | 3644 int32_t parameter2, |
| 3737 int32_t parameter3, | 3645 int32_t parameter3, |
| 3738 bool fp_return, | 3646 bool fp_return, |
| 3739 bool fp_args) { | 3647 bool fp_args) { |
| 3740 // Save the SP register before the call so we can restore it. | 3648 // Save the SP register before the call so we can restore it. |
| 3741 int32_t sp_before_call = get_register(SP); | 3649 int32_t sp_before_call = get_register(SP); |
| 3742 | 3650 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3884 int64_t return_value; | 3792 int64_t return_value; |
| 3885 if (fp_return) { | 3793 if (fp_return) { |
| 3886 ASSERT(TargetCPUFeatures::vfp_supported()); | 3794 ASSERT(TargetCPUFeatures::vfp_supported()); |
| 3887 return_value = bit_cast<int64_t, double>(get_dregister(D0)); | 3795 return_value = bit_cast<int64_t, double>(get_dregister(D0)); |
| 3888 } else { | 3796 } else { |
| 3889 return_value = Utils::LowHighTo64Bits(get_register(R0), get_register(R1)); | 3797 return_value = Utils::LowHighTo64Bits(get_register(R0), get_register(R1)); |
| 3890 } | 3798 } |
| 3891 return return_value; | 3799 return return_value; |
| 3892 } | 3800 } |
| 3893 | 3801 |
| 3894 | |
| 3895 void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) { | 3802 void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) { |
| 3896 // Walk over all setjmp buffers (simulated --> C++ transitions) | 3803 // Walk over all setjmp buffers (simulated --> C++ transitions) |
| 3897 // and try to find the setjmp associated with the simulated stack pointer. | 3804 // and try to find the setjmp associated with the simulated stack pointer. |
| 3898 SimulatorSetjmpBuffer* buf = last_setjmp_buffer(); | 3805 SimulatorSetjmpBuffer* buf = last_setjmp_buffer(); |
| 3899 while (buf->link() != NULL && buf->link()->sp() <= sp) { | 3806 while (buf->link() != NULL && buf->link()->sp() <= sp) { |
| 3900 buf = buf->link(); | 3807 buf = buf->link(); |
| 3901 } | 3808 } |
| 3902 ASSERT(buf != NULL); | 3809 ASSERT(buf != NULL); |
| 3903 | 3810 |
| 3904 // The C++ caller has not cleaned up the stack memory of C++ frames. | 3811 // The C++ caller has not cleaned up the stack memory of C++ frames. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3923 set_register(CODE_REG, code); | 3830 set_register(CODE_REG, code); |
| 3924 set_register(PP, pp); | 3831 set_register(PP, pp); |
| 3925 buf->Longjmp(); | 3832 buf->Longjmp(); |
| 3926 } | 3833 } |
| 3927 | 3834 |
| 3928 } // namespace dart | 3835 } // namespace dart |
| 3929 | 3836 |
| 3930 #endif // defined(USING_SIMULATOR) | 3837 #endif // defined(USING_SIMULATOR) |
| 3931 | 3838 |
| 3932 #endif // defined TARGET_ARCH_ARM | 3839 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |