• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
data_prefix(struct output_data * d)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
general_mod$r_m(struct output_data * d)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
FCT_MOD$R_M(struct output_data * d)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
FCT_Mod$R_m(struct output_data * d)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
generic_abs(struct output_data * d,const char * absstring,int abslen)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
FCT_absval(struct output_data * d)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
FCT_abs(struct output_data * d)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
FCT_ax(struct output_data * d)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
FCT_ax$w(struct output_data * d)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))
FCT_crdb(struct output_data * d,const char * regstr)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
FCT_ccc(struct output_data * d)572 FCT_ccc (struct output_data *d)
573 {
574   return FCT_crdb (d, "cr");
575 }
576 
577 
578 static int
FCT_ddd(struct output_data * d)579 FCT_ddd (struct output_data *d)
580 {
581   return FCT_crdb (d, "db");
582 }
583 
584 
585 static int
FCT_disp8(struct output_data * d)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))
FCT_ds_xx(struct output_data * d,const char * reg)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
FCT_ds_bx(struct output_data * d)642 FCT_ds_bx (struct output_data *d)
643 {
644   return FCT_ds_xx (d, "bx");
645 }
646 
647 
648 static int
FCT_ds_si(struct output_data * d)649 FCT_ds_si (struct output_data *d)
650 {
651   return FCT_ds_xx (d, "si");
652 }
653 
654 
655 static int
FCT_dx(struct output_data * d)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
FCT_es_di(struct output_data * d)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
FCT_imm(struct output_data * d)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
FCT_imm$w(struct output_data * d)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
FCT_imm64$w(struct output_data * d)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
FCT_imms(struct output_data * d)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
FCT_imm$s(struct output_data * d)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
FCT_imm16(struct output_data * d)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
FCT_imms8(struct output_data * d)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
FCT_imm8(struct output_data * d)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
FCT_rel(struct output_data * d)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
FCT_mmxreg(struct output_data * d)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
FCT_mod$r_m(struct output_data * d)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
FCT_moda$r_m(struct output_data * d)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
FCT_mod$r_m$w(struct output_data * d)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
FCT_mod$8r_m(struct output_data * d)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
FCT_mod$16r_m(struct output_data * d)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
FCT_mod$64r_m(struct output_data * d)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
FCT_reg(struct output_data * d)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
FCT_oreg(struct output_data * d)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
FCT_reg64(struct output_data * d)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
FCT_reg$w(struct output_data * d)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
FCT_oreg$w(struct output_data * d)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
FCT_freg(struct output_data * d)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
FCT_reg16(struct output_data * d)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
FCT_sel(struct output_data * d)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
FCT_sreg2(struct output_data * d)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
FCT_sreg3(struct output_data * d)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
FCT_string(struct output_data * d)1398 FCT_string (struct output_data *d __attribute__ ((unused)))
1399 {
1400   return 0;
1401 }
1402 
1403 
1404 static int
FCT_xmmreg(struct output_data * d)1405 FCT_xmmreg (struct output_data *d)
1406 {
1407   uint_fast8_t byte = d->data[d->opoff1 / 8];
1408   assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
1409   byte = (byte >> (5 - d->opoff1 % 8)) & 7;
1410 
1411   size_t *bufcntp = d->bufcntp;
1412   size_t avail = d->bufsize - *bufcntp;
1413   int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, byte);
1414   if ((size_t) needed > avail)
1415     return needed - avail;
1416   *bufcntp += needed;
1417   return 0;
1418 }
1419