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