d3d8/tests: Test the presentation parameters after creating an additional swap chain.
[wine.git] / libs / zydis / src / FormatterIntel.c
blob0584fb24093bb165da3f4c03521fad8e24b542b8
1 /***************************************************************************************************
3 Zyan Disassembler Library (Zydis)
5 Original Author : Florian Bernd, Joel Hoener
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:
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
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.
25 ***************************************************************************************************/
27 #include <Zydis/Internal/FormatterIntel.h>
28 #include <Zydis/Utils.h>
29 #include <Zycore/Format.h>
31 /* ============================================================================================== */
32 /* Constants */
33 /* ============================================================================================== */
35 #include <Generated/FormatterStrings.inc>
37 /* ============================================================================================== */
38 /* Formatter functions */
39 /* ============================================================================================== */
41 /* ---------------------------------------------------------------------------------------------- */
42 /* Intel */
43 /* ---------------------------------------------------------------------------------------------- */
45 ZyanStatus ZydisFormatterIntelFormatInstruction(const ZydisFormatter* formatter,
46 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
48 ZYAN_ASSERT(formatter);
49 ZYAN_ASSERT(buffer);
50 ZYAN_ASSERT(context);
51 ZYAN_ASSERT(context->instruction);
52 ZYAN_ASSERT(context->operands);
54 ZYAN_CHECK(formatter->func_print_prefixes(formatter, buffer, context));
55 ZYAN_CHECK(formatter->func_print_mnemonic(formatter, buffer, context));
57 ZyanUPointer state_mnemonic;
58 ZYDIS_BUFFER_REMEMBER(buffer, state_mnemonic);
59 for (ZyanU8 i = 0; i < context->instruction->operand_count_visible; ++i)
61 const ZydisDecodedOperand* const operand = &context->operands[i];
63 // Print embedded-mask registers as decorator instead of a regular operand
64 if ((i == 1) && (operand->type == ZYDIS_OPERAND_TYPE_REGISTER) &&
65 (operand->encoding == ZYDIS_OPERAND_ENCODING_MASK))
67 continue;
70 ZyanUPointer buffer_state;
71 ZYDIS_BUFFER_REMEMBER(buffer, buffer_state);
73 if (buffer_state != state_mnemonic)
75 ZYDIS_BUFFER_APPEND(buffer, DELIM_OPERAND);
76 } else
78 ZYDIS_BUFFER_APPEND(buffer, DELIM_MNEMONIC);
81 // Set current operand
82 context->operand = operand;
84 ZyanStatus status;
85 if (formatter->func_pre_operand)
87 status = formatter->func_pre_operand(formatter, buffer, context);
88 if (status == ZYDIS_STATUS_SKIP_TOKEN)
90 ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
91 continue;
93 if (!ZYAN_SUCCESS(status))
95 return status;
99 switch (operand->type)
101 case ZYDIS_OPERAND_TYPE_REGISTER:
102 status = formatter->func_format_operand_reg(formatter, buffer, context);
103 break;
104 case ZYDIS_OPERAND_TYPE_MEMORY:
105 status = formatter->func_format_operand_mem(formatter, buffer, context);
106 break;
107 case ZYDIS_OPERAND_TYPE_POINTER:
108 status = formatter->func_format_operand_ptr(formatter, buffer, context);
109 break;
110 case ZYDIS_OPERAND_TYPE_IMMEDIATE:
111 status = formatter->func_format_operand_imm(formatter, buffer, context);
112 break;
113 default:
114 return ZYAN_STATUS_INVALID_ARGUMENT;
116 if (status == ZYDIS_STATUS_SKIP_TOKEN)
118 ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
119 continue;
121 if (!ZYAN_SUCCESS(status))
123 return status;
126 if (formatter->func_post_operand)
128 status = formatter->func_post_operand(formatter, buffer, context);
129 if (status == ZYDIS_STATUS_SKIP_TOKEN)
131 ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
132 continue;
134 if (ZYAN_SUCCESS(status))
136 return status;
140 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
141 if ((context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
142 (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX))
144 if ((i == 0) &&
145 (context->instruction->operand_count_visible > 1) &&
146 (context->operands[i + 1].encoding == ZYDIS_OPERAND_ENCODING_MASK))
148 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
149 ZYDIS_DECORATOR_MASK));
151 if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY)
153 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
154 ZYDIS_DECORATOR_BC));
155 if (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
157 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
158 ZYDIS_DECORATOR_CONVERSION));
159 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
160 ZYDIS_DECORATOR_EH));
162 } else
164 ZyanBool decorate_operand;
165 if (i == (context->instruction->operand_count_visible - 1))
167 decorate_operand = operand->type != ZYDIS_OPERAND_TYPE_IMMEDIATE;
169 else
171 decorate_operand =
172 (context->instruction->operand_count_visible > (i + 1)) &&
173 ((context->operands[i + 1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) ||
174 (context->operands[i + 1].visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN));
176 if (decorate_operand)
178 if (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
180 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
181 ZYDIS_DECORATOR_SWIZZLE));
183 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
184 ZYDIS_DECORATOR_RC));
185 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
186 ZYDIS_DECORATOR_SAE));
190 #endif
193 return ZYAN_STATUS_SUCCESS;
196 ZyanStatus ZydisFormatterIntelFormatOperandMEM(const ZydisFormatter* formatter,
197 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
199 ZYAN_ASSERT(formatter);
200 ZYAN_ASSERT(buffer);
201 ZYAN_ASSERT(context);
203 if ((context->operand->mem.type == ZYDIS_MEMOP_TYPE_MEM) ||
204 (context->operand->mem.type == ZYDIS_MEMOP_TYPE_VSIB))
206 ZYAN_CHECK(formatter->func_print_typecast(formatter, buffer, context));
208 ZYAN_CHECK(formatter->func_print_segment(formatter, buffer, context));
210 ZYDIS_BUFFER_APPEND(buffer, MEMORY_BEGIN_INTEL);
212 const ZyanBool absolute = !formatter->force_relative_riprel &&
213 (context->runtime_address != ZYDIS_RUNTIME_ADDRESS_NONE);
214 if (absolute && context->operand->mem.disp.has_displacement &&
215 (context->operand->mem.index == ZYDIS_REGISTER_NONE) &&
216 ((context->operand->mem.base == ZYDIS_REGISTER_NONE) ||
217 (context->operand->mem.base == ZYDIS_REGISTER_EIP ) ||
218 (context->operand->mem.base == ZYDIS_REGISTER_RIP )))
220 // EIP/RIP-relative or absolute-displacement address operand
221 ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context));
222 } else
224 const ZyanBool should_print_reg = context->operand->mem.base != ZYDIS_REGISTER_NONE;
225 const ZyanBool should_print_idx = context->operand->mem.index != ZYDIS_REGISTER_NONE;
226 const ZyanBool neither_reg_nor_idx = !should_print_reg && !should_print_idx;
228 // Regular memory operand
229 if (should_print_reg)
231 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
232 context->operand->mem.base));
234 if (should_print_idx)
236 if (context->operand->mem.base != ZYDIS_REGISTER_NONE)
238 ZYDIS_BUFFER_APPEND(buffer, ADD);
240 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
241 context->operand->mem.index));
242 if (context->operand->mem.scale &&
243 (context->operand->mem.type != ZYDIS_MEMOP_TYPE_MIB) &&
244 ((context->operand->mem.scale > 1) || formatter->force_memory_scale))
246 ZYDIS_BUFFER_APPEND(buffer, MUL);
247 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE);
248 ZYAN_CHECK(ZydisStringAppendDecU(&buffer->string, context->operand->mem.scale, 0,
249 ZYAN_NULL, ZYAN_NULL));
252 if (neither_reg_nor_idx)
254 ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context));
255 } else if (context->operand->mem.disp.has_displacement && context->operand->mem.disp.value)
257 ZYAN_CHECK(formatter->func_print_disp(formatter, buffer, context));
261 ZYDIS_BUFFER_APPEND(buffer, MEMORY_END_INTEL);
262 return ZYAN_STATUS_SUCCESS;
265 ZyanStatus ZydisFormatterIntelPrintMnemonic(const ZydisFormatter* formatter,
266 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
268 ZYAN_ASSERT(formatter);
269 ZYAN_ASSERT(buffer);
270 ZYAN_ASSERT(context);
272 const ZydisShortString* mnemonic = ZydisMnemonicGetStringWrapped(
273 context->instruction->mnemonic);
274 if (!mnemonic)
276 ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_MNEMONIC, formatter->case_mnemonic);
277 return ZYAN_STATUS_SUCCESS;
280 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_MNEMONIC);
281 ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, mnemonic, formatter->case_mnemonic));
282 if (context->instruction->meta.branch_type == ZYDIS_BRANCH_TYPE_FAR)
284 return ZydisStringAppendShortCase(&buffer->string, &STR_FAR, formatter->case_mnemonic);
286 if (formatter->print_branch_size)
288 switch (context->instruction->meta.branch_type)
290 case ZYDIS_BRANCH_TYPE_NONE:
291 break;
292 case ZYDIS_BRANCH_TYPE_SHORT:
293 return ZydisStringAppendShortCase(&buffer->string, &STR_SHORT,
294 formatter->case_mnemonic);
295 case ZYDIS_BRANCH_TYPE_NEAR:
296 return ZydisStringAppendShortCase(&buffer->string, &STR_NEAR,
297 formatter->case_mnemonic);
298 default:
299 return ZYAN_STATUS_INVALID_ARGUMENT;
303 return ZYAN_STATUS_SUCCESS;
306 ZyanStatus ZydisFormatterIntelPrintRegister(const ZydisFormatter* formatter,
307 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg)
309 ZYAN_UNUSED(context);
311 ZYAN_ASSERT(formatter);
312 ZYAN_ASSERT(buffer);
313 ZYAN_ASSERT(context);
315 const ZydisShortString* str = ZydisRegisterGetStringWrapped(reg);
316 if (!str)
318 ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_REG, formatter->case_registers);
319 return ZYAN_STATUS_SUCCESS;
322 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_REGISTER);
323 return ZydisStringAppendShortCase(&buffer->string, str, formatter->case_registers);
326 ZyanStatus ZydisFormatterIntelPrintDISP(const ZydisFormatter* formatter,
327 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
329 ZYAN_ASSERT(formatter);
330 ZYAN_ASSERT(buffer);
331 ZYAN_ASSERT(context);
333 switch (formatter->disp_signedness)
335 case ZYDIS_SIGNEDNESS_AUTO:
336 case ZYDIS_SIGNEDNESS_SIGNED:
337 if (context->operand->mem.disp.value < 0)
339 if ((context->operand->mem.base != ZYDIS_REGISTER_NONE) ||
340 (context->operand->mem.index != ZYDIS_REGISTER_NONE))
342 ZYDIS_BUFFER_APPEND(buffer, SUB);
344 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT);
345 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string,
346 ZyanAbsI64(context->operand->mem.disp.value), formatter->disp_padding,
347 formatter->hex_force_leading_number);
348 break;
350 ZYAN_FALLTHROUGH;
351 case ZYDIS_SIGNEDNESS_UNSIGNED:
352 if ((context->operand->mem.base != ZYDIS_REGISTER_NONE) ||
353 (context->operand->mem.index != ZYDIS_REGISTER_NONE))
355 ZYDIS_BUFFER_APPEND(buffer, ADD);
357 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT);
358 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string,
359 context->operand->mem.disp.value, formatter->disp_padding,
360 formatter->hex_force_leading_number);
361 break;
362 default:
363 return ZYAN_STATUS_INVALID_ARGUMENT;
366 return ZYAN_STATUS_SUCCESS;
369 ZyanStatus ZydisFormatterIntelPrintTypecast(const ZydisFormatter* formatter,
370 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
372 ZYAN_ASSERT(formatter);
373 ZYAN_ASSERT(buffer);
374 ZYAN_ASSERT(context);
376 switch (ZydisFormatterHelperGetExplicitSize(formatter, context, context->operand))
378 case 8: ZYDIS_BUFFER_APPEND(buffer, SIZE_8_INTEL ); break;
379 case 16: ZYDIS_BUFFER_APPEND(buffer, SIZE_16_INTEL ); break;
380 case 32: ZYDIS_BUFFER_APPEND(buffer, SIZE_32_INTEL ); break;
381 case 48: ZYDIS_BUFFER_APPEND(buffer, SIZE_48 ); break;
382 case 64: ZYDIS_BUFFER_APPEND(buffer, SIZE_64_INTEL ); break;
383 case 80: ZYDIS_BUFFER_APPEND(buffer, SIZE_80 ); break;
384 case 128: ZYDIS_BUFFER_APPEND(buffer, SIZE_128_INTEL); break;
385 case 256: ZYDIS_BUFFER_APPEND(buffer, SIZE_256_INTEL); break;
386 case 512: ZYDIS_BUFFER_APPEND(buffer, SIZE_512_INTEL); break;
387 default:
388 break;
391 return ZYAN_STATUS_SUCCESS;
394 /* ---------------------------------------------------------------------------------------------- */
395 /* MASM */
396 /* ---------------------------------------------------------------------------------------------- */
398 ZyanStatus ZydisFormatterIntelFormatInstructionMASM(const ZydisFormatter* formatter,
399 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
401 ZYAN_ASSERT(formatter);
402 ZYAN_ASSERT(buffer);
403 ZYAN_ASSERT(context);
405 // Force the formatter to always call our MASM `ZYDIS_FORMATTER_PRINT_ADDRESS_ABS` function.
406 // This implicitly omits printing of the `RIP`/`EIP` registers for `RIP`/`EIP`-relative
407 // memory operands
408 context->runtime_address = 0;
410 return ZydisFormatterIntelFormatInstruction(formatter, buffer, context);
413 ZyanStatus ZydisFormatterIntelPrintAddressMASM(const ZydisFormatter* formatter,
414 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
416 ZYAN_ASSERT(formatter);
417 ZYAN_ASSERT(buffer);
418 ZYAN_ASSERT(context);
420 ZyanU64 address;
421 ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand, 0, &address));
423 ZyanU8 padding = (formatter->addr_padding_relative ==
424 ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->addr_padding_relative;
425 if ((formatter->addr_padding_relative == ZYDIS_PADDING_AUTO) &&
426 (formatter->addr_base == ZYDIS_NUMERIC_BASE_HEX))
428 switch (context->instruction->stack_width)
430 case 16:
431 padding = 4;
432 address = (ZyanU16)address;
433 break;
434 case 32:
435 padding = 8;
436 address = (ZyanU32)address;
437 break;
438 case 64:
439 padding = 16;
440 break;
441 default:
442 return ZYAN_STATUS_INVALID_ARGUMENT;
446 ZYDIS_BUFFER_APPEND(buffer, ADDR_RELATIVE);
447 ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->addr_base, &buffer->string, address, padding,
448 formatter->hex_force_leading_number, ZYAN_TRUE);
450 return ZYAN_STATUS_SUCCESS;
453 /* ---------------------------------------------------------------------------------------------- */
455 /* ============================================================================================== */