summaryrefslogtreecommitdiff
path: root/libcpu/i386_data.h
diff options
context:
space:
mode:
Diffstat (limited to 'libcpu/i386_data.h')
-rw-r--r--libcpu/i386_data.h1406
1 files changed, 1406 insertions, 0 deletions
diff --git a/libcpu/i386_data.h b/libcpu/i386_data.h
new file mode 100644
index 00000000..38e99354
--- /dev/null
+++ b/libcpu/i386_data.h
@@ -0,0 +1,1406 @@
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <libasm.h>
+
+struct instr_enc
+{
+ /* The mnemonic. Especially encoded for the optimized table. */
+ unsigned int mnemonic : MNEMONIC_BITS;
+
+ /* The rep/repe prefixes. */
+ unsigned int rep : 1;
+ unsigned int repe : 1;
+
+ /* Mnemonic suffix. */
+ unsigned int suffix : SUFFIX_BITS;
+
+ /* Nonzero if the instruction uses modr/m. */
+ unsigned int modrm : 1;
+
+ /* 1st parameter. */
+ unsigned int fct1 : FCT1_BITS;
+#ifdef STR1_BITS
+ unsigned int str1 : STR1_BITS;
+#endif
+ unsigned int off1_1 : OFF1_1_BITS;
+ unsigned int off1_2 : OFF1_2_BITS;
+ unsigned int off1_3 : OFF1_3_BITS;
+
+ /* 2nd parameter. */
+ unsigned int fct2 : FCT2_BITS;
+#ifdef STR2_BITS
+ unsigned int str2 : STR2_BITS;
+#endif
+ unsigned int off2_1 : OFF2_1_BITS;
+ unsigned int off2_2 : OFF2_2_BITS;
+ unsigned int off2_3 : OFF2_3_BITS;
+
+ /* 3rd parameter. */
+ unsigned int fct3 : FCT3_BITS;
+#ifdef STR3_BITS
+ unsigned int str3 : STR3_BITS;
+#endif
+ unsigned int off3_1 : OFF3_1_BITS;
+#ifdef OFF3_2_BITS
+ unsigned int off3_2 : OFF3_2_BITS;
+#endif
+#ifdef OFF3_3_BITS
+ unsigned int off3_3 : OFF3_3_BITS;
+#endif
+};
+
+
+typedef int (*opfct_t) (GElf_Addr, int *, const char *, size_t, size_t, size_t,
+ char *, size_t *, size_t, const uint8_t *data,
+ const uint8_t **param_start, const uint8_t *end,
+ DisasmGetSymCB_t, void *);
+
+
+static int
+data_prefix (int *prefixes, char *bufp, size_t *bufcntp, size_t bufsize)
+{
+ char ch = '\0';
+ if (*prefixes & has_cs)
+ {
+ ch = 'c';
+ *prefixes &= ~has_cs;
+ }
+ else if (*prefixes & has_ds)
+ {
+ ch = 'd';
+ *prefixes &= ~has_ds;
+ }
+ else if (*prefixes & has_es)
+ {
+ ch = 'e';
+ *prefixes &= has_es;
+ }
+ else if (*prefixes & has_fs)
+ {
+ ch = 'f';
+ *prefixes &= ~has_fs;
+ }
+ else if (*prefixes & has_gs)
+ {
+ ch = 'g';
+ *prefixes &= ~has_gs;
+ }
+ else if (*prefixes & has_ss)
+ {
+ ch = 's';
+ *prefixes &= ~has_ss;
+ }
+ else
+ return 0;
+
+ if (*bufcntp + 4 > bufsize)
+ return *bufcntp + 4 - bufsize;
+
+ bufp[(*bufcntp)++] = '%';
+ bufp[(*bufcntp)++] = ch;
+ bufp[(*bufcntp)++] = 's';
+ bufp[(*bufcntp)++] = ':';
+
+ return 0;
+}
+
+static const char regs[8][4] =
+ {
+ "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
+ };
+
+static int
+general_mod$r_m (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ int r = data_prefix (prefixes, bufp, bufcntp, bufsize);
+ if (r != 0)
+ return r;
+
+ uint_fast8_t modrm = data[opoff1 / 8];
+ if ((*prefixes & has_addr16) == 0)
+ {
+ if ((modrm & 7) != 4)
+ {
+ int32_t disp = 0;
+ bool nodisp = false;
+
+ if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80)
+ /* 32 bit displacement. */
+ disp = read_4sbyte_unaligned (&data[opoff1 / 8 + 1]);
+ else if ((modrm & 0xc0) == 0x40)
+ /* 8 bit displacement. */
+ disp = *(const int8_t *) &data[opoff1 / 8 + 1];
+ else if ((modrm & 0xc0) == 0)
+ nodisp = true;
+
+ char tmpbuf[sizeof ("-0x12345678(%rrr)")];
+ int n;
+ if (nodisp)
+ n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)", regs[modrm & 7]);
+ else if ((modrm & 0xc7) != 5)
+ n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%s)",
+ disp < 0 ? "-" : "", disp < 0 ? -disp : disp,
+ regs[modrm & 7]);
+ else
+ n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp);
+
+ if (*bufcntp + n + 1 > bufsize)
+ return *bufcntp + n + 1 - bufsize;
+
+ memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
+ *bufcntp += n;
+ }
+ else
+ {
+ /* SIB */
+ uint_fast8_t sib = data[opoff1 / 8 + 1];
+ int32_t disp = 0;
+ bool nodisp = false;
+
+ if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80
+ || ((modrm & 0xc7) == 0x4 && (sib & 0x7) == 0x5))
+ /* 32 bit displacement. */
+ disp = read_4sbyte_unaligned (&data[opoff1 / 8 + 2]);
+ else if ((modrm & 0xc0) == 0x40)
+ /* 8 bit displacement. */
+ disp = *(const int8_t *) &data[opoff1 / 8 + 2];
+ else
+ nodisp = true;
+
+ char tmpbuf[sizeof ("-0x12345678(%rrr,%rrr,N)")];
+ char *cp = tmpbuf;
+ int n;
+ if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25)
+ {
+ if (!nodisp)
+ {
+ n = snprintf (cp, sizeof (tmpbuf), "%s0x%" PRIx32,
+ disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
+ cp += n;
+ }
+
+ *cp++ = '(';
+
+ if ((modrm & 0xc7) != 0x4 || (sib & 0x7) != 0x5)
+ {
+ *cp++ = '%';
+ cp = mempcpy (cp, regs[sib & 7], 3);
+ }
+
+ if ((sib & 0x38) != 0x20)
+ {
+ *cp++ = ',';
+ *cp++ = '%';
+ cp = mempcpy (cp, regs[(sib >> 3) & 7], 3);
+
+ *cp++ = ',';
+ *cp++ = '0' + (1 << (sib >> 6));
+ }
+
+ *cp++ = ')';
+ }
+ else
+ {
+ assert (! nodisp);
+ n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx32, disp);
+ cp += n;
+ }
+
+ if (*bufcntp + (cp - tmpbuf) > bufsize)
+ return *bufcntp + (cp - tmpbuf) - bufsize;
+
+ memcpy (&bufp[*bufcntp], tmpbuf, cp - tmpbuf);
+ *bufcntp += cp - tmpbuf;
+ }
+ }
+ return 0;
+}
+
+
+static int
+FCT_MOD$R_M (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ assert (opoff1 % 8 == 0);
+ uint_fast8_t modrm = data[opoff1 / 8];
+ if ((modrm & 0xc0) == 0xc0)
+ {
+ uint_fast8_t byte = data[opoff2 / 8] & 7;
+ assert (opoff2 % 8 == 5);
+ size_t avail = bufsize - *bufcntp;
+ int needed;
+ if (*prefixes & (has_rep | has_repne))
+ needed = snprintf (&bufp[*bufcntp], avail, "%%%s", regs[byte]);
+ else
+ needed = snprintf (&bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+ }
+
+ return general_mod$r_m (addr, prefixes, op1str, opoff1, opoff2, opoff3, bufp,
+ bufcntp, bufsize, data, param_start, end,
+ symcb, symcbarg);
+}
+
+
+static int
+FCT_Mod$R_m (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ assert (opoff1 % 8 == 0);
+ uint_fast8_t modrm = data[opoff1 / 8];
+ if ((modrm & 0xc0) == 0xc0)
+ {
+ uint_fast8_t byte = data[opoff2 / 8] & 7;
+ assert (opoff2 % 8 == 5);
+ size_t avail = bufsize - *bufcntp;
+ int needed = snprintf (&bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, byte);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+ }
+
+ return general_mod$r_m (addr, prefixes, op1str, opoff1, opoff2, opoff3, bufp,
+ bufcntp, bufsize, data, param_start, end,
+ symcb, symcbarg);
+}
+
+static int
+generic_abs (int *prefixes __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)),
+ const char *absstring)
+{
+ int r = data_prefix (prefixes, bufp, bufcntp, bufsize);
+ if (r != 0)
+ return r;
+
+ assert (opoff1 % 8 == 0);
+ assert (opoff1 / 8 == 1);
+ if (*param_start + 4 > end)
+ return -1;
+ *param_start += 4;
+ uint32_t absval = read_4ubyte_unaligned (&data[1]);
+ size_t avail = bufsize - *bufcntp;
+ int needed = snprintf (&bufp[*bufcntp], avail, "%s0x%" PRIx32,
+ absstring, absval);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+static int
+FCT_absval (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ return generic_abs (prefixes, opoff1, bufp,
+ bufcntp, bufsize, data, param_start, end, symcb,
+ symcbarg, "$");
+}
+
+static int
+FCT_abs (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ return generic_abs (prefixes, opoff1, bufp,
+ bufcntp, bufsize, data, param_start, end, symcb,
+ symcbarg, "");
+}
+
+static int
+FCT_ax (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ int is_16bit = (*prefixes & has_data16) != 0;
+
+ if (*bufcntp + 4 - is_16bit > bufsize)
+ return *bufcntp + 4 - is_16bit - bufsize;
+
+ bufp[(*bufcntp)++] = '%';
+ if (! is_16bit)
+ bufp[(*bufcntp)++] = 'e';
+ bufp[(*bufcntp)++] = 'a';
+ bufp[(*bufcntp)++] = 'x';
+
+ return 0;
+}
+
+static int
+FCT_ax$w (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ if ((data[opoff2 / 8] & (1 << (7 - (opoff2 & 7)))) != 0)
+ return FCT_ax (addr, prefixes, op1str, opoff1, opoff2, opoff3, bufp,
+ bufcntp, bufsize, data, param_start, end, symcb, symcbarg);
+
+ if (*bufcntp + 3 > bufsize)
+ return *bufcntp + 3 - bufsize;
+
+ bufp[(*bufcntp)++] = '%';
+ bufp[(*bufcntp)++] = 'a';
+ bufp[(*bufcntp)++] = 'l';
+
+ return 0;
+}
+
+static int
+FCT_ccc (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ if (*prefixes & has_data16)
+ return -1;
+
+ assert (opoff1 % 8 == 2);
+ size_t avail = bufsize - *bufcntp;
+ int needed = snprintf (&bufp[*bufcntp], avail, "%%cr%" PRIx32,
+ (uint32_t) (data[opoff1 / 8] >> 3) & 7);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+static int
+FCT_ddd (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ if (*prefixes & has_data16)
+ return -1;
+
+ assert (opoff1 % 8 == 2);
+ size_t avail = bufsize - *bufcntp;
+ int needed = snprintf (&bufp[*bufcntp], avail, "%%db%" PRIx32,
+ (uint32_t) (data[opoff1 / 8] >> 3) & 7);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+static int
+FCT_disp8 (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ assert (opoff1 % 8 == 0);
+ int32_t offset = *(const int8_t *) (*param_start)++;
+ size_t avail = bufsize - *bufcntp;
+ int needed = snprintf (&bufp[*bufcntp], avail, "0x%" PRIx32,
+ (uint32_t) (addr + (*param_start - data) + offset));
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+static int
+__attribute__ ((noinline))
+FCT_ds_xx (const char *reg,
+ int *prefixes __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)))
+{
+ int prefix = *prefixes & SEGMENT_PREFIXES;
+
+ if (prefix == 0)
+ prefix = has_ds;
+ /* Make sure only one bit is set. */
+ else if ((prefix - 1) & prefix)
+ return -1;
+ else
+ *prefixes ^= prefix;
+
+ int r = data_prefix (&prefix, bufp, bufcntp, bufsize);
+ if (r != 0)
+ return r;
+
+ size_t avail = bufsize - *bufcntp;
+ int needed = snprintf (&bufp[*bufcntp], avail, "(%%%s%s)",
+ *prefixes & idx_addr16 ? "" : "e", reg);
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+
+ return 0;
+}
+
+static int
+FCT_ds_bx (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ return FCT_ds_xx ("bx", prefixes, bufp, bufcntp, bufsize);
+}
+
+static int
+FCT_ds_si (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ return FCT_ds_xx ("si", prefixes, bufp, bufcntp, bufsize);
+}
+
+static int
+FCT_dx (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ if (*bufcntp + 7 > bufsize)
+ return *bufcntp + 7 - bufsize;
+
+ memcpy (&bufp[*bufcntp], "(%dx)", 5);
+ *bufcntp += 5;
+
+ return 0;
+}
+
+static int
+FCT_es_di (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ size_t avail = bufsize - *bufcntp;
+ int needed = snprintf (&bufp[*bufcntp], avail, "%%es:(%%%sdi)",
+ *prefixes & idx_addr16 ? "" : "e");
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+
+ return 0;
+}
+
+static int
+FCT_imm (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ size_t avail = bufsize - *bufcntp;
+ int needed;
+ if (*prefixes & has_data16)
+ {
+ if (*param_start + 2 > end)
+ return -1;
+ uint16_t word = read_2ubyte_unaligned_inc (*param_start);
+ needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx16, word);
+ }
+ else
+ {
+ if (*param_start + 4 > end)
+ return -1;
+ uint32_t word = read_4ubyte_unaligned_inc (*param_start);
+ needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx32, word);
+ }
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+static int
+FCT_imm$w (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ if ((data[opoff2 / 8] & (1 << (7 - (opoff2 & 7)))) != 0)
+ return FCT_imm (addr, prefixes, op1str, opoff1, opoff2, opoff3, bufp,
+ bufcntp, bufsize, data, param_start, end, symcb, symcbarg);
+
+ size_t avail = bufsize - *bufcntp;
+ uint_fast8_t word = *(*param_start)++;
+ int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIxFAST8, word);
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+static int
+FCT_imms (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ size_t avail = bufsize - *bufcntp;
+ int_fast8_t byte = *(*param_start)++;
+ int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx32,
+ (int32_t) byte);
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+static int
+FCT_imm$s (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ uint_fast8_t opcode = data[opoff2 / 8];
+ size_t avail = bufsize - *bufcntp;
+ if ((opcode & 2) != 0)
+ return FCT_imms (addr, prefixes, op1str, opoff1, opoff2, opoff3, bufp,
+ bufcntp, bufsize, data, param_start, end, symcb,
+ symcbarg);
+
+ if ((*prefixes & has_data16) == 0)
+ {
+ if (*param_start + 4 > end)
+ return -1;
+ uint32_t word = read_4ubyte_unaligned_inc (*param_start);
+ int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx32, word);
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ }
+ else
+ {
+ if (*param_start + 2 > end)
+ return -1;
+ uint16_t word = read_2ubyte_unaligned_inc (*param_start);
+ int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx16, word);
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ }
+ return 0;
+}
+
+static int
+FCT_imm16 (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ if (*param_start + 2 > end)
+ return -1;
+ uint16_t word = read_2ubyte_unaligned_inc (*param_start);
+ size_t avail = bufsize - *bufcntp;
+ int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx16, word);
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+static int
+FCT_imms8 (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ size_t avail = bufsize - *bufcntp;
+ int_fast8_t byte = *(*param_start)++;
+ int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx32,
+ (int32_t) byte);
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+static int
+FCT_imm8 (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ size_t avail = bufsize - *bufcntp;
+ uint_fast8_t byte = *(*param_start)++;
+ int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx32,
+ (uint32_t) byte);
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+#ifndef X86_64
+static int
+FCT_rel (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ size_t avail = bufsize - *bufcntp;
+ if (*param_start + 4 > end)
+ return -1;
+ uint32_t rel = read_4ubyte_unaligned_inc (*param_start);
+ int needed = snprintf (&bufp[*bufcntp], avail, "0x%" PRIx32,
+ (uint32_t) (addr + rel + (*param_start - data)));
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+#endif
+
+static int
+FCT_mmxreg (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ uint_fast8_t byte = data[opoff1 / 8];
+ assert (opoff1 % 8 == 2 || opoff1 % 8 == 5);
+ byte = (byte >> (5 - opoff1 % 8)) & 7;
+ size_t avail = bufsize - *bufcntp;
+ int needed = snprintf (&bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+static int
+FCT_mmxreg2 (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ uint_fast8_t byte = data[opoff1 / 8];
+ assert (opoff1 % 8 == 2 || opoff1 % 8 == 5);
+ byte = (byte >> (5 - opoff1 % 8)) & 7;
+ size_t avail = bufsize - *bufcntp;
+ int needed;
+ if (*prefixes & (has_rep | has_repne))
+ needed = snprintf (&bufp[*bufcntp], avail, "%%%s", regs[byte]);
+ else
+ needed = snprintf (&bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+
+static int
+FCT_mod$r_m (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ assert (opoff1 % 8 == 0);
+ uint_fast8_t modrm = data[opoff1 / 8];
+ if ((modrm & 0xc0) == 0xc0)
+ {
+ int is_16bit = (*prefixes & has_data16) != 0;
+
+ if (*bufcntp + 5 - is_16bit > bufsize)
+ return *bufcntp + 5 - is_16bit - bufsize;
+ bufp[(*bufcntp)++] = '%';
+ memcpy (&bufp[*bufcntp], regs[modrm & 7] + is_16bit,
+ sizeof (regs[0]) - is_16bit);
+ *bufcntp += 3 - is_16bit;
+ return 0;
+ }
+
+ return general_mod$r_m (addr, prefixes, op1str, opoff1, opoff2, opoff3, bufp,
+ bufcntp, bufsize, data, param_start, end,
+ symcb, symcbarg);
+}
+
+
+#ifndef X86_64
+static int
+FCT_moda$r_m (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ int r = data_prefix (prefixes, bufp, bufcntp, bufsize);
+ if (r != 0)
+ return r;
+
+ assert (opoff1 % 8 == 0);
+ uint_fast8_t modrm = data[opoff1 / 8];
+ if ((modrm & 0xc0) == 0xc0)
+ {
+ if (*bufcntp + 3 > bufsize)
+ return *bufcntp + 3 - bufsize;
+
+ memcpy (&bufp[*bufcntp], "???", 3);
+ *bufcntp += 3;
+
+ return 0;
+ }
+
+ return general_mod$r_m (addr, prefixes, op1str, opoff1, opoff2, opoff3, bufp,
+ bufcntp, bufsize, data, param_start, end,
+ symcb, symcbarg);
+}
+#endif
+
+
+static int
+FCT_mod$r_m$w (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ int r = data_prefix (prefixes, bufp, bufcntp, bufsize);
+ if (r != 0)
+ return r;
+
+ assert (opoff1 % 8 == 0);
+ uint_fast8_t modrm = data[opoff1 / 8];
+ if ((modrm & 0xc0) == 0xc0)
+ {
+ if ((data[opoff3 / 8] & (1 << (7 - (opoff3 & 7)))) == 0)
+ {
+ if (*bufcntp + 3 > bufsize)
+ return *bufcntp + 3 - bufsize;
+ bufp[(*bufcntp)++] = '%';
+ bufp[(*bufcntp)++] = "acdb"[modrm & 3];
+ bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
+ }
+ else
+ {
+ int is_16bit = (*prefixes & has_data16) != 0;
+
+ if (*bufcntp + 5 - is_16bit > bufsize)
+ return *bufcntp + 5 - is_16bit - bufsize;
+ bufp[(*bufcntp)++] = '%';
+ memcpy (&bufp[*bufcntp], regs[modrm & 7] + is_16bit,
+ sizeof (regs[0]) - is_16bit);
+ *bufcntp += 3 - is_16bit;
+ }
+ return 0;
+ }
+
+ return general_mod$r_m (addr, prefixes, op1str, opoff1, opoff2, opoff3, bufp,
+ bufcntp, bufsize, data, param_start, end,
+ symcb, symcbarg);
+}
+
+
+#ifndef X86_64
+static int
+FCT_mod$8r_m (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ assert (opoff1 % 8 == 0);
+ uint_fast8_t modrm = data[opoff1 / 8];
+ if ((modrm & 0xc0) == 0xc0)
+ {
+ if (*bufcntp + 3 > bufsize)
+ return *bufcntp + 3 - bufsize;
+ bufp[(*bufcntp)++] = '%';
+ bufp[(*bufcntp)++] = "acdb"[modrm & 3];
+ bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
+ return 0;
+ }
+
+ return general_mod$r_m (addr, prefixes, op1str, opoff1, opoff2, opoff3, bufp,
+ bufcntp, bufsize, data, param_start, end,
+ symcb, symcbarg);
+}
+#endif
+
+static int
+FCT_mod$16r_m (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ assert (opoff1 % 8 == 0);
+ uint_fast8_t modrm = data[opoff1 / 8];
+ if ((modrm & 0xc0) == 0xc0)
+ {
+ uint_fast8_t byte = data[opoff1 / 8] & 7;
+ if (*bufcntp + 3 > bufsize)
+ return *bufcntp + 3 - bufsize;
+ bufp[(*bufcntp)++] = '%';
+ memcpy (&bufp[*bufcntp], regs[byte] + 1, sizeof (regs[0]) - 1);
+ *bufcntp += 2;
+ return 0;
+ }
+
+ return general_mod$r_m (addr, prefixes, op1str, opoff1, opoff2, opoff3, bufp,
+ bufcntp, bufsize, data, param_start, end,
+ symcb, symcbarg);
+}
+
+static int
+FCT_reg (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ uint_fast8_t byte = data[opoff1 / 8];
+ assert (opoff1 % 8 + 3 <= 8);
+ byte >>= 8 - (opoff1 % 8 + 3);
+ byte &= 7;
+ int is_16bit = (*prefixes & has_data16) != 0;
+ if (*bufcntp + 4 > bufsize)
+ return *bufcntp + 4 - bufsize;
+ bufp[(*bufcntp)++] = '%';
+ memcpy (&bufp[*bufcntp], regs[byte] + is_16bit, sizeof (regs[0]) - is_16bit);
+ *bufcntp += 3 - is_16bit;
+ return 0;
+}
+
+static int
+FCT_reg$w (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ if (data[opoff2 / 8] & (1 << (7 - (opoff2 & 7))))
+ return FCT_reg (addr, prefixes, op1str, opoff1, opoff2, opoff3, bufp,
+ bufcntp, bufsize, data, param_start, end, symcb, symcbarg);
+ uint_fast8_t byte = data[opoff1 / 8];
+ assert (opoff1 % 8 + 3 <= 8);
+ byte >>= 8 - (opoff1 % 8 + 3);
+ byte &= 7;
+ if (*bufcntp + 3 > bufsize)
+ return *bufcntp + 3 - bufsize;
+ bufp[(*bufcntp)++] = '%';
+ bufp[(*bufcntp)++] = "acdb"[byte & 3];
+ bufp[(*bufcntp)++] = "lh"[byte >> 2];
+ return 0;
+}
+
+#ifndef X86_64
+static int
+FCT_freg (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ assert (opoff1 / 8 == 1);
+ assert (opoff1 % 8 == 5);
+ size_t avail = bufsize - *bufcntp;
+ int needed = snprintf (&bufp[*bufcntp], avail, "%%st(%" PRIx32 ")",
+ (uint32_t) (data[1] & 7));
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+static int
+FCT_reg16 (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ if (*prefixes & has_data16)
+ return -1;
+
+ *prefixes |= has_data16;
+ return FCT_reg (addr, prefixes, op1str, opoff1, opoff2, opoff3, bufp,
+ bufcntp, bufsize, data, param_start, end, symcb, symcbarg);
+}
+#endif
+
+static int
+FCT_sel (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ assert (opoff1 % 8 == 0);
+ assert (opoff1 / 8 == 5);
+ if (*param_start + 2 > end)
+ return -1;
+ *param_start += 2;
+ uint16_t absval = read_2ubyte_unaligned (&data[5]);
+ size_t avail = bufsize - *bufcntp;
+ int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx16, absval);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+static int
+FCT_sreg2 (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ uint_fast8_t byte = data[opoff1 / 8];
+ assert (opoff1 % 8 + 3 <= 8);
+ byte >>= 8 - (opoff1 % 8 + 2);
+
+ if (*bufcntp + 3 > bufsize)
+ return *bufcntp + 3 - bufsize;
+
+ bufp[(*bufcntp)++] = '%';
+ bufp[(*bufcntp)++] = "ecsd"[byte & 3];
+ bufp[(*bufcntp)++] = 's';
+
+ return 0;
+}
+
+static int
+FCT_sreg3 (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ uint_fast8_t byte = data[opoff1 / 8];
+ assert (opoff1 % 8 + 4 <= 8);
+ byte >>= 8 - (opoff1 % 8 + 3);
+
+ if ((byte & 7) >= 6)
+ return -1;
+
+ if (*bufcntp + 3 > bufsize)
+ return *bufcntp + 3 - bufsize;
+
+ bufp[(*bufcntp)++] = '%';
+ bufp[(*bufcntp)++] = "ecsdfg"[byte & 7];
+ bufp[(*bufcntp)++] = 's';
+
+ return 0;
+}
+
+static int
+FCT_string (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ return 0;
+}
+
+static int
+FCT_xmmreg (GElf_Addr addr __attribute__ ((unused)),
+ int *prefixes __attribute__ ((unused)),
+ const char *op1str __attribute__ ((unused)),
+ size_t opoff1 __attribute__ ((unused)),
+ size_t opoff2 __attribute__ ((unused)),
+ size_t opoff3 __attribute__ ((unused)),
+ char *bufp __attribute__ ((unused)),
+ size_t *bufcntp __attribute__ ((unused)),
+ size_t bufsize __attribute__ ((unused)),
+ const uint8_t *data __attribute__ ((unused)),
+ const uint8_t **param_start __attribute__ ((unused)),
+ const uint8_t *end __attribute__ ((unused)),
+ DisasmGetSymCB_t symcb __attribute__ ((unused)),
+ void *symcbarg __attribute__ ((unused)))
+{
+ uint_fast8_t byte = data[opoff1 / 8];
+ assert (opoff1 % 8 == 2 || opoff1 % 8 == 5);
+ byte = (byte >> (5 - opoff1 % 8)) & 7;
+ size_t avail = bufsize - *bufcntp;
+ int needed = snprintf (&bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, byte);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+}