Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/zydis/src/FormatterBase.c
4211 views
1
/***************************************************************************************************
2
3
Zyan Disassembler Library (Zydis)
4
5
Original Author : Florian Bernd, Joel Hoener
6
7
* Permission is hereby granted, free of charge, to any person obtaining a copy
8
* of this software and associated documentation files (the "Software"), to deal
9
* in the Software without restriction, including without limitation the rights
10
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
* copies of the Software, and to permit persons to whom the Software is
12
* furnished to do so, subject to the following conditions:
13
*
14
* The above copyright notice and this permission notice shall be included in all
15
* copies or substantial portions of the Software.
16
*
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
* SOFTWARE.
24
25
***************************************************************************************************/
26
27
#include <Zydis/Internal/FormatterBase.h>
28
#include <Zydis/Utils.h>
29
30
/* ============================================================================================== */
31
/* Constants */
32
/* ============================================================================================== */
33
34
#include <Generated/FormatterStrings.inc>
35
36
static const ZydisShortString* const STR_PREF_REX[16] =
37
{
38
&STR_PREF_REX_40,
39
&STR_PREF_REX_41,
40
&STR_PREF_REX_42,
41
&STR_PREF_REX_43,
42
&STR_PREF_REX_44,
43
&STR_PREF_REX_45,
44
&STR_PREF_REX_46,
45
&STR_PREF_REX_47,
46
&STR_PREF_REX_48,
47
&STR_PREF_REX_49,
48
&STR_PREF_REX_4A,
49
&STR_PREF_REX_4B,
50
&STR_PREF_REX_4C,
51
&STR_PREF_REX_4D,
52
&STR_PREF_REX_4E,
53
&STR_PREF_REX_4F
54
};
55
56
static const ZydisPredefinedToken* const TOK_PREF_REX[16] =
57
{
58
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_40,
59
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_41,
60
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_42,
61
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_43,
62
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_44,
63
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_45,
64
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_46,
65
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_47,
66
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_48,
67
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_49,
68
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_4A,
69
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_4B,
70
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_4C,
71
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_4D,
72
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_4E,
73
(const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_4F
74
};
75
76
/* ============================================================================================== */
77
/* Helper functions */
78
/* ============================================================================================== */
79
80
ZyanU32 ZydisFormatterHelperGetExplicitSize(const ZydisFormatter* formatter,
81
ZydisFormatterContext* context, const ZydisDecodedOperand* operand)
82
{
83
ZYAN_ASSERT(formatter);
84
ZYAN_ASSERT(context);
85
ZYAN_ASSERT(operand);
86
87
ZYAN_ASSERT(operand->type == ZYDIS_OPERAND_TYPE_MEMORY);
88
ZYAN_ASSERT((operand->mem.type == ZYDIS_MEMOP_TYPE_MEM) ||
89
(operand->mem.type == ZYDIS_MEMOP_TYPE_VSIB));
90
91
if (formatter->force_memory_size)
92
{
93
return operand->size;
94
}
95
96
if (!context->operands)
97
{
98
// Single operand formatting. We can not derive the explicit size by using the other
99
// operands.
100
return 0;
101
}
102
103
switch (operand->id)
104
{
105
case 0:
106
if (context->instruction->operand_count_visible < 2)
107
{
108
return 0;
109
}
110
if ((context->operands[1].type == ZYDIS_OPERAND_TYPE_UNUSED) ||
111
(context->operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE))
112
{
113
return context->operands[0].size;
114
}
115
if (context->operands[0].size != context->operands[1].size)
116
{
117
return context->operands[0].size;
118
}
119
if ((context->operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER) &&
120
(context->operands[1].visibility == ZYDIS_OPERAND_VISIBILITY_IMPLICIT) &&
121
(context->operands[1].reg.value == ZYDIS_REGISTER_CL))
122
{
123
return context->operands[0].size;
124
}
125
break;
126
case 1:
127
case 2:
128
if (context->operands[operand->id - 1].size !=
129
context->operands[operand->id].size)
130
{
131
return context->operands[operand->id].size;
132
}
133
break;
134
default:
135
break;
136
}
137
138
return 0;
139
}
140
141
/* ============================================================================================== */
142
/* Formatter functions */
143
/* ============================================================================================== */
144
145
/* ---------------------------------------------------------------------------------------------- */
146
/* Operands */
147
/* ---------------------------------------------------------------------------------------------- */
148
149
ZyanStatus ZydisFormatterBaseFormatOperandREG(const ZydisFormatter* formatter,
150
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
151
{
152
ZYAN_ASSERT(formatter);
153
ZYAN_ASSERT(buffer);
154
ZYAN_ASSERT(context);
155
156
return formatter->func_print_register(formatter, buffer, context, context->operand->reg.value);
157
}
158
159
ZyanStatus ZydisFormatterBaseFormatOperandPTR(const ZydisFormatter* formatter,
160
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
161
{
162
ZYAN_ASSERT(formatter);
163
ZYAN_ASSERT(buffer);
164
ZYAN_ASSERT(context);
165
166
ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE);
167
ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string,
168
context->operand->ptr.segment, 4, formatter->hex_force_leading_number);
169
ZYDIS_BUFFER_APPEND(buffer, DELIM_SEGMENT);
170
171
ZyanU8 padding;
172
switch (context->instruction->operand_width)
173
{
174
case 16:
175
padding = 4;
176
break;
177
case 32:
178
padding = 8;
179
break;
180
default:
181
return ZYAN_STATUS_INVALID_ARGUMENT;
182
}
183
184
ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE);
185
ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string,
186
context->operand->ptr.offset , padding, formatter->hex_force_leading_number);
187
188
return ZYAN_STATUS_SUCCESS;
189
}
190
191
ZyanStatus ZydisFormatterBaseFormatOperandIMM(const ZydisFormatter* formatter,
192
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
193
{
194
ZYAN_ASSERT(formatter);
195
ZYAN_ASSERT(buffer);
196
ZYAN_ASSERT(context);
197
198
// The immediate operand contains an address
199
if (context->operand->imm.is_relative)
200
{
201
const ZyanBool absolute = !formatter->force_relative_branches &&
202
(context->runtime_address != ZYDIS_RUNTIME_ADDRESS_NONE);
203
if (absolute)
204
{
205
return formatter->func_print_address_abs(formatter, buffer, context);
206
}
207
return formatter->func_print_address_rel(formatter, buffer, context);
208
}
209
210
// The immediate operand contains an actual ordinal value
211
return formatter->func_print_imm(formatter, buffer, context);
212
}
213
214
/* ---------------------------------------------------------------------------------------------- */
215
/* Elemental tokens */
216
/* ---------------------------------------------------------------------------------------------- */
217
218
ZyanStatus ZydisFormatterBasePrintAddressABS(const ZydisFormatter* formatter,
219
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
220
{
221
ZYAN_ASSERT(formatter);
222
ZYAN_ASSERT(buffer);
223
ZYAN_ASSERT(context);
224
225
ZyanU64 address;
226
ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand,
227
context->runtime_address, &address));
228
ZyanU8 padding = (formatter->addr_padding_absolute ==
229
ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->addr_padding_absolute;
230
if ((formatter->addr_padding_absolute == ZYDIS_PADDING_AUTO) &&
231
(formatter->addr_base == ZYDIS_NUMERIC_BASE_HEX))
232
{
233
switch (context->instruction->stack_width)
234
{
235
case 16:
236
padding = 4;
237
address = (ZyanU16)address;
238
break;
239
case 32:
240
padding = 8;
241
address = (ZyanU32)address;
242
break;
243
case 64:
244
padding = 16;
245
break;
246
default:
247
return ZYAN_STATUS_INVALID_ARGUMENT;
248
}
249
}
250
251
ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_ADDRESS_ABS);
252
ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string, address, padding,
253
formatter->hex_force_leading_number);
254
255
return ZYAN_STATUS_SUCCESS;
256
}
257
258
ZyanStatus ZydisFormatterBasePrintAddressREL(const ZydisFormatter* formatter,
259
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
260
{
261
ZYAN_ASSERT(formatter);
262
ZYAN_ASSERT(buffer);
263
ZYAN_ASSERT(context);
264
265
ZyanU64 address;
266
ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand, 0, &address));
267
268
ZyanU8 padding = (formatter->addr_padding_relative ==
269
ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->addr_padding_relative;
270
if ((formatter->addr_padding_relative == ZYDIS_PADDING_AUTO) &&
271
(formatter->addr_base == ZYDIS_NUMERIC_BASE_HEX))
272
{
273
switch (context->instruction->stack_width)
274
{
275
case 16:
276
padding = 4;
277
address = (ZyanU16)address;
278
break;
279
case 32:
280
padding = 8;
281
address = (ZyanU32)address;
282
break;
283
case 64:
284
padding = 16;
285
break;
286
default:
287
return ZYAN_STATUS_INVALID_ARGUMENT;
288
}
289
}
290
291
ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_ADDRESS_REL);
292
switch (formatter->addr_signedness)
293
{
294
case ZYDIS_SIGNEDNESS_AUTO:
295
case ZYDIS_SIGNEDNESS_SIGNED:
296
ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->addr_base, &buffer->string, address,
297
padding, formatter->hex_force_leading_number, ZYAN_TRUE);
298
break;
299
case ZYDIS_SIGNEDNESS_UNSIGNED:
300
ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_ADD));
301
ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string, address,
302
padding, formatter->hex_force_leading_number);
303
break;
304
default:
305
return ZYAN_STATUS_INVALID_ARGUMENT;
306
}
307
308
return ZYAN_STATUS_SUCCESS;
309
}
310
311
ZyanStatus ZydisFormatterBasePrintIMM(const ZydisFormatter* formatter,
312
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
313
{
314
ZYAN_ASSERT(formatter);
315
ZYAN_ASSERT(buffer);
316
ZYAN_ASSERT(context);
317
318
ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE);
319
320
const ZyanBool is_signed =
321
(formatter->imm_signedness == ZYDIS_SIGNEDNESS_SIGNED) ||
322
(formatter->imm_signedness == ZYDIS_SIGNEDNESS_AUTO && (context->operand->imm.is_signed));
323
if (is_signed && (context->operand->imm.value.s < 0))
324
{
325
ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->imm_base, &buffer->string,
326
context->operand->imm.value.s, formatter->imm_padding,
327
formatter->hex_force_leading_number, ZYAN_FALSE);
328
return ZYAN_STATUS_SUCCESS;
329
}
330
ZyanU64 value;
331
ZyanU8 padding = (formatter->imm_padding ==
332
ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->imm_padding;
333
switch (context->instruction->operand_width)
334
{
335
case 8:
336
if (formatter->imm_padding == ZYDIS_PADDING_AUTO)
337
{
338
padding = 2;
339
}
340
value = (ZyanU8 )context->operand->imm.value.u;
341
break;
342
case 16:
343
if (formatter->imm_padding == ZYDIS_PADDING_AUTO)
344
{
345
padding = 4;
346
}
347
value = (ZyanU16)context->operand->imm.value.u;
348
break;
349
case 32:
350
if (formatter->imm_padding == ZYDIS_PADDING_AUTO)
351
{
352
padding = 8;
353
}
354
value = (ZyanU32)context->operand->imm.value.u;
355
break;
356
case 64:
357
if (formatter->imm_padding == ZYDIS_PADDING_AUTO)
358
{
359
padding = 16;
360
}
361
value = (ZyanU64)context->operand->imm.value.u;
362
break;
363
default:
364
return ZYAN_STATUS_INVALID_ARGUMENT;
365
}
366
ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->imm_base, &buffer->string, value, padding,
367
formatter->hex_force_leading_number);
368
369
return ZYAN_STATUS_SUCCESS;
370
}
371
372
/* ---------------------------------------------------------------------------------------------- */
373
/* Optional tokens */
374
/* ---------------------------------------------------------------------------------------------- */
375
376
ZyanStatus ZydisFormatterBasePrintSegment(const ZydisFormatter* formatter,
377
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
378
{
379
ZYAN_ASSERT(formatter);
380
ZYAN_ASSERT(buffer);
381
ZYAN_ASSERT(context);
382
383
ZyanBool printed_segment = ZYAN_FALSE;
384
switch (context->operand->mem.segment)
385
{
386
case ZYDIS_REGISTER_ES:
387
case ZYDIS_REGISTER_CS:
388
case ZYDIS_REGISTER_FS:
389
case ZYDIS_REGISTER_GS:
390
ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
391
context->operand->mem.segment));
392
printed_segment = ZYAN_TRUE;
393
break;
394
case ZYDIS_REGISTER_SS:
395
if ((formatter->force_memory_segment) ||
396
(context->instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_SS))
397
{
398
ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
399
context->operand->mem.segment));
400
printed_segment = ZYAN_TRUE;
401
}
402
break;
403
case ZYDIS_REGISTER_DS:
404
if ((formatter->force_memory_segment) ||
405
(context->instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_DS))
406
{
407
ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
408
context->operand->mem.segment));
409
printed_segment = ZYAN_TRUE;
410
}
411
break;
412
default:
413
break;
414
}
415
if (printed_segment)
416
{
417
ZYDIS_BUFFER_APPEND(buffer, DELIM_SEGMENT);
418
}
419
420
return ZYAN_STATUS_SUCCESS;
421
}
422
423
ZyanStatus ZydisFormatterBasePrintPrefixes(const ZydisFormatter* formatter,
424
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
425
{
426
ZYAN_ASSERT(formatter);
427
ZYAN_ASSERT(buffer);
428
ZYAN_ASSERT(context);
429
430
if (formatter->detailed_prefixes)
431
{
432
for (ZyanU8 i = 0; i < context->instruction->raw.prefix_count; ++i)
433
{
434
const ZyanU8 value = context->instruction->raw.prefixes[i].value;
435
switch (context->instruction->raw.prefixes[i].type)
436
{
437
case ZYDIS_PREFIX_TYPE_IGNORED:
438
case ZYDIS_PREFIX_TYPE_MANDATORY:
439
{
440
if ((value & 0xF0) == 0x40)
441
{
442
if (buffer->is_token_list)
443
{
444
// TODO: Case
445
ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer,
446
TOK_PREF_REX[value & 0x0F]));
447
} else
448
{
449
ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string,
450
STR_PREF_REX[value & 0x0F], formatter->case_prefixes));
451
}
452
} else
453
{
454
switch (value)
455
{
456
case 0xF0:
457
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_LOCK, formatter->case_prefixes);
458
break;
459
case 0x2E:
460
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_CS, formatter->case_prefixes);
461
break;
462
case 0x36:
463
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_SS, formatter->case_prefixes);
464
break;
465
case 0x3E:
466
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_DS, formatter->case_prefixes);
467
break;
468
case 0x26:
469
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_ES, formatter->case_prefixes);
470
break;
471
case 0x64:
472
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_FS, formatter->case_prefixes);
473
break;
474
case 0x65:
475
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_GS, formatter->case_prefixes);
476
break;
477
default:
478
ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_PREFIX);
479
ZYAN_CHECK(ZydisStringAppendHexU(&buffer->string, value, 0,
480
formatter->hex_force_leading_number, formatter->hex_uppercase,
481
ZYAN_NULL, ZYAN_NULL));
482
ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_WHITESPACE);
483
ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_WHITESPACE));
484
break;
485
}
486
}
487
break;
488
}
489
case ZYDIS_PREFIX_TYPE_EFFECTIVE:
490
switch (value)
491
{
492
case 0xF0:
493
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_LOCK, formatter->case_prefixes);
494
break;
495
case 0xF2:
496
if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XACQUIRE)
497
{
498
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XACQUIRE, formatter->case_prefixes);
499
}
500
if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPNE)
501
{
502
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPNE, formatter->case_prefixes);
503
}
504
505
if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_BND)
506
{
507
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_BND, formatter->case_prefixes);
508
}
509
break;
510
case 0xF3:
511
if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XRELEASE)
512
{
513
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XRELEASE, formatter->case_prefixes);
514
}
515
if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REP)
516
{
517
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REP, formatter->case_prefixes);
518
}
519
if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPE)
520
{
521
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPE, formatter->case_prefixes);
522
}
523
break;
524
default:
525
break;
526
}
527
break;
528
default:
529
return ZYAN_STATUS_INVALID_ARGUMENT;
530
}
531
}
532
return ZYAN_STATUS_SUCCESS;
533
}
534
535
if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XACQUIRE)
536
{
537
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XACQUIRE, formatter->case_prefixes);
538
}
539
if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XRELEASE)
540
{
541
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XRELEASE, formatter->case_prefixes);
542
}
543
544
if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_LOCK)
545
{
546
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_LOCK, formatter->case_prefixes);
547
}
548
549
if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_BND)
550
{
551
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_BND, formatter->case_prefixes);
552
}
553
554
if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_NOTRACK)
555
{
556
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_NOTRACK, formatter->case_prefixes);
557
}
558
559
if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REP)
560
{
561
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REP, formatter->case_prefixes);
562
return ZYAN_STATUS_SUCCESS;
563
}
564
if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPE)
565
{
566
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPE, formatter->case_prefixes);
567
return ZYAN_STATUS_SUCCESS;
568
}
569
if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPNE)
570
{
571
ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPNE, formatter->case_prefixes);
572
return ZYAN_STATUS_SUCCESS;
573
}
574
575
return ZYAN_STATUS_SUCCESS;
576
}
577
578
ZyanStatus ZydisFormatterBasePrintDecorator(const ZydisFormatter* formatter,
579
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisDecorator decorator)
580
{
581
ZYAN_ASSERT(formatter);
582
ZYAN_ASSERT(buffer);
583
ZYAN_ASSERT(context);
584
585
#if defined(ZYDIS_DISABLE_AVX512) && defined(ZYDIS_DISABLE_KNC)
586
ZYAN_UNUSED(formatter);
587
ZYAN_UNUSED(buffer);
588
ZYAN_UNUSED(context);
589
#endif
590
591
switch (decorator)
592
{
593
case ZYDIS_DECORATOR_MASK:
594
{
595
#if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
596
if (context->instruction->avx.mask.reg != ZYDIS_REGISTER_K0)
597
{
598
if (buffer->is_token_list)
599
{
600
ZYDIS_BUFFER_APPEND(buffer, DECO_BEGIN);
601
ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
602
context->instruction->avx.mask.reg));
603
ZYDIS_BUFFER_APPEND(buffer, DECO_END);
604
} else
605
{
606
ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_DECO_BEGIN));
607
ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
608
context->instruction->avx.mask.reg));
609
ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_DECO_END));
610
}
611
612
// Only print the zeroing decorator, if the instruction is not a "zeroing masking only"
613
// instruction (e.g. `vcmpsd`)
614
if ((context->instruction->avx.mask.mode == ZYDIS_MASK_MODE_ZEROING ||
615
context->instruction->avx.mask.mode == ZYDIS_MASK_MODE_CONTROL_ZEROING) &&
616
(context->instruction->raw.evex.z))
617
{
618
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_ZERO, formatter->case_decorators);
619
}
620
}
621
#endif
622
break;
623
}
624
case ZYDIS_DECORATOR_BC:
625
#if !defined(ZYDIS_DISABLE_AVX512)
626
if (!context->instruction->avx.broadcast.is_static)
627
{
628
switch (context->instruction->avx.broadcast.mode)
629
{
630
case ZYDIS_BROADCAST_MODE_INVALID:
631
break;
632
case ZYDIS_BROADCAST_MODE_1_TO_2:
633
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO2, formatter->case_decorators);
634
break;
635
case ZYDIS_BROADCAST_MODE_1_TO_4:
636
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO4, formatter->case_decorators);
637
break;
638
case ZYDIS_BROADCAST_MODE_1_TO_8:
639
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO8, formatter->case_decorators);
640
break;
641
case ZYDIS_BROADCAST_MODE_1_TO_16:
642
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO16, formatter->case_decorators);
643
break;
644
case ZYDIS_BROADCAST_MODE_1_TO_32:
645
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO32, formatter->case_decorators);
646
break;
647
case ZYDIS_BROADCAST_MODE_1_TO_64:
648
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO64, formatter->case_decorators);
649
break;
650
case ZYDIS_BROADCAST_MODE_4_TO_8:
651
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_4TO8, formatter->case_decorators);
652
break;
653
case ZYDIS_BROADCAST_MODE_4_TO_16:
654
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_4TO16, formatter->case_decorators);
655
break;
656
case ZYDIS_BROADCAST_MODE_8_TO_16:
657
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_8TO16, formatter->case_decorators);
658
break;
659
default:
660
return ZYAN_STATUS_INVALID_ARGUMENT;
661
}
662
}
663
#endif
664
break;
665
case ZYDIS_DECORATOR_RC:
666
#if !defined(ZYDIS_DISABLE_AVX512)
667
if (context->instruction->avx.has_sae)
668
{
669
switch (context->instruction->avx.rounding.mode)
670
{
671
case ZYDIS_ROUNDING_MODE_INVALID:
672
break;
673
case ZYDIS_ROUNDING_MODE_RN:
674
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RN_SAE, formatter->case_decorators);
675
break;
676
case ZYDIS_ROUNDING_MODE_RD:
677
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RD_SAE, formatter->case_decorators);
678
break;
679
case ZYDIS_ROUNDING_MODE_RU:
680
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RU_SAE, formatter->case_decorators);
681
break;
682
case ZYDIS_ROUNDING_MODE_RZ:
683
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RZ_SAE, formatter->case_decorators);
684
break;
685
default:
686
return ZYAN_STATUS_INVALID_ARGUMENT;
687
}
688
} else
689
{
690
switch (context->instruction->avx.rounding.mode)
691
{
692
case ZYDIS_ROUNDING_MODE_INVALID:
693
break;
694
case ZYDIS_ROUNDING_MODE_RN:
695
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RN, formatter->case_decorators);
696
break;
697
case ZYDIS_ROUNDING_MODE_RD:
698
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RD, formatter->case_decorators);
699
break;
700
case ZYDIS_ROUNDING_MODE_RU:
701
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RU, formatter->case_decorators);
702
break;
703
case ZYDIS_ROUNDING_MODE_RZ:
704
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RZ, formatter->case_decorators);
705
break;
706
default:
707
return ZYAN_STATUS_INVALID_ARGUMENT;
708
}
709
}
710
#endif
711
break;
712
case ZYDIS_DECORATOR_SAE:
713
#if !defined(ZYDIS_DISABLE_AVX512)
714
if (context->instruction->avx.has_sae && !context->instruction->avx.rounding.mode)
715
{
716
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_SAE, formatter->case_decorators);
717
}
718
#endif
719
break;
720
case ZYDIS_DECORATOR_SWIZZLE:
721
#if !defined(ZYDIS_DISABLE_KNC)
722
switch (context->instruction->avx.swizzle.mode)
723
{
724
case ZYDIS_SWIZZLE_MODE_INVALID:
725
case ZYDIS_SWIZZLE_MODE_DCBA:
726
// Nothing to do here
727
break;
728
case ZYDIS_SWIZZLE_MODE_CDAB:
729
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_CDAB, formatter->case_decorators);
730
break;
731
case ZYDIS_SWIZZLE_MODE_BADC:
732
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_BADC, formatter->case_decorators);
733
break;
734
case ZYDIS_SWIZZLE_MODE_DACB:
735
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_DACB, formatter->case_decorators);
736
break;
737
case ZYDIS_SWIZZLE_MODE_AAAA:
738
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_AAAA, formatter->case_decorators);
739
break;
740
case ZYDIS_SWIZZLE_MODE_BBBB:
741
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_BBBB, formatter->case_decorators);
742
break;
743
case ZYDIS_SWIZZLE_MODE_CCCC:
744
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_CCCC, formatter->case_decorators);
745
break;
746
case ZYDIS_SWIZZLE_MODE_DDDD:
747
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_DDDD, formatter->case_decorators);
748
break;
749
default:
750
return ZYAN_STATUS_INVALID_ARGUMENT;
751
}
752
#endif
753
break;
754
case ZYDIS_DECORATOR_CONVERSION:
755
#if !defined(ZYDIS_DISABLE_KNC)
756
switch (context->instruction->avx.conversion.mode)
757
{
758
case ZYDIS_CONVERSION_MODE_INVALID:
759
break;
760
case ZYDIS_CONVERSION_MODE_FLOAT16:
761
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_FLOAT16, formatter->case_decorators);
762
break;
763
case ZYDIS_CONVERSION_MODE_SINT8:
764
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_SINT8, formatter->case_decorators);
765
break;
766
case ZYDIS_CONVERSION_MODE_UINT8:
767
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_UINT8, formatter->case_decorators);
768
break;
769
case ZYDIS_CONVERSION_MODE_SINT16:
770
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_SINT16, formatter->case_decorators);
771
break;
772
case ZYDIS_CONVERSION_MODE_UINT16:
773
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_UINT16, formatter->case_decorators);
774
break;
775
default:
776
return ZYAN_STATUS_INVALID_ARGUMENT;
777
}
778
#endif
779
break;
780
case ZYDIS_DECORATOR_EH:
781
#if !defined(ZYDIS_DISABLE_KNC)
782
if (context->instruction->avx.has_eviction_hint)
783
{
784
ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_EH, formatter->case_decorators);
785
}
786
#endif
787
break;
788
default:
789
return ZYAN_STATUS_INVALID_ARGUMENT;
790
}
791
792
return ZYAN_STATUS_SUCCESS;
793
}
794
795
/* ---------------------------------------------------------------------------------------------- */
796
797
/* ============================================================================================== */
798
799