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