blob: 738fa69a005010135231d1128d57065a306ec548 [file] [log] [blame]
Jacob Bramley2af191d2018-05-16 10:22:44 +01001// Copyright 2018, VIXL authors
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// * Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9// * Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12// * Neither the name of ARM Limited nor the names of its contributors may be
13// used to endorse or promote products derived from this software without
14// specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24// OR TORT (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#ifndef VIXL_CPU_FEATURES_H
28#define VIXL_CPU_FEATURES_H
29
30#include <ostream>
31
32#include "globals-vixl.h"
33
34namespace vixl {
35
36
Jacob Bramley3d8d3942020-07-06 19:38:59 +010037// VIXL aims to handle and detect all architectural features that are likely to
38// influence code-generation decisions at EL0 (user-space).
39//
40// - There may be multiple VIXL feature flags for a given architectural
41// extension. This occurs where the extension allow components to be
42// implemented independently, or where kernel support is needed, and is likely
43// to be fragmented.
44//
45// For example, Pointer Authentication (kPAuth*) has a separate feature flag
46// for access to PACGA, and to indicate that the QARMA algorithm is
47// implemented.
48//
49// - Conversely, some extensions have configuration options that do not affect
50// EL0, so these are presented as a single VIXL feature.
51//
52// For example, the RAS extension (kRAS) has several variants, but the only
53// feature relevant to VIXL is the addition of the ESB instruction so we only
54// need a single flag.
55//
56// - VIXL offers separate flags for separate features even if they're
57// architecturally linked.
58//
59// For example, the architecture requires kFPHalf and kNEONHalf to be equal,
60// but they have separate hardware ID register fields so VIXL presents them as
61// separate features.
62//
63// - VIXL can detect every feature for which it can generate code.
64//
65// - VIXL can detect some features for which it cannot generate code.
66//
67// The CPUFeatures::Feature enum — derived from the macro list below — is
68// frequently extended. New features may be added to the list at any point, and
69// no assumptions should be made about the numerical values assigned to each
70// enum constant. The symbolic names can be considered to be stable.
71//
72// The debug descriptions are used only for debug output. The 'cpuinfo' strings
73// are informative; VIXL does not use /proc/cpuinfo for feature detection.
74
Jacob Bramley2af191d2018-05-16 10:22:44 +010075// clang-format off
76#define VIXL_CPU_FEATURE_LIST(V) \
77 /* If set, the OS traps and emulates MRS accesses to relevant (EL1) ID_* */ \
78 /* registers, so that the detailed feature registers can be read */ \
79 /* directly. */ \
Jacob Bramley3d8d3942020-07-06 19:38:59 +010080 \
81 /* Constant name Debug description Linux 'cpuinfo' string. */ \
Jacob Bramley2af191d2018-05-16 10:22:44 +010082 V(kIDRegisterEmulation, "ID register emulation", "cpuid") \
83 \
84 V(kFP, "FP", "fp") \
85 V(kNEON, "NEON", "asimd") \
86 V(kCRC32, "CRC32", "crc32") \
Jacob Bramley3d8d3942020-07-06 19:38:59 +010087 V(kDGH, "DGH", "dgh") \
88 /* Speculation control features. */ \
89 V(kCSV2, "CSV2", NULL) \
90 V(kSCXTNUM, "SCXTNUM", NULL) \
91 V(kCSV3, "CSV3", NULL) \
92 V(kSB, "SB", "sb") \
93 V(kSPECRES, "SPECRES", NULL) \
94 V(kSSBS, "SSBS", NULL) \
95 V(kSSBSControl, "SSBS (PSTATE control)", "ssbs") \
Jacob Bramley2af191d2018-05-16 10:22:44 +010096 /* Cryptographic support instructions. */ \
97 V(kAES, "AES", "aes") \
98 V(kSHA1, "SHA1", "sha1") \
99 V(kSHA2, "SHA2", "sha2") \
100 /* A form of PMULL{2} with a 128-bit (1Q) result. */ \
101 V(kPmull1Q, "Pmull1Q", "pmull") \
102 /* Atomic operations on memory: CAS, LDADD, STADD, SWP, etc. */ \
103 V(kAtomics, "Atomics", "atomics") \
104 /* Limited ordering regions: LDLAR, STLLR and their variants. */ \
105 V(kLORegions, "LORegions", NULL) \
106 /* Rounding doubling multiply add/subtract: SQRDMLAH and SQRDMLSH. */ \
107 V(kRDM, "RDM", "asimdrdm") \
Jacob Bramley4482be72018-09-14 15:57:57 +0100108 /* Scalable Vector Extension. */ \
109 V(kSVE, "SVE", "sve") \
Jacob Bramley3d8d3942020-07-06 19:38:59 +0100110 V(kSVEF64MM, "SVE F64MM", "svef64mm") \
111 V(kSVEF32MM, "SVE F32MM", "svef32mm") \
112 V(kSVEI8MM, "SVE I8MM", "svei8imm") \
113 V(kSVEBF16, "SVE BFloat16", "svebf16") \
Jacob Bramley2af191d2018-05-16 10:22:44 +0100114 /* SDOT and UDOT support (in NEON). */ \
115 V(kDotProduct, "DotProduct", "asimddp") \
Jacob Bramley3d8d3942020-07-06 19:38:59 +0100116 /* Int8 matrix multiplication (in NEON). */ \
117 V(kI8MM, "NEON I8MM", "i8mm") \
Jacob Bramley2af191d2018-05-16 10:22:44 +0100118 /* Half-precision (FP16) support for FP and NEON, respectively. */ \
119 V(kFPHalf, "FPHalf", "fphp") \
120 V(kNEONHalf, "NEONHalf", "asimdhp") \
Jacob Bramley3d8d3942020-07-06 19:38:59 +0100121 /* BFloat16 support (in both FP and NEON.) */ \
122 V(kBF16, "FP/NEON BFloat 16", "bf16") \
Jacob Bramleyca789742018-09-13 14:25:46 +0100123 /* The RAS extension, including the ESB instruction. */ \
124 V(kRAS, "RAS", NULL) \
Jacob Bramley2af191d2018-05-16 10:22:44 +0100125 /* Data cache clean to the point of persistence: DC CVAP. */ \
126 V(kDCPoP, "DCPoP", "dcpop") \
TatWai Chong684f5f72018-12-25 17:49:56 -0800127 /* Data cache clean to the point of deep persistence: DC CVADP. */ \
Jacob Bramley17b2e542019-11-07 18:26:05 +0000128 V(kDCCVADP, "DCCVADP", "dcpodp") \
Jacob Bramley2af191d2018-05-16 10:22:44 +0100129 /* Cryptographic support instructions. */ \
130 V(kSHA3, "SHA3", "sha3") \
131 V(kSHA512, "SHA512", "sha512") \
132 V(kSM3, "SM3", "sm3") \
133 V(kSM4, "SM4", "sm4") \
134 /* Pointer authentication for addresses. */ \
Jacob Bramley17b2e542019-11-07 18:26:05 +0000135 V(kPAuth, "PAuth", "paca") \
Jacob Bramley2af191d2018-05-16 10:22:44 +0100136 /* Pointer authentication for addresses uses QARMA. */ \
137 V(kPAuthQARMA, "PAuthQARMA", NULL) \
138 /* Generic authentication (using the PACGA instruction). */ \
Jacob Bramley17b2e542019-11-07 18:26:05 +0000139 V(kPAuthGeneric, "PAuthGeneric", "pacg") \
Jacob Bramley2af191d2018-05-16 10:22:44 +0100140 /* Generic authentication uses QARMA. */ \
141 V(kPAuthGenericQARMA, "PAuthGenericQARMA", NULL) \
Jacob Bramley4482be72018-09-14 15:57:57 +0100142 /* JavaScript-style FP -> integer conversion instruction: FJCVTZS. */ \
Jacob Bramley2af191d2018-05-16 10:22:44 +0100143 V(kJSCVT, "JSCVT", "jscvt") \
Jacob Bramley4482be72018-09-14 15:57:57 +0100144 /* Complex number support for NEON: FCMLA and FCADD. */ \
145 V(kFcma, "Fcma", "fcma") \
Jacob Bramley2af191d2018-05-16 10:22:44 +0100146 /* RCpc-based model (for weaker release consistency): LDAPR and variants. */ \
147 V(kRCpc, "RCpc", "lrcpc") \
Jacob Bramley4482be72018-09-14 15:57:57 +0100148 V(kRCpcImm, "RCpc (imm)", "ilrcpc") \
149 /* Flag manipulation instructions: SETF{8,16}, CFINV, RMIF. */ \
150 V(kFlagM, "FlagM", "flagm") \
151 /* Unaligned single-copy atomicity. */ \
152 V(kUSCAT, "USCAT", "uscat") \
153 /* FP16 fused multiply-add or -subtract long: FMLAL{2}, FMLSL{2}. */ \
154 V(kFHM, "FHM", "asimdfhm") \
155 /* Data-independent timing (for selected instructions). */ \
Martyn Capewellcb963f72018-10-22 15:25:28 +0100156 V(kDIT, "DIT", "dit") \
157 /* Branch target identification. */ \
Jacob Bramley3d8d3942020-07-06 19:38:59 +0100158 V(kBTI, "BTI", "bti") \
Alexander Gilday84ee1442018-11-06 15:28:07 +0000159 /* Flag manipulation instructions: {AX,XA}FLAG */ \
Jacob Bramley3d8d3942020-07-06 19:38:59 +0100160 V(kAXFlag, "AXFlag", "flagm2") \
TatWai Chong04edf682018-12-27 16:01:02 -0800161 /* Random number generation extension, */ \
Jacob Bramley3d8d3942020-07-06 19:38:59 +0100162 V(kRNG, "RNG", "rng") \
TatWai Chong04471812019-03-19 14:29:00 -0700163 /* Floating-point round to {32,64}-bit integer. */ \
Jacob Bramley3d8d3942020-07-06 19:38:59 +0100164 V(kFrintToFixedSizedInt,"Frint (bounded)", "frint") \
165 /* Memory Tagging Extension. */ \
166 V(kMTEInstructions, "MTE (EL0 instructions)", NULL) \
167 V(kMTE, "MTE", NULL) \
168 /* PAuth extensions. */ \
169 V(kPAuthEnhancedPAC, "PAuth EnhancedPAC", NULL) \
170 V(kPAuthEnhancedPAC2, "PAuth EnhancedPAC2", NULL) \
171 V(kPAuthFPAC, "PAuth FPAC", NULL) \
172 V(kPAuthFPACCombined, "PAuth FPACCombined", NULL)
Jacob Bramley2af191d2018-05-16 10:22:44 +0100173// clang-format on
174
175
176class CPUFeaturesConstIterator;
177
178// A representation of the set of features known to be supported by the target
179// device. Each feature is represented by a simple boolean flag.
180//
Jacob Bramley5997b462018-06-05 14:05:30 +0100181// - When the Assembler is asked to assemble an instruction, it asserts (in
182// debug mode) that the necessary features are available.
Jacob Bramley2af191d2018-05-16 10:22:44 +0100183//
Jacob Bramley2af191d2018-05-16 10:22:44 +0100184// - TODO: The MacroAssembler relies on the Assembler's assertions, but in
185// some cases it may be useful for macros to generate a fall-back sequence
186// in case features are not available.
187//
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100188// - The Simulator assumes by default that all features are available, but it
189// is possible to configure it to fail if the simulated code uses features
190// that are not enabled.
191//
192// The Simulator also offers pseudo-instructions to allow features to be
193// enabled and disabled dynamically. This is useful when you want to ensure
194// that some features are constrained to certain areas of code.
195//
196// - The base Disassembler knows nothing about CPU features, but the
197// PrintDisassembler can be configured to annotate its output with warnings
198// about unavailable features. The Simulator uses this feature when
199// instruction trace is enabled.
200//
201// - The Decoder-based components -- the Simulator and PrintDisassembler --
202// rely on a CPUFeaturesAuditor visitor. This visitor keeps a list of
203// features actually encountered so that a large block of code can be
204// examined (either directly or through simulation), and the required
205// features analysed later.
206//
Jacob Bramley2af191d2018-05-16 10:22:44 +0100207// Expected usage:
208//
209// // By default, VIXL uses CPUFeatures::AArch64LegacyBaseline(), for
210// // compatibility with older version of VIXL.
211// MacroAssembler masm;
212//
213// // Generate code only for the current CPU.
214// masm.SetCPUFeatures(CPUFeatures::InferFromOS());
215//
216// // Turn off feature checking entirely.
217// masm.SetCPUFeatures(CPUFeatures::All());
218//
219// Feature set manipulation:
220//
221// CPUFeatures f; // The default constructor gives an empty set.
222// // Individual features can be added (or removed).
223// f.Combine(CPUFeatures::kFP, CPUFeatures::kNEON, CPUFeatures::AES);
224// f.Remove(CPUFeatures::kNEON);
225//
226// // Some helpers exist for extensions that provide several features.
227// f.Remove(CPUFeatures::All());
228// f.Combine(CPUFeatures::AArch64LegacyBaseline());
229//
230// // Chained construction is also possible.
231// CPUFeatures g =
232// f.With(CPUFeatures::kPmull1Q).Without(CPUFeatures::kCRC32);
233//
234// // Features can be queried. Where multiple features are given, they are
235// // combined with logical AND.
236// if (h.Has(CPUFeatures::kNEON)) { ... }
237// if (h.Has(CPUFeatures::kFP, CPUFeatures::kNEON)) { ... }
238// if (h.Has(g)) { ... }
239// // If the empty set is requested, the result is always 'true'.
240// VIXL_ASSERT(h.Has(CPUFeatures()));
241//
242// // For debug and reporting purposes, features can be enumerated (or
243// // printed directly):
244// std::cout << CPUFeatures::kNEON; // Prints something like "NEON".
245// std::cout << f; // Prints something like "FP, NEON, CRC32".
246class CPUFeatures {
247 public:
248 // clang-format off
249 // Individual features.
250 // These should be treated as opaque tokens. User code should not rely on
251 // specific numeric values or ordering.
252 enum Feature {
253 // Refer to VIXL_CPU_FEATURE_LIST (above) for the list of feature names that
254 // this class supports.
255
Jacob Bramleyfdf332a2018-09-17 11:17:54 +0100256 kNone = -1,
Jacob Bramley2af191d2018-05-16 10:22:44 +0100257#define VIXL_DECLARE_FEATURE(SYMBOL, NAME, CPUINFO) SYMBOL,
258 VIXL_CPU_FEATURE_LIST(VIXL_DECLARE_FEATURE)
259#undef VIXL_DECLARE_FEATURE
Jacob Bramleyfdf332a2018-09-17 11:17:54 +0100260 kNumberOfFeatures
Jacob Bramley2af191d2018-05-16 10:22:44 +0100261 };
262 // clang-format on
263
264 // By default, construct with no features enabled.
265 CPUFeatures() : features_(0) {}
266
267 // Construct with some features already enabled.
268 CPUFeatures(Feature feature0,
269 Feature feature1 = kNone,
270 Feature feature2 = kNone,
271 Feature feature3 = kNone);
272
273 // Construct with all features enabled. This can be used to disable feature
274 // checking: `Has(...)` returns true regardless of the argument.
275 static CPUFeatures All();
276
Jacob Bramley7b8fc822018-06-26 16:48:21 +0100277 // Construct an empty CPUFeatures. This is equivalent to the default
278 // constructor, but is provided for symmetry and convenience.
279 static CPUFeatures None() { return CPUFeatures(); }
280
Jacob Bramley2af191d2018-05-16 10:22:44 +0100281 // The presence of these features was assumed by version of VIXL before this
282 // API was added, so using this set by default ensures API compatibility.
283 static CPUFeatures AArch64LegacyBaseline() {
284 return CPUFeatures(kFP, kNEON, kCRC32);
285 }
286
Jacob Bramley48934322019-02-04 18:27:53 +0000287 // Construct a new CPUFeatures object using ID registers. This assumes that
288 // kIDRegisterEmulation is present.
289 static CPUFeatures InferFromIDRegisters();
290
291 enum QueryIDRegistersOption {
292 kDontQueryIDRegisters,
293 kQueryIDRegistersIfAvailable
294 };
295
Jacob Bramley2af191d2018-05-16 10:22:44 +0100296 // Construct a new CPUFeatures object based on what the OS reports.
Jacob Bramley48934322019-02-04 18:27:53 +0000297 static CPUFeatures InferFromOS(
298 QueryIDRegistersOption option = kQueryIDRegistersIfAvailable);
Jacob Bramley2af191d2018-05-16 10:22:44 +0100299
300 // Combine another CPUFeatures object into this one. Features that already
301 // exist in this set are left unchanged.
302 void Combine(const CPUFeatures& other);
303
304 // Combine specific features into this set. Features that already exist in
305 // this set are left unchanged.
306 void Combine(Feature feature0,
307 Feature feature1 = kNone,
308 Feature feature2 = kNone,
309 Feature feature3 = kNone);
310
311 // Remove features in another CPUFeatures object from this one.
312 void Remove(const CPUFeatures& other);
313
314 // Remove specific features from this set.
315 void Remove(Feature feature0,
316 Feature feature1 = kNone,
317 Feature feature2 = kNone,
318 Feature feature3 = kNone);
319
320 // Chaining helpers for convenient construction.
321 CPUFeatures With(const CPUFeatures& other) const;
322 CPUFeatures With(Feature feature0,
323 Feature feature1 = kNone,
324 Feature feature2 = kNone,
325 Feature feature3 = kNone) const;
326 CPUFeatures Without(const CPUFeatures& other) const;
327 CPUFeatures Without(Feature feature0,
328 Feature feature1 = kNone,
329 Feature feature2 = kNone,
330 Feature feature3 = kNone) const;
331
332 // Query features.
333 // Note that an empty query (like `Has(kNone)`) always returns true.
334 bool Has(const CPUFeatures& other) const;
335 bool Has(Feature feature0,
336 Feature feature1 = kNone,
337 Feature feature2 = kNone,
338 Feature feature3 = kNone) const;
339
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100340 // Return the number of enabled features.
341 size_t Count() const;
Jacob Bramley2fb52cb2019-04-16 15:22:31 +0100342 bool HasNoFeatures() const { return Count() == 0; }
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100343
344 // Check for equivalence.
345 bool operator==(const CPUFeatures& other) const {
346 return Has(other) && other.Has(*this);
347 }
348 bool operator!=(const CPUFeatures& other) const { return !(*this == other); }
349
Jacob Bramley2af191d2018-05-16 10:22:44 +0100350 typedef CPUFeaturesConstIterator const_iterator;
351
352 const_iterator begin() const;
353 const_iterator end() const;
354
355 private:
356 // Each bit represents a feature. This field will be replaced as needed if
357 // features are added.
358 uint64_t features_;
359
360 friend std::ostream& operator<<(std::ostream& os,
361 const vixl::CPUFeatures& features);
362};
363
364std::ostream& operator<<(std::ostream& os, vixl::CPUFeatures::Feature feature);
365std::ostream& operator<<(std::ostream& os, const vixl::CPUFeatures& features);
366
367// This is not a proper C++ iterator type, but it simulates enough of
368// ForwardIterator that simple loops can be written.
369class CPUFeaturesConstIterator {
370 public:
371 CPUFeaturesConstIterator(const CPUFeatures* cpu_features = NULL,
372 CPUFeatures::Feature start = CPUFeatures::kNone)
373 : cpu_features_(cpu_features), feature_(start) {
374 VIXL_ASSERT(IsValid());
375 }
376
377 bool operator==(const CPUFeaturesConstIterator& other) const;
378 bool operator!=(const CPUFeaturesConstIterator& other) const {
379 return !(*this == other);
380 }
Jacob Bramleycaa40ee2020-07-08 20:46:38 +0100381 CPUFeaturesConstIterator& operator++();
382 CPUFeaturesConstIterator operator++(int);
Jacob Bramley2af191d2018-05-16 10:22:44 +0100383
384 CPUFeatures::Feature operator*() const {
385 VIXL_ASSERT(IsValid());
386 return feature_;
387 }
388
389 // For proper support of C++'s simplest "Iterator" concept, this class would
390 // have to define member types (such as CPUFeaturesIterator::pointer) to make
391 // it appear as if it iterates over Feature objects in memory. That is, we'd
392 // need CPUFeatures::iterator to behave like std::vector<Feature>::iterator.
393 // This is at least partially possible -- the std::vector<bool> specialisation
394 // does something similar -- but it doesn't seem worthwhile for a
395 // special-purpose debug helper, so they are omitted here.
396 private:
397 const CPUFeatures* cpu_features_;
398 CPUFeatures::Feature feature_;
399
400 bool IsValid() const {
Jacob Bramley5523f6c2019-06-28 11:37:26 +0100401 if (cpu_features_ == NULL) {
402 return feature_ == CPUFeatures::kNone;
403 }
404 return cpu_features_->Has(feature_);
Jacob Bramley2af191d2018-05-16 10:22:44 +0100405 }
406};
407
408// A convenience scope for temporarily modifying a CPU features object. This
409// allows features to be enabled for short sequences.
410//
411// Expected usage:
412//
413// {
414// CPUFeaturesScope cpu(&masm, CPUFeatures::kCRC32);
415// // This scope can now use CRC32, as well as anything else that was enabled
416// // before the scope.
417//
418// ...
419//
420// // At the end of the scope, the original CPU features are restored.
421// }
422class CPUFeaturesScope {
423 public:
424 // Start a CPUFeaturesScope on any object that implements
425 // `CPUFeatures* GetCPUFeatures()`.
426 template <typename T>
427 explicit CPUFeaturesScope(T* cpu_features_wrapper,
428 CPUFeatures::Feature feature0 = CPUFeatures::kNone,
429 CPUFeatures::Feature feature1 = CPUFeatures::kNone,
430 CPUFeatures::Feature feature2 = CPUFeatures::kNone,
431 CPUFeatures::Feature feature3 = CPUFeatures::kNone)
432 : cpu_features_(cpu_features_wrapper->GetCPUFeatures()),
433 old_features_(*cpu_features_) {
434 cpu_features_->Combine(feature0, feature1, feature2, feature3);
435 }
436
437 template <typename T>
438 CPUFeaturesScope(T* cpu_features_wrapper, const CPUFeatures& other)
439 : cpu_features_(cpu_features_wrapper->GetCPUFeatures()),
440 old_features_(*cpu_features_) {
441 cpu_features_->Combine(other);
442 }
443
444 ~CPUFeaturesScope() { *cpu_features_ = old_features_; }
445
446 // For advanced usage, the CPUFeatures object can be accessed directly.
447 // The scope will restore the original state when it ends.
448
449 CPUFeatures* GetCPUFeatures() const { return cpu_features_; }
450
451 void SetCPUFeatures(const CPUFeatures& cpu_features) {
452 *cpu_features_ = cpu_features;
453 }
454
455 private:
456 CPUFeatures* const cpu_features_;
457 const CPUFeatures old_features_;
458};
459
460
461} // namespace vixl
462
463#endif // VIXL_CPU_FEATURES_H