output: aout -- Use nasm_x_space helpers
[nasm.git] / disasm.c
blob5e3a5e5c269cf7e3a439485d798ec5b743058ee9
1 /* ----------------------------------------------------------------------- *
2 *
3 * Copyright 1996-2012 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
34 /*
35 * disasm.c where all the _work_ gets done in the Netwide Disassembler
38 #include "compiler.h"
40 #include <stdio.h>
41 #include <string.h>
42 #include <limits.h>
43 #include <inttypes.h>
45 #include "nasm.h"
46 #include "disasm.h"
47 #include "sync.h"
48 #include "insns.h"
49 #include "tables.h"
50 #include "regdis.h"
51 #include "disp8.h"
54 * Flags that go into the `segment' field of `insn' structures
55 * during disassembly.
57 #define SEG_RELATIVE 1
58 #define SEG_32BIT 2
59 #define SEG_RMREG 4
60 #define SEG_DISP8 8
61 #define SEG_DISP16 16
62 #define SEG_DISP32 32
63 #define SEG_NODISP 64
64 #define SEG_SIGNED 128
65 #define SEG_64BIT 256
68 * Prefix information
70 struct prefix_info {
71 uint8_t osize; /* Operand size */
72 uint8_t asize; /* Address size */
73 uint8_t osp; /* Operand size prefix present */
74 uint8_t asp; /* Address size prefix present */
75 uint8_t rep; /* Rep prefix present */
76 uint8_t seg; /* Segment override prefix present */
77 uint8_t wait; /* WAIT "prefix" present */
78 uint8_t lock; /* Lock prefix present */
79 uint8_t vex[3]; /* VEX prefix present */
80 uint8_t vex_c; /* VEX "class" (VEX, XOP, ...) */
81 uint8_t vex_m; /* VEX.M field */
82 uint8_t vex_v;
83 uint8_t vex_lp; /* VEX.LP fields */
84 uint32_t rex; /* REX prefix present */
85 uint8_t evex[3]; /* EVEX prefix present */
88 #define getu8(x) (*(uint8_t *)(x))
89 #if X86_MEMORY
90 /* Littleendian CPU which can handle unaligned references */
91 #define getu16(x) (*(uint16_t *)(x))
92 #define getu32(x) (*(uint32_t *)(x))
93 #define getu64(x) (*(uint64_t *)(x))
94 #else
95 static uint16_t getu16(uint8_t *data)
97 return (uint16_t)data[0] + ((uint16_t)data[1] << 8);
99 static uint32_t getu32(uint8_t *data)
101 return (uint32_t)getu16(data) + ((uint32_t)getu16(data+2) << 16);
103 static uint64_t getu64(uint8_t *data)
105 return (uint64_t)getu32(data) + ((uint64_t)getu32(data+4) << 32);
107 #endif
109 #define gets8(x) ((int8_t)getu8(x))
110 #define gets16(x) ((int16_t)getu16(x))
111 #define gets32(x) ((int32_t)getu32(x))
112 #define gets64(x) ((int64_t)getu64(x))
114 /* Important: regval must already have been adjusted for rex extensions */
115 static enum reg_enum whichreg(opflags_t regflags, int regval, int rex)
117 size_t i;
119 static const struct {
120 opflags_t flags;
121 enum reg_enum reg;
122 } specific_registers[] = {
123 {REG_AL, R_AL},
124 {REG_AX, R_AX},
125 {REG_EAX, R_EAX},
126 {REG_RAX, R_RAX},
127 {REG_DL, R_DL},
128 {REG_DX, R_DX},
129 {REG_EDX, R_EDX},
130 {REG_RDX, R_RDX},
131 {REG_CL, R_CL},
132 {REG_CX, R_CX},
133 {REG_ECX, R_ECX},
134 {REG_RCX, R_RCX},
135 {FPU0, R_ST0},
136 {XMM0, R_XMM0},
137 {YMM0, R_YMM0},
138 {ZMM0, R_ZMM0},
139 {REG_ES, R_ES},
140 {REG_CS, R_CS},
141 {REG_SS, R_SS},
142 {REG_DS, R_DS},
143 {REG_FS, R_FS},
144 {REG_GS, R_GS},
145 {OPMASK0, R_K0},
148 if (!(regflags & (REGISTER|REGMEM)))
149 return 0; /* Registers not permissible?! */
151 regflags |= REGISTER;
153 for (i = 0; i < ARRAY_SIZE(specific_registers); i++)
154 if (!(specific_registers[i].flags & ~regflags))
155 return specific_registers[i].reg;
157 /* All the entries below look up regval in an 16-entry array */
158 if (regval < 0 || regval > (rex & REX_EV ? 31 : 15))
159 return 0;
161 #define GET_REGISTER(__array, __index) \
162 ((size_t)(__index) < (size_t)ARRAY_SIZE(__array) ? __array[(__index)] : 0)
164 if (!(REG8 & ~regflags)) {
165 if (rex & (REX_P|REX_NH))
166 return GET_REGISTER(nasm_rd_reg8_rex, regval);
167 else
168 return GET_REGISTER(nasm_rd_reg8, regval);
170 if (!(REG16 & ~regflags))
171 return GET_REGISTER(nasm_rd_reg16, regval);
172 if (!(REG32 & ~regflags))
173 return GET_REGISTER(nasm_rd_reg32, regval);
174 if (!(REG64 & ~regflags))
175 return GET_REGISTER(nasm_rd_reg64, regval);
176 if (!(REG_SREG & ~regflags))
177 return GET_REGISTER(nasm_rd_sreg, regval & 7); /* Ignore REX */
178 if (!(REG_CREG & ~regflags))
179 return GET_REGISTER(nasm_rd_creg, regval);
180 if (!(REG_DREG & ~regflags))
181 return GET_REGISTER(nasm_rd_dreg, regval);
182 if (!(REG_TREG & ~regflags)) {
183 if (regval > 7)
184 return 0; /* TR registers are ill-defined with rex */
185 return GET_REGISTER(nasm_rd_treg, regval);
187 if (!(FPUREG & ~regflags))
188 return GET_REGISTER(nasm_rd_fpureg, regval & 7); /* Ignore REX */
189 if (!(MMXREG & ~regflags))
190 return GET_REGISTER(nasm_rd_mmxreg, regval & 7); /* Ignore REX */
191 if (!(XMMREG & ~regflags))
192 return GET_REGISTER(nasm_rd_xmmreg, regval);
193 if (!(YMMREG & ~regflags))
194 return GET_REGISTER(nasm_rd_ymmreg, regval);
195 if (!(ZMMREG & ~regflags))
196 return GET_REGISTER(nasm_rd_zmmreg, regval);
197 if (!(OPMASKREG & ~regflags))
198 return GET_REGISTER(nasm_rd_opmaskreg, regval);
199 if (!(BNDREG & ~regflags))
200 return GET_REGISTER(nasm_rd_bndreg, regval);
202 #undef GET_REGISTER
203 return 0;
206 static uint32_t append_evex_reg_deco(char *buf, uint32_t num,
207 decoflags_t deco, uint8_t *evex)
209 const char * const er_names[] = {"rn-sae", "rd-sae", "ru-sae", "rz-sae"};
210 uint32_t num_chars = 0;
212 if ((deco & MASK) && (evex[2] & EVEX_P2AAA)) {
213 enum reg_enum opmasknum = nasm_rd_opmaskreg[evex[2] & EVEX_P2AAA];
214 const char * regname = nasm_reg_names[opmasknum - EXPR_REG_START];
216 num_chars += snprintf(buf + num_chars, num - num_chars,
217 "{%s}", regname);
219 if ((deco & Z) && (evex[2] & EVEX_P2Z)) {
220 num_chars += snprintf(buf + num_chars, num - num_chars,
221 "{z}");
225 if (evex[2] & EVEX_P2B) {
226 if (deco & ER) {
227 uint8_t er_type = (evex[2] & EVEX_P2LL) >> 5;
228 num_chars += snprintf(buf + num_chars, num - num_chars,
229 ",{%s}", er_names[er_type]);
230 } else if (deco & SAE) {
231 num_chars += snprintf(buf + num_chars, num - num_chars,
232 ",{sae}");
236 return num_chars;
239 static uint32_t append_evex_mem_deco(char *buf, uint32_t num, opflags_t type,
240 decoflags_t deco, uint8_t *evex)
242 uint32_t num_chars = 0;
244 if ((evex[2] & EVEX_P2B) && (deco & BRDCAST_MASK)) {
245 decoflags_t deco_brsize = deco & BRSIZE_MASK;
246 opflags_t template_opsize = (deco_brsize == BR_BITS32 ? BITS32 : BITS64);
247 uint8_t br_num = (type & SIZE_MASK) / BITS128 *
248 BITS64 / template_opsize * 2;
250 num_chars += snprintf(buf + num_chars, num - num_chars,
251 "{1to%d}", br_num);
254 if ((deco & MASK) && (evex[2] & EVEX_P2AAA)) {
255 enum reg_enum opmasknum = nasm_rd_opmaskreg[evex[2] & EVEX_P2AAA];
256 const char * regname = nasm_reg_names[opmasknum - EXPR_REG_START];
258 num_chars += snprintf(buf + num_chars, num - num_chars,
259 "{%s}", regname);
261 if ((deco & Z) && (evex[2] & EVEX_P2Z)) {
262 num_chars += snprintf(buf + num_chars, num - num_chars,
263 "{z}");
268 return num_chars;
272 * Process an effective address (ModRM) specification.
274 static uint8_t *do_ea(uint8_t *data, int modrm, int asize,
275 int segsize, enum ea_type type,
276 operand *op, insn *ins)
278 int mod, rm, scale, index, base;
279 int rex;
280 uint8_t *evex;
281 uint8_t sib = 0;
282 bool is_evex = !!(ins->rex & REX_EV);
284 mod = (modrm >> 6) & 03;
285 rm = modrm & 07;
287 if (mod != 3 && asize != 16 && rm == 4)
288 sib = *data++;
290 rex = ins->rex;
291 evex = ins->evex_p;
293 if (mod == 3) { /* pure register version */
294 op->basereg = rm+(rex & REX_B ? 8 : 0);
295 op->segment |= SEG_RMREG;
296 if (is_evex && segsize == 64) {
297 op->basereg += (evex[0] & EVEX_P0X ? 0 : 16);
299 return data;
302 op->disp_size = 0;
303 op->eaflags = 0;
305 if (asize == 16) {
307 * <mod> specifies the displacement size (none, byte or
308 * word), and <rm> specifies the register combination.
309 * Exception: mod=0,rm=6 does not specify [BP] as one might
310 * expect, but instead specifies [disp16].
313 if (type != EA_SCALAR)
314 return NULL;
316 op->indexreg = op->basereg = -1;
317 op->scale = 1; /* always, in 16 bits */
318 switch (rm) {
319 case 0:
320 op->basereg = R_BX;
321 op->indexreg = R_SI;
322 break;
323 case 1:
324 op->basereg = R_BX;
325 op->indexreg = R_DI;
326 break;
327 case 2:
328 op->basereg = R_BP;
329 op->indexreg = R_SI;
330 break;
331 case 3:
332 op->basereg = R_BP;
333 op->indexreg = R_DI;
334 break;
335 case 4:
336 op->basereg = R_SI;
337 break;
338 case 5:
339 op->basereg = R_DI;
340 break;
341 case 6:
342 op->basereg = R_BP;
343 break;
344 case 7:
345 op->basereg = R_BX;
346 break;
348 if (rm == 6 && mod == 0) { /* special case */
349 op->basereg = -1;
350 if (segsize != 16)
351 op->disp_size = 16;
352 mod = 2; /* fake disp16 */
354 switch (mod) {
355 case 0:
356 op->segment |= SEG_NODISP;
357 break;
358 case 1:
359 op->segment |= SEG_DISP8;
360 if (ins->evex_tuple != 0) {
361 op->offset = gets8(data) * get_disp8N(ins);
362 } else {
363 op->offset = gets8(data);
365 data++;
366 break;
367 case 2:
368 op->segment |= SEG_DISP16;
369 op->offset = *data++;
370 op->offset |= ((unsigned)*data++) << 8;
371 break;
373 return data;
374 } else {
376 * Once again, <mod> specifies displacement size (this time
377 * none, byte or *dword*), while <rm> specifies the base
378 * register. Again, [EBP] is missing, replaced by a pure
379 * disp32 (this time that's mod=0,rm=*5*) in 32-bit mode,
380 * and RIP-relative addressing in 64-bit mode.
382 * However, rm=4
383 * indicates not a single base register, but instead the
384 * presence of a SIB byte...
386 int a64 = asize == 64;
388 op->indexreg = -1;
390 if (a64)
391 op->basereg = nasm_rd_reg64[rm | ((rex & REX_B) ? 8 : 0)];
392 else
393 op->basereg = nasm_rd_reg32[rm | ((rex & REX_B) ? 8 : 0)];
395 if (rm == 5 && mod == 0) {
396 if (segsize == 64) {
397 op->eaflags |= EAF_REL;
398 op->segment |= SEG_RELATIVE;
399 mod = 2; /* fake disp32 */
402 if (asize != 64)
403 op->disp_size = asize;
405 op->basereg = -1;
406 mod = 2; /* fake disp32 */
410 if (rm == 4) { /* process SIB */
411 uint8_t vsib_hi = 0;
412 scale = (sib >> 6) & 03;
413 index = (sib >> 3) & 07;
414 base = sib & 07;
416 op->scale = 1 << scale;
418 if (segsize == 64) {
419 vsib_hi = (rex & REX_X ? 8 : 0) |
420 (evex[2] & EVEX_P2VP ? 0 : 16);
423 if (type == EA_XMMVSIB)
424 op->indexreg = nasm_rd_xmmreg[index | vsib_hi];
425 else if (type == EA_YMMVSIB)
426 op->indexreg = nasm_rd_ymmreg[index | vsib_hi];
427 else if (type == EA_ZMMVSIB)
428 op->indexreg = nasm_rd_zmmreg[index | vsib_hi];
429 else if (index == 4 && !(rex & REX_X))
430 op->indexreg = -1; /* ESP/RSP cannot be an index */
431 else if (a64)
432 op->indexreg = nasm_rd_reg64[index | ((rex & REX_X) ? 8 : 0)];
433 else
434 op->indexreg = nasm_rd_reg32[index | ((rex & REX_X) ? 8 : 0)];
436 if (base == 5 && mod == 0) {
437 op->basereg = -1;
438 mod = 2; /* Fake disp32 */
439 } else if (a64)
440 op->basereg = nasm_rd_reg64[base | ((rex & REX_B) ? 8 : 0)];
441 else
442 op->basereg = nasm_rd_reg32[base | ((rex & REX_B) ? 8 : 0)];
444 if (segsize == 16)
445 op->disp_size = 32;
446 } else if (type != EA_SCALAR) {
447 /* Can't have VSIB without SIB */
448 return NULL;
451 switch (mod) {
452 case 0:
453 op->segment |= SEG_NODISP;
454 break;
455 case 1:
456 op->segment |= SEG_DISP8;
457 if (ins->evex_tuple != 0) {
458 op->offset = gets8(data) * get_disp8N(ins);
459 } else {
460 op->offset = gets8(data);
462 data++;
463 break;
464 case 2:
465 op->segment |= SEG_DISP32;
466 op->offset = gets32(data);
467 data += 4;
468 break;
470 return data;
475 * Determine whether the instruction template in t corresponds to the data
476 * stream in data. Return the number of bytes matched if so.
478 #define case4(x) case (x): case (x)+1: case (x)+2: case (x)+3
480 static int matches(const struct itemplate *t, uint8_t *data,
481 const struct prefix_info *prefix, int segsize, insn *ins)
483 uint8_t *r = (uint8_t *)(t->code);
484 uint8_t *origdata = data;
485 bool a_used = false, o_used = false;
486 enum prefixes drep = 0;
487 enum prefixes dwait = 0;
488 uint8_t lock = prefix->lock;
489 int osize = prefix->osize;
490 int asize = prefix->asize;
491 int i, c;
492 int op1, op2;
493 struct operand *opx, *opy;
494 uint8_t opex = 0;
495 bool vex_ok = false;
496 int regmask = (segsize == 64) ? 15 : 7;
497 enum ea_type eat = EA_SCALAR;
499 for (i = 0; i < MAX_OPERANDS; i++) {
500 ins->oprs[i].segment = ins->oprs[i].disp_size =
501 (segsize == 64 ? SEG_64BIT : segsize == 32 ? SEG_32BIT : 0);
503 ins->condition = -1;
504 ins->evex_tuple = 0;
505 ins->rex = prefix->rex;
506 memset(ins->prefixes, 0, sizeof ins->prefixes);
508 if (itemp_has(t, (segsize == 64 ? IF_NOLONG : IF_LONG)))
509 return 0;
511 if (prefix->rep == 0xF2)
512 drep = (itemp_has(t, IF_BND) ? P_BND : P_REPNE);
513 else if (prefix->rep == 0xF3)
514 drep = P_REP;
516 dwait = prefix->wait ? P_WAIT : 0;
518 while ((c = *r++) != 0) {
519 op1 = (c & 3) + ((opex & 1) << 2);
520 op2 = ((c >> 3) & 3) + ((opex & 2) << 1);
521 opx = &ins->oprs[op1];
522 opy = &ins->oprs[op2];
523 opex = 0;
525 switch (c) {
526 case 01:
527 case 02:
528 case 03:
529 case 04:
530 while (c--)
531 if (*r++ != *data++)
532 return 0;
533 break;
535 case 05:
536 case 06:
537 case 07:
538 opex = c;
539 break;
541 case4(010):
543 int t = *r++, d = *data++;
544 if (d < t || d > t + 7)
545 return 0;
546 else {
547 opx->basereg = (d-t)+
548 (ins->rex & REX_B ? 8 : 0);
549 opx->segment |= SEG_RMREG;
551 break;
554 case4(014):
555 /* this is an separate index reg position of MIB operand (ICC) */
556 /* Disassembler uses NASM's split EA form only */
557 break;
559 case4(0274):
560 opx->offset = (int8_t)*data++;
561 opx->segment |= SEG_SIGNED;
562 break;
564 case4(020):
565 opx->offset = *data++;
566 break;
568 case4(024):
569 opx->offset = *data++;
570 break;
572 case4(030):
573 opx->offset = getu16(data);
574 data += 2;
575 break;
577 case4(034):
578 if (osize == 32) {
579 opx->offset = getu32(data);
580 data += 4;
581 } else {
582 opx->offset = getu16(data);
583 data += 2;
585 if (segsize != asize)
586 opx->disp_size = asize;
587 break;
589 case4(040):
590 opx->offset = getu32(data);
591 data += 4;
592 break;
594 case4(0254):
595 opx->offset = gets32(data);
596 data += 4;
597 break;
599 case4(044):
600 switch (asize) {
601 case 16:
602 opx->offset = getu16(data);
603 data += 2;
604 if (segsize != 16)
605 opx->disp_size = 16;
606 break;
607 case 32:
608 opx->offset = getu32(data);
609 data += 4;
610 if (segsize == 16)
611 opx->disp_size = 32;
612 break;
613 case 64:
614 opx->offset = getu64(data);
615 opx->disp_size = 64;
616 data += 8;
617 break;
619 break;
621 case4(050):
622 opx->offset = gets8(data++);
623 opx->segment |= SEG_RELATIVE;
624 break;
626 case4(054):
627 opx->offset = getu64(data);
628 data += 8;
629 break;
631 case4(060):
632 opx->offset = gets16(data);
633 data += 2;
634 opx->segment |= SEG_RELATIVE;
635 opx->segment &= ~SEG_32BIT;
636 break;
638 case4(064): /* rel */
639 opx->segment |= SEG_RELATIVE;
640 /* In long mode rel is always 32 bits, sign extended. */
641 if (segsize == 64 || osize == 32) {
642 opx->offset = gets32(data);
643 data += 4;
644 if (segsize != 64)
645 opx->segment |= SEG_32BIT;
646 opx->type = (opx->type & ~SIZE_MASK)
647 | (segsize == 64 ? BITS64 : BITS32);
648 } else {
649 opx->offset = gets16(data);
650 data += 2;
651 opx->segment &= ~SEG_32BIT;
652 opx->type = (opx->type & ~SIZE_MASK) | BITS16;
654 break;
656 case4(070):
657 opx->offset = gets32(data);
658 data += 4;
659 opx->segment |= SEG_32BIT | SEG_RELATIVE;
660 break;
662 case4(0100):
663 case4(0110):
664 case4(0120):
665 case4(0130):
667 int modrm = *data++;
668 opx->segment |= SEG_RMREG;
669 data = do_ea(data, modrm, asize, segsize, eat, opy, ins);
670 if (!data)
671 return 0;
672 opx->basereg = ((modrm >> 3) & 7) + (ins->rex & REX_R ? 8 : 0);
673 if ((ins->rex & REX_EV) && (segsize == 64))
674 opx->basereg += (ins->evex_p[0] & EVEX_P0RP ? 0 : 16);
675 break;
678 case 0172:
680 uint8_t ximm = *data++;
681 c = *r++;
682 ins->oprs[c >> 3].basereg = (ximm >> 4) & regmask;
683 ins->oprs[c >> 3].segment |= SEG_RMREG;
684 ins->oprs[c & 7].offset = ximm & 15;
686 break;
688 case 0173:
690 uint8_t ximm = *data++;
691 c = *r++;
693 if ((c ^ ximm) & 15)
694 return 0;
696 ins->oprs[c >> 4].basereg = (ximm >> 4) & regmask;
697 ins->oprs[c >> 4].segment |= SEG_RMREG;
699 break;
701 case4(0174):
703 uint8_t ximm = *data++;
705 opx->basereg = (ximm >> 4) & regmask;
706 opx->segment |= SEG_RMREG;
708 break;
710 case4(0200):
711 case4(0204):
712 case4(0210):
713 case4(0214):
714 case4(0220):
715 case4(0224):
716 case4(0230):
717 case4(0234):
719 int modrm = *data++;
720 if (((modrm >> 3) & 07) != (c & 07))
721 return 0; /* spare field doesn't match up */
722 data = do_ea(data, modrm, asize, segsize, eat, opy, ins);
723 if (!data)
724 return 0;
725 break;
728 case4(0240):
729 case 0250:
731 uint8_t evexm = *r++;
732 uint8_t evexwlp = *r++;
733 uint8_t modrm, valid_mask;
734 ins->evex_tuple = *r++ - 0300;
735 modrm = *(origdata + 1);
737 ins->rex |= REX_EV;
738 if ((prefix->rex & (REX_EV|REX_V|REX_P)) != REX_EV)
739 return 0;
741 if ((evexm & 0x1f) != prefix->vex_m)
742 return 0;
744 switch (evexwlp & 060) {
745 case 000:
746 if (prefix->rex & REX_W)
747 return 0;
748 break;
749 case 020:
750 if (!(prefix->rex & REX_W))
751 return 0;
752 ins->rex |= REX_W;
753 break;
754 case 040: /* VEX.W is a don't care */
755 ins->rex &= ~REX_W;
756 break;
757 case 060:
758 break;
761 /* If EVEX.b is set with reg-reg op,
762 * EVEX.L'L contains embedded rounding control info
764 if ((prefix->evex[2] & EVEX_P2B) && ((modrm >> 6) == 3)) {
765 valid_mask = 0x3; /* prefix only */
766 } else {
767 valid_mask = 0xf; /* vector length and prefix */
769 if ((evexwlp ^ prefix->vex_lp) & valid_mask)
770 return 0;
772 if (c == 0250) {
773 if ((prefix->vex_v != 0) ||
774 (!(prefix->evex[2] & EVEX_P2VP) &&
775 ((eat < EA_XMMVSIB) || (eat > EA_ZMMVSIB))))
776 return 0;
777 } else {
778 opx->segment |= SEG_RMREG;
779 opx->basereg = ((~prefix->evex[2] & EVEX_P2VP) << (4 - 3) ) |
780 prefix->vex_v;
782 vex_ok = true;
783 memcpy(ins->evex_p, prefix->evex, 3);
784 break;
787 case4(0260):
788 case 0270:
790 int vexm = *r++;
791 int vexwlp = *r++;
793 ins->rex |= REX_V;
794 if ((prefix->rex & (REX_V|REX_P)) != REX_V)
795 return 0;
797 if ((vexm & 0x1f) != prefix->vex_m)
798 return 0;
800 switch (vexwlp & 060) {
801 case 000:
802 if (prefix->rex & REX_W)
803 return 0;
804 break;
805 case 020:
806 if (!(prefix->rex & REX_W))
807 return 0;
808 ins->rex &= ~REX_W;
809 break;
810 case 040: /* VEX.W is a don't care */
811 ins->rex &= ~REX_W;
812 break;
813 case 060:
814 break;
817 /* The 010 bit of vexwlp is set if VEX.L is ignored */
818 if ((vexwlp ^ prefix->vex_lp) & ((vexwlp & 010) ? 03 : 07))
819 return 0;
821 if (c == 0270) {
822 if (prefix->vex_v != 0)
823 return 0;
824 } else {
825 opx->segment |= SEG_RMREG;
826 opx->basereg = prefix->vex_v;
828 vex_ok = true;
829 break;
832 case 0271:
833 if (prefix->rep == 0xF3)
834 drep = P_XRELEASE;
835 break;
837 case 0272:
838 if (prefix->rep == 0xF2)
839 drep = P_XACQUIRE;
840 else if (prefix->rep == 0xF3)
841 drep = P_XRELEASE;
842 break;
844 case 0273:
845 if (prefix->lock == 0xF0) {
846 if (prefix->rep == 0xF2)
847 drep = P_XACQUIRE;
848 else if (prefix->rep == 0xF3)
849 drep = P_XRELEASE;
851 break;
853 case 0310:
854 if (asize != 16)
855 return 0;
856 else
857 a_used = true;
858 break;
860 case 0311:
861 if (asize != 32)
862 return 0;
863 else
864 a_used = true;
865 break;
867 case 0312:
868 if (asize != segsize)
869 return 0;
870 else
871 a_used = true;
872 break;
874 case 0313:
875 if (asize != 64)
876 return 0;
877 else
878 a_used = true;
879 break;
881 case 0314:
882 if (prefix->rex & REX_B)
883 return 0;
884 break;
886 case 0315:
887 if (prefix->rex & REX_X)
888 return 0;
889 break;
891 case 0316:
892 if (prefix->rex & REX_R)
893 return 0;
894 break;
896 case 0317:
897 if (prefix->rex & REX_W)
898 return 0;
899 break;
901 case 0320:
902 if (osize != 16)
903 return 0;
904 else
905 o_used = true;
906 break;
908 case 0321:
909 if (osize != 32)
910 return 0;
911 else
912 o_used = true;
913 break;
915 case 0322:
916 if (osize != (segsize == 16) ? 16 : 32)
917 return 0;
918 else
919 o_used = true;
920 break;
922 case 0323:
923 ins->rex |= REX_W; /* 64-bit only instruction */
924 osize = 64;
925 o_used = true;
926 break;
928 case 0324:
929 if (osize != 64)
930 return 0;
931 o_used = true;
932 break;
934 case 0325:
935 ins->rex |= REX_NH;
936 break;
938 case 0330:
940 int t = *r++, d = *data++;
941 if (d < t || d > t + 15)
942 return 0;
943 else
944 ins->condition = d - t;
945 break;
948 case 0326:
949 if (prefix->rep == 0xF3)
950 return 0;
951 break;
953 case 0331:
954 if (prefix->rep)
955 return 0;
956 break;
958 case 0332:
959 if (prefix->rep != 0xF2)
960 return 0;
961 drep = 0;
962 break;
964 case 0333:
965 if (prefix->rep != 0xF3)
966 return 0;
967 drep = 0;
968 break;
970 case 0334:
971 if (lock) {
972 ins->rex |= REX_R;
973 lock = 0;
975 break;
977 case 0335:
978 if (drep == P_REP)
979 drep = P_REPE;
980 break;
982 case 0336:
983 case 0337:
984 break;
986 case 0340:
987 return 0;
989 case 0341:
990 if (prefix->wait != 0x9B)
991 return 0;
992 dwait = 0;
993 break;
995 case 0360:
996 if (prefix->osp || prefix->rep)
997 return 0;
998 break;
1000 case 0361:
1001 if (!prefix->osp || prefix->rep)
1002 return 0;
1003 o_used = true;
1004 break;
1006 case 0364:
1007 if (prefix->osp)
1008 return 0;
1009 break;
1011 case 0365:
1012 if (prefix->asp)
1013 return 0;
1014 break;
1016 case 0366:
1017 if (!prefix->osp)
1018 return 0;
1019 o_used = true;
1020 break;
1022 case 0367:
1023 if (!prefix->asp)
1024 return 0;
1025 a_used = true;
1026 break;
1028 case 0370:
1029 case 0371:
1030 break;
1032 case 0374:
1033 eat = EA_XMMVSIB;
1034 break;
1036 case 0375:
1037 eat = EA_YMMVSIB;
1038 break;
1040 case 0376:
1041 eat = EA_ZMMVSIB;
1042 break;
1044 default:
1045 return 0; /* Unknown code */
1049 if (!vex_ok && (ins->rex & (REX_V | REX_EV)))
1050 return 0;
1052 /* REX cannot be combined with VEX */
1053 if ((ins->rex & REX_V) && (prefix->rex & REX_P))
1054 return 0;
1057 * Check for unused rep or a/o prefixes.
1059 for (i = 0; i < t->operands; i++) {
1060 if (ins->oprs[i].segment != SEG_RMREG)
1061 a_used = true;
1064 if (lock) {
1065 if (ins->prefixes[PPS_LOCK])
1066 return 0;
1067 ins->prefixes[PPS_LOCK] = P_LOCK;
1069 if (drep) {
1070 if (ins->prefixes[PPS_REP])
1071 return 0;
1072 ins->prefixes[PPS_REP] = drep;
1074 ins->prefixes[PPS_WAIT] = dwait;
1075 if (!o_used) {
1076 if (osize != ((segsize == 16) ? 16 : 32)) {
1077 enum prefixes pfx = 0;
1079 switch (osize) {
1080 case 16:
1081 pfx = P_O16;
1082 break;
1083 case 32:
1084 pfx = P_O32;
1085 break;
1086 case 64:
1087 pfx = P_O64;
1088 break;
1091 if (ins->prefixes[PPS_OSIZE])
1092 return 0;
1093 ins->prefixes[PPS_OSIZE] = pfx;
1096 if (!a_used && asize != segsize) {
1097 if (ins->prefixes[PPS_ASIZE])
1098 return 0;
1099 ins->prefixes[PPS_ASIZE] = asize == 16 ? P_A16 : P_A32;
1102 /* Fix: check for redundant REX prefixes */
1104 return data - origdata;
1107 /* Condition names for disassembly, sorted by x86 code */
1108 static const char * const condition_name[16] = {
1109 "o", "no", "c", "nc", "z", "nz", "na", "a",
1110 "s", "ns", "pe", "po", "l", "nl", "ng", "g"
1113 int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
1114 int32_t offset, int autosync, iflag_t *prefer)
1116 const struct itemplate * const *p, * const *best_p;
1117 const struct disasm_index *ix;
1118 uint8_t *dp;
1119 int length, best_length = 0;
1120 char *segover;
1121 int i, slen, colon, n;
1122 uint8_t *origdata;
1123 int works;
1124 insn tmp_ins, ins;
1125 iflag_t goodness, best;
1126 int best_pref;
1127 struct prefix_info prefix;
1128 bool end_prefix;
1129 bool is_evex;
1131 memset(&ins, 0, sizeof ins);
1134 * Scan for prefixes.
1136 memset(&prefix, 0, sizeof prefix);
1137 prefix.asize = segsize;
1138 prefix.osize = (segsize == 64) ? 32 : segsize;
1139 segover = NULL;
1140 origdata = data;
1142 ix = itable;
1144 end_prefix = false;
1145 while (!end_prefix) {
1146 switch (*data) {
1147 case 0xF2:
1148 case 0xF3:
1149 prefix.rep = *data++;
1150 break;
1152 case 0x9B:
1153 prefix.wait = *data++;
1154 break;
1156 case 0xF0:
1157 prefix.lock = *data++;
1158 break;
1160 case 0x2E:
1161 segover = "cs", prefix.seg = *data++;
1162 break;
1163 case 0x36:
1164 segover = "ss", prefix.seg = *data++;
1165 break;
1166 case 0x3E:
1167 segover = "ds", prefix.seg = *data++;
1168 break;
1169 case 0x26:
1170 segover = "es", prefix.seg = *data++;
1171 break;
1172 case 0x64:
1173 segover = "fs", prefix.seg = *data++;
1174 break;
1175 case 0x65:
1176 segover = "gs", prefix.seg = *data++;
1177 break;
1179 case 0x66:
1180 prefix.osize = (segsize == 16) ? 32 : 16;
1181 prefix.osp = *data++;
1182 break;
1183 case 0x67:
1184 prefix.asize = (segsize == 32) ? 16 : 32;
1185 prefix.asp = *data++;
1186 break;
1188 case 0xC4:
1189 case 0xC5:
1190 if (segsize == 64 || (data[1] & 0xc0) == 0xc0) {
1191 prefix.vex[0] = *data++;
1192 prefix.vex[1] = *data++;
1194 prefix.rex = REX_V;
1195 prefix.vex_c = RV_VEX;
1197 if (prefix.vex[0] == 0xc4) {
1198 prefix.vex[2] = *data++;
1199 prefix.rex |= (~prefix.vex[1] >> 5) & 7; /* REX_RXB */
1200 prefix.rex |= (prefix.vex[2] >> (7-3)) & REX_W;
1201 prefix.vex_m = prefix.vex[1] & 0x1f;
1202 prefix.vex_v = (~prefix.vex[2] >> 3) & 15;
1203 prefix.vex_lp = prefix.vex[2] & 7;
1204 } else {
1205 prefix.rex |= (~prefix.vex[1] >> (7-2)) & REX_R;
1206 prefix.vex_m = 1;
1207 prefix.vex_v = (~prefix.vex[1] >> 3) & 15;
1208 prefix.vex_lp = prefix.vex[1] & 7;
1211 ix = itable_vex[RV_VEX][prefix.vex_m][prefix.vex_lp & 3];
1213 end_prefix = true;
1214 break;
1216 case 0x62:
1218 uint8_t evex_p0 = data[1] & 0x0f;
1219 if (segsize == 64 ||
1220 ((evex_p0 >= 0x01) && (evex_p0 <= 0x03))) {
1221 data++; /* 62h EVEX prefix */
1222 prefix.evex[0] = *data++;
1223 prefix.evex[1] = *data++;
1224 prefix.evex[2] = *data++;
1226 prefix.rex = REX_EV;
1227 prefix.vex_c = RV_EVEX;
1228 prefix.rex |= (~prefix.evex[0] >> 5) & 7; /* REX_RXB */
1229 prefix.rex |= (prefix.evex[1] >> (7-3)) & REX_W;
1230 prefix.vex_m = prefix.evex[0] & EVEX_P0MM;
1231 prefix.vex_v = (~prefix.evex[1] & EVEX_P1VVVV) >> 3;
1232 prefix.vex_lp = ((prefix.evex[2] & EVEX_P2LL) >> (5-2)) |
1233 (prefix.evex[1] & EVEX_P1PP);
1235 ix = itable_vex[prefix.vex_c][prefix.vex_m][prefix.vex_lp & 3];
1237 end_prefix = true;
1238 break;
1241 case 0x8F:
1242 if ((data[1] & 030) != 0 &&
1243 (segsize == 64 || (data[1] & 0xc0) == 0xc0)) {
1244 prefix.vex[0] = *data++;
1245 prefix.vex[1] = *data++;
1246 prefix.vex[2] = *data++;
1248 prefix.rex = REX_V;
1249 prefix.vex_c = RV_XOP;
1251 prefix.rex |= (~prefix.vex[1] >> 5) & 7; /* REX_RXB */
1252 prefix.rex |= (prefix.vex[2] >> (7-3)) & REX_W;
1253 prefix.vex_m = prefix.vex[1] & 0x1f;
1254 prefix.vex_v = (~prefix.vex[2] >> 3) & 15;
1255 prefix.vex_lp = prefix.vex[2] & 7;
1257 ix = itable_vex[RV_XOP][prefix.vex_m][prefix.vex_lp & 3];
1259 end_prefix = true;
1260 break;
1262 case REX_P + 0x0:
1263 case REX_P + 0x1:
1264 case REX_P + 0x2:
1265 case REX_P + 0x3:
1266 case REX_P + 0x4:
1267 case REX_P + 0x5:
1268 case REX_P + 0x6:
1269 case REX_P + 0x7:
1270 case REX_P + 0x8:
1271 case REX_P + 0x9:
1272 case REX_P + 0xA:
1273 case REX_P + 0xB:
1274 case REX_P + 0xC:
1275 case REX_P + 0xD:
1276 case REX_P + 0xE:
1277 case REX_P + 0xF:
1278 if (segsize == 64) {
1279 prefix.rex = *data++;
1280 if (prefix.rex & REX_W)
1281 prefix.osize = 64;
1283 end_prefix = true;
1284 break;
1286 default:
1287 end_prefix = true;
1288 break;
1292 iflag_set_all(&best); /* Worst possible */
1293 best_p = NULL;
1294 best_pref = INT_MAX;
1296 if (!ix)
1297 return 0; /* No instruction table at all... */
1299 dp = data;
1300 ix += *dp++;
1301 while (ix->n == -1) {
1302 ix = (const struct disasm_index *)ix->p + *dp++;
1305 p = (const struct itemplate * const *)ix->p;
1306 for (n = ix->n; n; n--, p++) {
1307 if ((length = matches(*p, data, &prefix, segsize, &tmp_ins))) {
1308 works = true;
1310 * Final check to make sure the types of r/m match up.
1311 * XXX: Need to make sure this is actually correct.
1313 for (i = 0; i < (*p)->operands; i++) {
1314 if (
1315 /* If it's a mem-only EA but we have a
1316 register, die. */
1317 ((tmp_ins.oprs[i].segment & SEG_RMREG) &&
1318 is_class(MEMORY, (*p)->opd[i])) ||
1319 /* If it's a reg-only EA but we have a memory
1320 ref, die. */
1321 (!(tmp_ins.oprs[i].segment & SEG_RMREG) &&
1322 !(REG_EA & ~(*p)->opd[i]) &&
1323 !((*p)->opd[i] & REG_SMASK)) ||
1324 /* Register type mismatch (eg FS vs REG_DESS):
1325 die. */
1326 ((((*p)->opd[i] & (REGISTER | FPUREG)) ||
1327 (tmp_ins.oprs[i].segment & SEG_RMREG)) &&
1328 !whichreg((*p)->opd[i],
1329 tmp_ins.oprs[i].basereg, tmp_ins.rex))
1331 works = false;
1332 break;
1337 * Note: we always prefer instructions which incorporate
1338 * prefixes in the instructions themselves. This is to allow
1339 * e.g. PAUSE to be preferred to REP NOP, and deal with
1340 * MMX/SSE instructions where prefixes are used to select
1341 * between MMX and SSE register sets or outright opcode
1342 * selection.
1344 if (works) {
1345 int i, nprefix;
1346 goodness = iflag_pfmask(*p);
1347 goodness = iflag_xor(&goodness, prefer);
1348 nprefix = 0;
1349 for (i = 0; i < MAXPREFIX; i++)
1350 if (tmp_ins.prefixes[i])
1351 nprefix++;
1352 if (nprefix < best_pref ||
1353 (nprefix == best_pref &&
1354 iflag_cmp(&goodness, &best) < 0)) {
1355 /* This is the best one found so far */
1356 best = goodness;
1357 best_p = p;
1358 best_pref = nprefix;
1359 best_length = length;
1360 ins = tmp_ins;
1366 if (!best_p)
1367 return 0; /* no instruction was matched */
1369 /* Pick the best match */
1370 p = best_p;
1371 length = best_length;
1373 slen = 0;
1375 /* TODO: snprintf returns the value that the string would have if
1376 * the buffer were long enough, and not the actual length of
1377 * the returned string, so each instance of using the return
1378 * value of snprintf should actually be checked to assure that
1379 * the return value is "sane." Maybe a macro wrapper could
1380 * be used for that purpose.
1382 for (i = 0; i < MAXPREFIX; i++) {
1383 const char *prefix = prefix_name(ins.prefixes[i]);
1384 if (prefix)
1385 slen += snprintf(output+slen, outbufsize-slen, "%s ", prefix);
1388 i = (*p)->opcode;
1389 if (i >= FIRST_COND_OPCODE)
1390 slen += snprintf(output + slen, outbufsize - slen, "%s%s",
1391 nasm_insn_names[i], condition_name[ins.condition]);
1392 else
1393 slen += snprintf(output + slen, outbufsize - slen, "%s",
1394 nasm_insn_names[i]);
1396 colon = false;
1397 is_evex = !!(ins.rex & REX_EV);
1398 length += data - origdata; /* fix up for prefixes */
1399 for (i = 0; i < (*p)->operands; i++) {
1400 opflags_t t = (*p)->opd[i];
1401 decoflags_t deco = (*p)->deco[i];
1402 const operand *o = &ins.oprs[i];
1403 int64_t offs;
1405 output[slen++] = (colon ? ':' : i == 0 ? ' ' : ',');
1407 offs = o->offset;
1408 if (o->segment & SEG_RELATIVE) {
1409 offs += offset + length;
1411 * sort out wraparound
1413 if (!(o->segment & (SEG_32BIT|SEG_64BIT)))
1414 offs &= 0xffff;
1415 else if (segsize != 64)
1416 offs &= 0xffffffff;
1419 * add sync marker, if autosync is on
1421 if (autosync)
1422 add_sync(offs, 0L);
1425 if (t & COLON)
1426 colon = true;
1427 else
1428 colon = false;
1430 if ((t & (REGISTER | FPUREG)) ||
1431 (o->segment & SEG_RMREG)) {
1432 enum reg_enum reg;
1433 reg = whichreg(t, o->basereg, ins.rex);
1434 if (t & TO)
1435 slen += snprintf(output + slen, outbufsize - slen, "to ");
1436 slen += snprintf(output + slen, outbufsize - slen, "%s",
1437 nasm_reg_names[reg-EXPR_REG_START]);
1438 if (is_evex && deco)
1439 slen += append_evex_reg_deco(output + slen, outbufsize - slen,
1440 deco, ins.evex_p);
1441 } else if (!(UNITY & ~t)) {
1442 output[slen++] = '1';
1443 } else if (t & IMMEDIATE) {
1444 if (t & BITS8) {
1445 slen +=
1446 snprintf(output + slen, outbufsize - slen, "byte ");
1447 if (o->segment & SEG_SIGNED) {
1448 if (offs < 0) {
1449 offs *= -1;
1450 output[slen++] = '-';
1451 } else
1452 output[slen++] = '+';
1454 } else if (t & BITS16) {
1455 slen +=
1456 snprintf(output + slen, outbufsize - slen, "word ");
1457 } else if (t & BITS32) {
1458 slen +=
1459 snprintf(output + slen, outbufsize - slen, "dword ");
1460 } else if (t & BITS64) {
1461 slen +=
1462 snprintf(output + slen, outbufsize - slen, "qword ");
1463 } else if (t & NEAR) {
1464 slen +=
1465 snprintf(output + slen, outbufsize - slen, "near ");
1466 } else if (t & SHORT) {
1467 slen +=
1468 snprintf(output + slen, outbufsize - slen, "short ");
1470 slen +=
1471 snprintf(output + slen, outbufsize - slen, "0x%"PRIx64"",
1472 offs);
1473 } else if (!(MEM_OFFS & ~t)) {
1474 slen +=
1475 snprintf(output + slen, outbufsize - slen,
1476 "[%s%s%s0x%"PRIx64"]",
1477 (segover ? segover : ""),
1478 (segover ? ":" : ""),
1479 (o->disp_size == 64 ? "qword " :
1480 o->disp_size == 32 ? "dword " :
1481 o->disp_size == 16 ? "word " : ""), offs);
1482 segover = NULL;
1483 } else if (is_class(REGMEM, t)) {
1484 int started = false;
1485 if (t & BITS8)
1486 slen +=
1487 snprintf(output + slen, outbufsize - slen, "byte ");
1488 if (t & BITS16)
1489 slen +=
1490 snprintf(output + slen, outbufsize - slen, "word ");
1491 if (t & BITS32)
1492 slen +=
1493 snprintf(output + slen, outbufsize - slen, "dword ");
1494 if (t & BITS64)
1495 slen +=
1496 snprintf(output + slen, outbufsize - slen, "qword ");
1497 if (t & BITS80)
1498 slen +=
1499 snprintf(output + slen, outbufsize - slen, "tword ");
1500 if ((ins.evex_p[2] & EVEX_P2B) && (deco & BRDCAST_MASK)) {
1501 /* when broadcasting, each element size should be used */
1502 if (deco & BR_BITS32)
1503 slen +=
1504 snprintf(output + slen, outbufsize - slen, "dword ");
1505 else if (deco & BR_BITS64)
1506 slen +=
1507 snprintf(output + slen, outbufsize - slen, "qword ");
1508 } else {
1509 if (t & BITS128)
1510 slen +=
1511 snprintf(output + slen, outbufsize - slen, "oword ");
1512 if (t & BITS256)
1513 slen +=
1514 snprintf(output + slen, outbufsize - slen, "yword ");
1515 if (t & BITS512)
1516 slen +=
1517 snprintf(output + slen, outbufsize - slen, "zword ");
1519 if (t & FAR)
1520 slen += snprintf(output + slen, outbufsize - slen, "far ");
1521 if (t & NEAR)
1522 slen +=
1523 snprintf(output + slen, outbufsize - slen, "near ");
1524 output[slen++] = '[';
1525 if (o->disp_size)
1526 slen += snprintf(output + slen, outbufsize - slen, "%s",
1527 (o->disp_size == 64 ? "qword " :
1528 o->disp_size == 32 ? "dword " :
1529 o->disp_size == 16 ? "word " :
1530 ""));
1531 if (o->eaflags & EAF_REL)
1532 slen += snprintf(output + slen, outbufsize - slen, "rel ");
1533 if (segover) {
1534 slen +=
1535 snprintf(output + slen, outbufsize - slen, "%s:",
1536 segover);
1537 segover = NULL;
1539 if (o->basereg != -1) {
1540 slen += snprintf(output + slen, outbufsize - slen, "%s",
1541 nasm_reg_names[(o->basereg-EXPR_REG_START)]);
1542 started = true;
1544 if (o->indexreg != -1 && !itemp_has(*best_p, IF_MIB)) {
1545 if (started)
1546 output[slen++] = '+';
1547 slen += snprintf(output + slen, outbufsize - slen, "%s",
1548 nasm_reg_names[(o->indexreg-EXPR_REG_START)]);
1549 if (o->scale > 1)
1550 slen +=
1551 snprintf(output + slen, outbufsize - slen, "*%d",
1552 o->scale);
1553 started = true;
1557 if (o->segment & SEG_DISP8) {
1558 if (is_evex) {
1559 const char *prefix;
1560 uint32_t offset = offs;
1561 if ((int32_t)offset < 0) {
1562 prefix = "-";
1563 offset = -offset;
1564 } else {
1565 prefix = "+";
1567 slen +=
1568 snprintf(output + slen, outbufsize - slen, "%s0x%"PRIx32"",
1569 prefix, offset);
1570 } else {
1571 const char *prefix;
1572 uint8_t offset = offs;
1573 if ((int8_t)offset < 0) {
1574 prefix = "-";
1575 offset = -offset;
1576 } else {
1577 prefix = "+";
1579 slen +=
1580 snprintf(output + slen, outbufsize - slen, "%s0x%"PRIx8"",
1581 prefix, offset);
1583 } else if (o->segment & SEG_DISP16) {
1584 const char *prefix;
1585 uint16_t offset = offs;
1586 if ((int16_t)offset < 0 && started) {
1587 offset = -offset;
1588 prefix = "-";
1589 } else {
1590 prefix = started ? "+" : "";
1592 slen +=
1593 snprintf(output + slen, outbufsize - slen,
1594 "%s0x%"PRIx16"", prefix, offset);
1595 } else if (o->segment & SEG_DISP32) {
1596 if (prefix.asize == 64) {
1597 const char *prefix;
1598 uint64_t offset = (int64_t)(int32_t)offs;
1599 if ((int32_t)offs < 0 && started) {
1600 offset = -offset;
1601 prefix = "-";
1602 } else {
1603 prefix = started ? "+" : "";
1605 slen +=
1606 snprintf(output + slen, outbufsize - slen,
1607 "%s0x%"PRIx64"", prefix, offset);
1608 } else {
1609 const char *prefix;
1610 uint32_t offset = offs;
1611 if ((int32_t) offset < 0 && started) {
1612 offset = -offset;
1613 prefix = "-";
1614 } else {
1615 prefix = started ? "+" : "";
1617 slen +=
1618 snprintf(output + slen, outbufsize - slen,
1619 "%s0x%"PRIx32"", prefix, offset);
1623 if (o->indexreg != -1 && itemp_has(*best_p, IF_MIB)) {
1624 output[slen++] = ',';
1625 slen += snprintf(output + slen, outbufsize - slen, "%s",
1626 nasm_reg_names[(o->indexreg-EXPR_REG_START)]);
1627 if (o->scale > 1)
1628 slen +=
1629 snprintf(output + slen, outbufsize - slen, "*%d",
1630 o->scale);
1631 started = true;
1634 output[slen++] = ']';
1636 if (is_evex && deco)
1637 slen += append_evex_mem_deco(output + slen, outbufsize - slen,
1638 t, deco, ins.evex_p);
1639 } else {
1640 slen +=
1641 snprintf(output + slen, outbufsize - slen, "<operand%d>",
1645 output[slen] = '\0';
1646 if (segover) { /* unused segment override */
1647 char *p = output;
1648 int count = slen + 1;
1649 while (count--)
1650 p[count + 3] = p[count];
1651 strncpy(output, segover, 2);
1652 output[2] = ' ';
1654 return length;
1658 * This is called when we don't have a complete instruction. If it
1659 * is a standalone *single-byte* prefix show it as such, otherwise
1660 * print it as a literal.
1662 int32_t eatbyte(uint8_t *data, char *output, int outbufsize, int segsize)
1664 uint8_t byte = *data;
1665 const char *str = NULL;
1667 switch (byte) {
1668 case 0xF2:
1669 str = "repne";
1670 break;
1671 case 0xF3:
1672 str = "rep";
1673 break;
1674 case 0x9B:
1675 str = "wait";
1676 break;
1677 case 0xF0:
1678 str = "lock";
1679 break;
1680 case 0x2E:
1681 str = "cs";
1682 break;
1683 case 0x36:
1684 str = "ss";
1685 break;
1686 case 0x3E:
1687 str = "ss";
1688 break;
1689 case 0x26:
1690 str = "es";
1691 break;
1692 case 0x64:
1693 str = "fs";
1694 break;
1695 case 0x65:
1696 str = "gs";
1697 break;
1698 case 0x66:
1699 str = (segsize == 16) ? "o32" : "o16";
1700 break;
1701 case 0x67:
1702 str = (segsize == 32) ? "a16" : "a32";
1703 break;
1704 case REX_P + 0x0:
1705 case REX_P + 0x1:
1706 case REX_P + 0x2:
1707 case REX_P + 0x3:
1708 case REX_P + 0x4:
1709 case REX_P + 0x5:
1710 case REX_P + 0x6:
1711 case REX_P + 0x7:
1712 case REX_P + 0x8:
1713 case REX_P + 0x9:
1714 case REX_P + 0xA:
1715 case REX_P + 0xB:
1716 case REX_P + 0xC:
1717 case REX_P + 0xD:
1718 case REX_P + 0xE:
1719 case REX_P + 0xF:
1720 if (segsize == 64) {
1721 snprintf(output, outbufsize, "rex%s%s%s%s%s",
1722 (byte == REX_P) ? "" : ".",
1723 (byte & REX_W) ? "w" : "",
1724 (byte & REX_R) ? "r" : "",
1725 (byte & REX_X) ? "x" : "",
1726 (byte & REX_B) ? "b" : "");
1727 break;
1729 /* else fall through */
1730 default:
1731 snprintf(output, outbufsize, "db 0x%02x", byte);
1732 break;
1735 if (str)
1736 snprintf(output, outbufsize, "%s", str);
1738 return 1;