1 /* Helper routines for disassembler for x86/x86-64. 2 Copyright (C) 2007, 2008 Red Hat, Inc. 3 This file is part of Red Hat elfutils. 4 Written by Ulrich Drepper <drepper (at) redhat.com>, 2007. 5 6 Red Hat elfutils is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by the 8 Free Software Foundation; version 2 of the License. 9 10 Red Hat elfutils is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License along 16 with Red Hat elfutils; if not, write to the Free Software Foundation, 17 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 18 19 Red Hat elfutils is an included package of the Open Invention Network. 20 An included package of the Open Invention Network is a package for which 21 Open Invention Network licensees cross-license their patents. No patent 22 license is granted, either expressly or impliedly, by designation as an 23 included package. Should you wish to participate in the Open Invention 24 Network licensing program, please visit www.openinventionnetwork.com 25 <http://www.openinventionnetwork.com>. */ 26 27 #include <inttypes.h> 28 #include <stddef.h> 29 #include <stdio.h> 30 #include <stdint.h> 31 #include <libasm.h> 32 33 struct instr_enc 34 { 35 /* The mnemonic. Especially encoded for the optimized table. */ 36 unsigned int mnemonic : MNEMONIC_BITS; 37 38 /* The rep/repe prefixes. */ 39 unsigned int rep : 1; 40 unsigned int repe : 1; 41 42 /* Mnemonic suffix. */ 43 unsigned int suffix : SUFFIX_BITS; 44 45 /* Nonzero if the instruction uses modr/m. */ 46 unsigned int modrm : 1; 47 48 /* 1st parameter. */ 49 unsigned int fct1 : FCT1_BITS; 50 #ifdef STR1_BITS 51 unsigned int str1 : STR1_BITS; 52 #endif 53 unsigned int off1_1 : OFF1_1_BITS; 54 unsigned int off1_2 : OFF1_2_BITS; 55 unsigned int off1_3 : OFF1_3_BITS; 56 57 /* 2nd parameter. */ 58 unsigned int fct2 : FCT2_BITS; 59 #ifdef STR2_BITS 60 unsigned int str2 : STR2_BITS; 61 #endif 62 unsigned int off2_1 : OFF2_1_BITS; 63 unsigned int off2_2 : OFF2_2_BITS; 64 unsigned int off2_3 : OFF2_3_BITS; 65 66 /* 3rd parameter. */ 67 unsigned int fct3 : FCT3_BITS; 68 #ifdef STR3_BITS 69 unsigned int str3 : STR3_BITS; 70 #endif 71 unsigned int off3_1 : OFF3_1_BITS; 72 #ifdef OFF3_2_BITS 73 unsigned int off3_2 : OFF3_2_BITS; 74 #endif 75 #ifdef OFF3_3_BITS 76 unsigned int off3_3 : OFF3_3_BITS; 77 #endif 78 }; 79 80 81 typedef int (*opfct_t) (struct output_data *); 82 83 84 static int 85 data_prefix (struct output_data *d) 86 { 87 char ch = '\0'; 88 if (*d->prefixes & has_cs) 89 { 90 ch = 'c'; 91 *d->prefixes &= ~has_cs; 92 } 93 else if (*d->prefixes & has_ds) 94 { 95 ch = 'd'; 96 *d->prefixes &= ~has_ds; 97 } 98 else if (*d->prefixes & has_es) 99 { 100 ch = 'e'; 101 *d->prefixes &= ~has_es; 102 } 103 else if (*d->prefixes & has_fs) 104 { 105 ch = 'f'; 106 *d->prefixes &= ~has_fs; 107 } 108 else if (*d->prefixes & has_gs) 109 { 110 ch = 'g'; 111 *d->prefixes &= ~has_gs; 112 } 113 else if (*d->prefixes & has_ss) 114 { 115 ch = 's'; 116 *d->prefixes &= ~has_ss; 117 } 118 else 119 return 0; 120 121 if (*d->bufcntp + 4 > d->bufsize) 122 return *d->bufcntp + 4 - d->bufsize; 123 124 d->bufp[(*d->bufcntp)++] = '%'; 125 d->bufp[(*d->bufcntp)++] = ch; 126 d->bufp[(*d->bufcntp)++] = 's'; 127 d->bufp[(*d->bufcntp)++] = ':'; 128 129 return 0; 130 } 131 132 #ifdef X86_64 133 static const char hiregs[8][4] = 134 { 135 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 136 }; 137 static const char aregs[8][4] = 138 { 139 "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi" 140 }; 141 static const char dregs[8][4] = 142 { 143 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" 144 }; 145 #else 146 static const char aregs[8][4] = 147 { 148 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" 149 }; 150 # define dregs aregs 151 #endif 152 153 static int 154 general_mod$r_m (struct output_data *d) 155 { 156 int r = data_prefix (d); 157 if (r != 0) 158 return r; 159 160 int prefixes = *d->prefixes; 161 const uint8_t *data = &d->data[d->opoff1 / 8]; 162 char *bufp = d->bufp; 163 size_t *bufcntp = d->bufcntp; 164 size_t bufsize = d->bufsize; 165 166 uint_fast8_t modrm = data[0]; 167 #ifndef X86_64 168 if (unlikely ((prefixes & has_addr16) != 0)) 169 { 170 int16_t disp = 0; 171 bool nodisp = false; 172 173 if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80) 174 /* 16 bit displacement. */ 175 disp = read_2sbyte_unaligned (&data[1]); 176 else if ((modrm & 0xc0) == 0x40) 177 /* 8 bit displacement. */ 178 disp = *(const int8_t *) &data[1]; 179 else if ((modrm & 0xc0) == 0) 180 nodisp = true; 181 182 char tmpbuf[sizeof ("-0x1234(%rr,%rr)")]; 183 int n; 184 if ((modrm & 0xc7) == 6) 185 n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx16, disp); 186 else 187 { 188 n = 0; 189 if (!nodisp) 190 n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx16, 191 disp < 0 ? "-" : "", disp < 0 ? -disp : disp); 192 193 if ((modrm & 0x4) == 0) 194 n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%b%c,%%%ci)", 195 "xp"[(modrm >> 1) & 1], "sd"[modrm & 1]); 196 else 197 n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%%s)", 198 ((const char [4][3]) { "si", "di", "bp", "bx" })[modrm & 3]); 199 } 200 201 if (*bufcntp + n + 1 > bufsize) 202 return *bufcntp + n + 1 - bufsize; 203 204 memcpy (&bufp[*bufcntp], tmpbuf, n + 1); 205 *bufcntp += n; 206 } 207 else 208 #endif 209 { 210 if ((modrm & 7) != 4) 211 { 212 int32_t disp = 0; 213 bool nodisp = false; 214 215 if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80) 216 /* 32 bit displacement. */ 217 disp = read_4sbyte_unaligned (&data[1]); 218 else if ((modrm & 0xc0) == 0x40) 219 /* 8 bit displacement. */ 220 disp = *(const int8_t *) &data[1]; 221 else if ((modrm & 0xc0) == 0) 222 nodisp = true; 223 224 char tmpbuf[sizeof ("-0x12345678(%rrrr)")]; 225 int n; 226 if (nodisp) 227 { 228 n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)", 229 #ifdef X86_64 230 (prefixes & has_rex_b) ? hiregs[modrm & 7] : 231 #endif 232 aregs[modrm & 7]); 233 #ifdef X86_64 234 if (prefixes & has_addr16) 235 { 236 if (prefixes & has_rex_b) 237 tmpbuf[n++] = 'd'; 238 else 239 tmpbuf[2] = 'e'; 240 } 241 #endif 242 } 243 else if ((modrm & 0xc7) != 5) 244 { 245 int p; 246 n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%n%s)", 247 disp < 0 ? "-" : "", disp < 0 ? -disp : disp, &p, 248 #ifdef X86_64 249 (prefixes & has_rex_b) ? hiregs[modrm & 7] : 250 #endif 251 aregs[modrm & 7]); 252 #ifdef X86_64 253 if (prefixes & has_addr16) 254 { 255 if (prefixes & has_rex_b) 256 tmpbuf[n++] = 'd'; 257 else 258 tmpbuf[p] = 'e'; 259 } 260 #endif 261 } 262 else 263 { 264 #ifdef X86_64 265 n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%rip)", 266 disp < 0 ? "-" : "", disp < 0 ? -disp : disp); 267 268 d->symaddr_use = addr_rel_always; 269 d->symaddr = disp; 270 #else 271 n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp); 272 #endif 273 } 274 275 if (*bufcntp + n + 1 > bufsize) 276 return *bufcntp + n + 1 - bufsize; 277 278 memcpy (&bufp[*bufcntp], tmpbuf, n + 1); 279 *bufcntp += n; 280 } 281 else 282 { 283 /* SIB */ 284 uint_fast8_t sib = data[1]; 285 int32_t disp = 0; 286 bool nodisp = false; 287 288 if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80 289 || ((modrm & 0xc7) == 0x4 && (sib & 0x7) == 0x5)) 290 /* 32 bit displacement. */ 291 disp = read_4sbyte_unaligned (&data[2]); 292 else if ((modrm & 0xc0) == 0x40) 293 /* 8 bit displacement. */ 294 disp = *(const int8_t *) &data[2]; 295 else 296 nodisp = true; 297 298 char tmpbuf[sizeof ("-0x12345678(%rrrr,%rrrr,N)")]; 299 char *cp = tmpbuf; 300 int n; 301 if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25 302 #ifdef X86_64 303 || (prefixes & has_rex_x) != 0 304 #endif 305 ) 306 { 307 if (!nodisp) 308 { 309 n = snprintf (cp, sizeof (tmpbuf), "%s0x%" PRIx32, 310 disp < 0 ? "-" : "", disp < 0 ? -disp : disp); 311 cp += n; 312 } 313 314 *cp++ = '('; 315 316 if ((modrm & 0xc7) != 0x4 || (sib & 0x7) != 0x5) 317 { 318 *cp++ = '%'; 319 cp = stpcpy (cp, 320 #ifdef X86_64 321 (prefixes & has_rex_b) ? hiregs[sib & 7] : 322 (prefixes & has_addr16) ? dregs[sib & 7] : 323 #endif 324 aregs[sib & 7]); 325 #ifdef X86_64 326 if ((prefixes & (has_rex_b | has_addr16)) 327 == (has_rex_b | has_addr16)) 328 *cp++ = 'd'; 329 #endif 330 } 331 332 if ((sib & 0x38) != 0x20 333 #ifdef X86_64 334 || (prefixes & has_rex_x) != 0 335 #endif 336 ) 337 { 338 *cp++ = ','; 339 *cp++ = '%'; 340 cp = stpcpy (cp, 341 #ifdef X86_64 342 (prefixes & has_rex_x) 343 ? hiregs[(sib >> 3) & 7] : 344 (prefixes & has_addr16) 345 ? dregs[(sib >> 3) & 7] : 346 #endif 347 aregs[(sib >> 3) & 7]); 348 #ifdef X86_64 349 if ((prefixes & (has_rex_b | has_addr16)) 350 == (has_rex_b | has_addr16)) 351 *cp++ = 'd'; 352 #endif 353 354 *cp++ = ','; 355 *cp++ = '0' + (1 << (sib >> 6)); 356 } 357 358 *cp++ = ')'; 359 } 360 else 361 { 362 assert (! nodisp); 363 #ifdef X86_64 364 if ((prefixes & has_addr16) == 0) 365 n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx64, 366 (int64_t) disp); 367 else 368 #endif 369 n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx32, disp); 370 cp += n; 371 } 372 373 if (*bufcntp + (cp - tmpbuf) > bufsize) 374 return *bufcntp + (cp - tmpbuf) - bufsize; 375 376 memcpy (&bufp[*bufcntp], tmpbuf, cp - tmpbuf); 377 *bufcntp += cp - tmpbuf; 378 } 379 } 380 return 0; 381 } 382 383 384 static int 385 FCT_MOD$R_M (struct output_data *d) 386 { 387 assert (d->opoff1 % 8 == 0); 388 uint_fast8_t modrm = d->data[d->opoff1 / 8]; 389 if ((modrm & 0xc0) == 0xc0) 390 { 391 assert (d->opoff1 / 8 == d->opoff2 / 8); 392 assert (d->opoff2 % 8 == 5); 393 //uint_fast8_t byte = d->data[d->opoff2 / 8] & 7; 394 uint_fast8_t byte = modrm & 7; 395 396 size_t *bufcntp = d->bufcntp; 397 char *buf = d->bufp + *bufcntp; 398 size_t avail = d->bufsize - *bufcntp; 399 int needed; 400 if (*d->prefixes & (has_rep | has_repne)) 401 needed = snprintf (buf, avail, "%%%s", dregs[byte]); 402 else 403 needed = snprintf (buf, avail, "%%mm%" PRIxFAST8, byte); 404 if ((size_t) needed > avail) 405 return needed - avail; 406 *bufcntp += needed; 407 return 0; 408 } 409 410 return general_mod$r_m (d); 411 } 412 413 414 static int 415 FCT_Mod$R_m (struct output_data *d) 416 { 417 assert (d->opoff1 % 8 == 0); 418 uint_fast8_t modrm = d->data[d->opoff1 / 8]; 419 if ((modrm & 0xc0) == 0xc0) 420 { 421 assert (d->opoff1 / 8 == d->opoff2 / 8); 422 assert (d->opoff2 % 8 == 5); 423 //uint_fast8_t byte = data[opoff2 / 8] & 7; 424 uint_fast8_t byte = modrm & 7; 425 426 size_t *bufcntp = d->bufcntp; 427 size_t avail = d->bufsize - *bufcntp; 428 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, 429 byte); 430 if ((size_t) needed > avail) 431 return needed - avail; 432 *d->bufcntp += needed; 433 return 0; 434 } 435 436 return general_mod$r_m (d); 437 } 438 439 static int 440 generic_abs (struct output_data *d, const char *absstring 441 #ifdef X86_64 442 , int abslen 443 #else 444 # define abslen 4 445 #endif 446 ) 447 { 448 int r = data_prefix (d); 449 if (r != 0) 450 return r; 451 452 assert (d->opoff1 % 8 == 0); 453 assert (d->opoff1 / 8 == 1); 454 if (*d->param_start + abslen > d->end) 455 return -1; 456 *d->param_start += abslen; 457 #ifndef X86_64 458 uint32_t absval; 459 # define ABSPRIFMT PRIx32 460 #else 461 uint64_t absval; 462 # define ABSPRIFMT PRIx64 463 if (abslen == 8) 464 absval = read_8ubyte_unaligned (&d->data[1]); 465 else 466 #endif 467 absval = read_4ubyte_unaligned (&d->data[1]); 468 size_t *bufcntp = d->bufcntp; 469 size_t avail = d->bufsize - *bufcntp; 470 int needed = snprintf (&d->bufp[*bufcntp], avail, "%s0x%" ABSPRIFMT, 471 absstring, absval); 472 if ((size_t) needed > avail) 473 return needed - avail; 474 *bufcntp += needed; 475 return 0; 476 } 477 478 479 static int 480 FCT_absval (struct output_data *d) 481 { 482 return generic_abs (d, "$" 483 #ifdef X86_64 484 , 4 485 #endif 486 ); 487 } 488 489 static int 490 FCT_abs (struct output_data *d) 491 { 492 return generic_abs (d, "" 493 #ifdef X86_64 494 , 8 495 #endif 496 ); 497 } 498 499 static int 500 FCT_ax (struct output_data *d) 501 { 502 int is_16bit = (*d->prefixes & has_data16) != 0; 503 504 size_t *bufcntp = d->bufcntp; 505 char *bufp = d->bufp; 506 size_t bufsize = d->bufsize; 507 508 if (*bufcntp + 4 - is_16bit > bufsize) 509 return *bufcntp + 4 - is_16bit - bufsize; 510 511 bufp[(*bufcntp)++] = '%'; 512 if (! is_16bit) 513 bufp[(*bufcntp)++] = ( 514 #ifdef X86_64 515 (*d->prefixes & has_rex_w) ? 'r' : 516 #endif 517 'e'); 518 bufp[(*bufcntp)++] = 'a'; 519 bufp[(*bufcntp)++] = 'x'; 520 521 return 0; 522 } 523 524 525 static int 526 FCT_ax$w (struct output_data *d) 527 { 528 if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0) 529 return FCT_ax (d); 530 531 size_t *bufcntp = d->bufcntp; 532 char *bufp = d->bufp; 533 size_t bufsize = d->bufsize; 534 535 if (*bufcntp + 3 > bufsize) 536 return *bufcntp + 3 - bufsize; 537 538 bufp[(*bufcntp)++] = '%'; 539 bufp[(*bufcntp)++] = 'a'; 540 bufp[(*bufcntp)++] = 'l'; 541 542 return 0; 543 } 544 545 546 static int 547 __attribute__ ((noinline)) 548 FCT_crdb (struct output_data *d, const char *regstr) 549 { 550 if (*d->prefixes & has_data16) 551 return -1; 552 553 size_t *bufcntp = d->bufcntp; 554 555 // XXX If this assert is true, use absolute offset below 556 assert (d->opoff1 / 8 == 2); 557 assert (d->opoff1 % 8 == 2); 558 size_t avail = d->bufsize - *bufcntp; 559 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%%s%" PRIx32, 560 regstr, (uint32_t) (d->data[d->opoff1 / 8] >> 3) & 7); 561 if ((size_t) needed > avail) 562 return needed - avail; 563 *bufcntp += needed; 564 return 0; 565 } 566 567 568 static int 569 FCT_ccc (struct output_data *d) 570 { 571 return FCT_crdb (d, "cr"); 572 } 573 574 575 static int 576 FCT_ddd (struct output_data *d) 577 { 578 return FCT_crdb (d, "db"); 579 } 580 581 582 static int 583 FCT_disp8 (struct output_data *d) 584 { 585 assert (d->opoff1 % 8 == 0); 586 if (*d->param_start >= d->end) 587 return -1; 588 int32_t offset = *(const int8_t *) (*d->param_start)++; 589 590 size_t *bufcntp = d->bufcntp; 591 size_t avail = d->bufsize - *bufcntp; 592 int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32, 593 (uint32_t) (d->addr + (*d->param_start - d->data) 594 + offset)); 595 if ((size_t) needed > avail) 596 return needed - avail; 597 *bufcntp += needed; 598 return 0; 599 } 600 601 602 static int 603 __attribute__ ((noinline)) 604 FCT_ds_xx (struct output_data *d, const char *reg) 605 { 606 int prefix = *d->prefixes & SEGMENT_PREFIXES; 607 608 if (prefix == 0) 609 *d->prefixes |= prefix = has_ds; 610 /* Make sure only one bit is set. */ 611 else if ((prefix - 1) & prefix) 612 return -1; 613 614 int r = data_prefix (d); 615 616 assert ((*d->prefixes & prefix) == 0); 617 618 if (r != 0) 619 return r; 620 621 size_t *bufcntp = d->bufcntp; 622 size_t avail = d->bufsize - *bufcntp; 623 int needed = snprintf (&d->bufp[*bufcntp], avail, "(%%%s%s)", 624 #ifdef X86_64 625 *d->prefixes & idx_addr16 ? "e" : "r", 626 #else 627 *d->prefixes & idx_addr16 ? "" : "e", 628 #endif 629 reg); 630 if ((size_t) needed > avail) 631 return (size_t) needed - avail; 632 *bufcntp += needed; 633 634 return 0; 635 } 636 637 638 static int 639 FCT_ds_bx (struct output_data *d) 640 { 641 return FCT_ds_xx (d, "bx"); 642 } 643 644 645 static int 646 FCT_ds_si (struct output_data *d) 647 { 648 return FCT_ds_xx (d, "si"); 649 } 650 651 652 static int 653 FCT_dx (struct output_data *d) 654 { 655 size_t *bufcntp = d->bufcntp; 656 657 if (*bufcntp + 7 > d->bufsize) 658 return *bufcntp + 7 - d->bufsize; 659 660 memcpy (&d->bufp[*bufcntp], "(%dx)", 5); 661 *bufcntp += 5; 662 663 return 0; 664 } 665 666 667 static int 668 FCT_es_di (struct output_data *d) 669 { 670 size_t *bufcntp = d->bufcntp; 671 size_t avail = d->bufsize - *bufcntp; 672 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%es:(%%%sdi)", 673 #ifdef X86_64 674 *d->prefixes & idx_addr16 ? "e" : "r" 675 #else 676 *d->prefixes & idx_addr16 ? "" : "e" 677 #endif 678 ); 679 if ((size_t) needed > avail) 680 return (size_t) needed - avail; 681 *bufcntp += needed; 682 683 return 0; 684 } 685 686 687 static int 688 FCT_imm (struct output_data *d) 689 { 690 size_t *bufcntp = d->bufcntp; 691 size_t avail = d->bufsize - *bufcntp; 692 int needed; 693 if (*d->prefixes & has_data16) 694 { 695 if (*d->param_start + 2 > d->end) 696 return -1; 697 uint16_t word = read_2ubyte_unaligned_inc (*d->param_start); 698 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word); 699 } 700 else 701 { 702 if (*d->param_start + 4 > d->end) 703 return -1; 704 int32_t word = read_4sbyte_unaligned_inc (*d->param_start); 705 #ifdef X86_64 706 if (*d->prefixes & has_rex_w) 707 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, 708 (int64_t) word); 709 else 710 #endif 711 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word); 712 } 713 if ((size_t) needed > avail) 714 return (size_t) needed - avail; 715 *bufcntp += needed; 716 return 0; 717 } 718 719 720 static int 721 FCT_imm$w (struct output_data *d) 722 { 723 if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0) 724 return FCT_imm (d); 725 726 size_t *bufcntp = d->bufcntp; 727 size_t avail = d->bufsize - *bufcntp; 728 if (*d->param_start>= d->end) 729 return -1; 730 uint_fast8_t word = *(*d->param_start)++; 731 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIxFAST8, word); 732 if ((size_t) needed > avail) 733 return (size_t) needed - avail; 734 *bufcntp += needed; 735 return 0; 736 } 737 738 739 #ifdef X86_64 740 static int 741 FCT_imm64$w (struct output_data *d) 742 { 743 if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) == 0 744 || (*d->prefixes & has_data16) != 0) 745 return FCT_imm$w (d); 746 747 size_t *bufcntp = d->bufcntp; 748 size_t avail = d->bufsize - *bufcntp; 749 int needed; 750 if (*d->prefixes & has_rex_w) 751 { 752 if (*d->param_start + 8 > d->end) 753 return -1; 754 uint64_t word = read_8ubyte_unaligned_inc (*d->param_start); 755 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, word); 756 } 757 else 758 { 759 if (*d->param_start + 4 > d->end) 760 return -1; 761 int32_t word = read_4sbyte_unaligned_inc (*d->param_start); 762 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word); 763 } 764 if ((size_t) needed > avail) 765 return (size_t) needed - avail; 766 *bufcntp += needed; 767 return 0; 768 } 769 #endif 770 771 772 static int 773 FCT_imms (struct output_data *d) 774 { 775 size_t *bufcntp = d->bufcntp; 776 size_t avail = d->bufsize - *bufcntp; 777 if (*d->param_start>= d->end) 778 return -1; 779 int8_t byte = *(*d->param_start)++; 780 #ifdef X86_64 781 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, 782 (int64_t) byte); 783 #else 784 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, 785 (int32_t) byte); 786 #endif 787 if ((size_t) needed > avail) 788 return (size_t) needed - avail; 789 *bufcntp += needed; 790 return 0; 791 } 792 793 794 static int 795 FCT_imm$s (struct output_data *d) 796 { 797 uint_fast8_t opcode = d->data[d->opoff2 / 8]; 798 size_t *bufcntp = d->bufcntp; 799 size_t avail = d->bufsize - *bufcntp; 800 if ((opcode & 2) != 0) 801 return FCT_imms (d); 802 803 if ((*d->prefixes & has_data16) == 0) 804 { 805 if (*d->param_start + 4 > d->end) 806 return -1; 807 int32_t word = read_4sbyte_unaligned_inc (*d->param_start); 808 #ifdef X86_64 809 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, 810 (int64_t) word); 811 #else 812 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word); 813 #endif 814 if ((size_t) needed > avail) 815 return (size_t) needed - avail; 816 *bufcntp += needed; 817 } 818 else 819 { 820 if (*d->param_start + 2 > d->end) 821 return -1; 822 uint16_t word = read_2ubyte_unaligned_inc (*d->param_start); 823 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word); 824 if ((size_t) needed > avail) 825 return (size_t) needed - avail; 826 *bufcntp += needed; 827 } 828 return 0; 829 } 830 831 832 static int 833 FCT_imm16 (struct output_data *d) 834 { 835 if (*d->param_start + 2 > d->end) 836 return -1; 837 uint16_t word = read_2ubyte_unaligned_inc (*d->param_start); 838 size_t *bufcntp = d->bufcntp; 839 size_t avail = d->bufsize - *bufcntp; 840 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word); 841 if ((size_t) needed > avail) 842 return (size_t) needed - avail; 843 *bufcntp += needed; 844 return 0; 845 } 846 847 848 static int 849 FCT_imms8 (struct output_data *d) 850 { 851 size_t *bufcntp = d->bufcntp; 852 size_t avail = d->bufsize - *bufcntp; 853 if (*d->param_start >= d->end) 854 return -1; 855 int_fast8_t byte = *(*d->param_start)++; 856 int needed; 857 #ifdef X86_64 858 if (*d->prefixes & has_rex_w) 859 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, 860 (int64_t) byte); 861 else 862 #endif 863 needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, 864 (int32_t) byte); 865 if ((size_t) needed > avail) 866 return (size_t) needed - avail; 867 *bufcntp += needed; 868 return 0; 869 } 870 871 872 static int 873 FCT_imm8 (struct output_data *d) 874 { 875 size_t *bufcntp = d->bufcntp; 876 size_t avail = d->bufsize - *bufcntp; 877 if (*d->param_start >= d->end) 878 return -1; 879 uint_fast8_t byte = *(*d->param_start)++; 880 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, 881 (uint32_t) byte); 882 if ((size_t) needed > avail) 883 return (size_t) needed - avail; 884 *bufcntp += needed; 885 return 0; 886 } 887 888 889 static int 890 FCT_rel (struct output_data *d) 891 { 892 size_t *bufcntp = d->bufcntp; 893 size_t avail = d->bufsize - *bufcntp; 894 if (*d->param_start + 4 > d->end) 895 return -1; 896 int32_t rel = read_4sbyte_unaligned_inc (*d->param_start); 897 #ifdef X86_64 898 int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx64, 899 (uint64_t) (d->addr + rel 900 + (*d->param_start - d->data))); 901 #else 902 int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32, 903 (uint32_t) (d->addr + rel 904 + (*d->param_start - d->data))); 905 #endif 906 if ((size_t) needed > avail) 907 return (size_t) needed - avail; 908 *bufcntp += needed; 909 return 0; 910 } 911 912 913 static int 914 FCT_mmxreg (struct output_data *d) 915 { 916 uint_fast8_t byte = d->data[d->opoff1 / 8]; 917 assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5); 918 byte = (byte >> (5 - d->opoff1 % 8)) & 7; 919 size_t *bufcntp = d->bufcntp; 920 size_t avail = d->bufsize - *bufcntp; 921 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte); 922 if ((size_t) needed > avail) 923 return needed - avail; 924 *bufcntp += needed; 925 return 0; 926 } 927 928 929 static int 930 FCT_mod$r_m (struct output_data *d) 931 { 932 assert (d->opoff1 % 8 == 0); 933 uint_fast8_t modrm = d->data[d->opoff1 / 8]; 934 if ((modrm & 0xc0) == 0xc0) 935 { 936 int prefixes = *d->prefixes; 937 if (prefixes & has_addr16) 938 return -1; 939 940 int is_16bit = (prefixes & has_data16) != 0; 941 942 size_t *bufcntp = d->bufcntp; 943 char *bufp = d->bufp; 944 if (*bufcntp + 5 - is_16bit > d->bufsize) 945 return *bufcntp + 5 - is_16bit - d->bufsize; 946 bufp[(*bufcntp)++] = '%'; 947 948 char *cp; 949 #ifdef X86_64 950 if ((prefixes & has_rex_b) != 0 && !is_16bit) 951 { 952 cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]); 953 if ((prefixes & has_rex_w) == 0) 954 *cp++ = 'd'; 955 } 956 else 957 #endif 958 { 959 cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit); 960 #ifdef X86_64 961 if ((prefixes & has_rex_w) != 0) 962 bufp[*bufcntp] = 'r'; 963 #endif 964 } 965 *bufcntp = cp - bufp; 966 return 0; 967 } 968 969 return general_mod$r_m (d); 970 } 971 972 973 #ifndef X86_64 974 static int 975 FCT_moda$r_m (struct output_data *d) 976 { 977 assert (d->opoff1 % 8 == 0); 978 uint_fast8_t modrm = d->data[d->opoff1 / 8]; 979 if ((modrm & 0xc0) == 0xc0) 980 { 981 if (*d->prefixes & has_addr16) 982 return -1; 983 984 size_t *bufcntp = d->bufcntp; 985 if (*bufcntp + 3 > d->bufsize) 986 return *bufcntp + 3 - d->bufsize; 987 988 memcpy (&d->bufp[*bufcntp], "???", 3); 989 *bufcntp += 3; 990 991 return 0; 992 } 993 994 return general_mod$r_m (d); 995 } 996 #endif 997 998 999 #ifdef X86_64 1000 static const char rex_8bit[8][3] = 1001 { 1002 [0] = "a", [1] = "c", [2] = "d", [3] = "b", 1003 [4] = "sp", [5] = "bp", [6] = "si", [7] = "di" 1004 }; 1005 #endif 1006 1007 1008 static int 1009 FCT_mod$r_m$w (struct output_data *d) 1010 { 1011 assert (d->opoff1 % 8 == 0); 1012 const uint8_t *data = d->data; 1013 uint_fast8_t modrm = data[d->opoff1 / 8]; 1014 if ((modrm & 0xc0) == 0xc0) 1015 { 1016 int prefixes = *d->prefixes; 1017 1018 if (prefixes & has_addr16) 1019 return -1; 1020 1021 size_t *bufcntp = d->bufcntp; 1022 char *bufp = d->bufp; 1023 if (*bufcntp + 5 > d->bufsize) 1024 return *bufcntp + 5 - d->bufsize; 1025 1026 if ((data[d->opoff3 / 8] & (1 << (7 - (d->opoff3 & 7)))) == 0) 1027 { 1028 bufp[(*bufcntp)++] = '%'; 1029 1030 #ifdef X86_64 1031 if (prefixes & has_rex) 1032 { 1033 if (prefixes & has_rex_r) 1034 *bufcntp += snprintf (bufp + *bufcntp, d->bufsize - *bufcntp, 1035 "r%db", 8 + (modrm & 7)); 1036 else 1037 { 1038 char *cp = stpcpy (bufp + *bufcntp, hiregs[modrm & 7]); 1039 *cp++ = 'l'; 1040 *bufcntp = cp - bufp; 1041 } 1042 } 1043 else 1044 #endif 1045 { 1046 bufp[(*bufcntp)++] = "acdb"[modrm & 3]; 1047 bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2]; 1048 } 1049 } 1050 else 1051 { 1052 int is_16bit = (prefixes & has_data16) != 0; 1053 1054 bufp[(*bufcntp)++] = '%'; 1055 1056 char *cp; 1057 #ifdef X86_64 1058 if ((prefixes & has_rex_b) != 0 && !is_16bit) 1059 { 1060 cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]); 1061 if ((prefixes & has_rex_w) == 0) 1062 *cp++ = 'd'; 1063 } 1064 else 1065 #endif 1066 { 1067 cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit); 1068 #ifdef X86_64 1069 if ((prefixes & has_rex_w) != 0) 1070 bufp[*bufcntp] = 'r'; 1071 #endif 1072 } 1073 *bufcntp = cp - bufp; 1074 } 1075 return 0; 1076 } 1077 1078 return general_mod$r_m (d); 1079 } 1080 1081 1082 static int 1083 FCT_mod$8r_m (struct output_data *d) 1084 { 1085 assert (d->opoff1 % 8 == 0); 1086 uint_fast8_t modrm = d->data[d->opoff1 / 8]; 1087 if ((modrm & 0xc0) == 0xc0) 1088 { 1089 size_t *bufcntp = d->bufcntp; 1090 char *bufp = d->bufp; 1091 if (*bufcntp + 3 > d->bufsize) 1092 return *bufcntp + 3 - d->bufsize; 1093 bufp[(*bufcntp)++] = '%'; 1094 bufp[(*bufcntp)++] = "acdb"[modrm & 3]; 1095 bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2]; 1096 return 0; 1097 } 1098 1099 return general_mod$r_m (d); 1100 } 1101 1102 1103 static int 1104 FCT_mod$16r_m (struct output_data *d) 1105 { 1106 assert (d->opoff1 % 8 == 0); 1107 uint_fast8_t modrm = d->data[d->opoff1 / 8]; 1108 if ((modrm & 0xc0) == 0xc0) 1109 { 1110 assert (d->opoff1 / 8 == d->opoff2 / 8); 1111 //uint_fast8_t byte = data[opoff2 / 8] & 7; 1112 uint_fast8_t byte = modrm & 7; 1113 1114 size_t *bufcntp = d->bufcntp; 1115 if (*bufcntp + 3 > d->bufsize) 1116 return *bufcntp + 3 - d->bufsize; 1117 d->bufp[(*bufcntp)++] = '%'; 1118 memcpy (&d->bufp[*bufcntp], dregs[byte] + 1, sizeof (dregs[0]) - 1); 1119 *bufcntp += 2; 1120 return 0; 1121 } 1122 1123 return general_mod$r_m (d); 1124 } 1125 1126 1127 #ifdef X86_64 1128 static int 1129 FCT_mod$64r_m (struct output_data *d) 1130 { 1131 assert (d->opoff1 % 8 == 0); 1132 uint_fast8_t modrm = d->data[d->opoff1 / 8]; 1133 if ((modrm & 0xc0) == 0xc0) 1134 { 1135 assert (d->opoff1 / 8 == d->opoff2 / 8); 1136 //uint_fast8_t byte = data[opoff2 / 8] & 7; 1137 uint_fast8_t byte = modrm & 7; 1138 1139 size_t *bufcntp = d->bufcntp; 1140 if (*bufcntp + 4 > d->bufsize) 1141 return *bufcntp + 4 - d->bufsize; 1142 char *cp = &d->bufp[*bufcntp]; 1143 *cp++ = '%'; 1144 cp = stpcpy (cp, 1145 (*d->prefixes & has_rex_b) ? hiregs[byte] : aregs[byte]); 1146 *bufcntp = cp - d->bufp; 1147 return 0; 1148 } 1149 1150 return general_mod$r_m (d); 1151 } 1152 #else 1153 static typeof (FCT_mod$r_m) FCT_mod$64r_m __attribute__ ((alias ("FCT_mod$r_m"))); 1154 #endif 1155 1156 1157 static int 1158 FCT_reg (struct output_data *d) 1159 { 1160 uint_fast8_t byte = d->data[d->opoff1 / 8]; 1161 assert (d->opoff1 % 8 + 3 <= 8); 1162 byte >>= 8 - (d->opoff1 % 8 + 3); 1163 byte &= 7; 1164 int is_16bit = (*d->prefixes & has_data16) != 0; 1165 size_t *bufcntp = d->bufcntp; 1166 if (*bufcntp + 5 > d->bufsize) 1167 return *bufcntp + 5 - d->bufsize; 1168 d->bufp[(*bufcntp)++] = '%'; 1169 #ifdef X86_64 1170 if ((*d->prefixes & has_rex_r) != 0 && !is_16bit) 1171 { 1172 *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d", 1173 8 + byte); 1174 if ((*d->prefixes & has_rex_w) == 0) 1175 d->bufp[(*bufcntp)++] = 'd'; 1176 } 1177 else 1178 #endif 1179 { 1180 memcpy (&d->bufp[*bufcntp], dregs[byte] + is_16bit, 3 - is_16bit); 1181 #ifdef X86_64 1182 if ((*d->prefixes & has_rex_w) != 0 && !is_16bit) 1183 d->bufp[*bufcntp] = 'r'; 1184 #endif 1185 *bufcntp += 3 - is_16bit; 1186 } 1187 return 0; 1188 } 1189 1190 1191 #ifdef X86_64 1192 static int 1193 FCT_oreg (struct output_data *d) 1194 { 1195 /* Special form where register comes from opcode. The rex.B bit is used, 1196 rex.R and rex.X are ignored. */ 1197 int save_prefixes = *d->prefixes; 1198 1199 *d->prefixes = ((save_prefixes & ~has_rex_r) 1200 | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b))); 1201 1202 int r = FCT_reg (d); 1203 1204 *d->prefixes = save_prefixes; 1205 1206 return r; 1207 } 1208 #endif 1209 1210 1211 static int 1212 FCT_reg64 (struct output_data *d) 1213 { 1214 uint_fast8_t byte = d->data[d->opoff1 / 8]; 1215 assert (d->opoff1 % 8 + 3 <= 8); 1216 byte >>= 8 - (d->opoff1 % 8 + 3); 1217 byte &= 7; 1218 if ((*d->prefixes & has_data16) != 0) 1219 return -1; 1220 size_t *bufcntp = d->bufcntp; 1221 if (*bufcntp + 5 > d->bufsize) 1222 return *bufcntp + 5 - d->bufsize; 1223 d->bufp[(*bufcntp)++] = '%'; 1224 #ifdef X86_64 1225 if ((*d->prefixes & has_rex_r) != 0) 1226 { 1227 *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d", 1228 8 + byte); 1229 if ((*d->prefixes & has_rex_w) == 0) 1230 d->bufp[(*bufcntp)++] = 'd'; 1231 } 1232 else 1233 #endif 1234 { 1235 memcpy (&d->bufp[*bufcntp], aregs[byte], 3); 1236 *bufcntp += 3; 1237 } 1238 return 0; 1239 } 1240 1241 1242 static int 1243 FCT_reg$w (struct output_data *d) 1244 { 1245 if (d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) 1246 return FCT_reg (d); 1247 1248 uint_fast8_t byte = d->data[d->opoff1 / 8]; 1249 assert (d->opoff1 % 8 + 3 <= 8); 1250 byte >>= 8 - (d->opoff1 % 8 + 3); 1251 byte &= 7; 1252 1253 size_t *bufcntp = d->bufcntp; 1254 if (*bufcntp + 4 > d->bufsize) 1255 return *bufcntp + 4 - d->bufsize; 1256 1257 d->bufp[(*bufcntp)++] = '%'; 1258 1259 #ifdef X86_64 1260 if (*d->prefixes & has_rex) 1261 { 1262 if (*d->prefixes & has_rex_r) 1263 *bufcntp += snprintf (d->bufp + *bufcntp, d->bufsize - *bufcntp, 1264 "r%db", 8 + byte); 1265 else 1266 { 1267 char* cp = stpcpy (d->bufp + *bufcntp, rex_8bit[byte]); 1268 *cp++ = 'l'; 1269 *bufcntp = cp - d->bufp; 1270 } 1271 } 1272 else 1273 #endif 1274 { 1275 d->bufp[(*bufcntp)++] = "acdb"[byte & 3]; 1276 d->bufp[(*bufcntp)++] = "lh"[byte >> 2]; 1277 } 1278 return 0; 1279 } 1280 1281 1282 #ifdef X86_64 1283 static int 1284 FCT_oreg$w (struct output_data *d) 1285 { 1286 /* Special form where register comes from opcode. The rex.B bit is used, 1287 rex.R and rex.X are ignored. */ 1288 int save_prefixes = *d->prefixes; 1289 1290 *d->prefixes = ((save_prefixes & ~has_rex_r) 1291 | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b))); 1292 1293 int r = FCT_reg$w (d); 1294 1295 *d->prefixes = save_prefixes; 1296 1297 return r; 1298 } 1299 #endif 1300 1301 1302 static int 1303 FCT_freg (struct output_data *d) 1304 { 1305 assert (d->opoff1 / 8 == 1); 1306 assert (d->opoff1 % 8 == 5); 1307 size_t *bufcntp = d->bufcntp; 1308 size_t avail = d->bufsize - *bufcntp; 1309 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%st(%" PRIx32 ")", 1310 (uint32_t) (d->data[1] & 7)); 1311 if ((size_t) needed > avail) 1312 return (size_t) needed - avail; 1313 *bufcntp += needed; 1314 return 0; 1315 } 1316 1317 1318 #ifndef X86_64 1319 static int 1320 FCT_reg16 (struct output_data *d) 1321 { 1322 if (*d->prefixes & has_data16) 1323 return -1; 1324 1325 *d->prefixes |= has_data16; 1326 return FCT_reg (d); 1327 } 1328 #endif 1329 1330 1331 static int 1332 FCT_sel (struct output_data *d) 1333 { 1334 assert (d->opoff1 % 8 == 0); 1335 assert (d->opoff1 / 8 == 5); 1336 if (*d->param_start + 2 > d->end) 1337 return -1; 1338 *d->param_start += 2; 1339 uint16_t absval = read_2ubyte_unaligned (&d->data[5]); 1340 1341 size_t *bufcntp = d->bufcntp; 1342 size_t avail = d->bufsize - *bufcntp; 1343 int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, absval); 1344 if ((size_t) needed > avail) 1345 return needed - avail; 1346 *bufcntp += needed; 1347 return 0; 1348 } 1349 1350 1351 static int 1352 FCT_sreg2 (struct output_data *d) 1353 { 1354 uint_fast8_t byte = d->data[d->opoff1 / 8]; 1355 assert (d->opoff1 % 8 + 3 <= 8); 1356 byte >>= 8 - (d->opoff1 % 8 + 2); 1357 1358 size_t *bufcntp = d->bufcntp; 1359 char *bufp = d->bufp; 1360 if (*bufcntp + 3 > d->bufsize) 1361 return *bufcntp + 3 - d->bufsize; 1362 1363 bufp[(*bufcntp)++] = '%'; 1364 bufp[(*bufcntp)++] = "ecsd"[byte & 3]; 1365 bufp[(*bufcntp)++] = 's'; 1366 1367 return 0; 1368 } 1369 1370 1371 static int 1372 FCT_sreg3 (struct output_data *d) 1373 { 1374 uint_fast8_t byte = d->data[d->opoff1 / 8]; 1375 assert (d->opoff1 % 8 + 4 <= 8); 1376 byte >>= 8 - (d->opoff1 % 8 + 3); 1377 1378 if ((byte & 7) >= 6) 1379 return -1; 1380 1381 size_t *bufcntp = d->bufcntp; 1382 char *bufp = d->bufp; 1383 if (*bufcntp + 3 > d->bufsize) 1384 return *bufcntp + 3 - d->bufsize; 1385 1386 bufp[(*bufcntp)++] = '%'; 1387 bufp[(*bufcntp)++] = "ecsdfg"[byte & 7]; 1388 bufp[(*bufcntp)++] = 's'; 1389 1390 return 0; 1391 } 1392 1393 1394 static int 1395 FCT_string (struct output_data *d __attribute__ ((unused))) 1396 { 1397 return 0; 1398 } 1399 1400 1401 static int 1402 FCT_xmmreg (struct output_data *d) 1403 { 1404 uint_fast8_t byte = d->data[d->opoff1 / 8]; 1405 assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5); 1406 byte = (byte >> (5 - d->opoff1 % 8)) & 7; 1407 1408 size_t *bufcntp = d->bufcntp; 1409 size_t avail = d->bufsize - *bufcntp; 1410 int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, byte); 1411 if ((size_t) needed > avail) 1412 return needed - avail; 1413 *bufcntp += needed; 1414 return 0; 1415 } 1416