183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org// Copyright 2011 the V8 project authors. All rights reserved. 23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be 33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file. 45c838251403b0be9a882540f1922577abba4c872ager@chromium.org 55c838251403b0be9a882540f1922577abba4c872ager@chromium.org 65c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Declares a Simulator for MIPS instructions if we are not generating a native 75c838251403b0be9a882540f1922577abba4c872ager@chromium.org// MIPS binary. This Simulator allows us to run and debug MIPS code generation 85c838251403b0be9a882540f1922577abba4c872ager@chromium.org// on regular desktop machines. 95c838251403b0be9a882540f1922577abba4c872ager@chromium.org// V8 calls into generated code by "calling" the CALL_GENERATED_CODE macro, 105c838251403b0be9a882540f1922577abba4c872ager@chromium.org// which will start execution in the Simulator or forwards to the real entry 115c838251403b0be9a882540f1922577abba4c872ager@chromium.org// on a MIPS HW platform. 125c838251403b0be9a882540f1922577abba4c872ager@chromium.org 135c838251403b0be9a882540f1922577abba4c872ager@chromium.org#ifndef V8_MIPS_SIMULATOR_MIPS_H_ 145c838251403b0be9a882540f1922577abba4c872ager@chromium.org#define V8_MIPS_SIMULATOR_MIPS_H_ 155c838251403b0be9a882540f1922577abba4c872ager@chromium.org 16196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/allocation.h" 17196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/mips/constants-mips.h" 185c838251403b0be9a882540f1922577abba4c872ager@chromium.org 197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org#if !defined(USE_SIMULATOR) 207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// Running without a simulator on a native mips platform. 217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgnamespace v8 { 237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgnamespace internal { 245c838251403b0be9a882540f1922577abba4c872ager@chromium.org 255c838251403b0be9a882540f1922577abba4c872ager@chromium.org// When running without a simulator we call the entry directly. 265c838251403b0be9a882540f1922577abba4c872ager@chromium.org#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \ 277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org entry(p0, p1, p2, p3, p4) 287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgtypedef int (*mips_regexp_matcher)(String*, int, const byte*, const byte*, 30777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org void*, int*, int, Address, int, Isolate*); 3183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// Call the generated regexp code directly. The code at the entry address 347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// should act as a function matching the type arm_regexp_matcher. 357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// The fifth argument is a dummy that reserves the space used for 367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// the return address added by the ExitFrame in native calls. 37777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \ 3840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org (FUNCTION_CAST<mips_regexp_matcher>(entry)( \ 39777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8)) 407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 415c838251403b0be9a882540f1922577abba4c872ager@chromium.org// The stack limit beyond which we will throw stack overflow errors in 425c838251403b0be9a882540f1922577abba4c872ager@chromium.org// generated code. Because generated code on mips uses the C stack, we 435c838251403b0be9a882540f1922577abba4c872ager@chromium.org// just use the C stack limit. 445c838251403b0be9a882540f1922577abba4c872ager@chromium.orgclass SimulatorStack : public v8::internal::AllStatic { 455c838251403b0be9a882540f1922577abba4c872ager@chromium.org public: 461c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org static inline uintptr_t JsLimitFromCLimit(Isolate* isolate, 471c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org uintptr_t c_limit) { 485c838251403b0be9a882540f1922577abba4c872ager@chromium.org return c_limit; 495c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 505c838251403b0be9a882540f1922577abba4c872ager@chromium.org 515c838251403b0be9a882540f1922577abba4c872ager@chromium.org static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) { 525c838251403b0be9a882540f1922577abba4c872ager@chromium.org return try_catch_address; 535c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 545c838251403b0be9a882540f1922577abba4c872ager@chromium.org 555c838251403b0be9a882540f1922577abba4c872ager@chromium.org static inline void UnregisterCTryCatch() { } 565c838251403b0be9a882540f1922577abba4c872ager@chromium.org}; 575c838251403b0be9a882540f1922577abba4c872ager@chromium.org 587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org} } // namespace v8::internal 597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 605c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Calculated the stack limit beyond which we will throw stack overflow errors. 615c838251403b0be9a882540f1922577abba4c872ager@chromium.org// This macro must be called from a C++ method. It relies on being able to take 625c838251403b0be9a882540f1922577abba4c872ager@chromium.org// the address of "this" to get a value on the current execution stack and then 635c838251403b0be9a882540f1922577abba4c872ager@chromium.org// calculates the stack limit based on that value. 645c838251403b0be9a882540f1922577abba4c872ager@chromium.org// NOTE: The check for overflow is not safe as there is no guarantee that the 655c838251403b0be9a882540f1922577abba4c872ager@chromium.org// running thread has its stack in all memory up to address 0x00000000. 665c838251403b0be9a882540f1922577abba4c872ager@chromium.org#define GENERATED_CODE_STACK_LIMIT(limit) \ 675c838251403b0be9a882540f1922577abba4c872ager@chromium.org (reinterpret_cast<uintptr_t>(this) >= limit ? \ 685c838251403b0be9a882540f1922577abba4c872ager@chromium.org reinterpret_cast<uintptr_t>(this) - limit : 0) 695c838251403b0be9a882540f1922577abba4c872ager@chromium.org 707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org#else // !defined(USE_SIMULATOR) 717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// Running with a simulator. 725c838251403b0be9a882540f1922577abba4c872ager@chromium.org 73196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/assembler.h" 744b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/hashmap.h" 755c838251403b0be9a882540f1922577abba4c872ager@chromium.org 767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgnamespace v8 { 777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgnamespace internal { 785c838251403b0be9a882540f1922577abba4c872ager@chromium.org 797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// ----------------------------------------------------------------------------- 807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// Utility functions 815c838251403b0be9a882540f1922577abba4c872ager@chromium.org 827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgclass CachePage { 837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org public: 847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int LINE_VALID = 0; 857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int LINE_INVALID = 1; 867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kPageShift = 12; 887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kPageSize = 1 << kPageShift; 897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kPageMask = kPageSize - 1; 907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kLineShift = 2; // The cache line is only 4 bytes right now. 917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kLineLength = 1 << kLineShift; 927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kLineMask = kLineLength - 1; 937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org CachePage() { 957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org memset(&validity_map_, LINE_INVALID, sizeof(validity_map_)); 967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 975c838251403b0be9a882540f1922577abba4c872ager@chromium.org 987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org char* ValidityByte(int offset) { 997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org return &validity_map_[offset >> kLineShift]; 1007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 1015c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org char* CachedData(int offset) { 1037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org return &data_[offset]; 1047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 1055c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org private: 1077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org char data_[kPageSize]; // The cached data. 1087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static const int kValidityMapSize = kPageSize >> kLineShift; 1097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org char validity_map_[kValidityMapSize]; // One byte per line. 1107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}; 1115c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1125c838251403b0be9a882540f1922577abba4c872ager@chromium.orgclass Simulator { 1135c838251403b0be9a882540f1922577abba4c872ager@chromium.org public: 1147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org friend class MipsDebugger; 1155c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1165c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Registers are declared in order. See SMRL chapter 2. 1175c838251403b0be9a882540f1922577abba4c872ager@chromium.org enum Register { 1185c838251403b0be9a882540f1922577abba4c872ager@chromium.org no_reg = -1, 1195c838251403b0be9a882540f1922577abba4c872ager@chromium.org zero_reg = 0, 1205c838251403b0be9a882540f1922577abba4c872ager@chromium.org at, 1215c838251403b0be9a882540f1922577abba4c872ager@chromium.org v0, v1, 1225c838251403b0be9a882540f1922577abba4c872ager@chromium.org a0, a1, a2, a3, 1235c838251403b0be9a882540f1922577abba4c872ager@chromium.org t0, t1, t2, t3, t4, t5, t6, t7, 1245c838251403b0be9a882540f1922577abba4c872ager@chromium.org s0, s1, s2, s3, s4, s5, s6, s7, 1255c838251403b0be9a882540f1922577abba4c872ager@chromium.org t8, t9, 1265c838251403b0be9a882540f1922577abba4c872ager@chromium.org k0, k1, 1275c838251403b0be9a882540f1922577abba4c872ager@chromium.org gp, 1285c838251403b0be9a882540f1922577abba4c872ager@chromium.org sp, 1295c838251403b0be9a882540f1922577abba4c872ager@chromium.org s8, 1305c838251403b0be9a882540f1922577abba4c872ager@chromium.org ra, 13183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // LO, HI, and pc. 1325c838251403b0be9a882540f1922577abba4c872ager@chromium.org LO, 1335c838251403b0be9a882540f1922577abba4c872ager@chromium.org HI, 1345c838251403b0be9a882540f1922577abba4c872ager@chromium.org pc, // pc must be the last register. 1355c838251403b0be9a882540f1922577abba4c872ager@chromium.org kNumSimuRegisters, 1365c838251403b0be9a882540f1922577abba4c872ager@chromium.org // aliases 1375c838251403b0be9a882540f1922577abba4c872ager@chromium.org fp = s8 1385c838251403b0be9a882540f1922577abba4c872ager@chromium.org }; 1395c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1405c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Coprocessor registers. 1415c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Generated code will always use doubles. So we will only use even registers. 1425c838251403b0be9a882540f1922577abba4c872ager@chromium.org enum FPURegister { 1435c838251403b0be9a882540f1922577abba4c872ager@chromium.org f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, 14483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org f12, f13, f14, f15, // f12 and f14 are arguments FPURegisters. 1455c838251403b0be9a882540f1922577abba4c872ager@chromium.org f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, 1465c838251403b0be9a882540f1922577abba4c872ager@chromium.org f26, f27, f28, f29, f30, f31, 1475c838251403b0be9a882540f1922577abba4c872ager@chromium.org kNumFPURegisters 1485c838251403b0be9a882540f1922577abba4c872ager@chromium.org }; 1495c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1501c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org explicit Simulator(Isolate* isolate); 1515c838251403b0be9a882540f1922577abba4c872ager@chromium.org ~Simulator(); 1525c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1535c838251403b0be9a882540f1922577abba4c872ager@chromium.org // The currently executing Simulator instance. Potentially there can be one 1545c838251403b0be9a882540f1922577abba4c872ager@chromium.org // for each native thread. 1557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static Simulator* current(v8::internal::Isolate* isolate); 1565c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1575c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Accessors for register state. Reading the pc value adheres to the MIPS 1585c838251403b0be9a882540f1922577abba4c872ager@chromium.org // architecture specification and is off by a 8 from the currently executing 1595c838251403b0be9a882540f1922577abba4c872ager@chromium.org // instruction. 1605c838251403b0be9a882540f1922577abba4c872ager@chromium.org void set_register(int reg, int32_t value); 16183130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org void set_dw_register(int dreg, const int* dbl); 1625c838251403b0be9a882540f1922577abba4c872ager@chromium.org int32_t get_register(int reg) const; 16383130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org double get_double_from_register_pair(int reg); 16483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // Same for FPURegisters. 1655e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org void set_fpu_register(int fpureg, int64_t value); 1665e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org void set_fpu_register_word(int fpureg, int32_t value); 1675e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org void set_fpu_register_hi_word(int fpureg, int32_t value); 1687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void set_fpu_register_float(int fpureg, float value); 1695c838251403b0be9a882540f1922577abba4c872ager@chromium.org void set_fpu_register_double(int fpureg, double value); 1705e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org int64_t get_fpu_register(int fpureg) const; 1715e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org int32_t get_fpu_register_word(int fpureg) const; 1725e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org int32_t get_fpu_register_signed_word(int fpureg) const; 1735e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org int32_t get_fpu_register_hi_word(int fpureg) const; 1747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org float get_fpu_register_float(int fpureg) const; 1755c838251403b0be9a882540f1922577abba4c872ager@chromium.org double get_fpu_register_double(int fpureg) const; 1767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void set_fcsr_bit(uint32_t cc, bool value); 1777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org bool test_fcsr_bit(uint32_t cc); 1787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org bool set_fcsr_round_error(double original, double rounded); 1795c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1805c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Special case of set_register and get_register to access the raw PC value. 1815c838251403b0be9a882540f1922577abba4c872ager@chromium.org void set_pc(int32_t value); 1825c838251403b0be9a882540f1922577abba4c872ager@chromium.org int32_t get_pc() const; 1835c838251403b0be9a882540f1922577abba4c872ager@chromium.org 184f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Address get_sp() { 185f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return reinterpret_cast<Address>(static_cast<intptr_t>(get_register(sp))); 186f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1885c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Accessor to the internal simulator stack area. 1895c838251403b0be9a882540f1922577abba4c872ager@chromium.org uintptr_t StackLimit() const; 1905c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1915c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Executes MIPS instructions until the PC reaches end_sim_pc. 1925c838251403b0be9a882540f1922577abba4c872ager@chromium.org void Execute(); 1935c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1945c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Call on program start. 1951c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org static void Initialize(Isolate* isolate); 1965c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1975c838251403b0be9a882540f1922577abba4c872ager@chromium.org // V8 generally calls into generated JS code with 5 parameters and into 1985c838251403b0be9a882540f1922577abba4c872ager@chromium.org // generated RegExp code with 7 parameters. This is a convenience function, 1995c838251403b0be9a882540f1922577abba4c872ager@chromium.org // which sets up the simulator state and grabs the result on return. 2007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int32_t Call(byte* entry, int argument_count, ...); 20183130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org // Alternative: call a 2-argument double function. 20283130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org double CallFP(byte* entry, double d0, double d1); 2035c838251403b0be9a882540f1922577abba4c872ager@chromium.org 2045c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Push an address onto the JS stack. 2055c838251403b0be9a882540f1922577abba4c872ager@chromium.org uintptr_t PushAddress(uintptr_t address); 2065c838251403b0be9a882540f1922577abba4c872ager@chromium.org 2075c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Pop an address from the JS stack. 2085c838251403b0be9a882540f1922577abba4c872ager@chromium.org uintptr_t PopAddress(); 2095c838251403b0be9a882540f1922577abba4c872ager@chromium.org 210c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org // Debugger input. 211c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org void set_last_debugger_input(char* input); 212c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org char* last_debugger_input() { return last_debugger_input_; } 213c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org 2147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // ICache checking. 2157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static void FlushICache(v8::internal::HashMap* i_cache, void* start, 2167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org size_t size); 2177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 2187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Returns true if pc register contains one of the 'special_values' defined 2197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // below (bad_ra, end_sim_pc). 2207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org bool has_bad_pc() const; 2217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 2225c838251403b0be9a882540f1922577abba4c872ager@chromium.org private: 2235c838251403b0be9a882540f1922577abba4c872ager@chromium.org enum special_values { 2245c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Known bad pc value to ensure that the simulator does not execute 2255c838251403b0be9a882540f1922577abba4c872ager@chromium.org // without being properly setup. 2265c838251403b0be9a882540f1922577abba4c872ager@chromium.org bad_ra = -1, 2275c838251403b0be9a882540f1922577abba4c872ager@chromium.org // A pc value used to signal the simulator to stop execution. Generally 2285c838251403b0be9a882540f1922577abba4c872ager@chromium.org // the ra is set to this value on transition from native C code to 2295c838251403b0be9a882540f1922577abba4c872ager@chromium.org // simulated execution, so that the simulator can "return" to the native 2305c838251403b0be9a882540f1922577abba4c872ager@chromium.org // C code. 2315c838251403b0be9a882540f1922577abba4c872ager@chromium.org end_sim_pc = -2, 2325c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Unpredictable value. 2335c838251403b0be9a882540f1922577abba4c872ager@chromium.org Unpredictable = 0xbadbeaf 2345c838251403b0be9a882540f1922577abba4c872ager@chromium.org }; 2355c838251403b0be9a882540f1922577abba4c872ager@chromium.org 2365c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Unsupported instructions use Format to print an error and stop execution. 2375c838251403b0be9a882540f1922577abba4c872ager@chromium.org void Format(Instruction* instr, const char* format); 2385c838251403b0be9a882540f1922577abba4c872ager@chromium.org 2395c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Read and write memory. 2405c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline uint32_t ReadBU(int32_t addr); 2415c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline int32_t ReadB(int32_t addr); 2425c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline void WriteB(int32_t addr, uint8_t value); 2435c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline void WriteB(int32_t addr, int8_t value); 2445c838251403b0be9a882540f1922577abba4c872ager@chromium.org 2455c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline uint16_t ReadHU(int32_t addr, Instruction* instr); 2465c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline int16_t ReadH(int32_t addr, Instruction* instr); 2475c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Note: Overloaded on the sign of the value. 2485c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline void WriteH(int32_t addr, uint16_t value, Instruction* instr); 2495c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline void WriteH(int32_t addr, int16_t value, Instruction* instr); 2505c838251403b0be9a882540f1922577abba4c872ager@chromium.org 2515c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline int ReadW(int32_t addr, Instruction* instr); 2525c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline void WriteW(int32_t addr, int value, Instruction* instr); 2535c838251403b0be9a882540f1922577abba4c872ager@chromium.org 2545c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline double ReadD(int32_t addr, Instruction* instr); 2555c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline void WriteD(int32_t addr, double value, Instruction* instr); 2565c838251403b0be9a882540f1922577abba4c872ager@chromium.org 2575c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Operations depending on endianness. 2585c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Get Double Higher / Lower word. 2595c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline int32_t GetDoubleHIW(double* addr); 2605c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline int32_t GetDoubleLOW(double* addr); 2615c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Set Double Higher / Lower word. 2625c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline int32_t SetDoubleHIW(double* addr); 2635c838251403b0be9a882540f1922577abba4c872ager@chromium.org inline int32_t SetDoubleLOW(double* addr); 2645c838251403b0be9a882540f1922577abba4c872ager@chromium.org 2655c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Executing is handled based on the instruction type. 2665c838251403b0be9a882540f1922577abba4c872ager@chromium.org void DecodeTypeRegister(Instruction* instr); 2677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 2687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Helper function for DecodeTypeRegister. 2697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org void ConfigureTypeRegister(Instruction* instr, 270196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org int32_t* alu_out, 271196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org int64_t* i64hilo, 272196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org uint64_t* u64hilo, 273196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org int32_t* next_pc, 274196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org int32_t* return_addr_reg, 275196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org bool* do_interrupt); 2767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 2775c838251403b0be9a882540f1922577abba4c872ager@chromium.org void DecodeTypeImmediate(Instruction* instr); 2785c838251403b0be9a882540f1922577abba4c872ager@chromium.org void DecodeTypeJump(Instruction* instr); 2795c838251403b0be9a882540f1922577abba4c872ager@chromium.org 2805c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Used for breakpoints and traps. 2815c838251403b0be9a882540f1922577abba4c872ager@chromium.org void SoftwareInterrupt(Instruction* instr); 2825c838251403b0be9a882540f1922577abba4c872ager@chromium.org 283c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org // Stop helper functions. 284c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org bool IsWatchpoint(uint32_t code); 285c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org void PrintWatchpoint(uint32_t code); 286c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org void HandleStop(uint32_t code, Instruction* instr); 287c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org bool IsStopInstruction(Instruction* instr); 288c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org bool IsEnabledStop(uint32_t code); 289c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org void EnableStop(uint32_t code); 290c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org void DisableStop(uint32_t code); 291c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org void IncreaseStopCounter(uint32_t code); 292c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org void PrintStopInfo(uint32_t code); 293c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org 294c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org 2955c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Executes one instruction. 2965c838251403b0be9a882540f1922577abba4c872ager@chromium.org void InstructionDecode(Instruction* instr); 2975c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Execute one instruction placed in a branch delay slot. 2985c838251403b0be9a882540f1922577abba4c872ager@chromium.org void BranchDelayInstructionDecode(Instruction* instr) { 2996ff651481ed0a881f176f6d55e26679ca359792bulan@chromium.org if (instr->InstructionBits() == nopInstr) { 3006ff651481ed0a881f176f6d55e26679ca359792bulan@chromium.org // Short-cut generic nop instructions. They are always valid and they 3016ff651481ed0a881f176f6d55e26679ca359792bulan@chromium.org // never change the simulator state. 3026ff651481ed0a881f176f6d55e26679ca359792bulan@chromium.org return; 3036ff651481ed0a881f176f6d55e26679ca359792bulan@chromium.org } 3046ff651481ed0a881f176f6d55e26679ca359792bulan@chromium.org 3055c838251403b0be9a882540f1922577abba4c872ager@chromium.org if (instr->IsForbiddenInBranchDelay()) { 3065c838251403b0be9a882540f1922577abba4c872ager@chromium.org V8_Fatal(__FILE__, __LINE__, 3075c838251403b0be9a882540f1922577abba4c872ager@chromium.org "Eror:Unexpected %i opcode in a branch delay slot.", 3087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org instr->OpcodeValue()); 3095c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 3105c838251403b0be9a882540f1922577abba4c872ager@chromium.org InstructionDecode(instr); 3115c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 3125c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // ICache. 3147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr); 3157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start, 3167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int size); 3177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page); 3187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 3195c838251403b0be9a882540f1922577abba4c872ager@chromium.org enum Exception { 3205c838251403b0be9a882540f1922577abba4c872ager@chromium.org none, 3215c838251403b0be9a882540f1922577abba4c872ager@chromium.org kIntegerOverflow, 3225c838251403b0be9a882540f1922577abba4c872ager@chromium.org kIntegerUnderflow, 3235c838251403b0be9a882540f1922577abba4c872ager@chromium.org kDivideByZero, 3245c838251403b0be9a882540f1922577abba4c872ager@chromium.org kNumExceptions 3255c838251403b0be9a882540f1922577abba4c872ager@chromium.org }; 3265c838251403b0be9a882540f1922577abba4c872ager@chromium.org int16_t exceptions[kNumExceptions]; 3275c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3285c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Exceptions. 3295c838251403b0be9a882540f1922577abba4c872ager@chromium.org void SignalExceptions(); 3305c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3315c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Runtime call support. 3325c838251403b0be9a882540f1922577abba4c872ager@chromium.org static void* RedirectExternalReference(void* external_function, 3337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org ExternalReference::Type type); 3345c838251403b0be9a882540f1922577abba4c872ager@chromium.org 335e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Handle arguments and return value for runtime FP functions. 336e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org void GetFpArgs(double* x, double* y, int32_t* z); 33740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org void SetFpResult(const double& result); 33840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org 33983130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org void CallInternal(byte* entry); 3405c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3415c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Architecture state. 3425c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Registers. 3435c838251403b0be9a882540f1922577abba4c872ager@chromium.org int32_t registers_[kNumSimuRegisters]; 3445c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Coprocessor Registers. 3455e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org // Note: FP32 mode uses only the lower 32-bit part of each element, 3465e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org // the upper 32-bit is unpredictable. 3475e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org int64_t FPUregisters_[kNumFPURegisters]; 3487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // FPU control register. 3497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org uint32_t FCSR_; 3505c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3515c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Simulator support. 35283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // Allocate 1MB for stack. 35383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org static const size_t stack_size_ = 1 * 1024*1024; 3545c838251403b0be9a882540f1922577abba4c872ager@chromium.org char* stack_; 3555c838251403b0be9a882540f1922577abba4c872ager@chromium.org bool pc_modified_; 3565c838251403b0be9a882540f1922577abba4c872ager@chromium.org int icount_; 3577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org int break_count_; 3587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 359c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org // Debugger input. 360c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org char* last_debugger_input_; 361c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org 36283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // Icache simulation. 3637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org v8::internal::HashMap* i_cache_; 3645c838251403b0be9a882540f1922577abba4c872ager@chromium.org 36583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org v8::internal::Isolate* isolate_; 36683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 3675c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Registered breakpoints. 3685c838251403b0be9a882540f1922577abba4c872ager@chromium.org Instruction* break_pc_; 3695c838251403b0be9a882540f1922577abba4c872ager@chromium.org Instr break_instr_; 370c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org 371c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org // Stop is disabled if bit 31 is set. 372c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org static const uint32_t kStopDisabledBit = 1 << 31; 373c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org 374c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org // A stop is enabled, meaning the simulator will stop when meeting the 375f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org // instruction, if bit 31 of watched_stops_[code].count is unset. 376f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org // The value watched_stops_[code].count & ~(1 << 31) indicates how many times 377c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org // the breakpoint was hit or gone through. 378c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org struct StopCountAndDesc { 379c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org uint32_t count; 380c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org char* desc; 381c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org }; 382f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org StopCountAndDesc watched_stops_[kMaxStopCode + 1]; 3835c838251403b0be9a882540f1922577abba4c872ager@chromium.org}; 3845c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 3867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// When running with the simulator transition into simulated execution at this 3877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// point. 3887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \ 38983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->Call( \ 3907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4)) 3917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 392777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \ 39383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org Simulator::current(Isolate::Current())->Call( \ 394777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8) 3957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 3965c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3975c838251403b0be9a882540f1922577abba4c872ager@chromium.org// The simulator has its own stack. Thus it has a different stack limit from 3985c838251403b0be9a882540f1922577abba4c872ager@chromium.org// the C-based native code. Setting the c_limit to indicate a very small 3995c838251403b0be9a882540f1922577abba4c872ager@chromium.org// stack cause stack overflow errors, since the simulator ignores the input. 4005c838251403b0be9a882540f1922577abba4c872ager@chromium.org// This is unlikely to be an issue in practice, though it might cause testing 4015c838251403b0be9a882540f1922577abba4c872ager@chromium.org// trouble down the line. 4025c838251403b0be9a882540f1922577abba4c872ager@chromium.orgclass SimulatorStack : public v8::internal::AllStatic { 4035c838251403b0be9a882540f1922577abba4c872ager@chromium.org public: 4041c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org static inline uintptr_t JsLimitFromCLimit(Isolate* isolate, 4051c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org uintptr_t c_limit) { 4061c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org return Simulator::current(isolate)->StackLimit(); 4075c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 4085c838251403b0be9a882540f1922577abba4c872ager@chromium.org 4095c838251403b0be9a882540f1922577abba4c872ager@chromium.org static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) { 4107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org Simulator* sim = Simulator::current(Isolate::Current()); 4115c838251403b0be9a882540f1922577abba4c872ager@chromium.org return sim->PushAddress(try_catch_address); 4125c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 4135c838251403b0be9a882540f1922577abba4c872ager@chromium.org 4145c838251403b0be9a882540f1922577abba4c872ager@chromium.org static inline void UnregisterCTryCatch() { 4157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org Simulator::current(Isolate::Current())->PopAddress(); 4165c838251403b0be9a882540f1922577abba4c872ager@chromium.org } 4175c838251403b0be9a882540f1922577abba4c872ager@chromium.org}; 4185c838251403b0be9a882540f1922577abba4c872ager@chromium.org 4197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org} } // namespace v8::internal 4205c838251403b0be9a882540f1922577abba4c872ager@chromium.org 4217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org#endif // !defined(USE_SIMULATOR) 4225c838251403b0be9a882540f1922577abba4c872ager@chromium.org#endif // V8_MIPS_SIMULATOR_MIPS_H_ 423