Blame libcpu/i386_data.h

Packit 032894
/* Helper routines for disassembler for x86/x86-64.
Packit 032894
   Copyright (C) 2007, 2008 Red Hat, Inc.
Packit 032894
   This file is part of elfutils.
Packit 032894
   Written by Ulrich Drepper <drepper@redhat.com>, 2007.
Packit 032894
Packit 032894
   This file is free software; you can redistribute it and/or modify
Packit 032894
   it under the terms of either
Packit 032894
Packit 032894
     * the GNU Lesser General Public License as published by the Free
Packit 032894
       Software Foundation; either version 3 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or
Packit 032894
Packit 032894
     * the GNU General Public License as published by the Free
Packit 032894
       Software Foundation; either version 2 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or both in parallel, as here.
Packit 032894
Packit 032894
   elfutils is distributed in the hope that it will be useful, but
Packit 032894
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 032894
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 032894
   General Public License for more details.
Packit 032894
Packit 032894
   You should have received copies of the GNU General Public License and
Packit 032894
   the GNU Lesser General Public License along with this program.  If
Packit 032894
   not, see <http://www.gnu.org/licenses/>.  */
Packit 032894
Packit 032894
#include <inttypes.h>
Packit 032894
#include <stddef.h>
Packit 032894
#include <stdio.h>
Packit 032894
#include <stdint.h>
Packit 032894
#include <libasm.h>
Packit 032894
Packit 032894
struct instr_enc
Packit 032894
{
Packit 032894
  /* The mnemonic.  Especially encoded for the optimized table.  */
Packit 032894
  unsigned int mnemonic : MNEMONIC_BITS;
Packit 032894
Packit 032894
  /* The rep/repe prefixes.  */
Packit 032894
  unsigned int rep : 1;
Packit 032894
  unsigned int repe : 1;
Packit 032894
Packit 032894
  /* Mnemonic suffix.  */
Packit 032894
  unsigned int suffix : SUFFIX_BITS;
Packit 032894
Packit 032894
  /* Nonzero if the instruction uses modr/m.  */
Packit 032894
  unsigned int modrm : 1;
Packit 032894
Packit 032894
  /* 1st parameter.  */
Packit 032894
  unsigned int fct1 : FCT1_BITS;
Packit 032894
#ifdef STR1_BITS
Packit 032894
  unsigned int str1 : STR1_BITS;
Packit 032894
#endif
Packit 032894
  unsigned int off1_1 : OFF1_1_BITS;
Packit 032894
  unsigned int off1_2 : OFF1_2_BITS;
Packit 032894
  unsigned int off1_3 : OFF1_3_BITS;
Packit 032894
Packit 032894
  /* 2nd parameter.  */
Packit 032894
  unsigned int fct2 : FCT2_BITS;
Packit 032894
#ifdef STR2_BITS
Packit 032894
  unsigned int str2 : STR2_BITS;
Packit 032894
#endif
Packit 032894
  unsigned int off2_1 : OFF2_1_BITS;
Packit 032894
  unsigned int off2_2 : OFF2_2_BITS;
Packit 032894
  unsigned int off2_3 : OFF2_3_BITS;
Packit 032894
Packit 032894
  /* 3rd parameter.  */
Packit 032894
  unsigned int fct3 : FCT3_BITS;
Packit 032894
#ifdef STR3_BITS
Packit 032894
  unsigned int str3 : STR3_BITS;
Packit 032894
#endif
Packit 032894
  unsigned int off3_1 : OFF3_1_BITS;
Packit 032894
#ifdef OFF3_2_BITS
Packit 032894
  unsigned int off3_2 : OFF3_2_BITS;
Packit 032894
#endif
Packit 032894
#ifdef OFF3_3_BITS
Packit 032894
  unsigned int off3_3 : OFF3_3_BITS;
Packit 032894
#endif
Packit 032894
};
Packit 032894
Packit 032894
Packit 032894
typedef int (*opfct_t) (struct output_data *);
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
data_prefix (struct output_data *d)
Packit 032894
{
Packit 032894
  char ch = '\0';
Packit 032894
  if (*d->prefixes & has_cs)
Packit 032894
    {
Packit 032894
      ch = 'c';
Packit 032894
      *d->prefixes &= ~has_cs;
Packit 032894
    }
Packit 032894
  else if (*d->prefixes & has_ds)
Packit 032894
    {
Packit 032894
      ch = 'd';
Packit 032894
      *d->prefixes &= ~has_ds;
Packit 032894
    }
Packit 032894
  else if (*d->prefixes & has_es)
Packit 032894
    {
Packit 032894
      ch = 'e';
Packit 032894
      *d->prefixes &= ~has_es;
Packit 032894
    }
Packit 032894
  else if (*d->prefixes & has_fs)
Packit 032894
    {
Packit 032894
      ch = 'f';
Packit 032894
      *d->prefixes &= ~has_fs;
Packit 032894
    }
Packit 032894
  else if (*d->prefixes & has_gs)
Packit 032894
    {
Packit 032894
      ch = 'g';
Packit 032894
      *d->prefixes &= ~has_gs;
Packit 032894
    }
Packit 032894
  else if (*d->prefixes & has_ss)
Packit 032894
    {
Packit 032894
      ch = 's';
Packit 032894
      *d->prefixes &= ~has_ss;
Packit 032894
    }
Packit 032894
  else
Packit 032894
    return 0;
Packit 032894
Packit 032894
  if (*d->bufcntp + 4 > d->bufsize)
Packit 032894
    return *d->bufcntp + 4 - d->bufsize;
Packit 032894
Packit 032894
  d->bufp[(*d->bufcntp)++] = '%';
Packit 032894
  d->bufp[(*d->bufcntp)++] = ch;
Packit 032894
  d->bufp[(*d->bufcntp)++] = 's';
Packit 032894
  d->bufp[(*d->bufcntp)++] = ':';
Packit 032894
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
#ifdef X86_64
Packit 032894
static const char hiregs[8][4] =
Packit 032894
  {
Packit 032894
    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
Packit 032894
  };
Packit 032894
static const char aregs[8][4] =
Packit 032894
  {
Packit 032894
    "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"
Packit 032894
  };
Packit 032894
static const char dregs[8][4] =
Packit 032894
  {
Packit 032894
    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
Packit 032894
  };
Packit 032894
#else
Packit 032894
static const char aregs[8][4] =
Packit 032894
  {
Packit 032894
    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
Packit 032894
  };
Packit 032894
# define dregs aregs
Packit 032894
#endif
Packit 032894
Packit 032894
static int
Packit 032894
general_mod$r_m (struct output_data *d)
Packit 032894
{
Packit 032894
  int r = data_prefix (d);
Packit 032894
  if (r != 0)
Packit 032894
    return r;
Packit 032894
Packit 032894
  int prefixes = *d->prefixes;
Packit 032894
  const uint8_t *data = &d->data[d->opoff1 / 8];
Packit 032894
  char *bufp = d->bufp;
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t bufsize = d->bufsize;
Packit 032894
Packit 032894
  uint_fast8_t modrm = data[0];
Packit 032894
#ifndef X86_64
Packit 032894
  if (unlikely ((prefixes & has_addr16) != 0))
Packit 032894
    {
Packit 032894
      int16_t disp = 0;
Packit 032894
      bool nodisp = false;
Packit 032894
Packit 032894
      if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80)
Packit 032894
	/* 16 bit displacement.  */
Packit 032894
	disp = read_2sbyte_unaligned (&data[1]);
Packit 032894
      else if ((modrm & 0xc0) == 0x40)
Packit 032894
	/* 8 bit displacement.  */
Packit 032894
	disp = *(const int8_t *) &data[1];
Packit 032894
      else if ((modrm & 0xc0) == 0)
Packit 032894
	nodisp = true;
Packit 032894
Packit 032894
      char tmpbuf[sizeof ("-0x1234(%rr,%rr)")];
Packit 032894
      int n;
Packit 032894
      if ((modrm & 0xc7) == 6)
Packit 032894
	n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx16, disp);
Packit 032894
      else
Packit 032894
	{
Packit 032894
	  n = 0;
Packit 032894
	  if (!nodisp)
Packit 032894
	    n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx16,
Packit 032894
			  disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
Packit 032894
Packit 032894
	  if ((modrm & 0x4) == 0)
Packit 032894
	    n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%b%c,%%%ci)",
Packit 032894
			   "xp"[(modrm >> 1) & 1], "sd"[modrm & 1]);
