1 /* Helper routines for disassembler for x86/x86-64.
2 Copyright (C) 2007, 2008 Red Hat, Inc.
3 This file is part of Red Hat elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2007.
6 Red Hat elfutils is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by the
8 Free Software Foundation; version 2 of the License.
10 Red Hat elfutils is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with Red Hat elfutils; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
19 Red Hat elfutils is an included package of the Open Invention Network.
20 An included package of the Open Invention Network is a package for which
21 Open Invention Network licensees cross-license their patents. No patent
22 license is granted, either expressly or impliedly, by designation as an
23 included package. Should you wish to participate in the Open Invention
24 Network licensing program, please visit www.openinventionnetwork.com
25 <http://www.openinventionnetwork.com>. */
35 /* The mnemonic. Especially encoded for the optimized table. */
36 unsigned int mnemonic : MNEMONIC_BITS;
38 /* The rep/repe prefixes. */
40 unsigned int repe : 1;
42 /* Mnemonic suffix. */
43 unsigned int suffix : SUFFIX_BITS;
45 /* Nonzero if the instruction uses modr/m. */
46 unsigned int modrm : 1;
49 unsigned int fct1 : FCT1_BITS;
51 unsigned int str1 : STR1_BITS;
53 unsigned int off1_1 : OFF1_1_BITS;
54 unsigned int off1_2 : OFF1_2_BITS;
55 unsigned int off1_3 : OFF1_3_BITS;
58 unsigned int fct2 : FCT2_BITS;
60 unsigned int str2 : STR2_BITS;
62 unsigned int off2_1 : OFF2_1_BITS;
63 unsigned int off2_2 : OFF2_2_BITS;
64 unsigned int off2_3 : OFF2_3_BITS;
67 unsigned int fct3 : FCT3_BITS;
69 unsigned int str3 : STR3_BITS;
71 unsigned int off3_1 : OFF3_1_BITS;
73 unsigned int off3_2 : OFF3_2_BITS;
76 unsigned int off3_3 : OFF3_3_BITS;
81 typedef int (*opfct_t) (struct output_data *);
85 data_prefix (struct output_data *d)
88 if (*d->prefixes & has_cs)
91 *d->prefixes &= ~has_cs;
93 else if (*d->prefixes & has_ds)
96 *d->prefixes &= ~has_ds;
98 else if (*d->prefixes & has_es)
101 *d->prefixes &= ~has_es;
103 else if (*d->prefixes & has_fs)
106 *d->prefixes &= ~has_fs;
108 else if (*d->prefixes & has_gs)
111 *d->prefixes &= ~has_gs;
113 else if (*d->prefixes & has_ss)
116 *d->prefixes &= ~has_ss;
121 if (*d->bufcntp + 4 > d->bufsize)
122 return *d->bufcntp + 4 - d->bufsize;
124 d->bufp[(*d->bufcntp)++] = '%';
125 d->bufp[(*d->bufcntp)++] = ch;
126 d->bufp[(*d->bufcntp)++] = 's';
127 d->bufp[(*d->bufcntp)++] = ':';
133 static const char hiregs[8][4] =
135 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
137 static const char aregs[8][4] =
139 "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"
141 static const char dregs[8][4] =
143 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
146 static const char aregs[8][4] =
148 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
154 general_mod$r_m (struct output_data *d)
156 int r = data_prefix (d);
160 int prefixes = *d->prefixes;
161 const uint8_t *data = &d->data[d->opoff1 / 8];
162 char *bufp = d->bufp;
163 size_t *bufcntp = d->bufcntp;
164 size_t bufsize = d->bufsize;
166 uint_fast8_t modrm = data[0];
168 if (unlikely ((prefixes & has_addr16) != 0))
173 if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80)
174 /* 16 bit displacement. */
175 disp = read_2sbyte_unaligned (&data[1]);
176 else if ((modrm & 0xc0) == 0x40)
177 /* 8 bit displacement. */
178 disp = *(const int8_t *) &data[1];
179 else if ((modrm & 0xc0) == 0)
182 char tmpbuf[sizeof ("-0x1234(%rr,%rr)")];
184 if ((modrm & 0xc7) == 6)
185 n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx16, disp);
190 n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx16,
191 disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
193 if ((modrm & 0x4) == 0)
194 n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%b%c,%%%ci)",
195 "xp"[(modrm >> 1) & 1], "sd"[modrm & 1]);
197 n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%%s)",
198 ((const char [4][3]) { "si", "di", "bp", "bx" })[modrm & 3]);
201 if (*bufcntp + n + 1 > bufsize)
202 return *bufcntp + n + 1 - bufsize;
204 memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
210 if ((modrm & 7) != 4)
215 if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80)
216 /* 32 bit displacement. */
217 disp = read_4sbyte_unaligned (&data[1]);
218 else if ((modrm & 0xc0) == 0x40)
219 /* 8 bit displacement. */
220 disp = *(const int8_t *) &data[1];
221 else if ((modrm & 0xc0) == 0)
224 char tmpbuf[sizeof ("-0x12345678(%rrrr)")];
228 n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)",
230 (prefixes & has_rex_b) ? hiregs[modrm & 7] :
234 if (prefixes & has_addr16)
236 if (prefixes & has_rex_b)
243 else if ((modrm & 0xc7) != 5)
246 n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%n%s)",
247 disp < 0 ? "-" : "", disp < 0 ? -disp : disp, &p,
249 (prefixes & has_rex_b) ? hiregs[modrm & 7] :
253 if (prefixes & has_addr16)
255 if (prefixes & has_rex_b)
265 n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%rip)",
266 disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
268 d->symaddr_use = addr_rel_always;
271 n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp);
275 if (*bufcntp + n + 1 > bufsize)
276 return *bufcntp + n + 1 - bufsize;
278 memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
284 uint_fast8_t sib = data[1];
288 if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80
289 || ((modrm & 0xc7) == 0x4 && (sib & 0x7) == 0x5))
290 /* 32 bit displacement. */
291 disp = read_4sbyte_unaligned (&data[2]);
292 else if ((modrm & 0xc0) == 0x40)
293 /* 8 bit displacement. */
294 disp = *(const int8_t *) &data[2];
298 char tmpbuf[sizeof ("-0x12345678(%rrrr,%rrrr,N)")];
301 if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25
303 || (prefixes & has_rex_x) != 0
309 n = snprintf (cp, sizeof (tmpbuf), "%s0x%" PRIx32,
310 disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
316 if ((modrm & 0xc7) != 0x4 || (sib & 0x7) != 0x5)
321 (prefixes & has_rex_b) ? hiregs[sib & 7] :
322 (prefixes & has_addr16) ? dregs[sib & 7] :
326 if ((prefixes & (has_rex_b | has_addr16))
327 == (has_rex_b | has_addr16))
332 if ((sib & 0x38) != 0x20
334 || (prefixes & has_rex_x) != 0
342 (prefixes & has_rex_x)
343 ? hiregs[(sib >> 3) & 7] :
344 (prefixes & has_addr16)
345 ? dregs[(sib >> 3) & 7] :
347 aregs[(sib >> 3) & 7]);
349 if ((prefixes & (has_rex_b | has_addr16))
350 == (has_rex_b | has_addr16))
355 *cp++ = '0' + (1 << (sib >> 6));
364 if ((prefixes & has_addr16) == 0)
365 n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx64,
369 n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx32, disp);
373 if (*bufcntp + (cp - tmpbuf) > bufsize)
374 return *bufcntp + (cp - tmpbuf) - bufsize;
376 memcpy (&bufp[*bufcntp], tmpbuf, cp - tmpbuf);
377 *bufcntp += cp - tmpbuf;
385 FCT_MOD$R_M (struct output_data *d)
387 assert (d->opoff1 % 8 == 0);
388 uint_fast8_t modrm = d->data[d->opoff1 / 8];
389 if ((modrm & 0xc0) == 0xc0)
391 assert (d->opoff1 / 8 == d->opoff2 / 8);
392 assert (d->opoff2 % 8 == 5);
393 //uint_fast8_t byte = d->data[d->opoff2 / 8] & 7;
394 uint_fast8_t byte = modrm & 7;
396 size_t *bufcntp = d->bufcntp;
397 char *buf = d->bufp + *bufcntp;
398 size_t avail = d->bufsize - *bufcntp;
400 if (*d->prefixes & (has_rep | has_repne))
401 needed = snprintf (buf, avail, "%%%s", dregs[byte]);
403 needed = snprintf (buf, avail, "%%mm%" PRIxFAST8, byte);
404 if ((size_t) needed > avail)
405 return needed - avail;
410 return general_mod$r_m (d);
415 FCT_Mod$R_m (struct output_data *d)
417 assert (d->opoff1 % 8 == 0);
418 uint_fast8_t modrm = d->data[d->opoff1 / 8];
419 if ((modrm & 0xc0) == 0xc0)
421 assert (d->opoff1 / 8 == d->opoff2 / 8);
422 assert (d->opoff2 % 8 == 5);
423 //uint_fast8_t byte = data[opoff2 / 8] & 7;
424 uint_fast8_t byte = modrm & 7;
426 size_t *bufcntp = d->bufcntp;
427 size_t avail = d->bufsize - *bufcntp;
428 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8,
430 if ((size_t) needed > avail)
431 return needed - avail;
432 *d->bufcntp += needed;
436 return general_mod$r_m (d);
440 generic_abs (struct output_data *d, const char *absstring
448 int r = data_prefix (d);
452 assert (d->opoff1 % 8 == 0);
453 assert (d->opoff1 / 8 == 1);
454 if (*d->param_start + abslen > d->end)
456 *d->param_start += abslen;
459 # define ABSPRIFMT PRIx32
462 # define ABSPRIFMT PRIx64
464 absval = read_8ubyte_unaligned (&d->data[1]);
467 absval = read_4ubyte_unaligned (&d->data[1]);
468 size_t *bufcntp = d->bufcntp;
469 size_t avail = d->bufsize - *bufcntp;
470 int needed = snprintf (&d->bufp[*bufcntp], avail, "%s0x%" ABSPRIFMT,
472 if ((size_t) needed > avail)
473 return needed - avail;
480 FCT_absval (struct output_data *d)
482 return generic_abs (d, "$"
490 FCT_abs (struct output_data *d)
492 return generic_abs (d, ""
500 FCT_ax (struct output_data *d)
502 int is_16bit = (*d->prefixes & has_data16) != 0;
504 size_t *bufcntp = d->bufcntp;
505 char *bufp = d->bufp;
506 size_t bufsize = d->bufsize;
508 if (*bufcntp + 4 - is_16bit > bufsize)
509 return *bufcntp + 4 - is_16bit - bufsize;
511 bufp[(*bufcntp)++] = '%';
513 bufp[(*bufcntp)++] = (
515 (*d->prefixes & has_rex_w) ? 'r' :
518 bufp[(*bufcntp)++] = 'a';
519 bufp[(*bufcntp)++] = 'x';
526 FCT_ax$w (struct output_data *d)
528 if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
531 size_t *bufcntp = d->bufcntp;
532 char *bufp = d->bufp;
533 size_t bufsize = d->bufsize;
535 if (*bufcntp + 3 > bufsize)
536 return *bufcntp + 3 - bufsize;
538 bufp[(*bufcntp)++] = '%';
539 bufp[(*bufcntp)++] = 'a';
540 bufp[(*bufcntp)++] = 'l';
547 __attribute__ ((noinline))
548 FCT_crdb (struct output_data *d, const char *regstr)
550 if (*d->prefixes & has_data16)
553 size_t *bufcntp = d->bufcntp;
555 // XXX If this assert is true, use absolute offset below
556 assert (d->opoff1 / 8 == 2);
557 assert (d->opoff1 % 8 == 2);
558 size_t avail = d->bufsize - *bufcntp;
559 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%%s%" PRIx32,
560 regstr, (uint32_t) (d->data[d->opoff1 / 8] >> 3) & 7);
561 if ((size_t) needed > avail)
562 return needed - avail;
569 FCT_ccc (struct output_data *d)
571 return FCT_crdb (d, "cr");
576 FCT_ddd (struct output_data *d)
578 return FCT_crdb (d, "db");
583 FCT_disp8 (struct output_data *d)
585 assert (d->opoff1 % 8 == 0);
586 if (*d->param_start >= d->end)
588 int32_t offset = *(const int8_t *) (*d->param_start)++;
590 size_t *bufcntp = d->bufcntp;
591 size_t avail = d->bufsize - *bufcntp;
592 int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
593 (uint32_t) (d->addr + (*d->param_start - d->data)
595 if ((size_t) needed > avail)
596 return needed - avail;
603 __attribute__ ((noinline))
604 FCT_ds_xx (struct output_data *d, const char *reg)
606 int prefix = *d->prefixes & SEGMENT_PREFIXES;
609 *d->prefixes |= prefix = has_ds;
610 /* Make sure only one bit is set. */
611 else if ((prefix - 1) & prefix)
614 int r = data_prefix (d);
616 assert ((*d->prefixes & prefix) == 0);
621 size_t *bufcntp = d->bufcntp;
622 size_t avail = d->bufsize - *bufcntp;
623 int needed = snprintf (&d->bufp[*bufcntp], avail, "(%%%s%s)",
625 *d->prefixes & idx_addr16 ? "e" : "r",
627 *d->prefixes & idx_addr16 ? "" : "e",
630 if ((size_t) needed > avail)
631 return (size_t) needed - avail;
639 FCT_ds_bx (struct output_data *d)
641 return FCT_ds_xx (d, "bx");
646 FCT_ds_si (struct output_data *d)
648 return FCT_ds_xx (d, "si");
653 FCT_dx (struct output_data *d)
655 size_t *bufcntp = d->bufcntp;
657 if (*bufcntp + 7 > d->bufsize)
658 return *bufcntp + 7 - d->bufsize;
660 memcpy (&d->bufp[*bufcntp], "(%dx)", 5);
668 FCT_es_di (struct output_data *d)
670 size_t *bufcntp = d->bufcntp;
671 size_t avail = d->bufsize - *bufcntp;
672 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%es:(%%%sdi)",
674 *d->prefixes & idx_addr16 ? "e" : "r"
676 *d->prefixes & idx_addr16 ? "" : "e"
679 if ((size_t) needed > avail)
680 return (size_t) needed - avail;
688 FCT_imm (struct output_data *d)
690 size_t *bufcntp = d->bufcntp;
691 size_t avail = d->bufsize - *bufcntp;
693 if (*d->prefixes & has_data16)
695 if (*d->param_start + 2 > d->end)
697 uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
698 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
702 if (*d->param_start + 4 > d->end)
704 int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
706 if (*d->prefixes & has_rex_w)
707 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
711 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
713 if ((size_t) needed > avail)
714 return (size_t) needed - avail;
721 FCT_imm$w (struct output_data *d)
723 if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
726 size_t *bufcntp = d->bufcntp;
727 size_t avail = d->bufsize - *bufcntp;
728 if (*d->param_start>= d->end)
730 uint_fast8_t word = *(*d->param_start)++;
731 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIxFAST8, word);
732 if ((size_t) needed > avail)
733 return (size_t) needed - avail;
741 FCT_imm64$w (struct output_data *d)
743 if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) == 0
744 || (*d->prefixes & has_data16) != 0)
745 return FCT_imm$w (d);
747 size_t *bufcntp = d->bufcntp;
748 size_t avail = d->bufsize - *bufcntp;
750 if (*d->prefixes & has_rex_w)
752 if (*d->param_start + 8 > d->end)
754 uint64_t word = read_8ubyte_unaligned_inc (*d->param_start);
755 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, word);
759 if (*d->param_start + 4 > d->end)
761 int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
762 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
764 if ((size_t) needed > avail)
765 return (size_t) needed - avail;
773 FCT_imms (struct output_data *d)
775 size_t *bufcntp = d->bufcntp;
776 size_t avail = d->bufsize - *bufcntp;
777 if (*d->param_start>= d->end)
779 int8_t byte = *(*d->param_start)++;
781 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
784 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
787 if ((size_t) needed > avail)
788 return (size_t) needed - avail;
795 FCT_imm$s (struct output_data *d)
797 uint_fast8_t opcode = d->data[d->opoff2 / 8];
798 size_t *bufcntp = d->bufcntp;
799 size_t avail = d->bufsize - *bufcntp;
800 if ((opcode & 2) != 0)
803 if ((*d->prefixes & has_data16) == 0)
805 if (*d->param_start + 4 > d->end)
807 int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
809 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
812 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
814 if ((size_t) needed > avail)
815 return (size_t) needed - avail;
820 if (*d->param_start + 2 > d->end)
822 uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
823 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
824 if ((size_t) needed > avail)
825 return (size_t) needed - avail;
833 FCT_imm16 (struct output_data *d)
835 if (*d->param_start + 2 > d->end)
837 uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
838 size_t *bufcntp = d->bufcntp;
839 size_t avail = d->bufsize - *bufcntp;
840 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
841 if ((size_t) needed > avail)
842 return (size_t) needed - avail;
849 FCT_imms8 (struct output_data *d)
851 size_t *bufcntp = d->bufcntp;
852 size_t avail = d->bufsize - *bufcntp;
853 if (*d->param_start >= d->end)
855 int_fast8_t byte = *(*d->param_start)++;
858 if (*d->prefixes & has_rex_w)
859 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
863 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
865 if ((size_t) needed > avail)
866 return (size_t) needed - avail;
873 FCT_imm8 (struct output_data *d)
875 size_t *bufcntp = d->bufcntp;
876 size_t avail = d->bufsize - *bufcntp;
877 if (*d->param_start >= d->end)
879 uint_fast8_t byte = *(*d->param_start)++;
880 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
882 if ((size_t) needed > avail)
883 return (size_t) needed - avail;
890 FCT_rel (struct output_data *d)
892 size_t *bufcntp = d->bufcntp;
893 size_t avail = d->bufsize - *bufcntp;
894 if (*d->param_start + 4 > d->end)
896 int32_t rel = read_4sbyte_unaligned_inc (*d->param_start);
898 int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx64,
899 (uint64_t) (d->addr + rel
900 + (*d->param_start - d->data)));
902 int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
903 (uint32_t) (d->addr + rel
904 + (*d->param_start - d->data)));
906 if ((size_t) needed > avail)
907 return (size_t) needed - avail;
914 FCT_mmxreg (struct output_data *d)
916 uint_fast8_t byte = d->data[d->opoff1 / 8];
917 assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
918 byte = (byte >> (5 - d->opoff1 % 8)) & 7;
919 size_t *bufcntp = d->bufcntp;
920 size_t avail = d->bufsize - *bufcntp;
921 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte);
922 if ((size_t) needed > avail)
923 return needed - avail;
930 FCT_mod$r_m (struct output_data *d)
932 assert (d->opoff1 % 8 == 0);
933 uint_fast8_t modrm = d->data[d->opoff1 / 8];
934 if ((modrm & 0xc0) == 0xc0)
936 int prefixes = *d->prefixes;
937 if (prefixes & has_addr16)
940 int is_16bit = (prefixes & has_data16) != 0;
942 size_t *bufcntp = d->bufcntp;
943 char *bufp = d->bufp;
944 if (*bufcntp + 5 - is_16bit > d->bufsize)
945 return *bufcntp + 5 - is_16bit - d->bufsize;
946 bufp[(*bufcntp)++] = '%';
950 if ((prefixes & has_rex_b) != 0 && !is_16bit)
952 cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
953 if ((prefixes & has_rex_w) == 0)
959 cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
961 if ((prefixes & has_rex_w) != 0)
962 bufp[*bufcntp] = 'r';
965 *bufcntp = cp - bufp;
969 return general_mod$r_m (d);
975 FCT_moda$r_m (struct output_data *d)
977 assert (d->opoff1 % 8 == 0);
978 uint_fast8_t modrm = d->data[d->opoff1 / 8];
979 if ((modrm & 0xc0) == 0xc0)
981 if (*d->prefixes & has_addr16)
984 size_t *bufcntp = d->bufcntp;
985 if (*bufcntp + 3 > d->bufsize)
986 return *bufcntp + 3 - d->bufsize;
988 memcpy (&d->bufp[*bufcntp], "???", 3);
994 return general_mod$r_m (d);
1000 static const char rex_8bit[8][3] =
1002 [0] = "a", [1] = "c", [2] = "d", [3] = "b",
1003 [4] = "sp", [5] = "bp", [6] = "si", [7] = "di"
1009 FCT_mod$r_m$w (struct output_data *d)
1011 assert (d->opoff1 % 8 == 0);
1012 const uint8_t *data = d->data;
1013 uint_fast8_t modrm = data[d->opoff1 / 8];
1014 if ((modrm & 0xc0) == 0xc0)
1016 int prefixes = *d->prefixes;
1018 if (prefixes & has_addr16)
1021 size_t *bufcntp = d->bufcntp;
1022 char *bufp = d->bufp;
1023 if (*bufcntp + 5 > d->bufsize)
1024 return *bufcntp + 5 - d->bufsize;
1026 if ((data[d->opoff3 / 8] & (1 << (7 - (d->opoff3 & 7)))) == 0)
1028 bufp[(*bufcntp)++] = '%';
1031 if (prefixes & has_rex)
1033 if (prefixes & has_rex_r)
1034 *bufcntp += snprintf (bufp + *bufcntp, d->bufsize - *bufcntp,
1035 "r%db", 8 + (modrm & 7));
1038 char *cp = stpcpy (bufp + *bufcntp, hiregs[modrm & 7]);
1040 *bufcntp = cp - bufp;
1046 bufp[(*bufcntp)++] = "acdb"[modrm & 3];
1047 bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
1052 int is_16bit = (prefixes & has_data16) != 0;
1054 bufp[(*bufcntp)++] = '%';
1058 if ((prefixes & has_rex_b) != 0 && !is_16bit)
1060 cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
1061 if ((prefixes & has_rex_w) == 0)
1067 cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
1069 if ((prefixes & has_rex_w) != 0)
1070 bufp[*bufcntp] = 'r';
1073 *bufcntp = cp - bufp;
1078 return general_mod$r_m (d);
1083 FCT_mod$8r_m (struct output_data *d)
1085 assert (d->opoff1 % 8 == 0);
1086 uint_fast8_t modrm = d->data[d->opoff1 / 8];
1087 if ((modrm & 0xc0) == 0xc0)
1089 size_t *bufcntp = d->bufcntp;
1090 char *bufp = d->bufp;
1091 if (*bufcntp + 3 > d->bufsize)
1092 return *bufcntp + 3 - d->bufsize;
1093 bufp[(*bufcntp)++] = '%';
1094 bufp[(*bufcntp)++] = "acdb"[modrm & 3];
1095 bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
1099 return general_mod$r_m (d);
1104 FCT_mod$16r_m (struct output_data *d)
1106 assert (d->opoff1 % 8 == 0);
1107 uint_fast8_t modrm = d->data[d->opoff1 / 8];
1108 if ((modrm & 0xc0) == 0xc0)
1110 assert (d->opoff1 / 8 == d->opoff2 / 8);
1111 //uint_fast8_t byte = data[opoff2 / 8] & 7;
1112 uint_fast8_t byte = modrm & 7;
1114 size_t *bufcntp = d->bufcntp;
1115 if (*bufcntp + 3 > d->bufsize)
1116 return *bufcntp + 3 - d->bufsize;
1117 d->bufp[(*bufcntp)++] = '%';
1118 memcpy (&d->bufp[*bufcntp], dregs[byte] + 1, sizeof (dregs[0]) - 1);
1123 return general_mod$r_m (d);
1129 FCT_mod$64r_m (struct output_data *d)
1131 assert (d->opoff1 % 8 == 0);
1132 uint_fast8_t modrm = d->data[d->opoff1 / 8];
1133 if ((modrm & 0xc0) == 0xc0)
1135 assert (d->opoff1 / 8 == d->opoff2 / 8);
1136 //uint_fast8_t byte = data[opoff2 / 8] & 7;
1137 uint_fast8_t byte = modrm & 7;
1139 size_t *bufcntp = d->bufcntp;
1140 if (*bufcntp + 4 > d->bufsize)
1141 return *bufcntp + 4 - d->bufsize;
1142 char *cp = &d->bufp[*bufcntp];
1145 (*d->prefixes & has_rex_b) ? hiregs[byte] : aregs[byte]);
1146 *bufcntp = cp - d->bufp;
1150 return general_mod$r_m (d);
1153 static typeof (FCT_mod$r_m) FCT_mod$64r_m __attribute__ ((alias ("FCT_mod$r_m")));
1158 FCT_reg (struct output_data *d)
1160 uint_fast8_t byte = d->data[d->opoff1 / 8];
1161 assert (d->opoff1 % 8 + 3 <= 8);
1162 byte >>= 8 - (d->opoff1 % 8 + 3);
1164 int is_16bit = (*d->prefixes & has_data16) != 0;
1165 size_t *bufcntp = d->bufcntp;
1166 if (*bufcntp + 5 > d->bufsize)
1167 return *bufcntp + 5 - d->bufsize;
1168 d->bufp[(*bufcntp)++] = '%';
1170 if ((*d->prefixes & has_rex_r) != 0 && !is_16bit)
1172 *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
1174 if ((*d->prefixes & has_rex_w) == 0)
1175 d->bufp[(*bufcntp)++] = 'd';
1180 memcpy (&d->bufp[*bufcntp], dregs[byte] + is_16bit, 3 - is_16bit);
1182 if ((*d->prefixes & has_rex_w) != 0 && !is_16bit)
1183 d->bufp[*bufcntp] = 'r';
1185 *bufcntp += 3 - is_16bit;
1193 FCT_oreg (struct output_data *d)
1195 /* Special form where register comes from opcode. The rex.B bit is used,
1196 rex.R and rex.X are ignored. */
1197 int save_prefixes = *d->prefixes;
1199 *d->prefixes = ((save_prefixes & ~has_rex_r)
1200 | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
1202 int r = FCT_reg (d);
1204 *d->prefixes = save_prefixes;
1212 FCT_reg64 (struct output_data *d)
1214 uint_fast8_t byte = d->data[d->opoff1 / 8];
1215 assert (d->opoff1 % 8 + 3 <= 8);
1216 byte >>= 8 - (d->opoff1 % 8 + 3);
1218 if ((*d->prefixes & has_data16) != 0)
1220 size_t *bufcntp = d->bufcntp;
1221 if (*bufcntp + 5 > d->bufsize)
1222 return *bufcntp + 5 - d->bufsize;
1223 d->bufp[(*bufcntp)++] = '%';
1225 if ((*d->prefixes & has_rex_r) != 0)
1227 *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
1229 if ((*d->prefixes & has_rex_w) == 0)
1230 d->bufp[(*bufcntp)++] = 'd';
1235 memcpy (&d->bufp[*bufcntp], aregs[byte], 3);
1243 FCT_reg$w (struct output_data *d)
1245 if (d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7))))
1248 uint_fast8_t byte = d->data[d->opoff1 / 8];
1249 assert (d->opoff1 % 8 + 3 <= 8);
1250 byte >>= 8 - (d->opoff1 % 8 + 3);
1253 size_t *bufcntp = d->bufcntp;
1254 if (*bufcntp + 4 > d->bufsize)
1255 return *bufcntp + 4 - d->bufsize;
1257 d->bufp[(*bufcntp)++] = '%';
1260 if (*d->prefixes & has_rex)
1262 if (*d->prefixes & has_rex_r)
1263 *bufcntp += snprintf (d->bufp + *bufcntp, d->bufsize - *bufcntp,
1267 char* cp = stpcpy (d->bufp + *bufcntp, rex_8bit[byte]);
1269 *bufcntp = cp - d->bufp;
1275 d->bufp[(*bufcntp)++] = "acdb"[byte & 3];
1276 d->bufp[(*bufcntp)++] = "lh"[byte >> 2];
1284 FCT_oreg$w (struct output_data *d)
1286 /* Special form where register comes from opcode. The rex.B bit is used,
1287 rex.R and rex.X are ignored. */
1288 int save_prefixes = *d->prefixes;
1290 *d->prefixes = ((save_prefixes & ~has_rex_r)
1291 | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
1293 int r = FCT_reg$w (d);
1295 *d->prefixes = save_prefixes;
1303 FCT_freg (struct output_data *d)
1305 assert (d->opoff1 / 8 == 1);
1306 assert (d->opoff1 % 8 == 5);
1307 size_t *bufcntp = d->bufcntp;
1308 size_t avail = d->bufsize - *bufcntp;
1309 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%st(%" PRIx32 ")",
1310 (uint32_t) (d->data[1] & 7));
1311 if ((size_t) needed > avail)
1312 return (size_t) needed - avail;
1320 FCT_reg16 (struct output_data *d)
1322 if (*d->prefixes & has_data16)
1325 *d->prefixes |= has_data16;
1332 FCT_sel (struct output_data *d)
1334 assert (d->opoff1 % 8 == 0);
1335 assert (d->opoff1 / 8 == 5);
1336 if (*d->param_start + 2 > d->end)
1338 *d->param_start += 2;
1339 uint16_t absval = read_2ubyte_unaligned (&d->data[5]);
1341 size_t *bufcntp = d->bufcntp;
1342 size_t avail = d->bufsize - *bufcntp;
1343 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, absval);
1344 if ((size_t) needed > avail)
1345 return needed - avail;
1352 FCT_sreg2 (struct output_data *d)
1354 uint_fast8_t byte = d->data[d->opoff1 / 8];
1355 assert (d->opoff1 % 8 + 3 <= 8);
1356 byte >>= 8 - (d->opoff1 % 8 + 2);
1358 size_t *bufcntp = d->bufcntp;
1359 char *bufp = d->bufp;
1360 if (*bufcntp + 3 > d->bufsize)
1361 return *bufcntp + 3 - d->bufsize;
1363 bufp[(*bufcntp)++] = '%';
1364 bufp[(*bufcntp)++] = "ecsd"[byte & 3];
1365 bufp[(*bufcntp)++] = 's';
1372 FCT_sreg3 (struct output_data *d)
1374 uint_fast8_t byte = d->data[d->opoff1 / 8];
1375 assert (d->opoff1 % 8 + 4 <= 8);
1376 byte >>= 8 - (d->opoff1 % 8 + 3);
1378 if ((byte & 7) >= 6)
1381 size_t *bufcntp = d->bufcntp;
1382 char *bufp = d->bufp;
1383 if (*bufcntp + 3 > d->bufsize)
1384 return *bufcntp + 3 - d->bufsize;
1386 bufp[(*bufcntp)++] = '%';
1387 bufp[(*bufcntp)++] = "ecsdfg"[byte & 7];
1388 bufp[(*bufcntp)++] = 's';
1395 FCT_string (struct output_data *d __attribute__ ((unused)))
1402 FCT_xmmreg (struct output_data *d)
1404 uint_fast8_t byte = d->data[d->opoff1 / 8];
1405 assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
1406 byte = (byte >> (5 - d->opoff1 % 8)) & 7;
1408 size_t *bufcntp = d->bufcntp;
1409 size_t avail = d->bufsize - *bufcntp;
1410 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, byte);
1411 if ((size_t) needed > avail)
1412 return needed - avail;