1f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Copyright 2013 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
4f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
5fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#ifndef V8_ARM64_SIMULATOR_ARM64_H_
6fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#define V8_ARM64_SIMULATOR_ARM64_H_
7f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
8f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#include <stdarg.h>
9f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#include <vector>
10f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
12f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
13196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/allocation.h"
14196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/arm64/assembler-arm64.h"
15196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/arm64/decoder-arm64.h"
16196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/arm64/disasm-arm64.h"
17196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/arm64/instrument-arm64.h"
184b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/assembler.h"
194b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/globals.h"
204b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/utils.h"
21f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
22f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define REGISTER_CODE_LIST(R)                                                  \
23f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgR(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                                 \
24f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgR(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)                                \
25f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgR(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)                                \
26f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgR(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
27f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
28f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgnamespace v8 {
29f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgnamespace internal {
30f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
31f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#if !defined(USE_SIMULATOR)
32f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
33fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org// Running without a simulator on a native ARM64 platform.
34f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// When running without a simulator we call the entry directly.
35f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
36f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  (entry(p0, p1, p2, p3, p4))
37f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
38fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.orgtypedef int (*arm64_regexp_matcher)(String* input,
39fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                    int64_t start_offset,
40fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                    const byte* input_start,
41fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                    const byte* input_end,
42fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                    int* output,
43fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                    int64_t output_size,
44fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                    Address stack_base,
45fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                    int64_t direct_call,
46fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                    void* return_address,
47fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                    Isolate* isolate);
48f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
49f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Call the generated regexp code directly. The code at the entry address
50fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org// should act as a function matching the type arm64_regexp_matcher.
51f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// The ninth argument is a dummy that reserves the space used for
52f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// the return address added by the ExitFrame in native calls.
53f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
54fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  (FUNCTION_CAST<arm64_regexp_matcher>(entry)(                                \
55f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8))
56f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
57f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Running without a simulator there is nothing to do.
58f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgclass SimulatorStack : public v8::internal::AllStatic {
59f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org public:
60f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
61f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                            uintptr_t c_limit) {
62f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    USE(isolate);
63f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return c_limit;
64f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
65f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
66f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
67f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return try_catch_address;
68f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
69f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
70f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static void UnregisterCTryCatch() { }
71f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org};
72f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
73f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#else  // !defined(USE_SIMULATOR)
74f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
75f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgenum ReverseByteMode {
76f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Reverse16 = 0,
77f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Reverse32 = 1,
78f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Reverse64 = 2
79f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org};
80f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
81f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
82f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// The proper way to initialize a simulated system register (such as NZCV) is as
83f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// follows:
84f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org//  SimSystemRegister nzcv = SimSystemRegister::DefaultValueFor(NZCV);
85f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgclass SimSystemRegister {
86f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org public:
87f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The default constructor represents a register which has no writable bits.
88f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // It is not possible to set its value to anything other than 0.
89f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  SimSystemRegister() : value_(0), write_ignore_mask_(0xffffffff) { }
90f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
91f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  uint32_t RawValue() const {
92f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return value_;
93f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
94f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
95f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void SetRawValue(uint32_t new_value) {
96f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    value_ = (value_ & write_ignore_mask_) | (new_value & ~write_ignore_mask_);
97f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
98f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
99f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  uint32_t Bits(int msb, int lsb) const {
100f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return unsigned_bitextract_32(msb, lsb, value_);
101f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
103f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int32_t SignedBits(int msb, int lsb) const {
104f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return signed_bitextract_32(msb, lsb, value_);
105f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
106f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void SetBits(int msb, int lsb, uint32_t bits);
108f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
109f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Default system register values.
110f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static SimSystemRegister DefaultValueFor(SystemRegister id);
111f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1129801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org#define DEFINE_GETTER(Name, HighBit, LowBit, Func, Type)                       \
1139801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org  Type Name() const { return static_cast<Type>(Func(HighBit, LowBit)); }       \
1149801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org  void Set##Name(Type bits) {                                                  \
1159801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org    SetBits(HighBit, LowBit, static_cast<Type>(bits));                         \
1169801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org  }
1179801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org#define DEFINE_WRITE_IGNORE_MASK(Name, Mask)                                   \
118f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const uint32_t Name##WriteIgnoreMask = ~static_cast<uint32_t>(Mask);
119f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER, DEFINE_WRITE_IGNORE_MASK)
120f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#undef DEFINE_ZERO_BITS
121f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#undef DEFINE_GETTER
122f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
123f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org protected:
124f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Most system registers only implement a few of the bits in the word. Other
125f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // bits are "read-as-zero, write-ignored". The write_ignore_mask argument
126f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // describes the bits which are not modifiable.
127f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  SimSystemRegister(uint32_t value, uint32_t write_ignore_mask)
128f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      : value_(value), write_ignore_mask_(write_ignore_mask) { }
129f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
130f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  uint32_t value_;
131f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  uint32_t write_ignore_mask_;
132f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org};
133f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
134f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
135f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Represent a register (r0-r31, v0-v31).
136f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgclass SimRegisterBase {
137f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org public:
138f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  template<typename T>
1391845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  void Set(T new_value) {
1401845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    value_ = 0;
1411845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    memcpy(&value_, &new_value, sizeof(T));
142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  template<typename T>
1451845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  T Get() const {
146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    T result;
1471845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    memcpy(&result, &value_, sizeof(T));
148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return result;
149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org protected:
1521845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  int64_t value_;
153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org};
1541845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org
1551845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org
1561845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtypedef SimRegisterBase SimRegister;      // r0-r31
1571845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtypedef SimRegisterBase SimFPRegister;    // v0-v31
158f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
159f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
160f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgclass Simulator : public DecoderVisitor {
161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org public:
162f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  explicit Simulator(Decoder<DispatchingDecoderVisitor>* decoder,
163f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     Isolate* isolate = NULL,
164f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     FILE* stream = stderr);
165f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Simulator();
166f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  ~Simulator();
167f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
168f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // System functions.
169f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
170f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static void Initialize(Isolate* isolate);
171f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
172f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Simulator* current(v8::internal::Isolate* isolate);
173f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
174f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  class CallArgument;
175f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
176f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Call an arbitrary function taking an arbitrary number of arguments. The
177f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // varargs list must be a set of arguments with type CallArgument, and
178f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // terminated by CallArgument::End().
179f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void CallVoid(byte* entry, CallArgument* args);
180f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
181f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Like CallVoid, but expect a return value.
182f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int64_t CallInt64(byte* entry, CallArgument* args);
183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  double CallDouble(byte* entry, CallArgument* args);
184f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
185f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // V8 calls into generated JS code with 5 parameters and into
186f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // generated RegExp code with 10 parameters. These are convenience functions,
187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // which set up the simulator state and grab the result on return.
188f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int64_t CallJS(byte* entry,
189f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 byte* function_entry,
190f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 JSFunction* func,
191f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 Object* revc,
192f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 int64_t argc,
193f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 Object*** argv);
194f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int64_t CallRegExp(byte* entry,
195f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     String* input,
196f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     int64_t start_offset,
197f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     const byte* input_start,
198f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     const byte* input_end,
199f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     int* output,
200f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     int64_t output_size,
201f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     Address stack_base,
202f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     int64_t direct_call,
203f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     void* return_address,
204f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     Isolate* isolate);
205f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
206f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // A wrapper class that stores an argument for one of the above Call
207f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // functions.
208f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //
209f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Only arguments up to 64 bits in size are supported.
210f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  class CallArgument {
211f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org   public:
212f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    template<typename T>
213f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    explicit CallArgument(T argument) {
2147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      bits_ = 0;
215e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(sizeof(argument) <= sizeof(bits_));
216f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      memcpy(&bits_, &argument, sizeof(argument));
217f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      type_ = X_ARG;
218f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
219f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
220f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    explicit CallArgument(double argument) {
221e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(sizeof(argument) == sizeof(bits_));
222f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      memcpy(&bits_, &argument, sizeof(argument));
223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      type_ = D_ARG;
224f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
225f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
226f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    explicit CallArgument(float argument) {
227f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      // TODO(all): CallArgument(float) is untested, remove this check once
228f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      //            tested.
229f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      UNIMPLEMENTED();
230f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      // Make the D register a NaN to try to trap errors if the callee expects a
231f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      // double. If it expects a float, the callee should ignore the top word.
232e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(sizeof(kFP64SignallingNaN) == sizeof(bits_));
233f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      memcpy(&bits_, &kFP64SignallingNaN, sizeof(kFP64SignallingNaN));
234f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      // Write the float payload to the S register.
235e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(sizeof(argument) <= sizeof(bits_));
236f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      memcpy(&bits_, &argument, sizeof(argument));
237f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      type_ = D_ARG;
238f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
239f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
240f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // This indicates the end of the arguments list, so that CallArgument
241f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // objects can be passed into varargs functions.
242f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    static CallArgument End() { return CallArgument(); }
243f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
244f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    int64_t bits() const { return bits_; }
245f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    bool IsEnd() const { return type_ == NO_ARG; }
246f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    bool IsX() const { return type_ == X_ARG; }
247f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    bool IsD() const { return type_ == D_ARG; }
248f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
249f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org   private:
250f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    enum CallArgumentType { X_ARG, D_ARG, NO_ARG };
251f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
252f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // All arguments are aligned to at least 64 bits and we don't support
253f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // passing bigger arguments, so the payload size can be fixed at 64 bits.
254f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    int64_t bits_;
255f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    CallArgumentType type_;
256f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
257f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    CallArgument() { type_ = NO_ARG; }
258f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  };
259f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
260f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
261f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Start the debugging command line.
262f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void Debug();
263f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
264f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool GetValue(const char* desc, int64_t* value);
265f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
266f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool PrintValue(const char* desc);
267f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
268f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Push an address onto the JS stack.
269f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  uintptr_t PushAddress(uintptr_t address);
270f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
271f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Pop an address from the JS stack.
272f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  uintptr_t PopAddress();
273f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
274f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Accessor to the internal simulator stack area.
275f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  uintptr_t StackLimit() const;
276f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
277f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ResetState();
278f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
279f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Runtime call support.
280f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static void* RedirectExternalReference(void* external_function,
281f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                         ExternalReference::Type type);
2827010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org  void DoRuntimeCall(Instruction* instr);
283f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
284f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Run the simulator.
285f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const Instruction* kEndOfSimAddress;
286f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void DecodeInstruction();
287f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void Run();
288f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void RunFrom(Instruction* start);
289f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
290f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Simulation helpers.
291f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  template <typename T>
292f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void set_pc(T new_pc) {
293e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(sizeof(T) == sizeof(pc_));
294f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    memcpy(&pc_, &new_pc, sizeof(T));
295f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    pc_modified_ = true;
296f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
297f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Instruction* pc() { return pc_; }
298f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
299f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void increment_pc() {
300f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (!pc_modified_) {
3014452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org      pc_ = pc_->following();
302f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
303f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
304f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    pc_modified_ = false;
305f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
306f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
307f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  virtual void Decode(Instruction* instr) {
308f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    decoder_->Decode(instr);
309f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
310f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
311f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ExecuteInstruction() {
312e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(IsAligned(reinterpret_cast<uintptr_t>(pc_), kInstructionSize));
313f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    CheckBreakNext();
314f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Decode(pc_);
315f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    increment_pc();
316f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    CheckBreakpoints();
317f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
318f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
319f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Declare all Visitor functions.
320f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  #define DECLARE(A)  void Visit##A(Instruction* instr);
321f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  VISITOR_LIST(DECLARE)
322f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  #undef DECLARE
323f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
3241845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  bool IsZeroRegister(unsigned code, Reg31Mode r31mode) const {
3251845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    return ((code == 31) && (r31mode == Reg31IsZeroRegister));
3261845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  }
327f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
3281845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  // Register accessors.
329f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Return 'size' bits of the value of an integer register, as the specified
330f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // type. The value is zero-extended to fill the result.
331f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //
332f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  template<typename T>
3331845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
334e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(code < kNumberOfRegisters);
3351845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    if (IsZeroRegister(code, r31mode)) {
3361845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org      return 0;
337f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
3381845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    return registers_[code].Get<T>();
339f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
340f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
341f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Common specialized accessors for the reg() template.
3421845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  int32_t wreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
343f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return reg<int32_t>(code, r31mode);
344f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
345f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
3461845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  int64_t xreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
347f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return reg<int64_t>(code, r31mode);
348f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
349f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
3502c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // Write 'value' into an integer register. The value is zero-extended. This
3512c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // behaviour matches AArch64 register writes.
352f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  template<typename T>
353f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void set_reg(unsigned code, T value,
354f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org               Reg31Mode r31mode = Reg31IsZeroRegister) {
3552c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    set_reg_no_log(code, value, r31mode);
3562c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    LogRegister(code, r31mode);
357f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
358f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
359f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Common specialized accessors for the set_reg() template.
360f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void set_wreg(unsigned code, int32_t value,
361f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                Reg31Mode r31mode = Reg31IsZeroRegister) {
3621845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    set_reg(code, value, r31mode);
363f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
364f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
365f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void set_xreg(unsigned code, int64_t value,
366f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                Reg31Mode r31mode = Reg31IsZeroRegister) {
3671845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    set_reg(code, value, r31mode);
368f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
369f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
3702c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // As above, but don't automatically log the register update.
3712c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  template <typename T>
3722c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void set_reg_no_log(unsigned code, T value,
3732c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                      Reg31Mode r31mode = Reg31IsZeroRegister) {
3742c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    DCHECK(code < kNumberOfRegisters);
3752c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (!IsZeroRegister(code, r31mode)) {
3762c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      registers_[code].Set(value);
3772c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    }
3782c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  }
3792c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
3802c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void set_wreg_no_log(unsigned code, int32_t value,
3812c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                       Reg31Mode r31mode = Reg31IsZeroRegister) {
3822c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    set_reg_no_log(code, value, r31mode);
3832c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  }
3842c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
3852c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void set_xreg_no_log(unsigned code, int64_t value,
3862c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                       Reg31Mode r31mode = Reg31IsZeroRegister) {
3872c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    set_reg_no_log(code, value, r31mode);
3882c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  }
3892c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
390f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Commonly-used special cases.
391f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  template<typename T>
392f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void set_lr(T value) {
393e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(sizeof(T) == kPointerSize);
394f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    set_reg(kLinkRegCode, value);
395f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
396f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
397f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  template<typename T>
398f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void set_sp(T value) {
399e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(sizeof(T) == kPointerSize);
400f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    set_reg(31, value, Reg31IsStackPointer);
401f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
402f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
403f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int64_t sp() { return xreg(31, Reg31IsStackPointer); }
404f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); }
405f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int64_t fp() {
406f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      return xreg(kFramePointerRegCode, Reg31IsStackPointer);
407f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
408f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Instruction* lr() { return reg<Instruction*>(kLinkRegCode); }
409f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
410f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Address get_sp() { return reg<Address>(31, Reg31IsStackPointer); }
411f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
412f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  template<typename T>
413f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  T fpreg(unsigned code) const {
414e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(code < kNumberOfRegisters);
4151845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    return fpregisters_[code].Get<T>();
416f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
417f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
418f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Common specialized accessors for the fpreg() template.
419f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  float sreg(unsigned code) const {
420f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return fpreg<float>(code);
421f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
422f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
423f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  uint32_t sreg_bits(unsigned code) const {
424f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return fpreg<uint32_t>(code);
425f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
426f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
427f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  double dreg(unsigned code) const {
428f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return fpreg<double>(code);
429f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
430f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
431f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  uint64_t dreg_bits(unsigned code) const {
432f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return fpreg<uint64_t>(code);
433f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
434f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
435f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  double fpreg(unsigned size, unsigned code) const {
436f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    switch (size) {
43797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org      case kSRegSizeInBits: return sreg(code);
43897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org      case kDRegSizeInBits: return dreg(code);
439f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      default:
440f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        UNREACHABLE();
441f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        return 0.0;
442f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
443f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
444f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
445f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Write 'value' into a floating-point register. The value is zero-extended.
446f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // This behaviour matches AArch64 register writes.
447f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  template<typename T>
448f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void set_fpreg(unsigned code, T value) {
4492c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    set_fpreg_no_log(code, value);
4502c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
4512c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (sizeof(value) <= kSRegSize) {
4522c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      LogFPRegister(code, kPrintSRegValue);
4532c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    } else {
4542c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      LogFPRegister(code, kPrintDRegValue);
4552c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    }
456f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
457f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
458f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Common specialized accessors for the set_fpreg() template.
459f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void set_sreg(unsigned code, float value) {
460f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    set_fpreg(code, value);
461f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
462f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
463f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void set_sreg_bits(unsigned code, uint32_t value) {
464f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    set_fpreg(code, value);
465f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
466f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
467f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void set_dreg(unsigned code, double value) {
468f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    set_fpreg(code, value);
469f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
470f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
471f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void set_dreg_bits(unsigned code, uint64_t value) {
472f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    set_fpreg(code, value);
473f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
474f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
4752c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // As above, but don't automatically log the register update.
4762c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  template <typename T>
4772c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void set_fpreg_no_log(unsigned code, T value) {
4782c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    DCHECK((sizeof(value) == kDRegSize) || (sizeof(value) == kSRegSize));
4792c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    DCHECK(code < kNumberOfFPRegisters);
4802c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    fpregisters_[code].Set(value);
4812c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  }
4822c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
4832c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void set_sreg_no_log(unsigned code, float value) {
4842c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    set_fpreg_no_log(code, value);
4852c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  }
4862c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
4872c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void set_dreg_no_log(unsigned code, double value) {
4882c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    set_fpreg_no_log(code, value);
4892c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  }
4902c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
491f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  SimSystemRegister& nzcv() { return nzcv_; }
492f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  SimSystemRegister& fpcr() { return fpcr_; }
493f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
494f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Debug helpers
495f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
496f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Simulator breakpoints.
497f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  struct Breakpoint {
498f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Instruction* location;
499f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    bool enabled;
500f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  };
501f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  std::vector<Breakpoint> breakpoints_;
502f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void SetBreakpoint(Instruction* breakpoint);
503f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ListBreakpoints();
504f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void CheckBreakpoints();
505f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
506f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Helpers for the 'next' command.
507f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // When this is set, the Simulator will insert a breakpoint after the next BL
508f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // instruction it meets.
509f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool break_on_next_;
510f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Check if the Simulator should insert a break after the current instruction
511f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // for the 'next' command.
512f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void CheckBreakNext();
513f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
514f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Disassemble instruction at the given address.
515f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void PrintInstructionsAt(Instruction* pc, uint64_t count);
516f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
5172c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // Print all registers of the specified types.
5182c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void PrintRegisters();
5192c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void PrintFPRegisters();
5202c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void PrintSystemRegisters();
5212c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
5222c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // Like Print* (above), but respect log_parameters().
523f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void LogSystemRegisters() {
5242c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (log_parameters() & LOG_SYS_REGS) PrintSystemRegisters();
525f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
526f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void LogRegisters() {
5272c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (log_parameters() & LOG_REGS) PrintRegisters();
528f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
529f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void LogFPRegisters() {
5302c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (log_parameters() & LOG_FP_REGS) PrintFPRegisters();
5312c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  }
5322c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
5332c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // Specify relevant register sizes, for PrintFPRegister.
5342c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  //
5352c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // These values are bit masks; they can be combined in case multiple views of
5362c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // a machine register are interesting.
5372c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  enum PrintFPRegisterSizes {
5382c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    kPrintDRegValue = 1 << kDRegSize,
5392c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    kPrintSRegValue = 1 << kSRegSize,
5402c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    kPrintAllFPRegValues = kPrintDRegValue | kPrintSRegValue
5412c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  };
5422c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
5432c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // Print individual register values (after update).
5442c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void PrintRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer);
5452c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void PrintFPRegister(unsigned code,
5462c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                       PrintFPRegisterSizes sizes = kPrintAllFPRegValues);
5472c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void PrintSystemRegister(SystemRegister id);
5482c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
5492c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // Like Print* (above), but respect log_parameters().
5502c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void LogRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer) {
5512c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (log_parameters() & LOG_REGS) PrintRegister(code, r31mode);
552f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
5532c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void LogFPRegister(unsigned code,
5542c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                     PrintFPRegisterSizes sizes = kPrintAllFPRegValues) {
5552c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (log_parameters() & LOG_FP_REGS) PrintFPRegister(code, sizes);
556f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
5572c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void LogSystemRegister(SystemRegister id) {
5582c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (log_parameters() & LOG_SYS_REGS) PrintSystemRegister(id);
5592c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  }
5602c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
5612c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // Print memory accesses.
5622c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void PrintRead(uintptr_t address, size_t size, unsigned reg_code);
5632c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void PrintReadFP(uintptr_t address, size_t size, unsigned reg_code);
5642c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void PrintWrite(uintptr_t address, size_t size, unsigned reg_code);
5652c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void PrintWriteFP(uintptr_t address, size_t size, unsigned reg_code);
5662c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
5672c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // Like Print* (above), but respect log_parameters().
5682c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void LogRead(uintptr_t address, size_t size, unsigned reg_code) {
5692c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (log_parameters() & LOG_REGS) PrintRead(address, size, reg_code);
5702c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  }
5712c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void LogReadFP(uintptr_t address, size_t size, unsigned reg_code) {
5722c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (log_parameters() & LOG_FP_REGS) PrintReadFP(address, size, reg_code);
5732c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  }
5742c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void LogWrite(uintptr_t address, size_t size, unsigned reg_code) {
5752c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (log_parameters() & LOG_WRITE) PrintWrite(address, size, reg_code);
5762c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  }
5772c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void LogWriteFP(uintptr_t address, size_t size, unsigned reg_code) {
5782c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (log_parameters() & LOG_WRITE) PrintWriteFP(address, size, reg_code);
579f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
580f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
581f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int log_parameters() { return log_parameters_; }
582f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void set_log_parameters(int new_parameters) {
583f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    log_parameters_ = new_parameters;
584f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (!decoder_) {
585f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      if (new_parameters & LOG_DISASM) {
586f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        PrintF("Run --debug-sim to dynamically turn on disassembler\n");
587f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      }
588f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      return;
589f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
590f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (new_parameters & LOG_DISASM) {
591f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      decoder_->InsertVisitorBefore(print_disasm_, this);
592f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    } else {
593f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      decoder_->RemoveVisitor(print_disasm_);
594f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
595f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
596f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
597f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static inline const char* WRegNameForCode(unsigned code,
598f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      Reg31Mode mode = Reg31IsZeroRegister);
599f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static inline const char* XRegNameForCode(unsigned code,
600f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      Reg31Mode mode = Reg31IsZeroRegister);
601f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static inline const char* SRegNameForCode(unsigned code);
602f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static inline const char* DRegNameForCode(unsigned code);
603f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static inline const char* VRegNameForCode(unsigned code);
604f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static inline int CodeFromName(const char* name);
605f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
606f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org protected:
607f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Simulation helpers ------------------------------------
608f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool ConditionPassed(Condition cond) {
6099801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org    SimSystemRegister& flags = nzcv();
610f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    switch (cond) {
611f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case eq:
6129801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org        return flags.Z();
613f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case ne:
6149801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org        return !flags.Z();
615f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case hs:
6169801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org        return flags.C();
617f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case lo:
6189801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org        return !flags.C();
619f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case mi:
6209801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org        return flags.N();
621f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case pl:
6229801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org        return !flags.N();
623f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case vs:
6249801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org        return flags.V();
625f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case vc:
6269801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org        return !flags.V();
627f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case hi:
6289801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org        return flags.C() && !flags.Z();
629f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case ls:
6309801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org        return !(flags.C() && !flags.Z());
631f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case ge:
6329801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org        return flags.N() == flags.V();
633f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case lt:
6349801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org        return flags.N() != flags.V();
635f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case gt:
6369801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org        return !flags.Z() && (flags.N() == flags.V());
637f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case le:
6389801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org        return !(!flags.Z() && (flags.N() == flags.V()));
639f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case nv:  // Fall through.
640f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      case al:
641f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        return true;
642f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      default:
643f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        UNREACHABLE();
644f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        return false;
645f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
646f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
647f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
648f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool ConditionFailed(Condition cond) {
649f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return !ConditionPassed(cond);
650f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
651f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
6521845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  template<typename T>
6531845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  void AddSubHelper(Instruction* instr, T op2);
6541845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  template<typename T>
6551845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  T AddWithCarry(bool set_flags,
6561845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org                 T src1,
6571845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org                 T src2,
6581845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org                 T carry_in = 0);
6591845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  template<typename T>
6601845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  void AddSubWithCarry(Instruction* instr);
6611845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  template<typename T>
6621845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  void LogicalHelper(Instruction* instr, T op2);
6631845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  template<typename T>
6641845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  void ConditionalCompareHelper(Instruction* instr, T op2);
665f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void LoadStoreHelper(Instruction* instr,
666f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                       int64_t offset,
667f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                       AddrMode addrmode);
668f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void LoadStorePairHelper(Instruction* instr, AddrMode addrmode);
6692c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  uintptr_t LoadStoreAddress(unsigned addr_reg, int64_t offset,
6702c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                             AddrMode addrmode);
671f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void LoadStoreWriteBack(unsigned addr_reg,
672f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                          int64_t offset,
673f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                          AddrMode addrmode);
6742c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  void CheckMemoryAccess(uintptr_t address, uintptr_t stack);
675f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
6762c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // Memory read helpers.
6779aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  template <typename T, typename A>
6789aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  T MemoryRead(A address) {
6799aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    T value;
6809aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
6819aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org                  (sizeof(value) == 4) || (sizeof(value) == 8));
6829aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    memcpy(&value, reinterpret_cast<const void*>(address), sizeof(value));
6839aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    return value;
6849aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  }
685f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
6862c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // Memory write helpers.
6879aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  template <typename T, typename A>
6889aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  void MemoryWrite(A address, T value) {
6899aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) ||
6909aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org                  (sizeof(value) == 4) || (sizeof(value) == 8));
6919aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    memcpy(reinterpret_cast<void*>(address), &value, sizeof(value));
6929aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  }
6931845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org
6941845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  template <typename T>
6951845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  T ShiftOperand(T value,
696f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 Shift shift_type,
697f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 unsigned amount);
6981845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  template <typename T>
6991845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  T ExtendValue(T value,
7001845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org                Extend extend_type,
7011845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org                unsigned left_shift = 0);
7021845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  template <typename T>
7031845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  void Extract(Instruction* instr);
7041845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  template <typename T>
7051845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  void DataProcessing2Source(Instruction* instr);
7061845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  template <typename T>
7071845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  void BitfieldHelper(Instruction* instr);
708f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
709f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  uint64_t ReverseBits(uint64_t value, unsigned num_bits);
710f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  uint64_t ReverseBytes(uint64_t value, ReverseByteMode mode);
711f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
7126b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  template <typename T>
7136b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  T FPDefaultNaN() const;
7146b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
715f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void FPCompare(double val0, double val1);
716f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  double FPRoundInt(double value, FPRounding round_mode);
717f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  double FPToDouble(float value);
718f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  float FPToFloat(double value, FPRounding round_mode);
719f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  double FixedToDouble(int64_t src, int fbits, FPRounding round_mode);
720f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode);
721f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  float FixedToFloat(int64_t src, int fbits, FPRounding round_mode);
722f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode);
723f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int32_t FPToInt32(double value, FPRounding rmode);
724f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int64_t FPToInt64(double value, FPRounding rmode);
725f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  uint32_t FPToUInt32(double value, FPRounding rmode);
726f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  uint64_t FPToUInt64(double value, FPRounding rmode);
727f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
728f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  template <typename T>
7296b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  T FPAdd(T op1, T op2);
730f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
731f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  template <typename T>
7326b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  T FPDiv(T op1, T op2);
7336b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
7346b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  template <typename T>
7356b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  T FPMax(T a, T b);
736f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
737f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  template <typename T>
738f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  T FPMaxNM(T a, T b);
739f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
740f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  template <typename T>
7416b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  T FPMin(T a, T b);
7426b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
7436b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  template <typename T>
744f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  T FPMinNM(T a, T b);
745f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
7466b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  template <typename T>
7476b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  T FPMul(T op1, T op2);
7486b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
7496b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  template <typename T>
7506b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  T FPMulAdd(T a, T op1, T op2);
7516b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
7526b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  template <typename T>
7536b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  T FPSqrt(T op);
7546b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
7556b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  template <typename T>
7566b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  T FPSub(T op1, T op2);
7576b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
7586b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  // Standard NaN processing.
7596b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  template <typename T>
7606b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  T FPProcessNaN(T op);
7616b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
7626b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  bool FPProcessNaNs(Instruction* instr);
7636b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
7646b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  template <typename T>
7656b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  T FPProcessNaNs(T op1, T op2);
7666b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
7676b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  template <typename T>
7686b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  T FPProcessNaNs3(T op1, T op2, T op3);
7696b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
770f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void CheckStackAlignment();
771f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
772f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline void CheckPCSComplianceAndRun();
773f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
774f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#ifdef DEBUG
775f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Corruption values should have their least significant byte cleared to
776f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // allow the code of the register being corrupted to be inserted.
777f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const uint64_t kCallerSavedRegisterCorruptionValue =
778f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      0xca11edc0de000000UL;
779f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // This value is a NaN in both 32-bit and 64-bit FP.
780f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const uint64_t kCallerSavedFPRegisterCorruptionValue =
781f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      0x7ff000007f801000UL;
782f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // This value is a mix of 32/64-bits NaN and "verbose" immediate.
783f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const uint64_t kDefaultCPURegisterCorruptionValue =
784f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      0x7ffbad007f8bad00UL;
785f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
786f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void CorruptRegisters(CPURegList* list,
787f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                        uint64_t value = kDefaultCPURegisterCorruptionValue);
788f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void CorruptAllCallerSavedCPURegisters();
789f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif
790f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
791a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org  // Pseudo Printf instruction
792a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org  void DoPrintf(Instruction* instr);
793a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org
794f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Processor state ---------------------------------------
795f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
796f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Output stream.
797f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  FILE* stream_;
798f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  PrintDisassembler* print_disasm_;
7999e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org  void PRINTF_METHOD_CHECKING TraceSim(const char* format, ...);
800f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
801f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Instrumentation.
802f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Instrument* instrument_;
803f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
804f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // General purpose registers. Register 31 is the stack pointer.
805f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  SimRegister registers_[kNumberOfRegisters];
806f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
807f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Floating point registers
808f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  SimFPRegister fpregisters_[kNumberOfFPRegisters];
809f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
810f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Processor state
811f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // bits[31, 27]: Condition flags N, Z, C, and V.
812f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //               (Negative, Zero, Carry, Overflow)
813f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  SimSystemRegister nzcv_;
814f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
815f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Floating-Point Control Register
816f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  SimSystemRegister fpcr_;
817f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
818f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Only a subset of FPCR features are supported by the simulator. This helper
819f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // checks that the FPCR settings are supported.
820f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //
821f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // This is checked when floating-point instructions are executed, not when
822f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FPCR is set. This allows generated code to modify FPCR for external
823f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // functions, or to save and restore it when entering and leaving generated
824f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // code.
825f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void AssertSupportedFPCR() {
826e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(fpcr().FZ() == 0);             // No flush-to-zero support.
827e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(fpcr().RMode() == FPTieEven);  // Ties-to-even rounding only.
828f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
829f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // The simulator does not support half-precision operations so fpcr().AHP()
830f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // is irrelevant, and is not checked here.
831f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
832f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
8331845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  template <typename T>
8341845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  static int CalcNFlag(T result) {
8351845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    return (result >> (sizeof(T) * 8 - 1)) & 1;
836f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
837f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
838f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static int CalcZFlag(uint64_t result) {
839f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return result == 0;
840f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
841f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
842f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const uint32_t kConditionFlagsMask = 0xf0000000;
843f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
844f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Stack
8452c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  uintptr_t stack_;
8462c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  static const size_t stack_protection_size_ = KB;
8472c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  size_t stack_size_;
8482c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  uintptr_t stack_limit_;
849f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
850f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Decoder<DispatchingDecoderVisitor>* decoder_;
851f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Decoder<DispatchingDecoderVisitor>* disassembler_decoder_;
852f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
853f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Indicates if the pc has been modified by the instruction and should not be
854f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // automatically incremented.
855f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool pc_modified_;
856f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Instruction* pc_;
857f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
858f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const char* xreg_names[];
859f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const char* wreg_names[];
860f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const char* sreg_names[];
861f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const char* dreg_names[];
862f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const char* vreg_names[];
863f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
864f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Debugger input.
865f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void set_last_debugger_input(char* input) {
866f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    DeleteArray(last_debugger_input_);
867f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    last_debugger_input_ = input;
868f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
869f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  char* last_debugger_input() { return last_debugger_input_; }
870f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  char* last_debugger_input_;
871f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
872f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org private:
873f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void Init(FILE* stream);
874f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
875f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int  log_parameters_;
876f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Isolate* isolate_;
877f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org};
878f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
879f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
880f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// When running with the simulator transition into simulated execution at this
881f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// point.
882f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
883f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->CallJS(    \
884f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      FUNCTION_ADDR(entry),                                                    \
885f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      p0, p1, p2, p3, p4))
886f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
887f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8)  \
888f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Simulator::current(Isolate::Current())->CallRegExp(                          \
889f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      entry,                                                                   \
890f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8)
891f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
892f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
893f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// The simulator has its own stack. Thus it has a different stack limit from
894f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// the C-based native code.
895f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// See also 'class SimulatorStack' in arm/simulator-arm.h.
896f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgclass SimulatorStack : public v8::internal::AllStatic {
897f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org public:
898f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
899f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                            uintptr_t c_limit) {
900f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return Simulator::current(isolate)->StackLimit();
901f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
902f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
903f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
904f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Simulator* sim = Simulator::current(Isolate::Current());
905f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return sim->PushAddress(try_catch_address);
906f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
907f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
908f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static void UnregisterCTryCatch() {
909f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Simulator::current(Isolate::Current())->PopAddress();
910f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
911f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org};
912f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
913f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif  // !defined(USE_SIMULATOR)
914f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
915f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} }  // namespace v8::internal
916f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
917fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#endif  // V8_ARM64_SIMULATOR_ARM64_H_
918