summaryrefslogtreecommitdiffstats
path: root/src/libcpu/i386_data.h
diff options
context:
space:
mode:
authorChih-hung Hsieh <chh@google.com>2015-09-25 14:51:48 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-09-25 14:51:48 +0000
commitb0121c5547604527aaeea297b54047cd14b234df (patch)
tree7d9031ee3d5796de4a1825892fc6e04ba6e36ae2 /src/libcpu/i386_data.h
parentd03895cf5f8b77c6a85abcd84ea0d80ff56be846 (diff)
parent5eafdf0f9bfd9a3c5f93414ac16bb399b6da0b7f (diff)
downloadandroid_external_elfutils-b0121c5547604527aaeea297b54047cd14b234df.tar.gz
android_external_elfutils-b0121c5547604527aaeea297b54047cd14b234df.tar.bz2
android_external_elfutils-b0121c5547604527aaeea297b54047cd14b234df.zip
Merge "Move files up to match upstream source structure."
Diffstat (limited to 'src/libcpu/i386_data.h')
-rw-r--r--src/libcpu/i386_data.h1418
1 files changed, 0 insertions, 1418 deletions
diff --git a/src/libcpu/i386_data.h b/src/libcpu/i386_data.h
deleted file mode 100644
index b8a34c3e..00000000
--- a/src/libcpu/i386_data.h
+++ /dev/null
@@ -1,1418 +0,0 @@
-/* Helper routines for disassembler for x86/x86-64.
- Copyright (C) 2007, 2008 Red Hat, Inc.
- This file is part of elfutils.
- Written by Ulrich Drepper <drepper@redhat.com>, 2007.
-
- This file is free software; you can redistribute it and/or modify
- it under the terms of either
-
- * the GNU Lesser General Public License as published by the Free
- Software Foundation; either version 3 of the License, or (at
- your option) any later version
-
- or
-
- * the GNU General Public License as published by the Free
- Software Foundation; either version 2 of the License, or (at
- your option) any later version
-
- or both in parallel, as here.
-
- elfutils is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received copies of the GNU General Public License and
- the GNU Lesser General Public License along with this program. If
- not, see <http://www.gnu.org/licenses/>. */
-
-#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) (struct output_data *);
-
-
-static int
-data_prefix (struct output_data *d)
-{
- char ch = '\0';
- if (*d->prefixes & has_cs)
- {
- ch = 'c';
- *d->prefixes &= ~has_cs;
- }
- else if (*d->prefixes & has_ds)
- {
- ch = 'd';
- *d->prefixes &= ~has_ds;
- }
- else if (*d->prefixes & has_es)
- {
- ch = 'e';
- *d->prefixes &= ~has_es;
- }
- else if (*d->prefixes & has_fs)
- {
- ch = 'f';
- *d->prefixes &= ~has_fs;
- }
- else if (*d->prefixes & has_gs)
- {
- ch = 'g';
- *d->prefixes &= ~has_gs;
- }
- else if (*d->prefixes & has_ss)
- {
- ch = 's';
- *d->prefixes &= ~has_ss;
- }
- else
- return 0;
-
- if (*d->bufcntp + 4 > d->bufsize)
- return *d->bufcntp + 4 - d->bufsize;
-
- d->bufp[(*d->bufcntp)++] = '%';
- d->bufp[(*d->bufcntp)++] = ch;
- d->bufp[(*d->bufcntp)++] = 's';
- d->bufp[(*d->bufcntp)++] = ':';
-
- return 0;
-}
-
-#ifdef X86_64
-static const char hiregs[8][4] =
- {
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
- };
-static const char aregs[8][4] =
- {
- "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"
- };
-static const char dregs[8][4] =
- {
- "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
- };
-#else
-static const char aregs[8][4] =
- {
- "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
- };
-# define dregs aregs
-#endif
-
-static int
-general_mod$r_m (struct output_data *d)
-{
- int r = data_prefix (d);
- if (r != 0)
- return r;
-
- int prefixes = *d->prefixes;
- const uint8_t *data = &d->data[d->opoff1 / 8];
- char *bufp = d->bufp;
- size_t *bufcntp = d->bufcntp;
- size_t bufsize = d->bufsize;
-
- uint_fast8_t modrm = data[0];
-#ifndef X86_64
- if (unlikely ((prefixes & has_addr16) != 0))
- {
- int16_t disp = 0;
- bool nodisp = false;
-
- if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80)
- /* 16 bit displacement. */
- disp = read_2sbyte_unaligned (&data[1]);
- else if ((modrm & 0xc0) == 0x40)
- /* 8 bit displacement. */
- disp = *(const int8_t *) &data[1];
- else if ((modrm & 0xc0) == 0)
- nodisp = true;
-
- char tmpbuf[sizeof ("-0x1234(%rr,%rr)")];
- int n;
- if ((modrm & 0xc7) == 6)
- n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx16, disp);
- else
- {
- n = 0;
- if (!nodisp)
- n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx16,
- disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
-
- if ((modrm & 0x4) == 0)
- n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%b%c,%%%ci)",
- "xp"[(modrm >> 1) & 1], "sd"[modrm & 1]);
- else
- n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%%s)",
- ((const char [4][3]) { "si", "di", "bp", "bx" })[modrm & 3]);
- }
-
- if (*bufcntp + n + 1 > bufsize)
- return *bufcntp + n + 1 - bufsize;
-
- memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
- *bufcntp += n;
- }
- else
-#endif
- {
- 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[1]);
- else if ((modrm & 0xc0) == 0x40)
- /* 8 bit displacement. */
- disp = *(const int8_t *) &data[1];
- else if ((modrm & 0xc0) == 0)
- nodisp = true;
-
- char tmpbuf[sizeof ("-0x12345678(%rrrr)")];
- int n;
- if (nodisp)
- {
- n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)",
-#ifdef X86_64
- (prefixes & has_rex_b) ? hiregs[modrm & 7] :
-#endif
- aregs[modrm & 7]);
-#ifdef X86_64
- if (prefixes & has_addr16)
- {
- if (prefixes & has_rex_b)
- tmpbuf[n++] = 'd';
- else
- tmpbuf[2] = 'e';
- }
-#endif
- }
- else if ((modrm & 0xc7) != 5)
- {
- int p;
- n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%n%s)",
- disp < 0 ? "-" : "", disp < 0 ? -disp : disp, &p,
-#ifdef X86_64
- (prefixes & has_rex_b) ? hiregs[modrm & 7] :
-#endif
- aregs[modrm & 7]);
-#ifdef X86_64
- if (prefixes & has_addr16)
- {
- if (prefixes & has_rex_b)
- tmpbuf[n++] = 'd';
- else
- tmpbuf[p] = 'e';
- }
-#endif
- }
- else
- {
-#ifdef X86_64
- n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%rip)",
- disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
-
- d->symaddr_use = addr_rel_always;
- d->symaddr = disp;
-#else
- n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp);
-#endif
- }
-
- 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[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[2]);
- else if ((modrm & 0xc0) == 0x40)
- /* 8 bit displacement. */
- disp = *(const int8_t *) &data[2];
- else
- nodisp = true;
-
- char tmpbuf[sizeof ("-0x12345678(%rrrr,%rrrr,N)")];
- char *cp = tmpbuf;
- int n;
- if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25
-#ifdef X86_64
- || (prefixes & has_rex_x) != 0
-#endif
- )
- {
- 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 = stpcpy (cp,
-#ifdef X86_64
- (prefixes & has_rex_b) ? hiregs[sib & 7] :
- (prefixes & has_addr16) ? dregs[sib & 7] :
-#endif
- aregs[sib & 7]);
-#ifdef X86_64
- if ((prefixes & (has_rex_b | has_addr16))
- == (has_rex_b | has_addr16))
- *cp++ = 'd';
-#endif
- }
-
- if ((sib & 0x38) != 0x20
-#ifdef X86_64
- || (prefixes & has_rex_x) != 0
-#endif
- )
- {
- *cp++ = ',';
- *cp++ = '%';
- cp = stpcpy (cp,
-#ifdef X86_64
- (prefixes & has_rex_x)
- ? hiregs[(sib >> 3) & 7] :
- (prefixes & has_addr16)
- ? dregs[(sib >> 3) & 7] :
-#endif
- aregs[(sib >> 3) & 7]);
-#ifdef X86_64
- if ((prefixes & (has_rex_b | has_addr16))
- == (has_rex_b | has_addr16))
- *cp++ = 'd';
-#endif
-
- *cp++ = ',';
- *cp++ = '0' + (1 << (sib >> 6));
- }
-
- *cp++ = ')';
- }
- else
- {
- assert (! nodisp);
-#ifdef X86_64
- if ((prefixes & has_addr16) == 0)
- n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx64,
- (int64_t) disp);
- else
-#endif
- 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 (struct output_data *d)
-{
- assert (d->opoff1 % 8 == 0);
- uint_fast8_t modrm = d->data[d->opoff1 / 8];
- if ((modrm & 0xc0) == 0xc0)
- {
- assert (d->opoff1 / 8 == d->opoff2 / 8);
- assert (d->opoff2 % 8 == 5);
- //uint_fast8_t byte = d->data[d->opoff2 / 8] & 7;
- uint_fast8_t byte = modrm & 7;
-
- size_t *bufcntp = d->bufcntp;
- char *buf = d->bufp + *bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- int needed;
- if (*d->prefixes & (has_rep | has_repne))
- needed = snprintf (buf, avail, "%%%s", dregs[byte]);
- else
- needed = snprintf (buf, avail, "%%mm%" PRIxFAST8, byte);
- if ((size_t) needed > avail)
- return needed - avail;
- *bufcntp += needed;
- return 0;
- }
-
- return general_mod$r_m (d);
-}
-
-
-static int
-FCT_Mod$R_m (struct output_data *d)
-{
- assert (d->opoff1 % 8 == 0);
- uint_fast8_t modrm = d->data[d->opoff1 / 8];
- if ((modrm & 0xc0) == 0xc0)
- {
- assert (d->opoff1 / 8 == d->opoff2 / 8);
- assert (d->opoff2 % 8 == 5);
- //uint_fast8_t byte = data[opoff2 / 8] & 7;
- uint_fast8_t byte = modrm & 7;
-
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8,
- byte);
- if ((size_t) needed > avail)
- return needed - avail;
- *d->bufcntp += needed;
- return 0;
- }
-
- return general_mod$r_m (d);
-}
-
-static int
-generic_abs (struct output_data *d, const char *absstring
-#ifdef X86_64
- , int abslen
-#else
-# define abslen 4
-#endif
- )
-{
- int r = data_prefix (d);
- if (r != 0)
- return r;
-
- assert (d->opoff1 % 8 == 0);
- assert (d->opoff1 / 8 == 1);
- if (*d->param_start + abslen > d->end)
- return -1;
- *d->param_start += abslen;
-#ifndef X86_64
- uint32_t absval;
-# define ABSPRIFMT PRIx32
-#else
- uint64_t absval;
-# define ABSPRIFMT PRIx64
- if (abslen == 8)
- absval = read_8ubyte_unaligned (&d->data[1]);
- else
-#endif
- absval = read_4ubyte_unaligned (&d->data[1]);
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- int needed = snprintf (&d->bufp[*bufcntp], avail, "%s0x%" ABSPRIFMT,
- absstring, absval);
- if ((size_t) needed > avail)
- return needed - avail;
- *bufcntp += needed;
- return 0;
-}
-
-
-static int
-FCT_absval (struct output_data *d)
-{
- return generic_abs (d, "$"
-#ifdef X86_64
- , 4
-#endif
- );
-}
-
-static int
-FCT_abs (struct output_data *d)
-{
- return generic_abs (d, ""
-#ifdef X86_64
- , 8
-#endif
- );
-}
-
-static int
-FCT_ax (struct output_data *d)
-{
- int is_16bit = (*d->prefixes & has_data16) != 0;
-
- size_t *bufcntp = d->bufcntp;
- char *bufp = d->bufp;
- size_t bufsize = d->bufsize;
-
- if (*bufcntp + 4 - is_16bit > bufsize)
- return *bufcntp + 4 - is_16bit - bufsize;
-
- bufp[(*bufcntp)++] = '%';
- if (! is_16bit)
- bufp[(*bufcntp)++] = (
-#ifdef X86_64
- (*d->prefixes & has_rex_w) ? 'r' :
-#endif
- 'e');
- bufp[(*bufcntp)++] = 'a';
- bufp[(*bufcntp)++] = 'x';
-
- return 0;
-}
-
-
-static int
-FCT_ax$w (struct output_data *d)
-{
- if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
- return FCT_ax (d);
-
- size_t *bufcntp = d->bufcntp;
- char *bufp = d->bufp;
- size_t bufsize = d->bufsize;
-
- if (*bufcntp + 3 > bufsize)
- return *bufcntp + 3 - bufsize;
-
- bufp[(*bufcntp)++] = '%';
- bufp[(*bufcntp)++] = 'a';
- bufp[(*bufcntp)++] = 'l';
-
- return 0;
-}
-
-
-static int
-__attribute__ ((noinline))
-FCT_crdb (struct output_data *d, const char *regstr)
-{
- if (*d->prefixes & has_data16)
- return -1;
-
- size_t *bufcntp = d->bufcntp;
-
- // XXX If this assert is true, use absolute offset below
- assert (d->opoff1 / 8 == 2);
- assert (d->opoff1 % 8 == 2);
- size_t avail = d->bufsize - *bufcntp;
- int needed = snprintf (&d->bufp[*bufcntp], avail, "%%%s%" PRIx32,
- regstr, (uint32_t) (d->data[d->opoff1 / 8] >> 3) & 7);
- if ((size_t) needed > avail)
- return needed - avail;
- *bufcntp += needed;
- return 0;
-}
-
-
-static int
-FCT_ccc (struct output_data *d)
-{
- return FCT_crdb (d, "cr");
-}
-
-
-static int
-FCT_ddd (struct output_data *d)
-{
- return FCT_crdb (d, "db");
-}
-
-
-static int
-FCT_disp8 (struct output_data *d)
-{
- assert (d->opoff1 % 8 == 0);
- if (*d->param_start >= d->end)
- return -1;
- int32_t offset = *(const int8_t *) (*d->param_start)++;
-
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
- (uint32_t) (d->addr + (*d->param_start - d->data)
- + offset));
- if ((size_t) needed > avail)
- return needed - avail;
- *bufcntp += needed;
- return 0;
-}
-
-
-static int
-__attribute__ ((noinline))
-FCT_ds_xx (struct output_data *d, const char *reg)
-{
- int prefix = *d->prefixes & SEGMENT_PREFIXES;
-
- if (prefix == 0)
- *d->prefixes |= prefix = has_ds;
- /* Make sure only one bit is set. */
- else if ((prefix - 1) & prefix)
- return -1;
-
- int r = data_prefix (d);
-
- assert ((*d->prefixes & prefix) == 0);
-
- if (r != 0)
- return r;
-
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- int needed = snprintf (&d->bufp[*bufcntp], avail, "(%%%s%s)",
-#ifdef X86_64
- *d->prefixes & idx_addr16 ? "e" : "r",
-#else
- *d->prefixes & idx_addr16 ? "" : "e",
-#endif
- reg);
- if ((size_t) needed > avail)
- return (size_t) needed - avail;
- *bufcntp += needed;
-
- return 0;
-}
-
-
-static int
-FCT_ds_bx (struct output_data *d)
-{
- return FCT_ds_xx (d, "bx");
-}
-
-
-static int
-FCT_ds_si (struct output_data *d)
-{
- return FCT_ds_xx (d, "si");
-}
-
-
-static int
-FCT_dx (struct output_data *d)
-{
- size_t *bufcntp = d->bufcntp;
-
- if (*bufcntp + 7 > d->bufsize)
- return *bufcntp + 7 - d->bufsize;
-
- memcpy (&d->bufp[*bufcntp], "(%dx)", 5);
- *bufcntp += 5;
-
- return 0;
-}
-
-
-static int
-FCT_es_di (struct output_data *d)
-{
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- int needed = snprintf (&d->bufp[*bufcntp], avail, "%%es:(%%%sdi)",
-#ifdef X86_64
- *d->prefixes & idx_addr16 ? "e" : "r"
-#else
- *d->prefixes & idx_addr16 ? "" : "e"
-#endif
- );
- if ((size_t) needed > avail)
- return (size_t) needed - avail;
- *bufcntp += needed;
-
- return 0;
-}
-
-
-static int
-FCT_imm (struct output_data *d)
-{
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- int needed;
- if (*d->prefixes & has_data16)
- {
- if (*d->param_start + 2 > d->end)
- return -1;
- uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
- needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
- }
- else
- {
- if (*d->param_start + 4 > d->end)
- return -1;
- int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
-#ifdef X86_64
- if (*d->prefixes & has_rex_w)
- needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
- (int64_t) word);
- else
-#endif
- needed = snprintf (&d->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 (struct output_data *d)
-{
- if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
- return FCT_imm (d);
-
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- if (*d->param_start>= d->end)
- return -1;
- uint_fast8_t word = *(*d->param_start)++;
- int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIxFAST8, word);
- if ((size_t) needed > avail)
- return (size_t) needed - avail;
- *bufcntp += needed;
- return 0;
-}
-
-
-#ifdef X86_64
-static int
-FCT_imm64$w (struct output_data *d)
-{
- if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) == 0
- || (*d->prefixes & has_data16) != 0)
- return FCT_imm$w (d);
-
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- int needed;
- if (*d->prefixes & has_rex_w)
- {
- if (*d->param_start + 8 > d->end)
- return -1;
- uint64_t word = read_8ubyte_unaligned_inc (*d->param_start);
- needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, word);
- }
- else
- {
- if (*d->param_start + 4 > d->end)
- return -1;
- int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
- needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
- }
- if ((size_t) needed > avail)
- return (size_t) needed - avail;
- *bufcntp += needed;
- return 0;
-}
-#endif
-
-
-static int
-FCT_imms (struct output_data *d)
-{
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- if (*d->param_start>= d->end)
- return -1;
- int8_t byte = *(*d->param_start)++;
-#ifdef X86_64
- int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
- (int64_t) byte);
-#else
- int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
- (int32_t) byte);
-#endif
- if ((size_t) needed > avail)
- return (size_t) needed - avail;
- *bufcntp += needed;
- return 0;
-}
-
-
-static int
-FCT_imm$s (struct output_data *d)
-{
- uint_fast8_t opcode = d->data[d->opoff2 / 8];
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- if ((opcode & 2) != 0)
- return FCT_imms (d);
-
- if ((*d->prefixes & has_data16) == 0)
- {
- if (*d->param_start + 4 > d->end)
- return -1;
- int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
-#ifdef X86_64
- int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
- (int64_t) word);
-#else
- int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
-#endif
- if ((size_t) needed > avail)
- return (size_t) needed - avail;
- *bufcntp += needed;
- }
- else
- {
- if (*d->param_start + 2 > d->end)
- return -1;
- uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
- int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
- if ((size_t) needed > avail)
- return (size_t) needed - avail;
- *bufcntp += needed;
- }
- return 0;
-}
-
-
-static int
-FCT_imm16 (struct output_data *d)
-{
- if (*d->param_start + 2 > d->end)
- return -1;
- uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
- if ((size_t) needed > avail)
- return (size_t) needed - avail;
- *bufcntp += needed;
- return 0;
-}
-
-
-static int
-FCT_imms8 (struct output_data *d)
-{
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- if (*d->param_start >= d->end)
- return -1;
- int_fast8_t byte = *(*d->param_start)++;
- int needed;
-#ifdef X86_64
- if (*d->prefixes & has_rex_w)
- needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
- (int64_t) byte);
- else
-#endif
- needed = snprintf (&d->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 (struct output_data *d)
-{
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- if (*d->param_start >= d->end)
- return -1;
- uint_fast8_t byte = *(*d->param_start)++;
- int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
- (uint32_t) byte);
- if ((size_t) needed > avail)
- return (size_t) needed - avail;
- *bufcntp += needed;
- return 0;
-}
-
-
-static int
-FCT_rel (struct output_data *d)
-{
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- if (*d->param_start + 4 > d->end)
- return -1;
- int32_t rel = read_4sbyte_unaligned_inc (*d->param_start);
-#ifdef X86_64
- int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx64,
- (uint64_t) (d->addr + rel
- + (*d->param_start - d->data)));
-#else
- int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
- (uint32_t) (d->addr + rel
- + (*d->param_start - d->data)));
-#endif
- if ((size_t) needed > avail)
- return (size_t) needed - avail;
- *bufcntp += needed;
- return 0;
-}
-
-
-static int
-FCT_mmxreg (struct output_data *d)
-{
- uint_fast8_t byte = d->data[d->opoff1 / 8];
- assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
- byte = (byte >> (5 - d->opoff1 % 8)) & 7;
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- int needed = snprintf (&d->bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte);
- if ((size_t) needed > avail)
- return needed - avail;
- *bufcntp += needed;
- return 0;
-}
-
-
-static int
-FCT_mod$r_m (struct output_data *d)
-{
- assert (d->opoff1 % 8 == 0);
- uint_fast8_t modrm = d->data[d->opoff1 / 8];
- if ((modrm & 0xc0) == 0xc0)
- {
- int prefixes = *d->prefixes;
- if (prefixes & has_addr16)
- return -1;
-
- int is_16bit = (prefixes & has_data16) != 0;
-
- size_t *bufcntp = d->bufcntp;
- char *bufp = d->bufp;
- if (*bufcntp + 5 - is_16bit > d->bufsize)
- return *bufcntp + 5 - is_16bit - d->bufsize;
- bufp[(*bufcntp)++] = '%';
-
- char *cp;
-#ifdef X86_64
- if ((prefixes & has_rex_b) != 0 && !is_16bit)
- {
- cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
- if ((prefixes & has_rex_w) == 0)
- *cp++ = 'd';
- }
- else
-#endif
- {
- cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
-#ifdef X86_64
- if ((prefixes & has_rex_w) != 0)
- bufp[*bufcntp] = 'r';
-#endif
- }
- *bufcntp = cp - bufp;
- return 0;
- }
-
- return general_mod$r_m (d);
-}
-
-
-#ifndef X86_64
-static int
-FCT_moda$r_m (struct output_data *d)
-{
- assert (d->opoff1 % 8 == 0);
- uint_fast8_t modrm = d->data[d->opoff1 / 8];
- if ((modrm & 0xc0) == 0xc0)
- {
- if (*d->prefixes & has_addr16)
- return -1;
-
- size_t *bufcntp = d->bufcntp;
- if (*bufcntp + 3 > d->bufsize)
- return *bufcntp + 3 - d->bufsize;
-
- memcpy (&d->bufp[*bufcntp], "???", 3);
- *bufcntp += 3;
-
- return 0;
- }
-
- return general_mod$r_m (d);
-}
-#endif
-
-
-#ifdef X86_64
-static const char rex_8bit[8][3] =
- {
- [0] = "a", [1] = "c", [2] = "d", [3] = "b",
- [4] = "sp", [5] = "bp", [6] = "si", [7] = "di"
- };
-#endif
-
-
-static int
-FCT_mod$r_m$w (struct output_data *d)
-{
- assert (d->opoff1 % 8 == 0);
- const uint8_t *data = d->data;
- uint_fast8_t modrm = data[d->opoff1 / 8];
- if ((modrm & 0xc0) == 0xc0)
- {
- int prefixes = *d->prefixes;
-
- if (prefixes & has_addr16)
- return -1;
-
- size_t *bufcntp = d->bufcntp;
- char *bufp = d->bufp;
- if (*bufcntp + 5 > d->bufsize)
- return *bufcntp + 5 - d->bufsize;
-
- if ((data[d->opoff3 / 8] & (1 << (7 - (d->opoff3 & 7)))) == 0)
- {
- bufp[(*bufcntp)++] = '%';
-
-#ifdef X86_64
- if (prefixes & has_rex)
- {
- if (prefixes & has_rex_r)
- *bufcntp += snprintf (bufp + *bufcntp, d->bufsize - *bufcntp,
- "r%db", 8 + (modrm & 7));
- else
- {
- char *cp = stpcpy (bufp + *bufcntp, hiregs[modrm & 7]);
- *cp++ = 'l';
- *bufcntp = cp - bufp;
- }
- }
- else
-#endif
- {
- bufp[(*bufcntp)++] = "acdb"[modrm & 3];
- bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
- }
- }
- else
- {
- int is_16bit = (prefixes & has_data16) != 0;
-
- bufp[(*bufcntp)++] = '%';
-
- char *cp;
-#ifdef X86_64
- if ((prefixes & has_rex_b) != 0 && !is_16bit)
- {
- cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
- if ((prefixes & has_rex_w) == 0)
- *cp++ = 'd';
- }
- else
-#endif
- {
- cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
-#ifdef X86_64
- if ((prefixes & has_rex_w) != 0)
- bufp[*bufcntp] = 'r';
-#endif
- }
- *bufcntp = cp - bufp;
- }
- return 0;
- }
-
- return general_mod$r_m (d);
-}
-
-
-static int
-FCT_mod$8r_m (struct output_data *d)
-{
- assert (d->opoff1 % 8 == 0);
- uint_fast8_t modrm = d->data[d->opoff1 / 8];
- if ((modrm & 0xc0) == 0xc0)
- {
- size_t *bufcntp = d->bufcntp;
- char *bufp = d->bufp;
- if (*bufcntp + 3 > d->bufsize)
- return *bufcntp + 3 - d->bufsize;
- bufp[(*bufcntp)++] = '%';
- bufp[(*bufcntp)++] = "acdb"[modrm & 3];
- bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
- return 0;
- }
-
- return general_mod$r_m (d);
-}
-
-
-static int
-FCT_mod$16r_m (struct output_data *d)
-{
- assert (d->opoff1 % 8 == 0);
- uint_fast8_t modrm = d->data[d->opoff1 / 8];
- if ((modrm & 0xc0) == 0xc0)
- {
- assert (d->opoff1 / 8 == d->opoff2 / 8);
- //uint_fast8_t byte = data[opoff2 / 8] & 7;
- uint_fast8_t byte = modrm & 7;
-
- size_t *bufcntp = d->bufcntp;
- if (*bufcntp + 3 > d->bufsize)
- return *bufcntp + 3 - d->bufsize;
- d->bufp[(*bufcntp)++] = '%';
- memcpy (&d->bufp[*bufcntp], dregs[byte] + 1, sizeof (dregs[0]) - 1);
- *bufcntp += 2;
- return 0;
- }
-
- return general_mod$r_m (d);
-}
-
-
-#ifdef X86_64
-static int
-FCT_mod$64r_m (struct output_data *d)
-{
- assert (d->opoff1 % 8 == 0);
- uint_fast8_t modrm = d->data[d->opoff1 / 8];
- if ((modrm & 0xc0) == 0xc0)
- {
- assert (d->opoff1 / 8 == d->opoff2 / 8);
- //uint_fast8_t byte = data[opoff2 / 8] & 7;
- uint_fast8_t byte = modrm & 7;
-
- size_t *bufcntp = d->bufcntp;
- if (*bufcntp + 4 > d->bufsize)
- return *bufcntp + 4 - d->bufsize;
- char *cp = &d->bufp[*bufcntp];
- *cp++ = '%';
- cp = stpcpy (cp,
- (*d->prefixes & has_rex_b) ? hiregs[byte] : aregs[byte]);
- *bufcntp = cp - d->bufp;
- return 0;
- }
-
- return general_mod$r_m (d);
-}
-#else
-static typeof (FCT_mod$r_m) FCT_mod$64r_m __attribute__ ((alias ("FCT_mod$r_m")));
-#endif
-
-
-static int
-FCT_reg (struct output_data *d)
-{
- uint_fast8_t byte = d->data[d->opoff1 / 8];
- assert (d->opoff1 % 8 + 3 <= 8);
- byte >>= 8 - (d->opoff1 % 8 + 3);
- byte &= 7;
- int is_16bit = (*d->prefixes & has_data16) != 0;
- size_t *bufcntp = d->bufcntp;
- if (*bufcntp + 5 > d->bufsize)
- return *bufcntp + 5 - d->bufsize;
- d->bufp[(*bufcntp)++] = '%';
-#ifdef X86_64
- if ((*d->prefixes & has_rex_r) != 0 && !is_16bit)
- {
- *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
- 8 + byte);
- if ((*d->prefixes & has_rex_w) == 0)
- d->bufp[(*bufcntp)++] = 'd';
- }
- else
-#endif
- {
- memcpy (&d->bufp[*bufcntp], dregs[byte] + is_16bit, 3 - is_16bit);
-#ifdef X86_64
- if ((*d->prefixes & has_rex_w) != 0 && !is_16bit)
- d->bufp[*bufcntp] = 'r';
-#endif
- *bufcntp += 3 - is_16bit;
- }
- return 0;
-}
-
-
-#ifdef X86_64
-static int
-FCT_oreg (struct output_data *d)
-{
- /* Special form where register comes from opcode. The rex.B bit is used,
- rex.R and rex.X are ignored. */
- int save_prefixes = *d->prefixes;
-
- *d->prefixes = ((save_prefixes & ~has_rex_r)
- | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
-
- int r = FCT_reg (d);
-
- *d->prefixes = save_prefixes;
-
- return r;
-}
-#endif
-
-
-static int
-FCT_reg64 (struct output_data *d)
-{
- uint_fast8_t byte = d->data[d->opoff1 / 8];
- assert (d->opoff1 % 8 + 3 <= 8);
- byte >>= 8 - (d->opoff1 % 8 + 3);
- byte &= 7;
- if ((*d->prefixes & has_data16) != 0)
- return -1;
- size_t *bufcntp = d->bufcntp;
- if (*bufcntp + 5 > d->bufsize)
- return *bufcntp + 5 - d->bufsize;
- d->bufp[(*bufcntp)++] = '%';
-#ifdef X86_64
- if ((*d->prefixes & has_rex_r) != 0)
- {
- *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
- 8 + byte);
- if ((*d->prefixes & has_rex_w) == 0)
- d->bufp[(*bufcntp)++] = 'd';
- }
- else
-#endif
- {
- memcpy (&d->bufp[*bufcntp], aregs[byte], 3);
- *bufcntp += 3;
- }
- return 0;
-}
-
-
-static int
-FCT_reg$w (struct output_data *d)
-{
- if (d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7))))
- return FCT_reg (d);
-
- uint_fast8_t byte = d->data[d->opoff1 / 8];
- assert (d->opoff1 % 8 + 3 <= 8);
- byte >>= 8 - (d->opoff1 % 8 + 3);
- byte &= 7;
-
- size_t *bufcntp = d->bufcntp;
- if (*bufcntp + 4 > d->bufsize)
- return *bufcntp + 4 - d->bufsize;
-
- d->bufp[(*bufcntp)++] = '%';
-
-#ifdef X86_64
- if (*d->prefixes & has_rex)
- {
- if (*d->prefixes & has_rex_r)
- *bufcntp += snprintf (d->bufp + *bufcntp, d->bufsize - *bufcntp,
- "r%db", 8 + byte);
- else
- {
- char* cp = stpcpy (d->bufp + *bufcntp, rex_8bit[byte]);
- *cp++ = 'l';
- *bufcntp = cp - d->bufp;
- }
- }
- else
-#endif
- {
- d->bufp[(*bufcntp)++] = "acdb"[byte & 3];
- d->bufp[(*bufcntp)++] = "lh"[byte >> 2];
- }
- return 0;
-}
-
-
-#ifdef X86_64
-static int
-FCT_oreg$w (struct output_data *d)
-{
- /* Special form where register comes from opcode. The rex.B bit is used,
- rex.R and rex.X are ignored. */
- int save_prefixes = *d->prefixes;
-
- *d->prefixes = ((save_prefixes & ~has_rex_r)
- | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
-
- int r = FCT_reg$w (d);
-
- *d->prefixes = save_prefixes;
-
- return r;
-}
-#endif
-
-
-static int
-FCT_freg (struct output_data *d)
-{
- assert (d->opoff1 / 8 == 1);
- assert (d->opoff1 % 8 == 5);
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- int needed = snprintf (&d->bufp[*bufcntp], avail, "%%st(%" PRIx32 ")",
- (uint32_t) (d->data[1] & 7));
- if ((size_t) needed > avail)
- return (size_t) needed - avail;
- *bufcntp += needed;
- return 0;
-}
-
-
-#ifndef X86_64
-static int
-FCT_reg16 (struct output_data *d)
-{
- if (*d->prefixes & has_data16)
- return -1;
-
- *d->prefixes |= has_data16;
- return FCT_reg (d);
-}
-#endif
-
-
-static int
-FCT_sel (struct output_data *d)
-{
- assert (d->opoff1 % 8 == 0);
- assert (d->opoff1 / 8 == 5);
- if (*d->param_start + 2 > d->end)
- return -1;
- *d->param_start += 2;
- uint16_t absval = read_2ubyte_unaligned (&d->data[5]);
-
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, absval);
- if ((size_t) needed > avail)
- return needed - avail;
- *bufcntp += needed;
- return 0;
-}
-
-
-static int
-FCT_sreg2 (struct output_data *d)
-{
- uint_fast8_t byte = d->data[d->opoff1 / 8];
- assert (d->opoff1 % 8 + 3 <= 8);
- byte >>= 8 - (d->opoff1 % 8 + 2);
-
- size_t *bufcntp = d->bufcntp;
- char *bufp = d->bufp;
- if (*bufcntp + 3 > d->bufsize)
- return *bufcntp + 3 - d->bufsize;
-
- bufp[(*bufcntp)++] = '%';
- bufp[(*bufcntp)++] = "ecsd"[byte & 3];
- bufp[(*bufcntp)++] = 's';
-
- return 0;
-}
-
-
-static int
-FCT_sreg3 (struct output_data *d)
-{
- uint_fast8_t byte = d->data[d->opoff1 / 8];
- assert (d->opoff1 % 8 + 4 <= 8);
- byte >>= 8 - (d->opoff1 % 8 + 3);
-
- if ((byte & 7) >= 6)
- return -1;
-
- size_t *bufcntp = d->bufcntp;
- char *bufp = d->bufp;
- if (*bufcntp + 3 > d->bufsize)
- return *bufcntp + 3 - d->bufsize;
-
- bufp[(*bufcntp)++] = '%';
- bufp[(*bufcntp)++] = "ecsdfg"[byte & 7];
- bufp[(*bufcntp)++] = 's';
-
- return 0;
-}
-
-
-static int
-FCT_string (struct output_data *d __attribute__ ((unused)))
-{
- return 0;
-}
-
-
-static int
-FCT_xmmreg (struct output_data *d)
-{
- uint_fast8_t byte = d->data[d->opoff1 / 8];
- assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
- byte = (byte >> (5 - d->opoff1 % 8)) & 7;
-
- size_t *bufcntp = d->bufcntp;
- size_t avail = d->bufsize - *bufcntp;
- int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, byte);
- if ((size_t) needed > avail)
- return needed - avail;
- *bufcntp += needed;
- return 0;
-}