Packit 032894
	  else
Packit 032894
	    n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%%s)",
Packit 032894
			   ((const char [4][3]) { "si", "di", "bp", "bx" })[modrm & 3]);
Packit 032894
	}
Packit 032894
Packit 032894
      if (*bufcntp + n + 1 > bufsize)
Packit 032894
	return *bufcntp + n + 1 - bufsize;
Packit 032894
Packit 032894
      memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
Packit 032894
      *bufcntp += n;
Packit 032894
    }
Packit 032894
  else
Packit 032894
#endif
Packit 032894
    {
Packit 032894
      if ((modrm & 7) != 4)
Packit 032894
	{
Packit 032894
	  int32_t disp = 0;
Packit 032894
	  bool nodisp = false;
Packit 032894
Packit 032894
	  if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80)
Packit 032894
	    /* 32 bit displacement.  */
Packit 032894
	    disp = read_4sbyte_unaligned (&data[1]);
Packit 032894
	  else if ((modrm & 0xc0) == 0x40)
Packit 032894
	    /* 8 bit displacement.  */
Packit 032894
	    disp = *(const int8_t *) &data[1];
Packit 032894
	  else if ((modrm & 0xc0) == 0)
Packit 032894
	    nodisp = true;
Packit 032894
Packit 032894
	  char tmpbuf[sizeof ("-0x12345678(%rrrr)")];
Packit 032894
	  int n;
Packit 032894
	  if (nodisp)
Packit 032894
	    {
Packit 032894
	      n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)",
Packit 032894
#ifdef X86_64
Packit 032894
			    (prefixes & has_rex_b) ? hiregs[modrm & 7] :
Packit 032894
#endif
Packit 032894
			    aregs[modrm & 7]);
Packit 032894
#ifdef X86_64
Packit 032894
	      if (prefixes & has_addr16)
Packit 032894
		{
Packit 032894
		  if (prefixes & has_rex_b)
Packit 032894
		    tmpbuf[n++] = 'd';
Packit 032894
		  else
Packit 032894
		    tmpbuf[2] = 'e';
Packit 032894
		}
Packit 032894
#endif
Packit 032894
	    }
Packit 032894
	  else if ((modrm & 0xc7) != 5)
Packit 032894
	    {
Packit 032894
	      int p;
Packit 032894
	      n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%n%s)",
Packit 032894
			    disp < 0 ? "-" : "", disp < 0 ? -disp : disp, &p,
Packit 032894
#ifdef X86_64
Packit 032894
			    (prefixes & has_rex_b) ? hiregs[modrm & 7] :
Packit 032894
#endif
Packit 032894
			    aregs[modrm & 7]);
Packit 032894
#ifdef X86_64
Packit 032894
	      if (prefixes & has_addr16)
Packit 032894
		{
Packit 032894
		  if (prefixes & has_rex_b)
Packit 032894
		    tmpbuf[n++] = 'd';
Packit 032894
		  else
Packit 032894
		    tmpbuf[p] = 'e';
Packit 032894
		}
Packit 032894
#endif
Packit 032894
	    }
Packit 032894
	  else
Packit 032894
	    {
Packit 032894
#ifdef X86_64
Packit 032894
	      n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%rip)",
Packit 032894
			    disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
Packit 032894
Packit 032894
	      d->symaddr_use = addr_rel_always;
Packit 032894
	      d->symaddr = disp;
Packit 032894
#else
Packit 032894
	      n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp);
Packit 032894
#endif
Packit 032894
	    }
Packit 032894
Packit 032894
	  if (*bufcntp + n + 1 > bufsize)
Packit 032894
	    return *bufcntp + n + 1 - bufsize;
Packit 032894
Packit 032894
	  memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
Packit 032894
	  *bufcntp += n;
Packit 032894
	}
Packit 032894
      else
Packit 032894
	{
Packit 032894
	  /* SIB */
Packit 032894
	  uint_fast8_t sib = data[1];
Packit 032894
	  int32_t disp = 0;
Packit 032894
	  bool nodisp = false;
Packit 032894
Packit 032894
	  if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80
Packit 032894
	      || ((modrm & 0xc7) == 0x4 && (sib & 0x7) == 0x5))
Packit 032894
	    /* 32 bit displacement.  */
Packit 032894
	    disp = read_4sbyte_unaligned (&data[2]);
Packit 032894
	  else if ((modrm & 0xc0) == 0x40)
Packit 032894
	    /* 8 bit displacement.  */
Packit 032894
	    disp = *(const int8_t *) &data[2];
Packit 032894
	  else
Packit 032894
	    nodisp = true;
