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