Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 41 using ::v8::internal::Object; | 41 using ::v8::internal::Object; |
| 42 using ::v8::internal::PrintF; | 42 using ::v8::internal::PrintF; |
| 43 using ::v8::internal::OS; | 43 using ::v8::internal::OS; |
| 44 using ::v8::internal::ReadLine; | 44 using ::v8::internal::ReadLine; |
| 45 using ::v8::internal::DeleteArray; | 45 using ::v8::internal::DeleteArray; |
| 46 | 46 |
| 47 // This macro provides a platform independent use of sscanf. The reason for | 47 // This macro provides a platform independent use of sscanf. The reason for |
| 48 // SScanF not beeing implemented in a platform independent was through | 48 // SScanF not beeing implemented in a platform independent was through |
| 49 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time | 49 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time |
| 50 // Library does not provide vsscanf. | 50 // Library does not provide vsscanf. |
| 51 #ifdef WIN32 | |
| 52 #define SScanF sscanf_s | |
| 53 #else | |
| 54 #define SScanF sscanf // NOLINT | 51 #define SScanF sscanf // NOLINT |
| 55 #endif | |
| 56 | 52 |
| 57 // The Debugger class is used by the simulator while debugging simulated ARM | 53 // The Debugger class is used by the simulator while debugging simulated ARM |
| 58 // code. | 54 // code. |
| 59 class Debugger { | 55 class Debugger { |
| 60 public: | 56 public: |
| 61 explicit Debugger(Simulator* sim); | 57 explicit Debugger(Simulator* sim); |
| 62 ~Debugger(); | 58 ~Debugger(); |
| 63 | 59 |
| 64 void Stop(Instr* instr); | 60 void Stop(Instr* instr); |
| 65 void Debug(); | 61 void Debug(); |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 // allocated stack area. To be safe in potential stack underflows we leave | 371 // allocated stack area. To be safe in potential stack underflows we leave |
| 376 // some buffer below. | 372 // some buffer below. |
| 377 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; | 373 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; |
| 378 // The lr and pc are initialized to a known bad value that will cause an | 374 // The lr and pc are initialized to a known bad value that will cause an |
| 379 // access violation if the simulator ever tries to execute it. | 375 // access violation if the simulator ever tries to execute it. |
| 380 registers_[pc] = bad_lr; | 376 registers_[pc] = bad_lr; |
| 381 registers_[lr] = bad_lr; | 377 registers_[lr] = bad_lr; |
| 382 } | 378 } |
| 383 | 379 |
| 384 | 380 |
| 385 // This is the Simulator singleton. Currently only one thread is supported by | 381 // Create one simulator per thread and keep it in thread local storage. |
| 386 // V8. If we had multiple threads, then we should have a Simulator instance on | 382 static v8::internal::Thread::LocalStorageKey simulator_key = |
| 387 // a per thread basis. | 383 v8::internal::Thread::CreateThreadLocalKey(); |
| 388 static Simulator* the_sim = NULL; | |
| 389 | 384 |
| 390 | 385 // Get the active Simulator for the current thread. |
| 391 // Get the active Simulator for the current thread. See comment above about | |
| 392 // using a singleton currently. | |
| 393 Simulator* Simulator::current() { | 386 Simulator* Simulator::current() { |
| 394 if (the_sim == NULL) { | 387 Simulator* sim = reinterpret_cast<Simulator*>( |
| 395 the_sim = new Simulator(); | 388 v8::internal::Thread::GetThreadLocal(simulator_key)); |
| 389 if (sim == NULL) { | |
| 390 sim = new Simulator(); | |
| 391 v8::internal::Thread::SetThreadLocal(simulator_key, sim); | |
|
iposva
2008/11/12 20:16:42
Since there is no AttachCurrentThread/DetachCurren
| |
| 396 } | 392 } |
| 397 return the_sim; | 393 return sim; |
| 398 } | 394 } |
| 399 | 395 |
| 400 | 396 |
| 401 // Sets the register in the architecture state. It will also deal with updating | 397 // Sets the register in the architecture state. It will also deal with updating |
| 402 // Simulator internal state for special registers such as PC. | 398 // Simulator internal state for special registers such as PC. |
| 403 void Simulator::set_register(int reg, int32_t value) { | 399 void Simulator::set_register(int reg, int32_t value) { |
| 404 ASSERT((reg >= 0) && (reg < num_registers)); | 400 ASSERT((reg >= 0) && (reg < num_registers)); |
| 405 if (reg == pc) { | 401 if (reg == pc) { |
| 406 pc_modified_ = true; | 402 pc_modified_ = true; |
| 407 } | 403 } |
| (...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1488 } | 1484 } |
| 1489 } | 1485 } |
| 1490 } | 1486 } |
| 1491 if (!pc_modified_) { | 1487 if (!pc_modified_) { |
| 1492 set_register(pc, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); | 1488 set_register(pc, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); |
| 1493 } | 1489 } |
| 1494 } | 1490 } |
| 1495 | 1491 |
| 1496 | 1492 |
| 1497 // | 1493 // |
| 1498 void Simulator::execute() { | 1494 void Simulator::Execute() { |
| 1499 // Get the PC to simulate. Cannot use the accessor here as we need the | 1495 // Get the PC to simulate. Cannot use the accessor here as we need the |
| 1500 // raw PC value and not the one used as input to arithmetic instructions. | 1496 // raw PC value and not the one used as input to arithmetic instructions. |
| 1501 int program_counter = get_pc(); | 1497 int program_counter = get_pc(); |
| 1502 | 1498 |
| 1503 if (::v8::internal::FLAG_stop_sim_at == 0) { | 1499 if (::v8::internal::FLAG_stop_sim_at == 0) { |
| 1504 // Fast version of the dispatch loop without checking whether the simulator | 1500 // Fast version of the dispatch loop without checking whether the simulator |
| 1505 // should be stopping at a particular executed instruction. | 1501 // should be stopping at a particular executed instruction. |
| 1506 while (program_counter != end_sim_pc) { | 1502 while (program_counter != end_sim_pc) { |
| 1507 Instr* instr = reinterpret_cast<Instr*>(program_counter); | 1503 Instr* instr = reinterpret_cast<Instr*>(program_counter); |
| 1508 icount_++; | 1504 icount_++; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1520 dbg.Debug(); | 1516 dbg.Debug(); |
| 1521 } else { | 1517 } else { |
| 1522 InstructionDecode(instr); | 1518 InstructionDecode(instr); |
| 1523 } | 1519 } |
| 1524 program_counter = get_pc(); | 1520 program_counter = get_pc(); |
| 1525 } | 1521 } |
| 1526 } | 1522 } |
| 1527 } | 1523 } |
| 1528 | 1524 |
| 1529 | 1525 |
| 1530 Object* Simulator::call(int32_t entry, int32_t p0, int32_t p1, int32_t p2, | 1526 Object* Simulator::Call(int32_t entry, int32_t p0, int32_t p1, int32_t p2, |
| 1531 int32_t p3, int32_t p4) { | 1527 int32_t p3, int32_t p4) { |
| 1532 // Setup parameters | 1528 // Setup parameters |
| 1533 set_register(r0, p0); | 1529 set_register(r0, p0); |
| 1534 set_register(r1, p1); | 1530 set_register(r1, p1); |
| 1535 set_register(r2, p2); | 1531 set_register(r2, p2); |
| 1536 set_register(r3, p3); | 1532 set_register(r3, p3); |
| 1537 intptr_t* stack_pointer = reinterpret_cast<intptr_t*>(get_register(sp)); | 1533 intptr_t* stack_pointer = reinterpret_cast<intptr_t*>(get_register(sp)); |
| 1538 *(--stack_pointer) = p4; | 1534 *(--stack_pointer) = p4; |
| 1539 set_register(sp, reinterpret_cast<int32_t>(stack_pointer)); | 1535 set_register(sp, reinterpret_cast<int32_t>(stack_pointer)); |
| 1540 | 1536 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1563 set_register(r4, callee_saved_value); | 1559 set_register(r4, callee_saved_value); |
| 1564 set_register(r5, callee_saved_value); | 1560 set_register(r5, callee_saved_value); |
| 1565 set_register(r6, callee_saved_value); | 1561 set_register(r6, callee_saved_value); |
| 1566 set_register(r7, callee_saved_value); | 1562 set_register(r7, callee_saved_value); |
| 1567 set_register(r8, callee_saved_value); | 1563 set_register(r8, callee_saved_value); |
| 1568 set_register(r9, callee_saved_value); | 1564 set_register(r9, callee_saved_value); |
| 1569 set_register(r10, callee_saved_value); | 1565 set_register(r10, callee_saved_value); |
| 1570 set_register(r11, callee_saved_value); | 1566 set_register(r11, callee_saved_value); |
| 1571 | 1567 |
| 1572 // Start the simulation | 1568 // Start the simulation |
| 1573 execute(); | 1569 Execute(); |
| 1574 | 1570 |
| 1575 // Check that the callee-saved registers have been preserved. | 1571 // Check that the callee-saved registers have been preserved. |
| 1576 CHECK_EQ(get_register(r4), callee_saved_value); | 1572 CHECK_EQ(get_register(r4), callee_saved_value); |
| 1577 CHECK_EQ(get_register(r5), callee_saved_value); | 1573 CHECK_EQ(get_register(r5), callee_saved_value); |
| 1578 CHECK_EQ(get_register(r6), callee_saved_value); | 1574 CHECK_EQ(get_register(r6), callee_saved_value); |
| 1579 CHECK_EQ(get_register(r7), callee_saved_value); | 1575 CHECK_EQ(get_register(r7), callee_saved_value); |
| 1580 CHECK_EQ(get_register(r8), callee_saved_value); | 1576 CHECK_EQ(get_register(r8), callee_saved_value); |
| 1581 CHECK_EQ(get_register(r9), callee_saved_value); | 1577 CHECK_EQ(get_register(r9), callee_saved_value); |
| 1582 CHECK_EQ(get_register(r10), callee_saved_value); | 1578 CHECK_EQ(get_register(r10), callee_saved_value); |
| 1583 CHECK_EQ(get_register(r11), callee_saved_value); | 1579 CHECK_EQ(get_register(r11), callee_saved_value); |
| 1584 | 1580 |
| 1585 // Restore callee-saved registers with the original value. | 1581 // Restore callee-saved registers with the original value. |
| 1586 set_register(r4, r4_val); | 1582 set_register(r4, r4_val); |
| 1587 set_register(r5, r5_val); | 1583 set_register(r5, r5_val); |
| 1588 set_register(r6, r6_val); | 1584 set_register(r6, r6_val); |
| 1589 set_register(r7, r7_val); | 1585 set_register(r7, r7_val); |
| 1590 set_register(r8, r8_val); | 1586 set_register(r8, r8_val); |
| 1591 set_register(r9, r9_val); | 1587 set_register(r9, r9_val); |
| 1592 set_register(r10, r10_val); | 1588 set_register(r10, r10_val); |
| 1593 set_register(r11, r11_val); | 1589 set_register(r11, r11_val); |
| 1594 | 1590 |
| 1595 int result = get_register(r0); | 1591 int result = get_register(r0); |
| 1596 return reinterpret_cast<Object*>(result); | 1592 return reinterpret_cast<Object*>(result); |
| 1597 } | 1593 } |
| 1598 | 1594 |
| 1599 } } // namespace assembler::arm | 1595 } } // namespace assembler::arm |
| 1600 | 1596 |
| 1601 #endif // !defined(__arm__) | 1597 #endif // !defined(__arm__) |
| OLD | NEW |