• 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 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
data_prefix(struct output_data * d)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
general_mod$r_m(struct output_data * d)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
FCT_MOD$R_M(struct output_data * d)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
FCT_Mod$R_m(struct output_data * d)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
generic_abs(struct output_data * d,const char * absstring,int abslen)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
FCT_absval(struct output_data * d)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
FCT_abs(struct output_data * d)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
FCT_ax(struct output_data * d)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
FCT_ax$w(struct output_data * d)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))
FCT_crdb(struct output_data * d,const char * regstr)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
FCT_ccc(struct output_data * d)569 FCT_ccc (struct output_data *d)
570 {
571   return FCT_crdb (d, "cr");
572 }
573 
574 
575 static int
FCT_ddd(struct output_data * d)576 FCT_ddd (struct output_data *d)
577 {
578   return FCT_crdb (d, "db");
579 }
580 
581 
582 static int
FCT_disp8(struct output_data * d)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))
FCT_ds_xx(struct output_data * d,const char * reg)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
FCT_ds_bx(struct output_data * d)639 FCT_ds_bx (struct output_data *d)
640 {
641   return FCT_ds_xx (d, "bx");
642 }
643 
644 
645 static int
FCT_ds_si(struct output_data * d)646 FCT_ds_si (struct output_data *d)
647 {
648   return FCT_ds_xx (d, "si");
649 }
650 
651 
652 static int
FCT_dx(struct output_data * d)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
FCT_es_di(struct output_data * d)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
FCT_imm(struct output_data * d)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
FCT_imm$w(struct output_data * d)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
FCT_imm64$w(struct output_data * d)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
FCT_imms(struct output_data * d)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
FCT_imm$s(struct output_data * d)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
FCT_imm16(struct output_data * d)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
FCT_imms8(struct output_data * d)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
FCT_imm8(struct output_data * d)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
FCT_rel(struct output_data * d)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
FCT_mmxreg(struct output_data * d)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
FCT_mod$r_m(struct output_data * d)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
FCT_moda$r_m(struct output_data * d)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
FCT_mod$r_m$w(struct output_data * d)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
FCT_mod$8r_m(struct output_data * d)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
FCT_mod$16r_m(struct output_data * d)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
FCT_mod$64r_m(struct output_data * d)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
FCT_reg(struct output_data * d)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
FCT_oreg(struct output_data * d)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
FCT_reg64(struct output_data * d)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
FCT_reg$w(struct output_data * d)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
FCT_oreg$w(struct output_data * d)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
FCT_freg(struct output_data * d)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
FCT_reg16(struct output_data * d)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
FCT_sel(struct output_data * d)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
FCT_sreg2(struct output_data * d)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
FCT_sreg3(struct output_data * d)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
FCT_string(struct output_data * d)1395 FCT_string (struct output_data *d __attribute__ ((unused)))
1396 {
1397   return 0;
1398 }
1399 
1400 
1401 static int
FCT_xmmreg(struct output_data * d)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 }
1416