Coverage Report

Created: 2026-01-22 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/zydis/src/FormatterIntel.c
Line
Count
Source
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/FormatterIntel.h>
28
#include <Zydis/Utils.h>
29
#include <Zycore/Format.h>
30
31
/* ============================================================================================== */
32
/* Constants                                                                                      */
33
/* ============================================================================================== */
34
35
#include <Generated/FormatterStrings.inc>
36
37
/* ============================================================================================== */
38
/* Formatter functions                                                                            */
39
/* ============================================================================================== */
40
41
/* ---------------------------------------------------------------------------------------------- */
42
/* Intel                                                                                          */
43
/* ---------------------------------------------------------------------------------------------- */
44
45
ZyanStatus ZydisFormatterIntelFormatInstruction(const ZydisFormatter* formatter,
46
    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
47
2.51k
{
48
2.51k
    ZYAN_ASSERT(formatter);
49
2.51k
    ZYAN_ASSERT(buffer);
50
2.51k
    ZYAN_ASSERT(context);
51
2.51k
    ZYAN_ASSERT(context->instruction);
52
2.51k
    ZYAN_ASSERT(context->operands);
53
54
2.51k
    if (!formatter->deco_apx_nf_use_suffix)
55
2.51k
    {
56
2.51k
        ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, 
57
2.51k
            ZYDIS_DECORATOR_APX_NF));
58
2.51k
    }
59
    
60
2.50k
    ZYAN_CHECK(formatter->func_print_prefixes(formatter, buffer, context));
61
2.47k
    ZYAN_CHECK(formatter->func_print_mnemonic(formatter, buffer, context));
62
    
63
2.28k
    if (!formatter->deco_apx_dfv_use_immediate)
64
2.28k
    {
65
2.28k
        ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, 
66
2.28k
            ZYDIS_DECORATOR_APX_DFV));
67
2.28k
    }
68
69
2.24k
    ZyanUPointer state_mnemonic;
70
2.24k
    ZYDIS_BUFFER_REMEMBER(buffer, state_mnemonic);
71
72
2.24k
    if (formatter->deco_apx_dfv_use_immediate && (context->instruction->apx.scc != ZYDIS_SCC_NONE))
73
0
    {
74
0
        ZYDIS_BUFFER_APPEND(buffer, DELIM_MNEMONIC);
75
0
        ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE);
76
0
        ZYAN_CHECK(ZydisStringAppendDecU(&buffer->string, 
77
0
            context->instruction->apx.default_flags, 0,
78
0
            formatter->number_format[ZYDIS_NUMERIC_BASE_DEC][0].string,
79
0
            formatter->number_format[ZYDIS_NUMERIC_BASE_DEC][1].string));
80
0
    }
81
82
4.77k
    for (ZyanU8 i = 0; i < context->instruction->operand_count_visible; ++i)
