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_ |