1ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Copyright 2013, ARM Limited
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
27ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#ifndef VIXL_A64_TEST_UTILS_A64_H_
28ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#define VIXL_A64_TEST_UTILS_A64_H_
29ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
30ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include "cctest.h"
31ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include "a64/macro-assembler-a64.h"
32ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include "a64/simulator-a64.h"
33ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include "a64/disasm-a64.h"
34ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include "a64/cpu-a64.h"
35ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
36ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlnamespace vixl {
37ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
38ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// RegisterDump: Object allowing integer, floating point and flags registers
39ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// to be saved to itself for future reference.
40ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlclass RegisterDump {
41ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl public:
42ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  RegisterDump() : completed_(false) {
431123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(sizeof(dump_.d_[0]) == kDRegSizeInBytes);
441123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(sizeof(dump_.s_[0]) == kSRegSizeInBytes);
451123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(sizeof(dump_.d_[0]) == kXRegSizeInBytes);
461123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(sizeof(dump_.s_[0]) == kWRegSizeInBytes);
471123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(sizeof(dump_.x_[0]) == kXRegSizeInBytes);
481123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(sizeof(dump_.w_[0]) == kWRegSizeInBytes);
49ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
50ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
51ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // The Dump method generates code to store a snapshot of the register values.
52ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // It needs to be able to use the stack temporarily, and requires that the
53ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // current stack pointer is sp, and is properly aligned.
54ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  //
55ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // The dumping code is generated though the given MacroAssembler. No registers
56ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // are corrupted in the process, but the stack is used briefly. The flags will
57ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // be corrupted during this call.
58ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  void Dump(MacroAssembler* assm);
59ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
60ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Register accessors.
61ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline int32_t wreg(unsigned code) const {
62ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (code == kSPRegInternalCode) {
63ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return wspreg();
64ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
651123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(RegAliasesMatch(code));
66ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return dump_.w_[code];
67ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
68ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
69ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline int64_t xreg(unsigned code) const {
70ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (code == kSPRegInternalCode) {
71ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return spreg();
72ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(RegAliasesMatch(code));
74ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return dump_.x_[code];
75ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
76ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
77ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // FPRegister accessors.
78ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline uint32_t sreg_bits(unsigned code) const {
791123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(FPRegAliasesMatch(code));
80ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return dump_.s_[code];
81ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
82ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
83ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline float sreg(unsigned code) const {
84ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return rawbits_to_float(sreg_bits(code));
85ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
86ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
87ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline uint64_t dreg_bits(unsigned code) const {
881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(FPRegAliasesMatch(code));
89ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return dump_.d_[code];
90ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
91ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
92ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline double dreg(unsigned code) const {
93ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return rawbits_to_double(dreg_bits(code));
94ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
95ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
96ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Stack pointer accessors.
97ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline int64_t spreg() const {
981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(SPRegAliasesMatch());
99ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return dump_.sp_;
100ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
101ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
102ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline int64_t wspreg() const {
1031123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(SPRegAliasesMatch());
104ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return dump_.wsp_;
105ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
106ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
107ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Flags accessors.
108ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline uint64_t flags_nzcv() const {
1091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(IsComplete());
1101123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT((dump_.flags_ & ~Flags_mask) == 0);
111ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return dump_.flags_ & Flags_mask;
112ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
113ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
114ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  inline bool IsComplete() const {
115ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return completed_;
116ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
117ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
118ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl private:
119ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Indicate whether the dump operation has been completed.
120ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool completed_;
121ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
122ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Check that the lower 32 bits of x<code> exactly match the 32 bits of
123ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // w<code>. A failure of this test most likely represents a failure in the
124ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // ::Dump method, or a failure in the simulator.
125ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool RegAliasesMatch(unsigned code) const {
1261123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(IsComplete());
1271123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(code < kNumberOfRegisters);
128ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return ((dump_.x_[code] & kWRegMask) == dump_.w_[code]);
129ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
130ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
131ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // As RegAliasesMatch, but for the stack pointer.
132ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool SPRegAliasesMatch() const {
1331123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(IsComplete());
134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return ((dump_.sp_ & kWRegMask) == dump_.wsp_);
135ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
136ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
137ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // As RegAliasesMatch, but for floating-point registers.
138ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool FPRegAliasesMatch(unsigned code) const {
1391123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(IsComplete());
1401123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(code < kNumberOfFPRegisters);
141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return (dump_.d_[code] & kSRegMask) == dump_.s_[code];
142ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
143ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Store all the dumped elements in a simple struct so the implementation can
145ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // use offsetof to quickly find the correct field.
146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  struct dump_t {
147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Core registers.
148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    uint64_t x_[kNumberOfRegisters];
149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    uint32_t w_[kNumberOfRegisters];
150ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
151ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Floating-point registers, as raw bits.
152ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    uint64_t d_[kNumberOfFPRegisters];
153ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    uint32_t s_[kNumberOfFPRegisters];
154ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The stack pointer.
156ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    uint64_t sp_;
157ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    uint64_t wsp_;
158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
159ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // NZCV flags, stored in bits 28 to 31.
160ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // bit[31] : Negative
161ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // bit[30] : Zero
162ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // bit[29] : Carry
163ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // bit[28] : oVerflow
164ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    uint64_t flags_;
165ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } dump_;
166ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl};
167ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
168ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Some of these methods don't use the RegisterDump argument, but they have to
169ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// accept them so that they can overload those that take register arguments.
170ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool Equal32(uint32_t expected, const RegisterDump*, uint32_t result);
171ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool Equal64(uint64_t expected, const RegisterDump*, uint64_t result);
172ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualFP32(float expected, const RegisterDump*, float result);
174ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualFP64(double expected, const RegisterDump*, double result);
175ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool Equal32(uint32_t expected, const RegisterDump* core, const Register& reg);
177ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool Equal64(uint64_t expected, const RegisterDump* core, const Register& reg);
178ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
179ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualFP32(float expected, const RegisterDump* core,
180ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl               const FPRegister& fpreg);
181ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualFP64(double expected, const RegisterDump* core,
182ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl               const FPRegister& fpreg);
183ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool Equal64(const Register& reg0, const RegisterDump* core,
185ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl             const Register& reg1);
186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
187ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualNzcv(uint32_t expected, uint32_t result);
188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
189ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlbool EqualRegisters(const RegisterDump* a, const RegisterDump* b);
190ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
191ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Populate the w, x and r arrays with registers from the 'allowed' mask. The
192ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// r array will be populated with <reg_size>-sized registers,
193ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
194ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// This allows for tests which use large, parameterized blocks of registers
195ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// (such as the push and pop tests), but where certain registers must be
196ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// avoided as they are used for other purposes.
197ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
198ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Any of w, x, or r can be NULL if they are not required.
199ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
200ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// The return value is a RegList indicating which registers were allocated.
201ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlRegList PopulateRegisterArray(Register* w, Register* x, Register* r,
202ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                              int reg_size, int reg_count, RegList allowed);
203ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
204ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// As PopulateRegisterArray, but for floating-point registers.
205ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlRegList PopulateFPRegisterArray(FPRegister* s, FPRegister* d, FPRegister* v,
206ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                int reg_size, int reg_count, RegList allowed);
207ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
208ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Ovewrite the contents of the specified registers. This enables tests to
209ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// check that register contents are written in cases where it's likely that the
210ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// correct outcome could already be stored in the register.
211ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
212ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// This always overwrites X-sized registers. If tests are operating on W
213ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// registers, a subsequent write into an aliased W register should clear the
214ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// top word anyway, so clobbering the full X registers should make tests more
215ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// rigorous.
216ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Clobber(MacroAssembler* masm, RegList reg_list,
2171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl             uint64_t const value = 0xfedcba9876543210);
218ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
219ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// As Clobber, but for FP registers.
220ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid ClobberFP(MacroAssembler* masm, RegList reg_list,
221ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl               double const value = kFP64SignallingNaN);
222ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
223ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// As Clobber, but for a CPURegList with either FP or integer registers. When
224ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// using this method, the clobber value is always the default for the basic
225ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Clobber or ClobberFP functions.
226ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Clobber(MacroAssembler* masm, CPURegList reg_list);
227ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
228ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
229ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}  // namespace vixl
230ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
231ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#endif  // VIXL_A64_TEST_UTILS_A64_H_
232