83
3.35k
    {
84
3.35k
        const ZydisDecodedOperand* const operand = &context->operands[i];
85
86
        // Print embedded-mask registers as decorator instead of a regular operand
87
3.35k
        if ((i == 1) && (operand->type == ZYDIS_OPERAND_TYPE_REGISTER) &&
88
615
            (operand->encoding == ZYDIS_OPERAND_ENCODING_MASK))
89
114
        {
90
114
            continue;
91
114
        }
92
93
3.24k
        ZyanUPointer buffer_state;
94
3.24k
        ZYDIS_BUFFER_REMEMBER(buffer, buffer_state);
95
96
3.24k
        if (buffer_state != state_mnemonic)
97
1.19k
        {
98
1.19k
            ZYDIS_BUFFER_APPEND(buffer, DELIM_OPERAND);
99
1.15k
        } else
100
2.04k
        {
101
2.04k
            ZYDIS_BUFFER_APPEND(buffer, DELIM_MNEMONIC);
102
1.97k
        }
103
104
        // Set current operand
105
3.13k
        context->operand = operand;
106
107
3.13k
        ZyanStatus status;
108
3.13k
        if (formatter->func_pre_operand)
109
0
        {
110
0
            status = formatter->func_pre_operand(formatter, buffer, context);
111
0
            if (status == ZYDIS_STATUS_SKIP_TOKEN)
112
0
            {
113
0
                ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
114
0
                continue;
115
0
            }
116
0
            if (!ZYAN_SUCCESS(status))
117
0
            {
118
0
                return status;
119
0
            }
120
0
        }
121
122
3.13k
        switch (operand->type)
123
3.13k
        {
124
1.33k
        case ZYDIS_OPERAND_TYPE_REGISTER:
125
1.33k
            status = formatter->func_format_operand_reg(formatter, buffer, context);
126
1.33k
            break;
127
1.28k
        case ZYDIS_OPERAND_TYPE_MEMORY:
128
1.28k
            status = formatter->func_format_operand_mem(formatter, buffer, context);
129
1.28k
            break;
130
23
        case ZYDIS_OPERAND_TYPE_POINTER:
131
23
            status = formatter->func_format_operand_ptr(formatter, buffer, context);
132
23
            break;
133
490
        case ZYDIS_OPERAND_TYPE_IMMEDIATE:
134
490
            status = formatter->func_format_operand_imm(formatter, buffer, context);
135
490
            break;
136
0
        default:
137
0
            return ZYAN_STATUS_INVALID_ARGUMENT;
138
3.13k
        }
139
3.13k
        if (status == ZYDIS_STATUS_SKIP_TOKEN)
140
0
        {
141
0
            ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
142
0
            continue;
143
0
        }
144
3.13k
        if (!ZYAN_SUCCESS(status))
145
684
        {
146
684
            return status;
147
684
        }
148
149
2.44k
        if (formatter->func_post_operand)
150
0
        {
151
0
            status = formatter->func_post_operand(formatter, buffer, context);
152
0
            if (status == ZYDIS_STATUS_SKIP_TOKEN)
153
0
            {
154
0
                ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
155
0
                continue;
156
0
            }
157
0
            if (ZYAN_SUCCESS(status))
158
0
            {
159
0
                return status;
160
0
            }
161
0
        }
162
163
2.44k
#if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
164
2.44k
        if ((context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
165
2.21k
            (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX))
166
435
        {
167
435
            if  ((i == 0) &&
168
190
                 (context->instruction->operand_count_visible > 1) &&
169
183
                 (context->operands[i + 1].encoding == ZYDIS_OPERAND_ENCODING_MASK))
170
129
            {
171
129
                ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
172
129
                    ZYDIS_DECORATOR_MASK));
173
129
            }
174
422
            if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY)
175
113
            {
176
113
                ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
177
113
                    ZYDIS_DECORATOR_BC));
178
105
                if (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
179
40
                {
180
40
                    ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
181
40
                        ZYDIS_DECORATOR_CONVERSION));
182
37
                    ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
183
37
                        ZYDIS_DECORATOR_EH));
184
37
                }
185
105
            } else
186
309
            {
187
309
                ZyanBool decorate_operand;
188
309
                if (i == (context->instruction->operand_count_visible - 1))
189
83
                {
190
83
                    decorate_operand = operand->type != ZYDIS_OPERAND_TYPE_IMMEDIATE;
191
83
                }
192
226
                else
193
226
                {
194
226
                    decorate_operand =
195
226
                        (context->instruction->operand_count_visible > (i + 1)) &&
196
226
                        ((context->operands[i + 1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) ||
197
216
                        (context->operands[i + 1].visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN));
198
226
                }
199
309
                if (decorate_operand)
200
83
                {
201
83
                    if (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
202
33
                    {
203
33
                        ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
204
33
                            ZYDIS_DECORATOR_SWIZZLE));
205
33
                    }
206
79
                    ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
207
79
                        ZYDIS_DECORATOR_RC));
208
74
                    ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
209
74
                        ZYDIS_DECORATOR_SAE));
210
74
                }
211
309
            }
212
422
        }
213
2.44k
#endif
214
2.44k
    }
215
216
1.41k
    return ZYAN_STATUS_SUCCESS;
