gem5 v24.0.0.0
Loading...
Searching...
No Matches
aapcs64.hh
Go to the documentation of this file.
1/*
2 * Copyright 2019 Google Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met: redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer;
8 * redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution;
11 * neither the name of the copyright holders nor the names of its
12 * contributors may be used to endorse or promote products derived from
13 * this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifndef __ARCH_ARM_AAPCS64_HH__
29#define __ARCH_ARM_AAPCS64_HH__
30
31#include <algorithm>
32#include <array>
33#include <type_traits>
34#include <utility>
35
36#include "arch/arm/regs/int.hh"
37#include "arch/arm/regs/vec.hh"
38#include "arch/arm/utility.hh"
39#include "base/intmath.hh"
40#include "cpu/thread_context.hh"
41#include "sim/guest_abi.hh"
42#include "sim/proxy_ptr.hh"
43
44namespace gem5
45{
46
47class ThreadContext;
48
49struct Aapcs64
50{
51 using UintPtr = uint64_t;
52
53 struct State
54 {
55 int ngrn=0; // Next general purpose register number.
56 int nsrn=0; // Next SIMD and floating point register number.
57 Addr nsaa; // Next stacked argument address.
58
59 // The maximum allowed general purpose register number.
60 static const int MAX_GRN = 7;
61 // The maximum allowed SIMD and floating point register number.
62 static const int MAX_SRN = 7;
63
64 explicit State(const ThreadContext *tc) :
65 nsaa(tc->getReg(ArmISA::int_reg::Spx))
66 {}
67 };
68};
69
70namespace guest_abi
71{
72
73/*
74 * Short Vectors
75 */
76
77// A short vector is a machine type that is composed of repeated instances of
78// one fundamental integral or floating- point type. It may be 8 or 16 bytes
79// in total size.
80
81template <typename T, typename Enabled=void>
82struct IsAapcs64ShortVector : public std::false_type {};
83
84template <typename E, size_t N>
86 typename std::enable_if_t<
87 (std::is_integral_v<E> || std::is_floating_point_v<E>) &&
88 (sizeof(E) * N == 8 || sizeof(E) * N == 16)>> :
89 public std::true_type
90{};
91
92template <typename T>
94
95/*
96 * Composite Types
97 */
98
99template <typename T, typename Enabled=void>
100struct IsAapcs64Composite : public std::false_type {};
101
102template <typename T>
103struct IsAapcs64Composite<T, typename std::enable_if_t<
104 (std::is_array_v<T> || std::is_class_v<T> || std::is_union_v<T>) &&
105 // VarArgs is technically a composite type, but it's not a normal argument.
106 !IsVarArgsV<T> &&
107 // Short vectors are also composite types, but don't treat them as one.
108 !IsAapcs64ShortVectorV<T>
109 >> : public std::true_type
110{};
111
112template <typename T>
114
115// Homogeneous Aggregates
116// These *should* be any aggregate type which has only one type of member, but
117// we can't actually detect that or manipulate that with templates. Instead,
118// we approximate that by detecting only arrays with that property.
119
120// An Homogeneous Floating-Point Aggregate (HFA) is an Homogeneous Aggregate
121// with a Fundemental Data Type that is a Floating-Point type and at most four
122// uniquely addressable members.
123
124template <typename T, typename Enabled=void>
125struct IsAapcs64Hfa : public std::false_type {};
126
127template <typename E, size_t N>
128struct IsAapcs64Hfa<E[N],
129 typename std::enable_if_t<std::is_floating_point_v<E> && N <= 4>> :
130 public std::true_type
131{};
132
133template <typename T>
135
136// An Homogeneous Short-Vector Aggregate (HVA) is an Homogeneous Aggregate with
137// a Fundamental Data Type that is a Short-Vector type and at most four
138// uniquely addressable members.
139
140template <typename T, typename Enabled=void>
141struct IsAapcs64Hva : public std::false_type {};
142
143template <typename E, size_t N>
144struct IsAapcs64Hva<E[N],
145 typename std::enable_if_t<IsAapcs64ShortVectorV<E> && N <= 4>> :
146 public std::true_type
147{};
148
149template <typename T>
151
152// A shorthand to test if a type is an HVA or an HFA.
153template <typename T, typename Enabled=void>
154struct IsAapcs64Hxa : public std::false_type {};
155
156template <typename T>
157struct IsAapcs64Hxa<T, typename std::enable_if_t<
158 IsAapcs64HfaV<T> || IsAapcs64HvaV<T>>> :
159 public std::true_type
160{};
161
162template <typename T>
164
166{
167 template <typename T>
168 static T
170 {
171 // The alignment is the larger of 8 or the natural alignment of T.
172 size_t align = std::max<size_t>(8, alignof(T));
173 // Increase the size to the next multiple of 8.
174 size_t size = roundUp(sizeof(T), 8);
175
176 // Align the stack.
177 state.nsaa = roundUp(state.nsaa, align);
178
179 // Extract the value from it.
180 ConstVPtr<T> val(state.nsaa, tc);
181
182 // Move the nsaa past this argument.
183 state.nsaa += size;
184
185 // Return the value we extracted.
186 return gtoh(*val, ArmISA::byteOrder(tc));
187 }
188};
189
190
191/*
192 * Floating point and Short-Vector arguments and return values.
193 */
194
195template <typename Float>
196struct Argument<Aapcs64, Float, typename std::enable_if_t<
197 std::is_floating_point_v<Float> || IsAapcs64ShortVectorV<Float>>> :
199{
200 static Float
202 {
203 if (state.nsrn <= state.MAX_SRN) {
204 RegId id = ArmISA::vecRegClass[state.nsrn++];
206 tc->getReg(id, &vc);
207 return vc.as<Float>()[0];
208 }
209
210 return loadFromStack<Float>(tc, state);
211 }
212};
213
214template <typename Float>
215struct Result<Aapcs64, Float, typename std::enable_if_t<
216 std::is_floating_point_v<Float> || IsAapcs64ShortVectorV<Float>>>
217{
218 static void
219 store(ThreadContext *tc, const Float &f)
220 {
223 tc->getReg(id, &reg);
224 reg.as<Float>()[0] = f;
225 tc->setReg(id, &reg);
226 }
227};
228
229
230/*
231 * Integer arguments and return values.
232 */
233
234// This will pick up Addr as well, which should be used for guest pointers.
235template <typename Integer>
236struct Argument<Aapcs64, Integer, typename std::enable_if_t<
237 std::is_integral_v<Integer> && (sizeof(Integer) <= 8)>> :
239{
240 static Integer
242 {
243 if (state.ngrn <= state.MAX_GRN)
244 return tc->getReg(ArmISA::intRegClass[state.ngrn++]);
245
246 // Max out ngrn since we've effectively saturated it.
247 state.ngrn = state.MAX_GRN + 1;
248
249 return loadFromStack<Integer>(tc, state);
250 }
251};
252
253template <typename Integer>
254struct Argument<Aapcs64, Integer, typename std::enable_if_t<
255 std::is_integral_v<Integer> && (sizeof(Integer) > 8)>> :
257{
258 static Integer
260 {
261 if (alignof(Integer) == 16 && (state.ngrn % 2))
262 state.ngrn++;
263
264 if (sizeof(Integer) == 16 && state.ngrn + 1 <= state.MAX_GRN) {
265 Integer low = tc->getReg(ArmISA::intRegClass[state.ngrn++]);
266 Integer high = tc->getReg(ArmISA::intRegClass[state.ngrn++]);
267 high = high << 64;
268 return high | low;
269 }
270
271 // Max out ngrn since we've effectively saturated it.
272 state.ngrn = state.MAX_GRN + 1;
273
274 return loadFromStack<Integer>(tc, state);
275 }
276};
277
278template <typename Integer>
279struct Result<Aapcs64, Integer, typename std::enable_if_t<
280 std::is_integral_v<Integer> && (sizeof(Integer) <= 8)>>
281{
282 static void
283 store(ThreadContext *tc, const Integer &i)
284 {
286 }
287};
288
289template <typename Integer>
290struct Result<Aapcs64, Integer, typename std::enable_if_t<
291 std::is_integral_v<Integer> && (sizeof(Integer) > 8)>>
292{
293 static void
294 store(ThreadContext *tc, const Integer &i)
295 {
296 tc->setReg(ArmISA::int_reg::X0, (uint64_t)i);
297 tc->setReg(ArmISA::int_reg::X1, (uint64_t)(i >> 64));
298 }
299};
300
301
302/*
303 * Homogeneous Floating-Point and Short-Vector Aggregates (HFAs and HVAs)
304 * argument and return values.
305 */
306
307template <typename T>
308struct Aapcs64ArrayType { using Type = void; };
309
310template <typename E, size_t N>
311struct Aapcs64ArrayType<E[N]> { using Type = E; };
312
313template <typename HA>
314struct Argument<Aapcs64, HA, typename std::enable_if_t<
315 IsAapcs64HxaV<HA>>> : public Aapcs64ArgumentBase
316{
317 static HA
319 {
320 using Elem = typename Aapcs64ArrayType<HA>::Type;
321 constexpr size_t Count = sizeof(HA) / sizeof(Elem);
322
323 if (state.nsrn + Count - 1 <= state.MAX_SRN) {
324 HA ha;
325 for (int i = 0; i < Count; i++)
327 return ha;
328 }
329
330 // Max out the nsrn since we effectively exhausted it.
331 state.nsrn = state.MAX_SRN + 1;
332
333 return loadFromStack<HA>(tc, state);
334 }
335};
336
337template <typename HA>
338struct Result<Aapcs64, HA, typename std::enable_if_t<IsAapcs64HxaV<HA>>>
339{
340 static HA
341 store(ThreadContext *tc, const HA &ha)
342 {
343 using Elem = typename Aapcs64ArrayType<HA>::Type;
344 constexpr size_t Count = sizeof(HA) / sizeof(Elem);
345
346 for (int i = 0; i < Count; i++)
348 }
349};
350
351
352/*
353 * Composite arguments and return values which are not HVAs or HFAs.
354 */
355
356template <typename Composite>
357struct Argument<Aapcs64, Composite, typename std::enable_if_t<
358 IsAapcs64CompositeV<Composite> && !IsAapcs64HxaV<Composite>>> :
360{
361 static Composite
363 {
364 if (sizeof(Composite) > 16) {
365 // Composite values larger than 16 which aren't HFAs or HVAs are
366 // kept in a buffer, and the argument is actually a pointer to that
367 // buffer.
369 ConstVPtr<Composite> composite(addr, tc);
370 return gtoh(*composite, ArmISA::byteOrder(tc));
371 }
372
373 // The size of Composite must be 16 bytes or less after this point.
374
375 size_t bytes = sizeof(Composite);
376 using Chunk = uint64_t;
377
378 const int chunk_size = sizeof(Chunk);
379 const int regs = (bytes + chunk_size - 1) / chunk_size;
380
381 // Can it fit in GPRs?
382 if (state.ngrn + regs - 1 <= state.MAX_GRN) {
383 alignas(alignof(Composite)) uint8_t buf[bytes];
384 for (int i = 0; i < regs; i++) {
385 Chunk val = tc->getReg(ArmISA::intRegClass[state.ngrn++]);
387 size_t to_copy = std::min<size_t>(bytes, chunk_size);
388 memcpy(buf + i * chunk_size, &val, to_copy);
389 bytes -= to_copy;
390 }
391 return gtoh(*(Composite *)buf, ArmISA::byteOrder(tc));
392 }
393
394 // Max out the ngrn since we effectively exhausted it.
395 state.ngrn = state.MAX_GRN;
396
397 return loadFromStack<Composite>(tc, state);
398 }
399};
400
401template <typename Composite>
402struct Result<Aapcs64, Composite, typename std::enable_if_t<
403 IsAapcs64CompositeV<Composite> && !IsAapcs64HxaV<Composite>>>
404{
405 static void
406 store(ThreadContext *tc, const Composite &c)
407 {
408 if (sizeof(Composite) > 16) {
410 VPtr<Composite> composite(addr, tc);
411 *composite = htog(c, ArmISA::byteOrder(tc));
412 return;
413 }
414
415 // The size of Composite must be 16 bytes or less after this point.
416
417 size_t bytes = sizeof(Composite);
418 using Chunk = uint64_t;
419
420 const int chunk_size = sizeof(Chunk);
421 const int regs = (bytes + chunk_size - 1) / chunk_size;
422
423 Composite cp = htog(c, ArmISA::byteOrder(tc));
424 uint8_t *buf = (uint8_t *)&cp;
425 for (int i = 0; i < regs; i++) {
426 size_t to_copy = std::min<size_t>(bytes, chunk_size);
427
428 Chunk val;
429 memcpy(&val, buf, to_copy);
431
433
434 bytes -= to_copy;
435 buf += to_copy;
436 }
437 }
438};
439
440} // namespace guest_abi
441} // namespace gem5
442
443#endif // __ARCH_ARM_AAPCS64_HH__
Register ID: describe an architectural register with its class and index.
Definition reg_class.hh:94
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual RegVal getReg(const RegId &reg) const
virtual void setReg(const RegId &reg, RegVal val)
Vector Register Abstraction This generic class is the model in a particularization of MVC,...
Definition vec_reg.hh:126
VecElem * as()
View interposers.
Definition vec_reg.hh:191
static constexpr T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition intmath.hh:260
atomic_var_t state
Definition helpers.cc:211
constexpr RegId X0
Definition int.hh:240
constexpr RegId X1
Definition int.hh:241
static RegId x(unsigned index)
Definition int.hh:445
constexpr RegId X8
Definition int.hh:248
ByteOrder byteOrder(const ThreadContext *tc)
Definition utility.hh:359
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 29 > c
Definition misc_types.hh:53
constexpr RegClass intRegClass
Definition int.hh:173
Bitfield< 6 > f
Definition misc_types.hh:68
Bitfield< 39 > ha
constexpr RegClass vecRegClass
Definition vec.hh:101
Bitfield< 5, 3 > reg
Definition types.hh:92
Bitfield< 31, 0 > E
Definition int.hh:56
Bitfield< 63 > val
Definition misc.hh:804
Bitfield< 3 > addr
Definition types.hh:84
constexpr bool IsAapcs64CompositeV
Definition aapcs64.hh:113
constexpr bool IsAapcs64HvaV
Definition aapcs64.hh:150
constexpr bool IsAapcs64HfaV
Definition aapcs64.hh:134
constexpr bool IsAapcs64HxaV
Definition aapcs64.hh:163
constexpr bool IsAapcs64ShortVectorV
Definition aapcs64.hh:93
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
T gtoh(T value, ByteOrder guest_byte_order)
Definition byteswap.hh:194
T htog(T value, ByteOrder guest_byte_order)
Definition byteswap.hh:187
Overload hash function for BasicBlockRange type.
Definition binary32.hh:81
static const int MAX_GRN
Definition aapcs64.hh:60
static const int MAX_SRN
Definition aapcs64.hh:62
State(const ThreadContext *tc)
Definition aapcs64.hh:64
uint64_t UintPtr
Definition aapcs64.hh:51
static T loadFromStack(ThreadContext *tc, Aapcs64::State &state)
Definition aapcs64.hh:169

Generated on Tue Jun 18 2024 16:23:55 for gem5 by doxygen 1.11.0