1cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Helper routines for disassembler for x86/x86-64.
2cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Copyright (C) 2007, 2008 Red Hat, Inc.
3cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   This file is part of Red Hat elfutils.
4cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Written by Ulrich Drepper <drepper@redhat.com>, 2007.
5cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
6cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat elfutils is free software; you can redistribute it and/or modify
7cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   it under the terms of the GNU General Public License as published by the
8cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Free Software Foundation; version 2 of the License.
9cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
10cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat elfutils is distributed in the hope that it will be useful, but
11cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
12cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   General Public License for more details.
14cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
15cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   You should have received a copy of the GNU General Public License along
16cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   with Red Hat elfutils; if not, write to the Free Software Foundation,
17cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
18cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
19cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat elfutils is an included package of the Open Invention Network.
20cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   An included package of the Open Invention Network is a package for which
21cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Open Invention Network licensees cross-license their patents.  No patent
22cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   license is granted, either expressly or impliedly, by designation as an
23cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   included package.  Should you wish to participate in the Open Invention
24cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Network licensing program, please visit www.openinventionnetwork.com
25cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   <http://www.openinventionnetwork.com>.  */
26cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
27cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <inttypes.h>
28cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stddef.h>
29cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdio.h>
30cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdint.h>
31cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <libasm.h>
32cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
33cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstruct instr_enc
34cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
35cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* The mnemonic.  Especially encoded for the optimized table.  */
36cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int mnemonic : MNEMONIC_BITS;
37cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
38cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* The rep/repe prefixes.  */
39cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int rep : 1;
40cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int repe : 1;
41cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
42cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Mnemonic suffix.  */
43cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int suffix : SUFFIX_BITS;
44cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
45cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Nonzero if the instruction uses modr/m.  */
46cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int modrm : 1;
47cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
48cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* 1st parameter.  */
49cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int fct1 : FCT1_BITS;
50cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef STR1_BITS
51cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int str1 : STR1_BITS;
52cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
53cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int off1_1 : OFF1_1_BITS;
54cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int off1_2 : OFF1_2_BITS;
55cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int off1_3 : OFF1_3_BITS;
56cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
57cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* 2nd parameter.  */
58cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int fct2 : FCT2_BITS;
59cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef STR2_BITS
60cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int str2 : STR2_BITS;
61cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
62cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int off2_1 : OFF2_1_BITS;
63cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int off2_2 : OFF2_2_BITS;
64cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int off2_3 : OFF2_3_BITS;
65cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
66cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* 3rd parameter.  */
67cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int fct3 : FCT3_BITS;
68cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef STR3_BITS
69cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int str3 : STR3_BITS;
70cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
71cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int off3_1 : OFF3_1_BITS;
72cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef OFF3_2_BITS
73cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int off3_2 : OFF3_2_BITS;
74cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
75cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef OFF3_3_BITS
76cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  unsigned int off3_3 : OFF3_3_BITS;
77cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
78cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng};
79cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
80cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
81cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengtypedef int (*opfct_t) (struct output_data *);
82cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
83cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
84cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
85cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdata_prefix (struct output_data *d)
86cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
87cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  char ch = '\0';
88cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->prefixes & has_cs)
89cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
90cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      ch = 'c';
91cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *d->prefixes &= ~has_cs;
92cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
93cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else if (*d->prefixes & has_ds)
94cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
95cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      ch = 'd';
96cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *d->prefixes &= ~has_ds;
97cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
98cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else if (*d->prefixes & has_es)
99cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      ch = 'e';
101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *d->prefixes &= ~has_es;
102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else if (*d->prefixes & has_fs)
104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      ch = 'f';
106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *d->prefixes &= ~has_fs;
107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else if (*d->prefixes & has_gs)
109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      ch = 'g';
111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *d->prefixes &= ~has_gs;
112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else if (*d->prefixes & has_ss)
114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      ch = 's';
116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *d->prefixes &= ~has_ss;
117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return 0;
120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->bufcntp + 4 > d->bufsize)
122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return *d->bufcntp + 4 - d->bufsize;
123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  d->bufp[(*d->bufcntp)++] = '%';
125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  d->bufp[(*d->bufcntp)++] = ch;
126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  d->bufp[(*d->bufcntp)++] = 's';
127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  d->bufp[(*d->bufcntp)++] = ':';
128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char hiregs[8][4] =
134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  {
135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  };
137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char aregs[8][4] =
138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  {
139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"
140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  };
141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char dregs[8][4] =
142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  {
143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  };
145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else
146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char aregs[8][4] =
147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  {
148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  };
150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define dregs aregs
151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenggeneral_mod$r_m (struct output_data *d)
155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int r = data_prefix (d);
157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (r != 0)
158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return r;
159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int prefixes = *d->prefixes;
161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const uint8_t *data = &d->data[d->opoff1 / 8];
162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  char *bufp = d->bufp;
163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t bufsize = d->bufsize;
165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t modrm = data[0];
167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifndef X86_64
168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely ((prefixes & has_addr16) != 0))
169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int16_t disp = 0;
171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      bool nodisp = false;
172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80)
174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	/* 16 bit displacement.  */
175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	disp = read_2sbyte_unaligned (&data[1]);
176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else if ((modrm & 0xc0) == 0x40)
177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	/* 8 bit displacement.  */
178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	disp = *(const int8_t *) &data[1];
179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else if ((modrm & 0xc0) == 0)
180cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	nodisp = true;
181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
182cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char tmpbuf[sizeof ("-0x1234(%rr,%rr)")];
183cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int n;
184cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if ((modrm & 0xc7) == 6)
185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx16, disp);
186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
187cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
188cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  n = 0;
189cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (!nodisp)
190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx16,
191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if ((modrm & 0x4) == 0)
194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%b%c,%%%ci)",
195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   "xp"[(modrm >> 1) & 1], "sd"[modrm & 1]);
196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%%s)",
198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   ((const char [4][3]) { "si", "di", "bp", "bx" })[modrm & 3]);
199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*bufcntp + n + 1 > bufsize)
202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return *bufcntp + n + 1 - bufsize;
203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *bufcntp += n;
206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if ((modrm & 7) != 4)
211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  int32_t disp = 0;
213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  bool nodisp = false;
214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80)
216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* 32 bit displacement.  */
217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    disp = read_4sbyte_unaligned (&data[1]);
218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else if ((modrm & 0xc0) == 0x40)
219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* 8 bit displacement.  */
220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    disp = *(const int8_t *) &data[1];
221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else if ((modrm & 0xc0) == 0)
222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    nodisp = true;
223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  char tmpbuf[sizeof ("-0x12345678(%rrrr)")];
225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  int n;
226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (nodisp)
227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)",
229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    (prefixes & has_rex_b) ? hiregs[modrm & 7] :
231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    aregs[modrm & 7]);
233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (prefixes & has_addr16)
235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (prefixes & has_rex_b)
237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    tmpbuf[n++] = 'd';
238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  else
239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    tmpbuf[2] = 'e';
240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else if ((modrm & 0xc7) != 5)
244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      int p;
246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%n%s)",
247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    disp < 0 ? "-" : "", disp < 0 ? -disp : disp, &p,
248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    (prefixes & has_rex_b) ? hiregs[modrm & 7] :
250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    aregs[modrm & 7]);
252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (prefixes & has_addr16)
254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (prefixes & has_rex_b)
256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    tmpbuf[n++] = 'd';
257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  else
258cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    tmpbuf[p] = 'e';
259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%rip)",
266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      d->symaddr_use = addr_rel_always;
269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      d->symaddr = disp;
270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else
271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp);
272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (*bufcntp + n + 1 > bufsize)
276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    return *bufcntp + n + 1 - bufsize;
277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  *bufcntp += n;
280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* SIB */
284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  uint_fast8_t sib = data[1];
285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  int32_t disp = 0;
286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  bool nodisp = false;
287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80
289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      || ((modrm & 0xc7) == 0x4 && (sib & 0x7) == 0x5))
290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* 32 bit displacement.  */
291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    disp = read_4sbyte_unaligned (&data[2]);
292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else if ((modrm & 0xc0) == 0x40)
293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* 8 bit displacement.  */
294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    disp = *(const int8_t *) &data[2];
295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    nodisp = true;
297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  char tmpbuf[sizeof ("-0x12345678(%rrrr,%rrrr,N)")];
299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  char *cp = tmpbuf;
300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  int n;
301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25
302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      || (prefixes & has_rex_x) != 0
304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      )
306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (!nodisp)
308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  n = snprintf (cp, sizeof (tmpbuf), "%s0x%" PRIx32,
310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  cp += n;
312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      *cp++ = '(';
315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if ((modrm & 0xc7) != 0x4 || (sib & 0x7) != 0x5)
317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  *cp++ = '%';
319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  cp = stpcpy (cp,
320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			       (prefixes & has_rex_b) ? hiregs[sib & 7] :
322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			       (prefixes & has_addr16) ? dregs[sib & 7] :
323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
324cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			       aregs[sib & 7]);
325cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
326cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if ((prefixes & (has_rex_b | has_addr16))
327cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      == (has_rex_b | has_addr16))
328cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    *cp++ = 'd';
329cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if ((sib & 0x38) != 0x20
333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  || (prefixes & has_rex_x) != 0
335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  )
337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  *cp++ = ',';
339cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  *cp++ = '%';
340cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  cp = stpcpy (cp,
341cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			       (prefixes & has_rex_x)
343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			       ? hiregs[(sib >> 3) & 7] :
344cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			       (prefixes & has_addr16)
345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			       ? dregs[(sib >> 3) & 7] :
346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			       aregs[(sib >> 3) & 7]);
348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if ((prefixes & (has_rex_b | has_addr16))
350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      == (has_rex_b | has_addr16))
351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    *cp++ = 'd';
352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  *cp++ = ',';
355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  *cp++ = '0' + (1 << (sib >> 6));
356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      *cp++ = ')';
359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      assert (! nodisp);
363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if ((prefixes & has_addr16) == 0)
365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx64,
366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      (int64_t) disp);
367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      else
368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx32, disp);
370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      cp += n;
371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (*bufcntp + (cp - tmpbuf) > bufsize)
374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    return *bufcntp + (cp - tmpbuf) - bufsize;
375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  memcpy (&bufp[*bufcntp], tmpbuf, cp - tmpbuf);
377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  *bufcntp += cp - tmpbuf;
378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_MOD$R_M (struct output_data *d)
386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
387cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 == 0);
388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t modrm = d->data[d->opoff1 / 8];
389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((modrm & 0xc0) == 0xc0)
390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      assert (d->opoff1 / 8 == d->opoff2 / 8);
392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      assert (d->opoff2 % 8 == 5);
393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      //uint_fast8_t byte = d->data[d->opoff2 / 8] & 7;
394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      uint_fast8_t byte = modrm & 7;
395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t *bufcntp = d->bufcntp;
397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char *buf = d->bufp + *bufcntp;
398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t avail = d->bufsize - *bufcntp;
399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int needed;
400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*d->prefixes & (has_rep | has_repne))
401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	needed = snprintf (buf, avail, "%%%s", dregs[byte]);
402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	needed = snprintf (buf, avail, "%%mm%" PRIxFAST8, byte);
404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if ((size_t) needed > avail)
405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return needed - avail;
406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *bufcntp += needed;
407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return 0;
408cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return general_mod$r_m (d);
411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_Mod$R_m (struct output_data *d)
416cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
417cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 == 0);
418cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t modrm = d->data[d->opoff1 / 8];
419cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((modrm & 0xc0) == 0xc0)
420cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
421cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      assert (d->opoff1 / 8 == d->opoff2 / 8);
422cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      assert (d->opoff2 % 8 == 5);
423cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      //uint_fast8_t byte = data[opoff2 / 8] & 7;
424cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      uint_fast8_t byte = modrm & 7;
425cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
426cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t *bufcntp = d->bufcntp;
427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t avail = d->bufsize - *bufcntp;
428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8,
429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     byte);
430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if ((size_t) needed > avail)
431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return needed - avail;
432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *d->bufcntp += needed;
433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return 0;
434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return general_mod$r_m (d);
437cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
438cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
439cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
440cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenggeneric_abs (struct output_data *d, const char *absstring
441cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
442cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     , int abslen
443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else
444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define abslen 4
445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     )
447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int r = data_prefix (d);
449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (r != 0)
450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return r;
451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
452cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 == 0);
453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 / 8 == 1);
454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->param_start + abslen > d->end)
455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *d->param_start += abslen;
457cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifndef X86_64
458cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint32_t absval;
459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define ABSPRIFMT PRIx32
460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else
461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint64_t absval;
462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define ABSPRIFMT PRIx64
463cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (abslen == 8)
464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    absval = read_8ubyte_unaligned (&d->data[1]);
465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    absval = read_4ubyte_unaligned (&d->data[1]);
468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "%s0x%" ABSPRIFMT,
471cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 absstring, absval);
472cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
473cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return needed - avail;
474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
478cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
479cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
480cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_absval (struct output_data *d)
481cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
482cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return generic_abs (d, "$"
483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      , 4
485cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
486cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      );
487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
488cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
489cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
490cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_abs (struct output_data *d)
491cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
492cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return generic_abs (d, ""
493cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
494cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      , 8
495cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
496cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      );
497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
498cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
499cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
500cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_ax (struct output_data *d)
501cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
502cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int is_16bit = (*d->prefixes & has_data16) != 0;
503cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
504cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
505cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  char *bufp = d->bufp;
506cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t bufsize = d->bufsize;
507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
508cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*bufcntp + 4 - is_16bit > bufsize)
509cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return *bufcntp + 4 - is_16bit - bufsize;
510cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
511cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bufp[(*bufcntp)++] = '%';
512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (! is_16bit)
513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    bufp[(*bufcntp)++] = (
514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
515cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  (*d->prefixes & has_rex_w) ? 'r' :
516cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
517cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  'e');
518cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bufp[(*bufcntp)++] = 'a';
519cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bufp[(*bufcntp)++] = 'x';
520cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
521cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
522cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
523cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
524cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
525cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_ax$w (struct output_data *d)
527cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
528cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
529cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return FCT_ax (d);
530cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
532cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  char *bufp = d->bufp;
533cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t bufsize = d->bufsize;
534cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
535cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*bufcntp + 3 > bufsize)
536cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return *bufcntp + 3 - bufsize;
537cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
538cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bufp[(*bufcntp)++] = '%';
539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bufp[(*bufcntp)++] = 'a';
540cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bufp[(*bufcntp)++] = 'l';
541cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
543cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
544cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
545cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
546cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
547cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng__attribute__ ((noinline))
548cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_crdb (struct output_data *d, const char *regstr)
549cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
550cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->prefixes & has_data16)
551cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
552cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
553cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
554cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  // XXX If this assert is true, use absolute offset below
556cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 / 8 == 2);
557cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 == 2);
558cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
559cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%%s%" PRIx32,
560cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 regstr, (uint32_t) (d->data[d->opoff1 / 8] >> 3) & 7);
561cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
562cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return needed - avail;
563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
564cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
565cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
566cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
567cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
568cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
569cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_ccc (struct output_data *d)
570cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
571cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return FCT_crdb (d, "cr");
572cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
573cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
574cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
575cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
576cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_ddd (struct output_data *d)
577cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
578cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return FCT_crdb (d, "db");
579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
580cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
581cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
582cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
583cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_disp8 (struct output_data *d)
584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 == 0);
586cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->param_start >= d->end)
587cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
588cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int32_t offset = *(const int8_t *) (*d->param_start)++;
589cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
590cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
591cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 (uint32_t) (d->addr + (*d->param_start - d->data)
594cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				     + offset));
595cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
596cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return needed - avail;
597cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
602cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
603cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng__attribute__ ((noinline))
604cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_ds_xx (struct output_data *d, const char *reg)
605cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
606cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int prefix = *d->prefixes & SEGMENT_PREFIXES;
607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
608cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (prefix == 0)
609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    *d->prefixes |= prefix = has_ds;
610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Make sure only one bit is set.  */
611cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else if ((prefix - 1) & prefix)
612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
613cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
614cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int r = data_prefix (d);
615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
616cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert ((*d->prefixes & prefix) == 0);
617cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
618cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (r != 0)
619cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return r;
620cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
621cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
622cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
623cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "(%%%s%s)",
624cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
625cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 *d->prefixes & idx_addr16 ? "e" : "r",
626cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else
627cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 *d->prefixes & idx_addr16 ? "" : "e",
628cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
629cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 reg);
630cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
631cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return (size_t) needed - avail;
632cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
633cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
634cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
635cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
636cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
637cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
638cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
639cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_ds_bx (struct output_data *d)
640cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
641cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return FCT_ds_xx (d, "bx");
642cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
643cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
644cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
645cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
646cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_ds_si (struct output_data *d)
647cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
648cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return FCT_ds_xx (d, "si");
649cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
650cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
651cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
652cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
653cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_dx (struct output_data *d)
654cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
655cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
656cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
657cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*bufcntp + 7 > d->bufsize)
658cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return *bufcntp + 7 - d->bufsize;
659cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
660cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  memcpy (&d->bufp[*bufcntp], "(%dx)", 5);
661cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += 5;
662cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
663cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
664cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
665cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
666cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
667cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
668cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_es_di (struct output_data *d)
669cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
670cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
671cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
672cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%es:(%%%sdi)",
673cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
674cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 *d->prefixes & idx_addr16 ? "e" : "r"
675cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else
676cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 *d->prefixes & idx_addr16 ? "" : "e"
677cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
678cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 );
679cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
680cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return (size_t) needed - avail;
681cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
682cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
683cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
684cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
685cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
686cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
687cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
688cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imm (struct output_data *d)
689cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
690cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
691cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
692cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed;
693cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->prefixes & has_data16)
694cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
695cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*d->param_start + 2 > d->end)
696cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return -1;
697cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
698cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
699cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
700cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
701cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
702cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*d->param_start + 4 > d->end)
703cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return -1;
704cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
705cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
706cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*d->prefixes & has_rex_w)
707cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
708cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   (int64_t) word);
709cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
710cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
711cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
712cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
713cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
714cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return (size_t) needed - avail;
715cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
716cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
717cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
718cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
719cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
720cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
721cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imm$w (struct output_data *d)
722cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
723cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
724cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return FCT_imm (d);
725cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
726cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
727cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
728cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->param_start>= d->end)
729cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
730cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t word = *(*d->param_start)++;
731cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIxFAST8, word);
732cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
733cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return (size_t) needed - avail;
734cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
735cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
736cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
737cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
738cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
739cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
740cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
741cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imm64$w (struct output_data *d)
742cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
743cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) == 0
744cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      || (*d->prefixes & has_data16) != 0)
745cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return FCT_imm$w (d);
746cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
747cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
748cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
749cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed;
750cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->prefixes & has_rex_w)
751cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
752cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*d->param_start + 8 > d->end)
753cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return -1;
754cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      uint64_t word = read_8ubyte_unaligned_inc (*d->param_start);
755cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, word);
756cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
757cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
758cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
759cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*d->param_start + 4 > d->end)
760cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return -1;
761cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
762cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
763cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
764cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
765cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return (size_t) needed - avail;
766cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
767cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
768cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
769cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
770cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
771cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
772cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
773cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imms (struct output_data *d)
774cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
775cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
776cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
777cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->param_start>= d->end)
778cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
779cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int8_t byte = *(*d->param_start)++;
780cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
781cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
782cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 (int64_t) byte);
783cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else
784cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
785cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 (int32_t) byte);
786cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
787cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
788cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return (size_t) needed - avail;
789cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
790cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
791cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
792cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
793cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
794cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
795cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imm$s (struct output_data *d)
796cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
797cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t opcode = d->data[d->opoff2 / 8];
798cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
799cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
800cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((opcode & 2) != 0)
801cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return FCT_imms (d);
802cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
803cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((*d->prefixes & has_data16) == 0)
804cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
805cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*d->param_start + 4 > d->end)
806cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return -1;
807cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
808cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
809cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
810cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     (int64_t) word);
811cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else
812cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
813cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
814cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if ((size_t) needed > avail)
815cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return (size_t) needed - avail;
816cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *bufcntp += needed;
817cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
818cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
819cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
820cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*d->param_start + 2 > d->end)
821cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return -1;
822cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
823cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
824cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if ((size_t) needed > avail)
825cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return (size_t) needed - avail;
826cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *bufcntp += needed;
827cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
828cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
829cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
830cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
831cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
832cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
833cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imm16 (struct output_data *d)
834cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
835cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->param_start + 2 > d->end)
836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
837cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
838cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
839cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
840cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
841cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
842cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return (size_t) needed - avail;
843cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
844cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
845cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
846cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
847cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
848cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
849cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imms8 (struct output_data *d)
850cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
851cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
852cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
853cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->param_start >= d->end)
854cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
855cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int_fast8_t byte = *(*d->param_start)++;
856cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed;
857cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
858cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->prefixes & has_rex_w)
859cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
860cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		       (int64_t) byte);
861cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
862cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
863cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
864cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		       (int32_t) byte);
865cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
866cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return (size_t) needed - avail;
867cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
868cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
869cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
870cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
871cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
872cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
873cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imm8 (struct output_data *d)
874cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
875cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
876cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
877cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->param_start >= d->end)
878cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
879cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t byte = *(*d->param_start)++;
880cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
881cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 (uint32_t) byte);
882cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
883cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return (size_t) needed - avail;
884cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
885cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
886cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
887cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
888cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
889cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
890cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_rel (struct output_data *d)
891cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
892cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
893cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
894cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->param_start + 4 > d->end)
895cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
896cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int32_t rel = read_4sbyte_unaligned_inc (*d->param_start);
897cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
898cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx64,
899cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 (uint64_t) (d->addr + rel
900cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				     + (*d->param_start - d->data)));
901cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else
902cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
903cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 (uint32_t) (d->addr + rel
904cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				     + (*d->param_start - d->data)));
905cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
906cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
907cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return (size_t) needed - avail;
908cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
909cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
910cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
911cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
912cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
913cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
914cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_mmxreg (struct output_data *d)
915cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
916cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t byte = d->data[d->opoff1 / 8];
917cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
918cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  byte = (byte >> (5 - d->opoff1 % 8)) & 7;
919cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp =  d->bufcntp;
920cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
921cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte);
922cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
923cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return needed - avail;
924cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
925cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
926cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
927cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
928cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
929cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
930cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_mod$r_m (struct output_data *d)
931cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
932cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 == 0);
933cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t modrm = d->data[d->opoff1 / 8];
934cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((modrm & 0xc0) == 0xc0)
935cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
936cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int prefixes = *d->prefixes;
937cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (prefixes & has_addr16)
938cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return -1;
939cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
940cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int is_16bit = (prefixes & has_data16) != 0;
941cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
942cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t *bufcntp = d->bufcntp;
943cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char *bufp = d->bufp;
944cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*bufcntp + 5 - is_16bit > d->bufsize)
945cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return *bufcntp + 5 - is_16bit - d->bufsize;
946cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      bufp[(*bufcntp)++] = '%';
947cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
948cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char *cp;
949cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
950cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if ((prefixes & has_rex_b) != 0 && !is_16bit)
951cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
952cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
953cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if ((prefixes & has_rex_w) == 0)
954cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    *cp++ = 'd';
955cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
956cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
957cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
958cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
959cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
960cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
961cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if ((prefixes & has_rex_w) != 0)
962cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    bufp[*bufcntp] = 'r';
963cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
964cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
965cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *bufcntp = cp - bufp;
966cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return 0;
967cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
968cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
969cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return general_mod$r_m (d);
970cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
971cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
972cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
973cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifndef X86_64
974cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
975cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_moda$r_m (struct output_data *d)
976cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
977cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 == 0);
978cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t modrm = d->data[d->opoff1 / 8];
979cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((modrm & 0xc0) == 0xc0)
980cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
981cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*d->prefixes & has_addr16)
982cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return -1;
983cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
984cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t *bufcntp = d->bufcntp;
985cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*bufcntp + 3 > d->bufsize)
986cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return *bufcntp + 3 - d->bufsize;
987cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
988cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      memcpy (&d->bufp[*bufcntp], "???", 3);
989cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *bufcntp += 3;
990cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
991cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return 0;
992cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
993cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
994cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return general_mod$r_m (d);
995cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
996cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
997cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
998cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
999cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
1000cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char rex_8bit[8][3] =
1001cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  {
1002cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    [0] = "a", [1] = "c", [2] = "d", [3] = "b",
1003cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    [4] = "sp", [5] = "bp", [6] = "si", [7] = "di"
1004cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  };
1005cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
1006cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1007cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1008cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1009cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_mod$r_m$w (struct output_data *d)
1010cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1011cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 == 0);
1012cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const uint8_t *data = d->data;
1013cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t modrm = data[d->opoff1 / 8];
1014cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((modrm & 0xc0) == 0xc0)
1015cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1016cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      int prefixes = *d->prefixes;
1017cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1018cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (prefixes & has_addr16)
1019cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return -1;
1020cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1021cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t *bufcntp = d->bufcntp;
1022cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char *bufp = d->bufp;
1023cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*bufcntp + 5 > d->bufsize)
1024cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return *bufcntp + 5 - d->bufsize;
1025cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1026cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if ((data[d->opoff3 / 8] & (1 << (7 - (d->opoff3 & 7)))) == 0)
1027cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
1028cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  bufp[(*bufcntp)++] = '%';
1029cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1030cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
1031cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (prefixes & has_rex)
1032cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1033cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (prefixes & has_rex_r)
1034cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		*bufcntp += snprintf (bufp + *bufcntp, d->bufsize - *bufcntp,
1035cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				      "r%db", 8 + (modrm & 7));
1036cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      else
1037cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
1038cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  char *cp = stpcpy (bufp + *bufcntp, hiregs[modrm & 7]);
1039cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  *cp++ = 'l';
1040cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  *bufcntp = cp - bufp;
1041cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
1042cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1043cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
1044cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
1045cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1046cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      bufp[(*bufcntp)++] = "acdb"[modrm & 3];
1047cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
1048cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1049cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
1050cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
1051cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
1052cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  int is_16bit = (prefixes & has_data16) != 0;
1053cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1054cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  bufp[(*bufcntp)++] = '%';
1055cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1056cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  char *cp;
1057cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
1058cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if ((prefixes & has_rex_b) != 0 && !is_16bit)
1059cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1060cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
1061cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if ((prefixes & has_rex_w) == 0)
1062cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		*cp++ = 'd';
1063cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1064cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
1065cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
1066cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1067cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
1068cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
1069cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if ((prefixes & has_rex_w) != 0)
1070cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		bufp[*bufcntp] = 'r';
1071cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
1072cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1073cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  *bufcntp = cp - bufp;
1074cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
1075cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return 0;
1076cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1077cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1078cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return general_mod$r_m (d);
1079cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1080cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1081cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1082cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1083cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_mod$8r_m (struct output_data *d)
1084cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1085cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 == 0);
1086cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t modrm = d->data[d->opoff1 / 8];
1087cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((modrm & 0xc0) == 0xc0)
1088cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1089cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t *bufcntp = d->bufcntp;
1090cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char *bufp = d->bufp;
1091cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*bufcntp + 3 > d->bufsize)
1092cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return *bufcntp + 3 - d->bufsize;
1093cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      bufp[(*bufcntp)++] = '%';
1094cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      bufp[(*bufcntp)++] = "acdb"[modrm & 3];
1095cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
1096cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return 0;
1097cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1098cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1099cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return general_mod$r_m (d);
1100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_mod$16r_m (struct output_data *d)
1105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 == 0);
1107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t modrm = d->data[d->opoff1 / 8];
1108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((modrm & 0xc0) == 0xc0)
1109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      assert (d->opoff1 / 8 == d->opoff2 / 8);
1111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      //uint_fast8_t byte = data[opoff2 / 8] & 7;
1112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      uint_fast8_t byte = modrm & 7;
1113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t *bufcntp = d->bufcntp;
1115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*bufcntp + 3 > d->bufsize)
1116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return *bufcntp + 3 - d->bufsize;
1117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      d->bufp[(*bufcntp)++] = '%';
1118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      memcpy (&d->bufp[*bufcntp], dregs[byte] + 1, sizeof (dregs[0]) - 1);
1119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *bufcntp += 2;
1120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return 0;
1121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return general_mod$r_m (d);
1124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
1128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_mod$64r_m (struct output_data *d)
1130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 == 0);
1132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t modrm = d->data[d->opoff1 / 8];
1133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((modrm & 0xc0) == 0xc0)
1134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      assert (d->opoff1 / 8 == d->opoff2 / 8);
1136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      //uint_fast8_t byte = data[opoff2 / 8] & 7;
1137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      uint_fast8_t byte = modrm & 7;
1138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t *bufcntp = d->bufcntp;
1140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*bufcntp + 4 > d->bufsize)
1141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return *bufcntp + 4 - d->bufsize;
1142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char *cp = &d->bufp[*bufcntp];
1143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *cp++ = '%';
1144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      cp = stpcpy (cp,
1145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   (*d->prefixes & has_rex_b) ? hiregs[byte] : aregs[byte]);
1146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *bufcntp = cp - d->bufp;
1147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return 0;
1148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return general_mod$r_m (d);
1151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else
1153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic typeof (FCT_mod$r_m) FCT_mod$64r_m __attribute__ ((alias ("FCT_mod$r_m")));
1154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
1155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_reg (struct output_data *d)
1159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t byte = d->data[d->opoff1 / 8];
1161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 + 3 <= 8);
1162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  byte >>= 8 - (d->opoff1 % 8 + 3);
1163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  byte &= 7;
1164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int is_16bit = (*d->prefixes & has_data16) != 0;
1165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
1166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*bufcntp + 5 > d->bufsize)
1167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return *bufcntp + 5 - d->bufsize;
1168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  d->bufp[(*bufcntp)++] = '%';
1169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
1170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((*d->prefixes & has_rex_r) != 0 && !is_16bit)
1171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
1173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    8 + byte);
1174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if ((*d->prefixes & has_rex_w) == 0)
1175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	d->bufp[(*bufcntp)++] = 'd';
1176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
1178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
1179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1180cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      memcpy (&d->bufp[*bufcntp], dregs[byte] + is_16bit, 3 - is_16bit);
1181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
1182cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if ((*d->prefixes & has_rex_w) != 0 && !is_16bit)
1183cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	d->bufp[*bufcntp] = 'r';
1184cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
1185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *bufcntp += 3 - is_16bit;
1186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1187cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
1188cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1189cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
1192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_oreg (struct output_data *d)
1194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Special form where register comes from opcode.  The rex.B bit is used,
1196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     rex.R and rex.X are ignored.  */
1197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int save_prefixes = *d->prefixes;
1198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *d->prefixes = ((save_prefixes & ~has_rex_r)
1200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
1201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int r = FCT_reg (d);
1203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *d->prefixes = save_prefixes;
1205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return r;
1207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
1209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_reg64 (struct output_data *d)
1213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t byte = d->data[d->opoff1 / 8];
1215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 + 3 <= 8);
1216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  byte >>= 8 - (d->opoff1 % 8 + 3);
1217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  byte &= 7;
1218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((*d->prefixes & has_data16) != 0)
1219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
1220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
1221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*bufcntp + 5 > d->bufsize)
1222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return *bufcntp + 5 - d->bufsize;
1223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  d->bufp[(*bufcntp)++] = '%';
1224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
1225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((*d->prefixes & has_rex_r) != 0)
1226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
1228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    8 + byte);
1229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if ((*d->prefixes & has_rex_w) == 0)
1230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	d->bufp[(*bufcntp)++] = 'd';
1231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
1233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
1234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      memcpy (&d->bufp[*bufcntp], aregs[byte], 3);
1236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *bufcntp += 3;
1237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
1239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_reg$w (struct output_data *d)
1244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7))))
1246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return FCT_reg (d);
1247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t byte = d->data[d->opoff1 / 8];
1249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 + 3 <= 8);
1250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  byte >>= 8 - (d->opoff1 % 8 + 3);
1251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  byte &= 7;
1252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
1254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*bufcntp + 4 > d->bufsize)
1255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return *bufcntp + 4 - d->bufsize;
1256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  d->bufp[(*bufcntp)++] = '%';
1258cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
1260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->prefixes & has_rex)
1261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*d->prefixes & has_rex_r)
1263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	*bufcntp += snprintf (d->bufp + *bufcntp, d->bufsize - *bufcntp,
1264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      "r%db", 8 + byte);
1265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
1266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
1267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  char* cp = stpcpy (d->bufp + *bufcntp, rex_8bit[byte]);
1268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  *cp++ = 'l';
1269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  *bufcntp = cp - d->bufp;
1270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
1271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
1273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
1274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      d->bufp[(*bufcntp)++] = "acdb"[byte & 3];
1276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      d->bufp[(*bufcntp)++] = "lh"[byte >> 2];
1277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
1279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64
1283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_oreg$w (struct output_data *d)
1285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Special form where register comes from opcode.  The rex.B bit is used,
1287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     rex.R and rex.X are ignored.  */
1288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int save_prefixes = *d->prefixes;
1289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *d->prefixes = ((save_prefixes & ~has_rex_r)
1291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
1292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int r = FCT_reg$w (d);
1294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *d->prefixes = save_prefixes;
1296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return r;
1298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
1300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_freg (struct output_data *d)
1304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 / 8 == 1);
1306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 == 5);
1307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
1308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
1309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%st(%" PRIx32 ")",
1310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 (uint32_t) (d->data[1] & 7));
1311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
1312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return (size_t) needed - avail;
1313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
1314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
1315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifndef X86_64
1319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_reg16 (struct output_data *d)
1321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->prefixes & has_data16)
1323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
1324cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1325cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *d->prefixes |= has_data16;
1326cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return FCT_reg (d);
1327cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1328cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
1329cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_sel (struct output_data *d)
1333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 == 0);
1335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 / 8 == 5);
1336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*d->param_start + 2 > d->end)
1337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
1338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *d->param_start += 2;
1339cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint16_t absval = read_2ubyte_unaligned (&d->data[5]);
1340cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1341cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
1342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
1343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, absval);
1344cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
1345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return needed - avail;
1346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
1347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
1348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_sreg2 (struct output_data *d)
1353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t byte = d->data[d->opoff1 / 8];
1355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 + 3 <= 8);
1356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  byte >>= 8 - (d->opoff1 % 8 + 2);
1357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
1359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  char *bufp = d->bufp;
1360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*bufcntp + 3 > d->bufsize)
1361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return *bufcntp + 3 - d->bufsize;
1362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bufp[(*bufcntp)++] = '%';
1364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bufp[(*bufcntp)++] = "ecsd"[byte & 3];
1365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bufp[(*bufcntp)++] = 's';
1366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
1368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_sreg3 (struct output_data *d)
1373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t byte = d->data[d->opoff1 / 8];
1375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 + 4 <= 8);
1376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  byte >>= 8 - (d->opoff1 % 8 + 3);
1377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((byte & 7) >= 6)
1379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
1380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
1382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  char *bufp = d->bufp;
1383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*bufcntp + 3 > d->bufsize)
1384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return *bufcntp + 3 - d->bufsize;
1385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bufp[(*bufcntp)++] = '%';
1387cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bufp[(*bufcntp)++] = "ecsdfg"[byte & 7];
1388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bufp[(*bufcntp)++] = 's';
1389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
1391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_string (struct output_data *d __attribute__ ((unused)))
1396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
1398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_xmmreg (struct output_data *d)
1403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uint_fast8_t byte = d->data[d->opoff1 / 8];
1405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
1406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  byte = (byte >> (5 - d->opoff1 % 8)) & 7;
1407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1408cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t *bufcntp = d->bufcntp;
1409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t avail = d->bufsize - *bufcntp;
1410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, byte);
1411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((size_t) needed > avail)
1412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return needed - avail;
1413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *bufcntp += needed;
1414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
1415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1416