217
2.24k
}
218
219
ZyanStatus ZydisFormatterIntelFormatOperandMEM(const ZydisFormatter* formatter,
220
    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
221
2.37k
{
222
2.37k
    ZYAN_ASSERT(formatter);
223
2.37k
    ZYAN_ASSERT(buffer);
224
2.37k
    ZYAN_ASSERT(context);
225
226
2.37k
    if ((context->operand->mem.type == ZYDIS_MEMOP_TYPE_MEM) ||
227
156
        (context->operand->mem.type == ZYDIS_MEMOP_TYPE_AGEN) ||
228
93
        (context->operand->mem.type == ZYDIS_MEMOP_TYPE_VSIB))
229
2.34k
    {
230
2.34k
        ZYAN_CHECK(formatter->func_print_typecast(formatter, buffer, context));
231
2.34k
    }
232
2.14k
    ZYAN_CHECK(formatter->func_print_segment(formatter, buffer, context));
233
234
2.04k
    ZYDIS_BUFFER_APPEND(buffer, MEMORY_BEGIN_INTEL);
235
236
1.98k
    const ZyanBool absolute = !formatter->force_relative_riprel &&
237
1.06k
        (context->runtime_address != ZYDIS_RUNTIME_ADDRESS_NONE);
238
1.98k
    if (absolute && context->operand->mem.disp.size &&
239
389
        (context->operand->mem.index == ZYDIS_REGISTER_NONE) &&
240
275
       ((context->operand->mem.base  == ZYDIS_REGISTER_NONE) ||
241
204
        (context->operand->mem.base  == ZYDIS_REGISTER_EIP ) ||
242
190
        (context->operand->mem.base  == ZYDIS_REGISTER_RIP )))
243
111
    {
244
        // EIP/RIP-relative or absolute-displacement address operand
245
111
        ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context));
246
111
    } else
247
1.87k
    {
248
1.87k
        const ZyanBool should_print_reg = context->operand->mem.base != ZYDIS_REGISTER_NONE;
249
1.87k
        const ZyanBool should_print_idx = context->operand->mem.index != ZYDIS_REGISTER_NONE;
250
1.87k
        const ZyanBool neither_reg_nor_idx = !should_print_reg && !should_print_idx;
251
252
        // Regular memory operand
253
1.87k
        if (should_print_reg)
254
1.73k
        {
255
1.73k
            ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
256
1.73k
                context->operand->mem.base));
257
1.73k
        }
258
1.79k
        if (should_print_idx)
259
674
        {
260
674
            if (context->operand->mem.base != ZYDIS_REGISTER_NONE)
261
612
            {
262
612
                ZYDIS_BUFFER_APPEND(buffer, ADD);
263
591
            }
264
653
            ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
265
653
                context->operand->mem.index));
266
627
            if (context->operand->mem.scale &&
267
627
                (context->operand->mem.type != ZYDIS_MEMOP_TYPE_MIB) &&
268
610
                ((context->operand->mem.scale > 1) || formatter->force_memory_scale))
269
478
            {
270
478
                ZYDIS_BUFFER_APPEND(buffer, MUL);
271
464
                ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE);
272
458
                ZYAN_CHECK(ZydisStringAppendDecU(&buffer->string, context->operand->mem.scale, 0,
273
458
                    ZYAN_NULL, ZYAN_NULL));
274
458
            }
275
627
        }
276
1.72k
        if (neither_reg_nor_idx)
277
84
        {
278
84
            ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context));
279
1.64k
        } else if (context->operand->mem.disp.size && context->operand->mem.disp.value)
280
643
        {
281
643
            ZYAN_CHECK(formatter->func_print_disp(formatter, buffer, context));
282
643
        }
283
1.72k
    }
284
285
1.53k
    ZYDIS_BUFFER_APPEND(buffer, MEMORY_END_INTEL);
286
1.48k
    return ZYAN_STATUS_SUCCESS;
287
1.53k
}
288
289
ZyanStatus ZydisFormatterIntelPrintMnemonic(const ZydisFormatter* formatter,
290
    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
291
2.47k
{
292
2.47k
    ZYAN_ASSERT(formatter);
293
2.47k
    ZYAN_ASSERT(buffer);
294
2.47k
    ZYAN_ASSERT(context);
295
296
2.47k
    const ZydisShortString* mnemonic = ZydisMnemonicGetStringWrapped(
297
2.47k
        context->instruction->mnemonic);
298
2.47k
    if (!mnemonic)
299
0
    {
300
0
        ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_MNEMONIC, formatter->case_mnemonic);
301
0
        return ZYAN_STATUS_SUCCESS;
302
0
    }
303
304
2.47k
    ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_MNEMONIC);
305
2.45k
    ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, mnemonic, formatter->case_mnemonic));
