Chromium Code Reviews| Index: runtime/vm/simulator_arm.h |
| =================================================================== |
| --- runtime/vm/simulator_arm.h (revision 0) |
| +++ runtime/vm/simulator_arm.h (revision 0) |
| @@ -0,0 +1,230 @@ |
| +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +// Declares a Simulator for ARM instructions if we are not generating a native |
| +// ARM binary. This Simulator allows us to run and debug ARM code generation on |
| +// regular desktop machines. |
| +// Dart calls into generated code by "calling" the InvokeDartCode stub, |
| +// which will start execution in the Simulator or forwards to the real entry |
| +// on a ARM HW platform. |
| + |
| +#ifndef VM_SIMULATOR_ARM_H_ |
| +#define VM_SIMULATOR_ARM_H_ |
| + |
| +#ifndef VM_SIMULATOR_H_ |
| +#error Do not include simulator_arm.h directly; use simulator.h. |
| +#endif |
| + |
| +#if !defined(HOST_ARCH_ARM) |
| + |
| +#include "vm/allocation.h" |
| +#include "vm/constants_arm.h" |
| +#include "vm/object.h" |
| + |
| +namespace dart { |
| + |
| +class Isolate; |
| +class SimulatorSetjmpBuffer; |
| + |
| +class Simulator { |
| + public: |
| + static const size_t kSimulatorStackUnderflowSize = 64; |
| + |
| + Simulator(); |
| + ~Simulator(); |
| + |
| + // The currently executing Simulator instance. Potentially there can be one |
| + // for each isolate. |
|
siva
2013/01/24 02:03:09
There should be one for each isolate right, not su
Ivan Posva
2013/01/24 18:25:57
Actually the Simulator should be tied to the threa
regis
2013/01/24 21:47:48
No, there is zero or one simulator per isolate. If
regis
2013/01/24 21:47:48
OK, leaving as is for now.
|
| + static Simulator* Current(); |
| + |
| + // Accessors for register state. Reading the pc value adheres to the ARM |
| + // architecture specification and is off by 8 from the currently executing |
| + // instruction. |
| + void set_register(Register reg, int32_t value); |
| + int32_t get_register(Register reg) const; |
| + |
| + // Special case of set_register and get_register to access the raw PC value. |
| + void set_pc(int32_t value); |
| + int32_t get_pc() const; |
| + |
| + // Accessors for VFP register state. |
| + void set_sregister(SRegister reg, float value); |
| + float get_sregister(SRegister reg) const; |
| + void set_dregister(DRegister reg, double value); |
| + double get_dregister(DRegister reg) const; |
| + |
| + // Accessor to the internal simulator stack area. |
| + uintptr_t StackTop() const; |
| + uintptr_t StackLimit() const; |
| + |
| + // Executes ARM instructions until the PC reaches end_sim_pc. |
| + void Execute(); |
| + |
| + // Call on program start. |
| + static void InitOnce(); |
| + |
| + // Dart generally calls into generated code with 5 parameters. This is a |
| + // convenience function, which sets up the simulator state and grabs the |
| + // result on return. |
| + int64_t Call(int32_t entry, |
| + int32_t parameter0, |
| + int32_t parameter1, |
| + int32_t parameter2, |
| + int32_t parameter3, |
| + int32_t parameter4); |
| + |
| + // Implementation of atomic compare and exchange in the same synchronization |
| + // domain as other synchronization primitive instructions (e.g. ldrex, strex). |
| + static uword CompareExchange(uword* address, |
| + uword compare_value, |
| + uword new_value); |
| + |
| + // Runtime call support. |
| + static uword RedirectExternalReference(void* function, |
| + uint32_t argument_count); |
| + |
| + void Longjmp(int32_t pc, int32_t sp, int32_t fp, const Instance& object); |
| + |
| + private: |
| + // Known bad pc value to ensure that the simulator does not execute |
| + // without being properly setup. |
| + static const uword kBadLR = -1; |
| + // A pc value used to signal the simulator to stop execution. Generally |
| + // the lr is set to this value on transition from native C code to |
| + // simulated execution, so that the simulator can "return" to the native |
| + // C code. |
| + static const uword kEndSimulatingPC = -2; |
| + |
| + // CPU state. |
| + int32_t registers_[kNumberOfCpuRegisters]; |
| + bool n_flag_; |
| + bool z_flag_; |
| + bool c_flag_; |
| + bool v_flag_; |
| + |
| + // VFP state. |
| + union { // S and D register banks are overlapping. |
| + float sregisters_[kNumberOfSRegisters]; |
| + double dregisters_[kNumberOfDRegisters]; |
| + }; |
| + bool fp_n_flag_; |
| + bool fp_z_flag_; |
| + bool fp_c_flag_; |
| + bool fp_v_flag_; |
| + |
| + // Simulator support. |
| + char* stack_; |
| + bool pc_modified_; |
| + int icount_; |
| + static bool flag_trace_sim_; |
| + static int32_t flag_stop_sim_at_; |
| + SimulatorSetjmpBuffer* last_setjmp_buffer_; |
| + |
| + // Registered breakpoints. |
| + Instr* break_pc_; |
| + int32_t break_instr_; |
| + |
| + // Implicit null guard support. |
| + void HandleNullPageAccess(uword addr, Instr* instr); |
| + |
| + // Unsupported instructions use Format to print an error and stop execution. |
| + void Format(Instr* instr, const char* format); |
| + |
| + // Checks if the current instruction should be executed based on its |
| + // condition bits. |
| + bool ConditionallyExecute(Instr* instr); |
| + |
| + // Helper functions to set the conditional flags in the architecture state. |
| + void SetNZFlags(int32_t val); |
| + void SetCFlag(bool val); |
| + void SetVFlag(bool val); |
| + bool CarryFrom(int32_t left, int32_t right); |
| + bool BorrowFrom(int32_t left, int32_t right); |
| + bool OverflowFrom(int32_t alu_out, |
| + int32_t left, |
| + int32_t right, |
| + bool addition); |
| + |
| + // Helper functions to decode common "addressing" modes. |
| + int32_t GetShiftRm(Instr* instr, bool* carry_out); |
| + int32_t GetImm(Instr* instr, bool* carry_out); |
| + void HandleRList(Instr* instr, bool load); |
| + void SupervisorCall(Instr* instr); |
| + |
| + // Read and write memory. |
| + void UnalignedAccess(const char* msg, uword addr, Instr* instr); |
| + |
| + inline uint8_t ReadBU(uword addr); |
| + inline int8_t ReadB(uword addr); |
| + inline void WriteB(uword addr, uint8_t value); |
| + |
| + inline uint16_t ReadHU(uword addr, Instr* instr); |
| + inline int16_t ReadH(uword addr, Instr* instr); |
| + inline void WriteH(uword addr, uint16_t value, Instr* instr); |
| + |
| + inline int ReadW(uword addr, Instr* instr); |
| + inline void WriteW(uword addr, int value, Instr* instr); |
| + |
| + // Synchronization primitives support. |
| + void ClearExclusive(); |
| + int ReadExclusiveW(uword addr, Instr* instr); |
| + int WriteExclusiveW(uword addr, int value, Instr* instr); |
| + |
| + // In Dart, there is at most one thread per isolate. |
| + // We keep track of 16 exclusive access address tags across all isolates. |
| + // Since we cannot simulate a native context switch, which clears |
| + // the exclusive access state of the local monitor (using the CLREX |
| + // instruction), we associate the isolate requesting exclusive access to the |
| + // address tag. Multiple isolates requesting exclusive access (using the LDREX |
| + // instruction) to the same address will result in multiple address tags being |
| + // created for the same address, one per isolate. |
| + // At any given time, each isolate is associated to at most one address tag. |
| + static Mutex* exclusive_access_lock_; |
| + static const int kNumAddressTags = 16; |
| + static struct AddressTag { |
| + Isolate* isolate; |
| + uword addr; |
| + } exclusive_access_state_[kNumAddressTags]; |
|
siva
2013/01/24 02:03:09
Not sure if we will require this as there will be
regis
2013/01/24 21:47:48
TODO(regis) added.
|
| + static int next_address_tag_; |
| + |
| + // Set access to given address to 'exclusive state' for current isolate. |
| + static void SetExclusiveAccess(uword addr); |
| + |
| + // Returns true if the current isolate has exclusive access to given address, |
| + // returns false otherwise. In either case, set access to given address to |
| + // 'open state' for all isolates. |
| + // If given addr is NULL, set access to 'open state' for current |
| + // isolate (CLREX). |
| + static bool HasExclusiveAccessAndOpen(uword addr); |
| + |
| + // Executing is handled based on the instruction type. |
| + void DecodeType01(Instr* instr); // Both type 0 and type 1 rolled into one. |
| + void DecodeType2(Instr* instr); |
| + void DecodeType3(Instr* instr); |
| + void DecodeType4(Instr* instr); |
| + void DecodeType5(Instr* instr); |
| + void DecodeType6(Instr* instr); |
| + void DecodeType7(Instr* instr); |
| + |
| + // Executes one instruction. |
| + void InstructionDecode(Instr* instr); |
| + |
| + // Longjmp support for exceptions. |
| + SimulatorSetjmpBuffer* last_setjmp_buffer() { |
| + return last_setjmp_buffer_; |
| + } |
| + void set_last_setjmp_buffer(SimulatorSetjmpBuffer* buffer) { |
| + last_setjmp_buffer_ = buffer; |
| + } |
| + |
| + friend class SimulatorDebugger; |
| + friend class SimulatorSetjmpBuffer; |
| + DISALLOW_COPY_AND_ASSIGN(Simulator); |
| +}; |
| + |
| +} // namespace dart |
| + |
| +#endif // !defined(HOST_ARCH_ARM) |
| + |
| +#endif // VM_SIMULATOR_ARM_H_ |