LCOV - code coverage report
Current view: top level - libcpu - i386_data.h (source / functions) Hit Total Coverage
Test: elfutils-0.175 Lines: 595 664 89.6 %
Date: 2018-11-16 13:02:39 Functions: 46 46 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13