Files
sdk/runtime/vm/simulator_arm.h
T
regis@google.com d79c7c1969 Implement long jump in ARM and MIPS simulators.
Implement error and exception handler stubs on ARM.
Hook up simulator for object tests.
Enable codegen and object tests on ARM.

Review URL: https://codereview.chromium.org//14309004

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@21680 260f80e4-7a28-3924-810f-c04153c831b5
2013-04-18 16:23:25 +00:00

248 lines
8.3 KiB
C++

// 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
#include "vm/constants_arm.h"
#include "vm/object.h"
namespace dart {
class Isolate;
class SimulatorSetjmpBuffer;
class Simulator {
public:
static const uword kSimulatorStackUnderflowSize = 64;
Simulator();
~Simulator();
// The currently executing Simulator instance, which is associated to the
// current isolate
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 top.
uword StackTop() const;
// The isolate's top_exit_frame_info refers to a Dart frame in the simulator
// stack. The simulator's top_exit_frame_info refers to a C++ frame in the
// native stack.
uword top_exit_frame_info() const { return top_exit_frame_info_; }
void set_top_exit_frame_info(uword value) { top_exit_frame_info_ = value; }
// 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);
// 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 and native call support.
enum CallKind {
kRuntimeCall,
kLeafRuntimeCall,
kNativeCall
};
static uword RedirectExternalReference(uword function, CallKind call_kind);
void Longjmp(uword pc,
uword sp,
uword fp,
RawObject* raw_exception,
RawObject* raw_stacktrace);
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 int32_t flag_stop_sim_at_;
SimulatorSetjmpBuffer* last_setjmp_buffer_;
uword top_exit_frame_info_;
// Registered breakpoints.
Instr* break_pc_;
int32_t break_instr_;
// Illegal memory access support.
static bool IsIllegalAddress(uword addr) {
return addr < 64*1024;
}
void HandleIllegalAccess(uword addr, Instr* instr);
// Handles a legal instruction that the simulator does not implement.
void UnimplementedInstruction(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);
// Perform a division.
void DoDivision(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);
// TODO(regis): Remove exclusive access support machinery if not needed.
// 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];
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);
// Executes ARM instructions until the PC reaches kEndSimulatingPC.
void Execute();
// 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 // VM_SIMULATOR_ARM_H_