gem5  v21.2.1.1
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/utility.hh"
38 #include "base/intmath.hh"
39 #include "cpu/thread_context.hh"
40 #include "sim/guest_abi.hh"
41 #include "sim/proxy_ptr.hh"
42 
43 namespace gem5
44 {
45 
46 class ThreadContext;
47 
48 struct Aapcs64
49 {
50  using UintPtr = uint64_t;
51 
52  struct State
53  {
54  int ngrn=0; // Next general purpose register number.
55  int nsrn=0; // Next SIMD and floating point register number.
56  Addr nsaa; // Next stacked argument address.
57 
58  // The maximum allowed general purpose register number.
59  static const int MAX_GRN = 7;
60  // The maximum allowed SIMD and floating point register number.
61  static const int MAX_SRN = 7;
62 
63  explicit State(const ThreadContext *tc) :
64  nsaa(tc->readIntReg(ArmISA::INTREG_SPX))
65  {}
66  };
67 };
68 
69 GEM5_DEPRECATED_NAMESPACE(GuestABI, guest_abi);
70 namespace 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 
81 template <typename T, typename Enabled=void>
82 struct IsAapcs64ShortVector : public std::false_type {};
83 
84 template <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 
92 template <typename T>
94 
95 /*
96  * Composite Types
97  */
98 
99 template <typename T, typename Enabled=void>
100 struct IsAapcs64Composite : public std::false_type {};
101 
102 template <typename T>
103 struct 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 
112 template <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 
124 template <typename T, typename Enabled=void>
125 struct IsAapcs64Hfa : public std::false_type {};
126 
127 template <typename E, size_t N>
128 struct IsAapcs64Hfa<E[N],
129  typename std::enable_if_t<std::is_floating_point_v<E> && N <= 4>> :
130  public std::true_type
131 {};
132 
133 template <typename T>
134 constexpr bool IsAapcs64HfaV = IsAapcs64Hfa<T>::value;
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 
140 template <typename T, typename Enabled=void>
141 struct IsAapcs64Hva : public std::false_type {};
142 
143 template <typename E, size_t N>
144 struct IsAapcs64Hva<E[N],
145  typename std::enable_if_t<IsAapcs64ShortVectorV<E> && N <= 4>> :
146  public std::true_type
147 {};
148 
149 template <typename T>
150 constexpr bool IsAapcs64HvaV = IsAapcs64Hva<T>::value;
151 
152 // A shorthand to test if a type is an HVA or an HFA.
153 template <typename T, typename Enabled=void>
154 struct IsAapcs64Hxa : public std::false_type {};
155 
156 template <typename T>
157 struct IsAapcs64Hxa<T, typename std::enable_if_t<
158  IsAapcs64HfaV<T> || IsAapcs64HvaV<T>>> :
159  public std::true_type
160 {};
161 
162 template <typename T>
163 constexpr bool IsAapcs64HxaV = IsAapcs64Hxa<T>::value;
164 
165 struct Aapcs64ArgumentBase
166 {
167  template <typename T>
168  static T
169  loadFromStack(ThreadContext *tc, Aapcs64::State &state)
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 
195 template <typename Float>
196 struct Argument<Aapcs64, Float, typename std::enable_if_t<
197  std::is_floating_point_v<Float> || IsAapcs64ShortVectorV<Float>>> :
198  public Aapcs64ArgumentBase
199 {
200  static Float
201  get(ThreadContext *tc, Aapcs64::State &state)
202  {
203  if (state.nsrn <= state.MAX_SRN) {
204  RegId id(VecRegClass, state.nsrn++);
205  return tc->readVecReg(id).as<Float>()[0];
206  }
207 
208  return loadFromStack<Float>(tc, state);
209  }
210 };
211 
212 template <typename Float>
213 struct Result<Aapcs64, Float, typename std::enable_if_t<
214  std::is_floating_point_v<Float> || IsAapcs64ShortVectorV<Float>>>
215 {
216  static void
217  store(ThreadContext *tc, const Float &f)
218  {
219  RegId id(VecRegClass, 0);
220  auto reg = tc->readVecReg(id);
221  reg.as<Float>()[0] = f;
222  tc->setVecReg(id, reg);
223  }
224 };
225 
226 
227 /*
228  * Integer arguments and return values.
229  */
230 
231 // This will pick up Addr as well, which should be used for guest pointers.
232 template <typename Integer>
233 struct Argument<Aapcs64, Integer, typename std::enable_if_t<
234  std::is_integral_v<Integer> && (sizeof(Integer) <= 8)>> :
235  public Aapcs64ArgumentBase
236 {
237  static Integer
239  {
240  if (state.ngrn <= state.MAX_GRN)
241  return tc->readIntReg(state.ngrn++);
242 
243  // Max out ngrn since we've effectively saturated it.
244  state.ngrn = state.MAX_GRN + 1;
245 
246  return loadFromStack<Integer>(tc, state);
247  }
248 };
249 
250 template <typename Integer>
251 struct Argument<Aapcs64, Integer, typename std::enable_if_t<
252  std::is_integral_v<Integer> && (sizeof(Integer) > 8)>> :
253  public Aapcs64ArgumentBase
254 {
255  static Integer
256  get(ThreadContext *tc, Aapcs64::State &state)
257  {
258  if (alignof(Integer) == 16 && (state.ngrn % 2))
259  state.ngrn++;
260 
261  if (sizeof(Integer) == 16 && state.ngrn + 1 <= state.MAX_GRN) {
262  Integer low = tc->readIntReg(state.ngrn++);
263  Integer high = tc->readIntReg(state.ngrn++);
264  high = high << 64;
265  return high | low;
266  }
267 
268  // Max out ngrn since we've effectively saturated it.
269  state.ngrn = state.MAX_GRN + 1;
270 
271  return loadFromStack<Integer>(tc, state);
272  }
273 };
274 
275 template <typename Integer>
276 struct Result<Aapcs64, Integer, typename std::enable_if_t<
277  std::is_integral_v<Integer> && (sizeof(Integer) <= 8)>>
278 {
279  static void
280  store(ThreadContext *tc, const Integer &i)
281  {
282  tc->setIntReg(0, i);
283  }
284 };
285 
286 template <typename Integer>
287 struct Result<Aapcs64, Integer, typename std::enable_if_t<
288  std::is_integral_v<Integer> && (sizeof(Integer) > 8)>>
289 {
290  static void
291  store(ThreadContext *tc, const Integer &i)
292  {
293  tc->setIntReg(0, (uint64_t)i);
294  tc->setIntReg(1, (uint64_t)(i >> 64));
295  }
296 };
297 
298 
299 /*
300  * Homogeneous Floating-Point and Short-Vector Aggregates (HFAs and HVAs)
301  * argument and return values.
302  */
303 
304 template <typename T>
305 struct Aapcs64ArrayType { using Type = void; };
306 
307 template <typename E, size_t N>
308 struct Aapcs64ArrayType<E[N]> { using Type = E; };
309 
310 template <typename HA>
311 struct Argument<Aapcs64, HA, typename std::enable_if_t<
312  IsAapcs64HxaV<HA>>> : public Aapcs64ArgumentBase
313 {
314  static HA
316  {
317  using Elem = typename Aapcs64ArrayType<HA>::Type;
318  constexpr size_t Count = sizeof(HA) / sizeof(Elem);
319 
320  if (state.nsrn + Count - 1 <= state.MAX_SRN) {
321  HA ha;
322  for (int i = 0; i < Count; i++)
323  ha[i] = Argument<Aapcs64, Elem>::get(tc, state);
324  return ha;
325  }
326 
327  // Max out the nsrn since we effectively exhausted it.
328  state.nsrn = state.MAX_SRN + 1;
329 
330  return loadFromStack<HA>(tc, state);
331  }
332 };
333 
334 template <typename HA>
335 struct Result<Aapcs64, HA, typename std::enable_if_t<IsAapcs64HxaV<HA>>>
336 {
337  static HA
338  store(ThreadContext *tc, const HA &ha)
339  {
340  using Elem = typename Aapcs64ArrayType<HA>::Type;
341  constexpr size_t Count = sizeof(HA) / sizeof(Elem);
342 
343  for (int i = 0; i < Count; i++)
345  }
346 };
347 
348 
349 /*
350  * Composite arguments and return values which are not HVAs or HFAs.
351  */
352 
353 template <typename Composite>
354 struct Argument<Aapcs64, Composite, typename std::enable_if_t<
355  IsAapcs64CompositeV<Composite> && !IsAapcs64HxaV<Composite>>> :
356  public Aapcs64ArgumentBase
357 {
358  static Composite
360  {
361  if (sizeof(Composite) > 16) {
362  // Composite values larger than 16 which aren't HFAs or HVAs are
363  // kept in a buffer, and the argument is actually a pointer to that
364  // buffer.
366  ConstVPtr<Composite> composite(addr, tc);
367  return gtoh(*composite, ArmISA::byteOrder(tc));
368  }
369 
370  // The size of Composite must be 16 bytes or less after this point.
371 
372  size_t bytes = sizeof(Composite);
373  using Chunk = uint64_t;
374 
375  const int chunk_size = sizeof(Chunk);
376  const int regs = (bytes + chunk_size - 1) / chunk_size;
377 
378  // Can it fit in GPRs?
379  if (state.ngrn + regs - 1 <= state.MAX_GRN) {
380  alignas(alignof(Composite)) uint8_t buf[bytes];
381  for (int i = 0; i < regs; i++) {
382  Chunk val = tc->readIntReg(state.ngrn++);
383  val = htog(val, ArmISA::byteOrder(tc));
384  size_t to_copy = std::min<size_t>(bytes, chunk_size);
385  memcpy(buf + i * chunk_size, &val, to_copy);
386  bytes -= to_copy;
387  }
388  return gtoh(*(Composite *)buf, ArmISA::byteOrder(tc));
389  }
390 
391  // Max out the ngrn since we effectively exhausted it.
392  state.ngrn = state.MAX_GRN;
393 
394  return loadFromStack<Composite>(tc, state);
395  }
396 };
397 
398 template <typename Composite>
399 struct Result<Aapcs64, Composite, typename std::enable_if_t<
400  IsAapcs64CompositeV<Composite> && !IsAapcs64HxaV<Composite>>>
401 {
402  static void
403  store(ThreadContext *tc, const Composite &c)
404  {
405  if (sizeof(Composite) > 16) {
406  Addr addr = tc->readIntReg(ArmISA::INTREG_X8);
407  VPtr<Composite> composite(addr, tc);
408  *composite = htog(c, ArmISA::byteOrder(tc));
409  return;
410  }
411 
412  // The size of Composite must be 16 bytes or less after this point.
413 
414  size_t bytes = sizeof(Composite);
415  using Chunk = uint64_t;
416 
417  const int chunk_size = sizeof(Chunk);
418  const int regs = (bytes + chunk_size - 1) / chunk_size;
419 
420  Composite cp = htog(c, ArmISA::byteOrder(tc));
421  uint8_t *buf = (uint8_t *)&cp;
422  for (int i = 0; i < regs; i++) {
423  size_t to_copy = std::min<size_t>(bytes, chunk_size);
424 
425  Chunk val;
426  memcpy(&val, buf, to_copy);
427  val = gtoh(val, ArmISA::byteOrder(tc));
428 
429  tc->setIntReg(i, val);
430 
431  bytes -= to_copy;
432  buf += to_copy;
433  }
434  }
435 };
436 
437 } // namespace guest_abi
438 } // namespace gem5
439 
440 #endif // __ARCH_ARM_AAPCS64_HH__
gem5::ThreadContext::setIntReg
virtual void setIntReg(RegIndex reg_idx, RegVal val)=0
gem5::ConstProxyPtr
Definition: proxy_ptr.hh:109
gem5::Aapcs64::State::nsrn
int nsrn
Definition: aapcs64.hh:55
gem5::statistics::Result
double Result
All results are doubles.
Definition: types.hh:56
gem5::ArmISA::f
Bitfield< 6 > f
Definition: misc_types.hh:68
gem5::X86ISA::val
Bitfield< 63 > val
Definition: misc.hh:775
gem5::ArmISA::byteOrder
ByteOrder byteOrder(const ThreadContext *tc)
Definition: utility.hh:365
proxy_ptr.hh
gem5::guest_abi::Aapcs64ArrayType< E[N]>::Type
E Type
Definition: aapcs64.hh:308
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
sc_dt::align
void align(const scfx_rep &lhs, const scfx_rep &rhs, int &new_wp, int &len_mant, scfx_mant_ref &lhs_mant, scfx_mant_ref &rhs_mant)
Definition: scfx_rep.cc:2083
gem5::Aapcs64::UintPtr
uint64_t UintPtr
Definition: aapcs64.hh:50
gem5::guest_abi::Argument< Aapcs64, Composite, typename std::enable_if_t< IsAapcs64CompositeV< Composite > &&!IsAapcs64HxaV< Composite > > >::get
static Composite get(ThreadContext *tc, Aapcs64::State &state)
Definition: aapcs64.hh:359
gem5::Aapcs64::State::MAX_GRN
static const int MAX_GRN
Definition: aapcs64.hh:59
gem5::high
high
Definition: intmath.hh:176
gem5::ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:94
gem5::guest_abi::Aapcs64ArrayType
Definition: aapcs64.hh:305
gem5::Aapcs64::State::State
State(const ThreadContext *tc)
Definition: aapcs64.hh:63
gem5::guest_abi::IsAapcs64Composite
Definition: aapcs64.hh:100
gem5::gtoh
T gtoh(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:194
gem5::Aapcs64::State
Definition: aapcs64.hh:52
gem5::htog
T htog(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:187
gem5::guest_abi::Result< Aapcs64, Composite, typename std::enable_if_t< IsAapcs64CompositeV< Composite > &&!IsAapcs64HxaV< Composite > > >::store
static void store(ThreadContext *tc, const Composite &c)
Definition: aapcs64.hh:403
gem5::ProxyPtr
Definition: proxy_ptr.hh:238
gem5::guest_abi::enable_if_t< std::is_integral_v< Integer > &&(sizeof(Integer)<=8)> >::get
static Integer get(ThreadContext *tc, Aapcs64::State &state)
Definition: aapcs64.hh:238
gem5::guest_abi::Result< Aapcs64, HA, typename std::enable_if_t< IsAapcs64HxaV< HA > > >::store
static HA store(ThreadContext *tc, const HA &ha)
Definition: aapcs64.hh:338
gem5::ArmISA::c
Bitfield< 29 > c
Definition: misc_types.hh:53
gem5::guest_abi::enable_if_t< std::is_integral_v< Integer > &&(sizeof(Integer)<=8)> >::store
static void store(ThreadContext *tc, const Integer &i)
Definition: aapcs64.hh:280
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::ThreadContext::readIntReg
virtual RegVal readIntReg(RegIndex reg_idx) const =0
gem5::GEM5_DEPRECATED_NAMESPACE
GEM5_DEPRECATED_NAMESPACE(GuestABI, guest_abi)
gem5::Aapcs64
Definition: aapcs64.hh:48
utility.hh
gem5::X86ISA::reg
Bitfield< 5, 3 > reg
Definition: types.hh:92
gem5::Aapcs64::State::MAX_SRN
static const int MAX_SRN
Definition: aapcs64.hh:61
gem5::guest_abi::IsAapcs64Hfa
Definition: aapcs64.hh:125
std
Overload hash function for BasicBlockRange type.
Definition: types.hh:111
gem5::guest_abi::IsAapcs64CompositeV
constexpr bool IsAapcs64CompositeV
Definition: aapcs64.hh:113
gem5::guest_abi::IsAapcs64ShortVectorV
constexpr bool IsAapcs64ShortVectorV
Definition: aapcs64.hh:93
guest_abi.hh
gem5::X86ISA::E
Bitfield< 31, 0 > E
Definition: int.hh:53
gem5::roundUp
static constexpr T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:260
gem5::ArmISA::id
Bitfield< 33 > id
Definition: misc_types.hh:251
gem5::guest_abi::Argument
Definition: definition.hh:99
gem5::Aapcs64::State::nsaa
Addr nsaa
Definition: aapcs64.hh:56
gem5::VecRegClass
@ VecRegClass
Vector Register.
Definition: reg_class.hh:61
gem5::guest_abi::Aapcs64ArrayType::Type
void Type
Definition: aapcs64.hh:305
gem5::Aapcs64::State::ngrn
int ngrn
Definition: aapcs64.hh:54
gem5::guest_abi::Argument< Aapcs64, HA, typename std::enable_if_t< IsAapcs64HxaV< HA > > >::get
static HA get(ThreadContext *tc, Aapcs64::State &state)
Definition: aapcs64.hh:315
intmath.hh
gem5::guest_abi::IsAapcs64ShortVector
Definition: aapcs64.hh:82
gem5::guest_abi::Result
Definition: definition.hh:64
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: tlb.cc:60
gem5::ArmISA::ha
Bitfield< 39 > ha
Definition: misc_types.hh:544
int.hh
thread_context.hh
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84

Generated on Wed May 4 2022 12:13:45 for gem5 by doxygen 1.8.17