125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Helper routines for disassembler for x86/x86-64.
225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Copyright (C) 2007, 2008 Red Hat, Inc.
325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   This file is part of Red Hat elfutils.
425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Written by Ulrich Drepper <drepper@redhat.com>, 2007.
525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is free software; you can redistribute it and/or modify
725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   it under the terms of the GNU General Public License as published by the
825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Free Software Foundation; version 2 of the License.
925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is distributed in the hope that it will be useful, but
1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   General Public License for more details.
1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   You should have received a copy of the GNU General Public License along
1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   with Red Hat elfutils; if not, write to the Free Software Foundation,
1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is an included package of the Open Invention Network.
2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   An included package of the Open Invention Network is a package for which
2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Open Invention Network licensees cross-license their patents.  No patent
2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   license is granted, either expressly or impliedly, by designation as an
2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   included package.  Should you wish to participate in the Open Invention
2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Network licensing program, please visit www.openinventionnetwork.com
2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   <http://www.openinventionnetwork.com>.  */
2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <inttypes.h>
2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stddef.h>
2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdio.h>
3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdint.h>
3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libasm.h>
3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3325b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct instr_enc
3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* The mnemonic.  Especially encoded for the optimized table.  */
3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int mnemonic : MNEMONIC_BITS;
3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* The rep/repe prefixes.  */
3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int rep : 1;
4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int repe : 1;
4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Mnemonic suffix.  */
4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int suffix : SUFFIX_BITS;
4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Nonzero if the instruction uses modr/m.  */
4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int modrm : 1;
4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* 1st parameter.  */
4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int fct1 : FCT1_BITS;
5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef STR1_BITS
5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int str1 : STR1_BITS;
5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int off1_1 : OFF1_1_BITS;
5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int off1_2 : OFF1_2_BITS;
5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int off1_3 : OFF1_3_BITS;
5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* 2nd parameter.  */
5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int fct2 : FCT2_BITS;
5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef STR2_BITS
6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int str2 : STR2_BITS;
6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int off2_1 : OFF2_1_BITS;
6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int off2_2 : OFF2_2_BITS;
6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int off2_3 : OFF2_3_BITS;
6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* 3rd parameter.  */
6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int fct3 : FCT3_BITS;
6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef STR3_BITS
6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int str3 : STR3_BITS;
7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int off3_1 : OFF3_1_BITS;
7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef OFF3_2_BITS
7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int off3_2 : OFF3_2_BITS;
7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef OFF3_3_BITS
7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned int off3_3 : OFF3_3_BITS;
7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8125b3c049e70834cf33790a28643ab058b507b35cBen Chengtypedef int (*opfct_t) (struct output_data *);
8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
8525b3c049e70834cf33790a28643ab058b507b35cBen Chengdata_prefix (struct output_data *d)
8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char ch = '\0';
8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->prefixes & has_cs)
8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ch = 'c';
9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *d->prefixes &= ~has_cs;
9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (*d->prefixes & has_ds)
9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ch = 'd';
9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *d->prefixes &= ~has_ds;
9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (*d->prefixes & has_es)
9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ch = 'e';
10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *d->prefixes &= ~has_es;
10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (*d->prefixes & has_fs)
10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ch = 'f';
10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *d->prefixes &= ~has_fs;
10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (*d->prefixes & has_gs)
10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ch = 'g';
11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *d->prefixes &= ~has_gs;
11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (*d->prefixes & has_ss)
11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ch = 's';
11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *d->prefixes &= ~has_ss;
11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return 0;
12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->bufcntp + 4 > d->bufsize)
12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return *d->bufcntp + 4 - d->bufsize;
12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  d->bufp[(*d->bufcntp)++] = '%';
12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  d->bufp[(*d->bufcntp)++] = ch;
12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  d->bufp[(*d->bufcntp)++] = 's';
12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  d->bufp[(*d->bufcntp)++] = ':';
12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
13325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char hiregs[8][4] =
13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  };
13725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char aregs[8][4] =
13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"
14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  };
14125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char dregs[8][4] =
14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  };
14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
14625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char aregs[8][4] =
14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  };
15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define dregs aregs
15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
15425b3c049e70834cf33790a28643ab058b507b35cBen Chenggeneral_mod$r_m (struct output_data *d)
15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int r = data_prefix (d);
15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (r != 0)
15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return r;
15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int prefixes = *d->prefixes;
16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const uint8_t *data = &d->data[d->opoff1 / 8];
16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *bufp = d->bufp;
16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t bufsize = d->bufsize;
16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t modrm = data[0];
16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef X86_64
16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely ((prefixes & has_addr16) != 0))
16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int16_t disp = 0;
17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool nodisp = false;
17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80)
17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* 16 bit displacement.  */
17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	disp = read_2sbyte_unaligned (&data[1]);
17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if ((modrm & 0xc0) == 0x40)
17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* 8 bit displacement.  */
17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	disp = *(const int8_t *) &data[1];
17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if ((modrm & 0xc0) == 0)
18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	nodisp = true;
18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char tmpbuf[sizeof ("-0x1234(%rr,%rr)")];
18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int n;
18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((modrm & 0xc7) == 6)
18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx16, disp);
18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  n = 0;
18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (!nodisp)
19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx16,
19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if ((modrm & 0x4) == 0)
19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%b%c,%%%ci)",
19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   "xp"[(modrm >> 1) & 1], "sd"[modrm & 1]);
19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%%s)",
19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   ((const char [4][3]) { "si", "di", "bp", "bx" })[modrm & 3]);
19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*bufcntp + n + 1 > bufsize)
20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return *bufcntp + n + 1 - bufsize;
20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *bufcntp += n;
20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((modrm & 7) != 4)
21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int32_t disp = 0;
21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  bool nodisp = false;
21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80)
21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* 32 bit displacement.  */
21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    disp = read_4sbyte_unaligned (&data[1]);
21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if ((modrm & 0xc0) == 0x40)
21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* 8 bit displacement.  */
22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    disp = *(const int8_t *) &data[1];
22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if ((modrm & 0xc0) == 0)
22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    nodisp = true;
22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char tmpbuf[sizeof ("-0x12345678(%rrrr)")];
22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int n;
22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (nodisp)
22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)",
22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    (prefixes & has_rex_b) ? hiregs[modrm & 7] :
23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    aregs[modrm & 7]);
23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (prefixes & has_addr16)
23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (prefixes & has_rex_b)
23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    tmpbuf[n++] = 'd';
23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else
23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    tmpbuf[2] = 'e';
24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if ((modrm & 0xc7) != 5)
24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      int p;
24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%n%s)",
24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    disp < 0 ? "-" : "", disp < 0 ? -disp : disp, &p,
24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    (prefixes & has_rex_b) ? hiregs[modrm & 7] :
25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    aregs[modrm & 7]);
25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (prefixes & has_addr16)
25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (prefixes & has_rex_b)
25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    tmpbuf[n++] = 'd';
25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else
25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    tmpbuf[p] = 'e';
25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%rip)",
26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      d->symaddr_use = addr_rel_always;
26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      d->symaddr = disp;
27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp);
27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (*bufcntp + n + 1 > bufsize)
27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return *bufcntp + n + 1 - bufsize;
27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *bufcntp += n;
28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* SIB */
28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint_fast8_t sib = data[1];
28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int32_t disp = 0;
28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  bool nodisp = false;
28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80
28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      || ((modrm & 0xc7) == 0x4 && (sib & 0x7) == 0x5))
29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* 32 bit displacement.  */
29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    disp = read_4sbyte_unaligned (&data[2]);
29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if ((modrm & 0xc0) == 0x40)
29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* 8 bit displacement.  */
29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    disp = *(const int8_t *) &data[2];
29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    nodisp = true;
29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char tmpbuf[sizeof ("-0x12345678(%rrrr,%rrrr,N)")];
29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *cp = tmpbuf;
30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int n;
30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25
30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      || (prefixes & has_rex_x) != 0
30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      )
30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (!nodisp)
30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  n = snprintf (cp, sizeof (tmpbuf), "%s0x%" PRIx32,
31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  cp += n;
31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      *cp++ = '(';
31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if ((modrm & 0xc7) != 0x4 || (sib & 0x7) != 0x5)
31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  *cp++ = '%';
31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  cp = stpcpy (cp,
32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       (prefixes & has_rex_b) ? hiregs[sib & 7] :
32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       (prefixes & has_addr16) ? dregs[sib & 7] :
32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       aregs[sib & 7]);
32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if ((prefixes & (has_rex_b | has_addr16))
32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      == (has_rex_b | has_addr16))
32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    *cp++ = 'd';
32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if ((sib & 0x38) != 0x20
33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  || (prefixes & has_rex_x) != 0
33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  )
33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  *cp++ = ',';
33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  *cp++ = '%';
34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  cp = stpcpy (cp,
34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       (prefixes & has_rex_x)
34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       ? hiregs[(sib >> 3) & 7] :
34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       (prefixes & has_addr16)
34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       ? dregs[(sib >> 3) & 7] :
34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       aregs[(sib >> 3) & 7]);
34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if ((prefixes & (has_rex_b | has_addr16))
35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      == (has_rex_b | has_addr16))
35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    *cp++ = 'd';
35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  *cp++ = ',';
35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  *cp++ = '0' + (1 << (sib >> 6));
35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      *cp++ = ')';
35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      assert (! nodisp);
36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if ((prefixes & has_addr16) == 0)
36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx64,
36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      (int64_t) disp);
36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx32, disp);
37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      cp += n;
37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (*bufcntp + (cp - tmpbuf) > bufsize)
37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return *bufcntp + (cp - tmpbuf) - bufsize;
37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  memcpy (&bufp[*bufcntp], tmpbuf, cp - tmpbuf);
37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *bufcntp += cp - tmpbuf;
37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
38525b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_MOD$R_M (struct output_data *d)
38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 == 0);
38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t modrm = d->data[d->opoff1 / 8];
38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((modrm & 0xc0) == 0xc0)
39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (d->opoff1 / 8 == d->opoff2 / 8);
39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (d->opoff2 % 8 == 5);
39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      //uint_fast8_t byte = d->data[d->opoff2 / 8] & 7;
39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t byte = modrm & 7;
39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t *bufcntp = d->bufcntp;
39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *buf = d->bufp + *bufcntp;
39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t avail = d->bufsize - *bufcntp;
39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int needed;
40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*d->prefixes & (has_rep | has_repne))
40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	needed = snprintf (buf, avail, "%%%s", dregs[byte]);
40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	needed = snprintf (buf, avail, "%%mm%" PRIxFAST8, byte);
40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((size_t) needed > avail)
40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return needed - avail;
40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *bufcntp += needed;
40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 0;
40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return general_mod$r_m (d);
41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
41525b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_Mod$R_m (struct output_data *d)
41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 == 0);
41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t modrm = d->data[d->opoff1 / 8];
41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((modrm & 0xc0) == 0xc0)
42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (d->opoff1 / 8 == d->opoff2 / 8);
42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (d->opoff2 % 8 == 5);
42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      //uint_fast8_t byte = data[opoff2 / 8] & 7;
42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t byte = modrm & 7;
42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t *bufcntp = d->bufcntp;
42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t avail = d->bufsize - *bufcntp;
42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8,
42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     byte);
43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((size_t) needed > avail)
43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return needed - avail;
43225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *d->bufcntp += needed;
43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 0;
43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return general_mod$r_m (d);
43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
44025b3c049e70834cf33790a28643ab058b507b35cBen Chenggeneric_abs (struct output_data *d, const char *absstring
44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     , int abslen
44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define abslen 4
44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     )
44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int r = data_prefix (d);
44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (r != 0)
45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return r;
45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 == 0);
45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 / 8 == 1);
45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->param_start + abslen > d->end)
45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *d->param_start += abslen;
45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef X86_64
45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint32_t absval;
45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define ABSPRIFMT PRIx32
46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint64_t absval;
46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define ABSPRIFMT PRIx64
46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (abslen == 8)
46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    absval = read_8ubyte_unaligned (&d->data[1]);
46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    absval = read_4ubyte_unaligned (&d->data[1]);
46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "%s0x%" ABSPRIFMT,
47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 absstring, absval);
47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return needed - avail;
47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
47925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
48025b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_absval (struct output_data *d)
48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return generic_abs (d, "$"
48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      , 4
48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      );
48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
48925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
49025b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_abs (struct output_data *d)
49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return generic_abs (d, ""
49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      , 8
49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      );
49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
50025b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_ax (struct output_data *d)
50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
50225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int is_16bit = (*d->prefixes & has_data16) != 0;
50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *bufp = d->bufp;
50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t bufsize = d->bufsize;
50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*bufcntp + 4 - is_16bit > bufsize)
50925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return *bufcntp + 4 - is_16bit - bufsize;
51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bufp[(*bufcntp)++] = '%';
51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (! is_16bit)
51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    bufp[(*bufcntp)++] = (
51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (*d->prefixes & has_rex_w) ? 'r' :
51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  'e');
51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bufp[(*bufcntp)++] = 'a';
51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bufp[(*bufcntp)++] = 'x';
52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
52625b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_ax$w (struct output_data *d)
52725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
52925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return FCT_ax (d);
53025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
53225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *bufp = d->bufp;
53325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t bufsize = d->bufsize;
53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*bufcntp + 3 > bufsize)
53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return *bufcntp + 3 - bufsize;
53725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bufp[(*bufcntp)++] = '%';
53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bufp[(*bufcntp)++] = 'a';
54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bufp[(*bufcntp)++] = 'l';
54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng__attribute__ ((noinline))
54825b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_crdb (struct output_data *d, const char *regstr)
54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->prefixes & has_data16)
55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
55425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  // XXX If this assert is true, use absolute offset below
55625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 / 8 == 2);
55725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 == 2);
55825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%%s%" PRIx32,
56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 regstr, (uint32_t) (d->data[d->opoff1 / 8] >> 3) & 7);
56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return needed - avail;
56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
56925b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_ccc (struct output_data *d)
57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return FCT_crdb (d, "cr");
57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
57625b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_ddd (struct output_data *d)
57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return FCT_crdb (d, "db");
57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
58225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
58325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_disp8 (struct output_data *d)
58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 == 0);
58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->param_start >= d->end)
58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
58825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int32_t offset = *(const int8_t *) (*d->param_start)++;
58925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 (uint32_t) (d->addr + (*d->param_start - d->data)
59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     + offset));
59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return needed - avail;
59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng__attribute__ ((noinline))
60425b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_ds_xx (struct output_data *d, const char *reg)
60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int prefix = *d->prefixes & SEGMENT_PREFIXES;
60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (prefix == 0)
60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    *d->prefixes |= prefix = has_ds;
61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Make sure only one bit is set.  */
61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if ((prefix - 1) & prefix)
61225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int r = data_prefix (d);
61525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
61625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert ((*d->prefixes & prefix) == 0);
61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (r != 0)
61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return r;
62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
62225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "(%%%s%s)",
62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 *d->prefixes & idx_addr16 ? "e" : "r",
62625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 *d->prefixes & idx_addr16 ? "" : "e",
62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 reg);
63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return (size_t) needed - avail;
63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
63925b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_ds_bx (struct output_data *d)
64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return FCT_ds_xx (d, "bx");
64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
64525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
64625b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_ds_si (struct output_data *d)
64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return FCT_ds_xx (d, "si");
64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
65225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
65325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_dx (struct output_data *d)
65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*bufcntp + 7 > d->bufsize)
65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return *bufcntp + 7 - d->bufsize;
65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memcpy (&d->bufp[*bufcntp], "(%dx)", 5);
66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += 5;
66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
66325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
66425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
66725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
66825b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_es_di (struct output_data *d)
66925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%es:(%%%sdi)",
67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 *d->prefixes & idx_addr16 ? "e" : "r"
67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
67625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 *d->prefixes & idx_addr16 ? "" : "e"
67725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 );
67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return (size_t) needed - avail;
68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
68325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
68425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
68525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
68625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
68725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
68825b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imm (struct output_data *d)
68925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
69025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
69125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
69225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed;
69325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->prefixes & has_data16)
69425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
69525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*d->param_start + 2 > d->end)
69625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return -1;
69725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
69825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
69925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
70025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
70125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
70225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*d->param_start + 4 > d->end)
70325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return -1;
70425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
70525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
70625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*d->prefixes & has_rex_w)
70725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
70825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   (int64_t) word);
70925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
71025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
71125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
71225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
71325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
71425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return (size_t) needed - avail;
71525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
71625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
71725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
71825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
71925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
72025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
72125b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imm$w (struct output_data *d)
72225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
72325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
72425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return FCT_imm (d);
72525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
72625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
72725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
72825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->param_start>= d->end)
72925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
73025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t word = *(*d->param_start)++;
73125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIxFAST8, word);
73225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
73325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return (size_t) needed - avail;
73425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
73525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
73625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
73725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
73825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
73925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
74025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
74125b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imm64$w (struct output_data *d)
74225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
74325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) == 0
74425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      || (*d->prefixes & has_data16) != 0)
74525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return FCT_imm$w (d);
74625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
74725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
74825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
74925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed;
75025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->prefixes & has_rex_w)
75125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
75225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*d->param_start + 8 > d->end)
75325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return -1;
75425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint64_t word = read_8ubyte_unaligned_inc (*d->param_start);
75525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, word);
75625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
75725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
75825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
75925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*d->param_start + 4 > d->end)
76025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return -1;
76125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
76225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
76325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
76425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
76525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return (size_t) needed - avail;
76625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
76725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
76825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
76925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
77025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
77125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
77225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
77325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imms (struct output_data *d)
77425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
77525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
77625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
77725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->param_start>= d->end)
77825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
77925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int8_t byte = *(*d->param_start)++;
78025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
78125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
78225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 (int64_t) byte);
78325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
78425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
78525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 (int32_t) byte);
78625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
78725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
78825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return (size_t) needed - avail;
78925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
79025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
79125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
79225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
79325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
79425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
79525b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imm$s (struct output_data *d)
79625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
79725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t opcode = d->data[d->opoff2 / 8];
79825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
79925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
80025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((opcode & 2) != 0)
80125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return FCT_imms (d);
80225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
80325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((*d->prefixes & has_data16) == 0)
80425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
80525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*d->param_start + 4 > d->end)
80625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return -1;
80725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
80825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
80925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
81025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     (int64_t) word);
81125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
81225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
81325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
81425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((size_t) needed > avail)
81525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return (size_t) needed - avail;
81625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *bufcntp += needed;
81725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
81825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
81925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
82025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*d->param_start + 2 > d->end)
82125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return -1;
82225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
82325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
82425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((size_t) needed > avail)
82525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return (size_t) needed - avail;
82625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *bufcntp += needed;
82725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
82825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
82925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
83025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
83125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
83225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
83325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imm16 (struct output_data *d)
83425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
83525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->param_start + 2 > d->end)
83625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
83725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
83825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
83925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
84025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
84125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
84225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return (size_t) needed - avail;
84325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
84425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
84525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
84625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
84725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
84825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
84925b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imms8 (struct output_data *d)
85025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
85125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
85225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
85325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->param_start >= d->end)
85425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
85525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int_fast8_t byte = *(*d->param_start)++;
85625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed;
85725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
85825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->prefixes & has_rex_w)
85925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
86025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       (int64_t) byte);
86125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
86225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
86325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
86425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       (int32_t) byte);
86525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
86625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return (size_t) needed - avail;
86725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
86825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
86925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
87025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
87125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
87225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
87325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imm8 (struct output_data *d)
87425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
87525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
87625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
87725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->param_start >= d->end)
87825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
87925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t byte = *(*d->param_start)++;
88025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
88125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 (uint32_t) byte);
88225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
88325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return (size_t) needed - avail;
88425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
88525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
88625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
88725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
88825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
88925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
89025b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_rel (struct output_data *d)
89125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
89225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
89325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
89425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->param_start + 4 > d->end)
89525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
89625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int32_t rel = read_4sbyte_unaligned_inc (*d->param_start);
89725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
89825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx64,
89925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 (uint64_t) (d->addr + rel
90025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     + (*d->param_start - d->data)));
90125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
90225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
90325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 (uint32_t) (d->addr + rel
90425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     + (*d->param_start - d->data)));
90525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
90625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
90725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return (size_t) needed - avail;
90825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
90925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
91025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
91125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
91225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
91325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
91425b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_mmxreg (struct output_data *d)
91525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
91625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t byte = d->data[d->opoff1 / 8];
91725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
91825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  byte = (byte >> (5 - d->opoff1 % 8)) & 7;
91925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp =  d->bufcntp;
92025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
92125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte);
92225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
92325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return needed - avail;
92425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
92525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
92625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
92725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
92825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
92925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
93025b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_mod$r_m (struct output_data *d)
93125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
93225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 == 0);
93325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t modrm = d->data[d->opoff1 / 8];
93425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((modrm & 0xc0) == 0xc0)
93525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
93625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int prefixes = *d->prefixes;
93725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (prefixes & has_addr16)
93825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return -1;
93925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
94025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int is_16bit = (prefixes & has_data16) != 0;
94125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
94225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t *bufcntp = d->bufcntp;
94325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *bufp = d->bufp;
94425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*bufcntp + 5 - is_16bit > d->bufsize)
94525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return *bufcntp + 5 - is_16bit - d->bufsize;
94625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bufp[(*bufcntp)++] = '%';
94725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
94825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *cp;
94925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
95025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((prefixes & has_rex_b) != 0 && !is_16bit)
95125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
95225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
95325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if ((prefixes & has_rex_w) == 0)
95425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    *cp++ = 'd';
95525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
95625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
95725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
95825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
95925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
96025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
96125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if ((prefixes & has_rex_w) != 0)
96225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    bufp[*bufcntp] = 'r';
96325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
96425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
96525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *bufcntp = cp - bufp;
96625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 0;
96725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
96825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
96925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return general_mod$r_m (d);
97025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
97125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
97225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
97325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef X86_64
97425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
97525b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_moda$r_m (struct output_data *d)
97625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
97725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 == 0);
97825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t modrm = d->data[d->opoff1 / 8];
97925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((modrm & 0xc0) == 0xc0)
98025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
98125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*d->prefixes & has_addr16)
98225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return -1;
98325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
98425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t *bufcntp = d->bufcntp;
98525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*bufcntp + 3 > d->bufsize)
98625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return *bufcntp + 3 - d->bufsize;
98725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
98825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      memcpy (&d->bufp[*bufcntp], "???", 3);
98925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *bufcntp += 3;
99025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
99125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 0;
99225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
99325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
99425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return general_mod$r_m (d);
99525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
99625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
99725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
99825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
99925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
100025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char rex_8bit[8][3] =
100125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
100225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    [0] = "a", [1] = "c", [2] = "d", [3] = "b",
100325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    [4] = "sp", [5] = "bp", [6] = "si", [7] = "di"
100425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  };
100525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
100625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
100725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
100825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
100925b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_mod$r_m$w (struct output_data *d)
101025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
101125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 == 0);
101225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const uint8_t *data = d->data;
101325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t modrm = data[d->opoff1 / 8];
101425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((modrm & 0xc0) == 0xc0)
101525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
101625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int prefixes = *d->prefixes;
101725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
101825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (prefixes & has_addr16)
101925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return -1;
102025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
102125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t *bufcntp = d->bufcntp;
102225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *bufp = d->bufp;
102325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*bufcntp + 5 > d->bufsize)
102425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return *bufcntp + 5 - d->bufsize;
102525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
102625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((data[d->opoff3 / 8] & (1 << (7 - (d->opoff3 & 7)))) == 0)
102725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
102825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  bufp[(*bufcntp)++] = '%';
102925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
103025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
103125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (prefixes & has_rex)
103225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
103325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (prefixes & has_rex_r)
103425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		*bufcntp += snprintf (bufp + *bufcntp, d->bufsize - *bufcntp,
103525b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      "r%db", 8 + (modrm & 7));
103625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
103725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
103825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  char *cp = stpcpy (bufp + *bufcntp, hiregs[modrm & 7]);
103925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  *cp++ = 'l';
104025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  *bufcntp = cp - bufp;
104125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
104225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
104325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
104425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
104525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
104625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      bufp[(*bufcntp)++] = "acdb"[modrm & 3];
104725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
104825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
104925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
105025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
105125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
105225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int is_16bit = (prefixes & has_data16) != 0;
105325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
105425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  bufp[(*bufcntp)++] = '%';
105525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
105625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *cp;
105725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
105825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if ((prefixes & has_rex_b) != 0 && !is_16bit)
105925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
106025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
106125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if ((prefixes & has_rex_w) == 0)
106225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		*cp++ = 'd';
106325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
106425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
106525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
106625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
106725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
106825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
106925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if ((prefixes & has_rex_w) != 0)
107025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		bufp[*bufcntp] = 'r';
107125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
107225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
107325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *bufcntp = cp - bufp;
107425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
107525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 0;
107625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
107725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
107825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return general_mod$r_m (d);
107925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
108025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
108125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
108225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
108325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_mod$8r_m (struct output_data *d)
108425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
108525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 == 0);
108625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t modrm = d->data[d->opoff1 / 8];
108725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((modrm & 0xc0) == 0xc0)
108825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
108925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t *bufcntp = d->bufcntp;
109025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *bufp = d->bufp;
109125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*bufcntp + 3 > d->bufsize)
109225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return *bufcntp + 3 - d->bufsize;
109325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bufp[(*bufcntp)++] = '%';
109425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bufp[(*bufcntp)++] = "acdb"[modrm & 3];
109525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
109625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 0;
109725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
109825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
109925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return general_mod$r_m (d);
110025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
110125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
110225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
110325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
110425b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_mod$16r_m (struct output_data *d)
110525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
110625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 == 0);
110725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t modrm = d->data[d->opoff1 / 8];
110825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((modrm & 0xc0) == 0xc0)
110925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
111025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (d->opoff1 / 8 == d->opoff2 / 8);
111125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      //uint_fast8_t byte = data[opoff2 / 8] & 7;
111225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t byte = modrm & 7;
111325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
111425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t *bufcntp = d->bufcntp;
111525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*bufcntp + 3 > d->bufsize)
111625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return *bufcntp + 3 - d->bufsize;
111725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      d->bufp[(*bufcntp)++] = '%';
111825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      memcpy (&d->bufp[*bufcntp], dregs[byte] + 1, sizeof (dregs[0]) - 1);
111925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *bufcntp += 2;
112025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 0;
112125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
112225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
112325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return general_mod$r_m (d);
112425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
112525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
112625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
112725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
112825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
112925b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_mod$64r_m (struct output_data *d)
113025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
113125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 == 0);
113225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t modrm = d->data[d->opoff1 / 8];
113325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((modrm & 0xc0) == 0xc0)
113425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
113525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (d->opoff1 / 8 == d->opoff2 / 8);
113625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      //uint_fast8_t byte = data[opoff2 / 8] & 7;
113725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint_fast8_t byte = modrm & 7;
113825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
113925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t *bufcntp = d->bufcntp;
114025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*bufcntp + 4 > d->bufsize)
114125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return *bufcntp + 4 - d->bufsize;
114225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *cp = &d->bufp[*bufcntp];
114325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *cp++ = '%';
114425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      cp = stpcpy (cp,
114525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   (*d->prefixes & has_rex_b) ? hiregs[byte] : aregs[byte]);
114625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *bufcntp = cp - d->bufp;
114725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 0;
114825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
114925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
115025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return general_mod$r_m (d);
115125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
115225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
115325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic typeof (FCT_mod$r_m) FCT_mod$64r_m __attribute__ ((alias ("FCT_mod$r_m")));
115425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
115525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
115625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
115725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
115825b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_reg (struct output_data *d)
115925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
116025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t byte = d->data[d->opoff1 / 8];
116125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 + 3 <= 8);
116225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  byte >>= 8 - (d->opoff1 % 8 + 3);
116325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  byte &= 7;
116425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int is_16bit = (*d->prefixes & has_data16) != 0;
116525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
116625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*bufcntp + 5 > d->bufsize)
116725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return *bufcntp + 5 - d->bufsize;
116825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  d->bufp[(*bufcntp)++] = '%';
116925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
117025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((*d->prefixes & has_rex_r) != 0 && !is_16bit)
117125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
117225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
117325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    8 + byte);
117425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((*d->prefixes & has_rex_w) == 0)
117525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	d->bufp[(*bufcntp)++] = 'd';
117625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
117725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
117825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
117925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
118025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      memcpy (&d->bufp[*bufcntp], dregs[byte] + is_16bit, 3 - is_16bit);
118125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
118225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((*d->prefixes & has_rex_w) != 0 && !is_16bit)
118325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	d->bufp[*bufcntp] = 'r';
118425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
118525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *bufcntp += 3 - is_16bit;
118625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
118725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
118825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
118925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
119025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
119125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
119225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
119325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_oreg (struct output_data *d)
119425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
119525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Special form where register comes from opcode.  The rex.B bit is used,
119625b3c049e70834cf33790a28643ab058b507b35cBen Cheng     rex.R and rex.X are ignored.  */
119725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int save_prefixes = *d->prefixes;
119825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
119925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *d->prefixes = ((save_prefixes & ~has_rex_r)
120025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
120125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
120225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int r = FCT_reg (d);
120325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
120425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *d->prefixes = save_prefixes;
120525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
120625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return r;
120725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
120825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
120925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
121025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
121125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
121225b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_reg64 (struct output_data *d)
121325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
121425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t byte = d->data[d->opoff1 / 8];
121525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 + 3 <= 8);
121625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  byte >>= 8 - (d->opoff1 % 8 + 3);
121725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  byte &= 7;
121825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((*d->prefixes & has_data16) != 0)
121925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
122025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
122125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*bufcntp + 5 > d->bufsize)
122225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return *bufcntp + 5 - d->bufsize;
122325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  d->bufp[(*bufcntp)++] = '%';
122425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
122525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((*d->prefixes & has_rex_r) != 0)
122625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
122725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
122825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    8 + byte);
122925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((*d->prefixes & has_rex_w) == 0)
123025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	d->bufp[(*bufcntp)++] = 'd';
123125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
123225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
123325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
123425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
123525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      memcpy (&d->bufp[*bufcntp], aregs[byte], 3);
123625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *bufcntp += 3;
123725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
123825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
123925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
124025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
124125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
124225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
124325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_reg$w (struct output_data *d)
124425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
124525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7))))
124625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return FCT_reg (d);
124725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
124825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t byte = d->data[d->opoff1 / 8];
124925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 + 3 <= 8);
125025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  byte >>= 8 - (d->opoff1 % 8 + 3);
125125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  byte &= 7;
125225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
125325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
125425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*bufcntp + 4 > d->bufsize)
125525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return *bufcntp + 4 - d->bufsize;
125625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
125725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  d->bufp[(*bufcntp)++] = '%';
125825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
125925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
126025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->prefixes & has_rex)
126125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
126225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*d->prefixes & has_rex_r)
126325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*bufcntp += snprintf (d->bufp + *bufcntp, d->bufsize - *bufcntp,
126425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      "r%db", 8 + byte);
126525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
126625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
126725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char* cp = stpcpy (d->bufp + *bufcntp, rex_8bit[byte]);
126825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *cp++ = 'l';
126925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *bufcntp = cp - d->bufp;
127025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
127125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
127225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
127325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
127425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
127525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      d->bufp[(*bufcntp)++] = "acdb"[byte & 3];
127625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      d->bufp[(*bufcntp)++] = "lh"[byte >> 2];
127725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
127825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
127925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
128025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
128125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
128225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64
128325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
128425b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_oreg$w (struct output_data *d)
128525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
128625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Special form where register comes from opcode.  The rex.B bit is used,
128725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     rex.R and rex.X are ignored.  */
128825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int save_prefixes = *d->prefixes;
128925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
129025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *d->prefixes = ((save_prefixes & ~has_rex_r)
129125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
129225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
129325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int r = FCT_reg$w (d);
129425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
129525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *d->prefixes = save_prefixes;
129625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
129725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return r;
129825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
129925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
130025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
130125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
130225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
130325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_freg (struct output_data *d)
130425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
130525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 / 8 == 1);
130625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 == 5);
130725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
130825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
130925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%st(%" PRIx32 ")",
131025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 (uint32_t) (d->data[1] & 7));
131125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
131225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return (size_t) needed - avail;
131325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
131425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
131525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
131625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
131725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
131825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef X86_64
131925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
132025b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_reg16 (struct output_data *d)
132125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
132225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->prefixes & has_data16)
132325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
132425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
132525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *d->prefixes |= has_data16;
132625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return FCT_reg (d);
132725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
132825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
132925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
133025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
133125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
133225b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_sel (struct output_data *d)
133325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
133425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 == 0);
133525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 / 8 == 5);
133625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*d->param_start + 2 > d->end)
133725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
133825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *d->param_start += 2;
133925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint16_t absval = read_2ubyte_unaligned (&d->data[5]);
134025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
134125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
134225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
134325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, absval);
134425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
134525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return needed - avail;
134625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
134725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
134825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
134925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
135025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
135125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
135225b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_sreg2 (struct output_data *d)
135325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
135425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t byte = d->data[d->opoff1 / 8];
135525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 + 3 <= 8);
135625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  byte >>= 8 - (d->opoff1 % 8 + 2);
135725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
135825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
135925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *bufp = d->bufp;
136025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*bufcntp + 3 > d->bufsize)
136125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return *bufcntp + 3 - d->bufsize;
136225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
136325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bufp[(*bufcntp)++] = '%';
136425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bufp[(*bufcntp)++] = "ecsd"[byte & 3];
136525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bufp[(*bufcntp)++] = 's';
136625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
136725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
136825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
136925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
137025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
137125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
137225b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_sreg3 (struct output_data *d)
137325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
137425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t byte = d->data[d->opoff1 / 8];
137525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 + 4 <= 8);
137625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  byte >>= 8 - (d->opoff1 % 8 + 3);
137725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
137825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((byte & 7) >= 6)
137925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
138025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
138125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
138225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *bufp = d->bufp;
138325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*bufcntp + 3 > d->bufsize)
138425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return *bufcntp + 3 - d->bufsize;
138525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
138625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bufp[(*bufcntp)++] = '%';
138725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bufp[(*bufcntp)++] = "ecsdfg"[byte & 7];
138825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bufp[(*bufcntp)++] = 's';
138925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
139025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
139125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
139225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
139325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
139425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
139525b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_string (struct output_data *d __attribute__ ((unused)))
139625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
139725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
139825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
139925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
140025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
140125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
140225b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_xmmreg (struct output_data *d)
140325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
140425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uint_fast8_t byte = d->data[d->opoff1 / 8];
140525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
140625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  byte = (byte >> (5 - d->opoff1 % 8)) & 7;
140725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
140825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t *bufcntp = d->bufcntp;
140925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t avail = d->bufsize - *bufcntp;
141025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, byte);
141125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((size_t) needed > avail)
141225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return needed - avail;
141325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *bufcntp += needed;
141425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
141525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
1416