odin-blend2d

Odin bindings to Blend2D
Log | Files | Refs | README | LICENSE

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