Imported Upstream version 0.155
[platform/upstream/elfutils.git] / libcpu / i386_data.h
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 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 }