Packit 032894
Packit 032894
	  char tmpbuf[sizeof ("-0x12345678(%rrrr,%rrrr,N)")];
Packit 032894
	  char *cp = tmpbuf;
Packit 032894
	  int n;
Packit 032894
	  if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25
Packit 032894
#ifdef X86_64
Packit 032894
	      || (prefixes & has_rex_x) != 0
Packit 032894
#endif
Packit 032894
	      )
Packit 032894
	    {
Packit 032894
	      if (!nodisp)
Packit 032894
		{
Packit 032894
		  n = snprintf (cp, sizeof (tmpbuf), "%s0x%" PRIx32,
Packit 032894
				disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
Packit 032894
		  cp += n;
Packit 032894
		}
Packit 032894
Packit 032894
	      *cp++ = '(';
Packit 032894
Packit 032894
	      if ((modrm & 0xc7) != 0x4 || (sib & 0x7) != 0x5)
Packit 032894
		{
Packit 032894
		  *cp++ = '%';
Packit 032894
		  cp = stpcpy (cp,
Packit 032894
#ifdef X86_64
Packit 032894
			       (prefixes & has_rex_b) ? hiregs[sib & 7] :
Packit 032894
			       (prefixes & has_addr16) ? dregs[sib & 7] :
Packit 032894
#endif
Packit 032894
			       aregs[sib & 7]);
Packit 032894
#ifdef X86_64
Packit 032894
		  if ((prefixes & (has_rex_b | has_addr16))
Packit 032894
		      == (has_rex_b | has_addr16))
Packit 032894
		    *cp++ = 'd';
Packit 032894
#endif
Packit 032894
		}
Packit 032894
Packit 032894
	      if ((sib & 0x38) != 0x20
Packit 032894
#ifdef X86_64
Packit 032894
		  || (prefixes & has_rex_x) != 0
Packit 032894
#endif
Packit 032894
		  )
Packit 032894
		{
Packit 032894
		  *cp++ = ',';
Packit 032894
		  *cp++ = '%';
Packit 032894
		  cp = stpcpy (cp,
Packit 032894
#ifdef X86_64
Packit 032894
			       (prefixes & has_rex_x)
Packit 032894
			       ? hiregs[(sib >> 3) & 7] :
Packit 032894
			       (prefixes & has_addr16)
Packit 032894
			       ? dregs[(sib >> 3) & 7] :
Packit 032894
#endif
Packit 032894
			       aregs[(sib >> 3) & 7]);
Packit 032894
#ifdef X86_64
Packit 032894
		  if ((prefixes & (has_rex_b | has_addr16))
Packit 032894
		      == (has_rex_b | has_addr16))
Packit 032894
		    *cp++ = 'd';
Packit 032894
#endif
Packit 032894
Packit 032894
		  *cp++ = ',';
Packit 032894
		  *cp++ = '0' + (1 << (sib >> 6));
Packit 032894
		}
Packit 032894
Packit 032894
	      *cp++ = ')';
Packit 032894
	    }
Packit 032894
	  else
Packit 032894
	    {
Packit 032894
	      assert (! nodisp);
Packit 032894
#ifdef X86_64
Packit 032894
	      if ((prefixes & has_addr16) == 0)
Packit 032894
		n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx64,
Packit 032894
			      (int64_t) disp);
Packit 032894
	      else
Packit 032894
#endif
Packit 032894
		n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx32, disp);
Packit 032894
	      cp += n;
Packit 032894
	    }
Packit 032894
Packit 032894
	  if (*bufcntp + (cp - tmpbuf) > bufsize)
Packit 032894
	    return *bufcntp + (cp - tmpbuf) - bufsize;
Packit 032894
Packit 032894
	  memcpy (&bufp[*bufcntp], tmpbuf, cp - tmpbuf);
Packit 032894
	  *bufcntp += cp - tmpbuf;
Packit 032894
	}
Packit 032894
    }
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_MOD$R_M (struct output_data *d)
Packit 032894
{
Packit 032894
  assert (d->opoff1 % 8 == 0);
Packit 032894
  uint_fast8_t modrm = d->data[d->opoff1 / 8];
Packit 032894
  if ((modrm & 0xc0) == 0xc0)
Packit 032894
    {
Packit 032894
      assert (d->opoff1 / 8 == d->opoff2 / 8);
Packit 032894
      assert (d->opoff2 % 8 == 5);
Packit 032894
      //uint_fast8_t byte = d->data[d->opoff2 / 8] & 7;
Packit 032894
      uint_fast8_t byte = modrm & 7;
Packit 032894
Packit 032894
      size_t *bufcntp = d->bufcntp;
Packit 032894
      char *buf = d->bufp + *bufcntp;
Packit 032894
      size_t avail = d->bufsize - *bufcntp;
Packit 032894
      int needed;
Packit 032894
      if (*d->prefixes & (has_rep | has_repne))
Packit 032894
	needed = snprintf (buf, avail, "%%%s", dregs[byte]);
Packit 032894
      else
Packit 032894
	needed = snprintf (buf, avail, "%%mm%" PRIxFAST8, byte);
Packit 032894
      if ((size_t) needed > avail)
Packit 032894
	return needed - avail;
Packit 032894
      *bufcntp += needed;
Packit 032894
      return 0;
Packit 032894
    }
Packit 032894
Packit 032894
  return general_mod$r_m (d);
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_Mod$R_m (struct output_data *d)
Packit 032894
{
Packit 032894
  assert (d->opoff1 % 8 == 0);
Packit 032894
  uint_fast8_t modrm = d->data[d->opoff1 / 8];
Packit 032894
  if ((modrm & 0xc0) == 0xc0)
Packit 032894
    {
Packit 032894
      assert (d->opoff1 / 8 == d->opoff2 / 8);
Packit 032894
      assert (d->opoff2 % 8 == 5);
Packit 032894
      //uint_fast8_t byte = data[opoff2 / 8] & 7;
Packit 032894
      uint_fast8_t byte = modrm & 7;
Packit 032894
Packit 032894
      size_t *bufcntp = d->bufcntp;
Packit 032894
      size_t avail = d->bufsize - *bufcntp;
Packit 032894
      int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8,
Packit 032894
			     byte);
Packit 032894
      if ((size_t) needed > avail)
Packit 032894
	return needed - avail;
Packit 032894
      *d->bufcntp += needed;
Packit 032894
      return 0;
Packit 032894
    }
Packit 032894
Packit 032894
  return general_mod$r_m (d);
Packit 032894
}
Packit 032894
Packit 032894
static int
Packit 032894
generic_abs (struct output_data *d, const char *absstring
Packit 032894
#ifdef X86_64
Packit 032894
	     , int abslen
Packit 032894
#else
Packit 032894
# define abslen 4
Packit 032894
#endif
Packit 032894
	     )
