archtraits.cpp (4137B)
1 // This file is part of AsmJit project <https://asmjit.com> 2 // 3 // See <asmjit/core.h> or LICENSE.md for license and copyright information 4 // SPDX-License-Identifier: Zlib 5 6 #include "../core/api-build_p.h" 7 #include "../core/archtraits.h" 8 #include "../core/environment.h" 9 #include "../core/misc_p.h" 10 11 #if !defined(ASMJIT_NO_X86) 12 #include "../x86/x86archtraits_p.h" 13 #endif 14 15 #if !defined(ASMJIT_NO_AARCH64) 16 #include "../arm/a64archtraits_p.h" 17 #endif 18 19 ASMJIT_BEGIN_NAMESPACE 20 21 static const constexpr ArchTraits no_arch_traits = { 22 // SP/FP/LR/PC. 23 0xFFu, 0xFFu, 0xFFu, 0xFFu, 24 25 // Reserved, 26 { 0u, 0u, 0u }, 27 28 // HW stack alignment. 29 0u, 30 31 // Min/Max stack offset. 32 0, 0, 33 34 // Supported register types. 35 0u, 36 37 // ISA features [Gp, Vec, Mask, Extra]. 38 {{ 39 InstHints::kNoHints, 40 InstHints::kNoHints, 41 InstHints::kNoHints, 42 InstHints::kNoHints 43 }}, 44 45 // TypeIdToRegType. 46 #define V(index) RegType::kNone 47 {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, 48 #undef V 49 50 // Word names of 8-bit, 16-bit, 32-bit, and 64-bit quantities. 51 { 52 ArchTypeNameId::kByte, 53 ArchTypeNameId::kHalf, 54 ArchTypeNameId::kWord, 55 ArchTypeNameId::kQuad 56 } 57 }; 58 59 ASMJIT_VARAPI const ArchTraits _arch_traits[uint32_t(Arch::kMaxValue) + 1] = { 60 // No architecture. 61 no_arch_traits, 62 63 // X86/X86 architectures. 64 #if !defined(ASMJIT_NO_X86) 65 x86::x86_arch_traits, 66 x86::x64_arch_traits, 67 #else 68 no_arch_traits, 69 no_arch_traits, 70 #endif 71 72 // RISCV32/RISCV64 architectures. 73 no_arch_traits, 74 no_arch_traits, 75 76 // ARM architecture 77 no_arch_traits, 78 79 // AArch64 architecture. 80 #if !defined(ASMJIT_NO_AARCH64) 81 a64::a64_arch_traits, 82 #else 83 no_arch_traits, 84 #endif 85 86 // ARM/Thumb architecture. 87 no_arch_traits, 88 89 // Reserved. 90 no_arch_traits, 91 92 // MIPS32/MIPS64 93 no_arch_traits, 94 no_arch_traits 95 }; 96 97 ASMJIT_FAVOR_SIZE Error ArchUtils::type_id_to_reg_signature(Arch arch, TypeId type_id, Out<TypeId> type_id_out, Out<OperandSignature> reg_signature_out) noexcept { 98 const ArchTraits& arch_traits = ArchTraits::by_arch(arch); 99 100 // TODO: Remove this, should never be used like this. 101 // Passed RegType instead of TypeId? 102 if (uint32_t(type_id) <= uint32_t(RegType::kMaxValue)) { 103 type_id = RegUtils::type_id_of(RegType(uint32_t(type_id))); 104 } 105 106 if (ASMJIT_UNLIKELY(!TypeUtils::is_valid(type_id))) { 107 return make_error(Error::kInvalidTypeId); 108 } 109 110 // First normalize architecture dependent types. 111 if (TypeUtils::is_abstract(type_id)) { 112 bool is_32bit = Environment::is_32bit(arch); 113 if (type_id == TypeId::kIntPtr) { 114 type_id = is_32bit ? TypeId::kInt32 : TypeId::kInt64; 115 } 116 else { 117 type_id = is_32bit ? TypeId::kUInt32 : TypeId::kUInt64; 118 } 119 } 120 121 // Type size helps to construct all groups of registers. 122 // TypeId is invalid if the size is zero. 123 uint32_t size = TypeUtils::size_of(type_id); 124 if (ASMJIT_UNLIKELY(!size)) { 125 return make_error(Error::kInvalidTypeId); 126 } 127 128 if (ASMJIT_UNLIKELY(type_id == TypeId::kFloat80)) { 129 return make_error(Error::kInvalidUseOfF80); 130 } 131 132 RegType reg_type = RegType::kNone; 133 if (TypeUtils::is_between(type_id, TypeId::_kBaseStart, TypeId::_kVec32Start)) { 134 reg_type = arch_traits._type_id_to_reg_type[uint32_t(type_id) - uint32_t(TypeId::_kBaseStart)]; 135 if (reg_type == RegType::kNone) { 136 if (type_id == TypeId::kInt64 || type_id == TypeId::kUInt64) { 137 return make_error(Error::kInvalidUseOfGpq); 138 } 139 else { 140 return make_error(Error::kInvalidTypeId); 141 } 142 } 143 } 144 else { 145 if (size <= 8 && arch_traits.has_reg_type(RegType::kVec64)) { 146 reg_type = RegType::kVec64; 147 } 148 else if (size <= 16 && arch_traits.has_reg_type(RegType::kVec128)) { 149 reg_type = RegType::kVec128; 150 } 151 else if (size == 32 && arch_traits.has_reg_type(RegType::kVec256)) { 152 reg_type = RegType::kVec256; 153 } 154 else if (arch_traits.has_reg_type(RegType::kVec512)) { 155 reg_type = RegType::kVec512; 156 } 157 else { 158 return make_error(Error::kInvalidTypeId); 159 } 160 } 161 162 *type_id_out = type_id; 163 *reg_signature_out = RegUtils::signature_of(reg_type); 164 return Error::kOk; 165 } 166 167 ASMJIT_END_NAMESPACE