18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Declares a Simulator for ARM instructions if we are not generating a native 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ARM binary. This Simulator allows us to run and debug ARM code generation on 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// regular desktop machines. 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// V8 calls into generated code by "calling" the CALL_GENERATED_CODE macro, 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// which will start execution in the Simulator or forwards to the real entry 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// on a ARM HW platform. 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_ARM_SIMULATOR_ARM_H_ 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_ARM_SIMULATOR_ARM_H_ 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "allocation.h" 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#if !defined(USE_SIMULATOR) 425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck// Running without a simulator on a native arm platform. 435913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Recknamespace v8 { 455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Recknamespace internal { 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// When running without a simulator we call the entry directly. 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \ 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (entry(p0, p1, p2, p3, p4)) 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 51e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochtypedef int (*arm_regexp_matcher)(String*, int, const byte*, const byte*, 5244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void*, int*, Address, int, Isolate*); 53e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 54e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 55e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Call the generated regexp code directly. The code at the entry address 56e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// should act as a function matching the type arm_regexp_matcher. 57e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// The fifth argument is a dummy that reserves the space used for 58e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// the return address added by the ExitFrame in native calls. 5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \ 6044f0eee88ff00398ff7f715fab053374d808c90dSteve Block (FUNCTION_CAST<arm_regexp_matcher>(entry)( \ 6144f0eee88ff00398ff7f715fab053374d808c90dSteve Block p0, p1, p2, p3, NULL, p4, p5, p6, p7)) 625913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 635913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \ 6444f0eee88ff00398ff7f715fab053374d808c90dSteve Block reinterpret_cast<TryCatch*>(try_catch_address) 655913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The stack limit beyond which we will throw stack overflow errors in 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// generated code. Because generated code on arm uses the C stack, we 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// just use the C stack limit. 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass SimulatorStack : public v8::internal::AllStatic { 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) { 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return c_limit; 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 74d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 75d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) { 76d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return try_catch_address; 77d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 78d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 79d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static inline void UnregisterCTryCatch() { } 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 825913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck} } // namespace v8::internal 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 845913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#else // !defined(USE_SIMULATOR) 855913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck// Running with a simulator. 86d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "constants-arm.h" 886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "hashmap.h" 891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "assembler.h" 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blocknamespace v8 { 921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blocknamespace internal { 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 946ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CachePage { 956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int LINE_VALID = 0; 976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int LINE_INVALID = 1; 986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kPageShift = 12; 1006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kPageSize = 1 << kPageShift; 1016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kPageMask = kPageSize - 1; 1026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kLineShift = 2; // The cache line is only 4 bytes right now. 1036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kLineLength = 1 << kLineShift; 1046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kLineMask = kLineLength - 1; 1056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CachePage() { 1076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block memset(&validity_map_, LINE_INVALID, sizeof(validity_map_)); 1086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block char* ValidityByte(int offset) { 1116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return &validity_map_[offset >> kLineShift]; 1126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block char* CachedData(int offset) { 1156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return &data_[offset]; 1166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 1196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block char data_[kPageSize]; // The cached data. 1206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kValidityMapSize = kPageSize >> kLineShift; 1216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block char validity_map_[kValidityMapSize]; // One byte per line. 1226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 1236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Simulator { 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block friend class ArmDebugger; 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum Register { 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block no_reg = -1, 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r0 = 0, r1, r2, r3, r4, r5, r6, r7, 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r8, r9, r10, r11, r12, r13, r14, r15, 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_registers, 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sp = 13, 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lr = 14, 135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pc = 15, 136d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block s0 = 0, s1, s2, s3, s4, s5, s6, s7, 137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block s8, s9, s10, s11, s12, s13, s14, s15, 138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block s16, s17, s18, s19, s20, s21, s22, s23, 139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block s24, s25, s26, s27, s28, s29, s30, s31, 140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block num_s_registers = 32, 141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block d0 = 0, d1, d2, d3, d4, d5, d6, d7, 142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block d8, d9, d10, d11, d12, d13, d14, d15, 143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block num_d_registers = 16 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Simulator(); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~Simulator(); 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The currently executing Simulator instance. Potentially there can be one 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for each native thread. 15144f0eee88ff00398ff7f715fab053374d808c90dSteve Block static Simulator* current(v8::internal::Isolate* isolate); 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessors for register state. Reading the pc value adheres to the ARM 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // architecture specification and is off by a 8 from the currently executing 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instruction. 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_register(int reg, int32_t value); 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t get_register(int reg) const; 1588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch double get_double_from_register_pair(int reg); 15925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen void set_dw_register(int dreg, const int* dbl); 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Support for VFP. 162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void set_s_register(int reg, unsigned int value); 163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block unsigned int get_s_register(int reg) const; 164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void set_d_register_from_double(int dreg, const double& dbl); 165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block double get_double_from_d_register(int dreg); 166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void set_s_register_from_float(int sreg, const float dbl); 167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block float get_float_from_s_register(int sreg); 168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void set_s_register_from_sinteger(int reg, const int value); 169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int get_sinteger_from_s_register(int reg); 170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Special case of set_register and get_register to access the raw PC value. 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_pc(int32_t value); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t get_pc() const; 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessor to the internal simulator stack area. 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uintptr_t StackLimit() const; 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Executes ARM instructions until the PC reaches end_sim_pc. 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Execute(); 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call on program start. 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void Initialize(); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // V8 generally calls into generated JS code with 5 parameters and into 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // generated RegExp code with 7 parameters. This is a convenience function, 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // which sets up the simulator state and grabs the result on return. 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t Call(byte* entry, int argument_count, ...); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push an address onto the JS stack. 190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block uintptr_t PushAddress(uintptr_t address); 191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Pop an address from the JS stack. 193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block uintptr_t PopAddress(); 194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ICache checking. 19644f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void FlushICache(v8::internal::HashMap* i_cache, void* start, 19744f0eee88ff00398ff7f715fab053374d808c90dSteve Block size_t size); 1986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Returns true if pc register contains one of the 'special_values' defined 200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // below (bad_lr, end_sim_pc). 201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool has_bad_pc() const; 202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum special_values { 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Known bad pc value to ensure that the simulator does not execute 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // without being properly setup. 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bad_lr = -1, 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // A pc value used to signal the simulator to stop execution. Generally 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the lr is set to this value on transition from native C code to 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // simulated execution, so that the simulator can "return" to the native 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // C code. 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block end_sim_pc = -2 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Unsupported instructions use Format to print an error and stop execution. 2161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void Format(Instruction* instr, const char* format); 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Checks if the current instruction should be executed based on its 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // condition bits. 2201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool ConditionallyExecute(Instruction* instr); 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Helper functions to set the conditional flags in the architecture state. 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetNZFlags(int32_t val); 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetCFlag(bool val); 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetVFlag(bool val); 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool CarryFrom(int32_t left, int32_t right); 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool BorrowFrom(int32_t left, int32_t right); 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool OverflowFrom(int32_t alu_out, 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t left, 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t right, 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool addition); 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Support for VFP. 234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void Compute_FPSCR_Flags(double val1, double val2); 235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void Copy_FPSCR_to_APSR(); 236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Helper functions to decode common "addressing" modes 2381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int32_t GetShiftRm(Instruction* instr, bool* carry_out); 2391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int32_t GetImm(Instruction* instr, bool* carry_out); 2408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void ProcessPUW(Instruction* instr, 2418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int num_regs, 2428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int operand_size, 2438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch intptr_t* start_address, 2448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch intptr_t* end_address); 2451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void HandleRList(Instruction* instr, bool load); 2468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void HandleVList(Instruction* inst); 2471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void SoftwareInterrupt(Instruction* instr); 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Stop helper functions. 2501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline bool isStopInstruction(Instruction* instr); 2513e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu inline bool isWatchedStop(uint32_t bkpt_code); 2523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu inline bool isEnabledStop(uint32_t bkpt_code); 2533e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu inline void EnableStop(uint32_t bkpt_code); 2543e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu inline void DisableStop(uint32_t bkpt_code); 2553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu inline void IncreaseStopCounter(uint32_t bkpt_code); 2563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu void PrintStopInfo(uint32_t code); 2573e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read and write memory. 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline uint8_t ReadBU(int32_t addr); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline int8_t ReadB(int32_t addr); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void WriteB(int32_t addr, uint8_t value); 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline void WriteB(int32_t addr, int8_t value); 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline uint16_t ReadHU(int32_t addr, Instruction* instr); 2651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline int16_t ReadH(int32_t addr, Instruction* instr); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Note: Overloaded on the sign of the value. 2671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline void WriteH(int32_t addr, uint16_t value, Instruction* instr); 2681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline void WriteH(int32_t addr, int16_t value, Instruction* instr); 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline int ReadW(int32_t addr, Instruction* instr); 2711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block inline void WriteW(int32_t addr, int value, Instruction* instr); 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen int32_t* ReadDW(int32_t addr); 27425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen void WriteDW(int32_t addr, int32_t value1, int32_t value2); 27525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Executing is handled based on the instruction type. 2771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Both type 0 and type 1 rolled into one. 2781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType01(Instruction* instr); 2791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType2(Instruction* instr); 2801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType3(Instruction* instr); 2811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType4(Instruction* instr); 2821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType5(Instruction* instr); 2831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType6(Instruction* instr); 2841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType7(Instruction* instr); 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Support for VFP. 2871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeTypeVFP(Instruction* instr); 2881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeType6CoprocessorIns(Instruction* instr); 289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr); 2911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVCMP(Instruction* instr); 2921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr); 2931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr); 2946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Executes one instruction. 2961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void InstructionDecode(Instruction* instr); 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ICache. 29944f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr); 30044f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start, 30144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int size); 30244f0eee88ff00398ff7f715fab053374d808c90dSteve Block static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page); 3036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Runtime call support. 3051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static void* RedirectExternalReference( 3061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void* external_function, 3071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block v8::internal::ExternalReference::Type type); 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For use in calls that take two double values, constructed from r0, r1, r2 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and r3. 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void GetFpArgs(double* x, double* y); 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetFpResult(const double& result); 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void TrashCallerSaveRegisters(); 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Architecture state. 31650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // Saturating instructions require a Q flag to indicate saturation. 31750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // There is currently no way to read the CPSR directly, and thus read the Q 31850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen // flag, so this is left unimplemented. 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t registers_[16]; 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool n_flag_; 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool z_flag_; 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool c_flag_; 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool v_flag_; 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // VFP architecture state. 326d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block unsigned int vfp_register[num_s_registers]; 327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool n_flag_FPSCR_; 328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool z_flag_FPSCR_; 329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool c_flag_FPSCR_; 330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool v_flag_FPSCR_; 331d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 33290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // VFP rounding mode. See ARM DDI 0406B Page A2-29. 3331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block VFPRoundingMode FPSCR_rounding_mode_; 33490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner 335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // VFP FP exception flags architecture state. 336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool inv_op_vfp_flag_; 337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool div_zero_vfp_flag_; 338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool overflow_vfp_flag_; 339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool underflow_vfp_flag_; 340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool inexact_vfp_flag_; 341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Simulator support. 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* stack_; 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool pc_modified_; 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int icount_; 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Icache simulation 34844f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::internal::HashMap* i_cache_; 3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Registered breakpoints. 3511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Instruction* break_pc_; 3521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Instr break_instr_; 3533e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 35444f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::internal::Isolate* isolate_; 35544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // A stop is watched if its code is less than kNumOfWatchedStops. 3573e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Only watched stops support enabling/disabling and the counter feature. 3583e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu static const uint32_t kNumOfWatchedStops = 256; 3593e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 3603e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Breakpoint is disabled if bit 31 is set. 3613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu static const uint32_t kStopDisabledBit = 1 << 31; 3623e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 3633e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // A stop is enabled, meaning the simulator will stop when meeting the 3643e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // instruction, if bit 31 of watched_stops[code].count is unset. 3653e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // The value watched_stops[code].count & ~(1 << 31) indicates how many times 3663e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // the breakpoint was hit or gone through. 3671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block struct StopCountAndDesc { 3683e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu uint32_t count; 3693e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu char* desc; 3703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu }; 3711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block StopCountAndDesc watched_stops[kNumOfWatchedStops]; 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 3755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck// When running with the simulator transition into simulated execution at this 3765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck// point. 3775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \ 37844f0eee88ff00398ff7f715fab053374d808c90dSteve Block reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->Call( \ 3795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4)) 3805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 38144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \ 38244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Simulator::current(Isolate::Current())->Call( \ 38344f0eee88ff00398ff7f715fab053374d808c90dSteve Block entry, 9, p0, p1, p2, p3, NULL, p4, p5, p6, p7) 3845913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 38544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \ 38644f0eee88ff00398ff7f715fab053374d808c90dSteve Block try_catch_address == NULL ? \ 38744f0eee88ff00398ff7f715fab053374d808c90dSteve Block NULL : *(reinterpret_cast<TryCatch**>(try_catch_address)) 3885913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 3895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The simulator has its own stack. Thus it has a different stack limit from 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the C-based native code. Setting the c_limit to indicate a very small 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// stack cause stack overflow errors, since the simulator ignores the input. 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This is unlikely to be an issue in practice, though it might cause testing 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// trouble down the line. 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass SimulatorStack : public v8::internal::AllStatic { 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) { 39844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return Simulator::current(Isolate::Current())->StackLimit(); 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 401d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) { 40244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Simulator* sim = Simulator::current(Isolate::Current()); 403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return sim->PushAddress(try_catch_address); 404d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 405d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static inline void UnregisterCTryCatch() { 40744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Simulator::current(Isolate::Current())->PopAddress(); 408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4115913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck} } // namespace v8::internal 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4135913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#endif // !defined(USE_SIMULATOR) 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_ARM_SIMULATOR_ARM_H_ 415