1b78f13911bfe6eda303e91ef215c87a165aae8aeAlexandre Rames// Copyright 2014, VIXL authors
2ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// All rights reserved.
3ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
4ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Redistribution and use in source and binary forms, with or without
5ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// modification, are permitted provided that the following conditions are met:
6ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
7ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Redistributions of source code must retain the above copyright notice,
8ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     this list of conditions and the following disclaimer.
9ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Redistributions in binary form must reproduce the above copyright notice,
10ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     this list of conditions and the following disclaimer in the documentation
11ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     and/or other materials provided with the distribution.
12ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Neither the name of ARM Limited nor the names of its contributors may be
13ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     used to endorse or promote products derived from this software without
14ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     specific prior written permission.
15ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
16ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
276e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl#include <cmath>
28ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
29330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#include "test-runner.h"
30d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#include "test-utils-aarch64.h"
31b68bacb75c1ab265fc539afa93964c7f51f35589Alexandre Rames
32d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#include "aarch64/cpu-aarch64.h"
33d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#include "aarch64/disasm-aarch64.h"
34d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#include "aarch64/macro-assembler-aarch64.h"
35d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#include "aarch64/simulator-aarch64.h"
36ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
37ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#define __ masm->
38ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
39ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlnamespace vixl {
4088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisnamespace aarch64 {
41ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
42330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
43330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl// This value is a signalling NaN as both a double and as a float (taking the
44330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl// least-significant word).
45bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langloisconst double kFP64SignallingNaN = RawbitsToDouble(UINT64_C(0x7ff000007f800001));
4688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst float kFP32SignallingNaN = RawbitsToFloat(0x7f800001);
47330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
48330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl// A similar value, but as a quiet NaN.
4988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst double kFP64QuietNaN = RawbitsToDouble(UINT64_C(0x7ff800007fc00001));
5088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst float kFP32QuietNaN = RawbitsToFloat(0x7fc00001);
51330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
52330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
53ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool Equal32(uint32_t expected, const RegisterDump*, uint32_t result) {
54ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (result != expected) {
55ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    printf("Expected 0x%08" PRIx32 "\t Found 0x%08" PRIx32 "\n",
56bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           expected,
57bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           result);
58ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
59ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
60ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return expected == result;
61ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
62ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
63ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
64ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool Equal64(uint64_t expected, const RegisterDump*, uint64_t result) {
65ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (result != expected) {
66ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    printf("Expected 0x%016" PRIx64 "\t Found 0x%016" PRIx64 "\n",
67bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           expected,
68bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           result);
69ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
70ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
71ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return expected == result;
72ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
73ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
74ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlbool Equal128(vec128_t expected, const RegisterDump*, vec128_t result) {
765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((result.h != expected.h) || (result.l != expected.l)) {
77bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois    printf("Expected 0x%016" PRIx64 "%016" PRIx64
78bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           "\t "
795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl           "Found 0x%016" PRIx64 "%016" PRIx64 "\n",
80bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           expected.h,
81bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           expected.l,
82bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           result.h,
83bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           result.l);
845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  return ((expected.h == result.h) && (expected.l == result.l));
875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
895289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
90ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualFP32(float expected, const RegisterDump*, float result) {
9188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (FloatToRawbits(expected) == FloatToRawbits(result)) {
92578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return true;
93578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  } else {
946e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (std::isnan(expected) || (expected == 0.0)) {
95578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      printf("Expected 0x%08" PRIx32 "\t Found 0x%08" PRIx32 "\n",
96bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois             FloatToRawbits(expected),
97bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois             FloatToRawbits(result));
98578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    } else {
99bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois      printf("Expected %.9f (0x%08" PRIx32
100bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois             ")\t "
101578645f14e122d2b87d907e298cda7e7d0babf1farmvixl             "Found %.9f (0x%08" PRIx32 ")\n",
102bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois             expected,
103bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois             FloatToRawbits(expected),
104bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois             result,
105bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois             FloatToRawbits(result));
106578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
107578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return false;
108ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
109ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
110ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
111ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
112ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualFP64(double expected, const RegisterDump*, double result) {
11388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (DoubleToRawbits(expected) == DoubleToRawbits(result)) {
114578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return true;
115ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
116ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1176e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (std::isnan(expected) || (expected == 0.0)) {
118578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    printf("Expected 0x%016" PRIx64 "\t Found 0x%016" PRIx64 "\n",
119bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           DoubleToRawbits(expected),
120bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           DoubleToRawbits(result));
121578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  } else {
122bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois    printf("Expected %.17f (0x%016" PRIx64
123bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           ")\t "
124578645f14e122d2b87d907e298cda7e7d0babf1farmvixl           "Found %.17f (0x%016" PRIx64 ")\n",
125bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           expected,
126bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           DoubleToRawbits(expected),
127bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           result,
128bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           DoubleToRawbits(result));
129578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
130578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  return false;
131ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
132ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool Equal32(uint32_t expected, const RegisterDump* core, const Register& reg) {
135b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(reg.Is32Bits());
136ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Retrieve the corresponding X register so we can check that the upper part
137ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // was properly cleared.
13888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int64_t result_x = core->xreg(reg.GetCode());
139b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if ((result_x & 0xffffffff00000000) != 0) {
140ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    printf("Expected 0x%08" PRIx32 "\t Found 0x%016" PRIx64 "\n",
141bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           expected,
142bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           result_x);
143ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return false;
144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
14588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t result_w = core->wreg(reg.GetCode());
146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return Equal32(expected, core, result_w);
147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlbool Equal64(uint64_t expected, const RegisterDump* core, const Register& reg) {
151b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(reg.Is64Bits());
15288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint64_t result = core->xreg(reg.GetCode());
153ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return Equal64(expected, core, result);
154ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
156ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlbool Equal128(uint64_t expected_h,
1585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl              uint64_t expected_l,
1595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl              const RegisterDump* core,
1605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl              const VRegister& vreg) {
1615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(vreg.Is128Bits());
1625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  vec128_t expected = {expected_l, expected_h};
16388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  vec128_t result = core->qreg(vreg.GetCode());
1645289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  return Equal128(expected, core, result);
1655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
1665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
168ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualFP32(float expected,
169ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl               const RegisterDump* core,
170ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl               const FPRegister& fpreg) {
171b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(fpreg.Is32Bits());
172ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Retrieve the corresponding D register so we can check that the upper part
173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // was properly cleared.
17488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint64_t result_64 = core->dreg_bits(fpreg.GetCode());
175b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if ((result_64 & 0xffffffff00000000) != 0) {
176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    printf("Expected 0x%08" PRIx32 " (%f)\t Found 0x%016" PRIx64 "\n",
177bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           FloatToRawbits(expected),
178bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           expected,
179bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           result_64);
180ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return false;
181ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
182578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
18388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return EqualFP32(expected, core, core->sreg(fpreg.GetCode()));
184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
185ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
187ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualFP64(double expected,
188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl               const RegisterDump* core,
189ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl               const FPRegister& fpreg) {
190b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(fpreg.Is64Bits());
19188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return EqualFP64(expected, core, core->dreg(fpreg.GetCode()));
192ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
193ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
194ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
195ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool Equal64(const Register& reg0,
196ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl             const RegisterDump* core,
197ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl             const Register& reg1) {
198b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(reg0.Is64Bits() && reg1.Is64Bits());
19988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int64_t expected = core->xreg(reg0.GetCode());
20088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int64_t result = core->xreg(reg1.GetCode());
201ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return Equal64(expected, core, result);
202ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
203ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
204ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
20523703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langloisbool Equal64(uint64_t expected,
20623703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois             const RegisterDump* core,
20723703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois             const VRegister& vreg) {
20823703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois  VIXL_ASSERT(vreg.Is64Bits());
20923703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois  uint64_t result = core->dreg_bits(vreg.GetCode());
21023703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois  return Equal64(expected, core, result);
21123703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois}
21223703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois
21323703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois
214bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langloisstatic char FlagN(uint32_t flags) { return (flags & NFlag) ? 'N' : 'n'; }
215ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
216ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
217bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langloisstatic char FlagZ(uint32_t flags) { return (flags & ZFlag) ? 'Z' : 'z'; }
218ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
219ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
220bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langloisstatic char FlagC(uint32_t flags) { return (flags & CFlag) ? 'C' : 'c'; }
221ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
222ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
223bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langloisstatic char FlagV(uint32_t flags) { return (flags & VFlag) ? 'V' : 'v'; }
224ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
225ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
226ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualNzcv(uint32_t expected, uint32_t result) {
227b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT((expected & ~NZCVFlag) == 0);
228b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT((result & ~NZCVFlag) == 0);
229ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (result != expected) {
230ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    printf("Expected: %c%c%c%c\t Found: %c%c%c%c\n",
231bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           FlagN(expected),
232bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           FlagZ(expected),
233bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           FlagC(expected),
234bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           FlagV(expected),
235bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           FlagN(result),
236bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           FlagZ(result),
237bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           FlagC(result),
238bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           FlagV(result));
239578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return false;
240ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
241ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
242578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  return true;
243ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
244ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
245ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
246ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualRegisters(const RegisterDump* a, const RegisterDump* b) {
247ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
248ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (a->xreg(i) != b->xreg(i)) {
249ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      printf("x%d\t Expected 0x%016" PRIx64 "\t Found 0x%016" PRIx64 "\n",
250bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois             i,
251bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois             a->xreg(i),
252bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois             b->xreg(i));
253ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return false;
254ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
255ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
256ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
257ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
258ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    uint64_t a_bits = a->dreg_bits(i);
259ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    uint64_t b_bits = b->dreg_bits(i);
260ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (a_bits != b_bits) {
261ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      printf("d%d\t Expected 0x%016" PRIx64 "\t Found 0x%016" PRIx64 "\n",
262bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois             i,
263bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois             a_bits,
264bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois             b_bits);
265ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return false;
266ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
267ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
268ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
269ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return true;
270ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
271ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
272ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
273bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre LangloisRegList PopulateRegisterArray(Register* w,
274bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois                              Register* x,
275bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois                              Register* r,
276bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois                              int reg_size,
277bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois                              int reg_count,
278bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois                              RegList allowed) {
279ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  RegList list = 0;
280ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int i = 0;
281ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned n = 0; (n < kNumberOfRegisters) && (i < reg_count); n++) {
282b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    if (((UINT64_C(1) << n) & allowed) != 0) {
283ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Only assign allowed registers.
284ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (r) {
285ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        r[i] = Register(n, reg_size);
286ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
287ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (x) {
288ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        x[i] = Register(n, kXRegSize);
289ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
290ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (w) {
291ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        w[i] = Register(n, kWRegSize);
292ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
293b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      list |= (UINT64_C(1) << n);
294ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      i++;
295ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
296ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
297ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Check that we got enough registers.
298b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(CountSetBits(list, kNumberOfRegisters) == reg_count);
299ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
300ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return list;
301ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
302ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
303ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
304bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre LangloisRegList PopulateFPRegisterArray(FPRegister* s,
305bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois                                FPRegister* d,
306bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois                                FPRegister* v,
307bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois                                int reg_size,
308bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois                                int reg_count,
309bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois                                RegList allowed) {
310ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  RegList list = 0;
311ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int i = 0;
312ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned n = 0; (n < kNumberOfFPRegisters) && (i < reg_count); n++) {
313b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    if (((UINT64_C(1) << n) & allowed) != 0) {
314ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Only assigned allowed registers.
315ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (v) {
316ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        v[i] = FPRegister(n, reg_size);
317ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
318ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (d) {
319ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        d[i] = FPRegister(n, kDRegSize);
320ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
321ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (s) {
322ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        s[i] = FPRegister(n, kSRegSize);
323ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
324b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      list |= (UINT64_C(1) << n);
325ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      i++;
326ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
327ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
328ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Check that we got enough registers.
329b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(CountSetBits(list, kNumberOfFPRegisters) == reg_count);
330ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
331ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return list;
332ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
333ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
334ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
335ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Clobber(MacroAssembler* masm, RegList reg_list, uint64_t const value) {
336ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register first = NoReg;
337ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
338b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    if (reg_list & (UINT64_C(1) << i)) {
339ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      Register xn(i, kXRegSize);
340ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // We should never write into sp here.
341b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(!xn.Is(sp));
342ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (!xn.IsZero()) {
343ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        if (!first.IsValid()) {
344ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          // This is the first register we've hit, so construct the literal.
345ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          __ Mov(xn, value);
346ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          first = xn;
347ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        } else {
348ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          // We've already loaded the literal, so re-use the value already
349ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          // loaded into the first register we hit.
350ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          __ Mov(xn, first);
351ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
352ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
353ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
354ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
355ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
356ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
357ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
358ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid ClobberFP(MacroAssembler* masm, RegList reg_list, double const value) {
359ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  FPRegister first = NoFPReg;
360ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
361b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    if (reg_list & (UINT64_C(1) << i)) {
362ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      FPRegister dn(i, kDRegSize);
363ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (!first.IsValid()) {
364ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // This is the first register we've hit, so construct the literal.
365ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        __ Fmov(dn, value);
366ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        first = dn;
367ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
368ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // We've already loaded the literal, so re-use the value already loaded
369ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // into the first register we hit.
370ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        __ Fmov(dn, first);
371ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
372ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
373ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
374ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
375ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
376ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
377ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Clobber(MacroAssembler* masm, CPURegList reg_list) {
37888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (reg_list.GetType() == CPURegister::kRegister) {
379ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // This will always clobber X registers.
38088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Clobber(masm, reg_list.GetList());
38188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  } else if (reg_list.GetType() == CPURegister::kVRegister) {
382ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // This will always clobber D registers.
38388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ClobberFP(masm, reg_list.GetList());
384ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
385b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_UNREACHABLE();
386ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
387ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
388ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
389ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
390ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid RegisterDump::Dump(MacroAssembler* masm) {
391b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(__ StackPointer().Is(sp));
392ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
393ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that we don't unintentionally clobber any registers.
394b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope temps(masm);
395b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  temps.ExcludeAll();
396ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
397ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Preserve some temporary registers.
398ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register dump_base = x0;
399ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register dump = x1;
400ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register tmp = x2;
401ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register dump_base_w = dump_base.W();
402ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register dump_w = dump.W();
403ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register tmp_w = tmp.W();
404ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
405ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Offsets into the dump_ structure.
406ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const int x_offset = offsetof(dump_t, x_);
407ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const int w_offset = offsetof(dump_t, w_);
408ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const int d_offset = offsetof(dump_t, d_);
409ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const int s_offset = offsetof(dump_t, s_);
4105289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  const int q_offset = offsetof(dump_t, q_);
411ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const int sp_offset = offsetof(dump_t, sp_);
412ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const int wsp_offset = offsetof(dump_t, wsp_);
413ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const int flags_offset = offsetof(dump_t, flags_);
414ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
415ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Push(xzr, dump_base, dump, tmp);
416ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
417ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Load the address where we will dump the state.
418b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  __ Mov(dump_base, reinterpret_cast<uintptr_t>(&dump_));
419ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
420ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Dump the stack pointer (sp and wsp).
421ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // The stack pointer cannot be stored directly; it needs to be moved into
422ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // another register first. Also, we pushed four X registers, so we need to
423ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // compensate here.
424ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(tmp, sp, 4 * kXRegSizeInBytes);
425ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Str(tmp, MemOperand(dump_base, sp_offset));
426ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(tmp_w, wsp, 4 * kXRegSizeInBytes);
427ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Str(tmp_w, MemOperand(dump_base, wsp_offset));
428ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
429ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Dump X registers.
430ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(dump, dump_base, x_offset);
431ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfRegisters; i += 2) {
432bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois    __ Stp(Register::GetXRegFromCode(i),
433bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           Register::GetXRegFromCode(i + 1),
434ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl           MemOperand(dump, i * kXRegSizeInBytes));
435ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
436ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
437ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Dump W registers.
438ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(dump, dump_base, w_offset);
439ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfRegisters; i += 2) {
440bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois    __ Stp(Register::GetWRegFromCode(i),
441bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           Register::GetWRegFromCode(i + 1),
442ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl           MemOperand(dump, i * kWRegSizeInBytes));
443ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
444ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
445ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Dump D registers.
446ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(dump, dump_base, d_offset);
447ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfFPRegisters; i += 2) {
448bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois    __ Stp(FPRegister::GetDRegFromCode(i),
449bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           FPRegister::GetDRegFromCode(i + 1),
450ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl           MemOperand(dump, i * kDRegSizeInBytes));
451ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
452ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
453ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Dump S registers.
454ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(dump, dump_base, s_offset);
455ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfFPRegisters; i += 2) {
456bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois    __ Stp(FPRegister::GetSRegFromCode(i),
457bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           FPRegister::GetSRegFromCode(i + 1),
458ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl           MemOperand(dump, i * kSRegSizeInBytes));
459ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
460ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
4615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Dump Q registers.
4625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  __ Add(dump, dump_base, q_offset);
4635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  for (unsigned i = 0; i < kNumberOfVRegisters; i += 2) {
464bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois    __ Stp(VRegister::GetQRegFromCode(i),
465bde2e4b5ce376456d50a972b6f3aaee3475f8786Pierre Langlois           VRegister::GetQRegFromCode(i + 1),
4665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl           MemOperand(dump, i * kQRegSizeInBytes));
4675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
4685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
469ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Dump the flags.
470ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Mrs(tmp, NZCV);
471ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Str(tmp, MemOperand(dump_base, flags_offset));
472ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
473ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // To dump the values that were in tmp amd dump, we need a new scratch
4740f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // register. We can use any of the already dumped registers since we can
475ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // easily restore them.
476ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register dump2_base = x10;
477ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register dump2 = x11;
478b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!AreAliased(dump_base, dump, tmp, dump2_base, dump2));
479ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
480ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Don't lose the dump_ address.
481ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Mov(dump2_base, dump_base);
482ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
483ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Pop(tmp, dump, dump_base, xzr);
484ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
485ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(dump2, dump2_base, w_offset);
48688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Str(dump_base_w,
48788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois         MemOperand(dump2, dump_base.GetCode() * kWRegSizeInBytes));
48888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Str(dump_w, MemOperand(dump2, dump.GetCode() * kWRegSizeInBytes));
48988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Str(tmp_w, MemOperand(dump2, tmp.GetCode() * kWRegSizeInBytes));
490ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
491ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(dump2, dump2_base, x_offset);
49288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Str(dump_base, MemOperand(dump2, dump_base.GetCode() * kXRegSizeInBytes));
49388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Str(dump, MemOperand(dump2, dump.GetCode() * kXRegSizeInBytes));
49488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Str(tmp, MemOperand(dump2, tmp.GetCode() * kXRegSizeInBytes));
495ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
496ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Finally, restore dump2_base and dump2.
49788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Ldr(dump2_base,
49888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois         MemOperand(dump2, dump2_base.GetCode() * kXRegSizeInBytes));
49988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Ldr(dump2, MemOperand(dump2, dump2.GetCode() * kXRegSizeInBytes));
500ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
501ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  completed_ = true;
502ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
503ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
50488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}  // namespace aarch64
505ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}  // namespace vixl
506