| Index: src/mips/simulator-mips.h
|
| diff --git a/src/mips/simulator-mips.h b/src/mips/simulator-mips.h
|
| index 6e42683a2eb71e68d9458c235d8ae78bf6129aa0..0cd9bbe75ca62b100842c818dacaed5a935839e8 100644
|
| --- a/src/mips/simulator-mips.h
|
| +++ b/src/mips/simulator-mips.h
|
| @@ -37,12 +37,31 @@
|
| #define V8_MIPS_SIMULATOR_MIPS_H_
|
|
|
| #include "allocation.h"
|
| +#include "constants-mips.h"
|
|
|
| -#if defined(__mips) && !defined(USE_SIMULATOR)
|
| +#if !defined(USE_SIMULATOR)
|
| +// Running without a simulator on a native mips platform.
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
|
|
| // When running without a simulator we call the entry directly.
|
| #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
|
| - entry(p0, p1, p2, p3, p4);
|
| + entry(p0, p1, p2, p3, p4)
|
| +
|
| +typedef int (*mips_regexp_matcher)(String*, int, const byte*, const byte*,
|
| + void*, int*, Address, int, Isolate*);
|
| +
|
| +// Call the generated regexp code directly. The code at the entry address
|
| +// should act as a function matching the type arm_regexp_matcher.
|
| +// The fifth argument is a dummy that reserves the space used for
|
| +// the return address added by the ExitFrame in native calls.
|
| +#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
|
| + (FUNCTION_CAST<mips_regexp_matcher>(entry)( \
|
| + p0, p1, p2, p3, NULL, p4, p5, p6, p7))
|
| +
|
| +#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
|
| + reinterpret_cast<TryCatch*>(try_catch_address)
|
|
|
| // The stack limit beyond which we will throw stack overflow errors in
|
| // generated code. Because generated code on mips uses the C stack, we
|
| @@ -60,6 +79,8 @@ class SimulatorStack : public v8::internal::AllStatic {
|
| static inline void UnregisterCTryCatch() { }
|
| };
|
|
|
| +} } // namespace v8::internal
|
| +
|
| // Calculated the stack limit beyond which we will throw stack overflow errors.
|
| // This macro must be called from a C++ method. It relies on being able to take
|
| // the address of "this" to get a value on the current execution stack and then
|
| @@ -70,39 +91,50 @@ class SimulatorStack : public v8::internal::AllStatic {
|
| (reinterpret_cast<uintptr_t>(this) >= limit ? \
|
| reinterpret_cast<uintptr_t>(this) - limit : 0)
|
|
|
| -// Call the generated regexp code directly. The entry function pointer should
|
| -// expect seven int/pointer sized arguments and return an int.
|
| -#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
|
| - entry(p0, p1, p2, p3, p4, p5, p6)
|
| -
|
| -#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
|
| - reinterpret_cast<TryCatch*>(try_catch_address)
|
| +#else // !defined(USE_SIMULATOR)
|
| +// Running with a simulator.
|
|
|
| +#include "hashmap.h"
|
|
|
| -#else // #if !defined(__mips) || defined(USE_SIMULATOR)
|
| +namespace v8 {
|
| +namespace internal {
|
|
|
| -// When running with the simulator transition into simulated execution at this
|
| -// point.
|
| -#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
|
| - reinterpret_cast<Object*>(\
|
| - assembler::mips::Simulator::current()->Call(FUNCTION_ADDR(entry), 5, \
|
| - p0, p1, p2, p3, p4))
|
| +// -----------------------------------------------------------------------------
|
| +// Utility functions
|
|
|
| -#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
|
| - assembler::mips::Simulator::current()->Call(\
|
| - FUNCTION_ADDR(entry), 7, p0, p1, p2, p3, p4, p5, p6)
|
| +class CachePage {
|
| + public:
|
| + static const int LINE_VALID = 0;
|
| + static const int LINE_INVALID = 1;
|
| +
|
| + static const int kPageShift = 12;
|
| + static const int kPageSize = 1 << kPageShift;
|
| + static const int kPageMask = kPageSize - 1;
|
| + static const int kLineShift = 2; // The cache line is only 4 bytes right now.
|
| + static const int kLineLength = 1 << kLineShift;
|
| + static const int kLineMask = kLineLength - 1;
|
| +
|
| + CachePage() {
|
| + memset(&validity_map_, LINE_INVALID, sizeof(validity_map_));
|
| + }
|
|
|
| -#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
|
| - try_catch_address == NULL ? \
|
| - NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
|
| + char* ValidityByte(int offset) {
|
| + return &validity_map_[offset >> kLineShift];
|
| + }
|
|
|
| + char* CachedData(int offset) {
|
| + return &data_[offset];
|
| + }
|
|
|
| -namespace assembler {
|
| -namespace mips {
|
| + private:
|
| + char data_[kPageSize]; // The cached data.
|
| + static const int kValidityMapSize = kPageSize >> kLineShift;
|
| + char validity_map_[kValidityMapSize]; // One byte per line.
|
| +};
|
|
|
| class Simulator {
|
| public:
|
| - friend class Debugger;
|
| + friend class MipsDebugger;
|
|
|
| // Registers are declared in order. See SMRL chapter 2.
|
| enum Register {
|
| @@ -143,7 +175,7 @@ class Simulator {
|
|
|
| // The currently executing Simulator instance. Potentially there can be one
|
| // for each native thread.
|
| - static Simulator* current();
|
| + static Simulator* current(v8::internal::Isolate* isolate);
|
|
|
| // Accessors for register state. Reading the pc value adheres to the MIPS
|
| // architecture specification and is off by a 8 from the currently executing
|
| @@ -152,9 +184,15 @@ class Simulator {
|
| int32_t get_register(int reg) const;
|
| // Same for FPURegisters
|
| void set_fpu_register(int fpureg, int32_t value);
|
| + void set_fpu_register_float(int fpureg, float value);
|
| void set_fpu_register_double(int fpureg, double value);
|
| int32_t get_fpu_register(int fpureg) const;
|
| + int64_t get_fpu_register_long(int fpureg) const;
|
| + float get_fpu_register_float(int fpureg) const;
|
| double get_fpu_register_double(int fpureg) const;
|
| + void set_fcsr_bit(uint32_t cc, bool value);
|
| + bool test_fcsr_bit(uint32_t cc);
|
| + bool set_fcsr_round_error(double original, double rounded);
|
|
|
| // Special case of set_register and get_register to access the raw PC value.
|
| void set_pc(int32_t value);
|
| @@ -172,7 +210,7 @@ class Simulator {
|
| // V8 generally calls into generated JS code with 5 parameters and into
|
| // generated RegExp code with 7 parameters. This is a convenience function,
|
| // which sets up the simulator state and grabs the result on return.
|
| - int32_t Call(byte_* entry, int argument_count, ...);
|
| + int32_t Call(byte* entry, int argument_count, ...);
|
|
|
| // Push an address onto the JS stack.
|
| uintptr_t PushAddress(uintptr_t address);
|
| @@ -180,6 +218,14 @@ class Simulator {
|
| // Pop an address from the JS stack.
|
| uintptr_t PopAddress();
|
|
|
| + // ICache checking.
|
| + static void FlushICache(v8::internal::HashMap* i_cache, void* start,
|
| + size_t size);
|
| +
|
| + // Returns true if pc register contains one of the 'special_values' defined
|
| + // below (bad_ra, end_sim_pc).
|
| + bool has_bad_pc() const;
|
| +
|
| private:
|
| enum special_values {
|
| // Known bad pc value to ensure that the simulator does not execute
|
| @@ -223,9 +269,17 @@ class Simulator {
|
| inline int32_t SetDoubleHIW(double* addr);
|
| inline int32_t SetDoubleLOW(double* addr);
|
|
|
| -
|
| // Executing is handled based on the instruction type.
|
| void DecodeTypeRegister(Instruction* instr);
|
| +
|
| + // Helper function for DecodeTypeRegister.
|
| + void ConfigureTypeRegister(Instruction* instr,
|
| + int32_t& alu_out,
|
| + int64_t& i64hilo,
|
| + uint64_t& u64hilo,
|
| + int32_t& next_pc,
|
| + bool& do_interrupt);
|
| +
|
| void DecodeTypeImmediate(Instruction* instr);
|
| void DecodeTypeJump(Instruction* instr);
|
|
|
| @@ -239,11 +293,18 @@ class Simulator {
|
| if (instr->IsForbiddenInBranchDelay()) {
|
| V8_Fatal(__FILE__, __LINE__,
|
| "Eror:Unexpected %i opcode in a branch delay slot.",
|
| - instr->OpcodeField());
|
| + instr->OpcodeValue());
|
| }
|
| InstructionDecode(instr);
|
| }
|
|
|
| + // ICache.
|
| + static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
|
| + static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
|
| + int size);
|
| + static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
|
| +
|
| +
|
| enum Exception {
|
| none,
|
| kIntegerOverflow,
|
| @@ -258,7 +319,7 @@ class Simulator {
|
|
|
| // Runtime call support.
|
| static void* RedirectExternalReference(void* external_function,
|
| - bool fp_return);
|
| + ExternalReference::Type type);
|
|
|
| // Used for real time calls that takes two double values as arguments and
|
| // returns a double.
|
| @@ -269,19 +330,40 @@ class Simulator {
|
| int32_t registers_[kNumSimuRegisters];
|
| // Coprocessor Registers.
|
| int32_t FPUregisters_[kNumFPURegisters];
|
| + // FPU control register.
|
| + uint32_t FCSR_;
|
|
|
| // Simulator support.
|
| char* stack_;
|
| + size_t stack_size_;
|
| bool pc_modified_;
|
| int icount_;
|
| - static bool initialized_;
|
| + int break_count_;
|
| +
|
| + // Icache simulation
|
| + v8::internal::HashMap* i_cache_;
|
|
|
| // Registered breakpoints.
|
| Instruction* break_pc_;
|
| Instr break_instr_;
|
| +
|
| + v8::internal::Isolate* isolate_;
|
| };
|
|
|
| -} } // namespace assembler::mips
|
| +
|
| +// When running with the simulator transition into simulated execution at this
|
| +// point.
|
| +#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
|
| +reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->Call( \
|
| + FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4))
|
| +
|
| +#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
|
| + Simulator::current(Isolate::Current())->Call( \
|
| + entry, 9, p0, p1, p2, p3, NULL, p4, p5, p6, p7)
|
| +
|
| +#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
|
| + try_catch_address == NULL ? \
|
| + NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
|
|
|
|
|
| // The simulator has its own stack. Thus it has a different stack limit from
|
| @@ -292,20 +374,21 @@ class Simulator {
|
| class SimulatorStack : public v8::internal::AllStatic {
|
| public:
|
| static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) {
|
| - return assembler::mips::Simulator::current()->StackLimit();
|
| + return Simulator::current(Isolate::Current())->StackLimit();
|
| }
|
|
|
| static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
|
| - assembler::mips::Simulator* sim = assembler::mips::Simulator::current();
|
| + Simulator* sim = Simulator::current(Isolate::Current());
|
| return sim->PushAddress(try_catch_address);
|
| }
|
|
|
| static inline void UnregisterCTryCatch() {
|
| - assembler::mips::Simulator::current()->PopAddress();
|
| + Simulator::current(Isolate::Current())->PopAddress();
|
| }
|
| };
|
|
|
| -#endif // !defined(__mips) || defined(USE_SIMULATOR)
|
| +} } // namespace v8::internal
|
|
|
| +#endif // !defined(USE_SIMULATOR)
|
| #endif // V8_MIPS_SIMULATOR_MIPS_H_
|
|
|
|
|