Line data Source code
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 : // [Guard]
33 : #include "./asmjit_build.h"
34 : #if !defined(ASMJIT_DISABLE_LOGGING)
35 :
36 : // [Dependencies]
37 : #include "./misc_p.h"
38 : #include "./x86inst.h"
39 : #include "./x86logging_p.h"
40 : #include "./x86operand.h"
41 :
42 : #if !defined(ASMJIT_DISABLE_COMPILER)
43 : #include "./codecompiler.h"
44 : #endif // !ASMJIT_DISABLE_COMPILER
45 :
46 : // [Api-Begin]
47 : #include "./asmjit_apibegin.h"
48 :
49 : namespace PLMD {
50 : namespace asmjit {
51 :
52 : // ============================================================================
53 : // [asmjit::X86Logging - Constants]
54 : // ============================================================================
55 :
56 : struct X86RegFormatInfo {
57 : uint8_t count;
58 : uint8_t formatIndex;
59 : uint8_t specialIndex;
60 : uint8_t specialCount;
61 : };
62 :
63 : static const char x86RegFormatStrings[] =
64 : "r%ub" "\0" // #0
65 : "r%uh" "\0" // #5
66 : "r%uw" "\0" // #10
67 : "r%ud" "\0" // #15
68 : "r%u" "\0" // #20
69 : "xmm%u" "\0" // #24
70 : "ymm%u" "\0" // #30
71 : "zmm%u" "\0" // #36
72 : "rip%u" "\0" // #42
73 : "seg%u" "\0" // #48
74 : "fp%u" "\0" // #54
75 : "mm%u" "\0" // #59
76 : "k%u" "\0" // #64
77 : "bnd%u" "\0" // #68
78 : "cr%u" "\0" // #74
79 : "dr%u" "\0" // #79
80 :
81 : "rip\0" // #84
82 : "\0\0\0\0" // #88
83 : "\0\0\0\0" // #92
84 :
85 : "al\0\0" "cl\0\0" "dl\0\0" "bl\0\0" "spl\0" "bpl\0" "sil\0" "dil\0" // #96
86 : "ah\0\0" "ch\0\0" "dh\0\0" "bh\0\0" "n/a\0" "n/a\0" "n/a\0" "n/a\0" // #128
87 : "eax\0" "ecx\0" "edx\0" "ebx\0" "esp\0" "ebp\0" "esi\0" "edi\0" // #160
88 : "rax\0" "rcx\0" "rdx\0" "rbx\0" "rsp\0" "rbp\0" "rsi\0" "rdi\0" // #192
89 : "n/a\0" "es\0\0" "cs\0\0" "ss\0\0" "ds\0\0" "fs\0\0" "gs\0\0" "n/a\0"; // #224
90 :
91 : template<uint32_t X>
92 : struct X86RegFormatInfo_T {
93 : enum {
94 : kFormatIndex = X == X86Reg::kRegGpbLo ? 0 :
95 : X == X86Reg::kRegGpbHi ? 5 :
96 : X == X86Reg::kRegGpw ? 10 :
97 : X == X86Reg::kRegGpd ? 15 :
98 : X == X86Reg::kRegGpq ? 20 :
99 : X == X86Reg::kRegXmm ? 24 :
100 : X == X86Reg::kRegYmm ? 30 :
101 : X == X86Reg::kRegZmm ? 36 :
102 : X == X86Reg::kRegRip ? 42 :
103 : X == X86Reg::kRegSeg ? 48 :
104 : X == X86Reg::kRegFp ? 54 :
105 : X == X86Reg::kRegMm ? 59 :
106 : X == X86Reg::kRegK ? 64 :
107 : X == X86Reg::kRegBnd ? 68 :
108 : X == X86Reg::kRegCr ? 74 :
109 : X == X86Reg::kRegDr ? 79 : 0,
110 :
111 : kSpecialIndex = X == X86Reg::kRegGpbLo ? 96 :
112 : X == X86Reg::kRegGpbHi ? 128 :
113 : X == X86Reg::kRegGpw ? 161 :
114 : X == X86Reg::kRegGpd ? 160 :
115 : X == X86Reg::kRegGpq ? 192 :
116 : X == X86Reg::kRegRip ? 84 :
117 : X == X86Reg::kRegSeg ? 224 : 0,
118 :
119 : kSpecialCount = X == X86Reg::kRegGpbLo ? 8 :
120 : X == X86Reg::kRegGpbHi ? 4 :
121 : X == X86Reg::kRegGpw ? 8 :
122 : X == X86Reg::kRegGpd ? 8 :
123 : X == X86Reg::kRegGpq ? 8 :
124 : X == X86Reg::kRegRip ? 1 :
125 : X == X86Reg::kRegSeg ? 7 : 0
126 : };
127 : };
128 :
129 : #define ASMJIT_X86_REG_FORMAT(TYPE) { \
130 : X86RegTraits<TYPE>::kCount, \
131 : X86RegFormatInfo_T<TYPE>::kFormatIndex, \
132 : X86RegFormatInfo_T<TYPE>::kSpecialIndex, \
133 : X86RegFormatInfo_T<TYPE>::kSpecialCount \
134 : }
135 :
136 : static const X86RegFormatInfo x86RegFormatInfo[] = {
137 : ASMJIT_TABLE_16(ASMJIT_X86_REG_FORMAT, 0 ),
138 : ASMJIT_TABLE_16(ASMJIT_X86_REG_FORMAT, 16)
139 : };
140 :
141 0 : static const char* x86GetAddressSizeString(uint32_t size) noexcept {
142 0 : switch (size) {
143 : case 1 : return "byte ";
144 0 : case 2 : return "word ";
145 0 : case 4 : return "dword ";
146 0 : case 6 : return "fword ";
147 0 : case 8 : return "qword ";
148 0 : case 10: return "tword ";
149 0 : case 16: return "oword ";
150 0 : case 32: return "yword ";
151 0 : case 64: return "zword ";
152 0 : default: return "";
153 : }
154 : }
155 :
156 : // ============================================================================
157 : // [asmjit::X86Logging - Format Operand]
158 : // ============================================================================
159 :
160 0 : ASMJIT_FAVOR_SIZE Error X86Logging::formatOperand(
161 : StringBuilder& sb,
162 : uint32_t logOptions,
163 : const CodeEmitter* emitter,
164 : uint32_t archType,
165 : const Operand_& op) noexcept {
166 :
167 0 : if (op.isReg())
168 0 : return formatRegister(sb, logOptions, emitter, archType, op.as<Reg>().getType(), op.as<Reg>().getId());
169 :
170 0 : if (op.isMem()) {
171 : const X86Mem& m = op.as<X86Mem>();
172 0 : ASMJIT_PROPAGATE(sb.appendString(x86GetAddressSizeString(m.getSize())));
173 :
174 : // Segment override prefix.
175 : uint32_t seg = m.getSegmentId();
176 0 : if (seg != X86Seg::kIdNone && seg < X86Seg::kIdCount)
177 0 : ASMJIT_PROPAGATE(sb.appendFormat("%s:", x86RegFormatStrings + 224 + seg * 4));
178 :
179 0 : ASMJIT_PROPAGATE(sb.appendChar('['));
180 0 : if (m.isAbs())
181 0 : ASMJIT_PROPAGATE(sb.appendString("abs "));
182 :
183 0 : if (m.hasBase()) {
184 0 : if (m.hasBaseLabel()) {
185 0 : ASMJIT_PROPAGATE(Logging::formatLabel(sb, logOptions, emitter, m.getBaseId()));
186 : }
187 : else {
188 0 : if (m.isArgHome()) ASMJIT_PROPAGATE(sb.appendString("$"));
189 0 : if (m.isRegHome()) ASMJIT_PROPAGATE(sb.appendString("&"));
190 0 : ASMJIT_PROPAGATE(formatRegister(sb, logOptions, emitter, archType, m.getBaseType(), m.getBaseId()));
191 : }
192 : }
193 :
194 0 : if (m.hasIndex()) {
195 0 : ASMJIT_PROPAGATE(sb.appendChar('+'));
196 0 : ASMJIT_PROPAGATE(formatRegister(sb, logOptions, emitter, archType, m.getIndexType(), m.getIndexId()));
197 0 : if (m.hasShift())
198 0 : ASMJIT_PROPAGATE(sb.appendFormat("*%u", 1 << m.getShift()));
199 : }
200 :
201 0 : uint64_t off = static_cast<uint64_t>(m.getOffset());
202 0 : if (off) {
203 : uint32_t base = 10;
204 : char prefix = '+';
205 :
206 0 : if (static_cast<int64_t>(off) < 0) {
207 0 : off = ~off + 1;
208 : prefix = '-';
209 : }
210 :
211 0 : ASMJIT_PROPAGATE(sb.appendChar(prefix));
212 0 : if ((logOptions & Logger::kOptionHexDisplacement) != 0 && off > 9) {
213 0 : ASMJIT_PROPAGATE(sb.appendString("0x", 2));
214 : base = 16;
215 : }
216 0 : ASMJIT_PROPAGATE(sb.appendUInt(off, base));
217 : }
218 :
219 0 : return sb.appendChar(']');
220 : }
221 :
222 0 : if (op.isImm()) {
223 : const Imm& i = op.as<Imm>();
224 : int64_t val = i.getInt64();
225 :
226 0 : if ((logOptions & Logger::kOptionHexImmediate) != 0 && static_cast<uint64_t>(val) > 9)
227 0 : return sb.appendUInt(static_cast<uint64_t>(val), 16);
228 : else
229 0 : return sb.appendInt(val, 10);
230 : }
231 :
232 0 : if (op.isLabel()) {
233 0 : return Logging::formatLabel(sb, logOptions, emitter, op.getId());
234 : }
235 :
236 0 : return sb.appendString("<None>");
237 : }
238 :
239 : // ============================================================================
240 : // [asmjit::X86Logging - Format Immediate (Extension)]
241 : // ============================================================================
242 :
243 : struct ImmBits {
244 : enum Mode {
245 : kModeLookup = 0x0,
246 : kModeFormat = 0x1
247 : };
248 :
249 : uint8_t mask;
250 : uint8_t shift;
251 : uint8_t mode;
252 : char text[45];
253 : };
254 :
255 0 : ASMJIT_FAVOR_SIZE static Error X86Logging_formatImmShuf(StringBuilder& sb, uint32_t u8, uint32_t bits, uint32_t count) noexcept {
256 0 : ASMJIT_PROPAGATE(sb.appendChar('<'));
257 0 : uint32_t mask = (1 << bits) - 1;
258 :
259 0 : for (uint32_t i = 0; i < count; i++, u8 >>= bits) {
260 0 : uint32_t value = u8 & mask;
261 0 : if (i != 0)
262 0 : ASMJIT_PROPAGATE(sb.appendChar('|'));
263 0 : ASMJIT_PROPAGATE(sb.appendUInt(value));
264 : }
265 :
266 0 : return sb.appendChar('>');
267 : }
268 :
269 0 : ASMJIT_FAVOR_SIZE static Error X86Logging_formatImmBits(StringBuilder& sb, uint32_t u8, const ImmBits* bits, uint32_t count) noexcept {
270 : uint32_t n = 0;
271 : char buf[64];
272 :
273 0 : for (uint32_t i = 0; i < count; i++) {
274 0 : const ImmBits& spec = bits[i];
275 :
276 0 : uint32_t value = (u8 & static_cast<uint32_t>(spec.mask)) >> spec.shift;
277 : const char* str = nullptr;
278 :
279 0 : switch (spec.mode) {
280 0 : case ImmBits::kModeLookup:
281 0 : str = Utils::findPackedString(spec.text, value);
282 : break;
283 :
284 0 : case ImmBits::kModeFormat:
285 0 : snprintf(buf, sizeof(buf), spec.text, static_cast<unsigned int>(value));
286 : str = buf;
287 0 : break;
288 :
289 : default:
290 : return DebugUtils::errored(kErrorInvalidState);
291 : }
292 :
293 0 : if (!str[0])
294 0 : continue;
295 :
296 0 : ASMJIT_PROPAGATE(sb.appendChar(++n == 1 ? '<' : '|'));
297 0 : ASMJIT_PROPAGATE(sb.appendString(str));
298 : }
299 :
300 0 : return n ? sb.appendChar('>') : static_cast<Error>(kErrorOk);
301 : }
302 :
303 0 : ASMJIT_FAVOR_SIZE static Error X86Logging_formatImmText(StringBuilder& sb, uint32_t u8, uint32_t bits, uint32_t advance, const char* text, uint32_t count = 1) noexcept {
304 0 : ASMJIT_PROPAGATE(sb.appendChar('<'));
305 :
306 0 : uint32_t mask = (1 << bits) - 1;
307 : uint32_t pos = 0;
308 :
309 0 : for (uint32_t i = 0; i < count; i++, u8 >>= bits, pos += advance) {
310 0 : uint32_t value = (u8 & mask) + pos;
311 0 : if (i != 0)
312 0 : ASMJIT_PROPAGATE(sb.appendChar('|'));
313 0 : ASMJIT_PROPAGATE(sb.appendString(Utils::findPackedString(text, value)));
314 : }
315 :
316 0 : return sb.appendChar('>');
317 : }
318 :
319 0 : ASMJIT_FAVOR_SIZE static Error X86Logging_formatImmExtended(
320 : StringBuilder& sb,
321 : uint32_t logOptions,
322 : uint32_t instId,
323 : uint32_t vecSize,
324 : const Imm& imm) noexcept {
325 :
326 : static const char vcmpx[] =
327 : "eq_oq\0" "lt_os\0" "le_os\0" "unord_q\0" "neq_uq\0" "nlt_us\0" "nle_us\0" "ord_q\0"
328 : "eq_uq\0" "nge_us\0" "ngt_us\0" "false_oq\0" "neq_oq\0" "ge_os\0" "gt_os\0" "true_uq\0"
329 : "eq_os\0" "lt_oq\0" "le_oq\0" "unord_s\0" "neq_us\0" "nlt_uq\0" "nle_uq\0" "ord_s\0"
330 : "eq_us\0" "nge_uq\0" "ngt_uq\0" "false_os\0" "neq_os\0" "ge_oq\0" "gt_oq\0" "true_us\0";
331 :
332 : // Try to find 7 differences...
333 : static const char vpcmpx[] = "eq\0" "lt\0" "le\0" "false\0" "neq\0" "ge\0" "gt\0" "true\0";
334 : static const char vpcomx[] = "lt\0" "le\0" "gt\0" "ge\0" "eq\0" "neq\0" "false\0" "true\0";
335 :
336 : static const char vshufpd[] = "a0\0a1\0b0\0b1\0a2\0a3\0b2\0b3\0a4\0a5\0b4\0b5\0a6\0a7\0b6\0b7\0";
337 : static const char vshufps[] = "a0\0a1\0a2\0a3\0a0\0a1\0a2\0a3\0b0\0b1\0b2\0b3\0b0\0b1\0b2\0b3\0";
338 :
339 : static const ImmBits vfpclassxx[] = {
340 : { 0x07, 0, ImmBits::kModeLookup, "qnan\0" "+0\0" "-0\0" "+inf\0" "-inf\0" "denormal\0" "-finite\0" "snan\0" }
341 : };
342 :
343 : static const ImmBits vgetmantxx[] = {
344 : { 0x03, 0, ImmBits::kModeLookup, "[1, 2)\0" "[1/2, 2)\0" "1/2, 1)\0" "[3/4, 3/2)\0" },
345 : { 0x04, 2, ImmBits::kModeLookup, "\0" "no-sign\0" },
346 : { 0x08, 3, ImmBits::kModeLookup, "\0" "qnan-if-sign\0" }
347 : };
348 :
349 : static const ImmBits vmpsadbw[] = {
350 : { 0x04, 2, ImmBits::kModeLookup, "blk1[0]\0" "blk1[1]\0" },
351 : { 0x03, 0, ImmBits::kModeLookup, "blk2[0]\0" "blk2[1]\0" "blk2[2]\0" "blk2[3]\0" },
352 : { 0x40, 6, ImmBits::kModeLookup, "blk1[4]\0" "blk1[5]\0" },
353 : { 0x30, 4, ImmBits::kModeLookup, "blk2[4]\0" "blk2[5]\0" "blk2[6]\0" "blk2[7]\0" }
354 : };
355 :
356 : static const ImmBits vpclmulqdq[] = {
357 : { 0x01, 0, ImmBits::kModeLookup, "lq\0" "hq\0" },
358 : { 0x10, 4, ImmBits::kModeLookup, "lq\0" "hq\0" }
359 : };
360 :
361 : static const ImmBits vperm2x128[] = {
362 : { 0x0B, 0, ImmBits::kModeLookup, "a0\0" "a1\0" "b0\0" "b1\0" "\0" "\0" "\0" "\0" "0\0" "0\0" "0\0" "0\0" },
363 : { 0xB0, 4, ImmBits::kModeLookup, "a0\0" "a1\0" "b0\0" "b1\0" "\0" "\0" "\0" "\0" "0\0" "0\0" "0\0" "0\0" }
364 : };
365 :
366 : static const ImmBits vrangexx[] = {
367 : { 0x03, 0, ImmBits::kModeLookup, "min\0" "max\0" "min-abs\0" "max-abs\0" },
368 : { 0x0C, 2, ImmBits::kModeLookup, "sign=src1\0" "sign=src2\0" "sign=0\0" "sign=1\0" }
369 : };
370 :
371 : static const ImmBits vreducexx_vrndscalexx[] = {
372 : { 0x07, 0, ImmBits::kModeLookup, "\0" "\0" "\0" "\0" "round\0" "floor\0" "ceil\0" "truncate\0" },
373 : { 0x08, 3, ImmBits::kModeLookup, "\0" "suppress\0" },
374 : { 0xF0, 4, ImmBits::kModeFormat, "len=%d" }
375 : };
376 :
377 : static const ImmBits vroundxx[] = {
378 : { 0x07, 0, ImmBits::kModeLookup, "round\0" "floor\0" "ceil\0" "truncate\0" "\0" "\0" "\0" "\0" },
379 : { 0x08, 3, ImmBits::kModeLookup, "\0" "inexact\0" }
380 : };
381 :
382 : uint32_t u8 = imm.getUInt8();
383 0 : switch (instId) {
384 0 : case X86Inst::kIdVblendpd:
385 : case X86Inst::kIdBlendpd:
386 0 : return X86Logging_formatImmShuf(sb, u8, 1, vecSize / 8);
387 :
388 0 : case X86Inst::kIdVblendps:
389 : case X86Inst::kIdBlendps:
390 0 : return X86Logging_formatImmShuf(sb, u8, 1, vecSize / 4);
391 :
392 0 : case X86Inst::kIdVcmppd:
393 : case X86Inst::kIdVcmpps:
394 : case X86Inst::kIdVcmpsd:
395 : case X86Inst::kIdVcmpss:
396 0 : return X86Logging_formatImmText(sb, u8, 5, 0, vcmpx);
397 :
398 0 : case X86Inst::kIdCmppd:
399 : case X86Inst::kIdCmpps:
400 : case X86Inst::kIdCmpsd:
401 : case X86Inst::kIdCmpss:
402 0 : return X86Logging_formatImmText(sb, u8, 3, 0, vcmpx);
403 :
404 0 : case X86Inst::kIdVdbpsadbw:
405 0 : return X86Logging_formatImmShuf(sb, u8, 2, 4);
406 :
407 0 : case X86Inst::kIdVdppd:
408 : case X86Inst::kIdVdpps:
409 : case X86Inst::kIdDppd:
410 : case X86Inst::kIdDpps:
411 0 : return X86Logging_formatImmShuf(sb, u8, 1, 8);
412 :
413 0 : case X86Inst::kIdVmpsadbw:
414 : case X86Inst::kIdMpsadbw:
415 0 : return X86Logging_formatImmBits(sb, u8, vmpsadbw, std::min<uint32_t>(vecSize / 8, 4));
416 :
417 0 : case X86Inst::kIdVpblendw:
418 : case X86Inst::kIdPblendw:
419 0 : return X86Logging_formatImmShuf(sb, u8, 1, 8);
420 :
421 0 : case X86Inst::kIdVpblendd:
422 0 : return X86Logging_formatImmShuf(sb, u8, 1, std::min<uint32_t>(vecSize / 4, 8));
423 :
424 0 : case X86Inst::kIdVpclmulqdq:
425 : case X86Inst::kIdPclmulqdq:
426 0 : return X86Logging_formatImmBits(sb, u8, vpclmulqdq, ASMJIT_ARRAY_SIZE(vpclmulqdq));
427 :
428 0 : case X86Inst::kIdVroundpd:
429 : case X86Inst::kIdVroundps:
430 : case X86Inst::kIdVroundsd:
431 : case X86Inst::kIdVroundss:
432 : case X86Inst::kIdRoundpd:
433 : case X86Inst::kIdRoundps:
434 : case X86Inst::kIdRoundsd:
435 : case X86Inst::kIdRoundss:
436 0 : return X86Logging_formatImmBits(sb, u8, vroundxx, ASMJIT_ARRAY_SIZE(vroundxx));
437 :
438 0 : case X86Inst::kIdVshufpd:
439 : case X86Inst::kIdShufpd:
440 0 : return X86Logging_formatImmText(sb, u8, 1, 2, vshufpd, std::min<uint32_t>(vecSize / 8, 8));
441 :
442 0 : case X86Inst::kIdVshufps:
443 : case X86Inst::kIdShufps:
444 0 : return X86Logging_formatImmText(sb, u8, 2, 4, vshufps, 4);
445 :
446 0 : case X86Inst::kIdVcvtps2ph:
447 0 : return X86Logging_formatImmBits(sb, u8, vroundxx, 1);
448 :
449 0 : case X86Inst::kIdVperm2f128:
450 : case X86Inst::kIdVperm2i128:
451 0 : return X86Logging_formatImmBits(sb, u8, vperm2x128, ASMJIT_ARRAY_SIZE(vperm2x128));
452 :
453 0 : case X86Inst::kIdVpermilpd:
454 0 : return X86Logging_formatImmShuf(sb, u8, 1, vecSize / 8);
455 :
456 0 : case X86Inst::kIdVpermilps:
457 0 : return X86Logging_formatImmShuf(sb, u8, 2, 4);
458 :
459 0 : case X86Inst::kIdVpshufd:
460 : case X86Inst::kIdPshufd:
461 0 : return X86Logging_formatImmShuf(sb, u8, 2, 4);
462 :
463 0 : case X86Inst::kIdVpshufhw:
464 : case X86Inst::kIdVpshuflw:
465 : case X86Inst::kIdPshufhw:
466 : case X86Inst::kIdPshuflw:
467 : case X86Inst::kIdPshufw:
468 0 : return X86Logging_formatImmShuf(sb, u8, 2, 4);
469 :
470 : // TODO: Maybe?
471 : case X86Inst::kIdVfixupimmpd:
472 : case X86Inst::kIdVfixupimmps:
473 : case X86Inst::kIdVfixupimmsd:
474 : case X86Inst::kIdVfixupimmss:
475 : return kErrorOk;
476 :
477 0 : case X86Inst::kIdVfpclasspd:
478 : case X86Inst::kIdVfpclassps:
479 : case X86Inst::kIdVfpclasssd:
480 : case X86Inst::kIdVfpclassss:
481 0 : return X86Logging_formatImmBits(sb, u8, vfpclassxx, ASMJIT_ARRAY_SIZE(vfpclassxx));
482 :
483 0 : case X86Inst::kIdVgetmantpd:
484 : case X86Inst::kIdVgetmantps:
485 : case X86Inst::kIdVgetmantsd:
486 : case X86Inst::kIdVgetmantss:
487 0 : return X86Logging_formatImmBits(sb, u8, vgetmantxx, ASMJIT_ARRAY_SIZE(vgetmantxx));
488 :
489 0 : case X86Inst::kIdVpcmpb:
490 : case X86Inst::kIdVpcmpd:
491 : case X86Inst::kIdVpcmpq:
492 : case X86Inst::kIdVpcmpw:
493 : case X86Inst::kIdVpcmpub:
494 : case X86Inst::kIdVpcmpud:
495 : case X86Inst::kIdVpcmpuq:
496 : case X86Inst::kIdVpcmpuw:
497 0 : return X86Logging_formatImmText(sb, u8, 2, 4, vpcmpx, 4);
498 :
499 0 : case X86Inst::kIdVpcomb:
500 : case X86Inst::kIdVpcomd:
501 : case X86Inst::kIdVpcomq:
502 : case X86Inst::kIdVpcomw:
503 : case X86Inst::kIdVpcomub:
504 : case X86Inst::kIdVpcomud:
505 : case X86Inst::kIdVpcomuq:
506 : case X86Inst::kIdVpcomuw:
507 0 : return X86Logging_formatImmText(sb, u8, 2, 4, vpcomx, 4);
508 :
509 0 : case X86Inst::kIdVpermq:
510 : case X86Inst::kIdVpermpd:
511 0 : return X86Logging_formatImmShuf(sb, u8, 2, 4);
512 :
513 0 : case X86Inst::kIdVpternlogd:
514 : case X86Inst::kIdVpternlogq:
515 0 : return X86Logging_formatImmShuf(sb, u8, 1, 8);
516 :
517 0 : case X86Inst::kIdVrangepd:
518 : case X86Inst::kIdVrangeps:
519 : case X86Inst::kIdVrangesd:
520 : case X86Inst::kIdVrangess:
521 0 : return X86Logging_formatImmBits(sb, u8, vrangexx, ASMJIT_ARRAY_SIZE(vrangexx));
522 :
523 0 : case X86Inst::kIdVreducepd:
524 : case X86Inst::kIdVreduceps:
525 : case X86Inst::kIdVreducesd:
526 : case X86Inst::kIdVreducess:
527 : case X86Inst::kIdVrndscalepd:
528 : case X86Inst::kIdVrndscaleps:
529 : case X86Inst::kIdVrndscalesd:
530 : case X86Inst::kIdVrndscaless:
531 0 : return X86Logging_formatImmBits(sb, u8, vreducexx_vrndscalexx, ASMJIT_ARRAY_SIZE(vreducexx_vrndscalexx));
532 :
533 0 : case X86Inst::kIdVshuff32x4:
534 : case X86Inst::kIdVshuff64x2:
535 : case X86Inst::kIdVshufi32x4:
536 : case X86Inst::kIdVshufi64x2: {
537 0 : uint32_t count = std::max<uint32_t>(vecSize / 16, 2);
538 0 : uint32_t bits = count <= 2 ? 1 : 2;
539 0 : return X86Logging_formatImmShuf(sb, u8, bits, count);
540 : }
541 :
542 : default:
543 : return kErrorOk;
544 : }
545 : }
546 :
547 : // ============================================================================
548 : // [asmjit::X86Logging - Format Register]
549 : // ============================================================================
550 :
551 0 : ASMJIT_FAVOR_SIZE Error X86Logging::formatRegister(
552 : StringBuilder& sb,
553 : uint32_t logOptions,
554 : const CodeEmitter* emitter,
555 : uint32_t archType,
556 : uint32_t rType,
557 : uint32_t rId) noexcept {
558 :
559 : ASMJIT_UNUSED(logOptions);
560 : ASMJIT_UNUSED(archType);
561 :
562 0 : if (Operand::isPackedId(rId)) {
563 : #if !defined(ASMJIT_DISABLE_COMPILER)
564 0 : if (emitter && emitter->getType() == CodeEmitter::kTypeCompiler) {
565 : const CodeCompiler* cc = static_cast<const CodeCompiler*>(emitter);
566 :
567 0 : if (cc->isVirtRegValid(rId)) {
568 : VirtReg* vReg = cc->getVirtRegById(rId);
569 : ASMJIT_ASSERT(vReg != nullptr);
570 :
571 : const char* name = vReg->getName();
572 0 : if (name && name[0] != '\0')
573 0 : return sb.appendString(name);
574 : else
575 0 : return sb.appendFormat("v%u", static_cast<unsigned int>(Operand::unpackId(rId)));
576 : }
577 : }
578 : #endif // !ASMJIT_DISABLE_COMPILER
579 :
580 0 : return sb.appendFormat("VirtReg<Type=%u Id=%u>", rType, rId);
581 : }
582 : else {
583 0 : if (rType < ASMJIT_ARRAY_SIZE(x86RegFormatInfo)) {
584 : const X86RegFormatInfo& rfi = x86RegFormatInfo[rType];
585 :
586 0 : if (rId < rfi.specialCount)
587 0 : return sb.appendString(x86RegFormatStrings + rfi.specialIndex + rId * 4);
588 :
589 0 : if (rId < rfi.count)
590 0 : return sb.appendFormat(x86RegFormatStrings + rfi.formatIndex, static_cast<unsigned int>(rId));
591 : }
592 :
593 0 : return sb.appendFormat("PhysReg<Type=%u Id=%u>", rType, rId);
594 : }
595 : }
596 :
597 : // ============================================================================
598 : // [asmjit::X86Logging - Format Instruction]
599 : // ============================================================================
600 :
601 0 : ASMJIT_FAVOR_SIZE Error X86Logging::formatInstruction(
602 : StringBuilder& sb,
603 : uint32_t logOptions,
604 : const CodeEmitter* emitter,
605 : uint32_t archType,
606 : const Inst::Detail& detail, const Operand_* opArray, uint32_t opCount) noexcept {
607 :
608 0 : uint32_t instId = detail.instId;
609 0 : uint32_t options = detail.options;
610 :
611 : // Format instruction options and instruction mnemonic.
612 0 : if (instId < X86Inst::_kIdCount) {
613 : const X86Inst& instInfo = X86Inst::getInst(instId);
614 :
615 : // SHORT|LONG options.
616 0 : if (options & X86Inst::kOptionShortForm) ASMJIT_PROPAGATE(sb.appendString("short "));
617 0 : if (options & X86Inst::kOptionLongForm) ASMJIT_PROPAGATE(sb.appendString("long "));
618 :
619 : // LOCK|XACQUIRE|XRELEASE options.
620 0 : if (options & X86Inst::kOptionXAcquire) ASMJIT_PROPAGATE(sb.appendString("xacquire "));
621 0 : if (options & X86Inst::kOptionXRelease) ASMJIT_PROPAGATE(sb.appendString("xrelease "));
622 0 : if (options & X86Inst::kOptionLock) ASMJIT_PROPAGATE(sb.appendString("lock "));
623 :
624 : // REP|REPNZ options.
625 0 : if (options & (X86Inst::kOptionRep | X86Inst::kOptionRepnz)) {
626 0 : sb.appendString((options & X86Inst::kOptionRep) ? "rep " : "repnz ");
627 0 : if (detail.hasExtraReg()) {
628 0 : ASMJIT_PROPAGATE(sb.appendChar('{'));
629 0 : ASMJIT_PROPAGATE(formatOperand(sb, logOptions, emitter, archType, detail.extraReg.toReg<Reg>()));
630 0 : ASMJIT_PROPAGATE(sb.appendString("} "));
631 : }
632 : }
633 :
634 : // REX options.
635 0 : if (options & X86Inst::kOptionRex) {
636 : const uint32_t kRXBWMask = X86Inst::kOptionOpCodeR |
637 : X86Inst::kOptionOpCodeX |
638 : X86Inst::kOptionOpCodeB |
639 : X86Inst::kOptionOpCodeW ;
640 0 : if (options & kRXBWMask) {
641 : sb.appendString("rex.");
642 0 : if (options & X86Inst::kOptionOpCodeR) sb.appendChar('r');
643 0 : if (options & X86Inst::kOptionOpCodeX) sb.appendChar('x');
644 0 : if (options & X86Inst::kOptionOpCodeB) sb.appendChar('b');
645 0 : if (options & X86Inst::kOptionOpCodeW) sb.appendChar('w');
646 : sb.appendChar(' ');
647 : }
648 : else {
649 0 : ASMJIT_PROPAGATE(sb.appendString("rex "));
650 : }
651 : }
652 :
653 : // VEX|EVEX options.
654 0 : if (options & X86Inst::kOptionVex3) ASMJIT_PROPAGATE(sb.appendString("vex3 "));
655 0 : if (options & X86Inst::kOptionEvex) ASMJIT_PROPAGATE(sb.appendString("evex "));
656 :
657 0 : ASMJIT_PROPAGATE(sb.appendString(instInfo.getName()));
658 : }
659 : else {
660 0 : ASMJIT_PROPAGATE(sb.appendFormat("<unknown id=#%u>", static_cast<unsigned int>(instId)));
661 : }
662 :
663 0 : for (uint32_t i = 0; i < opCount; i++) {
664 0 : const Operand_& op = opArray[i];
665 0 : if (op.isNone()) break;
666 :
667 0 : ASMJIT_PROPAGATE(sb.appendString(i == 0 ? " " : ", "));
668 0 : ASMJIT_PROPAGATE(formatOperand(sb, logOptions, emitter, archType, op));
669 :
670 0 : if (op.isImm() && (logOptions & Logger::kOptionImmExtended)) {
671 0 : uint32_t vecSize = 16;
672 0 : for (uint32_t j = 0; j < opCount; j++)
673 0 : if (opArray[j].isReg())
674 0 : vecSize = std::max<uint32_t>(vecSize, opArray[j].getSize());
675 0 : ASMJIT_PROPAGATE(X86Logging_formatImmExtended(sb, logOptions, instId, vecSize, op.as<Imm>()));
676 : }
677 :
678 : // Support AVX-512 {k}{z}.
679 0 : if (i == 0) {
680 0 : if (detail.extraReg.getKind() == X86Reg::kKindK) {
681 0 : ASMJIT_PROPAGATE(sb.appendString(" {"));
682 0 : ASMJIT_PROPAGATE(formatOperand(sb, logOptions, emitter, archType, detail.extraReg.toReg<Reg>()));
683 0 : ASMJIT_PROPAGATE(sb.appendChar('}'));
684 :
685 0 : if (options & X86Inst::kOptionZMask)
686 0 : ASMJIT_PROPAGATE(sb.appendString("{z}"));
687 : }
688 0 : else if (options & X86Inst::kOptionZMask) {
689 0 : ASMJIT_PROPAGATE(sb.appendString(" {z}"));
690 : }
691 : }
692 :
693 : // Support AVX-512 {1tox}.
694 0 : if (op.isMem() && (options & X86Inst::kOption1ToX))
695 0 : ASMJIT_PROPAGATE(sb.appendString(" {1tox}"));
696 : }
697 :
698 : return kErrorOk;
699 : }
700 :
701 : } // asmjit namespace
702 : } // namespace PLMD
703 :
704 : // [Api-End]
705 : #include "./asmjit_apiend.h"
706 :
707 : // [Guard]
708 : #endif // !ASMJIT_DISABLE_LOGGING
709 : #pragma GCC diagnostic pop
710 : #endif // __PLUMED_HAS_ASMJIT
|