306
307
2.33k
    if (formatter->deco_apx_nf_use_suffix && context->instruction->apx.has_nf)
308
0
    {
309
0
        ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, &STR_NF, formatter->case_mnemonic));
310
0
    }
311
312
2.33k
    if (context->instruction->meta.branch_type == ZYDIS_BRANCH_TYPE_FAR)
313
81
    {
314
81
        return ZydisStringAppendShortCase(&buffer->string, &STR_FAR, formatter->case_mnemonic);
315
81
    }
316
317
2.25k
    if (formatter->print_branch_size)
318
1.46k
    {
319
1.46k
        switch (context->instruction->meta.branch_type)
320
1.46k
        {
321
1.18k
        case ZYDIS_BRANCH_TYPE_NONE:
322
1.18k
            break;
323
183
        case ZYDIS_BRANCH_TYPE_SHORT:
324
183
            return ZydisStringAppendShortCase(&buffer->string, &STR_SHORT,
325
183
                formatter->case_mnemonic);
326
95
        case ZYDIS_BRANCH_TYPE_NEAR:
327
95
            return ZydisStringAppendShortCase(&buffer->string, &STR_NEAR,
328
95
                formatter->case_mnemonic);
329
3
        default:
330
3
            return ZYAN_STATUS_INVALID_ARGUMENT;
331
1.46k
        }
332
1.46k
    }
333
334
1.97k
    return ZYAN_STATUS_SUCCESS;
335
2.25k
}
336
337
ZyanStatus ZydisFormatterIntelPrintRegister(const ZydisFormatter* formatter,
338
    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg)
339
6.01k
{
340
6.01k
    ZYAN_UNUSED(context);
341
342
6.01k
    ZYAN_ASSERT(formatter);
343
6.01k
    ZYAN_ASSERT(buffer);
344
6.01k
    ZYAN_ASSERT(context);
345
346
6.01k
    const ZydisShortString* str = ZydisRegisterGetStringWrapped(reg);
347
6.01k
    if (!str)
348
0
    {
349
0
        ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_REG, formatter->case_registers);
350
0
        return ZYAN_STATUS_SUCCESS;
351
0
    }
352
353
6.01k
    ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_REGISTER);
354
5.94k
    return ZydisStringAppendShortCase(&buffer->string, str, formatter->case_registers);
355
6.01k
}
356
357
ZyanStatus ZydisFormatterIntelPrintDISP(const ZydisFormatter* formatter,
358
    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
359
643
{
360
643
    ZYAN_ASSERT(formatter);
361
643
    ZYAN_ASSERT(buffer);
362
643
    ZYAN_ASSERT(context);
363
364
643
    switch (formatter->disp_signedness)
365
643
    {
366
374
    case ZYDIS_SIGNEDNESS_AUTO:
367
620
    case ZYDIS_SIGNEDNESS_SIGNED:
368
620
        if (context->operand->mem.disp.value < 0)
369
433
        {
370
433
            if ((context->operand->mem.base  != ZYDIS_REGISTER_NONE) ||
371
24
                (context->operand->mem.index != ZYDIS_REGISTER_NONE))
372
433
            {
373
433
                ZYDIS_BUFFER_APPEND(buffer, SUB);
374
423
            }
375
423
            ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT);
376
419
            ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string,
377
419
                ZyanAbsI64(context->operand->mem.disp.value), formatter->disp_padding,
378
419
                formatter->hex_force_leading_number);
379
284
            break;
380
419
        }
381
187
        ZYAN_FALLTHROUGH;
382
210
    case ZYDIS_SIGNEDNESS_UNSIGNED:
383
210
        if ((context->operand->mem.base  != ZYDIS_REGISTER_NONE) ||
384
33
            (context->operand->mem.index != ZYDIS_REGISTER_NONE))
385
210
        {
386
210
            ZYDIS_BUFFER_APPEND(buffer, ADD);
387
196
        }
388
196
        ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT);
389
194
        ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string,
390
194
            context->operand->mem.disp.value, formatter->disp_padding,
391
194
            formatter->hex_force_leading_number);
392
131
        break;
393
0
    default:
394
0
        return ZYAN_STATUS_INVALID_ARGUMENT;
395
643
    }
396
397
415
    return ZYAN_STATUS_SUCCESS;
