test-utils-aarch64.cc revision 23703a72b1cd9a49428bcd850429f7be381c1e63
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).
45330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlconst double kFP64SignallingNaN =
4688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    RawbitsToDouble(UINT64_C(0x7ff000007f800001));
4788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst float kFP32SignallingNaN = RawbitsToFloat(0x7f800001);
48330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
49330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl// A similar value, but as a quiet NaN.
5088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst double kFP64QuietNaN = RawbitsToDouble(UINT64_C(0x7ff800007fc00001));
5188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst float kFP32QuietNaN = RawbitsToFloat(0x7fc00001);
52330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
53330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
54ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool Equal32(uint32_t expected, const RegisterDump*, uint32_t result) {
55ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (result != expected) {
56ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    printf("Expected 0x%08" PRIx32 "\t Found 0x%08" PRIx32 "\n",
57ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl           expected, 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",
67ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl           expected, result);
68ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
69ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
70ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return expected == result;
71ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
72ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
73ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlbool Equal128(vec128_t expected, const RegisterDump*, vec128_t result) {
755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((result.h != expected.h) || (result.l != expected.l)) {
765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    printf("Expected 0x%016" PRIx64 "%016" PRIx64 "\t "
775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl           "Found 0x%016" PRIx64 "%016" PRIx64 "\n",
785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl           expected.h, expected.l, result.h, result.l);
795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
815289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  return ((expected.h == result.h) && (expected.l == result.l));
825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
85ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualFP32(float expected, const RegisterDump*, float result) {
8688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (FloatToRawbits(expected) == FloatToRawbits(result)) {
87578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return true;
88578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  } else {
896e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (std::isnan(expected) || (expected == 0.0)) {
90578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      printf("Expected 0x%08" PRIx32 "\t Found 0x%08" PRIx32 "\n",
9188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             FloatToRawbits(expected), FloatToRawbits(result));
92578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    } else {
93578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      printf("Expected %.9f (0x%08" PRIx32 ")\t "
94578645f14e122d2b87d907e298cda7e7d0babf1farmvixl             "Found %.9f (0x%08" PRIx32 ")\n",
9588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             expected, FloatToRawbits(expected),
9688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             result, FloatToRawbits(result));
97578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
98578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return false;
99ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
100ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
101ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
102ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
103ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualFP64(double expected, const RegisterDump*, double result) {
10488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (DoubleToRawbits(expected) == DoubleToRawbits(result)) {
105578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return true;
106ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
107ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1086e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (std::isnan(expected) || (expected == 0.0)) {
109578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    printf("Expected 0x%016" PRIx64 "\t Found 0x%016" PRIx64 "\n",
11088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           DoubleToRawbits(expected), DoubleToRawbits(result));
111578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  } else {
112578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    printf("Expected %.17f (0x%016" PRIx64 ")\t "
113578645f14e122d2b87d907e298cda7e7d0babf1farmvixl           "Found %.17f (0x%016" PRIx64 ")\n",
11488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           expected, DoubleToRawbits(expected),
11588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           result, DoubleToRawbits(result));
116578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
117578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  return false;
118ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
119ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
120ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
121ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool Equal32(uint32_t expected, const RegisterDump* core, const Register& reg) {
122b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(reg.Is32Bits());
123ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Retrieve the corresponding X register so we can check that the upper part
124ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // was properly cleared.
12588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int64_t result_x = core->xreg(reg.GetCode());
126b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if ((result_x & 0xffffffff00000000) != 0) {
127ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    printf("Expected 0x%08" PRIx32 "\t Found 0x%016" PRIx64 "\n",
128ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl           expected, result_x);
129ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return false;
130ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
13188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t result_w = core->wreg(reg.GetCode());
132ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return Equal32(expected, core, result_w);
133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
135ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlbool Equal64(uint64_t expected, const RegisterDump* core, const Register& reg) {
137b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(reg.Is64Bits());
13888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint64_t result = core->xreg(reg.GetCode());
139ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return Equal64(expected, core, result);
140ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
142ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1435289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlbool Equal128(uint64_t expected_h,
1445289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl              uint64_t expected_l,
1455289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl              const RegisterDump* core,
1465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl              const VRegister& vreg) {
1475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(vreg.Is128Bits());
1485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  vec128_t expected = {expected_l, expected_h};
14988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  vec128_t result = core->qreg(vreg.GetCode());
1505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  return Equal128(expected, core, result);
1515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
1525289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
154ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualFP32(float expected,
155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl               const RegisterDump* core,
156ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl               const FPRegister& fpreg) {
157b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(fpreg.Is32Bits());
158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Retrieve the corresponding D register so we can check that the upper part
159ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // was properly cleared.
16088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint64_t result_64 = core->dreg_bits(fpreg.GetCode());
161b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if ((result_64 & 0xffffffff00000000) != 0) {
162ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    printf("Expected 0x%08" PRIx32 " (%f)\t Found 0x%016" PRIx64 "\n",
16388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           FloatToRawbits(expected), expected, result_64);
164ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return false;
165ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
166578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
16788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return EqualFP32(expected, core, core->sreg(fpreg.GetCode()));
168ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
169ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
170ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
171ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualFP64(double expected,
172ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl               const RegisterDump* core,
173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl               const FPRegister& fpreg) {
174b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(fpreg.Is64Bits());
17588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return EqualFP64(expected, core, core->dreg(fpreg.GetCode()));
176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
177ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
178ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
179ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool Equal64(const Register& reg0,
180ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl             const RegisterDump* core,
181ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl             const Register& reg1) {
182b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(reg0.Is64Bits() && reg1.Is64Bits());
18388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int64_t expected = core->xreg(reg0.GetCode());
18488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int64_t result = core->xreg(reg1.GetCode());
185ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return Equal64(expected, core, result);
186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
187ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
18923703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langloisbool Equal64(uint64_t expected,
19023703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois             const RegisterDump* core,
19123703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois             const VRegister& vreg) {
19223703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois  VIXL_ASSERT(vreg.Is64Bits());
19323703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois  uint64_t result = core->dreg_bits(vreg.GetCode());
19423703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois  return Equal64(expected, core, result);
19523703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois}
19623703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois
19723703a72b1cd9a49428bcd850429f7be381c1e63Pierre Langlois
198ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlstatic char FlagN(uint32_t flags) {
199ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return (flags & NFlag) ? 'N' : 'n';
200ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
201ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
202ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
203ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlstatic char FlagZ(uint32_t flags) {
204ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return (flags & ZFlag) ? 'Z' : 'z';
205ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
206ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
207ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
208ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlstatic char FlagC(uint32_t flags) {
209ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return (flags & CFlag) ? 'C' : 'c';
210ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
211ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
212ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
213ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlstatic char FlagV(uint32_t flags) {
214ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return (flags & VFlag) ? 'V' : 'v';
215ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
216ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
217ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
218ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualNzcv(uint32_t expected, uint32_t result) {
219b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT((expected & ~NZCVFlag) == 0);
220b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT((result & ~NZCVFlag) == 0);
221ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (result != expected) {
222ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    printf("Expected: %c%c%c%c\t Found: %c%c%c%c\n",
223ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        FlagN(expected), FlagZ(expected), FlagC(expected), FlagV(expected),
224ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        FlagN(result), FlagZ(result), FlagC(result), FlagV(result));
225578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return false;
226ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
227ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
228578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  return true;
229ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
230ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
231ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
232ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualRegisters(const RegisterDump* a, const RegisterDump* b) {
233ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
234ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (a->xreg(i) != b->xreg(i)) {
235ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      printf("x%d\t Expected 0x%016" PRIx64 "\t Found 0x%016" PRIx64 "\n",
236ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl             i, a->xreg(i), b->xreg(i));
237ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return false;
238ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
239ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
240ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
241ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
242ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    uint64_t a_bits = a->dreg_bits(i);
243ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    uint64_t b_bits = b->dreg_bits(i);
244ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (a_bits != b_bits) {
245ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      printf("d%d\t Expected 0x%016" PRIx64 "\t Found 0x%016" PRIx64 "\n",
246ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl             i, a_bits, b_bits);
247ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return false;
248ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
249ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
250ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
251ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return true;
252ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
253ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
254ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
255ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlRegList PopulateRegisterArray(Register* w, Register* x, Register* r,
256ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                              int reg_size, int reg_count, RegList allowed) {
257ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  RegList list = 0;
258ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int i = 0;
259ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned n = 0; (n < kNumberOfRegisters) && (i < reg_count); n++) {
260b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    if (((UINT64_C(1) << n) & allowed) != 0) {
261ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Only assign allowed registers.
262ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (r) {
263ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        r[i] = Register(n, reg_size);
264ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
265ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (x) {
266ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        x[i] = Register(n, kXRegSize);
267ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
268ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (w) {
269ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        w[i] = Register(n, kWRegSize);
270ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
271b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      list |= (UINT64_C(1) << n);
272ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      i++;
273ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
274ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
275ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Check that we got enough registers.
276b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(CountSetBits(list, kNumberOfRegisters) == reg_count);
277ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
278ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return list;
279ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
280ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
281ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
282ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlRegList PopulateFPRegisterArray(FPRegister* s, FPRegister* d, FPRegister* v,
283ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                int reg_size, int reg_count, RegList allowed) {
284ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  RegList list = 0;
285ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int i = 0;
286ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned n = 0; (n < kNumberOfFPRegisters) && (i < reg_count); n++) {
287b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    if (((UINT64_C(1) << n) & allowed) != 0) {
288ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Only assigned allowed registers.
289ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (v) {
290ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        v[i] = FPRegister(n, reg_size);
291ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
292ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (d) {
293ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        d[i] = FPRegister(n, kDRegSize);
294ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
295ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (s) {
296ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        s[i] = FPRegister(n, kSRegSize);
297ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
298b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      list |= (UINT64_C(1) << n);
299ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      i++;
300ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
301ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
302ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Check that we got enough registers.
303b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(CountSetBits(list, kNumberOfFPRegisters) == reg_count);
304ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
305ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return list;
306ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
307ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
308ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
309ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Clobber(MacroAssembler* masm, RegList reg_list, uint64_t const value) {
310ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register first = NoReg;
311ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
312b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    if (reg_list & (UINT64_C(1) << i)) {
313ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      Register xn(i, kXRegSize);
314ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // We should never write into sp here.
315b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(!xn.Is(sp));
316ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (!xn.IsZero()) {
317ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        if (!first.IsValid()) {
318ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          // This is the first register we've hit, so construct the literal.
319ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          __ Mov(xn, value);
320ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          first = xn;
321ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        } else {
322ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          // We've already loaded the literal, so re-use the value already
323ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          // loaded into the first register we hit.
324ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          __ Mov(xn, first);
325ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
326ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
327ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
328ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
329ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
330ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
331ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
332ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid ClobberFP(MacroAssembler* masm, RegList reg_list, double const value) {
333ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  FPRegister first = NoFPReg;
334ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
335b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    if (reg_list & (UINT64_C(1) << i)) {
336ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      FPRegister dn(i, kDRegSize);
337ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (!first.IsValid()) {
338ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // This is the first register we've hit, so construct the literal.
339ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        __ Fmov(dn, value);
340ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        first = dn;
341ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
342ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // We've already loaded the literal, so re-use the value already loaded
343ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // into the first register we hit.
344ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        __ Fmov(dn, first);
345ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
346ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
347ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
348ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
349ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
350ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
351ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Clobber(MacroAssembler* masm, CPURegList reg_list) {
35288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (reg_list.GetType() == CPURegister::kRegister) {
353ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // This will always clobber X registers.
35488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Clobber(masm, reg_list.GetList());
35588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  } else if (reg_list.GetType() == CPURegister::kVRegister) {
356ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // This will always clobber D registers.
35788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ClobberFP(masm, reg_list.GetList());
358ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
359b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_UNREACHABLE();
360ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
361ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
362ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
363ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
364ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid RegisterDump::Dump(MacroAssembler* masm) {
365b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(__ StackPointer().Is(sp));
366ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
367ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that we don't unintentionally clobber any registers.
368b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope temps(masm);
369b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  temps.ExcludeAll();
370ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
371ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Preserve some temporary registers.
372ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register dump_base = x0;
373ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register dump = x1;
374ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register tmp = x2;
375ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register dump_base_w = dump_base.W();
376ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register dump_w = dump.W();
377ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register tmp_w = tmp.W();
378ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
379ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Offsets into the dump_ structure.
380ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const int x_offset = offsetof(dump_t, x_);
381ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const int w_offset = offsetof(dump_t, w_);
382ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const int d_offset = offsetof(dump_t, d_);
383ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const int s_offset = offsetof(dump_t, s_);
3845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  const int q_offset = offsetof(dump_t, q_);
385ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const int sp_offset = offsetof(dump_t, sp_);
386ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const int wsp_offset = offsetof(dump_t, wsp_);
387ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  const int flags_offset = offsetof(dump_t, flags_);
388ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
389ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Push(xzr, dump_base, dump, tmp);
390ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
391ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Load the address where we will dump the state.
392b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  __ Mov(dump_base, reinterpret_cast<uintptr_t>(&dump_));
393ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
394ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Dump the stack pointer (sp and wsp).
395ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // The stack pointer cannot be stored directly; it needs to be moved into
396ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // another register first. Also, we pushed four X registers, so we need to
397ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // compensate here.
398ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(tmp, sp, 4 * kXRegSizeInBytes);
399ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Str(tmp, MemOperand(dump_base, sp_offset));
400ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(tmp_w, wsp, 4 * kXRegSizeInBytes);
401ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Str(tmp_w, MemOperand(dump_base, wsp_offset));
402ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
403ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Dump X registers.
404ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(dump, dump_base, x_offset);
405ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfRegisters; i += 2) {
40688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    __ Stp(Register::GetXRegFromCode(i), Register::GetXRegFromCode(i + 1),
407ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl           MemOperand(dump, i * kXRegSizeInBytes));
408ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
409ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
410ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Dump W registers.
411ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(dump, dump_base, w_offset);
412ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfRegisters; i += 2) {
41388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    __ Stp(Register::GetWRegFromCode(i), Register::GetWRegFromCode(i + 1),
414ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl           MemOperand(dump, i * kWRegSizeInBytes));
415ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
416ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
417ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Dump D registers.
418ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(dump, dump_base, d_offset);
419ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfFPRegisters; i += 2) {
42088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    __ Stp(FPRegister::GetDRegFromCode(i), FPRegister::GetDRegFromCode(i + 1),
421ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl           MemOperand(dump, i * kDRegSizeInBytes));
422ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
423ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
424ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Dump S registers.
425ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(dump, dump_base, s_offset);
426ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfFPRegisters; i += 2) {
42788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    __ Stp(FPRegister::GetSRegFromCode(i), FPRegister::GetSRegFromCode(i + 1),
428ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl           MemOperand(dump, i * kSRegSizeInBytes));
429ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
430ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
4315289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Dump Q registers.
4325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  __ Add(dump, dump_base, q_offset);
4335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  for (unsigned i = 0; i < kNumberOfVRegisters; i += 2) {
43488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    __ Stp(VRegister::GetQRegFromCode(i), VRegister::GetQRegFromCode(i + 1),
4355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl           MemOperand(dump, i * kQRegSizeInBytes));
4365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
4375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
438ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Dump the flags.
439ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Mrs(tmp, NZCV);
440ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Str(tmp, MemOperand(dump_base, flags_offset));
441ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
442ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // To dump the values that were in tmp amd dump, we need a new scratch
4430f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // register. We can use any of the already dumped registers since we can
444ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // easily restore them.
445ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register dump2_base = x10;
446ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register dump2 = x11;
447b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!AreAliased(dump_base, dump, tmp, dump2_base, dump2));
448ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
449ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Don't lose the dump_ address.
450ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Mov(dump2_base, dump_base);
451ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
452ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Pop(tmp, dump, dump_base, xzr);
453ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
454ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(dump2, dump2_base, w_offset);
45588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Str(dump_base_w,
45688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois         MemOperand(dump2, dump_base.GetCode() * kWRegSizeInBytes));
45788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Str(dump_w, MemOperand(dump2, dump.GetCode() * kWRegSizeInBytes));
45888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Str(tmp_w, MemOperand(dump2, tmp.GetCode() * kWRegSizeInBytes));
459ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
460ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  __ Add(dump2, dump2_base, x_offset);
46188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Str(dump_base, MemOperand(dump2, dump_base.GetCode() * kXRegSizeInBytes));
46288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Str(dump, MemOperand(dump2, dump.GetCode() * kXRegSizeInBytes));
46388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Str(tmp, MemOperand(dump2, tmp.GetCode() * kXRegSizeInBytes));
464ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
465ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Finally, restore dump2_base and dump2.
46688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Ldr(dump2_base,
46788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois         MemOperand(dump2, dump2_base.GetCode() * kXRegSizeInBytes));
46888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  __ Ldr(dump2, MemOperand(dump2, dump2.GetCode() * kXRegSizeInBytes));
469ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
470ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  completed_ = true;
471ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
472ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
47388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}  // namespace aarch64
474ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}  // namespace vixl
475