gem5  v21.1.0.2
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<E>::value || std::is_floating_point<E>::value) &&
88  (sizeof(E) * N == 8 || sizeof(E) * N == 16)>> :
89  public std::true_type
90 {};
91 
92 /*
93  * Composite Types
94  */
95 
96 template <typename T, typename Enabled=void>
97 struct IsAapcs64Composite : public std::false_type {};
98 
99 template <typename T>
100 struct IsAapcs64Composite<T, typename std::enable_if_t<
101  (std::is_array<T>::value ||
102  std::is_class<T>::value ||
103  std::is_union<T>::value) &&
104  // VarArgs is technically a composite type, but it's not a normal argument.
105  !IsVarArgs<T>::value &&
106  // Short vectors are also composite types, but don't treat them as one.
107  !IsAapcs64ShortVector<T>::value
108  >> : public std::true_type
109 {};
110 
111 // Homogeneous Aggregates
112 // These *should* be any aggregate type which has only one type of member, but
113 // we can't actually detect that or manipulate that with templates. Instead,
114 // we approximate that by detecting only arrays with that property.
115 
116 // An Homogeneous Floating-Point Aggregate (HFA) is an Homogeneous Aggregate
117 // with a Fundemental Data Type that is a Floating-Point type and at most four
118 // uniquely addressable members.
119 
120 template <typename T, typename Enabled=void>
121 struct IsAapcs64Hfa : public std::false_type {};
122 
123 template <typename E, size_t N>
124 struct IsAapcs64Hfa<E[N],
125  typename std::enable_if_t<std::is_floating_point<E>::value && N <= 4>> :
126  public std::true_type
127 {};
128 
129 // An Homogeneous Short-Vector Aggregate (HVA) is an Homogeneous Aggregate with
130 // a Fundamental Data Type that is a Short-Vector type and at most four
131 // uniquely addressable members.
132 
133 template <typename T, typename Enabled=void>
134 struct IsAapcs64Hva : public std::false_type {};
135 
136 template <typename E, size_t N>
137 struct IsAapcs64Hva<E[N],
138  typename std::enable_if_t<IsAapcs64ShortVector<E>::value && N <= 4>> :
139  public std::true_type
140 {};
141 
142 // A shorthand to test if a type is an HVA or an HFA.
143 template <typename T, typename Enabled=void>
144 struct IsAapcs64Hxa : public std::false_type {};
145 
146 template <typename T>
147 struct IsAapcs64Hxa<T, typename std::enable_if_t<
148  IsAapcs64Hfa<T>::value || IsAapcs64Hva<T>::value>> :
149  public std::true_type
150 {};
151 
152 struct Aapcs64ArgumentBase
153 {
154  template <typename T>
155  static T
156  loadFromStack(ThreadContext *tc, Aapcs64::State &state)
157  {
158  // The alignment is the larger of 8 or the natural alignment of T.
159  size_t align = std::max<size_t>(8, alignof(T));
160  // Increase the size to the next multiple of 8.
161  size_t size = roundUp(sizeof(T), 8);
162 
163  // Align the stack.
164  state.nsaa = roundUp(state.nsaa, align);
165 
166  // Extract the value from it.
167  ConstVPtr<T> val(state.nsaa, tc);
168 
169  // Move the nsaa past this argument.
170  state.nsaa += size;
171 
172  // Return the value we extracted.
173  return gtoh(*val, ArmISA::byteOrder(tc));
174  }
175 };
176 
177 
178 /*
179  * Floating point and Short-Vector arguments and return values.
180  */
181 
182 template <typename Float>
183 struct Argument<Aapcs64, Float, typename std::enable_if_t<
184  std::is_floating_point<Float>::value ||
185  IsAapcs64ShortVector<Float>::value>> :
186  public Aapcs64ArgumentBase
187 {
188  static Float
189  get(ThreadContext *tc, Aapcs64::State &state)
190  {
191  if (state.nsrn <= state.MAX_SRN) {
192  RegId id(VecRegClass, state.nsrn++);
193  return tc->readVecReg(id).as<Float>()[0];
194  }
195 
196  return loadFromStack<Float>(tc, state);
197  }
198 };
199 
200 template <typename Float>
201 struct Result<Aapcs64, Float, typename std::enable_if_t<
202  std::is_floating_point<Float>::value ||
203  IsAapcs64ShortVector<Float>::value>>
204 {
205  static void
206  store(ThreadContext *tc, const Float &f)
207  {
208  RegId id(VecRegClass, 0);
209  auto reg = tc->readVecReg(id);
210  reg.as<Float>()[0] = f;
211  tc->setVecReg(id, reg);
212  }
213 };
214 
215 
216 /*
217  * Integer arguments and return values.
218  */
219 
220 // This will pick up Addr as well, which should be used for guest pointers.
221 template <typename Integer>
222 struct Argument<Aapcs64, Integer, typename std::enable_if_t<
223  std::is_integral<Integer>::value && (sizeof(Integer) <= 8)>> :
224  public Aapcs64ArgumentBase
225 {
226  static Integer
228  {
229  if (state.ngrn <= state.MAX_GRN)
230  return tc->readIntReg(state.ngrn++);
231 
232  // Max out ngrn since we've effectively saturated it.
233  state.ngrn = state.MAX_GRN + 1;
234 
235  return loadFromStack<Integer>(tc, state);
236  }
237 };
238 
239 template <typename Integer>
240 struct Argument<Aapcs64, Integer, typename std::enable_if_t<
241  std::is_integral<Integer>::value && (sizeof(Integer) > 8)>> :
242  public Aapcs64ArgumentBase
243 {
244  static Integer
245  get(ThreadContext *tc, Aapcs64::State &state)
246  {
247  if (alignof(Integer) == 16 && (state.ngrn % 2))
248  state.ngrn++;
249 
250  if (sizeof(Integer) == 16 && state.ngrn + 1 <= state.MAX_GRN) {
251  Integer low = tc->readIntReg(state.ngrn++);
252  Integer high = tc->readIntReg(state.ngrn++);
253  high = high << 64;
254  return high | low;
255  }
256 
257  // Max out ngrn since we've effectively saturated it.
258  state.ngrn = state.MAX_GRN + 1;
259 
260  return loadFromStack<Integer>(tc, state);
261  }
262 };
263 
264 template <typename Integer>
265 struct Result<Aapcs64, Integer, typename std::enable_if_t<
266  std::is_integral<Integer>::value && (sizeof(Integer) <= 8)>>
267 {
268  static void
269  store(ThreadContext *tc, const Integer &i)
270  {
271  tc->setIntReg(0, i);
272  }
273 };
274 
275 template <typename Integer>
276 struct Result<Aapcs64, Integer, typename std::enable_if_t<
277  std::is_integral<Integer>::value && (sizeof(Integer) > 8)>>
278 {
279  static void
280  store(ThreadContext *tc, const Integer &i)
281  {
282  tc->setIntReg(0, (uint64_t)i);
283  tc->setIntReg(1, (uint64_t)(i >> 64));
284  }
285 };
286 
287 
288 /*
289  * Homogeneous Floating-Point and Short-Vector Aggregates (HFAs and HVAs)
290  * argument and return values.
291  */
292 
293 template <typename T>
294 struct Aapcs64ArrayType { using Type = void; };
295 
296 template <typename E, size_t N>
297 struct Aapcs64ArrayType<E[N]> { using Type = E; };
298 
299 template <typename HA>
300 struct Argument<Aapcs64, HA, typename std::enable_if_t<
301  IsAapcs64Hxa<HA>::value>> : public Aapcs64ArgumentBase
302 {
303  static HA
305  {
306  using Elem = typename Aapcs64ArrayType<HA>::Type;
307  constexpr size_t Count = sizeof(HA) / sizeof(Elem);
308 
309  if (state.nsrn + Count - 1 <= state.MAX_SRN) {
310  HA ha;
311  for (int i = 0; i < Count; i++)
312  ha[i] = Argument<Aapcs64, Elem>::get(tc, state);
313  return ha;
314  }
315 
316  // Max out the nsrn since we effectively exhausted it.
317  state.nsrn = state.MAX_SRN + 1;
318 
319  return loadFromStack<HA>(tc, state);
320  }
321 };
322 
323 template <typename HA>
324 struct Result<Aapcs64, HA,
325  typename std::enable_if_t<IsAapcs64Hxa<HA>::value>>
326 {
327  static HA
328  store(ThreadContext *tc, const HA &ha)
329  {
330  using Elem = typename Aapcs64ArrayType<HA>::Type;
331  constexpr size_t Count = sizeof(HA) / sizeof(Elem);
332 
333  for (int i = 0; i < Count; i++)
335  }
336 };
337 
338 
339 /*
340  * Composite arguments and return values which are not HVAs or HFAs.
341  */
342 
343 template <typename Composite>
344 struct Argument<Aapcs64, Composite, typename std::enable_if_t<
345  IsAapcs64Composite<Composite>::value && !IsAapcs64Hxa<Composite>::value>> :
346  public Aapcs64ArgumentBase
347 {
348  static Composite
350  {
351  if (sizeof(Composite) > 16) {
352  // Composite values larger than 16 which aren't HFAs or HVAs are
353  // kept in a buffer, and the argument is actually a pointer to that
354  // buffer.
356  ConstVPtr<Composite> composite(addr, tc);
357  return gtoh(*composite, ArmISA::byteOrder(tc));
358  }
359 
360  // The size of Composite must be 16 bytes or less after this point.
361 
362  size_t bytes = sizeof(Composite);
363  using Chunk = uint64_t;
364 
365  const int chunk_size = sizeof(Chunk);
366  const int regs = (bytes + chunk_size - 1) / chunk_size;
367 
368  // Can it fit in GPRs?
369  if (state.ngrn + regs - 1 <= state.MAX_GRN) {
370  alignas(alignof(Composite)) uint8_t buf[bytes];
371  for (int i = 0; i < regs; i++) {
372  Chunk val = tc->readIntReg(state.ngrn++);
373  val = htog(val, ArmISA::byteOrder(tc));
374  size_t to_copy = std::min<size_t>(bytes, chunk_size);
375  memcpy(buf + i * chunk_size, &val, to_copy);
376  bytes -= to_copy;
377  }
378  return gtoh(*(Composite *)buf, ArmISA::byteOrder(tc));
379  }
380 
381  // Max out the ngrn since we effectively exhausted it.
382  state.ngrn = state.MAX_GRN;
383 
384  return loadFromStack<Composite>(tc, state);
385  }
386 };
387 
388 template <typename Composite>
389 struct Result<Aapcs64, Composite, typename std::enable_if_t<
390  IsAapcs64Composite<Composite>::value && !IsAapcs64Hxa<Composite>::value>>
391 {
392  static void
393  store(ThreadContext *tc, const Composite &c)
394  {
395  if (sizeof(Composite) > 16) {
396  Addr addr = tc->readIntReg(ArmISA::INTREG_X8);
397  VPtr<Composite> composite(addr, tc);
398  *composite = htog(c, ArmISA::byteOrder(tc));
399  return;
400  }
401 
402  // The size of Composite must be 16 bytes or less after this point.
403 
404  size_t bytes = sizeof(Composite);
405  using Chunk = uint64_t;
406 
407  const int chunk_size = sizeof(Chunk);
408  const int regs = (bytes + chunk_size - 1) / chunk_size;
409 
410  Composite cp = htog(c, ArmISA::byteOrder(tc));
411  uint8_t *buf = (uint8_t *)&cp;
412  for (int i = 0; i < regs; i++) {
413  size_t to_copy = std::min<size_t>(bytes, chunk_size);
414 
415  Chunk val;
416  memcpy(&val, buf, to_copy);
417  val = gtoh(val, ArmISA::byteOrder(tc));
418 
419  tc->setIntReg(i, val);
420 
421  bytes -= to_copy;
422  buf += to_copy;
423  }
424  }
425 };
426 
427 } // namespace guest_abi
428 } // namespace gem5
429 
430 #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::guest_abi::Argument< Aapcs64, HA, typename std::enable_if_t< IsAapcs64Hxa< HA >::value > >::get
static HA get(ThreadContext *tc, Aapcs64::State &state)
Definition: aapcs64.hh:304
gem5::ArmISA::f
Bitfield< 6 > f
Definition: misc_types.hh:67
gem5::X86ISA::val
Bitfield< 63 > val
Definition: misc.hh:775
gem5::ArmISA::byteOrder
ByteOrder byteOrder(const ThreadContext *tc)
Definition: utility.hh:412
proxy_ptr.hh
gem5::guest_abi::Aapcs64ArrayType< E[N]>::Type
E Type
Definition: aapcs64.hh:297
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:66
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::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:93
gem5::guest_abi::enable_if_t< std::is_integral< Integer >::value &&(sizeof(Integer)<=8)> >::get
static Integer get(ThreadContext *tc, Aapcs64::State &state)
Definition: aapcs64.hh:227
gem5::guest_abi::Aapcs64ArrayType
Definition: aapcs64.hh:294
gem5::Aapcs64::State::State
State(const ThreadContext *tc)
Definition: aapcs64.hh:63
gem5::guest_abi::IsAapcs64Composite
Definition: aapcs64.hh:97
gem5::gtoh
T gtoh(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:194
gem5::Aapcs64::State
Definition: aapcs64.hh:52
gem5::guest_abi::Argument< Aapcs64, Composite, typename std::enable_if_t< IsAapcs64Composite< Composite >::value &&!IsAapcs64Hxa< Composite >::value > >::get
static Composite get(ThreadContext *tc, Aapcs64::State &state)
Definition: aapcs64.hh:349
gem5::htog
T htog(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:187
gem5::ProxyPtr
Definition: proxy_ptr.hh:238
gem5::guest_abi::enable_if_t< std::is_integral< Integer >::value &&(sizeof(Integer)<=8)> >::store
static void store(ThreadContext *tc, const Integer &i)
Definition: aapcs64.hh:269
gem5::ArmISA::c
Bitfield< 29 > c
Definition: misc_types.hh:53
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::guest_abi::Result< Aapcs64, Composite, typename std::enable_if_t< IsAapcs64Composite< Composite >::value &&!IsAapcs64Hxa< Composite >::value > >::store
static void store(ThreadContext *tc, const Composite &c)
Definition: aapcs64.hh:393
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::VecRegClass
@ VecRegClass
Vector Register.
Definition: reg_class.hh:60
gem5::guest_abi::IsAapcs64Hfa
Definition: aapcs64.hh:121
gem5::guest_abi::Result< Aapcs64, HA, typename std::enable_if_t< IsAapcs64Hxa< HA >::value > >::store
static HA store(ThreadContext *tc, const HA &ha)
Definition: aapcs64.hh:328
std
Overload hash function for BasicBlockRange type.
Definition: types.hh:111
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:250
gem5::guest_abi::Argument
Definition: definition.hh:99
gem5::Aapcs64::State::nsaa
Addr nsaa
Definition: aapcs64.hh:56
gem5::guest_abi::Aapcs64ArrayType::Type
void Type
Definition: aapcs64.hh:294
gem5::Aapcs64::State::ngrn
int ngrn
Definition: aapcs64.hh:54
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: decoder.cc:40
gem5::ArmISA::ha
Bitfield< 39 > ha
Definition: misc_types.hh:543
int.hh
thread_context.hh
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84

Generated on Tue Sep 21 2021 12:24:21 for gem5 by doxygen 1.8.17