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