Branch data Line data Source code
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
88 : 22802 : data_prefix (struct output_data *d)
89 : : {
90 : 22802 : char ch = '\0';
91 [ + + ]: 22802 : if (*d->prefixes & has_cs)
92 : : {
93 : 2 : ch = 'c';
94 : 2 : *d->prefixes &= ~has_cs;
95 : : }
96 [ + + ]: 22800 : else if (*d->prefixes & has_ds)
97 : : {
98 : 48 : ch = 'd';
99 : 48 : *d->prefixes &= ~has_ds;
100 : : }
101 [ + + ]: 22752 : else if (*d->prefixes & has_es)
102 : : {
103 : 2 : ch = 'e';
104 : 2 : *d->prefixes &= ~has_es;
105 : : }
106 [ + + ]: 22750 : else if (*d->prefixes & has_fs)
107 : : {
108 : 16 : ch = 'f';
109 : 16 : *d->prefixes &= ~has_fs;
110 : : }
111 [ + + ]: 22734 : else if (*d->prefixes & has_gs)
112 : : {
113 : 20 : ch = 'g';
114 : 20 : *d->prefixes &= ~has_gs;
115 : : }
116 [ + + ]: 22714 : else if (*d->prefixes & has_ss)
117 : : {
118 : 2 : ch = 's';
119 : 2 : *d->prefixes &= ~has_ss;
120 : : }
121 : : else
122 : : return 0;
123 : :
124 [ - + ]: 90 : if (*d->bufcntp + 4 > d->bufsize)
125 : 0 : return *d->bufcntp + 4 - d->bufsize;
126 : :
127 : 90 : d->bufp[(*d->bufcntp)++] = '%';
128 : 90 : d->bufp[(*d->bufcntp)++] = ch;
129 : 90 : d->bufp[(*d->bufcntp)++] = 's';
130 : 90 : d->bufp[(*d->bufcntp)++] = ':';
131 : :
132 : 90 : 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
157 : 22696 : general_mod$r_m (struct output_data *d)
158 : : {
159 : 22696 : int r = data_prefix (d);
160 [ + - ]: 22696 : if (r != 0)
161 : : return r;
162 : :
163 : 22696 : int prefixes = *d->prefixes;
164 : 22696 : const uint8_t *data = &d->data[d->opoff1 / 8];
165 : 22696 : char *bufp = d->bufp;
166 : 22696 : size_t *bufcntp = d->bufcntp;
167 : 22696 : size_t bufsize = d->bufsize;
168 : :
169 : 22696 : uint_fast8_t modrm = data[0];
170 : : #ifndef X86_64
171 [ + + ]: 7504 : if (unlikely ((prefixes & has_addr16) != 0))
172 : : {
173 : 80 : int16_t disp = 0;
174 : 80 : bool nodisp = false;
175 : :
176 [ + + + + ]: 80 : if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80)
177 : : /* 16 bit displacement. */
178 : 34 : disp = read_2sbyte_unaligned (&data[1]);
179 [ + + ]: 46 : else if ((modrm & 0xc0) == 0x40)
180 : : /* 8 bit displacement. */
181 : 32 : disp = *(const int8_t *) &data[1];
182 [ + - ]: 14 : else if ((modrm & 0xc0) == 0)
183 : 14 : nodisp = true;
184 : :
185 : 80 : char tmpbuf[sizeof ("-0x1234(%rr,%rr)")];
186 : 80 : int n;
187 [ + + ]: 80 : if ((modrm & 0xc7) == 6)
188 : 2 : n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx16, disp);
189 : : else
190 : : {
191 : 78 : n = 0;
192 [ + + ]: 78 : if (!nodisp)
193 : 64 : n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx16,
194 [ + + ]: 64 : disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
195 : :
196 [ + + ]: 78 : if ((modrm & 0x4) == 0)
197 : 40 : n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%b%c,%%%ci)",
198 : 40 : "xp"[(modrm >> 1) & 1], "sd"[modrm & 1]);
199 : : else
200 : 38 : n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%%s)",
201 : 38 : ((const char [4][3]) { "si", "di", "bp", "bx" })[modrm & 3]);
202 : : }
203 : :
204 [ - + ]: 80 : if (*bufcntp + n + 1 > bufsize)
205 : 0 : return *bufcntp + n + 1 - bufsize;
206 : :
207 : 80 : memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
208 : 80 : *bufcntp += n;
209 : : }
210 : : else
211 : : #endif
212 : : {
213 [ + + ]: 22616 : if ((modrm & 7) != 4)
214 : : {
215 : 10344 : int32_t disp = 0;
216 : 10344 : bool nodisp = false;
217 : :
218 [ + + + + ]: 10344 : if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80)
219 : : /* 32 bit displacement. */
220 : 3752 : disp = read_4sbyte_unaligned (&data[1]);
221 [ + + ]: 6592 : else if ((modrm & 0xc0) == 0x40)
222 : : /* 8 bit displacement. */
223 : 3498 : disp = *(const int8_t *) &data[1];
224 [ + - ]: 3094 : else if ((modrm & 0xc0) == 0)
225 : 3094 : nodisp = true;
226 : :
227 : 10344 : char tmpbuf[sizeof ("-0x12345678(%rrrr)")];
228 : 10344 : int n;
229 : 7250 : if (nodisp)
230 : : {
231 : 3094 : n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)",
232 : : #ifdef X86_64
233 [ + + ]: 1732 : (prefixes & has_rex_b) ? hiregs[modrm & 7] :
234 : : #endif
235 : 1362 : aregs[modrm & 7]);
236 : : #ifdef X86_64
237 [ + + ]: 1732 : if (prefixes & has_addr16)
238 : : {
239 [ - + ]: 12 : if (prefixes & has_rex_b)
240 : 0 : tmpbuf[n++] = 'd';
241 : : else
242 : 12 : tmpbuf[2] = 'e';
243 : : }
244 : : #endif
245 : : }
246 [ + + ]: 7250 : else if ((modrm & 0xc7) != 5)
247 : : {
248 : 6854 : int p;
249 [ + + ]: 6854 : n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%n%s)",
250 : : disp < 0 ? "-" : "", disp < 0 ? -disp : disp, &p,
251 : : #ifdef X86_64
252 [ + + ]: 3788 : (prefixes & has_rex_b) ? hiregs[modrm & 7] :
253 : : #endif
254 [ + + ]: 3066 : aregs[modrm & 7]);
255 : : #ifdef X86_64
256 [ + + ]: 3788 : if (prefixes & has_addr16)
257 : : {
258 [ - + ]: 52 : if (prefixes & has_rex_b)
259 : 0 : tmpbuf[n++] = 'd';
260 : : else
261 : 52 : tmpbuf[p] = 'e';
262 : : }
263 : : #endif
264 : : }
265 : : else
266 : : {
267 : : #ifdef X86_64
268 [ + + ]: 222 : n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%rip)",
269 : : disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
270 : :
271 : 222 : d->symaddr_use = addr_rel_always;
272 : 222 : d->symaddr = disp;
273 : : #else
274 : 174 : n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp);
275 : : #endif
276 : : }
277 : :
278 [ - + ]: 10344 : if (*bufcntp + n + 1 > bufsize)
279 : 0 : return *bufcntp + n + 1 - bufsize;
280 : :
281 : 10344 : memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
282 : 10344 : *bufcntp += n;
283 : : }
284 : : else
285 : : {
286 : : /* SIB */
287 : 12272 : uint_fast8_t sib = data[1];
288 : 12272 : int32_t disp = 0;
289 : 12272 : bool nodisp = false;
290 : :
291 [ + - + + ]: 12272 : if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80
292 [ + + + + ]: 8576 : || ((modrm & 0xc7) == 0x4 && (sib & 0x7) == 0x5))
293 : : /* 32 bit displacement. */
294 : 4380 : disp = read_4sbyte_unaligned (&data[2]);
295 [ + + ]: 7892 : else if ((modrm & 0xc0) == 0x40)
296 : : /* 8 bit displacement. */
297 : 3664 : disp = *(const int8_t *) &data[2];
298 : : else
299 : : nodisp = true;
300 : :
301 : 12272 : char tmpbuf[sizeof ("-0x12345678(%rrrr,%rrrr,N)")];
302 : 12272 : char *cp = tmpbuf;
303 : 12272 : int n;
304 [ + + + + ]: 12272 : if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25
305 : : #ifdef X86_64
306 [ + + ]: 42 : || (prefixes & has_rex_x) != 0
307 : : #endif
308 : : )
309 : : {
310 [ + + ]: 12228 : if (!nodisp)
311 : : {
312 [ + + ]: 8000 : n = snprintf (cp, sizeof (tmpbuf), "%s0x%" PRIx32,
313 : : disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
314 : 8000 : cp += n;
315 : : }
316 : :
317 : 12228 : *cp++ = '(';
318 : :
319 [ + + + + ]: 12228 : if ((modrm & 0xc7) != 0x4 || (sib & 0x7) != 0x5)
320 : : {
321 : 11588 : *cp++ = '%';
322 : 22220 : cp = stpcpy (cp,
323 : : #ifdef X86_64
324 [ + + ]: 8948 : (prefixes & has_rex_b) ? hiregs[sib & 7] :
325 [ + + ]: 7264 : (prefixes & has_addr16) ? dregs[sib & 7] :
326 : : #endif
327 : 9894 : aregs[sib & 7]);
328 : : #ifdef X86_64
329 [ - + ]: 8948 : if ((prefixes & (has_rex_b | has_addr16))
330 : : == (has_rex_b | has_addr16))
331 : 0 : *cp++ = 'd';
332 : : #endif
333 : : }
334 : :
335 [ + + ]: 12228 : if ((sib & 0x38) != 0x20
336 : : #ifdef X86_64
337 [ + + ]: 1054 : || (prefixes & has_rex_x) != 0
338 : : #endif
339 : : )
340 : : {
341 : 11056 : *cp++ = ',';
342 : 11056 : *cp++ = '%';
343 : 21308 : cp = stpcpy (cp,
344 : : #ifdef X86_64
345 [ + + ]: 8554 : (prefixes & has_rex_x)
346 : 1698 : ? hiregs[(sib >> 3) & 7] :
347 : 6856 : (prefixes & has_addr16)
348 [ + + ]: 6856 : ? dregs[(sib >> 3) & 7] :
349 : : #endif
350 : 9348 : aregs[(sib >> 3) & 7]);
351 : : #ifdef X86_64
352 [ - + ]: 8554 : if ((prefixes & (has_rex_b | has_addr16))
353 : : == (has_rex_b | has_addr16))
354 : 0 : *cp++ = 'd';
355 : : #endif
356 : :
357 : 11056 : *cp++ = ',';
358 : 11056 : *cp++ = '0' + (1 << (sib >> 6));
359 : : }
360 : :
361 : 12228 : *cp++ = ')';
362 : : }
363 : : else
364 : : {
365 [ - + ]: 44 : assert (! nodisp);
366 : : #ifdef X86_64
367 [ + - ]: 34 : if ((prefixes & has_addr16) == 0)
368 : 34 : n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx64,
369 : : (int64_t) disp);
370 : : else
371 : : #endif
372 : 10 : n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx32, disp);
373 : 44 : cp += n;
374 : : }
375 : :
376 [ - + ]: 12272 : if (*bufcntp + (cp - tmpbuf) > bufsize)
377 : 0 : return *bufcntp + (cp - tmpbuf) - bufsize;
378 : :
379 : 12272 : memcpy (&bufp[*bufcntp], tmpbuf, cp - tmpbuf);
380 : 12272 : *bufcntp += cp - tmpbuf;
381 : : }
382 : : }
383 : : return 0;
384 : : }
385 : :
386 : :
387 : : static int
388 : 3588 : FCT_MOD$R_M (struct output_data *d)
389 : : {
390 [ - + ]: 3588 : assert (d->opoff1 % 8 == 0);
391 : 3588 : uint_fast8_t modrm = d->data[d->opoff1 / 8];
392 [ + + ]: 3588 : if ((modrm & 0xc0) == 0xc0)
393 : : {
394 [ - + ]: 2496 : assert (d->opoff1 / 8 == d->opoff2 / 8);
395 [ - + ]: 2496 : assert (d->opoff2 % 8 == 5);
396 : : //uint_fast8_t byte = d->data[d->opoff2 / 8] & 7;
397 : 2496 : uint_fast8_t byte = modrm & 7;
398 : :
399 : 2496 : size_t *bufcntp = d->bufcntp;
400 : 2496 : char *buf = d->bufp + *bufcntp;
401 : 2496 : size_t avail = d->bufsize - *bufcntp;
402 : 2496 : int needed;
403 [ - + ]: 2496 : if (*d->prefixes & (has_rep | has_repne))
404 : 0 : needed = snprintf (buf, avail, "%%%s", dregs[byte]);
405 : : else
406 : 2496 : needed = snprintf (buf, avail, "%%mm%" PRIxFAST8, byte);
407 [ - + ]: 2496 : if ((size_t) needed > avail)
408 : 0 : return needed - avail;
409 : 2496 : *bufcntp += needed;
410 : 2496 : return 0;
411 : : }
412 : :
413 : 1092 : return general_mod$r_m (d);
414 : : }
415 : :
416 : :
417 : : static int
418 : 10584 : FCT_Mod$R_m (struct output_data *d)
419 : : {
420 [ - + ]: 10584 : assert (d->opoff1 % 8 == 0);
421 : 10584 : uint_fast8_t modrm = d->data[d->opoff1 / 8];
422 [ + + ]: 10584 : if ((modrm & 0xc0) == 0xc0)
423 : : {
424 [ - + ]: 6152 : assert (d->opoff1 / 8 == d->opoff2 / 8);
425 [ - + ]: 6152 : assert (d->opoff2 % 8 == 5);
426 : : //uint_fast8_t byte = data[opoff2 / 8] & 7;
427 : 6152 : uint_fast8_t byte = modrm & 7;
428 : :
429 : 6152 : size_t *bufcntp = d->bufcntp;
430 : 6152 : size_t avail = d->bufsize - *bufcntp;
431 [ - + ]: 6152 : int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8,
432 : : byte);
433 [ - + ]: 6152 : if ((size_t) needed > avail)
434 : 0 : return needed - avail;
435 : 6152 : *d->bufcntp += needed;
436 : 6152 : return 0;
437 : : }
438 : :
439 : 4432 : return general_mod$r_m (d);
440 : : }
441 : :
442 : : static int
443 : 22 : 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 : 22 : int r = data_prefix (d);
452 [ + - ]: 22 : if (r != 0)
453 : : return r;
454 : :
455 [ - + ]: 22 : assert (d->opoff1 % 8 == 0);
456 [ - + ]: 22 : assert (d->opoff1 / 8 == 1);
457 [ + - ]: 22 : if (*d->param_start + abslen > d->end)
458 : : return -1;
459 : 22 : *d->param_start += abslen;
460 : : #ifndef X86_64
461 : 14 : uint32_t absval;
462 : : # define ABSPRIFMT PRIx32
463 : : #else
464 : 8 : uint64_t absval;
465 : : # define ABSPRIFMT PRIx64
466 [ + - ]: 8 : if (abslen == 8)
467 : 8 : absval = read_8ubyte_unaligned (&d->data[1]);
468 : : else
469 : : #endif
470 : 14 : absval = read_4ubyte_unaligned (&d->data[1]);
471 : 22 : size_t *bufcntp = d->bufcntp;
472 : 22 : size_t avail = d->bufsize - *bufcntp;
473 [ - + ]: 22 : int needed = snprintf (&d->bufp[*bufcntp], avail, "%s0x%" ABSPRIFMT,
474 : : absstring, absval);
475 [ - + ]: 22 : if ((size_t) needed > avail)
476 : 0 : return needed - avail;
477 : 22 : *bufcntp += needed;
478 : 22 : return 0;
479 : : }
480 : :
481 : :
482 : : static int
483 : 6 : FCT_absval (struct output_data *d)
484 : : {
485 : 6 : return generic_abs (d, "$"
486 : : #ifdef X86_64
487 : : , 4
488 : : #endif
489 : : );
490 : : }
491 : :
492 : : static int
493 : 16 : FCT_abs (struct output_data *d)
494 : : {
495 : 16 : return generic_abs (d, ""
496 : : #ifdef X86_64
497 : : , 8
498 : : #endif
499 : : );
500 : : }
501 : :
502 : : static int
503 : 212 : FCT_ax (struct output_data *d)
504 : : {
505 : 212 : int is_16bit = (*d->prefixes & has_data16) != 0;
506 : :
507 : 212 : size_t *bufcntp = d->bufcntp;
508 : 212 : char *bufp = d->bufp;
509 : 212 : size_t bufsize = d->bufsize;
510 : :
511 [ - + ]: 212 : if (*bufcntp + 4 - is_16bit > bufsize)
512 : 0 : return *bufcntp + 4 - is_16bit - bufsize;
513 : :
514 : 212 : bufp[(*bufcntp)++] = '%';
515 [ + + ]: 212 : if (! is_16bit)
516 : 164 : bufp[(*bufcntp)++] = (
517 : : #ifdef X86_64
518 [ + + ]: 102 : (*d->prefixes & has_rex_w) ? 'r' :
519 : : #endif
520 : : 'e');
521 : 212 : bufp[(*bufcntp)++] = 'a';
522 : 212 : bufp[(*bufcntp)++] = 'x';
523 : :
524 : 212 : return 0;
525 : : }
526 : :
527 : :
528 : : static int
529 : 276 : FCT_ax$w (struct output_data *d)
530 : : {
531 [ + + ]: 276 : if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
532 : 176 : return FCT_ax (d);
533 : :
534 : 100 : size_t *bufcntp = d->bufcntp;
535 : 100 : char *bufp = d->bufp;
536 : 100 : size_t bufsize = d->bufsize;
537 : :
538 [ - + ]: 100 : if (*bufcntp + 3 > bufsize)
539 : 0 : return *bufcntp + 3 - bufsize;
540 : :
541 : 100 : bufp[(*bufcntp)++] = '%';
542 : 100 : bufp[(*bufcntp)++] = 'a';
543 : 100 : bufp[(*bufcntp)++] = 'l';
544 : :
545 : 100 : return 0;
546 : : }
547 : :
548 : :
549 : : static int
550 : : __attribute__ ((noinline))
551 : 1024 : FCT_crdb (struct output_data *d, const char *regstr)
552 : : {
553 [ + - ]: 1024 : if (*d->prefixes & has_data16)
554 : : return -1;
555 : :
556 : 1024 : size_t *bufcntp = d->bufcntp;
557 : :
558 : : // XXX If this assert is true, use absolute offset below
559 [ - + ]: 1024 : assert (d->opoff1 / 8 == 2);
560 [ - + ]: 1024 : assert (d->opoff1 % 8 == 2);
561 : 1024 : size_t avail = d->bufsize - *bufcntp;
562 : 1024 : int needed = snprintf (&d->bufp[*bufcntp], avail, "%%%s%" PRIx32,
563 [ - + ]: 1024 : regstr, (uint32_t) (d->data[d->opoff1 / 8] >> 3) & 7);
564 [ - + ]: 1024 : if ((size_t) needed > avail)
565 : 0 : return needed - avail;
566 : 1024 : *bufcntp += needed;
567 : 1024 : return 0;
568 : : }
569 : :
570 : :
571 : : static int
572 : 512 : FCT_ccc (struct output_data *d)
573 : : {
574 : 512 : return FCT_crdb (d, "cr");
575 : : }
576 : :
577 : :
578 : : static int
579 : 512 : FCT_ddd (struct output_data *d)
580 : : {
581 : 512 : return FCT_crdb (d, "db");
582 : : }
583 : :
584 : :
585 : : static int
586 : 176 : FCT_disp8 (struct output_data *d)
587 : : {
588 [ - + ]: 176 : assert (d->opoff1 % 8 == 0);
589 [ + - ]: 176 : if (*d->param_start >= d->end)
590 : : return -1;
591 : 176 : int32_t offset = *(const int8_t *) (*d->param_start)++;
592 : :
593 : 176 : size_t *bufcntp = d->bufcntp;
594 : 176 : size_t avail = d->bufsize - *bufcntp;
595 : 176 : int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
596 [ - + ]: 176 : (uint32_t) (d->addr + (*d->param_start - d->data)
597 : : + offset));
598 [ - + ]: 176 : if ((size_t) needed > avail)
599 : 0 : return needed - avail;
600 : 176 : *bufcntp += needed;
601 : 176 : return 0;
602 : : }
603 : :
604 : :
605 : : static int
606 : : __attribute__ ((noinline))
607 : 84 : FCT_ds_xx (struct output_data *d, const char *reg)
608 : : {
609 : 84 : int prefix = *d->prefixes & SEGMENT_PREFIXES;
610 : :
611 [ + + ]: 84 : if (prefix == 0)
612 : 48 : *d->prefixes |= prefix = has_ds;
613 : : /* Make sure only one bit is set. */
614 [ + - ]: 36 : else if ((prefix - 1) & prefix)
615 : : return -1;
616 : :
617 : 84 : int r = data_prefix (d);
618 : :
619 [ - + ]: 84 : assert ((*d->prefixes & prefix) == 0);
620 : :
621 [ + - ]: 84 : if (r != 0)
622 : : return r;
623 : :
624 : 84 : size_t *bufcntp = d->bufcntp;
625 : 84 : size_t avail = d->bufsize - *bufcntp;
626 [ - + ]: 84 : int needed = snprintf (&d->bufp[*bufcntp], avail, "(%%%s%s)",
627 : : #ifdef X86_64
628 [ + - ]: 42 : *d->prefixes & idx_addr16 ? "e" : "r",
629 : : #else
630 [ + - ]: 42 : *d->prefixes & idx_addr16 ? "" : "e",
631 : : #endif
632 : : reg);
633 [ - + ]: 84 : if ((size_t) needed > avail)
634 : 0 : return (size_t) needed - avail;
635 : 84 : *bufcntp += needed;
636 : :
637 : 84 : return 0;
638 : : }
639 : :
640 : :
641 : : static int
642 : 8 : FCT_ds_bx (struct output_data *d)
643 : : {
644 : 8 : return FCT_ds_xx (d, "bx");
645 : : }
646 : :
647 : :
648 : : static int
649 : 76 : FCT_ds_si (struct output_data *d)
650 : : {
651 : 76 : return FCT_ds_xx (d, "si");
652 : : }
653 : :
654 : :
655 : : static int
656 : 40 : FCT_dx (struct output_data *d)
657 : : {
658 : 40 : size_t *bufcntp = d->bufcntp;
659 : :
660 [ - + ]: 40 : if (*bufcntp + 7 > d->bufsize)
661 : 0 : return *bufcntp + 7 - d->bufsize;
662 : :
663 : 40 : memcpy (&d->bufp[*bufcntp], "(%dx)", 5);
664 : 40 : *bufcntp += 5;
665 : :
666 : 40 : return 0;
667 : : }
668 : :
669 : :
670 : : static int
671 : 80 : FCT_es_di (struct output_data *d)
672 : : {
673 : 80 : size_t *bufcntp = d->bufcntp;
674 : 80 : size_t avail = d->bufsize - *bufcntp;
675 [ - + ]: 80 : int needed = snprintf (&d->bufp[*bufcntp], avail, "%%es:(%%%sdi)",
676 : : #ifdef X86_64
677 [ + - ]: 40 : *d->prefixes & idx_addr16 ? "e" : "r"
678 : : #else
679 [ + - ]: 40 : *d->prefixes & idx_addr16 ? "" : "e"
680 : : #endif
681 : : );
682 [ - + ]: 80 : if ((size_t) needed > avail)
683 : 0 : return (size_t) needed - avail;
684 : 80 : *bufcntp += needed;
685 : :
686 : 80 : return 0;
687 : : }
688 : :
689 : :
690 : : static int
691 : 488 : FCT_imm (struct output_data *d)
692 : : {
693 : 488 : size_t *bufcntp = d->bufcntp;
694 : 488 : size_t avail = d->bufsize - *bufcntp;
695 : 488 : int needed;
696 [ + + ]: 488 : if (*d->prefixes & has_data16)
697 : : {
698 [ + - ]: 88 : if (*d->param_start + 2 > d->end)
699 : : return -1;
700 : 88 : uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
701 : 88 : needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
702 : : }
703 : : else
704 : : {
705 [ + - ]: 400 : if (*d->param_start + 4 > d->end)
706 : : return -1;
707 : 400 : int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
708 : : #ifdef X86_64
709 [ + + ]: 200 : if (*d->prefixes & has_rex_w)
710 : 16 : needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
711 : : (int64_t) word);
712 : : else
713 : : #endif
714 : 384 : needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
715 : : }
716 [ - + ]: 488 : if ((size_t) needed > avail)
717 : 0 : return (size_t) needed - avail;
718 : 488 : *bufcntp += needed;
719 : 488 : return 0;
720 : : }
721 : :
722 : :
723 : : static int
724 : 900 : FCT_imm$w (struct output_data *d)
725 : : {
726 [ + + ]: 900 : if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
727 : 488 : return FCT_imm (d);
728 : :
729 : 412 : size_t *bufcntp = d->bufcntp;
730 : 412 : size_t avail = d->bufsize - *bufcntp;
731 [ + - ]: 412 : if (*d->param_start>= d->end)
732 : : return -1;
733 : 412 : uint_fast8_t word = *(*d->param_start)++;
734 [ - + ]: 412 : int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIxFAST8, word);
735 [ - + ]: 412 : if ((size_t) needed > avail)
736 : 0 : return (size_t) needed - avail;
737 : 412 : *bufcntp += needed;
738 : 412 : return 0;
739 : : }
740 : :
741 : :
742 : : #ifdef X86_64
743 : : static int
744 : 108 : FCT_imm64$w (struct output_data *d)
745 : : {
746 [ + + ]: 108 : if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) == 0
747 [ + + ]: 72 : || (*d->prefixes & has_data16) != 0)
748 : 68 : return FCT_imm$w (d);
749 : :
750 : 40 : size_t *bufcntp = d->bufcntp;
751 : 40 : size_t avail = d->bufsize - *bufcntp;
752 : 40 : int needed;
753 [ + + ]: 40 : if (*d->prefixes & has_rex_w)
754 : : {
755 [ + - ]: 4 : if (*d->param_start + 8 > d->end)
756 : : return -1;
757 : 4 : uint64_t word = read_8ubyte_unaligned_inc (*d->param_start);
758 : 4 : needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, word);
759 : : }
760 : : else
761 : : {
762 [ + - ]: 36 : if (*d->param_start + 4 > d->end)
763 : : return -1;
764 : 36 : int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
765 : 36 : needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
766 : : }
767 [ - + ]: 40 : if ((size_t) needed > avail)
768 : 0 : return (size_t) needed - avail;
769 : 40 : *bufcntp += needed;
770 : 40 : return 0;
771 : : }
772 : : #endif
773 : :
774 : :
775 : : static int
776 : 24 : FCT_imms (struct output_data *d)
777 : : {
778 : 24 : size_t *bufcntp = d->bufcntp;
779 : 24 : size_t avail = d->bufsize - *bufcntp;
780 [ + - ]: 24 : if (*d->param_start>= d->end)
781 : : return -1;
782 : 24 : int8_t byte = *(*d->param_start)++;
783 : : #ifdef X86_64
784 [ - + ]: 12 : int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
785 : : (int64_t) byte);
786 : : #else
787 [ - + ]: 12 : int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
788 : : (int32_t) byte);
789 : : #endif
790 [ - + ]: 24 : if ((size_t) needed > avail)
791 : 0 : return (size_t) needed - avail;
792 : 24 : *bufcntp += needed;
793 : 24 : return 0;
794 : : }
795 : :
796 : :
797 : : static int
798 : 44 : FCT_imm$s (struct output_data *d)
799 : : {
800 : 44 : uint_fast8_t opcode = d->data[d->opoff2 / 8];
801 : 44 : size_t *bufcntp = d->bufcntp;
802 : 44 : size_t avail = d->bufsize - *bufcntp;
803 [ + + ]: 44 : if ((opcode & 2) != 0)
804 : 24 : return FCT_imms (d);
805 : :
806 [ + - ]: 20 : if ((*d->prefixes & has_data16) == 0)
807 : : {
808 [ + - ]: 20 : if (*d->param_start + 4 > d->end)
809 : : return -1;
810 : 20 : int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
811 : : #ifdef X86_64
812 [ - + ]: 10 : int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
813 : : (int64_t) word);
814 : : #else
815 [ - + ]: 10 : int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
816 : : #endif
817 [ - + ]: 20 : if ((size_t) needed > avail)
818 : 0 : return (size_t) needed - avail;
819 : 20 : *bufcntp += needed;
820 : : }
821 : : else
822 : : {
823 [ # # ]: 0 : if (*d->param_start + 2 > d->end)
824 : : return -1;
825 : 0 : uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
826 [ # # ]: 0 : int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
827 [ # # ]: 0 : if ((size_t) needed > avail)
828 : 0 : return (size_t) needed - avail;
829 : 0 : *bufcntp += needed;
830 : : }
831 : : return 0;
832 : : }
833 : :
834 : :
835 : : static int
836 : 20 : FCT_imm16 (struct output_data *d)
837 : : {
838 [ + - ]: 20 : if (*d->param_start + 2 > d->end)
839 : : return -1;
840 : 20 : uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
841 : 20 : size_t *bufcntp = d->bufcntp;
842 : 20 : size_t avail = d->bufsize - *bufcntp;
843 [ - + ]: 20 : int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
844 [ - + ]: 20 : if ((size_t) needed > avail)
845 : 0 : return (size_t) needed - avail;
846 : 20 : *bufcntp += needed;
847 : 20 : return 0;
848 : : }
849 : :
850 : :
851 : : static int
852 : 216 : FCT_imms8 (struct output_data *d)
853 : : {
854 : 216 : size_t *bufcntp = d->bufcntp;
855 : 216 : size_t avail = d->bufsize - *bufcntp;
856 [ + - ]: 216 : if (*d->param_start >= d->end)
857 : : return -1;
858 : 216 : int_fast8_t byte = *(*d->param_start)++;
859 : 216 : int needed;
860 : : #ifdef X86_64
861 [ + + ]: 124 : if (*d->prefixes & has_rex_w)
862 : 16 : needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
863 : : (int64_t) byte);
864 : : else
865 : : #endif
866 [ - + ]: 200 : needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
867 : : (int32_t) byte);
868 [ - + ]: 216 : if ((size_t) needed > avail)
869 : 0 : return (size_t) needed - avail;
870 : 216 : *bufcntp += needed;
871 : 216 : return 0;
872 : : }
873 : :
874 : :
875 : : static int
876 : 1876 : FCT_imm8 (struct output_data *d)
877 : : {
878 : 1876 : size_t *bufcntp = d->bufcntp;
879 : 1876 : size_t avail = d->bufsize - *bufcntp;
880 [ + - ]: 1876 : if (*d->param_start >= d->end)
881 : : return -1;
882 : 1876 : uint_fast8_t byte = *(*d->param_start)++;
883 [ - + ]: 1876 : int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
884 : : (uint32_t) byte);
885 [ - + ]: 1876 : if ((size_t) needed > avail)
886 : 0 : return (size_t) needed - avail;
887 : 1876 : *bufcntp += needed;
888 : 1876 : return 0;
889 : : }
890 : :
891 : :
892 : : static int
893 : 80 : FCT_rel (struct output_data *d)
894 : : {
895 : 80 : size_t *bufcntp = d->bufcntp;
896 : 80 : size_t avail = d->bufsize - *bufcntp;
897 [ + - ]: 80 : if (*d->param_start + 4 > d->end)
898 : : return -1;
899 : 80 : int32_t rel = read_4sbyte_unaligned_inc (*d->param_start);
900 : : #ifdef X86_64
901 : 40 : int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx64,
902 : 40 : (uint64_t) (d->addr + rel
903 [ - + ]: 40 : + (*d->param_start - d->data)));
904 : : #else
905 : 40 : int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
906 : 40 : (uint32_t) (d->addr + rel
907 [ - + ]: 40 : + (*d->param_start - d->data)));
908 : : #endif
909 [ - + ]: 80 : if ((size_t) needed > avail)
910 : 0 : return (size_t) needed - avail;
911 : 80 : *bufcntp += needed;
912 : 80 : return 0;
913 : : }
914 : :
915 : :
916 : : static int
917 : 4064 : FCT_mmxreg (struct output_data *d)
918 : : {
919 : 4064 : uint_fast8_t byte = d->data[d->opoff1 / 8];
920 [ - + ]: 4064 : assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
921 : 4064 : byte = (byte >> (5 - d->opoff1 % 8)) & 7;
922 : 4064 : size_t *bufcntp = d->bufcntp;
923 : 4064 : size_t avail = d->bufsize - *bufcntp;
924 [ - + ]: 4064 : int needed = snprintf (&d->bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte);
925 [ - + ]: 4064 : if ((size_t) needed > avail)
926 : 0 : return needed - avail;
927 : 4064 : *bufcntp += needed;
928 : 4064 : return 0;
929 : : }
930 : :
931 : :
932 : : static int
933 : 2706 : FCT_mod$r_m (struct output_data *d)
934 : : {
935 [ - + ]: 2706 : assert (d->opoff1 % 8 == 0);
936 : 2706 : uint_fast8_t modrm = d->data[d->opoff1 / 8];
937 [ + + ]: 2706 : if ((modrm & 0xc0) == 0xc0)
938 : : {
939 : 648 : int prefixes = *d->prefixes;
940 [ + - ]: 648 : if (prefixes & has_addr16)
941 : : return -1;
942 : :
943 : 648 : int is_16bit = (prefixes & has_data16) != 0;
944 : :
945 : 648 : size_t *bufcntp = d->bufcntp;
946 : 648 : char *bufp = d->bufp;
947 [ - + ]: 648 : if (*bufcntp + 5 - is_16bit > d->bufsize)
948 : 0 : return *bufcntp + 5 - is_16bit - d->bufsize;
949 : 648 : bufp[(*bufcntp)++] = '%';
950 : :
951 : 648 : char *cp;
952 : : #ifdef X86_64
953 [ - + - - ]: 304 : if ((prefixes & has_rex_b) != 0 && !is_16bit)
954 : : {
955 [ # # ]: 0 : cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
956 [ # # ]: 0 : if ((prefixes & has_rex_w) == 0)
957 : 0 : *cp++ = 'd';
958 : : }
959 : : else
960 : : #endif
961 : : {
962 [ + - ]: 648 : cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
963 : : #ifdef X86_64
964 [ + - ]: 304 : if ((prefixes & has_rex_w) != 0)
965 : 0 : bufp[*bufcntp] = 'r';
966 : : #endif
967 : : }
968 : 648 : *bufcntp = cp - bufp;
969 : 648 : return 0;
970 : : }
971 : :
972 : 2058 : return general_mod$r_m (d);
973 : : }
974 : :
975 : :
976 : : #ifndef X86_64
977 : : static int
978 : 4 : FCT_moda$r_m (struct output_data *d)
979 : : {
980 [ - + ]: 4 : assert (d->opoff1 % 8 == 0);
981 : 4 : uint_fast8_t modrm = d->data[d->opoff1 / 8];
982 [ - + ]: 4 : if ((modrm & 0xc0) == 0xc0)
983 : : {
984 [ # # ]: 0 : if (*d->prefixes & has_addr16)
985 : : return -1;
986 : :
987 : 0 : size_t *bufcntp = d->bufcntp;
988 [ # # ]: 0 : if (*bufcntp + 3 > d->bufsize)
989 : 0 : return *bufcntp + 3 - d->bufsize;
990 : :
991 : 0 : memcpy (&d->bufp[*bufcntp], "???", 3);
992 : 0 : *bufcntp += 3;
993 : :
994 : 0 : return 0;
995 : : }
996 : :
997 : 4 : 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
1012 : 16098 : FCT_mod$r_m$w (struct output_data *d)
1013 : : {
1014 [ - + ]: 16098 : assert (d->opoff1 % 8 == 0);
1015 : 16098 : const uint8_t *data = d->data;
1016 : 16098 : uint_fast8_t modrm = data[d->opoff1 / 8];
1017 [ + + ]: 16098 : if ((modrm & 0xc0) == 0xc0)
1018 : : {
1019 : 1372 : int prefixes = *d->prefixes;
1020 : :
1021 [ + - ]: 1372 : if (prefixes & has_addr16)
1022 : : return -1;
1023 : :
1024 : 1372 : size_t *bufcntp = d->bufcntp;
1025 : 1372 : char *bufp = d->bufp;
1026 [ - + ]: 1372 : if (*bufcntp + 5 > d->bufsize)
1027 : 0 : return *bufcntp + 5 - d->bufsize;
1028 : :
1029 [ + + ]: 1372 : if ((data[d->opoff3 / 8] & (1 << (7 - (d->opoff3 & 7)))) == 0)
1030 : : {
1031 : 492 : bufp[(*bufcntp)++] = '%';
1032 : :
1033 : : #ifdef X86_64
1034 [ - + ]: 246 : if (prefixes & has_rex)
1035 : : {
1036 [ # # ]: 0 : if (prefixes & has_rex_r)
1037 : 0 : *bufcntp += snprintf (bufp + *bufcntp, d->bufsize - *bufcntp,
1038 : 0 : "r%db", 8 + (modrm & 7));
1039 : : else
1040 : : {
1041 : 0 : char *cp = stpcpy (bufp + *bufcntp, hiregs[modrm & 7]);
1042 : 0 : *cp++ = 'l';
1043 : 0 : *bufcntp = cp - bufp;
1044 : : }
1045 : : }
1046 : : else
1047 : : #endif
1048 : : {
1049 : 492 : bufp[(*bufcntp)++] = "acdb"[modrm & 3];
1050 : 492 : bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
1051 : : }
1052 : : }
1053 : : else
1054 : : {
1055 : 880 : int is_16bit = (prefixes & has_data16) != 0;
1056 : :
1057 : 880 : bufp[(*bufcntp)++] = '%';
1058 : :
1059 : 880 : char *cp;
1060 : : #ifdef X86_64
1061 [ + + + - ]: 504 : if ((prefixes & has_rex_b) != 0 && !is_16bit)
1062 : : {
1063 [ + - ]: 128 : cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
1064 [ + - ]: 128 : if ((prefixes & has_rex_w) == 0)
1065 : 128 : *cp++ = 'd';
1066 : : }
1067 : : else
1068 : : #endif
1069 : : {
1070 [ + - ]: 752 : cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
1071 : : #ifdef X86_64
1072 [ + - ]: 376 : if ((prefixes & has_rex_w) != 0)
1073 : 0 : bufp[*bufcntp] = 'r';
1074 : : #endif
1075 : : }
1076 : 880 : *bufcntp = cp - bufp;
1077 : : }
1078 : 1372 : return 0;
1079 : : }
1080 : :
1081 : 14726 : return general_mod$r_m (d);
1082 : : }
1083 : :
1084 : :
1085 : : static int
1086 : 320 : FCT_mod$8r_m (struct output_data *d)
1087 : : {
1088 [ - + ]: 320 : assert (d->opoff1 % 8 == 0);
1089 : 320 : uint_fast8_t modrm = d->data[d->opoff1 / 8];
1090 [ + + ]: 320 : if ((modrm & 0xc0) == 0xc0)
1091 : : {
1092 : 80 : size_t *bufcntp = d->bufcntp;
1093 : 80 : char *bufp = d->bufp;
1094 [ - + ]: 80 : if (*bufcntp + 3 > d->bufsize)
1095 : 0 : return *bufcntp + 3 - d->bufsize;
1096 : 80 : bufp[(*bufcntp)++] = '%';
1097 : 80 : bufp[(*bufcntp)++] = "acdb"[modrm & 3];
1098 : 80 : bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
1099 : 80 : return 0;
1100 : : }
1101 : :
1102 : 240 : return general_mod$r_m (d);
1103 : : }
1104 : :
1105 : :
1106 : : static int
1107 : 144 : FCT_mod$16r_m (struct output_data *d)
1108 : : {
1109 [ - + ]: 144 : assert (d->opoff1 % 8 == 0);
1110 : 144 : uint_fast8_t modrm = d->data[d->opoff1 / 8];
1111 [ + + ]: 144 : if ((modrm & 0xc0) == 0xc0)
1112 : : {
1113 [ - + ]: 36 : assert (d->opoff1 / 8 == d->opoff2 / 8);
1114 : : //uint_fast8_t byte = data[opoff2 / 8] & 7;
1115 : 36 : uint_fast8_t byte = modrm & 7;
1116 : :
1117 : 36 : size_t *bufcntp = d->bufcntp;
1118 [ - + ]: 36 : if (*bufcntp + 3 > d->bufsize)
1119 : 0 : return *bufcntp + 3 - d->bufsize;
1120 : 36 : d->bufp[(*bufcntp)++] = '%';
1121 : 36 : memcpy (&d->bufp[*bufcntp], dregs[byte] + 1, sizeof (dregs[0]) - 1);
1122 : 36 : *bufcntp += 2;
1123 : 36 : return 0;
1124 : : }
1125 : :
1126 : 108 : return general_mod$r_m (d);
1127 : : }
1128 : :
1129 : :
1130 : : #ifdef X86_64
1131 : : static int
1132 : 72 : FCT_mod$64r_m (struct output_data *d)
1133 : : {
1134 [ - + ]: 72 : assert (d->opoff1 % 8 == 0);
1135 : 72 : uint_fast8_t modrm = d->data[d->opoff1 / 8];
1136 [ + + ]: 72 : if ((modrm & 0xc0) == 0xc0)
1137 : : {
1138 [ - + ]: 36 : assert (d->opoff1 / 8 == d->opoff2 / 8);
1139 : : //uint_fast8_t byte = data[opoff2 / 8] & 7;
1140 : 36 : uint_fast8_t byte = modrm & 7;
1141 : :
1142 : 36 : size_t *bufcntp = d->bufcntp;
1143 [ - + ]: 36 : if (*bufcntp + 4 > d->bufsize)
1144 : 0 : return *bufcntp + 4 - d->bufsize;
1145 : 36 : char *cp = &d->bufp[*bufcntp];
1146 : 36 : *cp++ = '%';
1147 : 108 : cp = stpcpy (cp,
1148 [ - + ]: 36 : (*d->prefixes & has_rex_b) ? hiregs[byte] : aregs[byte]);
1149 : 36 : *bufcntp = cp - d->bufp;
1150 : 36 : return 0;
1151 : : }
1152 : :
1153 : 36 : return general_mod$r_m (d);
1154 : : }
1155 : : #else
1156 : : #define FCT_mod$64r_m FCT_mod$r_m
1157 : : #endif
1158 : :
1159 : :
1160 : : static int
1161 : 14292 : FCT_reg (struct output_data *d)
1162 : : {
1163 : 14292 : uint_fast8_t byte = d->data[d->opoff1 / 8];
1164 [ - + ]: 14292 : assert (d->opoff1 % 8 + 3 <= 8);
1165 : 14292 : byte >>= 8 - (d->opoff1 % 8 + 3);
1166 : 14292 : byte &= 7;
1167 : 14292 : int is_16bit = (*d->prefixes & has_data16) != 0;
1168 : 14292 : size_t *bufcntp = d->bufcntp;
1169 [ - + ]: 14292 : if (*bufcntp + 5 > d->bufsize)
1170 : 0 : return *bufcntp + 5 - d->bufsize;
1171 : 14292 : d->bufp[(*bufcntp)++] = '%';
1172 : : #ifdef X86_64
1173 [ + + + - ]: 10978 : if ((*d->prefixes & has_rex_r) != 0 && !is_16bit)
1174 : : {
1175 [ + + ]: 2120 : *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
1176 : : 8 + byte);
1177 [ + + ]: 2120 : if ((*d->prefixes & has_rex_w) == 0)
1178 : 2052 : d->bufp[(*bufcntp)++] = 'd';
1179 : : }
1180 : : else
1181 : : #endif
1182 : : {
1183 [ + + ]: 12172 : memcpy (&d->bufp[*bufcntp], dregs[byte] + is_16bit, 3 - is_16bit);
1184 : : #ifdef X86_64
1185 [ + + + - ]: 8858 : if ((*d->prefixes & has_rex_w) != 0 && !is_16bit)
1186 : 1986 : d->bufp[*bufcntp] = 'r';
1187 : : #endif
1188 : 12172 : *bufcntp += 3 - is_16bit;
1189 : : }
1190 : 3314 : return 0;
1191 : : }
1192 : :
1193 : :
1194 : : #ifdef X86_64
1195 : : static int
1196 : 22 : 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 : 22 : int save_prefixes = *d->prefixes;
1201 : :
1202 : 22 : *d->prefixes = ((save_prefixes & ~has_rex_r)
1203 : 22 : | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
1204 : :
1205 : 22 : int r = FCT_reg (d);
1206 : :
1207 : 22 : *d->prefixes = save_prefixes;
1208 : :
1209 : 22 : return r;
1210 : : }
1211 : : #endif
1212 : :
1213 : :
1214 : : static int
1215 : 1158 : FCT_reg64 (struct output_data *d)
1216 : : {
1217 : 1158 : uint_fast8_t byte = d->data[d->opoff1 / 8];
1218 [ - + ]: 1158 : assert (d->opoff1 % 8 + 3 <= 8);
1219 : 1158 : byte >>= 8 - (d->opoff1 % 8 + 3);
1220 : 1158 : byte &= 7;
1221 [ + - ]: 1158 : if ((*d->prefixes & has_data16) != 0)
1222 : : return -1;
1223 : 1158 : size_t *bufcntp = d->bufcntp;
1224 [ - + ]: 1158 : if (*bufcntp + 5 > d->bufsize)
1225 : 0 : return *bufcntp + 5 - d->bufsize;
1226 : 1158 : d->bufp[(*bufcntp)++] = '%';
1227 : : #ifdef X86_64
1228 [ - + ]: 602 : if ((*d->prefixes & has_rex_r) != 0)
1229 : : {
1230 [ # # ]: 0 : *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
1231 : : 8 + byte);
1232 [ # # ]: 0 : if ((*d->prefixes & has_rex_w) == 0)
1233 : 0 : d->bufp[(*bufcntp)++] = 'd';
1234 : : }
1235 : : else
1236 : : #endif
1237 : : {
1238 : 1158 : memcpy (&d->bufp[*bufcntp], aregs[byte], 3);
1239 : 1158 : *bufcntp += 3;
1240 : : }
1241 : 556 : return 0;
1242 : : }
1243 : :
1244 : :
1245 : : static int
1246 : 14650 : FCT_reg$w (struct output_data *d)
1247 : : {
1248 [ + + ]: 14650 : if (d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7))))
1249 : 13176 : return FCT_reg (d);
1250 : :
1251 : 1474 : uint_fast8_t byte = d->data[d->opoff1 / 8];
1252 [ - + ]: 1474 : assert (d->opoff1 % 8 + 3 <= 8);
1253 : 1474 : byte >>= 8 - (d->opoff1 % 8 + 3);
1254 : 1474 : byte &= 7;
1255 : :
1256 : 1474 : size_t *bufcntp = d->bufcntp;
1257 [ - + ]: 1474 : if (*bufcntp + 4 > d->bufsize)
1258 : 0 : return *bufcntp + 4 - d->bufsize;
1259 : :
1260 : 1474 : d->bufp[(*bufcntp)++] = '%';
1261 : :
1262 : : #ifdef X86_64
1263 [ + + ]: 768 : if (*d->prefixes & has_rex)
1264 : : {
1265 [ + + ]: 48 : if (*d->prefixes & has_rex_r)
1266 : 28 : *bufcntp += snprintf (d->bufp + *bufcntp, d->bufsize - *bufcntp,
1267 : : "r%db", 8 + byte);
1268 : : else
1269 : : {
1270 : 20 : char* cp = stpcpy (d->bufp + *bufcntp, rex_8bit[byte]);
1271 : 20 : *cp++ = 'l';
1272 : 20 : *bufcntp = cp - d->bufp;
1273 : : }
1274 : : }
1275 : : else
1276 : : #endif
1277 : : {
1278 : 1426 : d->bufp[(*bufcntp)++] = "acdb"[byte & 3];
1279 : 1426 : d->bufp[(*bufcntp)++] = "lh"[byte >> 2];
1280 : : }
1281 : 706 : return 0;
1282 : : }
1283 : :
1284 : :
1285 : : #ifdef X86_64
1286 : : static int
1287 : 108 : 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 : 108 : int save_prefixes = *d->prefixes;
1292 : :
1293 : 108 : *d->prefixes = ((save_prefixes & ~has_rex_r)
1294 : 108 : | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
1295 : :
1296 : 108 : int r = FCT_reg$w (d);
1297 : :
1298 : 108 : *d->prefixes = save_prefixes;
1299 : :
1300 : 108 : return r;
1301 : : }
1302 : : #endif
1303 : :
1304 : :
1305 : : static int
1306 : 1248 : FCT_freg (struct output_data *d)
1307 : : {
1308 [ - + ]: 1248 : assert (d->opoff1 / 8 == 1);
1309 [ - + ]: 1248 : assert (d->opoff1 % 8 == 5);
1310 : 1248 : size_t *bufcntp = d->bufcntp;
1311 : 1248 : size_t avail = d->bufsize - *bufcntp;
1312 : 1248 : int needed = snprintf (&d->bufp[*bufcntp], avail, "%%st(%" PRIx32 ")",
1313 [ - + ]: 1248 : (uint32_t) (d->data[1] & 7));
1314 [ - + ]: 1248 : if ((size_t) needed > avail)
1315 : 0 : return (size_t) needed - avail;
1316 : 1248 : *bufcntp += needed;
1317 : 1248 : return 0;
1318 : : }
1319 : :
1320 : :
1321 : : #ifndef X86_64
1322 : : static int
1323 : 8 : FCT_reg16 (struct output_data *d)
1324 : : {
1325 [ + - ]: 8 : if (*d->prefixes & has_data16)
1326 : : return -1;
1327 : :
1328 : 8 : *d->prefixes |= has_data16;
1329 : 8 : return FCT_reg (d);
1330 : : }
1331 : : #endif
1332 : :
1333 : :
1334 : : static int
1335 : 6 : FCT_sel (struct output_data *d)
1336 : : {
1337 [ - + ]: 6 : assert (d->opoff1 % 8 == 0);
1338 [ - + ]: 6 : assert (d->opoff1 / 8 == 5);
1339 [ + - ]: 6 : if (*d->param_start + 2 >= d->end)
1340 : : return -1;
1341 : 6 : *d->param_start += 2;
1342 : 6 : uint16_t absval = read_2ubyte_unaligned (&d->data[5]);
1343 : :
1344 : 6 : size_t *bufcntp = d->bufcntp;
1345 : 6 : size_t avail = d->bufsize - *bufcntp;
1346 [ - + ]: 6 : int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, absval);
1347 [ - + ]: 6 : if ((size_t) needed > avail)
1348 : 0 : return needed - avail;
1349 : 6 : *bufcntp += needed;
1350 : 6 : return 0;
1351 : : }
1352 : :
1353 : :
1354 : : static int
1355 : 14 : FCT_sreg2 (struct output_data *d)
1356 : : {
1357 : 14 : uint_fast8_t byte = d->data[d->opoff1 / 8];
1358 [ - + ]: 14 : assert (d->opoff1 % 8 + 3 <= 8);
1359 : 14 : byte >>= 8 - (d->opoff1 % 8 + 2);
1360 : :
1361 : 14 : size_t *bufcntp = d->bufcntp;
1362 : 14 : char *bufp = d->bufp;
1363 [ - + ]: 14 : if (*bufcntp + 3 > d->bufsize)
1364 : 0 : return *bufcntp + 3 - d->bufsize;
1365 : :
1366 : 14 : bufp[(*bufcntp)++] = '%';
1367 : 14 : bufp[(*bufcntp)++] = "ecsd"[byte & 3];
1368 : 14 : bufp[(*bufcntp)++] = 's';
1369 : :
1370 : 14 : return 0;
1371 : : }
1372 : :
1373 : :
1374 : : static int
1375 : 260 : FCT_sreg3 (struct output_data *d)
1376 : : {
1377 : 260 : uint_fast8_t byte = d->data[d->opoff1 / 8];
1378 [ - + ]: 260 : assert (d->opoff1 % 8 + 4 <= 8);
1379 : 260 : byte >>= 8 - (d->opoff1 % 8 + 3);
1380 : :
1381 [ + - ]: 260 : if ((byte & 7) >= 6)
1382 : : return -1;
1383 : :
1384 : 260 : size_t *bufcntp = d->bufcntp;
1385 : 260 : char *bufp = d->bufp;
1386 [ - + ]: 260 : if (*bufcntp + 3 > d->bufsize)
1387 : 0 : return *bufcntp + 3 - d->bufsize;
1388 : :
1389 : 260 : bufp[(*bufcntp)++] = '%';
1390 : 260 : bufp[(*bufcntp)++] = "ecsdfg"[byte & 7];
1391 : 260 : bufp[(*bufcntp)++] = 's';
1392 : :
1393 : 260 : return 0;
1394 : : }
1395 : :
1396 : :
1397 : : static int
1398 : 1424 : FCT_string (struct output_data *d __attribute__ ((unused)))
1399 : : {
1400 : 1424 : return 0;
1401 : : }
1402 : :
1403 : :
1404 : : static int
1405 : 11424 : FCT_xmmreg (struct output_data *d)
1406 : : {
1407 : 11424 : uint_fast8_t byte = d->data[d->opoff1 / 8];
1408 [ - + ]: 11424 : assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
1409 : 11424 : byte = (byte >> (5 - d->opoff1 % 8)) & 7;
1410 : :
1411 : 11424 : size_t *bufcntp = d->bufcntp;
1412 : 11424 : size_t avail = d->bufsize - *bufcntp;
1413 [ - + ]: 11424 : int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, byte);
1414 [ - + ]: 11424 : if ((size_t) needed > avail)
1415 : 0 : return needed - avail;
1416 : 11424 : *bufcntp += needed;
1417 : 11424 : return 0;
1418 : : }
|