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