1 /* Helper routines for disassembler for x86/x86-64.
2 Copyright (C) 2007, 2008 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2007.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
9 * the GNU Lesser General Public License as published by the Free
10 Software Foundation; either version 3 of the License, or (at
11 your option) any later version
15 * the GNU General Public License as published by the Free
16 Software Foundation; either version 2 of the License, or (at
17 your option) any later version
19 or both in parallel, as here.
21 elfutils is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received copies of the GNU General Public License and
27 the GNU Lesser General Public License along with this program. If
28 not, see <http://www.gnu.org/licenses/>. */
38 /* The mnemonic. Especially encoded for the optimized table. */
39 unsigned int mnemonic : MNEMONIC_BITS;
41 /* The rep/repe prefixes. */
43 unsigned int repe : 1;
45 /* Mnemonic suffix. */
46 unsigned int suffix : SUFFIX_BITS;
48 /* Nonzero if the instruction uses modr/m. */
49 unsigned int modrm : 1;
52 unsigned int fct1 : FCT1_BITS;
54 unsigned int str1 : STR1_BITS;
56 unsigned int off1_1 : OFF1_1_BITS;
57 unsigned int off1_2 : OFF1_2_BITS;
58 unsigned int off1_3 : OFF1_3_BITS;
61 unsigned int fct2 : FCT2_BITS;
63 unsigned int str2 : STR2_BITS;
65 unsigned int off2_1 : OFF2_1_BITS;
66 unsigned int off2_2 : OFF2_2_BITS;
67 unsigned int off2_3 : OFF2_3_BITS;
70 unsigned int fct3 : FCT3_BITS;
72 unsigned int str3 : STR3_BITS;
74 unsigned int off3_1 : OFF3_1_BITS;
76 unsigned int off3_2 : OFF3_2_BITS;
79 unsigned int off3_3 : OFF3_3_BITS;
84 typedef int (*opfct_t) (struct output_data *);
88 data_prefix (struct output_data *d)
91 if (*d->prefixes & has_cs)
94 *d->prefixes &= ~has_cs;
96 else if (*d->prefixes & has_ds)
99 *d->prefixes &= ~has_ds;
101 else if (*d->prefixes & has_es)
104 *d->prefixes &= ~has_es;
106 else if (*d->prefixes & has_fs)
109 *d->prefixes &= ~has_fs;
111 else if (*d->prefixes & has_gs)
114 *d->prefixes &= ~has_gs;
116 else if (*d->prefixes & has_ss)
119 *d->prefixes &= ~has_ss;
124 if (*d->bufcntp + 4 > d->bufsize)
125 return *d->bufcntp + 4 - d->bufsize;
127 d->bufp[(*d->bufcntp)++] = '%';
128 d->bufp[(*d->bufcntp)++] = ch;
129 d->bufp[(*d->bufcntp)++] = 's';
130 d->bufp[(*d->bufcntp)++] = ':';
136 static const char hiregs[8][4] =
138 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
140 static const char aregs[8][4] =
142 "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"
144 static const char dregs[8][4] =
146 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
149 static const char aregs[8][4] =
151 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
157 general_mod$r_m (struct output_data *d)
159 int r = data_prefix (d);
163 int prefixes = *d->prefixes;
164 const uint8_t *data = &d->data[d->opoff1 / 8];
165 char *bufp = d->bufp;
166 size_t *bufcntp = d->bufcntp;
167 size_t bufsize = d->bufsize;
169 uint_fast8_t modrm = data[0];
171 if (unlikely ((prefixes & has_addr16) != 0))
176 if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80)
177 /* 16 bit displacement. */
178 disp = read_2sbyte_unaligned (&data[1]);
179 else if ((modrm & 0xc0) == 0x40)
180 /* 8 bit displacement. */
181 disp = *(const int8_t *) &data[1];
182 else if ((modrm & 0xc0) == 0)
185 char tmpbuf[sizeof ("-0x1234(%rr,%rr)")];
187 if ((modrm & 0xc7) == 6)
188 n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx16, disp);
193 n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx16,
194 disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
196 if ((modrm & 0x4) == 0)
197 n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%b%c,%%%ci)",
198 "xp"[(modrm >> 1) & 1], "sd"[modrm & 1]);
200 n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%%s)",
201 ((const char [4][3]) { "si", "di", "bp", "bx" })[modrm & 3]);
204 if (*bufcntp + n + 1 > bufsize)
205 return *bufcntp + n + 1 - bufsize;
207 memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
213 if ((modrm & 7) != 4)
218 if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80)
219 /* 32 bit displacement. */
220 disp = read_4sbyte_unaligned (&data[1]);
221 else if ((modrm & 0xc0) == 0x40)
222 /* 8 bit displacement. */
223 disp = *(const int8_t *) &data[1];
224 else if ((modrm & 0xc0) == 0)
227 char tmpbuf[sizeof ("-0x12345678(%rrrr)")];
231 n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)",
233 (prefixes & has_rex_b) ? hiregs[modrm & 7] :
237 if (prefixes & has_addr16)
239 if (prefixes & has_rex_b)
246 else if ((modrm & 0xc7) != 5)
249 n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%n%s)",
250 disp < 0 ? "-" : "", disp < 0 ? -disp : disp, &p,
252 (prefixes & has_rex_b) ? hiregs[modrm & 7] :
256 if (prefixes & has_addr16)
258 if (prefixes & has_rex_b)
268 n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%rip)",
269 disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
271 d->symaddr_use = addr_rel_always;
274 n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp);
278 if (*bufcntp + n + 1 > bufsize)
279 return *bufcntp + n + 1 - bufsize;
281 memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
287 uint_fast8_t sib = data[1];
291 if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80
292 || ((modrm & 0xc7) == 0x4 && (sib & 0x7) == 0x5))
293 /* 32 bit displacement. */
294 disp = read_4sbyte_unaligned (&data[2]);
295 else if ((modrm & 0xc0) == 0x40)
296 /* 8 bit displacement. */
297 disp = *(const int8_t *) &data[2];
301 char tmpbuf[sizeof ("-0x12345678(%rrrr,%rrrr,N)")];
304 if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25
306 || (prefixes & has_rex_x) != 0
312 n = snprintf (cp, sizeof (tmpbuf), "%s0x%" PRIx32,
313 disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
319 if ((modrm & 0xc7) != 0x4 || (sib & 0x7) != 0x5)
324 (prefixes & has_rex_b) ? hiregs[sib & 7] :
325 (prefixes & has_addr16) ? dregs[sib & 7] :
329 if ((prefixes & (has_rex_b | has_addr16))
330 == (has_rex_b | has_addr16))
335 if ((sib & 0x38) != 0x20
337 || (prefixes & has_rex_x) != 0
345 (prefixes & has_rex_x)
346 ? hiregs[(sib >> 3) & 7] :
347 (prefixes & has_addr16)
348 ? dregs[(sib >> 3) & 7] :
350 aregs[(sib >> 3) & 7]);
352 if ((prefixes & (has_rex_b | has_addr16))
353 == (has_rex_b | has_addr16))
358 *cp++ = '0' + (1 << (sib >> 6));
367 if ((prefixes & has_addr16) == 0)
368 n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx64,
372 n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx32, disp);
376 if (*bufcntp + (cp - tmpbuf) > bufsize)
377 return *bufcntp + (cp - tmpbuf) - bufsize;
379 memcpy (&bufp[*bufcntp], tmpbuf, cp - tmpbuf);
380 *bufcntp += cp - tmpbuf;
388 FCT_MOD$R_M (struct output_data *d)
390 assert (d->opoff1 % 8 == 0);
391 uint_fast8_t modrm = d->data[d->opoff1 / 8];
392 if ((modrm & 0xc0) == 0xc0)
394 assert (d->opoff1 / 8 == d->opoff2 / 8);
395 assert (d->opoff2 % 8 == 5);
396 //uint_fast8_t byte = d->data[d->opoff2 / 8] & 7;
397 uint_fast8_t byte = modrm & 7;
399 size_t *bufcntp = d->bufcntp;
400 char *buf = d->bufp + *bufcntp;
401 size_t avail = d->bufsize - *bufcntp;
403 if (*d->prefixes & (has_rep | has_repne))
404 needed = snprintf (buf, avail, "%%%s", dregs[byte]);
406 needed = snprintf (buf, avail, "%%mm%" PRIxFAST8, byte);
407 if ((size_t) needed > avail)
408 return needed - avail;
413 return general_mod$r_m (d);
418 FCT_Mod$R_m (struct output_data *d)
420 assert (d->opoff1 % 8 == 0);
421 uint_fast8_t modrm = d->data[d->opoff1 / 8];
422 if ((modrm & 0xc0) == 0xc0)
424 assert (d->opoff1 / 8 == d->opoff2 / 8);
425 assert (d->opoff2 % 8 == 5);
426 //uint_fast8_t byte = data[opoff2 / 8] & 7;
427 uint_fast8_t byte = modrm & 7;
429 size_t *bufcntp = d->bufcntp;
430 size_t avail = d->bufsize - *bufcntp;
431 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8,
433 if ((size_t) needed > avail)
434 return needed - avail;
435 *d->bufcntp += needed;
439 return general_mod$r_m (d);
443 generic_abs (struct output_data *d, const char *absstring
451 int r = data_prefix (d);
455 assert (d->opoff1 % 8 == 0);
456 assert (d->opoff1 / 8 == 1);
457 if (*d->param_start + abslen > d->end)
459 *d->param_start += abslen;
462 # define ABSPRIFMT PRIx32
465 # define ABSPRIFMT PRIx64
467 absval = read_8ubyte_unaligned (&d->data[1]);
470 absval = read_4ubyte_unaligned (&d->data[1]);
471 size_t *bufcntp = d->bufcntp;
472 size_t avail = d->bufsize - *bufcntp;
473 int needed = snprintf (&d->bufp[*bufcntp], avail, "%s0x%" ABSPRIFMT,
475 if ((size_t) needed > avail)
476 return needed - avail;
483 FCT_absval (struct output_data *d)
485 return generic_abs (d, "$"
493 FCT_abs (struct output_data *d)
495 return generic_abs (d, ""
503 FCT_ax (struct output_data *d)
505 int is_16bit = (*d->prefixes & has_data16) != 0;
507 size_t *bufcntp = d->bufcntp;
508 char *bufp = d->bufp;
509 size_t bufsize = d->bufsize;
511 if (*bufcntp + 4 - is_16bit > bufsize)
512 return *bufcntp + 4 - is_16bit - bufsize;
514 bufp[(*bufcntp)++] = '%';
516 bufp[(*bufcntp)++] = (
518 (*d->prefixes & has_rex_w) ? 'r' :
521 bufp[(*bufcntp)++] = 'a';
522 bufp[(*bufcntp)++] = 'x';
529 FCT_ax$w (struct output_data *d)
531 if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
534 size_t *bufcntp = d->bufcntp;
535 char *bufp = d->bufp;
536 size_t bufsize = d->bufsize;
538 if (*bufcntp + 3 > bufsize)
539 return *bufcntp + 3 - bufsize;
541 bufp[(*bufcntp)++] = '%';
542 bufp[(*bufcntp)++] = 'a';
543 bufp[(*bufcntp)++] = 'l';
550 __attribute__ ((noinline))
551 FCT_crdb (struct output_data *d, const char *regstr)
553 if (*d->prefixes & has_data16)
556 size_t *bufcntp = d->bufcntp;
558 // XXX If this assert is true, use absolute offset below
559 assert (d->opoff1 / 8 == 2);
560 assert (d->opoff1 % 8 == 2);
561 size_t avail = d->bufsize - *bufcntp;
562 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%%s%" PRIx32,
563 regstr, (uint32_t) (d->data[d->opoff1 / 8] >> 3) & 7);
564 if ((size_t) needed > avail)
565 return needed - avail;
572 FCT_ccc (struct output_data *d)
574 return FCT_crdb (d, "cr");
579 FCT_ddd (struct output_data *d)
581 return FCT_crdb (d, "db");
586 FCT_disp8 (struct output_data *d)
588 assert (d->opoff1 % 8 == 0);
589 if (*d->param_start >= d->end)
591 int32_t offset = *(const int8_t *) (*d->param_start)++;
593 size_t *bufcntp = d->bufcntp;
594 size_t avail = d->bufsize - *bufcntp;
595 int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
596 (uint32_t) (d->addr + (*d->param_start - d->data)
598 if ((size_t) needed > avail)
599 return needed - avail;
606 __attribute__ ((noinline))
607 FCT_ds_xx (struct output_data *d, const char *reg)
609 int prefix = *d->prefixes & SEGMENT_PREFIXES;
612 *d->prefixes |= prefix = has_ds;
613 /* Make sure only one bit is set. */
614 else if ((prefix - 1) & prefix)
617 int r = data_prefix (d);
619 assert ((*d->prefixes & prefix) == 0);
624 size_t *bufcntp = d->bufcntp;
625 size_t avail = d->bufsize - *bufcntp;
626 int needed = snprintf (&d->bufp[*bufcntp], avail, "(%%%s%s)",
628 *d->prefixes & idx_addr16 ? "e" : "r",
630 *d->prefixes & idx_addr16 ? "" : "e",
633 if ((size_t) needed > avail)
634 return (size_t) needed - avail;
642 FCT_ds_bx (struct output_data *d)
644 return FCT_ds_xx (d, "bx");
649 FCT_ds_si (struct output_data *d)
651 return FCT_ds_xx (d, "si");
656 FCT_dx (struct output_data *d)
658 size_t *bufcntp = d->bufcntp;
660 if (*bufcntp + 7 > d->bufsize)
661 return *bufcntp + 7 - d->bufsize;
663 memcpy (&d->bufp[*bufcntp], "(%dx)", 5);
671 FCT_es_di (struct output_data *d)
673 size_t *bufcntp = d->bufcntp;
674 size_t avail = d->bufsize - *bufcntp;
675 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%es:(%%%sdi)",
677 *d->prefixes & idx_addr16 ? "e" : "r"
679 *d->prefixes & idx_addr16 ? "" : "e"
682 if ((size_t) needed > avail)
683 return (size_t) needed - avail;
691 FCT_imm (struct output_data *d)
693 size_t *bufcntp = d->bufcntp;
694 size_t avail = d->bufsize - *bufcntp;
696 if (*d->prefixes & has_data16)
698 if (*d->param_start + 2 > d->end)
700 uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
701 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
705 if (*d->param_start + 4 > d->end)
707 int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
709 if (*d->prefixes & has_rex_w)
710 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
714 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
716 if ((size_t) needed > avail)
717 return (size_t) needed - avail;
724 FCT_imm$w (struct output_data *d)
726 if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
729 size_t *bufcntp = d->bufcntp;
730 size_t avail = d->bufsize - *bufcntp;
731 if (*d->param_start>= d->end)
733 uint_fast8_t word = *(*d->param_start)++;
734 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIxFAST8, word);
735 if ((size_t) needed > avail)
736 return (size_t) needed - avail;
744 FCT_imm64$w (struct output_data *d)
746 if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) == 0
747 || (*d->prefixes & has_data16) != 0)
748 return FCT_imm$w (d);
750 size_t *bufcntp = d->bufcntp;
751 size_t avail = d->bufsize - *bufcntp;
753 if (*d->prefixes & has_rex_w)
755 if (*d->param_start + 8 > d->end)
757 uint64_t word = read_8ubyte_unaligned_inc (*d->param_start);
758 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, word);
762 if (*d->param_start + 4 > d->end)
764 int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
765 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
767 if ((size_t) needed > avail)
768 return (size_t) needed - avail;
776 FCT_imms (struct output_data *d)
778 size_t *bufcntp = d->bufcntp;
779 size_t avail = d->bufsize - *bufcntp;
780 if (*d->param_start>= d->end)
782 int8_t byte = *(*d->param_start)++;
784 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
787 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
790 if ((size_t) needed > avail)
791 return (size_t) needed - avail;
798 FCT_imm$s (struct output_data *d)
800 uint_fast8_t opcode = d->data[d->opoff2 / 8];
801 size_t *bufcntp = d->bufcntp;
802 size_t avail = d->bufsize - *bufcntp;
803 if ((opcode & 2) != 0)
806 if ((*d->prefixes & has_data16) == 0)
808 if (*d->param_start + 4 > d->end)
810 int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
812 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
815 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
817 if ((size_t) needed > avail)
818 return (size_t) needed - avail;
823 if (*d->param_start + 2 > d->end)
825 uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
826 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
827 if ((size_t) needed > avail)
828 return (size_t) needed - avail;
836 FCT_imm16 (struct output_data *d)
838 if (*d->param_start + 2 > d->end)
840 uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
841 size_t *bufcntp = d->bufcntp;
842 size_t avail = d->bufsize - *bufcntp;
843 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
844 if ((size_t) needed > avail)
845 return (size_t) needed - avail;
852 FCT_imms8 (struct output_data *d)
854 size_t *bufcntp = d->bufcntp;
855 size_t avail = d->bufsize - *bufcntp;
856 if (*d->param_start >= d->end)
858 int_fast8_t byte = *(*d->param_start)++;
861 if (*d->prefixes & has_rex_w)
862 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
866 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
868 if ((size_t) needed > avail)
869 return (size_t) needed - avail;
876 FCT_imm8 (struct output_data *d)
878 size_t *bufcntp = d->bufcntp;
879 size_t avail = d->bufsize - *bufcntp;
880 if (*d->param_start >= d->end)
882 uint_fast8_t byte = *(*d->param_start)++;
883 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
885 if ((size_t) needed > avail)
886 return (size_t) needed - avail;
893 FCT_rel (struct output_data *d)
895 size_t *bufcntp = d->bufcntp;
896 size_t avail = d->bufsize - *bufcntp;
897 if (*d->param_start + 4 > d->end)
899 int32_t rel = read_4sbyte_unaligned_inc (*d->param_start);
901 int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx64,
902 (uint64_t) (d->addr + rel
903 + (*d->param_start - d->data)));
905 int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
906 (uint32_t) (d->addr + rel
907 + (*d->param_start - d->data)));
909 if ((size_t) needed > avail)
910 return (size_t) needed - avail;
917 FCT_mmxreg (struct output_data *d)
919 uint_fast8_t byte = d->data[d->opoff1 / 8];
920 assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
921 byte = (byte >> (5 - d->opoff1 % 8)) & 7;
922 size_t *bufcntp = d->bufcntp;
923 size_t avail = d->bufsize - *bufcntp;
924 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte);
925 if ((size_t) needed > avail)
926 return needed - avail;
933 FCT_mod$r_m (struct output_data *d)
935 assert (d->opoff1 % 8 == 0);
936 uint_fast8_t modrm = d->data[d->opoff1 / 8];
937 if ((modrm & 0xc0) == 0xc0)
939 int prefixes = *d->prefixes;
940 if (prefixes & has_addr16)
943 int is_16bit = (prefixes & has_data16) != 0;
945 size_t *bufcntp = d->bufcntp;
946 char *bufp = d->bufp;
947 if (*bufcntp + 5 - is_16bit > d->bufsize)
948 return *bufcntp + 5 - is_16bit - d->bufsize;
949 bufp[(*bufcntp)++] = '%';
953 if ((prefixes & has_rex_b) != 0 && !is_16bit)
955 cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
956 if ((prefixes & has_rex_w) == 0)
962 cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
964 if ((prefixes & has_rex_w) != 0)
965 bufp[*bufcntp] = 'r';
968 *bufcntp = cp - bufp;
972 return general_mod$r_m (d);
978 FCT_moda$r_m (struct output_data *d)
980 assert (d->opoff1 % 8 == 0);
981 uint_fast8_t modrm = d->data[d->opoff1 / 8];
982 if ((modrm & 0xc0) == 0xc0)
984 if (*d->prefixes & has_addr16)
987 size_t *bufcntp = d->bufcntp;
988 if (*bufcntp + 3 > d->bufsize)
989 return *bufcntp + 3 - d->bufsize;
991 memcpy (&d->bufp[*bufcntp], "???", 3);
997 return general_mod$r_m (d);
1003 static const char rex_8bit[8][3] =
1005 [0] = "a", [1] = "c", [2] = "d", [3] = "b",
1006 [4] = "sp", [5] = "bp", [6] = "si", [7] = "di"
1012 FCT_mod$r_m$w (struct output_data *d)
1014 assert (d->opoff1 % 8 == 0);
1015 const uint8_t *data = d->data;
1016 uint_fast8_t modrm = data[d->opoff1 / 8];
1017 if ((modrm & 0xc0) == 0xc0)
1019 int prefixes = *d->prefixes;
1021 if (prefixes & has_addr16)
1024 size_t *bufcntp = d->bufcntp;
1025 char *bufp = d->bufp;
1026 if (*bufcntp + 5 > d->bufsize)
1027 return *bufcntp + 5 - d->bufsize;
1029 if ((data[d->opoff3 / 8] & (1 << (7 - (d->opoff3 & 7)))) == 0)
1031 bufp[(*bufcntp)++] = '%';
1034 if (prefixes & has_rex)
1036 if (prefixes & has_rex_r)
1037 *bufcntp += snprintf (bufp + *bufcntp, d->bufsize - *bufcntp,
1038 "r%db", 8 + (modrm & 7));
1041 char *cp = stpcpy (bufp + *bufcntp, hiregs[modrm & 7]);
1043 *bufcntp = cp - bufp;
1049 bufp[(*bufcntp)++] = "acdb"[modrm & 3];
1050 bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
1055 int is_16bit = (prefixes & has_data16) != 0;
1057 bufp[(*bufcntp)++] = '%';
1061 if ((prefixes & has_rex_b) != 0 && !is_16bit)
1063 cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
1064 if ((prefixes & has_rex_w) == 0)
1070 cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
1072 if ((prefixes & has_rex_w) != 0)
1073 bufp[*bufcntp] = 'r';
1076 *bufcntp = cp - bufp;
1081 return general_mod$r_m (d);
1086 FCT_mod$8r_m (struct output_data *d)
1088 assert (d->opoff1 % 8 == 0);
1089 uint_fast8_t modrm = d->data[d->opoff1 / 8];
1090 if ((modrm & 0xc0) == 0xc0)
1092 size_t *bufcntp = d->bufcntp;
1093 char *bufp = d->bufp;
1094 if (*bufcntp + 3 > d->bufsize)
1095 return *bufcntp + 3 - d->bufsize;
1096 bufp[(*bufcntp)++] = '%';
1097 bufp[(*bufcntp)++] = "acdb"[modrm & 3];
1098 bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
1102 return general_mod$r_m (d);
1107 FCT_mod$16r_m (struct output_data *d)
1109 assert (d->opoff1 % 8 == 0);
1110 uint_fast8_t modrm = d->data[d->opoff1 / 8];
1111 if ((modrm & 0xc0) == 0xc0)
1113 assert (d->opoff1 / 8 == d->opoff2 / 8);
1114 //uint_fast8_t byte = data[opoff2 / 8] & 7;
1115 uint_fast8_t byte = modrm & 7;
1117 size_t *bufcntp = d->bufcntp;
1118 if (*bufcntp + 3 > d->bufsize)
1119 return *bufcntp + 3 - d->bufsize;
1120 d->bufp[(*bufcntp)++] = '%';
1121 memcpy (&d->bufp[*bufcntp], dregs[byte] + 1, sizeof (dregs[0]) - 1);
1126 return general_mod$r_m (d);
1132 FCT_mod$64r_m (struct output_data *d)
1134 assert (d->opoff1 % 8 == 0);
1135 uint_fast8_t modrm = d->data[d->opoff1 / 8];
1136 if ((modrm & 0xc0) == 0xc0)
1138 assert (d->opoff1 / 8 == d->opoff2 / 8);
1139 //uint_fast8_t byte = data[opoff2 / 8] & 7;
1140 uint_fast8_t byte = modrm & 7;
1142 size_t *bufcntp = d->bufcntp;
1143 if (*bufcntp + 4 > d->bufsize)
1144 return *bufcntp + 4 - d->bufsize;
1145 char *cp = &d->bufp[*bufcntp];
1148 (*d->prefixes & has_rex_b) ? hiregs[byte] : aregs[byte]);
1149 *bufcntp = cp - d->bufp;
1153 return general_mod$r_m (d);
1156 static typeof (FCT_mod$r_m) FCT_mod$64r_m __attribute__ ((alias ("FCT_mod$r_m")));
1161 FCT_reg (struct output_data *d)
1163 uint_fast8_t byte = d->data[d->opoff1 / 8];
1164 assert (d->opoff1 % 8 + 3 <= 8);
1165 byte >>= 8 - (d->opoff1 % 8 + 3);
1167 int is_16bit = (*d->prefixes & has_data16) != 0;
1168 size_t *bufcntp = d->bufcntp;
1169 if (*bufcntp + 5 > d->bufsize)
1170 return *bufcntp + 5 - d->bufsize;
1171 d->bufp[(*bufcntp)++] = '%';
1173 if ((*d->prefixes & has_rex_r) != 0 && !is_16bit)
1175 *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
1177 if ((*d->prefixes & has_rex_w) == 0)
1178 d->bufp[(*bufcntp)++] = 'd';
1183 memcpy (&d->bufp[*bufcntp], dregs[byte] + is_16bit, 3 - is_16bit);
1185 if ((*d->prefixes & has_rex_w) != 0 && !is_16bit)
1186 d->bufp[*bufcntp] = 'r';
1188 *bufcntp += 3 - is_16bit;
1196 FCT_oreg (struct output_data *d)
1198 /* Special form where register comes from opcode. The rex.B bit is used,
1199 rex.R and rex.X are ignored. */
1200 int save_prefixes = *d->prefixes;
1202 *d->prefixes = ((save_prefixes & ~has_rex_r)
1203 | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
1205 int r = FCT_reg (d);
1207 *d->prefixes = save_prefixes;
1215 FCT_reg64 (struct output_data *d)
1217 uint_fast8_t byte = d->data[d->opoff1 / 8];
1218 assert (d->opoff1 % 8 + 3 <= 8);
1219 byte >>= 8 - (d->opoff1 % 8 + 3);
1221 if ((*d->prefixes & has_data16) != 0)
1223 size_t *bufcntp = d->bufcntp;
1224 if (*bufcntp + 5 > d->bufsize)
1225 return *bufcntp + 5 - d->bufsize;
1226 d->bufp[(*bufcntp)++] = '%';
1228 if ((*d->prefixes & has_rex_r) != 0)
1230 *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
1232 if ((*d->prefixes & has_rex_w) == 0)
1233 d->bufp[(*bufcntp)++] = 'd';
1238 memcpy (&d->bufp[*bufcntp], aregs[byte], 3);
1246 FCT_reg$w (struct output_data *d)
1248 if (d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7))))
1251 uint_fast8_t byte = d->data[d->opoff1 / 8];
1252 assert (d->opoff1 % 8 + 3 <= 8);
1253 byte >>= 8 - (d->opoff1 % 8 + 3);
1256 size_t *bufcntp = d->bufcntp;
1257 if (*bufcntp + 4 > d->bufsize)
1258 return *bufcntp + 4 - d->bufsize;
1260 d->bufp[(*bufcntp)++] = '%';
1263 if (*d->prefixes & has_rex)
1265 if (*d->prefixes & has_rex_r)
1266 *bufcntp += snprintf (d->bufp + *bufcntp, d->bufsize - *bufcntp,
1270 char* cp = stpcpy (d->bufp + *bufcntp, rex_8bit[byte]);
1272 *bufcntp = cp - d->bufp;
1278 d->bufp[(*bufcntp)++] = "acdb"[byte & 3];
1279 d->bufp[(*bufcntp)++] = "lh"[byte >> 2];
1287 FCT_oreg$w (struct output_data *d)
1289 /* Special form where register comes from opcode. The rex.B bit is used,
1290 rex.R and rex.X are ignored. */
1291 int save_prefixes = *d->prefixes;
1293 *d->prefixes = ((save_prefixes & ~has_rex_r)
1294 | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
1296 int r = FCT_reg$w (d);
1298 *d->prefixes = save_prefixes;
1306 FCT_freg (struct output_data *d)
1308 assert (d->opoff1 / 8 == 1);
1309 assert (d->opoff1 % 8 == 5);
1310 size_t *bufcntp = d->bufcntp;
1311 size_t avail = d->bufsize - *bufcntp;
1312 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%st(%" PRIx32 ")",
1313 (uint32_t) (d->data[1] & 7));
1314 if ((size_t) needed > avail)
1315 return (size_t) needed - avail;
1323 FCT_reg16 (struct output_data *d)
1325 if (*d->prefixes & has_data16)
1328 *d->prefixes |= has_data16;
1335 FCT_sel (struct output_data *d)
1337 assert (d->opoff1 % 8 == 0);
1338 assert (d->opoff1 / 8 == 5);
1339 if (*d->param_start + 2 > d->end)
1341 *d->param_start += 2;
1342 uint16_t absval = read_2ubyte_unaligned (&d->data[5]);
1344 size_t *bufcntp = d->bufcntp;
1345 size_t avail = d->bufsize - *bufcntp;
1346 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, absval);
1347 if ((size_t) needed > avail)
1348 return needed - avail;
1355 FCT_sreg2 (struct output_data *d)
1357 uint_fast8_t byte = d->data[d->opoff1 / 8];
1358 assert (d->opoff1 % 8 + 3 <= 8);
1359 byte >>= 8 - (d->opoff1 % 8 + 2);
1361 size_t *bufcntp = d->bufcntp;
1362 char *bufp = d->bufp;
1363 if (*bufcntp + 3 > d->bufsize)
1364 return *bufcntp + 3 - d->bufsize;
1366 bufp[(*bufcntp)++] = '%';
1367 bufp[(*bufcntp)++] = "ecsd"[byte & 3];
1368 bufp[(*bufcntp)++] = 's';
1375 FCT_sreg3 (struct output_data *d)
1377 uint_fast8_t byte = d->data[d->opoff1 / 8];
1378 assert (d->opoff1 % 8 + 4 <= 8);
1379 byte >>= 8 - (d->opoff1 % 8 + 3);
1381 if ((byte & 7) >= 6)
1384 size_t *bufcntp = d->bufcntp;
1385 char *bufp = d->bufp;
1386 if (*bufcntp + 3 > d->bufsize)
1387 return *bufcntp + 3 - d->bufsize;
1389 bufp[(*bufcntp)++] = '%';
1390 bufp[(*bufcntp)++] = "ecsdfg"[byte & 7];
1391 bufp[(*bufcntp)++] = 's';
1398 FCT_string (struct output_data *d __attribute__ ((unused)))
1405 FCT_xmmreg (struct output_data *d)
1407 uint_fast8_t byte = d->data[d->opoff1 / 8];
1408 assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
1409 byte = (byte >> (5 - d->opoff1 % 8)) & 7;
1411 size_t *bufcntp = d->bufcntp;
1412 size_t avail = d->bufsize - *bufcntp;
1413 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, byte);
1414 if ((size_t) needed > avail)
1415 return needed - avail;