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