1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Declares a Simulator for ARM instructions if we are not generating a native 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ARM binary. This Simulator allows us to run and debug ARM code generation on 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// regular desktop machines. 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// V8 calls into generated code by "calling" the CALL_GENERATED_CODE macro, 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// which will start execution in the Simulator or forwards to the real entry 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// on a ARM HW platform. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_ARM_SIMULATOR_ARM_H_ 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_ARM_SIMULATOR_ARM_H_ 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/allocation.h" 1762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/base/lazy-instance.h" 1862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/base/platform/mutex.h" 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 205913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#if !defined(USE_SIMULATOR) 215913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck// Running without a simulator on a native arm platform. 225913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 235913587db4c6bab03d97bfe44b06289fd6d7270dJohn Recknamespace v8 { 245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Recknamespace internal { 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// When running without a simulator we call the entry directly. 27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (entry(p0, p1, p2, p3, p4)) 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochtypedef int (*arm_regexp_matcher)(String*, int, const byte*, const byte*, 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void*, int*, int, Address, int, Isolate*); 32e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 33e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 34e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Call the generated regexp code directly. The code at the entry address 35e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// should act as a function matching the type arm_regexp_matcher. 36e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// The fifth argument is a dummy that reserves the space used for 37e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// the return address added by the ExitFrame in native calls. 38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \ 39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch p7, p8) \ 40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch (FUNCTION_CAST<arm_regexp_matcher>(entry)(p0, p1, p2, p3, NULL, p4, p5, p6, \ 41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch p7, p8)) 425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The stack limit beyond which we will throw stack overflow errors in 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// generated code. Because generated code on arm uses the C stack, we 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// just use the C stack limit. 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass SimulatorStack : public v8::internal::AllStatic { 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 48257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate, 49257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uintptr_t c_limit) { 50257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch USE(isolate); 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return c_limit; 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 53d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static inline uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate, 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uintptr_t try_catch_address) { 56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch USE(isolate); 57d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return try_catch_address; 58d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 59d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static inline void UnregisterCTryCatch(v8::internal::Isolate* isolate) { 61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch USE(isolate); 62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#else // !defined(USE_SIMULATOR) 695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck// Running with a simulator. 70d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/constants-arm.h" 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/assembler.h" 7313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/base/hashmap.h" 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blocknamespace v8 { 761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blocknamespace internal { 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 786ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CachePage { 796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int LINE_VALID = 0; 816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int LINE_INVALID = 1; 826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kPageShift = 12; 846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kPageSize = 1 << kPageShift; 856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kPageMask = kPageSize - 1; 866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kLineShift = 2; // The cache line is only 4 bytes right now. 876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kLineLength = 1 << kLineShift; 886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kLineMask = kLineLength - 1; 896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CachePage() { 916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block memset(&validity_map_, LINE_INVALID, sizeof(validity_map_)); 926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block char* ValidityByte(int offset) { 956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return &validity_map_[offset >> kLineShift]; 966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block char* CachedData(int offset) { 996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return &data_[offset]; 1006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 1036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block char data_[kPageSize]; // The cached data. 1046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kValidityMapSize = kPageSize >> kLineShift; 1056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block char validity_map_[kValidityMapSize]; // One byte per line. 1066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 1076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Simulator { 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block friend class ArmDebugger; 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum Register { 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block no_reg = -1, 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r0 = 0, r1, r2, r3, r4, r5, r6, r7, 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r8, r9, r10, r11, r12, r13, r14, r15, 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_registers, 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sp = 13, 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lr = 14, 119d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pc = 15, 120d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block s0 = 0, s1, s2, s3, s4, s5, s6, s7, 121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block s8, s9, s10, s11, s12, s13, s14, s15, 122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block s16, s17, s18, s19, s20, s21, s22, s23, 123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block s24, s25, s26, s27, s28, s29, s30, s31, 124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block num_s_registers = 32, 125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block d0 = 0, d1, d2, d3, d4, d5, d6, d7, 126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block d8, d9, d10, d11, d12, d13, d14, d15, 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch d16, d17, d18, d19, d20, d21, d22, d23, 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch d24, d25, d26, d27, d28, d29, d30, d31, 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch num_d_registers = 32, 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch q0 = 0, q1, q2, q3, q4, q5, q6, q7, 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch q8, q9, q10, q11, q12, q13, q14, q15, 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch num_q_registers = 16 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch explicit Simulator(Isolate* isolate); 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~Simulator(); 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The currently executing Simulator instance. Potentially there can be one 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for each native thread. 14044f0eee88ff00398ff7f715fab053374d808c90dSteve Block static Simulator* current(v8::internal::Isolate* isolate); 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessors for register state. Reading the pc value adheres to the ARM 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // architecture specification and is off by a 8 from the currently executing 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instruction. 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_register(int reg, int32_t value); 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t get_register(int reg) const; 1478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch double get_double_from_register_pair(int reg); 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_register_pair_from_double(int reg, double* value); 14925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen void set_dw_register(int dreg, const int* dbl); 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Support for VFP. 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void get_d_register(int dreg, uint64_t* value); 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_d_register(int dreg, const uint64_t* value); 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void get_d_register(int dreg, uint32_t* value); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_d_register(int dreg, const uint32_t* value); 15662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Support for NEON. 15762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch template <typename T> 15862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void get_q_register(int qreg, T* value); 15962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch template <typename T> 16062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void set_q_register(int qreg, const T* value); 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void set_s_register(int reg, unsigned int value); 163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block unsigned int get_s_register(int reg) const; 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_d_register_from_double(int dreg, const double& dbl) { 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetVFPRegister<double, 2>(dreg, dbl); 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double get_double_from_d_register(int dreg) { 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetFromVFPRegister<double, 2>(dreg); 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_s_register_from_float(int sreg, const float flt) { 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetVFPRegister<float, 1>(sreg, flt); 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch float get_float_from_s_register(int sreg) { 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetFromVFPRegister<float, 1>(sreg); 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void set_s_register_from_sinteger(int sreg, const int sint) { 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetVFPRegister<int, 1>(sreg, sint); 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int get_sinteger_from_s_register(int sreg) { 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GetFromVFPRegister<int, 1>(sreg); 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Special case of set_register and get_register to access the raw PC value. 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_pc(int32_t value); 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t get_pc() const; 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Address get_sp() const { 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reinterpret_cast<Address>(static_cast<intptr_t>(get_register(sp))); 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessor to the internal simulator stack area. 198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uintptr_t StackLimit(uintptr_t c_limit) const; 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Executes ARM instructions until the PC reaches end_sim_pc. 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Execute(); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call on program start. 204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static void Initialize(Isolate* isolate); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 206f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static void TearDown(base::CustomMatcherHashMap* i_cache, Redirection* first); 207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // V8 generally calls into generated JS code with 5 parameters and into 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // generated RegExp code with 7 parameters. This is a convenience function, 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // which sets up the simulator state and grabs the result on return. 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t Call(byte* entry, int argument_count, ...); 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Alternative: call a 2-argument double function. 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CallFP(byte* entry, double d0, double d1); 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t CallFPReturnsInt(byte* entry, double d0, double d1); 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double CallFPReturnsDouble(byte* entry, double d0, double d1); 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push an address onto the JS stack. 218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block uintptr_t PushAddress(uintptr_t address); 219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Pop an address from the JS stack. 221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block uintptr_t PopAddress(); 222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Debugger input. 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void set_last_debugger_input(char* input); 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch char* last_debugger_input() { return last_debugger_input_; } 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ICache checking. 228f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static void FlushICache(base::CustomMatcherHashMap* i_cache, void* start, 229f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch size_t size); 2306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Returns true if pc register contains one of the 'special_values' defined 232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // below (bad_lr, end_sim_pc). 233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool has_bad_pc() const; 234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // EABI variant for double arguments in use. 236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool use_eabi_hardfloat() { 237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#if USE_EABI_HARDFLOAT 238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return true; 239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#else 240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return false; 241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif 242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum special_values { 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Known bad pc value to ensure that the simulator does not execute 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // without being properly setup. 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bad_lr = -1, 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // A pc value used to signal the simulator to stop execution. Generally 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the lr is set to this value on transition from native C code to 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // simulated execution, so that the simulator can "return" to the native 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // C code. 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block end_sim_pc = -2 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Unsupported instructions use Format to print an error and stop execution. 2571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void Format(Instruction* instr, const char* format); 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Checks if the current instruction should be executed based on its 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // condition bits. 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline bool ConditionallyExecute(Instruction* instr); 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Helper functions to set the conditional flags in the architecture state. 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetNZFlags(int32_t val); 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetCFlag(bool val); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetVFlag(bool val); 267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0); 2683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch bool BorrowFrom(int32_t left, int32_t right, int32_t carry = 1); 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool OverflowFrom(int32_t alu_out, 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t left, 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t right, 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool addition); 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch inline int GetCarry() { 275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return c_flag_ ? 1 : 0; 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Support for VFP. 279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Compute_FPSCR_Flags(float val1, float val2); 280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void Compute_FPSCR_Flags(double val1, double val2); 281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void Copy_FPSCR_to_APSR(); 282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch inline float canonicalizeNaN(float value); 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline double canonicalizeNaN(double value); 284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Helper functions to decode common "addressing" modes 2861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int32_t GetShiftRm(Instruction* instr, bool* carry_out); 2871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int32_t GetImm(Instruction* instr, bool* carry_out); 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t ProcessPU(Instruction* instr, 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int num_regs, 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int operand_size, 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch intptr_t* start_address, 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch intptr_t* end_address); 2931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void HandleRList(Instruction* instr, bool load); 2948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void HandleVList(Instruction* inst); 2951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void SoftwareInterrupt(Instruction* instr); 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Stop helper functions. 2981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline bool isStopInstruction(Instruction* instr); 2993e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu inline bool isWatchedStop(uint32_t bkpt_code); 3003e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu inline bool isEnabledStop(uint32_t bkpt_code); 3013e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu inline void EnableStop(uint32_t bkpt_code); 3023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu inline void DisableStop(uint32_t bkpt_code); 3033e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu inline void IncreaseStopCounter(uint32_t bkpt_code); 3043e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu void PrintStopInfo(uint32_t code); 3053e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read and write memory. 30762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // The *Ex functions are exclusive access. The writes return the strex status: 30862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // 0 if the write succeeds, and 1 if the write fails. 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline uint8_t ReadBU(int32_t addr); 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline int8_t ReadB(int32_t addr); 31162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch uint8_t ReadExBU(int32_t addr); 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void WriteB(int32_t addr, uint8_t value); 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void WriteB(int32_t addr, int8_t value); 31462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int WriteExB(int32_t addr, uint8_t value); 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline uint16_t ReadHU(int32_t addr, Instruction* instr); 3171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline int16_t ReadH(int32_t addr, Instruction* instr); 31862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch uint16_t ReadExHU(int32_t addr, Instruction* instr); 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Note: Overloaded on the sign of the value. 3201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline void WriteH(int32_t addr, uint16_t value, Instruction* instr); 3211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline void WriteH(int32_t addr, int16_t value, Instruction* instr); 32262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int WriteExH(int32_t addr, uint16_t value, Instruction* instr); 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline int ReadW(int32_t addr, Instruction* instr); 32562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int ReadExW(int32_t addr, Instruction* instr); 3261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline void WriteW(int32_t addr, int value, Instruction* instr); 32762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int WriteExW(int32_t addr, int value, Instruction* instr); 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 32925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen int32_t* ReadDW(int32_t addr); 33025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen void WriteDW(int32_t addr, int32_t value1, int32_t value2); 33125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Executing is handled based on the instruction type. 3331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Both type 0 and type 1 rolled into one. 3341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType01(Instruction* instr); 3351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType2(Instruction* instr); 3361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType3(Instruction* instr); 3371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType4(Instruction* instr); 3381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType5(Instruction* instr); 3391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType6(Instruction* instr); 3401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType7(Instruction* instr); 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 342f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // CP15 coprocessor instructions. 343f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void DecodeTypeCP15(Instruction* instr); 344f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 345d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Support for VFP. 3461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeTypeVFP(Instruction* instr); 3471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType6CoprocessorIns(Instruction* instr); 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DecodeSpecialCondition(Instruction* instr); 349d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr); 3511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVCMP(Instruction* instr); 3521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr); 35362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int32_t ConvertDoubleToInt(double val, bool unsigned_integer, 35462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch VFPRoundingMode mode); 3551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr); 3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Executes one instruction. 3581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void InstructionDecode(Instruction* instr); 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ICache. 361f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static void CheckICache(base::CustomMatcherHashMap* i_cache, 362f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Instruction* instr); 363f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static void FlushOnePage(base::CustomMatcherHashMap* i_cache, intptr_t start, 364f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int size); 365f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static CachePage* GetCachePage(base::CustomMatcherHashMap* i_cache, 366f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch void* page); 3676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Runtime call support. 3691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static void* RedirectExternalReference( 370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate* isolate, void* external_function, 3711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block v8::internal::ExternalReference::Type type); 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Handle arguments and return value for runtime FP functions. 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GetFpArgs(double* x, double* y, int32_t* z); 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetFpResult(const double& result); 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void TrashCallerSaveRegisters(); 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<class ReturnType, int register_size> 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ReturnType GetFromVFPRegister(int reg_index); 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<class InputType, int register_size> 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetVFPRegister(int reg_index, const InputType& value); 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch void SetSpecialRegister(SRegisterFieldMask reg_and_mask, uint32_t value); 3853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch uint32_t GetFromSpecialRegister(SRegister reg); 3863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CallInternal(byte* entry); 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Architecture state. 39050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Saturating instructions require a Q flag to indicate saturation. 39150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // There is currently no way to read the CPSR directly, and thus read the Q 39250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // flag, so this is left unimplemented. 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t registers_[16]; 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool n_flag_; 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool z_flag_; 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool c_flag_; 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool v_flag_; 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 399d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // VFP architecture state. 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned int vfp_registers_[num_d_registers * 2]; 401d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool n_flag_FPSCR_; 402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool z_flag_FPSCR_; 403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool c_flag_FPSCR_; 404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool v_flag_FPSCR_; 405d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 40690bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // VFP rounding mode. See ARM DDI 0406B Page A2-29. 4071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block VFPRoundingMode FPSCR_rounding_mode_; 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool FPSCR_default_NaN_mode_; 40990bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner 410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // VFP FP exception flags architecture state. 411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool inv_op_vfp_flag_; 412d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool div_zero_vfp_flag_; 413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool overflow_vfp_flag_; 414d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool underflow_vfp_flag_; 415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool inexact_vfp_flag_; 416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Simulator support. 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* stack_; 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool pc_modified_; 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int icount_; 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Debugger input. 4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch char* last_debugger_input_; 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Icache simulation 426f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch base::CustomMatcherHashMap* i_cache_; 4276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Registered breakpoints. 4291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Instruction* break_pc_; 4301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Instr break_instr_; 4313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 43244f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::internal::Isolate* isolate_; 43344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4343e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // A stop is watched if its code is less than kNumOfWatchedStops. 4353e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Only watched stops support enabling/disabling and the counter feature. 4363e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu static const uint32_t kNumOfWatchedStops = 256; 4373e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 4383e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Breakpoint is disabled if bit 31 is set. 4393e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu static const uint32_t kStopDisabledBit = 1 << 31; 4403e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 4413e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // A stop is enabled, meaning the simulator will stop when meeting the 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instruction, if bit 31 of watched_stops_[code].count is unset. 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The value watched_stops_[code].count & ~(1 << 31) indicates how many times 4443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // the breakpoint was hit or gone through. 4451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block struct StopCountAndDesc { 4463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu uint32_t count; 4473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu char* desc; 4483e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu }; 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StopCountAndDesc watched_stops_[kNumOfWatchedStops]; 45062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 45162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Syncronization primitives. See ARM DDI 0406C.b, A2.9. 45262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch enum class MonitorAccess { 45362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Open, 45462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Exclusive, 45562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch }; 45662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 45762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch enum class TransactionSize { 45862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch None = 0, 45962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Byte = 1, 46062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch HalfWord = 2, 46162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Word = 4, 46262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch }; 46362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 46462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // The least-significant bits of the address are ignored. The number of bits 46562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // is implementation-defined, between 3 and 11. See ARM DDI 0406C.b, A3.4.3. 46662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch static const int32_t kExclusiveTaggedAddrMask = ~((1 << 11) - 1); 46762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 46862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch class LocalMonitor { 46962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch public: 47062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LocalMonitor(); 47162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 47262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // These functions manage the state machine for the local monitor, but do 47362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // not actually perform loads and stores. NotifyStoreExcl only returns 47462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // true if the exclusive store is allowed; the global monitor will still 47562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // have to be checked to see whether the memory should be updated. 47662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void NotifyLoad(int32_t addr); 47762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void NotifyLoadExcl(int32_t addr, TransactionSize size); 47862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void NotifyStore(int32_t addr); 47962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch bool NotifyStoreExcl(int32_t addr, TransactionSize size); 48062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 48162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch private: 48262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void Clear(); 48362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 48462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MonitorAccess access_state_; 48562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int32_t tagged_addr_; 48662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TransactionSize size_; 48762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch }; 48862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 48962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch class GlobalMonitor { 49062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch public: 49162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GlobalMonitor(); 49262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 49362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch class Processor { 49462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch public: 49562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Processor(); 49662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 49762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch private: 49862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch friend class GlobalMonitor; 49962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // These functions manage the state machine for the global monitor, but do 50062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // not actually perform loads and stores. 50162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void Clear_Locked(); 50262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void NotifyLoadExcl_Locked(int32_t addr); 50362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void NotifyStore_Locked(int32_t addr, bool is_requesting_processor); 50462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch bool NotifyStoreExcl_Locked(int32_t addr, bool is_requesting_processor); 50562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 50662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MonitorAccess access_state_; 50762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int32_t tagged_addr_; 50862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Processor* next_; 50962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Processor* prev_; 51062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // A strex can fail due to background cache evictions. Rather than 51162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // simulating this, we'll just occasionally introduce cases where an 51262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // exclusive store fails. This will happen once after every 51362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // kMaxFailureCounter exclusive stores. 51462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch static const int kMaxFailureCounter = 5; 51562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch int failure_counter_; 51662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch }; 51762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 51862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Exposed so it can be accessed by Simulator::{Read,Write}Ex*. 51962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch base::Mutex mutex; 52062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 52162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void NotifyLoadExcl_Locked(int32_t addr, Processor* processor); 52262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void NotifyStore_Locked(int32_t addr, Processor* processor); 52362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch bool NotifyStoreExcl_Locked(int32_t addr, Processor* processor); 52462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 52562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Called when the simulator is destroyed. 52662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void RemoveProcessor(Processor* processor); 52762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 52862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch private: 52962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch bool IsProcessorInLinkedList_Locked(Processor* processor) const; 53062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void PrependProcessor_Locked(Processor* processor); 53162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 53262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Processor* head_; 53362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch }; 53462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 53562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LocalMonitor local_monitor_; 53662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GlobalMonitor::Processor global_monitor_processor_; 53762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch static base::LazyInstance<GlobalMonitor>::type global_monitor_; 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5405913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 5415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck// When running with the simulator transition into simulated execution at this 5425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck// point. 543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ 544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reinterpret_cast<Object*>(Simulator::current(isolate)->Call( \ 5455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4)) 5465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define CALL_GENERATED_FP_INT(isolate, entry, p0, p1) \ 548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Simulator::current(isolate)->CallFPReturnsInt(FUNCTION_ADDR(entry), p0, p1) 5495913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \ 551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch p7, p8) \ 552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Simulator::current(isolate) \ 553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ->Call(entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8) 5545913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 5555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The simulator has its own stack. Thus it has a different stack limit from 557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// the C-based native code. The JS-based limit normally points near the end of 558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// the simulator stack. When the C-based limit is exhausted we reflect that by 559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// lowering the JS-based limit as well, to make stack checks trigger. 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass SimulatorStack : public v8::internal::AllStatic { 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate, 563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uintptr_t c_limit) { 564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return Simulator::current(isolate)->StackLimit(c_limit); 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 566d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static inline uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate, 568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uintptr_t try_catch_address) { 569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Simulator* sim = Simulator::current(isolate); 570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return sim->PushAddress(try_catch_address); 571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 572d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static inline void UnregisterCTryCatch(v8::internal::Isolate* isolate) { 574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Simulator::current(isolate)->PopAddress(); 575d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5815913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#endif // !defined(USE_SIMULATOR) 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_ARM_SIMULATOR_ARM_H_ 583