summaryrefslogtreecommitdiffstats
path: root/libcpu/i386_data.h
diff options
context:
space:
mode:
Diffstat (limited to 'libcpu/i386_data.h')
-rw-r--r--libcpu/i386_data.h466
1 files changed, 412 insertions, 54 deletions
diff --git a/libcpu/i386_data.h b/libcpu/i386_data.h
index 5148fa06..398c672b 100644
--- a/libcpu/i386_data.h
+++ b/libcpu/i386_data.h
@@ -101,7 +101,7 @@ data_prefix (int *prefixes, char *bufp, size_t *bufcntp, size_t bufsize)
else if (*prefixes & has_es)
{
ch = 'e';
- *prefixes &= has_es;
+ *prefixes &= ~has_es;
}
else if (*prefixes & has_fs)
{
@@ -132,10 +132,26 @@ data_prefix (int *prefixes, char *bufp, size_t *bufcntp, size_t bufsize)
return 0;
}
-static const char regs[8][4] =
+#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 (GElf_Addr addr __attribute__ ((unused)),
@@ -158,7 +174,48 @@ general_mod$r_m (GElf_Addr addr __attribute__ ((unused)),
return r;
uint_fast8_t modrm = data[opoff1 / 8];
- if ((*prefixes & has_addr16) == 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[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 ("-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)
{
@@ -174,16 +231,53 @@ general_mod$r_m (GElf_Addr addr __attribute__ ((unused)),
else if ((modrm & 0xc0) == 0)
nodisp = true;
- char tmpbuf[sizeof ("-0x12345678(%rrr)")];
+ char tmpbuf[sizeof ("-0x12345678(%rrrr)")];
int n;
if (nodisp)
- n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)", regs[modrm & 7]);
+ {
+ 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)
- n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%s)",
- disp < 0 ? "-" : "", disp < 0 ? -disp : disp,
- regs[modrm & 7]);
+ {
+ 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
- n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp);
+ {
+#ifdef X86_64
+ n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%rip)",
+ disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
+#else
+ n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp);
+#endif
+ }
if (*bufcntp + n + 1 > bufsize)
return *bufcntp + n + 1 - bufsize;
@@ -208,10 +302,14 @@ general_mod$r_m (GElf_Addr addr __attribute__ ((unused)),
else
nodisp = true;
- char tmpbuf[sizeof ("-0x12345678(%rrr,%rrr,N)")];
+ char tmpbuf[sizeof ("-0x12345678(%rrrr,%rrrr,N)")];
char *cp = tmpbuf;
int n;
- if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25)
+ if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25
+#ifdef X86_64
+ || (*prefixes & has_rex_x) != 0
+#endif
+ )
{
if (!nodisp)
{
@@ -225,14 +323,40 @@ general_mod$r_m (GElf_Addr addr __attribute__ ((unused)),
if ((modrm & 0xc7) != 0x4 || (sib & 0x7) != 0x5)
{
*cp++ = '%';
- cp = mempcpy (cp, regs[sib & 7], 3);
+ 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)
+ if ((sib & 0x38) != 0x20
+#ifdef X86_64
+ || (*prefixes & has_rex_x) != 0
+#endif
+ )
{
*cp++ = ',';
*cp++ = '%';
- cp = mempcpy (cp, regs[(sib >> 3) & 7], 3);
+ 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));
@@ -243,7 +367,13 @@ general_mod$r_m (GElf_Addr addr __attribute__ ((unused)),
else
{
assert (! nodisp);
- n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx32, disp);
+#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;
}
@@ -283,7 +413,7 @@ FCT_MOD$R_M (GElf_Addr addr __attribute__ ((unused)),
size_t avail = bufsize - *bufcntp;
int needed;
if (*prefixes & (has_rep | has_repne))
- needed = snprintf (&bufp[*bufcntp], avail, "%%%s", regs[byte]);
+ needed = snprintf (&bufp[*bufcntp], avail, "%%%s", dregs[byte]);
else
needed = snprintf (&bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte);
if ((size_t) needed > avail)
@@ -344,7 +474,13 @@ generic_abs (int *prefixes __attribute__ ((unused)),
const uint8_t *end __attribute__ ((unused)),
DisasmGetSymCB_t symcb __attribute__ ((unused)),
void *symcbarg __attribute__ ((unused)),
- const char *absstring)
+ const char *absstring
+#ifdef X86_64
+ , int abslen
+#else
+# define abslen 4
+#endif
+ )
{
int r = data_prefix (prefixes, bufp, bufcntp, bufsize);
if (r != 0)
@@ -352,12 +488,22 @@ generic_abs (int *prefixes __attribute__ ((unused)),
assert (opoff1 % 8 == 0);
assert (opoff1 / 8 == 1);
- if (*param_start + 4 > end)
+ if (*param_start + abslen > end)
return -1;
- *param_start += 4;
- uint32_t absval = read_4ubyte_unaligned (&data[1]);
+ *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 (&data[1]);
+ else
+#endif
+ absval = read_4ubyte_unaligned (&data[1]);
size_t avail = bufsize - *bufcntp;
- int needed = snprintf (&bufp[*bufcntp], avail, "%s0x%" PRIx32,
+ int needed = snprintf (&bufp[*bufcntp], avail, "%s0x%" ABSPRIFMT,
absstring, absval);
if ((size_t) needed > avail)
return needed - avail;
@@ -383,7 +529,11 @@ FCT_absval (GElf_Addr addr __attribute__ ((unused)),
{
return generic_abs (prefixes, opoff1, bufp,
bufcntp, bufsize, data, param_start, end, symcb,
- symcbarg, "$");
+ symcbarg, "$"
+#ifdef X86_64
+ , 4
+#endif
+ );
}
static int
@@ -404,7 +554,11 @@ FCT_abs (GElf_Addr addr __attribute__ ((unused)),
{
return generic_abs (prefixes, opoff1, bufp,
bufcntp, bufsize, data, param_start, end, symcb,
- symcbarg, "");
+ symcbarg, ""
+#ifdef X86_64
+ , 8
+#endif
+ );
}
static int
@@ -576,7 +730,12 @@ FCT_ds_xx (const char *reg,
size_t avail = bufsize - *bufcntp;
int needed = snprintf (&bufp[*bufcntp], avail, "(%%%s%s)",
- *prefixes & idx_addr16 ? "" : "e", reg);
+#ifdef X86_64
+ *prefixes & idx_addr16 ? "e" : "r",
+#else
+ *prefixes & idx_addr16 ? "" : "e",
+#endif
+ reg);
if ((size_t) needed > avail)
return (size_t) needed - avail;
*bufcntp += needed;
@@ -665,7 +824,12 @@ FCT_es_di (GElf_Addr addr __attribute__ ((unused)),
{
size_t avail = bufsize - *bufcntp;
int needed = snprintf (&bufp[*bufcntp], avail, "%%es:(%%%sdi)",
- *prefixes & idx_addr16 ? "" : "e");
+#ifdef X86_64
+ *prefixes & idx_addr16 ? "e" : "r"
+#else
+ *prefixes & idx_addr16 ? "" : "e"
+#endif
+ );
if ((size_t) needed > avail)
return (size_t) needed - avail;
*bufcntp += needed;
@@ -757,9 +921,14 @@ FCT_imms (GElf_Addr addr __attribute__ ((unused)),
void *symcbarg __attribute__ ((unused)))
{
size_t avail = bufsize - *bufcntp;
- int_fast8_t byte = *(*param_start)++;
+ int8_t byte = *(*param_start)++;
+#ifdef X86_64
+ int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx64,
+ (int64_t) byte);
+#else
int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx32,
(int32_t) byte);
+#endif
if ((size_t) needed > avail)
return (size_t) needed - avail;
*bufcntp += needed;
@@ -793,8 +962,13 @@ FCT_imm$s (GElf_Addr addr __attribute__ ((unused)),
{
if (*param_start + 4 > end)
return -1;
- uint32_t word = read_4ubyte_unaligned_inc (*param_start);
+ int32_t word = read_4sbyte_unaligned_inc (*param_start);
+#ifdef X86_64
+ int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx64,
+ (int64_t) word);
+#else
int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx32, word);
+#endif
if ((size_t) needed > avail)
return (size_t) needed - avail;
*bufcntp += needed;
@@ -893,7 +1067,6 @@ FCT_imm8 (GElf_Addr addr __attribute__ ((unused)),
return 0;
}
-#ifndef X86_64
static int
FCT_rel (GElf_Addr addr __attribute__ ((unused)),
int *prefixes __attribute__ ((unused)),
@@ -913,15 +1086,19 @@ FCT_rel (GElf_Addr addr __attribute__ ((unused)),
size_t avail = bufsize - *bufcntp;
if (*param_start + 4 > end)
return -1;
- uint32_t rel = read_4ubyte_unaligned_inc (*param_start);
+ int32_t rel = read_4sbyte_unaligned_inc (*param_start);
+#ifdef X86_64
+ int needed = snprintf (&bufp[*bufcntp], avail, "0x%" PRIx64,
+ (uint64_t) (addr + rel + (*param_start - data)));
+#else
int needed = snprintf (&bufp[*bufcntp], avail, "0x%" PRIx32,
(uint32_t) (addr + rel + (*param_start - data)));
+#endif
if ((size_t) needed > avail)
return (size_t) needed - avail;
*bufcntp += needed;
return 0;
}
-#endif
static int
FCT_mmxreg (GElf_Addr addr __attribute__ ((unused)),
@@ -971,14 +1148,33 @@ FCT_mod$r_m (GElf_Addr addr __attribute__ ((unused)),
uint_fast8_t modrm = data[opoff1 / 8];
if ((modrm & 0xc0) == 0xc0)
{
+ if (*prefixes & has_addr16)
+ return -1;
+
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;
+
+ 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;
}
@@ -1013,6 +1209,9 @@ FCT_moda$r_m (GElf_Addr addr __attribute__ ((unused)),
uint_fast8_t modrm = data[opoff1 / 8];
if ((modrm & 0xc0) == 0xc0)
{
+ if (*prefixes & has_addr16)
+ return -1;
+
if (*bufcntp + 3 > bufsize)
return *bufcntp + 3 - bufsize;
@@ -1029,6 +1228,14 @@ FCT_moda$r_m (GElf_Addr addr __attribute__ ((unused)),
#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 (GElf_Addr addr __attribute__ ((unused)),
int *prefixes __attribute__ ((unused)),
@@ -1053,24 +1260,60 @@ FCT_mod$r_m$w (GElf_Addr addr __attribute__ ((unused)),
uint_fast8_t modrm = data[opoff1 / 8];
if ((modrm & 0xc0) == 0xc0)
{
+ if (*prefixes & has_addr16)
+ return -1;
+
+ if (*bufcntp + 5 > bufsize)
+ return *bufcntp + 5 - bufsize;
+
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];
+
+#ifdef X86_64
+ if (*prefixes & has_rex)
+ {
+ if (*prefixes & has_rex_r)
+ *bufcntp += snprintf (bufp + *bufcntp, 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;
- 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;
+
+ 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;
}
@@ -1081,7 +1324,6 @@ FCT_mod$r_m$w (GElf_Addr addr __attribute__ ((unused)),
}
-#ifndef X86_64
static int
FCT_mod$8r_m (GElf_Addr addr __attribute__ ((unused)),
int *prefixes __attribute__ ((unused)),
@@ -1114,7 +1356,6 @@ FCT_mod$8r_m (GElf_Addr addr __attribute__ ((unused)),
bufcntp, bufsize, data, param_start, end,
symcb, symcbarg);
}
-#endif
static int
FCT_mod$16r_m (GElf_Addr addr __attribute__ ((unused)),
@@ -1140,7 +1381,7 @@ FCT_mod$16r_m (GElf_Addr addr __attribute__ ((unused)),
if (*bufcntp + 3 > bufsize)
return *bufcntp + 3 - bufsize;
bufp[(*bufcntp)++] = '%';
- memcpy (&bufp[*bufcntp], regs[byte] + 1, sizeof (regs[0]) - 1);
+ memcpy (&bufp[*bufcntp], dregs[byte] + 1, sizeof (dregs[0]) - 1);
*bufcntp += 2;
return 0;
}
@@ -1150,6 +1391,45 @@ FCT_mod$16r_m (GElf_Addr addr __attribute__ ((unused)),
symcb, symcbarg);
}
+#ifdef X86_64
+static int
+FCT_mod$64r_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 + 4 > bufsize)
+ return *bufcntp + 4 - bufsize;
+ char *cp = &bufp[*bufcntp];
+ *cp++ = '%';
+ cp = stpcpy (cp, (*prefixes & has_rex_b) ? hiregs[byte] : aregs[byte]);
+ *bufcntp = cp - bufp;
+ return 0;
+ }
+
+ return general_mod$r_m (addr, prefixes, op1str, opoff1, opoff2, opoff3, bufp,
+ bufcntp, bufsize, data, param_start, end,
+ symcb, symcbarg);
+}
+#else
+static typeof (FCT_mod$r_m) FCT_mod$64r_m __attribute__ ((alias ("FCT_mod$r_m")));
+#endif
+
static int
FCT_reg (GElf_Addr addr __attribute__ ((unused)),
int *prefixes __attribute__ ((unused)),
@@ -1171,11 +1451,69 @@ FCT_reg (GElf_Addr addr __attribute__ ((unused)),
byte >>= 8 - (opoff1 % 8 + 3);
byte &= 7;
int is_16bit = (*prefixes & has_data16) != 0;
- if (*bufcntp + 4 > bufsize)
- return *bufcntp + 4 - bufsize;
+ if (*bufcntp + 5 > bufsize)
+ return *bufcntp + 5 - bufsize;
+ bufp[(*bufcntp)++] = '%';
+#ifdef X86_64
+ if ((*prefixes & has_rex_r) != 0 && !is_16bit)
+ {
+ *bufcntp += snprintf (&bufp[*bufcntp], bufsize - *bufcntp, "r%d",
+ 8 + byte);
+ if ((*prefixes & has_rex_w) == 0)
+ bufp[(*bufcntp)++] = 'd';
+ }
+ else
+#endif
+ {
+ memcpy (&bufp[*bufcntp], dregs[byte] + is_16bit, 3 - is_16bit);
+#ifdef X86_64
+ if ((*prefixes & has_rex_w) != 0 && !is_16bit)
+ bufp[*bufcntp] = 'r';
+#endif
+ *bufcntp += 3 - is_16bit;
+ }
+ return 0;
+}
+
+static int
+FCT_reg64 (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;
+ if ((*prefixes & has_data16) != 0)
+ return -1;
+ if (*bufcntp + 5 > bufsize)
+ return *bufcntp + 5 - bufsize;
bufp[(*bufcntp)++] = '%';
- memcpy (&bufp[*bufcntp], regs[byte] + is_16bit, sizeof (regs[0]) - is_16bit);
- *bufcntp += 3 - is_16bit;
+#ifdef X86_64
+ if ((*prefixes & has_rex_r) != 0)
+ {
+ *bufcntp += snprintf (&bufp[*bufcntp], bufsize - *bufcntp, "r%d",
+ 8 + byte);
+ if ((*prefixes & has_rex_w) == 0)
+ bufp[(*bufcntp)++] = 'd';
+ }
+ else
+#endif
+ {
+ memcpy (&bufp[*bufcntp], aregs[byte], 3);
+ *bufcntp += 3;
+ }
return 0;
}
@@ -1202,15 +1540,34 @@ FCT_reg$w (GElf_Addr addr __attribute__ ((unused)),
assert (opoff1 % 8 + 3 <= 8);
byte >>= 8 - (opoff1 % 8 + 3);
byte &= 7;
- if (*bufcntp + 3 > bufsize)
- return *bufcntp + 3 - bufsize;
+
+ if (*bufcntp + 4 > bufsize)
+ return *bufcntp + 4 - bufsize;
+
bufp[(*bufcntp)++] = '%';
- bufp[(*bufcntp)++] = "acdb"[byte & 3];
- bufp[(*bufcntp)++] = "lh"[byte >> 2];
+
+#ifdef X86_64
+ if (*prefixes & has_rex)
+ {
+ if (*prefixes & has_rex_r)
+ *bufcntp += snprintf (bufp + *bufcntp, bufsize - *bufcntp,
+ "r%db", 8 + byte);
+ else
+ {
+ char* cp = stpcpy (bufp + *bufcntp, rex_8bit[byte]);
+ *cp++ = 'l';
+ *bufcntp = cp - bufp;
+ }
+ }
+ else
+#endif
+ {
+ 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)),
@@ -1238,6 +1595,7 @@ FCT_freg (GElf_Addr addr __attribute__ ((unused)),
return 0;
}
+#ifndef X86_64
static int
FCT_reg16 (GElf_Addr addr __attribute__ ((unused)),
int *prefixes __attribute__ ((unused)),