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