Packit 032894
{
Packit 032894
  int r = data_prefix (d);
Packit 032894
  if (r != 0)
Packit 032894
    return r;
Packit 032894
Packit 032894
  assert (d->opoff1 % 8 == 0);
Packit 032894
  assert (d->opoff1 / 8 == 1);
Packit 032894
  if (*d->param_start + abslen > d->end)
Packit 032894
    return -1;
Packit 032894
  *d->param_start += abslen;
Packit 032894
#ifndef X86_64
Packit 032894
  uint32_t absval;
Packit 032894
# define ABSPRIFMT PRIx32
Packit 032894
#else
Packit 032894
  uint64_t absval;
Packit 032894
# define ABSPRIFMT PRIx64
Packit 032894
  if (abslen == 8)
Packit 032894
    absval = read_8ubyte_unaligned (&d->data[1]);
Packit 032894
  else
Packit 032894
#endif
Packit 032894
    absval = read_4ubyte_unaligned (&d->data[1]);
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "%s0x%" ABSPRIFMT,
Packit 032894
			 absstring, absval);
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_absval (struct output_data *d)
Packit 032894
{
Packit 032894
  return generic_abs (d, "$"
Packit 032894
#ifdef X86_64
Packit 032894
		      , 4
Packit 032894
#endif
Packit 032894
		      );
Packit 032894
}
Packit 032894
Packit 032894
static int
Packit 032894
FCT_abs (struct output_data *d)
Packit 032894
{
Packit 032894
  return generic_abs (d, ""
Packit 032894
#ifdef X86_64
Packit 032894
		      , 8
Packit 032894
#endif
Packit 032894
		      );
Packit 032894
}
Packit 032894
Packit 032894
static int
Packit 032894
FCT_ax (struct output_data *d)
Packit 032894
{
Packit 032894
  int is_16bit = (*d->prefixes & has_data16) != 0;
Packit 032894
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  char *bufp = d->bufp;
Packit 032894
  size_t bufsize = d->bufsize;
Packit 032894
Packit 032894
  if (*bufcntp + 4 - is_16bit > bufsize)
Packit 032894
    return *bufcntp + 4 - is_16bit - bufsize;
Packit 032894
Packit 032894
  bufp[(*bufcntp)++] = '%';
Packit 032894
  if (! is_16bit)
Packit 032894
    bufp[(*bufcntp)++] = (
Packit 032894
#ifdef X86_64
Packit 032894
			  (*d->prefixes & has_rex_w) ? 'r' :
Packit 032894
#endif
Packit 032894
			  'e');
Packit 032894
  bufp[(*bufcntp)++] = 'a';
Packit 032894
  bufp[(*bufcntp)++] = 'x';
Packit 032894
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_ax$w (struct output_data *d)
Packit 032894
{
Packit 032894
  if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
Packit 032894
    return FCT_ax (d);
Packit 032894
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  char *bufp = d->bufp;
Packit 032894
  size_t bufsize = d->bufsize;
Packit 032894
Packit 032894
  if (*bufcntp + 3 > bufsize)
Packit 032894
    return *bufcntp + 3 - bufsize;
Packit 032894
Packit 032894
  bufp[(*bufcntp)++] = '%';
Packit 032894
  bufp[(*bufcntp)++] = 'a';
Packit 032894
  bufp[(*bufcntp)++] = 'l';
Packit 032894
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
__attribute__ ((noinline))
Packit 032894
FCT_crdb (struct output_data *d, const char *regstr)
Packit 032894
{
Packit 032894
  if (*d->prefixes & has_data16)
Packit 032894
    return -1;
Packit 032894
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
Packit 032894
  // XXX If this assert is true, use absolute offset below
Packit 032894
  assert (d->opoff1 / 8 == 2);
Packit 032894
  assert (d->opoff1 % 8 == 2);
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%%s%" PRIx32,
Packit 032894
			 regstr, (uint32_t) (d->data[d->opoff1 / 8] >> 3) & 7);
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_ccc (struct output_data *d)
Packit 032894
{
Packit 032894
  return FCT_crdb (d, "cr");
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_ddd (struct output_data *d)
Packit 032894
{
Packit 032894
  return FCT_crdb (d, "db");
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_disp8 (struct output_data *d)
Packit 032894
{
Packit 032894
  assert (d->opoff1 % 8 == 0);
Packit 032894
  if (*d->param_start >= d->end)
Packit 032894
    return -1;
Packit 032894
  int32_t offset = *(const int8_t *) (*d->param_start)++;
Packit 032894
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
Packit 032894
			 (uint32_t) (d->addr + (*d->param_start - d->data)
Packit 032894
				     + offset));
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
__attribute__ ((noinline))
Packit 032894
FCT_ds_xx (struct output_data *d, const char *reg)
Packit 032894
{
Packit 032894
  int prefix = *d->prefixes & SEGMENT_PREFIXES;
Packit 032894
Packit 032894
  if (prefix == 0)
Packit 032894
    *d->prefixes |= prefix = has_ds;
Packit 032894
  /* Make sure only one bit is set.  */
Packit 032894
  else if ((prefix - 1) & prefix)
Packit 032894
    return -1;
Packit 032894
Packit 032894
  int r = data_prefix (d);
Packit 032894
Packit 032894
  assert ((*d->prefixes & prefix) == 0);
Packit 032894
Packit 032894
  if (r != 0)
Packit 032894
    return r;
Packit 032894
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "(%%%s%s)",
Packit 032894
#ifdef X86_64
Packit 032894
			 *d->prefixes & idx_addr16 ? "e" : "r",
Packit 032894
#else
Packit 032894
			 *d->prefixes & idx_addr16 ? "" : "e",
Packit 032894
#endif
Packit 032894
			 reg);
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return (size_t) needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_ds_bx (struct output_data *d)
Packit 032894
{
Packit 032894
  return FCT_ds_xx (d, "bx");
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_ds_si (struct output_data *d)
Packit 032894
{
Packit 032894
  return FCT_ds_xx (d, "si");
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_dx (struct output_data *d)
Packit 032894
{
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
Packit 032894
  if (*bufcntp + 7 > d->bufsize)
Packit 032894
    return *bufcntp + 7 - d->bufsize;
Packit 032894
Packit 032894
  memcpy (&d->bufp[*bufcntp], "(%dx)", 5);
Packit 032894
  *bufcntp += 5;
Packit 032894
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_es_di (struct output_data *d)
Packit 032894
{
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%es:(%%%sdi)",
Packit 032894
#ifdef X86_64
Packit 032894
			 *d->prefixes & idx_addr16 ? "e" : "r"
Packit 032894
#else
Packit 032894
			 *d->prefixes & idx_addr16 ? "" : "e"
Packit 032894
#endif
Packit 032894
			 );
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return (size_t) needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_imm (struct output_data *d)
Packit 032894
{
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  int needed;
Packit 032894
  if (*d->prefixes & has_data16)
Packit 032894
    {
Packit 032894
      if (*d->param_start + 2 > d->end)
Packit 032894
	return -1;
Packit 032894
      uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
Packit 032894
      needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
Packit 032894
    }
Packit 032894
  else
Packit 032894
    {
Packit 032894
      if (*d->param_start + 4 > d->end)
Packit 032894
	return -1;
Packit 032894
      int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
Packit 032894
#ifdef X86_64
Packit 032894
      if (*d->prefixes & has_rex_w)
Packit 032894
	needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
Packit 032894
			   (int64_t) word);
Packit 032894
      else
Packit 032894
#endif
Packit 032894
	needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
Packit 032894
    }
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return (size_t) needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_imm$w (struct output_data *d)
Packit 032894
{
Packit 032894
  if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
Packit 032894
    return FCT_imm (d);
Packit 032894
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  if (*d->param_start>= d->end)
Packit 032894
    return -1;
Packit 032894
  uint_fast8_t word = *(*d->param_start)++;
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIxFAST8, word);
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return (size_t) needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
#ifdef X86_64
Packit 032894
static int
Packit 032894
FCT_imm64$w (struct output_data *d)
Packit 032894
{
Packit 032894
  if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) == 0
Packit 032894
      || (*d->prefixes & has_data16) != 0)
Packit 032894
    return FCT_imm$w (d);
Packit 032894
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  int needed;
Packit 032894
  if (*d->prefixes & has_rex_w)
Packit 032894
    {
Packit 032894
      if (*d->param_start + 8 > d->end)
Packit 032894
	return -1;
Packit 032894
      uint64_t word = read_8ubyte_unaligned_inc (*d->param_start);
Packit 032894
      needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, word);
Packit 032894
    }
Packit 032894
  else
Packit 032894
    {
Packit 032894
      if (*d->param_start + 4 > d->end)
Packit 032894
	return -1;
Packit 032894
      int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
Packit 032894
      needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
Packit 032894
    }
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return (size_t) needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
#endif
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_imms (struct output_data *d)
Packit 032894
{
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  if (*d->param_start>= d->end)
Packit 032894
    return -1;
Packit 032894
  int8_t byte = *(*d->param_start)++;
Packit 032894
#ifdef X86_64
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
Packit 032894
			 (int64_t) byte);
Packit 032894
#else
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
Packit 032894
			 (int32_t) byte);
Packit 032894
#endif
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return (size_t) needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_imm$s (struct output_data *d)
Packit 032894
{
Packit 032894
  uint_fast8_t opcode = d->data[d->opoff2 / 8];
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  if ((opcode & 2) != 0)
Packit 032894
    return FCT_imms (d);
Packit 032894
Packit 032894
  if ((*d->prefixes & has_data16) == 0)
Packit 032894
    {
Packit 032894
      if (*d->param_start + 4 > d->end)
Packit 032894
	return -1;
Packit 032894
      int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
Packit 032894
#ifdef X86_64
Packit 032894
      int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
Packit 032894
			     (int64_t) word);
Packit 032894
#else
Packit 032894
      int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
Packit 032894
#endif
Packit 032894
      if ((size_t) needed > avail)
Packit 032894
	return (size_t) needed - avail;
Packit 032894
      *bufcntp += needed;
Packit 032894
    }
Packit 032894
  else
Packit 032894
    {
Packit 032894
      if (*d->param_start + 2 > d->end)
Packit 032894
	return -1;
Packit 032894
      uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
Packit 032894
      int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
Packit 032894
      if ((size_t) needed > avail)
Packit 032894
	return (size_t) needed - avail;
Packit 032894
      *bufcntp += needed;
Packit 032894
    }
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_imm16 (struct output_data *d)
Packit 032894
{
Packit 032894
  if (*d->param_start + 2 > d->end)
Packit 032894
    return -1;
Packit 032894
  uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return (size_t) needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_imms8 (struct output_data *d)
Packit 032894
{
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  if (*d->param_start >= d->end)
Packit 032894
    return -1;
Packit 032894
  int_fast8_t byte = *(*d->param_start)++;
Packit 032894
  int needed;
Packit 032894
#ifdef X86_64
Packit 032894
  if (*d->prefixes & has_rex_w)
Packit 032894
    needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
Packit 032894
		       (int64_t) byte);
Packit 032894
  else
Packit 032894
#endif
Packit 032894
    needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
Packit 032894
		       (int32_t) byte);
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return (size_t) needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_imm8 (struct output_data *d)
Packit 032894
{
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  if (*d->param_start >= d->end)
Packit 032894
    return -1;
Packit 032894
  uint_fast8_t byte = *(*d->param_start)++;
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
Packit 032894
			 (uint32_t) byte);
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return (size_t) needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_rel (struct output_data *d)
Packit 032894
{
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  if (*d->param_start + 4 > d->end)
Packit 032894
    return -1;
Packit 032894
  int32_t rel = read_4sbyte_unaligned_inc (*d->param_start);
Packit 032894
#ifdef X86_64
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx64,
Packit 032894
			 (uint64_t) (d->addr + rel
Packit 032894
				     + (*d->param_start - d->data)));
Packit 032894
#else
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
Packit 032894
			 (uint32_t) (d->addr + rel
Packit 032894
				     + (*d->param_start - d->data)));
Packit 032894
#endif
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return (size_t) needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_mmxreg (struct output_data *d)
Packit 032894
{
Packit 032894
  uint_fast8_t byte = d->data[d->opoff1 / 8];
Packit 032894
  assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
Packit 032894
  byte = (byte >> (5 - d->opoff1 % 8)) & 7;
Packit 032894
  size_t *bufcntp =  d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte);
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_mod$r_m (struct output_data *d)
Packit 032894
{
Packit 032894
  assert (d->opoff1 % 8 == 0);
Packit 032894
  uint_fast8_t modrm = d->data[d->opoff1 / 8];
Packit 032894
  if ((modrm & 0xc0) == 0xc0)
Packit 032894
    {
Packit 032894
      int prefixes = *d->prefixes;
Packit 032894
      if (prefixes & has_addr16)
Packit 032894
	return -1;
Packit 032894
Packit 032894
      int is_16bit = (prefixes & has_data16) != 0;
Packit 032894
Packit 032894
      size_t *bufcntp = d->bufcntp;
Packit 032894
      char *bufp = d->bufp;
Packit 032894
      if (*bufcntp + 5 - is_16bit > d->bufsize)
Packit 032894
	return *bufcntp + 5 - is_16bit - d->bufsize;
Packit 032894
      bufp[(*bufcntp)++] = '%';
Packit 032894
Packit 032894
      char *cp;
Packit 032894
#ifdef X86_64
Packit 032894
      if ((prefixes & has_rex_b) != 0 && !is_16bit)
Packit 032894
	{
Packit 032894
	  cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
Packit 032894
	  if ((prefixes & has_rex_w) == 0)
Packit 032894
	    *cp++ = 'd';
Packit 032894
	}
Packit 032894
      else
Packit 032894
#endif
Packit 032894
	{
Packit 032894
	  cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
Packit 032894
#ifdef X86_64
Packit 032894
	  if ((prefixes & has_rex_w) != 0)
Packit 032894
	    bufp[*bufcntp] = 'r';
Packit 032894
#endif
Packit 032894
	}
Packit 032894
      *bufcntp = cp - bufp;
Packit 032894
      return 0;
Packit 032894
    }
Packit 032894
Packit 032894
  return general_mod$r_m (d);
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
#ifndef X86_64
Packit 032894
static int
Packit 032894
FCT_moda$r_m (struct output_data *d)
Packit 032894
{
Packit 032894
  assert (d->opoff1 % 8 == 0);
Packit 032894
  uint_fast8_t modrm = d->data[d->opoff1 / 8];
Packit 032894
  if ((modrm & 0xc0) == 0xc0)
Packit 032894
    {
Packit 032894
      if (*d->prefixes & has_addr16)
Packit 032894
	return -1;
Packit 032894
Packit 032894
      size_t *bufcntp = d->bufcntp;
Packit 032894
      if (*bufcntp + 3 > d->bufsize)
Packit 032894
	return *bufcntp + 3 - d->bufsize;
Packit 032894
Packit 032894
      memcpy (&d->bufp[*bufcntp], "???", 3);
Packit 032894
      *bufcntp += 3;
Packit 032894
Packit 032894
      return 0;
Packit 032894
    }
Packit 032894
Packit 032894
  return general_mod$r_m (d);
Packit 032894
}
Packit 032894
#endif
Packit 032894
Packit 032894
Packit 032894
#ifdef X86_64
Packit 032894
static const char rex_8bit[8][3] =
Packit 032894
  {
Packit 032894
    [0] = "a", [1] = "c", [2] = "d", [3] = "b",
Packit 032894
    [4] = "sp", [5] = "bp", [6] = "si", [7] = "di"
Packit 032894
  };
Packit 032894
#endif
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_mod$r_m$w (struct output_data *d)
Packit 032894
{
Packit 032894
  assert (d->opoff1 % 8 == 0);
Packit 032894
  const uint8_t *data = d->data;
Packit 032894
  uint_fast8_t modrm = data[d->opoff1 / 8];
Packit 032894
  if ((modrm & 0xc0) == 0xc0)
Packit 032894
    {
Packit 032894
      int prefixes = *d->prefixes;
Packit 032894
Packit 032894
      if (prefixes & has_addr16)
Packit 032894
	return -1;
Packit 032894
Packit 032894
      size_t *bufcntp = d->bufcntp;
Packit 032894
      char *bufp = d->bufp;
Packit 032894
      if (*bufcntp + 5 > d->bufsize)
Packit 032894
	return *bufcntp + 5 - d->bufsize;
Packit 032894
Packit 032894
      if ((data[d->opoff3 / 8] & (1 << (7 - (d->opoff3 & 7)))) == 0)
Packit 032894
	{
Packit 032894
	  bufp[(*bufcntp)++] = '%';
Packit 032894
Packit 032894
#ifdef X86_64
Packit 032894
	  if (prefixes & has_rex)
Packit 032894
	    {
Packit 032894
	      if (prefixes & has_rex_r)
Packit 032894
		*bufcntp += snprintf (bufp + *bufcntp, d->bufsize - *bufcntp,
Packit 032894
				      "r%db", 8 + (modrm & 7));
Packit 032894
	      else
Packit 032894
		{
Packit 032894
		  char *cp = stpcpy (bufp + *bufcntp, hiregs[modrm & 7]);
Packit 032894
		  *cp++ = 'l';
Packit 032894
		  *bufcntp = cp - bufp;
Packit 032894
		}
Packit 032894
	    }
Packit 032894
	  else
Packit 032894
#endif
Packit 032894
	    {
Packit 032894
	      bufp[(*bufcntp)++] = "acdb"[modrm & 3];
Packit 032894
	      bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
Packit 032894
	    }
Packit 032894
	}
Packit 032894
      else
Packit 032894
	{
Packit 032894
	  int is_16bit = (prefixes & has_data16) != 0;
Packit 032894
Packit 032894
	  bufp[(*bufcntp)++] = '%';
Packit 032894
Packit 032894
	  char *cp;
Packit 032894
#ifdef X86_64
Packit 032894
	  if ((prefixes & has_rex_b) != 0 && !is_16bit)
Packit 032894
	    {
Packit 032894
	      cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
Packit 032894
	      if ((prefixes & has_rex_w) == 0)
Packit 032894
		*cp++ = 'd';
Packit 032894
	    }
Packit 032894
	  else
Packit 032894
#endif
Packit 032894
	    {
Packit 032894
	      cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
Packit 032894
#ifdef X86_64
Packit 032894
	      if ((prefixes & has_rex_w) != 0)
Packit 032894
		bufp[*bufcntp] = 'r';
Packit 032894
#endif
Packit 032894
	    }
Packit 032894
	  *bufcntp = cp - bufp;
Packit 032894
	}
Packit 032894
      return 0;
Packit 032894
    }
Packit 032894
Packit 032894
  return general_mod$r_m (d);
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_mod$8r_m (struct output_data *d)
Packit 032894
{
Packit 032894
  assert (d->opoff1 % 8 == 0);
Packit 032894
  uint_fast8_t modrm = d->data[d->opoff1 / 8];
Packit 032894
  if ((modrm & 0xc0) == 0xc0)
Packit 032894
    {
Packit 032894
      size_t *bufcntp = d->bufcntp;
Packit 032894
      char *bufp = d->bufp;
Packit 032894
      if (*bufcntp + 3 > d->bufsize)
Packit 032894
	return *bufcntp + 3 - d->bufsize;
Packit 032894
      bufp[(*bufcntp)++] = '%';
Packit 032894
      bufp[(*bufcntp)++] = "acdb"[modrm & 3];
Packit 032894
      bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
Packit 032894
      return 0;
Packit 032894
    }
Packit 032894
Packit 032894
  return general_mod$r_m (d);
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_mod$16r_m (struct output_data *d)
Packit 032894
{
Packit 032894
  assert (d->opoff1 % 8 == 0);
Packit 032894
  uint_fast8_t modrm = d->data[d->opoff1 / 8];
Packit 032894
  if ((modrm & 0xc0) == 0xc0)
Packit 032894
    {
Packit 032894
      assert (d->opoff1 / 8 == d->opoff2 / 8);
Packit 032894
      //uint_fast8_t byte = data[opoff2 / 8] & 7;
Packit 032894
      uint_fast8_t byte = modrm & 7;
Packit 032894
Packit 032894
      size_t *bufcntp = d->bufcntp;
Packit 032894
      if (*bufcntp + 3 > d->bufsize)
Packit 032894
	return *bufcntp + 3 - d->bufsize;
Packit 032894
      d->bufp[(*bufcntp)++] = '%';
Packit 032894
      memcpy (&d->bufp[*bufcntp], dregs[byte] + 1, sizeof (dregs[0]) - 1);
Packit 032894
      *bufcntp += 2;
Packit 032894
      return 0;
Packit 032894
    }
Packit 032894
Packit 032894
  return general_mod$r_m (d);
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
#ifdef X86_64
Packit 032894
static int
Packit 032894
FCT_mod$64r_m (struct output_data *d)
Packit 032894
{
Packit 032894
  assert (d->opoff1 % 8 == 0);
Packit 032894
  uint_fast8_t modrm = d->data[d->opoff1 / 8];
Packit 032894
  if ((modrm & 0xc0) == 0xc0)
Packit 032894
    {
Packit 032894
      assert (d->opoff1 / 8 == d->opoff2 / 8);
Packit 032894
      //uint_fast8_t byte = data[opoff2 / 8] & 7;
Packit 032894
      uint_fast8_t byte = modrm & 7;
Packit 032894
Packit 032894
      size_t *bufcntp = d->bufcntp;
Packit 032894
      if (*bufcntp + 4 > d->bufsize)
Packit 032894
	return *bufcntp + 4 - d->bufsize;
Packit 032894
      char *cp = &d->bufp[*bufcntp];
Packit 032894
      *cp++ = '%';
Packit 032894
      cp = stpcpy (cp,
Packit 032894
		   (*d->prefixes & has_rex_b) ? hiregs[byte] : aregs[byte]);
Packit 032894
      *bufcntp = cp - d->bufp;
Packit 032894
      return 0;
Packit 032894
    }
Packit 032894
Packit 032894
  return general_mod$r_m (d);
Packit 032894
}
Packit 032894
#else
Packit 032894
static typeof (FCT_mod$r_m) FCT_mod$64r_m __attribute__ ((alias ("FCT_mod$r_m")));
Packit 032894
#endif
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_reg (struct output_data *d)
Packit 032894
{
Packit 032894
  uint_fast8_t byte = d->data[d->opoff1 / 8];
Packit 032894
  assert (d->opoff1 % 8 + 3 <= 8);
Packit 032894
  byte >>= 8 - (d->opoff1 % 8 + 3);
Packit 032894
  byte &= 7;
Packit 032894
  int is_16bit = (*d->prefixes & has_data16) != 0;
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  if (*bufcntp + 5 > d->bufsize)
Packit 032894
    return *bufcntp + 5 - d->bufsize;
Packit 032894
  d->bufp[(*bufcntp)++] = '%';
Packit 032894
#ifdef X86_64
Packit 032894
  if ((*d->prefixes & has_rex_r) != 0 && !is_16bit)
Packit 032894
    {
Packit 032894
      *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
Packit 032894
			    8 + byte);
Packit 032894
      if ((*d->prefixes & has_rex_w) == 0)
Packit 032894
	d->bufp[(*bufcntp)++] = 'd';
Packit 032894
    }
Packit 032894
  else
Packit 032894
#endif
Packit 032894
    {
Packit 032894
      memcpy (&d->bufp[*bufcntp], dregs[byte] + is_16bit, 3 - is_16bit);
Packit 032894
#ifdef X86_64
Packit 032894
      if ((*d->prefixes & has_rex_w) != 0 && !is_16bit)
Packit 032894
	d->bufp[*bufcntp] = 'r';
Packit 032894
#endif
Packit 032894
      *bufcntp += 3 - is_16bit;
Packit 032894
    }
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
#ifdef X86_64
Packit 032894
static int
Packit 032894
FCT_oreg (struct output_data *d)
Packit 032894
{
Packit 032894
  /* Special form where register comes from opcode.  The rex.B bit is used,
Packit 032894
     rex.R and rex.X are ignored.  */
Packit 032894
  int save_prefixes = *d->prefixes;
Packit 032894
Packit 032894
  *d->prefixes = ((save_prefixes & ~has_rex_r)
Packit 032894
		  | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
Packit 032894
Packit 032894
  int r = FCT_reg (d);
Packit 032894
Packit 032894
  *d->prefixes = save_prefixes;
Packit 032894
Packit 032894
  return r;
Packit 032894
}
Packit 032894
#endif
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_reg64 (struct output_data *d)
Packit 032894
{
Packit 032894
  uint_fast8_t byte = d->data[d->opoff1 / 8];
Packit 032894
  assert (d->opoff1 % 8 + 3 <= 8);
Packit 032894
  byte >>= 8 - (d->opoff1 % 8 + 3);
Packit 032894
  byte &= 7;
Packit 032894
  if ((*d->prefixes & has_data16) != 0)
Packit 032894
    return -1;
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  if (*bufcntp + 5 > d->bufsize)
Packit 032894
    return *bufcntp + 5 - d->bufsize;
Packit 032894
  d->bufp[(*bufcntp)++] = '%';
Packit 032894
#ifdef X86_64
Packit 032894
  if ((*d->prefixes & has_rex_r) != 0)
Packit 032894
    {
Packit 032894
      *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
Packit 032894
			    8 + byte);
Packit 032894
      if ((*d->prefixes & has_rex_w) == 0)
Packit 032894
	d->bufp[(*bufcntp)++] = 'd';
Packit 032894
    }
Packit 032894
  else
Packit 032894
#endif
Packit 032894
    {
Packit 032894
      memcpy (&d->bufp[*bufcntp], aregs[byte], 3);
Packit 032894
      *bufcntp += 3;
Packit 032894
    }
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_reg$w (struct output_data *d)
Packit 032894
{
Packit 032894
  if (d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7))))
Packit 032894
    return FCT_reg (d);
Packit 032894
Packit 032894
  uint_fast8_t byte = d->data[d->opoff1 / 8];
Packit 032894
  assert (d->opoff1 % 8 + 3 <= 8);
Packit 032894
  byte >>= 8 - (d->opoff1 % 8 + 3);
Packit 032894
  byte &= 7;
Packit 032894
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  if (*bufcntp + 4 > d->bufsize)
Packit 032894
    return *bufcntp + 4 - d->bufsize;
Packit 032894
Packit 032894
  d->bufp[(*bufcntp)++] = '%';
Packit 032894
Packit 032894
#ifdef X86_64
Packit 032894
  if (*d->prefixes & has_rex)
Packit 032894
    {
Packit 032894
      if (*d->prefixes & has_rex_r)
Packit 032894
	*bufcntp += snprintf (d->bufp + *bufcntp, d->bufsize - *bufcntp,
Packit 032894
			      "r%db", 8 + byte);
Packit 032894
      else
Packit 032894
	{
Packit 032894
	  char* cp = stpcpy (d->bufp + *bufcntp, rex_8bit[byte]);
Packit 032894
	  *cp++ = 'l';
Packit 032894
	  *bufcntp = cp - d->bufp;
Packit 032894
	}
Packit 032894
    }
Packit 032894
  else
Packit 032894
#endif
Packit 032894
    {
Packit 032894
      d->bufp[(*bufcntp)++] = "acdb"[byte & 3];
Packit 032894
      d->bufp[(*bufcntp)++] = "lh"[byte >> 2];
Packit 032894
    }
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
#ifdef X86_64
Packit 032894
static int
Packit 032894
FCT_oreg$w (struct output_data *d)
Packit 032894
{
Packit 032894
  /* Special form where register comes from opcode.  The rex.B bit is used,
Packit 032894
     rex.R and rex.X are ignored.  */
Packit 032894
  int save_prefixes = *d->prefixes;
Packit 032894
Packit 032894
  *d->prefixes = ((save_prefixes & ~has_rex_r)
Packit 032894
		  | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
Packit 032894
Packit 032894
  int r = FCT_reg$w (d);
Packit 032894
Packit 032894
  *d->prefixes = save_prefixes;
Packit 032894
Packit 032894
  return r;
Packit 032894
}
Packit 032894
#endif
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_freg (struct output_data *d)
Packit 032894
{
Packit 032894
  assert (d->opoff1 / 8 == 1);
Packit 032894
  assert (d->opoff1 % 8 == 5);
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%st(%" PRIx32 ")",
Packit 032894
			 (uint32_t) (d->data[1] & 7));
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return (size_t) needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
#ifndef X86_64
Packit 032894
static int
Packit 032894
FCT_reg16 (struct output_data *d)
Packit 032894
{
Packit 032894
  if (*d->prefixes & has_data16)
Packit 032894
    return -1;
Packit 032894
Packit 032894
  *d->prefixes |= has_data16;
Packit 032894
  return FCT_reg (d);
Packit 032894
}
Packit 032894
#endif
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_sel (struct output_data *d)
Packit 032894
{
Packit 032894
  assert (d->opoff1 % 8 == 0);
Packit 032894
  assert (d->opoff1 / 8 == 5);
Packit 032894
  if (*d->param_start + 2 >= d->end)
Packit 032894
    return -1;
Packit 032894
  *d->param_start += 2;
Packit 032894
  uint16_t absval = read_2ubyte_unaligned (&d->data[5]);
Packit 032894
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, absval);
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_sreg2 (struct output_data *d)
Packit 032894
{
Packit 032894
  uint_fast8_t byte = d->data[d->opoff1 / 8];
Packit 032894
  assert (d->opoff1 % 8 + 3 <= 8);
Packit 032894
  byte >>= 8 - (d->opoff1 % 8 + 2);
Packit 032894
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  char *bufp = d->bufp;
Packit 032894
  if (*bufcntp + 3 > d->bufsize)
Packit 032894
    return *bufcntp + 3 - d->bufsize;
Packit 032894
Packit 032894
  bufp[(*bufcntp)++] = '%';
Packit 032894
  bufp[(*bufcntp)++] = "ecsd"[byte & 3];
Packit 032894
  bufp[(*bufcntp)++] = 's';
Packit 032894
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_sreg3 (struct output_data *d)
Packit 032894
{
Packit 032894
  uint_fast8_t byte = d->data[d->opoff1 / 8];
Packit 032894
  assert (d->opoff1 % 8 + 4 <= 8);
Packit 032894
  byte >>= 8 - (d->opoff1 % 8 + 3);
Packit 032894
Packit 032894
  if ((byte & 7) >= 6)
Packit 032894
    return -1;
Packit 032894
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  char *bufp = d->bufp;
Packit 032894
  if (*bufcntp + 3 > d->bufsize)
Packit 032894
    return *bufcntp + 3 - d->bufsize;
Packit 032894
Packit 032894
  bufp[(*bufcntp)++] = '%';
Packit 032894
  bufp[(*bufcntp)++] = "ecsdfg"[byte & 7];
Packit 032894
  bufp[(*bufcntp)++] = 's';
Packit 032894
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_string (struct output_data *d __attribute__ ((unused)))
Packit 032894
{
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static int
Packit 032894
FCT_xmmreg (struct output_data *d)
Packit 032894
{
Packit 032894
  uint_fast8_t byte = d->data[d->opoff1 / 8];
Packit 032894
  assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
Packit 032894
  byte = (byte >> (5 - d->opoff1 % 8)) & 7;
Packit 032894
Packit 032894
  size_t *bufcntp = d->bufcntp;
Packit 032894
  size_t avail = d->bufsize - *bufcntp;
Packit 032894
  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, byte);
Packit 032894
  if ((size_t) needed > avail)
Packit 032894
    return needed - avail;
Packit 032894
  *bufcntp += needed;
Packit 032894
  return 0;
Packit 032894
}