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/Zydis/Internal/FormatterBase.h"
28 #include "zydis/Zydis/Utils.h"
29
30 /* ============================================================================================== */
31 /* Constants */
32 /* ============================================================================================== */
33
34 #include "zydis/Zydis/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
ZydisFormatterHelperGetExplicitSize(const ZydisFormatter * formatter,ZydisFormatterContext * context,ZyanU8 memop_id)80 ZyanU32 ZydisFormatterHelperGetExplicitSize(const ZydisFormatter* formatter,
81 ZydisFormatterContext* context, ZyanU8 memop_id)
82 {
83 ZYAN_ASSERT(formatter);
84 ZYAN_ASSERT(context);
85 ZYAN_ASSERT(memop_id < context->instruction->operand_count);
86
87 const ZydisDecodedOperand* const operand = &context->instruction->operands[memop_id];
88 ZYAN_ASSERT(operand->type == ZYDIS_OPERAND_TYPE_MEMORY);
89 ZYAN_ASSERT(operand->mem.type == ZYDIS_MEMOP_TYPE_MEM);
90
91 if (formatter->force_memory_size)
92 {
93 return operand->size;
94 }
95
96 switch (operand->id)
97 {
98 case 0:
99 if ((context->instruction->operands[1].type == ZYDIS_OPERAND_TYPE_UNUSED) ||
100 (context->instruction->operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE))
101 {
102 return context->instruction->operands[0].size;
103 }
104 if (context->instruction->operands[0].size != context->instruction->operands[1].size)
105 {
106 return context->instruction->operands[0].size;
107 }
108 if ((context->instruction->operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER) &&
109 (context->instruction->operands[1].visibility == ZYDIS_OPERAND_VISIBILITY_IMPLICIT) &&
110 (context->instruction->operands[1].reg.value == ZYDIS_REGISTER_CL))
111 {
112 return context->instruction->operands[0].size;
113 }
114 break;
115 case 1:
116 case 2:
117 if (context->instruction->operands[operand->id - 1].size !=
118 context->instruction->operands[operand->id].size)
119 {
120 return context->instruction->operands[operand->id].size;
121 }
122 break;
123 default:
124 break;
125 }
126
127 return 0;
128 }
129
130 /* ============================================================================================== */
131 /* Formatter functions */
132 /* ============================================================================================== */
133
134 /* ---------------------------------------------------------------------------------------------- */
135 /* Operands */
136 /* ---------------------------------------------------------------------------------------------- */
137
ZydisFormatterBaseFormatOperandREG(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context)138 ZyanStatus ZydisFormatterBaseFormatOperandREG(const ZydisFormatter* formatter,
139 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
140 {
141 ZYAN_ASSERT(formatter);
142 ZYAN_ASSERT(buffer);
143 ZYAN_ASSERT(context);
144
145 return formatter->func_print_register(formatter, buffer, context, context->operand->reg.value);
146 }
147
ZydisFormatterBaseFormatOperandPTR(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context)148 ZyanStatus ZydisFormatterBaseFormatOperandPTR(const ZydisFormatter* formatter,
149 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
150 {
151 ZYAN_ASSERT(formatter);
152 ZYAN_ASSERT(buffer);
153 ZYAN_ASSERT(context);
154
155 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE);
156 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string,
157 context->operand->ptr.segment, 4);
158 ZYDIS_BUFFER_APPEND(buffer, DELIM_SEGMENT);
159 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE);
160 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string,
161 context->operand->ptr.offset , 8);
162
163 return ZYAN_STATUS_SUCCESS;
164 }
165
ZydisFormatterBaseFormatOperandIMM(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context)166 ZyanStatus ZydisFormatterBaseFormatOperandIMM(const ZydisFormatter* formatter,
167 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
168 {
169 ZYAN_ASSERT(formatter);
170 ZYAN_ASSERT(buffer);
171 ZYAN_ASSERT(context);
172
173 // The immediate operand contains an address
174 if (context->operand->imm.is_relative)
175 {
176 const ZyanBool absolute = !formatter->force_relative_branches &&
177 (context->runtime_address != ZYDIS_RUNTIME_ADDRESS_NONE);
178 if (absolute)
179 {
180 return formatter->func_print_address_abs(formatter, buffer, context);
181 }
182 return formatter->func_print_address_rel(formatter, buffer, context);
183 }
184
185 // The immediate operand contains an actual ordinal value
186 return formatter->func_print_imm(formatter, buffer, context);
187 }
188
189 /* ---------------------------------------------------------------------------------------------- */
190 /* Elemental tokens */
191 /* ---------------------------------------------------------------------------------------------- */
192
ZydisFormatterBasePrintAddressABS(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context)193 ZyanStatus ZydisFormatterBasePrintAddressABS(const ZydisFormatter* formatter,
194 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
195 {
196 ZYAN_ASSERT(formatter);
197 ZYAN_ASSERT(buffer);
198 ZYAN_ASSERT(context);
199
200 ZyanU64 address;
201 ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand,
202 context->runtime_address, &address));
203 ZyanU8 padding = (formatter->addr_padding_absolute ==
204 ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->addr_padding_absolute;
205 if ((formatter->addr_padding_absolute == ZYDIS_PADDING_AUTO) &&
206 (formatter->addr_base == ZYDIS_NUMERIC_BASE_HEX))
207 {
208 switch (context->instruction->stack_width)
209 {
210 case 16:
211 padding = 4;
212 address = (ZyanU16)address;
213 break;
214 case 32:
215 padding = 8;
216 address = (ZyanU32)address;
217 break;
218 case 64:
219 padding = 16;
220 break;
221 default:
222 return ZYAN_STATUS_INVALID_ARGUMENT;
223 }
224 }
225
226 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_ADDRESS_ABS);
227 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string, address, padding);
228
229 return ZYAN_STATUS_SUCCESS;
230 }
231
ZydisFormatterBasePrintAddressREL(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context)232 ZyanStatus ZydisFormatterBasePrintAddressREL(const ZydisFormatter* formatter,
233 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
234 {
235 ZYAN_ASSERT(formatter);
236 ZYAN_ASSERT(buffer);
237 ZYAN_ASSERT(context);
238
239 ZyanU64 address;
240 ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand, 0, &address));
241
242 ZyanU8 padding = (formatter->addr_padding_relative ==
243 ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->addr_padding_relative;
244 if ((formatter->addr_padding_relative == ZYDIS_PADDING_AUTO) &&
245 (formatter->addr_base == ZYDIS_NUMERIC_BASE_HEX))
246 {
247 switch (context->instruction->stack_width)
248 {
249 case 16:
250 padding = 4;
251 address = (ZyanU16)address;
252 break;
253 case 32:
254 padding = 8;
255 address = (ZyanU32)address;
256 break;
257 case 64:
258 padding = 16;
259 break;
260 default:
261 return ZYAN_STATUS_INVALID_ARGUMENT;
262 }
263 }
264
265 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_ADDRESS_REL);
266 switch (formatter->addr_signedness)
267 {
268 case ZYDIS_SIGNEDNESS_AUTO:
269 case ZYDIS_SIGNEDNESS_SIGNED:
270 ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->addr_base, &buffer->string, address,
271 padding, ZYAN_TRUE);
272 break;
273 case ZYDIS_SIGNEDNESS_UNSIGNED:
274 ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_ADD));
275 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string, address,
276 padding);
277 break;
278 default:
279 return ZYAN_STATUS_INVALID_ARGUMENT;
280 }
281
282 return ZYAN_STATUS_SUCCESS;
283 }
284
ZydisFormatterBasePrintIMM(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context)285 ZyanStatus ZydisFormatterBasePrintIMM(const ZydisFormatter* formatter,
286 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
287 {
288 ZYAN_ASSERT(formatter);
289 ZYAN_ASSERT(buffer);
290 ZYAN_ASSERT(context);
291
292 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE);
293
294 const ZyanBool is_signed =
295 (formatter->imm_signedness == ZYDIS_SIGNEDNESS_SIGNED) ||
296 (formatter->imm_signedness == ZYDIS_SIGNEDNESS_AUTO && (context->operand->imm.is_signed));
297 if (is_signed && (context->operand->imm.value.s < 0))
298 {
299 ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->imm_base, &buffer->string,
300 context->operand->imm.value.s, formatter->imm_padding, ZYAN_FALSE);
301 return ZYAN_STATUS_SUCCESS;
302 }
303 ZyanU64 value;
304 ZyanU8 padding = (formatter->imm_padding ==
305 ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->imm_padding;
306 switch (context->instruction->operand_width)
307 {
308 case 8:
309 if (formatter->imm_padding == ZYDIS_PADDING_AUTO)
310 {
311 padding = 2;
312 }
313 value = (ZyanU8 )context->operand->imm.value.u;
314 break;
315 case 16:
316 if (formatter->imm_padding == ZYDIS_PADDING_AUTO)
317 {
318 padding = 4;
319 }
320 value = (ZyanU16)context->operand->imm.value.u;
321 break;
322 case 32:
323 if (formatter->imm_padding == ZYDIS_PADDING_AUTO)
324 {
325 padding = 8;
326 }
327 value = (ZyanU32)context->operand->imm.value.u;
328 break;
329 case 64:
330 if (formatter->imm_padding == ZYDIS_PADDING_AUTO)
331 {
332 padding = 16;
333 }
334 value = (ZyanU64)context->operand->imm.value.u;
335 break;
336 default:
337 return ZYAN_STATUS_INVALID_ARGUMENT;
338 }
339 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->imm_base, &buffer->string, value, padding);
340
341 return ZYAN_STATUS_SUCCESS;
342 }
343
344 /* ---------------------------------------------------------------------------------------------- */
345 /* Optional tokens */
346 /* ---------------------------------------------------------------------------------------------- */
347
ZydisFormatterBasePrintSegment(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context)348 ZyanStatus ZydisFormatterBasePrintSegment(const ZydisFormatter* formatter,
349 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
350 {
351 ZYAN_ASSERT(formatter);
352 ZYAN_ASSERT(buffer);
353 ZYAN_ASSERT(context);
354
355 ZyanBool printed_segment = ZYAN_FALSE;
356 switch (context->operand->mem.segment)
357 {
358 case ZYDIS_REGISTER_ES:
359 case ZYDIS_REGISTER_CS:
360 case ZYDIS_REGISTER_FS:
361 case ZYDIS_REGISTER_GS:
362 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
363 context->operand->mem.segment));
364 printed_segment = ZYAN_TRUE;
365 break;
366 case ZYDIS_REGISTER_SS:
367 if ((formatter->force_memory_segment) ||
368 (context->instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_SS))
369 {
370 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
371 context->operand->mem.segment));
372 printed_segment = ZYAN_TRUE;
373 }
374 break;
375 case ZYDIS_REGISTER_DS:
376 if ((formatter->force_memory_segment) ||
377 (context->instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_DS))
378 {
379 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
380 context->operand->mem.segment));
381 printed_segment = ZYAN_TRUE;
382 }
383 break;
384 default:
385 break;
386 }
387 if (printed_segment)
388 {
389 ZYDIS_BUFFER_APPEND(buffer, DELIM_SEGMENT);
390 }
391
392 return ZYAN_STATUS_SUCCESS;
393 }
394
ZydisFormatterBasePrintPrefixes(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context)395 ZyanStatus ZydisFormatterBasePrintPrefixes(const ZydisFormatter* formatter,
396 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
397 {
398 ZYAN_ASSERT(formatter);
399 ZYAN_ASSERT(buffer);
400 ZYAN_ASSERT(context);
401
402 if (formatter->detailed_prefixes)
403 {
404 for (ZyanU8 i = 0; i < context->instruction->raw.prefix_count; ++i)
405 {
406 const ZyanU8 value = context->instruction->raw.prefixes[i].value;
407 switch (context->instruction->raw.prefixes[i].type)
408 {
409 case ZYDIS_PREFIX_TYPE_IGNORED:
410 case ZYDIS_PREFIX_TYPE_MANDATORY:
411 {
412 if ((value & 0xF0) == 0x40)
413 {
414 if (buffer->is_token_list)
415 {
416 // TODO: Case
417 ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer,
418 TOK_PREF_REX[value & 0x0F]));
419 } else
420 {
421 ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string,
422 STR_PREF_REX[value & 0x0F], formatter->case_prefixes));
423 }
424 } else
425 {
426 switch (value)
427 {
428 case 0xF0:
429 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_LOCK, formatter->case_prefixes);
430 break;
431 case 0x2E:
432 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_CS, formatter->case_prefixes);
433 break;
434 case 0x36:
435 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_SS, formatter->case_prefixes);
436 break;
437 case 0x3E:
438 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_DS, formatter->case_prefixes);
439 break;
440 case 0x26:
441 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_ES, formatter->case_prefixes);
442 break;
443 case 0x64:
444 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_FS, formatter->case_prefixes);
445 break;
446 case 0x65:
447 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_GS, formatter->case_prefixes);
448 break;
449 default:
450 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_PREFIX);
451 ZYAN_CHECK(ZydisStringAppendHexU(&buffer->string, value, 0,
452 formatter->hex_uppercase, ZYAN_NULL, ZYAN_NULL));
453 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_WHITESPACE);
454 ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_WHITESPACE));
455 break;
456 }
457 }
458 break;
459 }
460 case ZYDIS_PREFIX_TYPE_EFFECTIVE:
461 switch (value)
462 {
463 case 0xF0:
464 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_LOCK, formatter->case_prefixes);
465 break;
466 case 0xF2:
467 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XACQUIRE)
468 {
469 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XACQUIRE, formatter->case_prefixes);
470 }
471 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPNE)
472 {
473 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPNE, formatter->case_prefixes);
474 }
475
476 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_BND)
477 {
478 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_BND, formatter->case_prefixes);
479 }
480 break;
481 case 0xF3:
482 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XRELEASE)
483 {
484 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XRELEASE, formatter->case_prefixes);
485 }
486 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REP)
487 {
488 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REP, formatter->case_prefixes);
489 }
490 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPE)
491 {
492 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPE, formatter->case_prefixes);
493 }
494 break;
495 default:
496 break;
497 }
498 break;
499 default:
500 return ZYAN_STATUS_INVALID_ARGUMENT;
501 }
502 }
503 return ZYAN_STATUS_SUCCESS;
504 }
505
506 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XACQUIRE)
507 {
508 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XACQUIRE, formatter->case_prefixes);
509 }
510 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XRELEASE)
511 {
512 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XRELEASE, formatter->case_prefixes);
513 }
514
515 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_LOCK)
516 {
517 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_LOCK, formatter->case_prefixes);
518 return ZYAN_STATUS_SUCCESS;
519 }
520
521 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REP)
522 {
523 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REP, formatter->case_prefixes);
524 return ZYAN_STATUS_SUCCESS;
525 }
526 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPE)
527 {
528 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPE, formatter->case_prefixes);
529 return ZYAN_STATUS_SUCCESS;
530 }
531 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPNE)
532 {
533 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPNE, formatter->case_prefixes);
534 return ZYAN_STATUS_SUCCESS;
535 }
536
537 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_BND)
538 {
539 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_BND, formatter->case_prefixes);
540 return ZYAN_STATUS_SUCCESS;
541 }
542
543 return ZYAN_STATUS_SUCCESS;
544 }
545
ZydisFormatterBasePrintDecorator(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context,ZydisDecorator decorator)546 ZyanStatus ZydisFormatterBasePrintDecorator(const ZydisFormatter* formatter,
547 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisDecorator decorator)
548 {
549 ZYAN_ASSERT(formatter);
550 ZYAN_ASSERT(buffer);
551 ZYAN_ASSERT(context);
552
553 #if defined(ZYDIS_DISABLE_AVX512) && defined(ZYDIS_DISABLE_KNC)
554 ZYAN_UNUSED(formatter);
555 ZYAN_UNUSED(buffer);
556 ZYAN_UNUSED(context);
557 #endif
558
559 switch (decorator)
560 {
561 case ZYDIS_DECORATOR_MASK:
562 {
563 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
564 if (context->instruction->avx.mask.reg != ZYDIS_REGISTER_K0)
565 {
566 if (buffer->is_token_list)
567 {
568 ZYDIS_BUFFER_APPEND(buffer, DECO_BEGIN);
569 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
570 context->instruction->avx.mask.reg));
571 ZYDIS_BUFFER_APPEND(buffer, DECO_END);
572 } else
573 {
574 ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_DECO_BEGIN));
575 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
576 context->instruction->avx.mask.reg));
577 ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_DECO_END));
578 }
579
580 // Only print the zeroing decorator, if the instruction is not a "zeroing masking only"
581 // instruction (e.g. `vcmpsd`)
582 if ((context->instruction->avx.mask.mode == ZYDIS_MASK_MODE_ZEROING) &&
583 (context->instruction->raw.evex.z))
584 {
585 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_ZERO, formatter->case_decorators);
586 }
587 }
588 #endif
589 break;
590 }
591 case ZYDIS_DECORATOR_BC:
592 #if !defined(ZYDIS_DISABLE_AVX512)
593 if (!context->instruction->avx.broadcast.is_static)
594 {
595 switch (context->instruction->avx.broadcast.mode)
596 {
597 case ZYDIS_BROADCAST_MODE_INVALID:
598 break;
599 case ZYDIS_BROADCAST_MODE_1_TO_2:
600 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO2, formatter->case_decorators);
601 break;
602 case ZYDIS_BROADCAST_MODE_1_TO_4:
603 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO4, formatter->case_decorators);
604 break;
605 case ZYDIS_BROADCAST_MODE_1_TO_8:
606 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO8, formatter->case_decorators);
607 break;
608 case ZYDIS_BROADCAST_MODE_1_TO_16:
609 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO16, formatter->case_decorators);
610 break;
611 case ZYDIS_BROADCAST_MODE_4_TO_8:
612 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_4TO8, formatter->case_decorators);
613 break;
614 case ZYDIS_BROADCAST_MODE_4_TO_16:
615 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_4TO16, formatter->case_decorators);
616 break;
617 default:
618 return ZYAN_STATUS_INVALID_ARGUMENT;
619 }
620 }
621 #endif
622 break;
623 case ZYDIS_DECORATOR_RC:
624 #if !defined(ZYDIS_DISABLE_AVX512)
625 if (context->instruction->avx.has_sae)
626 {
627 switch (context->instruction->avx.rounding.mode)
628 {
629 case ZYDIS_ROUNDING_MODE_INVALID:
630 break;
631 case ZYDIS_ROUNDING_MODE_RN:
632 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RN_SAE, formatter->case_decorators);
633 break;
634 case ZYDIS_ROUNDING_MODE_RD:
635 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RD_SAE, formatter->case_decorators);
636 break;
637 case ZYDIS_ROUNDING_MODE_RU:
638 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RU_SAE, formatter->case_decorators);
639 break;
640 case ZYDIS_ROUNDING_MODE_RZ:
641 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RZ_SAE, formatter->case_decorators);
642 break;
643 default:
644 return ZYAN_STATUS_INVALID_ARGUMENT;
645 }
646 } else
647 {
648 switch (context->instruction->avx.rounding.mode)
649 {
650 case ZYDIS_ROUNDING_MODE_INVALID:
651 break;
652 case ZYDIS_ROUNDING_MODE_RN:
653 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RN, formatter->case_decorators);
654 break;
655 case ZYDIS_ROUNDING_MODE_RD:
656 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RD, formatter->case_decorators);
657 break;
658 case ZYDIS_ROUNDING_MODE_RU:
659 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RU, formatter->case_decorators);
660 break;
661 case ZYDIS_ROUNDING_MODE_RZ:
662 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RZ, formatter->case_decorators);
663 break;
664 default:
665 return ZYAN_STATUS_INVALID_ARGUMENT;
666 }
667 }
668 #endif
669 break;
670 case ZYDIS_DECORATOR_SAE:
671 #if !defined(ZYDIS_DISABLE_AVX512)
672 if (context->instruction->avx.has_sae && !context->instruction->avx.rounding.mode)
673 {
674 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_SAE, formatter->case_decorators);
675 }
676 #endif
677 break;
678 case ZYDIS_DECORATOR_SWIZZLE:
679 #if !defined(ZYDIS_DISABLE_KNC)
680 switch (context->instruction->avx.swizzle.mode)
681 {
682 case ZYDIS_SWIZZLE_MODE_INVALID:
683 case ZYDIS_SWIZZLE_MODE_DCBA:
684 // Nothing to do here
685 break;
686 case ZYDIS_SWIZZLE_MODE_CDAB:
687 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_CDAB, formatter->case_decorators);
688 break;
689 case ZYDIS_SWIZZLE_MODE_BADC:
690 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_BADC, formatter->case_decorators);
691 break;
692 case ZYDIS_SWIZZLE_MODE_DACB:
693 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_DACB, formatter->case_decorators);
694 break;
695 case ZYDIS_SWIZZLE_MODE_AAAA:
696 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_AAAA, formatter->case_decorators);
697 break;
698 case ZYDIS_SWIZZLE_MODE_BBBB:
699 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_BBBB, formatter->case_decorators);
700 break;
701 case ZYDIS_SWIZZLE_MODE_CCCC:
702 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_CCCC, formatter->case_decorators);
703 break;
704 case ZYDIS_SWIZZLE_MODE_DDDD:
705 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_DDDD, formatter->case_decorators);
706 break;
707 default:
708 return ZYAN_STATUS_INVALID_ARGUMENT;
709 }
710 #endif
711 break;
712 case ZYDIS_DECORATOR_CONVERSION:
713 #if !defined(ZYDIS_DISABLE_KNC)
714 switch (context->instruction->avx.conversion.mode)
715 {
716 case ZYDIS_CONVERSION_MODE_INVALID:
717 break;
718 case ZYDIS_CONVERSION_MODE_FLOAT16:
719 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_FLOAT16, formatter->case_decorators);
720 break;
721 case ZYDIS_CONVERSION_MODE_SINT8:
722 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_SINT8, formatter->case_decorators);
723 break;
724 case ZYDIS_CONVERSION_MODE_UINT8:
725 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_UINT8, formatter->case_decorators);
726 break;
727 case ZYDIS_CONVERSION_MODE_SINT16:
728 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_SINT16, formatter->case_decorators);
729 break;
730 case ZYDIS_CONVERSION_MODE_UINT16:
731 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_UINT16, formatter->case_decorators);
732 break;
733 default:
734 return ZYAN_STATUS_INVALID_ARGUMENT;
735 }
736 #endif
737 break;
738 case ZYDIS_DECORATOR_EH:
739 #if !defined(ZYDIS_DISABLE_KNC)
740 if (context->instruction->avx.has_eviction_hint)
741 {
742 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_EH, formatter->case_decorators);
743 }
744 #endif
745 break;
746 default:
747 return ZYAN_STATUS_INVALID_ARGUMENT;
748 }
749
750 return ZYAN_STATUS_SUCCESS;
751 }
752
753 /* ---------------------------------------------------------------------------------------------- */
754
755 /* ============================================================================================== */
756