Line data Source code
1 : #ifdef __PLUMED_HAS_ASMJIT
2 : // This file is part of AsmJit project <https://asmjit.com>
3 : //
4 : // See asmjit.h or LICENSE.md for license and copyright information
5 : // SPDX-License-Identifier: Zlib
6 :
7 : #include "api-build_p.h"
8 : #if !defined(ASMJIT_NO_AARCH64)
9 :
10 : #include "cpuinfo.h"
11 : #include "misc_p.h"
12 : #include "support.h"
13 : #include "a64instapi_p.h"
14 : #include "a64instdb_p.h"
15 : #include "a64operand.h"
16 :
17 : ASMJIT_BEGIN_SUB_NAMESPACE(a64)
18 :
19 : // a64::InstInternal - Text
20 : // ========================
21 :
22 : #ifndef ASMJIT_NO_TEXT
23 0 : Error InstInternal::instIdToString(Arch arch, InstId instId, String& output) noexcept {
24 0 : uint32_t realId = instId & uint32_t(InstIdParts::kRealId);
25 : DebugUtils::unused(arch);
26 :
27 0 : if (ASMJIT_UNLIKELY(!Inst::isDefinedId(realId)))
28 : return DebugUtils::errored(kErrorInvalidInstruction);
29 :
30 : const InstDB::InstInfo& info = InstDB::infoById(realId);
31 0 : return output.append(InstDB::_nameData + info._nameDataIndex);
32 : }
33 :
34 0 : InstId InstInternal::stringToInstId(Arch arch, const char* s, size_t len) noexcept {
35 : DebugUtils::unused(arch);
36 :
37 0 : if (ASMJIT_UNLIKELY(!s))
38 : return Inst::kIdNone;
39 :
40 0 : if (len == SIZE_MAX)
41 0 : len = strlen(s);
42 :
43 0 : if (ASMJIT_UNLIKELY(len == 0 || len > InstDB::kMaxNameSize))
44 : return Inst::kIdNone;
45 :
46 0 : uint32_t prefix = uint32_t(s[0]) - 'a';
47 0 : if (ASMJIT_UNLIKELY(prefix > 'z' - 'a'))
48 : return Inst::kIdNone;
49 :
50 0 : uint32_t index = InstDB::instNameIndex[prefix].start;
51 0 : if (ASMJIT_UNLIKELY(!index))
52 : return Inst::kIdNone;
53 :
54 : const char* nameData = InstDB::_nameData;
55 : const InstDB::InstInfo* table = InstDB::_instInfoTable;
56 :
57 0 : const InstDB::InstInfo* base = table + index;
58 0 : const InstDB::InstInfo* end = table + InstDB::instNameIndex[prefix].end;
59 :
60 0 : for (size_t lim = (size_t)(end - base); lim != 0; lim >>= 1) {
61 0 : const InstDB::InstInfo* cur = base + (lim >> 1);
62 0 : int result = Support::cmpInstName(nameData + cur[0]._nameDataIndex, s, len);
63 :
64 0 : if (result < 0) {
65 0 : base = cur + 1;
66 0 : lim--;
67 0 : continue;
68 : }
69 :
70 0 : if (result > 0)
71 0 : continue;
72 :
73 0 : return uint32_t((size_t)(cur - table));
74 : }
75 :
76 : return Inst::kIdNone;
77 : }
78 : #endif // !ASMJIT_NO_TEXT
79 :
80 : // a64::InstInternal - Validate
81 : // ============================
82 :
83 : #ifndef ASMJIT_NO_VALIDATION
84 0 : ASMJIT_FAVOR_SIZE Error InstInternal::validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept {
85 : // TODO:
86 : DebugUtils::unused(arch, inst, operands, opCount, validationFlags);
87 0 : return kErrorOk;
88 : }
89 : #endif // !ASMJIT_NO_VALIDATION
90 :
91 : // a64::InstInternal - QueryRWInfo
92 : // ===============================
93 :
94 : #ifndef ASMJIT_NO_INTROSPECTION
95 : struct InstRWInfoData {
96 : uint8_t rwx[Globals::kMaxOpCount];
97 : };
98 :
99 : static const InstRWInfoData instRWInfoData[] = {
100 : #define R uint8_t(OpRWFlags::kRead)
101 : #define W uint8_t(OpRWFlags::kWrite)
102 : #define X uint8_t(OpRWFlags::kRW)
103 :
104 : {{ R, R, R, R, R, R }}, // kRWI_R
105 : {{ R, W, R, R, R, R }}, // kRWI_RW
106 : {{ R, X, R, R, R, R }}, // kRWI_RX
107 : {{ R, R, W, R, R, R }}, // kRWI_RRW
108 : {{ R, W, X, R, R, R }}, // kRWI_RWX
109 : {{ W, R, R, R, R, R }}, // kRWI_W
110 : {{ W, R, W, R, R, R }}, // kRWI_WRW
111 : {{ W, R, X, R, R, R }}, // kRWI_WRX
112 : {{ W, R, R, W, R, R }}, // kRWI_WRRW
113 : {{ W, R, R, X, R, R }}, // kRWI_WRRX
114 : {{ W, W, R, R, R, R }}, // kRWI_WW
115 : {{ X, R, R, R, R, R }}, // kRWI_X
116 : {{ X, R, X, R, R, R }}, // kRWI_XRX
117 : {{ X, X, R, R, X, R }}, // kRWI_XXRRX
118 :
119 : {{ W, R, R, R, R, R }}, // kRWI_LDn
120 : {{ R, W, R, R, R, R }}, // kRWI_STn
121 : {{ R, R, R, R, R, R }} // kRWI_TODO
122 :
123 : #undef R
124 : #undef W
125 : #undef X
126 : };
127 :
128 : static const uint8_t elementTypeSize[8] = { 0, 1, 2, 4, 8, 4, 4, 0 };
129 :
130 0 : Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept {
131 : // Unused in Release configuration as the assert is not compiled in.
132 : DebugUtils::unused(arch);
133 :
134 : // Only called when `arch` matches X86 family.
135 : ASMJIT_ASSERT(Environment::isFamilyARM(arch));
136 :
137 : // Get the instruction data.
138 0 : uint32_t realId = inst.id() & uint32_t(InstIdParts::kRealId);
139 :
140 0 : if (ASMJIT_UNLIKELY(!Inst::isDefinedId(realId)))
141 : return DebugUtils::errored(kErrorInvalidInstruction);
142 :
143 0 : out->_instFlags = InstRWFlags::kNone;
144 0 : out->_opCount = uint8_t(opCount);
145 0 : out->_rmFeature = 0;
146 0 : out->_extraReg.reset();
147 0 : out->_readFlags = CpuRWFlags::kNone; // TODO: [ARM] Read PSTATUS.
148 0 : out->_writeFlags = CpuRWFlags::kNone; // TODO: [ARM] Write PSTATUS
149 :
150 : const InstDB::InstInfo& instInfo = InstDB::_instInfoTable[realId];
151 : const InstRWInfoData& rwInfo = instRWInfoData[instInfo.rwInfoIndex()];
152 :
153 0 : if (instInfo.hasFlag(InstDB::kInstFlagConsecutive) && opCount > 2) {
154 0 : for (uint32_t i = 0; i < opCount; i++) {
155 0 : OpRWInfo& op = out->_operands[i];
156 0 : const Operand_& srcOp = operands[i];
157 :
158 0 : if (!srcOp.isRegOrMem()) {
159 0 : op.reset();
160 0 : continue;
161 : }
162 :
163 0 : OpRWFlags rwFlags = i < opCount - 1 ? (OpRWFlags)rwInfo.rwx[0] : (OpRWFlags)rwInfo.rwx[1];
164 :
165 0 : op._opFlags = rwFlags & ~(OpRWFlags::kZExt);
166 0 : op._physId = BaseReg::kIdBad;
167 0 : op._rmSize = 0;
168 : op._resetReserved();
169 :
170 0 : uint64_t rByteMask = op.isRead() ? 0xFFFFFFFFFFFFFFFFu : 0x0000000000000000u;
171 0 : uint64_t wByteMask = op.isWrite() ? 0xFFFFFFFFFFFFFFFFu : 0x0000000000000000u;
172 :
173 0 : op._readByteMask = rByteMask;
174 0 : op._writeByteMask = wByteMask;
175 0 : op._extendByteMask = 0;
176 0 : op._consecutiveLeadCount = 0;
177 :
178 0 : if (srcOp.isReg()) {
179 0 : if (i == 0)
180 0 : op._consecutiveLeadCount = uint8_t(opCount - 1);
181 : else
182 : op.addOpFlags(OpRWFlags::kConsecutive);
183 : }
184 : else {
185 : const Mem& memOp = srcOp.as<Mem>();
186 :
187 0 : if (memOp.hasBase()) {
188 : op.addOpFlags(OpRWFlags::kMemBaseRead);
189 : }
190 :
191 0 : if (memOp.hasIndex()) {
192 : op.addOpFlags(OpRWFlags::kMemIndexRead);
193 0 : op.addOpFlags(memOp.isPreOrPost() ? OpRWFlags::kMemIndexWrite : OpRWFlags::kNone);
194 : }
195 : }
196 : }
197 : }
198 : else {
199 0 : for (uint32_t i = 0; i < opCount; i++) {
200 0 : OpRWInfo& op = out->_operands[i];
201 0 : const Operand_& srcOp = operands[i];
202 :
203 0 : if (!srcOp.isRegOrMem()) {
204 0 : op.reset();
205 0 : continue;
206 : }
207 :
208 0 : OpRWFlags rwFlags = (OpRWFlags)rwInfo.rwx[i];
209 :
210 0 : op._opFlags = rwFlags & ~(OpRWFlags::kZExt);
211 0 : op._physId = BaseReg::kIdBad;
212 0 : op._rmSize = 0;
213 : op._resetReserved();
214 :
215 0 : uint64_t rByteMask = op.isRead() ? 0xFFFFFFFFFFFFFFFFu : 0x0000000000000000u;
216 0 : uint64_t wByteMask = op.isWrite() ? 0xFFFFFFFFFFFFFFFFu : 0x0000000000000000u;
217 :
218 0 : op._readByteMask = rByteMask;
219 0 : op._writeByteMask = wByteMask;
220 0 : op._extendByteMask = 0;
221 0 : op._consecutiveLeadCount = 0;
222 :
223 0 : if (srcOp.isReg()) {
224 0 : if (srcOp.as<Vec>().hasElementIndex()) {
225 : // Only part of the vector is accessed if element index [] is used.
226 : uint32_t elementType = srcOp.as<Vec>().elementType();
227 : uint32_t elementIndex = srcOp.as<Vec>().elementIndex();
228 :
229 0 : uint32_t elementSize = elementTypeSize[elementType];
230 0 : uint64_t accessMask = uint64_t(Support::lsbMask<uint32_t>(elementSize)) << (elementIndex * elementSize);
231 :
232 0 : op._readByteMask &= accessMask;
233 0 : op._writeByteMask &= accessMask;
234 : }
235 :
236 : // TODO: [ARM] RW info is not finished.
237 : }
238 : else {
239 : const Mem& memOp = srcOp.as<Mem>();
240 :
241 0 : if (memOp.hasBase()) {
242 : op.addOpFlags(OpRWFlags::kMemBaseRead);
243 : }
244 :
245 0 : if (memOp.hasIndex()) {
246 : op.addOpFlags(OpRWFlags::kMemIndexRead);
247 0 : op.addOpFlags(memOp.isPreOrPost() ? OpRWFlags::kMemIndexWrite : OpRWFlags::kNone);
248 : }
249 : }
250 : }
251 : }
252 :
253 : return kErrorOk;
254 : }
255 : #endif // !ASMJIT_NO_INTROSPECTION
256 :
257 : // a64::InstInternal - QueryFeatures
258 : // =================================
259 :
260 : #ifndef ASMJIT_NO_INTROSPECTION
261 0 : Error InstInternal::queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept {
262 : // TODO: [ARM] QueryFeatures not implemented yet.
263 : DebugUtils::unused(arch, inst, operands, opCount, out);
264 0 : return kErrorOk;
265 : }
266 : #endif // !ASMJIT_NO_INTROSPECTION
267 :
268 : // a64::InstInternal - Unit
269 : // ========================
270 :
271 : #if defined(ASMJIT_TEST)
272 : UNIT(arm_inst_api_text) {
273 : // TODO:
274 : }
275 : #endif
276 :
277 : ASMJIT_END_SUB_NAMESPACE
278 :
279 : #endif // !ASMJIT_NO_AARCH64
280 :
281 : #endif // __PLUMED_HAS_ASMJIT
|