1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 Copyright (c) 2008-2017, Petr Kobalicek
3 
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7 
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11 
12 1. The origin of this software must not be misrepresented; you must not
13    claim that you wrote the original software. If you use this software
14    in a product, an acknowledgment in the product documentation would be
15    appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17    misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
20 #ifdef __PLUMED_HAS_ASMJIT
21 #pragma GCC diagnostic push
22 #pragma GCC diagnostic ignored "-Wpedantic"
23 // [AsmJit]
24 // Complete x86/x64 JIT and Remote Assembler for C++.
25 //
26 // [License]
27 // Zlib - See LICENSE.md file in the package.
28 
29 // [Export]
30 #define ASMJIT_EXPORTS
31 
32 // [Dependencies]
33 #include "./arch.h"
34 
35 #if defined(ASMJIT_BUILD_X86)
36 #include "./x86operand.h"
37 #endif // ASMJIT_BUILD_X86
38 
39 // [Api-Begin]
40 #include "./asmjit_apibegin.h"
41 
42 namespace PLMD {
43 namespace asmjit {
44 
45 // ============================================================================
46 // [asmjit::ArchInfo]
47 // ============================================================================
48 
49 static const uint32_t archInfoTable[] = {
50   // <-------------+---------------------+-----------------------+-------+
51   //               | Type                | SubType               | GPInfo|
52   // <-------------+---------------------+-----------------------+-------+
53   ASMJIT_PACK32_4x8(ArchInfo::kTypeNone  , ArchInfo::kSubTypeNone, 0,  0),
54   ASMJIT_PACK32_4x8(ArchInfo::kTypeX86   , ArchInfo::kSubTypeNone, 4,  8),
55   ASMJIT_PACK32_4x8(ArchInfo::kTypeX64   , ArchInfo::kSubTypeNone, 8, 16),
56   ASMJIT_PACK32_4x8(ArchInfo::kTypeX32   , ArchInfo::kSubTypeNone, 8, 16),
57   ASMJIT_PACK32_4x8(ArchInfo::kTypeA32   , ArchInfo::kSubTypeNone, 4, 16),
58   ASMJIT_PACK32_4x8(ArchInfo::kTypeA64   , ArchInfo::kSubTypeNone, 8, 32)
59 };
60 
init(uint32_t type,uint32_t subType)61 ASMJIT_FAVOR_SIZE void ArchInfo::init(uint32_t type, uint32_t subType) noexcept {
62   uint32_t index = type < ASMJIT_ARRAY_SIZE(archInfoTable) ? type : uint32_t(0);
63 
64   // Make sure the `archInfoTable` array is correctly indexed.
65   _signature = archInfoTable[index];
66   ASMJIT_ASSERT(_type == index);
67 
68   // Even if the architecture is not known we setup its type and sub-type,
69   // however, such architecture is not really useful.
70   _type = type;
71   _subType = subType;
72 }
73 
74 // ============================================================================
75 // [asmjit::ArchUtils]
76 // ============================================================================
77 
typeIdToRegInfo(uint32_t archType,uint32_t & typeIdInOut,RegInfo & regInfo)78 ASMJIT_FAVOR_SIZE Error ArchUtils::typeIdToRegInfo(uint32_t archType, uint32_t& typeIdInOut, RegInfo& regInfo) noexcept {
79   uint32_t typeId = typeIdInOut;
80 
81   // Zero the signature so it's clear in case that typeId is not invalid.
82   regInfo._signature = 0;
83 
84 #if defined(ASMJIT_BUILD_X86)
85   if (ArchInfo::isX86Family(archType)) {
86     // Passed RegType instead of TypeId?
87     if (typeId <= Reg::kRegMax)
88       typeId = x86OpData.archRegs.regTypeToTypeId[typeId];
89 
90     if (ASMJIT_UNLIKELY(!TypeId::isValid(typeId)))
91       return DebugUtils::errored(kErrorInvalidTypeId);
92 
93     // First normalize architecture dependent types.
94     if (TypeId::isAbstract(typeId)) {
95       if (typeId == TypeId::kIntPtr)
96         typeId = (archType == ArchInfo::kTypeX86) ? TypeId::kI32 : TypeId::kI64;
97       else
98         typeId = (archType == ArchInfo::kTypeX86) ? TypeId::kU32 : TypeId::kU64;
99     }
100 
101     // Type size helps to construct all kinds of registers. If the size is zero
102     // then the TypeId is invalid.
103     uint32_t size = TypeId::sizeOf(typeId);
104     if (ASMJIT_UNLIKELY(!size))
105       return DebugUtils::errored(kErrorInvalidTypeId);
106 
107     if (ASMJIT_UNLIKELY(typeId == TypeId::kF80))
108       return DebugUtils::errored(kErrorInvalidUseOfF80);
109 
110     uint32_t regType = 0;
111 
112     switch (typeId) {
113       case TypeId::kI8:
114       case TypeId::kU8:
115         regType = X86Reg::kRegGpbLo;
116         break;
117 
118       case TypeId::kI16:
119       case TypeId::kU16:
120         regType = X86Reg::kRegGpw;
121         break;
122 
123       case TypeId::kI32:
124       case TypeId::kU32:
125         regType = X86Reg::kRegGpd;
126         break;
127 
128       case TypeId::kI64:
129       case TypeId::kU64:
130         if (archType == ArchInfo::kTypeX86)
131           return DebugUtils::errored(kErrorInvalidUseOfGpq);
132 
133         regType = X86Reg::kRegGpq;
134         break;
135 
136       // F32 and F64 are always promoted to use vector registers.
137       case TypeId::kF32:
138         typeId = TypeId::kF32x1;
139         regType = X86Reg::kRegXmm;
140         break;
141 
142       case TypeId::kF64:
143         typeId = TypeId::kF64x1;
144         regType = X86Reg::kRegXmm;
145         break;
146 
147       // Mask registers {k}.
148       case TypeId::kMask8:
149       case TypeId::kMask16:
150       case TypeId::kMask32:
151       case TypeId::kMask64:
152         regType = X86Reg::kRegK;
153         break;
154 
155       // MMX registers.
156       case TypeId::kMmx32:
157       case TypeId::kMmx64:
158         regType = X86Reg::kRegMm;
159         break;
160 
161       // XMM|YMM|ZMM registers.
162       default:
163         if (size <= 16)
164           regType = X86Reg::kRegXmm;
165         else if (size == 32)
166           regType = X86Reg::kRegYmm;
167         else
168           regType = X86Reg::kRegZmm;
169         break;
170     }
171 
172     typeIdInOut = typeId;
173     regInfo._signature = x86OpData.archRegs.regInfo[regType].getSignature();
174     return kErrorOk;
175   }
176 #endif // ASMJIT_BUILD_X86
177 
178   return DebugUtils::errored(kErrorInvalidArch);
179 }
180 
181 } // asmjit namespace
182 } // namespace PLMD
183 
184 // [Api-End]
185 #include "./asmjit_apiend.h"
186 #pragma GCC diagnostic pop
187 #endif // __PLUMED_HAS_ASMJIT
188