398
643
}
399
400
ZyanStatus ZydisFormatterIntelPrintTypecast(const ZydisFormatter* formatter,
401
    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
402
2.34k
{
403
2.34k
    ZYAN_ASSERT(formatter);
404
2.34k
    ZYAN_ASSERT(buffer);
405
2.34k
    ZYAN_ASSERT(context);
406
407
2.34k
    switch (ZydisFormatterHelperGetExplicitSize(formatter, context, context->operand))
408
2.34k
    {
409
750
    case   8: ZYDIS_BUFFER_APPEND(buffer, SIZE_8_INTEL  ); break;
410
311
    case  16: ZYDIS_BUFFER_APPEND(buffer, SIZE_16_INTEL ); break;
411
317
    case  32: ZYDIS_BUFFER_APPEND(buffer, SIZE_32_INTEL ); break;
412
84
    case  48: ZYDIS_BUFFER_APPEND(buffer, SIZE_48       ); break;
413
134
    case  64: ZYDIS_BUFFER_APPEND(buffer, SIZE_64_INTEL ); break;
414
109
    case  80: ZYDIS_BUFFER_APPEND(buffer, SIZE_80       ); break;
415
86
    case 128: ZYDIS_BUFFER_APPEND(buffer, SIZE_128_INTEL); break;
416
94
    case 256: ZYDIS_BUFFER_APPEND(buffer, SIZE_256_INTEL); break;
417
72
    case 512: ZYDIS_BUFFER_APPEND(buffer, SIZE_512_INTEL); break;
418
386
    default:
419
386
        break;
420
2.34k
    }
421
422
2.10k
    return ZYAN_STATUS_SUCCESS;
423
2.34k
}
424
425
/* ---------------------------------------------------------------------------------------------- */
426
/* MASM                                                                                           */
427
/* ---------------------------------------------------------------------------------------------- */
428
429
ZyanStatus ZydisFormatterIntelFormatInstructionMASM(const ZydisFormatter* formatter,
430
    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
431
1.11k
{
432
1.11k
    ZYAN_ASSERT(formatter);
433
1.11k
    ZYAN_ASSERT(buffer);
434
1.11k
    ZYAN_ASSERT(context);
435
436
    // Force the formatter to always call our MASM `ZYDIS_FORMATTER_PRINT_ADDRESS_ABS` function.
437
    // This implicitly omits printing of the `RIP`/`EIP` registers for `RIP`/`EIP`-relative
438
    // memory operands
439
1.11k
    context->runtime_address = 0;
440
441
1.11k
    return ZydisFormatterIntelFormatInstruction(formatter, buffer, context);
442
1.11k
}
443
444
ZyanStatus ZydisFormatterIntelPrintAddressMASM(const ZydisFormatter* formatter,
445
    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
446
635
{
447
635
    ZYAN_ASSERT(formatter);
448
635
    ZYAN_ASSERT(buffer);
449
635
    ZYAN_ASSERT(context);
450
451
635
    ZyanU64 address;
452
635
    ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand, 0, &address));
453
454
635
    ZyanU8 padding = (formatter->addr_padding_relative ==
455
635
        ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->addr_padding_relative;
456
635
    if ((formatter->addr_padding_relative == ZYDIS_PADDING_AUTO) &&
457
145
        (formatter->addr_base == ZYDIS_NUMERIC_BASE_HEX))
458
88
    {
459
88
        switch (context->instruction->address_width)
460
88
        {
461
27
        case 16:
462
27
            padding =  4;
463
27
            address = (ZyanU16)address;
464
27
            break;
465
40
        case 32:
466
40
            padding =  8;
467
40
            address = (ZyanU32)address;
468
40
            break;
469
21
        case 64:
470
21
            padding = 16;
471
21
            break;
472
0
        default:
473
0
            return ZYAN_STATUS_INVALID_ARGUMENT;
474
88
        }
475
88
    }
476
477
635
    ZYDIS_BUFFER_APPEND(buffer, ADDR_RELATIVE);
478
607
    ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->addr_base, &buffer->string, address, padding,
479
607
        formatter->hex_force_leading_number, ZYAN_TRUE);
480
481
390
    return ZYAN_STATUS_SUCCESS;
482
607
}
483
484
/* ---------------------------------------------------------------------------------------------- */
485
486
/* ============================================================================================== */