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