1 /* Copyright (C) 2007-2024 Free Software Foundation, Inc. 2 3 This file is part of the GNU opcodes library. 4 5 This library is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3, or (at your option) 8 any later version. 9 10 It is distributed in the hope that it will be useful, but WITHOUT 11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 13 License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 18 MA 02110-1301, USA. */ 19 20 #include "sysdep.h" 21 #include <stdbool.h> 22 #include <stdio.h> 23 #include <errno.h> 24 #include "getopt.h" 25 #include "libiberty.h" 26 #include "hashtab.h" 27 #include "safe-ctype.h" 28 29 #include "i386-opc.h" 30 31 /* Build-time checks are preferrable over runtime ones. Use this construct 32 in preference where possible. */ 33 #define static_assert(e) ((void)sizeof (struct { int _:1 - 2 * !(e); })) 34 35 static const char *program_name = NULL; 36 static int debug = 0; 37 38 typedef struct dependency 39 { 40 const char *name; 41 /* Note: Only direct dependencies should be enumerated. */ 42 const char *deps; 43 } dependency; 44 45 static const dependency isa_dependencies[] = 46 { 47 { "UNKNOWN", 48 "~IAMCU" }, 49 { "GENERIC32", 50 "386" }, 51 { "GENERIC64", 52 "PENTIUMPRO|Clflush|SYSCALL|MMX|SSE2|LM" }, 53 { "NONE", 54 "0" }, 55 { "PENTIUMPRO", 56 "686|Nop" }, 57 { "P2", 58 "PENTIUMPRO|MMX" }, 59 { "P3", 60 "P2|SSE" }, 61 { "P4", 62 "P3|Clflush|SSE2" }, 63 { "NOCONA", 64 "GENERIC64|FISTTP|SSE3|MONITOR|CX16" }, 65 { "CORE", 66 "P4|FISTTP|SSE3|MONITOR" }, 67 { "CORE2", 68 "NOCONA|SSSE3" }, 69 { "COREI7", 70 "CORE2|SSE4_2|Rdtscp|LAHF_SAHF" }, 71 { "K6", 72 "186|286|386|486|586|SYSCALL|387|MMX" }, 73 { "K6_2", 74 "K6|3dnow" }, 75 { "ATHLON", 76 "K6_2|686:min|687|Nop|3dnowA" }, 77 { "K8", 78 "ATHLON|Rdtscp|SSE2|LM" }, 79 { "AMDFAM10", 80 "K8|FISTTP|SSE4A|ABM|MONITOR" }, 81 { "BDVER1", 82 "GENERIC64|FISTTP|Rdtscp|MONITOR|CX16|LAHF_SAHF|XOP|ABM|LWP|SVME|AES|PCLMULQDQ|PRFCHW" }, 83 { "BDVER2", 84 "BDVER1|FMA|BMI|TBM|F16C" }, 85 { "BDVER3", 86 "BDVER2|Xsaveopt|FSGSBase" }, 87 { "BDVER4", 88 "BDVER3|AVX2|Movbe|BMI2|RdRnd|MWAITX" }, 89 { "ZNVER1", 90 "GENERIC64|FISTTP|Rdtscp|MONITOR|CX16|LAHF_SAHF|AVX2|SSE4A|ABM|SVME|AES|PCLMULQDQ|PRFCHW|FMA|BMI|F16C|Xsaveopt|FSGSBase|Movbe|BMI2|RdRnd|ADX|RdSeed|SMAP|SHA|XSAVEC|XSAVES|ClflushOpt|CLZERO|MWAITX" }, 91 { "ZNVER2", 92 "ZNVER1|CLWB|RDPID|RDPRU|MCOMMIT|WBNOINVD" }, 93 { "ZNVER3", 94 "ZNVER2|INVLPGB|TLBSYNC|VAES|VPCLMULQDQ|INVPCID|SNP|OSPKE" }, 95 { "ZNVER4", 96 "ZNVER3|AVX512F|AVX512DQ|AVX512IFMA|AVX512CD|AVX512BW|AVX512VL|AVX512_BF16|AVX512VBMI|AVX512_VBMI2|AVX512_VNNI|AVX512_BITALG|AVX512_VPOPCNTDQ|GFNI|RMPQUERY" }, 97 { "ZNVER5", 98 "ZNVER4|AVX_VNNI|MOVDIRI|MOVDIR64B|AVX512_VP2INTERSECT|PREFETCHI" }, 99 { "BTVER1", 100 "GENERIC64|FISTTP|MONITOR|CX16|LAHF_SAHF|Rdtscp|SSSE3|SSE4A|ABM|PRFCHW|Clflush|FISTTP|SVME" }, 101 { "BTVER2", 102 "BTVER1|AVX|BMI|F16C|AES|PCLMULQDQ|Movbe|Xsaveopt|PRFCHW" }, 103 { "286", 104 "186" }, 105 { "386", 106 "286" }, 107 { "486", 108 "386" }, 109 { "586", 110 "486|387" }, 111 { "586:nofpu", 112 "486" }, 113 { "686", 114 "586|687|CMOV|FXSR" }, 115 { "686:min", 116 "586|687" }, 117 { "687", 118 "387" }, 119 { "FISTTP", 120 "687" }, 121 { "SSE", 122 "FXSR" }, 123 { "SSE2", 124 "SSE" }, 125 { "SSE3", 126 "SSE2" }, 127 { "SSSE3", 128 "SSE3" }, 129 { "SSE4_1", 130 "SSSE3" }, 131 { "SSE4_2", 132 "SSE4_1|POPCNT" }, 133 { "Xsaveopt", 134 "XSAVE" }, 135 { "AES", 136 "SSE2" }, 137 { "PCLMULQDQ", 138 "SSE2" }, 139 { "FMA", 140 "AVX" }, 141 { "FMA4", 142 "AVX" }, 143 { "XOP", 144 "SSE4A|FMA4" }, 145 { "LWP", 146 "XSAVE" }, 147 { "F16C", 148 "AVX" }, 149 { "3dnow", 150 "MMX" }, 151 { "3dnowA", 152 "3dnow" }, 153 { "SSE4a", 154 "SSE3" }, 155 { "ABM", 156 "LZCNT|POPCNT" }, 157 { "AVX", 158 "SSE4_2|XSAVE" }, 159 { "AVX2", 160 "AVX" }, 161 { "AVX_VNNI", 162 "AVX2" }, 163 { "AVX_IFMA", 164 "AVX2" }, 165 { "AVX_VNNI_INT8", 166 "AVX2" }, 167 { "AVX_VNNI_INT16", 168 "AVX2" }, 169 { "AVX_NE_CONVERT", 170 "AVX2" }, 171 { "CX16", 172 "64" }, 173 { "LKGS", 174 "64" }, 175 { "FRED", 176 "LKGS" }, 177 { "AVX512F", 178 "AVX2" }, 179 { "AVX512CD", 180 "AVX512F" }, 181 { "AVX512ER", 182 "AVX512F" }, 183 { "AVX512PF", 184 "AVX512F" }, 185 { "AVX512DQ", 186 "AVX512F" }, 187 { "AVX512BW", 188 "AVX512F" }, 189 { "AVX512VL", 190 "AVX512F" }, 191 { "AVX512IFMA", 192 "AVX512F" }, 193 { "AVX512VBMI", 194 "AVX512BW" }, 195 { "AVX512_4FMAPS", 196 "AVX512F" }, 197 { "AVX512_4VNNIW", 198 "AVX512F" }, 199 { "AVX512_VPOPCNTDQ", 200 "AVX512F" }, 201 { "AVX512_VBMI2", 202 "AVX512BW" }, 203 { "AVX512_VNNI", 204 "AVX512F" }, 205 { "AVX512_BITALG", 206 "AVX512BW" }, 207 { "AVX512_VP2INTERSECT", 208 "AVX512F" }, 209 { "AVX512_BF16", 210 "AVX512BW" }, 211 { "AVX512_FP16", 212 "AVX512BW" }, 213 { "IAMCU", 214 "586:nofpu" }, 215 { "EPT", 216 "VMX" }, 217 { "VMFUNC", 218 "VMX" }, 219 { "MPX", 220 "XSAVE" }, 221 { "SHA", 222 "SSE2" }, 223 { "SHA512", 224 "AVX2" }, 225 { "SM3", 226 "AVX" }, 227 { "SM4", 228 "AVX2" }, 229 { "XSAVES", 230 "XSAVEC" }, 231 { "XSAVEC", 232 "XSAVE" }, 233 { "OSPKE", 234 "XSAVE" }, 235 { "GFNI", 236 "SSE2" }, 237 { "VAES", 238 "AVX2|AES" }, 239 { "VPCLMULQDQ", 240 "AVX2|PCLMULQDQ" }, 241 { "AVX10_1", 242 "AVX512VL|AVX512DQ|AVX512CD|AVX512VBMI|AVX512_VBMI2|AVX512IFMA" 243 "|AVX512_VNNI|AVX512_BF16|AVX512_FP16|AVX512_VPOPCNTDQ|AVX512_BITALG" }, 244 { "SEV_ES", 245 "SVME" }, 246 { "SNP", 247 "SEV_ES" }, 248 { "RMPQUERY", 249 "SNP|64" }, 250 { "TSX", 251 "RTM|HLE" }, 252 { "TSXLDTRK", 253 "RTM" }, 254 { "AMX_TILE", 255 "XSAVE|64" }, 256 { "AMX_INT8", 257 "AMX_TILE" }, 258 { "AMX_BF16", 259 "AMX_TILE" }, 260 { "AMX_FP16", 261 "AMX_TILE" }, 262 { "AMX_COMPLEX", 263 "AMX_TILE" }, 264 { "KL", 265 "SSE2" }, 266 { "WIDEKL", 267 "KL" }, 268 { "PBNDKB", 269 "64" }, 270 { "UINTR", 271 "64" }, 272 { "PREFETCHI", 273 "64" }, 274 { "CMPCCXADD", 275 "64" }, 276 { "MSRLIST", 277 "64" }, 278 { "USER_MSR", 279 "64" }, 280 { "APX_F", 281 "XSAVE|64" }, 282 }; 283 284 /* This array is populated as process_i386_initializers() walks cpu_flags[]. */ 285 static unsigned char isa_reverse_deps[CpuMax][CpuMax]; 286 287 typedef struct bitfield 288 { 289 int position; 290 int value; 291 const char *name; 292 } bitfield; 293 294 #define BITFIELD(n) { Cpu##n, 0, #n } 295 296 static bitfield cpu_flags[] = 297 { 298 BITFIELD (186), 299 BITFIELD (286), 300 BITFIELD (386), 301 BITFIELD (486), 302 BITFIELD (586), 303 BITFIELD (686), 304 BITFIELD (CMOV), 305 BITFIELD (FXSR), 306 BITFIELD (Clflush), 307 BITFIELD (Nop), 308 BITFIELD (SYSCALL), 309 BITFIELD (8087), 310 BITFIELD (287), 311 BITFIELD (387), 312 BITFIELD (687), 313 BITFIELD (FISTTP), 314 BITFIELD (MMX), 315 BITFIELD (SSE), 316 BITFIELD (SSE2), 317 BITFIELD (SSE3), 318 BITFIELD (SSSE3), 319 BITFIELD (SSE4_1), 320 BITFIELD (SSE4_2), 321 BITFIELD (AVX), 322 BITFIELD (AVX2), 323 BITFIELD (AVX512F), 324 BITFIELD (AVX512CD), 325 BITFIELD (AVX512ER), 326 BITFIELD (AVX512PF), 327 BITFIELD (AVX512VL), 328 BITFIELD (AVX512DQ), 329 BITFIELD (AVX512BW), 330 BITFIELD (IAMCU), 331 BITFIELD (SSE4a), 332 BITFIELD (3dnow), 333 BITFIELD (3dnowA), 334 BITFIELD (PadLock), 335 BITFIELD (SVME), 336 BITFIELD (VMX), 337 BITFIELD (SMX), 338 BITFIELD (Xsave), 339 BITFIELD (Xsaveopt), 340 BITFIELD (AES), 341 BITFIELD (PCLMULQDQ), 342 BITFIELD (FMA), 343 BITFIELD (FMA4), 344 BITFIELD (XOP), 345 BITFIELD (LWP), 346 BITFIELD (BMI), 347 BITFIELD (TBM), 348 BITFIELD (Movbe), 349 BITFIELD (CX16), 350 BITFIELD (LAHF_SAHF), 351 BITFIELD (EPT), 352 BITFIELD (Rdtscp), 353 BITFIELD (FSGSBase), 354 BITFIELD (RdRnd), 355 BITFIELD (F16C), 356 BITFIELD (BMI2), 357 BITFIELD (LZCNT), 358 BITFIELD (POPCNT), 359 BITFIELD (MONITOR), 360 BITFIELD (HLE), 361 BITFIELD (RTM), 362 BITFIELD (INVPCID), 363 BITFIELD (VMFUNC), 364 BITFIELD (RDSEED), 365 BITFIELD (ADX), 366 BITFIELD (PRFCHW), 367 BITFIELD (SMAP), 368 BITFIELD (SHA), 369 BITFIELD (SHA512), 370 BITFIELD (SM3), 371 BITFIELD (SM4), 372 BITFIELD (ClflushOpt), 373 BITFIELD (XSAVES), 374 BITFIELD (XSAVEC), 375 BITFIELD (PREFETCHWT1), 376 BITFIELD (SE1), 377 BITFIELD (CLWB), 378 BITFIELD (MPX), 379 BITFIELD (AVX512IFMA), 380 BITFIELD (AVX512VBMI), 381 BITFIELD (AVX512_4FMAPS), 382 BITFIELD (AVX512_4VNNIW), 383 BITFIELD (AVX512_VPOPCNTDQ), 384 BITFIELD (AVX512_VBMI2), 385 BITFIELD (AVX512_VNNI), 386 BITFIELD (AVX512_BITALG), 387 BITFIELD (AVX512_BF16), 388 BITFIELD (AVX512_VP2INTERSECT), 389 BITFIELD (TDX), 390 BITFIELD (AVX_VNNI), 391 BITFIELD (AVX512_FP16), 392 BITFIELD (PREFETCHI), 393 BITFIELD (AVX_IFMA), 394 BITFIELD (AVX_VNNI_INT8), 395 BITFIELD (AVX_VNNI_INT16), 396 BITFIELD (CMPCCXADD), 397 BITFIELD (WRMSRNS), 398 BITFIELD (MSRLIST), 399 BITFIELD (AVX_NE_CONVERT), 400 BITFIELD (RAO_INT), 401 BITFIELD (FRED), 402 BITFIELD (LKGS), 403 BITFIELD (USER_MSR), 404 BITFIELD (APX_F), 405 BITFIELD (MWAITX), 406 BITFIELD (CLZERO), 407 BITFIELD (OSPKE), 408 BITFIELD (RDPID), 409 BITFIELD (PTWRITE), 410 BITFIELD (IBT), 411 BITFIELD (SHSTK), 412 BITFIELD (GFNI), 413 BITFIELD (VAES), 414 BITFIELD (VPCLMULQDQ), 415 BITFIELD (WBNOINVD), 416 BITFIELD (PCONFIG), 417 BITFIELD (PBNDKB), 418 BITFIELD (WAITPKG), 419 BITFIELD (UINTR), 420 BITFIELD (CLDEMOTE), 421 BITFIELD (AMX_INT8), 422 BITFIELD (AMX_BF16), 423 BITFIELD (AMX_FP16), 424 BITFIELD (AMX_COMPLEX), 425 BITFIELD (AMX_TILE), 426 BITFIELD (MOVDIRI), 427 BITFIELD (MOVDIR64B), 428 BITFIELD (ENQCMD), 429 BITFIELD (SERIALIZE), 430 BITFIELD (RDPRU), 431 BITFIELD (MCOMMIT), 432 BITFIELD (SEV_ES), 433 BITFIELD (TSXLDTRK), 434 BITFIELD (KL), 435 BITFIELD (WideKL), 436 BITFIELD (HRESET), 437 BITFIELD (INVLPGB), 438 BITFIELD (TLBSYNC), 439 BITFIELD (SNP), 440 BITFIELD (RMPQUERY), 441 BITFIELD (64), 442 BITFIELD (No64), 443 #ifdef CpuUnused 444 BITFIELD (Unused), 445 #endif 446 }; 447 448 #undef BITFIELD 449 #define BITFIELD(n) { n, 0, #n } 450 451 static bitfield opcode_modifiers[] = 452 { 453 BITFIELD (D), 454 BITFIELD (W), 455 BITFIELD (Load), 456 BITFIELD (Modrm), 457 BITFIELD (Jump), 458 BITFIELD (FloatMF), 459 BITFIELD (Size), 460 BITFIELD (CheckOperandSize), 461 BITFIELD (OperandConstraint), 462 BITFIELD (MnemonicSize), 463 BITFIELD (No_bSuf), 464 BITFIELD (No_wSuf), 465 BITFIELD (No_lSuf), 466 BITFIELD (No_sSuf), 467 BITFIELD (No_qSuf), 468 BITFIELD (FWait), 469 BITFIELD (IsString), 470 BITFIELD (RegMem), 471 BITFIELD (BNDPrefixOk), 472 BITFIELD (PrefixOk), 473 BITFIELD (IsPrefix), 474 BITFIELD (ImmExt), 475 BITFIELD (NoRex64), 476 BITFIELD (Vex), 477 BITFIELD (VexVVVV), 478 BITFIELD (VexW), 479 BITFIELD (OpcodePrefix), 480 BITFIELD (SIB), 481 BITFIELD (SSE2AVX), 482 BITFIELD (EVex), 483 BITFIELD (Masking), 484 BITFIELD (Broadcast), 485 BITFIELD (StaticRounding), 486 BITFIELD (SAE), 487 BITFIELD (Disp8MemShift), 488 BITFIELD (Optimize), 489 BITFIELD (Dialect), 490 BITFIELD (ISA64), 491 BITFIELD (NoEgpr), 492 BITFIELD (NF), 493 BITFIELD (Rex2), 494 BITFIELD (ZU), 495 }; 496 497 #define CLASS(n) #n, n 498 499 static const struct { 500 const char *name; 501 enum operand_class value; 502 } operand_classes[] = { 503 CLASS (Reg), 504 CLASS (SReg), 505 CLASS (RegCR), 506 CLASS (RegDR), 507 CLASS (RegTR), 508 CLASS (RegMMX), 509 CLASS (RegSIMD), 510 CLASS (RegMask), 511 CLASS (RegBND), 512 }; 513 514 #undef CLASS 515 516 #define INSTANCE(n) #n, n 517 518 static const struct { 519 const char *name; 520 enum operand_instance value; 521 } operand_instances[] = { 522 INSTANCE (Accum), 523 INSTANCE (RegC), 524 INSTANCE (RegD), 525 INSTANCE (RegB), 526 }; 527 528 #undef INSTANCE 529 530 static bitfield operand_types[] = 531 { 532 BITFIELD (Imm1), 533 BITFIELD (Imm8), 534 BITFIELD (Imm8S), 535 BITFIELD (Imm16), 536 BITFIELD (Imm32), 537 BITFIELD (Imm32S), 538 BITFIELD (Imm64), 539 BITFIELD (BaseIndex), 540 BITFIELD (Disp8), 541 BITFIELD (Disp16), 542 BITFIELD (Disp32), 543 BITFIELD (Disp64), 544 BITFIELD (Byte), 545 BITFIELD (Word), 546 BITFIELD (Dword), 547 BITFIELD (Fword), 548 BITFIELD (Qword), 549 BITFIELD (Tbyte), 550 BITFIELD (Xmmword), 551 BITFIELD (Ymmword), 552 BITFIELD (Zmmword), 553 BITFIELD (Tmmword), 554 BITFIELD (Unspecified), 555 #ifdef OTUnused 556 BITFIELD (OTUnused), 557 #endif 558 }; 559 560 static const char *filename; 561 static i386_cpu_flags active_cpu_flags; 562 static int active_isstring; 563 564 struct template_arg { 565 const struct template_arg *next; 566 const char *val; 567 }; 568 569 struct template_instance { 570 const struct template_instance *next; 571 const char *name; 572 const struct template_arg *args; 573 }; 574 575 struct template_param { 576 const struct template_param *next; 577 const char *name; 578 }; 579 580 struct template { 581 struct template *next; 582 const char *name; 583 const struct template_instance *instances; 584 const struct template_param *params; 585 }; 586 587 static struct template *templates; 588 589 static int 590 compare (const void *x, const void *y) 591 { 592 const bitfield *xp = (const bitfield *) x; 593 const bitfield *yp = (const bitfield *) y; 594 return xp->position - yp->position; 595 } 596 597 static void 598 fail (const char *message, ...) 599 { 600 va_list args; 601 602 va_start (args, message); 603 fprintf (stderr, "%s: error: ", program_name); 604 vfprintf (stderr, message, args); 605 va_end (args); 606 xexit (1); 607 } 608 609 static void 610 process_copyright (FILE *fp) 611 { 612 fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\ 613 /* Copyright (C) 2007-2024 Free Software Foundation, Inc.\n\ 614 \n\ 615 This file is part of the GNU opcodes library.\n\ 616 \n\ 617 This library is free software; you can redistribute it and/or modify\n\ 618 it under the terms of the GNU General Public License as published by\n\ 619 the Free Software Foundation; either version 3, or (at your option)\n\ 620 any later version.\n\ 621 \n\ 622 It is distributed in the hope that it will be useful, but WITHOUT\n\ 623 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\ 624 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\ 625 License for more details.\n\ 626 \n\ 627 You should have received a copy of the GNU General Public License\n\ 628 along with this program; if not, write to the Free Software\n\ 629 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\ 630 MA 02110-1301, USA. */\n"); 631 } 632 633 /* Remove leading white spaces. */ 634 635 static char * 636 remove_leading_whitespaces (char *str) 637 { 638 while (ISSPACE (*str)) 639 str++; 640 return str; 641 } 642 643 /* Remove trailing white spaces. */ 644 645 static void 646 remove_trailing_whitespaces (char *str) 647 { 648 size_t last = strlen (str); 649 650 if (last == 0) 651 return; 652 653 do 654 { 655 last--; 656 if (ISSPACE (str [last])) 657 str[last] = '\0'; 658 else 659 break; 660 } 661 while (last != 0); 662 } 663 664 /* Find next field separated by SEP and terminate it. Return a 665 pointer to the one after it. */ 666 667 static char * 668 next_field (char *str, char sep, char **next, char *last) 669 { 670 char *p; 671 672 p = remove_leading_whitespaces (str); 673 for (str = p; *str != sep && *str != '\0'; str++); 674 675 *str = '\0'; 676 remove_trailing_whitespaces (p); 677 678 *next = str + 1; 679 680 if (p >= last) 681 abort (); 682 683 return p; 684 } 685 686 static void set_bitfield (char *, bitfield *, int, unsigned int, int); 687 688 static void 689 set_bitfield (char *f, bitfield *array, int value, 690 unsigned int size, int lineno) 691 { 692 unsigned int i; 693 694 /* Ignore empty fields; they may result from template expansions. */ 695 if (*f == '\0') 696 return; 697 698 for (i = 0; i < size; i++) 699 if (strcasecmp (array[i].name, f) == 0) 700 { 701 array[i].value = value; 702 return; 703 } 704 705 if (value) 706 { 707 const char *v = strchr (f, '='); 708 709 if (v) 710 { 711 size_t n = v - f; 712 char *end; 713 714 for (i = 0; i < size; i++) 715 if (strncasecmp (array[i].name, f, n) == 0) 716 { 717 value = strtol (v + 1, &end, 0); 718 if (*end == '\0') 719 { 720 array[i].value = value; 721 return; 722 } 723 break; 724 } 725 } 726 } 727 728 if (lineno != -1) 729 fail ("%s: %d: unknown bitfield: %s\n", filename, lineno, f); 730 else 731 fail ("unknown bitfield: %s\n", f); 732 } 733 734 static void 735 add_isa_dependencies (bitfield *flags, const char *f, int value, 736 unsigned int reverse) 737 { 738 unsigned int i; 739 char *str = NULL; 740 const char *isa = f; 741 static bool is_avx; 742 bool is_isa = false, orig_is_avx = is_avx; 743 744 /* Need to find base entry for references to auxiliary ones. */ 745 if (strchr (f, ':')) 746 { 747 str = xstrdup (f); 748 *strchr (str, ':') = '\0'; 749 isa = str; 750 } 751 /* isa_dependencies[] prefers "LM" over "64". */ 752 else if (!strcmp (f, "LM")) 753 isa = "64"; 754 for (i = 0; i < CpuMax; ++i) 755 if (strcasecmp (flags[i].name, isa) == 0) 756 { 757 flags[i].value = value; 758 if (reverse < ARRAY_SIZE (isa_reverse_deps[0]) 759 /* Don't record the feature itself here. */ 760 && reverse != i 761 /* Don't record base architectures. */ 762 && reverse > Cpu686) 763 isa_reverse_deps[i][reverse] = 1; 764 is_isa = true; 765 if (i == CpuAVX || i == CpuXOP || i == CpuVAES || i == CpuVPCLMULQDQ) 766 is_avx = true; 767 break; 768 } 769 free (str); 770 771 /* Do not turn off dependencies. */ 772 if (is_isa && !value) 773 { 774 is_avx = orig_is_avx; 775 return; 776 } 777 778 for (i = 0; i < ARRAY_SIZE (isa_dependencies); ++i) 779 if (strcasecmp (isa_dependencies[i].name, f) == 0) 780 { 781 char *deps = xstrdup (isa_dependencies[i].deps); 782 char *next = deps; 783 char *last = deps + strlen (deps); 784 785 for (; next && next < last; ) 786 { 787 char *str = next_field (next, '|', &next, last); 788 789 /* No AVX/XOP -> SSE reverse dependencies. */ 790 if (is_avx && strncmp (str, "SSE", 3) == 0) 791 add_isa_dependencies (flags, str, value, CpuMax); 792 else 793 add_isa_dependencies (flags, str, value, reverse); 794 } 795 free (deps); 796 797 /* ISA extensions with dependencies need CPU_ANY_*_FLAGS emitted, 798 unless the sole dependency is the "64-bit mode only" one. */ 799 if (reverse < ARRAY_SIZE (isa_reverse_deps[0]) 800 && strcmp (isa_dependencies[i].deps, "64")) 801 isa_reverse_deps[reverse][reverse] = 1; 802 803 is_avx = orig_is_avx; 804 return; 805 } 806 807 if (!is_isa) 808 fail ("unknown bitfield: %s\n", f); 809 810 is_avx = orig_is_avx; 811 } 812 813 static void 814 output_cpu_flags (FILE *table, bitfield *flags, unsigned int size, 815 int mode, const char *comma, const char *indent, int lineno) 816 { 817 unsigned int i = 0, j = 0; 818 819 if (mode < 0) 820 memset (&active_cpu_flags, 0, sizeof(active_cpu_flags)); 821 822 fprintf (table, "%s{ { ", indent); 823 824 if (mode <= 0) 825 { 826 for (j = ~0u; i < CpuAttrEnums; i++) 827 { 828 if (!flags[i].value) 829 continue; 830 831 if (j < ~0u) 832 fail ("%s: %d: invalid combination of CPU identifiers\n", 833 filename, lineno); 834 j = i; 835 if (mode) 836 active_cpu_flags.array[i / 32] |= 1U << (i % 32); 837 } 838 839 /* Write 0 to indicate "no associated flag". */ 840 fprintf (table, "%u, ", j + 1); 841 842 j = 1; 843 } 844 845 for (; i < size - 1; i++, j++) 846 { 847 if (((j + 1) % 20) != 0) 848 fprintf (table, "%d, ", flags[i].value); 849 else 850 fprintf (table, "%d,", flags[i].value); 851 if (((j + 1) % 20) == 0) 852 { 853 /* We need \\ for macro. */ 854 if (mode > 0) 855 fprintf (table, " \\\n %s", indent); 856 else 857 fprintf (table, "\n %s", indent); 858 } 859 if (mode < 0 && flags[i].value) 860 active_cpu_flags.array[i / 32] |= 1U << (i % 32); 861 } 862 863 #if defined(CpuAttrUnused) != defined(CpuUnused) 864 if (mode <= 0) 865 # ifdef CpuUnused 866 fprintf (table, " } }%s\n", comma); 867 # else 868 fprintf (table, "%d, 0 } }%s\n", flags[i].value, comma); 869 # endif 870 else 871 #endif 872 fprintf (table, "%d } }%s\n", flags[i].value, comma); 873 } 874 875 static void 876 process_i386_cpu_flag (FILE *table, char *flag, 877 const char *name, 878 const char *comma, const char *indent, 879 int lineno, unsigned int reverse) 880 { 881 char *str, *next = flag, *last; 882 unsigned int i; 883 int value = 1; 884 bool is_isa = false; 885 bitfield all [ARRAY_SIZE (cpu_flags)]; 886 bitfield any [ARRAY_SIZE (cpu_flags)]; 887 888 /* Copy the default cpu flags. */ 889 memcpy (all, cpu_flags, sizeof (cpu_flags)); 890 memcpy (any, cpu_flags, sizeof (cpu_flags)); 891 892 if (flag == NULL) 893 { 894 for (i = 0; i < ARRAY_SIZE (isa_reverse_deps[0]); ++i) 895 any[i].value = isa_reverse_deps[reverse][i]; 896 goto output; 897 } 898 899 if (flag[0] == '~') 900 { 901 last = flag + strlen (flag); 902 903 if (flag[1] == '(') 904 { 905 last -= 1; 906 next = flag + 2; 907 if (*last != ')') 908 fail ("%s: %d: missing `)' in bitfield: %s\n", filename, 909 lineno, flag); 910 *last = '\0'; 911 } 912 else 913 next = flag + 1; 914 915 /* First we turn on everything except for cpuno64 and - if 916 present - the padding field. */ 917 for (i = 0; i < ARRAY_SIZE (any); i++) 918 if (any[i].position < CpuNo64) 919 any[i].value = 1; 920 921 /* Turn off selective bits. */ 922 value = 0; 923 } 924 925 if (name != NULL && value != 0) 926 { 927 for (i = 0; i < ARRAY_SIZE (any); i++) 928 if (strcasecmp (any[i].name, name) == 0) 929 { 930 add_isa_dependencies (any, name, 1, reverse); 931 is_isa = true; 932 break; 933 } 934 } 935 936 if (strcmp (flag, "0")) 937 { 938 bool combined = false; 939 940 if (is_isa) 941 return; 942 943 /* Turn on/off selective bits. */ 944 last = flag + strlen (flag); 945 if (name == NULL && strchr (flag, '&')) 946 { 947 for (; next < last && *next != '('; ) 948 { 949 str = next_field (next, '&', &next, last); 950 set_bitfield (str, all, value, ARRAY_SIZE (all), lineno); 951 } 952 if (*next == '(') 953 { 954 if (*--last != ')') 955 fail ("%s: %d: missing `)' in bitfield: %s\n", filename, 956 lineno, flag); 957 ++next; 958 *last = '\0'; 959 } 960 combined = true; 961 } 962 for (; next && next < last; ) 963 { 964 str = next_field (next, '|', &next, last); 965 if (name) 966 add_isa_dependencies (any, str, value, reverse); 967 else if (combined || next < last) 968 set_bitfield (str, any, value, ARRAY_SIZE (any), lineno); 969 else /* Singular specifiers go into "all". */ 970 set_bitfield (str, all, value, ARRAY_SIZE (all), lineno); 971 combined = true; 972 } 973 } 974 975 output: 976 if (name != NULL) 977 { 978 size_t len = strlen (name); 979 char *upper = xmalloc (len + 1); 980 981 /* Cpu64 is special: It specifies a mode dependency, not an ISA one. Zap 982 the flag from ISA initializer macros (and from CPU_ANY_64_FLAGS 983 itself we only care about tracking its dependents. Also don't emit the 984 (otherwise all zero) CPU_64_FLAGS. */ 985 if (flag != NULL && reverse == Cpu64) 986 return; 987 if (is_isa || flag == NULL) 988 any[Cpu64].value = 0; 989 990 for (i = 0; i < len; ++i) 991 { 992 /* Don't emit #define-s for auxiliary entries. */ 993 if (name[i] == ':') 994 return; 995 upper[i] = TOUPPER (name[i]); 996 } 997 upper[i] = '\0'; 998 fprintf (table, "\n#define CPU_%s%s_FLAGS \\\n", 999 flag != NULL ? "": "ANY_", upper); 1000 free (upper); 1001 } 1002 else 1003 { 1004 /* Synthesize "64-bit mode only" dependencies from the dependencies we 1005 have accumulated. */ 1006 for (i = 0; i < ARRAY_SIZE (isa_reverse_deps[0]); ++i) 1007 if (all[i].value && isa_reverse_deps[Cpu64][i]) 1008 all[Cpu64].value = 1; 1009 1010 output_cpu_flags(table, all, ARRAY_SIZE (all), -1, comma, indent, lineno); 1011 } 1012 1013 output_cpu_flags (table, any, ARRAY_SIZE (any), name != NULL, 1014 comma, indent, lineno); 1015 } 1016 1017 static void 1018 output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size) 1019 { 1020 unsigned int i; 1021 1022 fprintf (table, " { "); 1023 1024 for (i = 0; i < size - 1; i++) 1025 { 1026 if (((i + 1) % 20) != 0) 1027 fprintf (table, "%d, ", modifier[i].value); 1028 else 1029 fprintf (table, "%d,", modifier[i].value); 1030 if (((i + 1) % 20) == 0) 1031 fprintf (table, "\n "); 1032 } 1033 1034 fprintf (table, "%d },\n", modifier[i].value); 1035 } 1036 1037 /* Returns LOG2 of element size. */ 1038 static int 1039 get_element_size (char **opnd, int lineno) 1040 { 1041 char *str, *next, *last, *op; 1042 const char *full = opnd[0]; 1043 int elem_size = INT_MAX; 1044 1045 /* Find the memory operand. */ 1046 while (full != NULL && strstr(full, "BaseIndex") == NULL) 1047 full = *++opnd; 1048 if (full == NULL) 1049 fail ("%s: %d: no memory operand\n", filename, lineno); 1050 1051 op = xstrdup (full); 1052 last = op + strlen (op); 1053 for (next = op; next && next < last; ) 1054 { 1055 str = next_field (next, '|', &next, last); 1056 if (str) 1057 { 1058 if (strcasecmp(str, "Byte") == 0) 1059 { 1060 /* The smallest element size, no need to check 1061 further. */ 1062 elem_size = 0; 1063 break; 1064 } 1065 else if (strcasecmp(str, "Word") == 0) 1066 { 1067 if (elem_size > 1) 1068 elem_size = 1; 1069 } 1070 else if (strcasecmp(str, "Dword") == 0) 1071 { 1072 if (elem_size > 2) 1073 elem_size = 2; 1074 } 1075 else if (strcasecmp(str, "Qword") == 0) 1076 { 1077 if (elem_size > 3) 1078 elem_size = 3; 1079 } 1080 } 1081 } 1082 free (op); 1083 1084 if (elem_size == INT_MAX) 1085 fail ("%s: %d: unknown element size: %s\n", filename, lineno, full); 1086 1087 return elem_size; 1088 } 1089 1090 static bool 1091 rex2_disallowed (const unsigned long long opcode, unsigned int length, 1092 unsigned int space, const char *cpu_flags) 1093 { 1094 /* Some opcodes encode a ModR/M-like byte directly in the opcode. */ 1095 unsigned int base_opcode = opcode >> (8 * length - 8); 1096 1097 /* All opcodes listed map0 0x4*, 0x7*, 0xa*, 0xe* and map1 0x3*, 0x8* 1098 are reserved under REX2 and triggers #UD when prefixed with REX2 */ 1099 if (space == 0) 1100 switch (base_opcode >> 4) 1101 { 1102 case 0x4: 1103 case 0x7: 1104 case 0xA: 1105 case 0xE: 1106 return true; 1107 default: 1108 return false; 1109 } 1110 1111 if (space == SPACE_0F) 1112 switch (base_opcode >> 4) 1113 { 1114 case 0x3: 1115 case 0x8: 1116 return true; 1117 default: 1118 return false; 1119 } 1120 1121 return false; 1122 } 1123 1124 static void 1125 process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space, 1126 unsigned int prefix, const char *extension_opcode, 1127 char **opnd, int lineno, bool rex2_disallowed) 1128 { 1129 char *str, *next, *last; 1130 bool disp8_shift_derived = false; 1131 bitfield modifiers [ARRAY_SIZE (opcode_modifiers)]; 1132 static const char *const spaces[] = { 1133 #define SPACE(n) [SPACE_##n] = #n 1134 SPACE(BASE), 1135 SPACE(0F), 1136 SPACE(0F38), 1137 SPACE(0F3A), 1138 SPACE(EVEXMAP4), 1139 SPACE(EVEXMAP5), 1140 SPACE(EVEXMAP6), 1141 SPACE(VEXMAP7), 1142 SPACE(XOP08), 1143 SPACE(XOP09), 1144 SPACE(XOP0A), 1145 #undef SPACE 1146 }; 1147 1148 active_isstring = 0; 1149 1150 /* Copy the default opcode modifier. */ 1151 memcpy (modifiers, opcode_modifiers, sizeof (modifiers)); 1152 1153 if (strcmp (mod, "0")) 1154 { 1155 unsigned int have_w = 0, bwlq_suf = 0xf; 1156 1157 last = mod + strlen (mod); 1158 for (next = mod; next && next < last; ) 1159 { 1160 str = next_field (next, '|', &next, last); 1161 if (str) 1162 { 1163 int val = 1; 1164 1165 if (strncmp(str, "OpcodeSpace", 11) == 0) 1166 { 1167 char *end; 1168 1169 if (str[11] != '=') 1170 fail ("%s:%d: Missing value for `OpcodeSpace'\n", 1171 filename, lineno); 1172 1173 val = strtol (str + 12, &end, 0); 1174 if (*end) 1175 fail ("%s:%d: Bogus value `%s' for `OpcodeSpace'\n", 1176 filename, lineno, end); 1177 1178 if (space) 1179 { 1180 if (val != space) 1181 fail ("%s:%d: Conflicting opcode space specifications\n", 1182 filename, lineno); 1183 fprintf (stderr, 1184 "%s:%d: Warning: redundant opcode space specification\n", 1185 filename, lineno); 1186 } 1187 1188 space = val; 1189 continue; 1190 } 1191 1192 if (strcasecmp(str, "Broadcast") == 0) 1193 val = get_element_size (opnd, lineno) + BYTE_BROADCAST; 1194 else if (strcasecmp(str, "Disp8MemShift") == 0) 1195 { 1196 val = get_element_size (opnd, lineno); 1197 disp8_shift_derived = true; 1198 } 1199 1200 set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers), 1201 lineno); 1202 if (strcasecmp(str, "IsString") == 0) 1203 active_isstring = 1; 1204 1205 if (strcasecmp(str, "W") == 0) 1206 have_w = 1; 1207 1208 if (strcasecmp(str, "No_bSuf") == 0) 1209 bwlq_suf &= ~1; 1210 if (strcasecmp(str, "No_wSuf") == 0) 1211 bwlq_suf &= ~2; 1212 if (strcasecmp(str, "No_lSuf") == 0) 1213 bwlq_suf &= ~4; 1214 if (strcasecmp(str, "No_qSuf") == 0) 1215 bwlq_suf &= ~8; 1216 } 1217 } 1218 1219 if (prefix) 1220 { 1221 if (!modifiers[OpcodePrefix].value) 1222 modifiers[OpcodePrefix].value = prefix; 1223 else if (modifiers[OpcodePrefix].value != prefix) 1224 fail ("%s:%d: Conflicting prefix specifications\n", 1225 filename, lineno); 1226 else 1227 fprintf (stderr, 1228 "%s:%d: Warning: redundant prefix specification\n", 1229 filename, lineno); 1230 } 1231 1232 if (have_w && !bwlq_suf) 1233 fail ("%s: %d: stray W modifier\n", filename, lineno); 1234 if (have_w && !(bwlq_suf & 1)) 1235 fprintf (stderr, "%s: %d: W modifier without Byte operand(s)\n", 1236 filename, lineno); 1237 if (have_w && !(bwlq_suf & ~1)) 1238 fprintf (stderr, 1239 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n", 1240 filename, lineno); 1241 } 1242 1243 if (space >= ARRAY_SIZE (spaces) || !spaces[space]) 1244 fail ("%s:%d: Unknown opcode space %u\n", filename, lineno, space); 1245 1246 fprintf (table, " SPACE_%s, %s,\n", 1247 spaces[space], extension_opcode ? extension_opcode : "None"); 1248 1249 /* Rather than evaluating multiple conditions at runtime to determine 1250 whether an EVEX encoding is being dealt with, derive that information 1251 right here. A missing EVex attribute means "dynamic". There's one 1252 exception though: A value-less Disp8MemShift needs zapping rather than 1253 respecting if no other attribute indicates EVEX encoding. This is for 1254 certain SSE2AVX templatized templates to work reasonably. */ 1255 if (!modifiers[EVex].value) 1256 { 1257 if (modifiers[Broadcast].value 1258 || modifiers[Masking].value 1259 || modifiers[SAE].value) 1260 modifiers[EVex].value = EVEXDYN; 1261 else if (disp8_shift_derived) 1262 modifiers[Disp8MemShift].value = 0; 1263 else if (modifiers[Disp8MemShift].value) 1264 modifiers[EVex].value = EVEXDYN; 1265 } 1266 1267 /* Vex, legacy map2 and map3 and rex2_disallowed do not support EGPR. 1268 For templates supporting both Vex and EVex allowing EGPR. */ 1269 if ((modifiers[Vex].value || space > SPACE_0F || rex2_disallowed) 1270 && !modifiers[EVex].value) 1271 modifiers[NoEgpr].value = 1; 1272 1273 output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers)); 1274 } 1275 1276 enum stage { 1277 stage_macros, 1278 stage_opcodes, 1279 stage_registers, 1280 }; 1281 1282 static void 1283 output_operand_type (FILE *table, enum operand_class class, 1284 enum operand_instance instance, 1285 const bitfield *types, unsigned int size, 1286 enum stage stage, const char *indent) 1287 { 1288 unsigned int i; 1289 1290 fprintf (table, "{ { %d, %d, ", class, instance); 1291 1292 for (i = 0; i < size - 1; i++) 1293 { 1294 if (((i + 3) % 20) != 0) 1295 fprintf (table, "%d, ", types[i].value); 1296 else 1297 fprintf (table, "%d,", types[i].value); 1298 if (((i + 3) % 20) == 0) 1299 { 1300 /* We need \\ for macro. */ 1301 if (stage == stage_macros) 1302 fprintf (table, " \\\n%s", indent); 1303 else 1304 fprintf (table, "\n%s", indent); 1305 } 1306 } 1307 1308 fprintf (table, "%d } }", types[i].value); 1309 } 1310 1311 static void 1312 process_i386_operand_type (FILE *table, char *op, enum stage stage, 1313 const char *indent, int lineno) 1314 { 1315 char *str, *next, *last; 1316 enum operand_class class = ClassNone; 1317 enum operand_instance instance = InstanceNone; 1318 bitfield types [ARRAY_SIZE (operand_types)]; 1319 1320 /* Copy the default operand type. */ 1321 memcpy (types, operand_types, sizeof (types)); 1322 1323 if (strcmp (op, "0")) 1324 { 1325 int baseindex = 0; 1326 1327 last = op + strlen (op); 1328 for (next = op; next && next < last; ) 1329 { 1330 str = next_field (next, '|', &next, last); 1331 if (str) 1332 { 1333 unsigned int i; 1334 1335 if (!strncmp(str, "Class=", 6)) 1336 { 1337 for (i = 0; i < ARRAY_SIZE(operand_classes); ++i) 1338 if (!strcmp(str + 6, operand_classes[i].name)) 1339 { 1340 class = operand_classes[i].value; 1341 str = NULL; 1342 break; 1343 } 1344 } 1345 1346 if (str && !strncmp(str, "Instance=", 9)) 1347 { 1348 for (i = 0; i < ARRAY_SIZE(operand_instances); ++i) 1349 if (!strcmp(str + 9, operand_instances[i].name)) 1350 { 1351 instance = operand_instances[i].value; 1352 str = NULL; 1353 break; 1354 } 1355 } 1356 } 1357 if (str) 1358 { 1359 set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno); 1360 if (strcasecmp(str, "BaseIndex") == 0) 1361 baseindex = 1; 1362 } 1363 } 1364 1365 if (stage == stage_opcodes && baseindex && !active_isstring) 1366 { 1367 set_bitfield("Disp8", types, 1, ARRAY_SIZE (types), lineno); 1368 if (!active_cpu_flags.bitfield.cpu64 1369 && !active_cpu_flags.bitfield.cpumpx) 1370 set_bitfield("Disp16", types, 1, ARRAY_SIZE (types), lineno); 1371 set_bitfield("Disp32", types, 1, ARRAY_SIZE (types), lineno); 1372 } 1373 } 1374 output_operand_type (table, class, instance, types, ARRAY_SIZE (types), 1375 stage, indent); 1376 } 1377 1378 static char *mkident (const char *mnem) 1379 { 1380 char *ident = xstrdup (mnem), *p = ident; 1381 1382 do 1383 { 1384 if (!ISALNUM (*p)) 1385 *p = '_'; 1386 } 1387 while (*++p); 1388 1389 return ident; 1390 } 1391 1392 static void 1393 output_i386_opcode (FILE *table, const char *name, char *str, 1394 char *last, int lineno) 1395 { 1396 unsigned int i, length, prefix = 0, space = 0; 1397 char *base_opcode, *extension_opcode, *end, *ident; 1398 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS]; 1399 unsigned long long opcode; 1400 1401 /* Find base_opcode. */ 1402 base_opcode = next_field (str, ',', &str, last); 1403 1404 /* Find extension_opcode, if any. */ 1405 extension_opcode = strchr (base_opcode, '/'); 1406 if (extension_opcode) 1407 *extension_opcode++ = '\0'; 1408 1409 /* Find cpu_flags. */ 1410 cpu_flags = next_field (str, ',', &str, last); 1411 1412 /* Find opcode_modifier. */ 1413 opcode_modifier = next_field (str, ',', &str, last); 1414 1415 /* Remove the first {. */ 1416 str = remove_leading_whitespaces (str); 1417 if (*str != '{') 1418 abort (); 1419 str = remove_leading_whitespaces (str + 1); 1420 remove_trailing_whitespaces (str); 1421 1422 /* Remove } and trailing white space. */ 1423 i = strlen (str); 1424 if (!i || str[i - 1] != '}') 1425 abort (); 1426 str[--i] = '\0'; 1427 remove_trailing_whitespaces (str); 1428 1429 if (!*str) 1430 operand_types [i = 0] = NULL; 1431 else 1432 { 1433 last = str + strlen (str); 1434 1435 /* Find operand_types. */ 1436 for (i = 0; i < ARRAY_SIZE (operand_types); i++) 1437 { 1438 if (str >= last) 1439 { 1440 operand_types [i] = NULL; 1441 break; 1442 } 1443 1444 operand_types [i] = next_field (str, ',', &str, last); 1445 } 1446 } 1447 1448 opcode = strtoull (base_opcode, &end, 0); 1449 1450 /* Determine opcode length. */ 1451 for (length = 1; length < 8; ++length) 1452 if (!(opcode >> (8 * length))) 1453 break; 1454 1455 /* Transform prefixes encoded in the opcode into opcode modifier 1456 representation. */ 1457 if (length > 1) 1458 { 1459 switch (opcode >> (8 * length - 8)) 1460 { 1461 case 0x66: prefix = PREFIX_0X66; break; 1462 case 0xF3: prefix = PREFIX_0XF3; break; 1463 case 0xF2: prefix = PREFIX_0XF2; break; 1464 } 1465 1466 if (prefix) 1467 opcode &= (1ULL << (8 * --length)) - 1; 1468 } 1469 1470 /* Transform opcode space encoded in the opcode into opcode modifier 1471 representation. */ 1472 if (length > 1 && (opcode >> (8 * length - 8)) == 0xf) 1473 { 1474 switch ((opcode >> (8 * length - 16)) & 0xff) 1475 { 1476 default: space = SPACE_0F; break; 1477 case 0x38: space = SPACE_0F38; break; 1478 case 0x3A: space = SPACE_0F3A; break; 1479 } 1480 1481 if (space != SPACE_0F && --length == 1) 1482 fail ("%s:%d: %s: unrecognized opcode encoding space\n", 1483 filename, lineno, name); 1484 opcode &= (1ULL << (8 * --length)) - 1; 1485 } 1486 1487 if (length > 2) 1488 fail ("%s:%d: %s: residual opcode (0x%0*llx) too large\n", 1489 filename, lineno, name, 2 * length, opcode); 1490 1491 ident = mkident (name); 1492 fprintf (table, " { MN_%s, 0x%0*llx%s, %u,", 1493 ident, 2 * (int)length, opcode, end, i); 1494 free (ident); 1495 1496 process_i386_opcode_modifier (table, opcode_modifier, space, prefix, 1497 extension_opcode, operand_types, lineno, 1498 rex2_disallowed (opcode, length, space, 1499 cpu_flags)); 1500 1501 process_i386_cpu_flag (table, cpu_flags, NULL, ",", " ", lineno, CpuMax); 1502 1503 fprintf (table, " { "); 1504 1505 for (i = 0; i < ARRAY_SIZE (operand_types); i++) 1506 { 1507 if (!operand_types[i]) 1508 { 1509 if (i == 0) 1510 process_i386_operand_type (table, "0", stage_opcodes, "\t ", 1511 lineno); 1512 break; 1513 } 1514 1515 if (i != 0) 1516 fprintf (table, ",\n "); 1517 1518 process_i386_operand_type (table, operand_types[i], stage_opcodes, 1519 "\t ", lineno); 1520 } 1521 fprintf (table, " } },\n"); 1522 } 1523 1524 struct opcode_hash_entry 1525 { 1526 const char *name; 1527 struct opcode_entry 1528 { 1529 struct opcode_entry *next; 1530 char *opcode; 1531 int lineno; 1532 } entry; 1533 }; 1534 1535 /* Calculate the hash value of an opcode hash entry P. */ 1536 1537 static hashval_t 1538 opcode_hash_hash (const void *p) 1539 { 1540 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p; 1541 return htab_hash_string (entry->name); 1542 } 1543 1544 /* Compare a string Q against an opcode hash entry P. */ 1545 1546 static int 1547 opcode_hash_eq (const void *p, const void *q) 1548 { 1549 struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p; 1550 const char *name = (const char *) q; 1551 return strcmp (name, entry->name) == 0; 1552 } 1553 1554 static bool 1555 parse_template (char *buf, int lineno) 1556 { 1557 char sep, *end, *ptr; 1558 struct template *tmpl; 1559 struct template_instance *last_inst = NULL; 1560 1561 buf = remove_leading_whitespaces (buf + 1); 1562 end = strchr (buf, ':'); 1563 if (end == NULL) 1564 { 1565 struct template *prev = NULL; 1566 1567 end = strchr (buf, '>'); 1568 if (end == NULL) 1569 fail ("%s: %d: missing ':' or '>'\n", filename, lineno); 1570 if (*remove_leading_whitespaces (end + 1)) 1571 fail ("%s: %d: malformed template purge\n", filename, lineno); 1572 *end = '\0'; 1573 remove_trailing_whitespaces (buf); 1574 /* Don't bother freeing the various structures. */ 1575 for (tmpl = templates; tmpl != NULL; tmpl = (prev = tmpl)->next) 1576 if (!strcmp (buf, tmpl->name)) 1577 break; 1578 if (tmpl == NULL) 1579 fail ("%s: %d: no template '%s'\n", filename, lineno, buf); 1580 if (prev) 1581 prev->next = tmpl->next; 1582 else 1583 templates = tmpl->next; 1584 return true; 1585 } 1586 1587 /* Check whether this actually is a reference to an existing template: 1588 If there's '>' ahead of ':', it can't be a new template definition 1589 (and template undefs have are dealt with above). */ 1590 ptr = strchr (buf, '>'); 1591 if (ptr != NULL && ptr < end) 1592 return false; 1593 1594 *end++ = '\0'; 1595 remove_trailing_whitespaces (buf); 1596 1597 if (*buf == '\0') 1598 fail ("%s: %d: missing template identifier\n", filename, lineno); 1599 tmpl = xmalloc (sizeof (*tmpl)); 1600 tmpl->name = xstrdup (buf); 1601 1602 tmpl->params = NULL; 1603 do { 1604 struct template_param *param; 1605 1606 buf = remove_leading_whitespaces (end); 1607 end = strpbrk (buf, ":,"); 1608 if (end == NULL) 1609 fail ("%s: %d: missing ':' or ','\n", filename, lineno); 1610 1611 sep = *end; 1612 *end++ = '\0'; 1613 remove_trailing_whitespaces (buf); 1614 1615 param = xmalloc (sizeof (*param)); 1616 param->name = xstrdup (buf); 1617 param->next = tmpl->params; 1618 tmpl->params = param; 1619 } while (sep == ':'); 1620 1621 tmpl->instances = NULL; 1622 do { 1623 struct template_instance *inst; 1624 char *cur, *next; 1625 const struct template_param *param; 1626 1627 buf = remove_leading_whitespaces (end); 1628 end = strpbrk (buf, ",>"); 1629 if (end == NULL) 1630 fail ("%s: %d: missing ',' or '>'\n", filename, lineno); 1631 1632 sep = *end; 1633 *end++ = '\0'; 1634 1635 inst = xmalloc (sizeof (*inst)); 1636 inst->next = NULL; 1637 inst->args = NULL; 1638 1639 cur = next_field (buf, ':', &next, end); 1640 inst->name = *cur != '$' ? xstrdup (cur) : ""; 1641 1642 for (param = tmpl->params; param; param = param->next) 1643 { 1644 struct template_arg *arg = xmalloc (sizeof (*arg)); 1645 1646 cur = next_field (next, ':', &next, end); 1647 if (next > end) 1648 fail ("%s: %d: missing argument for '%s'\n", filename, lineno, param->name); 1649 arg->val = xstrdup (cur); 1650 arg->next = inst->args; 1651 inst->args = arg; 1652 } 1653 1654 if (tmpl->instances) 1655 last_inst->next = inst; 1656 else 1657 tmpl->instances = inst; 1658 last_inst = inst; 1659 } while (sep == ','); 1660 1661 buf = remove_leading_whitespaces (end); 1662 if (*buf) 1663 fprintf(stderr, "%s: %d: excess characters '%s'\n", 1664 filename, lineno, buf); 1665 1666 tmpl->next = templates; 1667 templates = tmpl; 1668 1669 return true; 1670 } 1671 1672 static unsigned int 1673 expand_templates (char *name, const char *str, htab_t opcode_hash_table, 1674 struct opcode_hash_entry ***opcode_array_p, int lineno) 1675 { 1676 static unsigned int idx, opcode_array_size; 1677 struct opcode_hash_entry **opcode_array = *opcode_array_p; 1678 struct opcode_hash_entry **hash_slot; 1679 struct opcode_entry *entry; 1680 char *ptr1 = strchr(name, '<'), *ptr2; 1681 1682 if (ptr1 == NULL) 1683 { 1684 /* Get the slot in hash table. */ 1685 hash_slot = (struct opcode_hash_entry **) 1686 htab_find_slot_with_hash (opcode_hash_table, name, 1687 htab_hash_string (name), 1688 INSERT); 1689 1690 if (*hash_slot == NULL) 1691 { 1692 /* It is the new one. Put it on opcode array. */ 1693 if (idx >= opcode_array_size) 1694 { 1695 /* Grow the opcode array when needed. */ 1696 opcode_array_size += 1024; 1697 opcode_array = (struct opcode_hash_entry **) 1698 xrealloc (opcode_array, 1699 sizeof (*opcode_array) * opcode_array_size); 1700 *opcode_array_p = opcode_array; 1701 } 1702 1703 opcode_array[idx] = (struct opcode_hash_entry *) 1704 xmalloc (sizeof (struct opcode_hash_entry)); 1705 opcode_array[idx]->name = xstrdup (name); 1706 *hash_slot = opcode_array[idx]; 1707 entry = &opcode_array[idx]->entry; 1708 idx++; 1709 } 1710 else 1711 { 1712 /* Append it to the existing one. */ 1713 struct opcode_entry **entryp = &(*hash_slot)->entry.next; 1714 1715 while (*entryp != NULL) 1716 entryp = &(*entryp)->next; 1717 entry = (struct opcode_entry *)xmalloc (sizeof (struct opcode_entry)); 1718 *entryp = entry; 1719 } 1720 1721 entry->next = NULL; 1722 entry->opcode = xstrdup (str); 1723 entry->lineno = lineno; 1724 } 1725 else if ((ptr2 = strchr(ptr1 + 1, '>')) == NULL) 1726 fail ("%s: %d: missing '>'\n", filename, lineno); 1727 else 1728 { 1729 const struct template *tmpl; 1730 const struct template_instance *inst; 1731 1732 *ptr1 = '\0'; 1733 ptr1 = remove_leading_whitespaces (ptr1 + 1); 1734 remove_trailing_whitespaces (ptr1); 1735 1736 *ptr2++ = '\0'; 1737 1738 for ( tmpl = templates; tmpl; tmpl = tmpl->next ) 1739 if (!strcmp(ptr1, tmpl->name)) 1740 break; 1741 if (!tmpl) 1742 fail ("reference to unknown template '%s'\n", ptr1); 1743 1744 for (inst = tmpl->instances; inst; inst = inst->next) 1745 { 1746 char *name2 = xmalloc(strlen(name) + strlen(inst->name) + strlen(ptr2) + 1); 1747 char *str2 = xmalloc(2 * strlen(str)); 1748 const char *src; 1749 1750 strcpy (name2, name); 1751 strcat (name2, inst->name); 1752 strcat (name2, ptr2); 1753 1754 for (ptr1 = str2, src = str; *src; ) 1755 { 1756 const char *ident = tmpl->name, *end; 1757 const struct template_param *param; 1758 const struct template_arg *arg; 1759 1760 if ((*ptr1 = *src++) != '<') 1761 { 1762 ++ptr1; 1763 continue; 1764 } 1765 while (ISSPACE(*src)) 1766 ++src; 1767 while (*ident && *src == *ident) 1768 ++src, ++ident; 1769 while (ISSPACE(*src)) 1770 ++src; 1771 if (*src != ':' || *ident != '\0') 1772 { 1773 memcpy (++ptr1, tmpl->name, ident - tmpl->name); 1774 ptr1 += ident - tmpl->name; 1775 continue; 1776 } 1777 while (ISSPACE(*++src)) 1778 ; 1779 1780 end = src; 1781 while (*end != '\0' && !ISSPACE(*end) && *end != '>') 1782 ++end; 1783 1784 for (param = tmpl->params, arg = inst->args; param; 1785 param = param->next, arg = arg->next) 1786 { 1787 if (end - src == strlen (param->name) 1788 && !memcmp (src, param->name, end - src)) 1789 { 1790 src = end; 1791 break; 1792 } 1793 } 1794 1795 if (param == NULL) 1796 fail ("template '%s' has no parameter '%.*s'\n", 1797 tmpl->name, (int)(end - src), src); 1798 1799 while (ISSPACE(*src)) 1800 ++src; 1801 if (*src != '>') 1802 fail ("%s: %d: missing '>'\n", filename, lineno); 1803 1804 memcpy(ptr1, arg->val, strlen(arg->val)); 1805 ptr1 += strlen(arg->val); 1806 ++src; 1807 } 1808 1809 *ptr1 = '\0'; 1810 1811 expand_templates (name2, str2, opcode_hash_table, opcode_array_p, 1812 lineno); 1813 1814 free (str2); 1815 free (name2); 1816 } 1817 } 1818 1819 return idx; 1820 } 1821 1822 static int mnemonic_cmp(const void *p1, const void *p2) 1823 { 1824 const struct opcode_hash_entry *const *e1 = p1, *const *e2 = p2; 1825 const char *s1 = (*e1)->name, *s2 = (*e2)->name; 1826 unsigned int i; 1827 size_t l1 = strlen (s1), l2 = strlen (s2); 1828 1829 for (i = 1; i <= l1 && i <= l2; ++i) 1830 { 1831 if (s1[l1 - i] != s2[l2 - i]) 1832 return (unsigned char)s1[l1 - i] - (unsigned char)s2[l2 - i]; 1833 } 1834 1835 return (int)(l1 - l2); 1836 } 1837 1838 static void 1839 process_i386_opcodes (FILE *table) 1840 { 1841 FILE *fp; 1842 char buf[2048]; 1843 unsigned int i, j, nr, offs; 1844 size_t l; 1845 char *str, *p, *last; 1846 htab_t opcode_hash_table; 1847 struct opcode_hash_entry **opcode_array = NULL; 1848 int lineno = 0, marker = 0; 1849 1850 filename = "i386-opc.tbl"; 1851 fp = stdin; 1852 1853 i = 0; 1854 opcode_hash_table = htab_create_alloc (16, opcode_hash_hash, 1855 opcode_hash_eq, NULL, 1856 xcalloc, free); 1857 1858 fprintf (table, "\n#include \"i386-mnem.h\"\n"); 1859 fprintf (table, "\n/* i386 opcode table. */\n\n"); 1860 fprintf (table, "static const insn_template i386_optab[] =\n{\n"); 1861 1862 /* Put everything on opcode array. */ 1863 while (!feof (fp)) 1864 { 1865 char *name; 1866 1867 if (fgets (buf, sizeof (buf), fp) == NULL) 1868 break; 1869 1870 p = remove_leading_whitespaces (buf); 1871 1872 for ( ; ; ) 1873 { 1874 lineno++; 1875 1876 /* Skip comments. */ 1877 str = strstr (p, "//"); 1878 if (str != NULL) 1879 { 1880 str[0] = '\0'; 1881 remove_trailing_whitespaces (p); 1882 break; 1883 } 1884 1885 /* Look for line continuation character. */ 1886 remove_trailing_whitespaces (p); 1887 j = strlen (buf); 1888 if (!j || buf[j - 1] != '+') 1889 break; 1890 if (j >= sizeof (buf) - 1) 1891 fail ("%s: %d: (continued) line too long\n", filename, lineno); 1892 1893 if (fgets (buf + j - 1, sizeof (buf) - j + 1, fp) == NULL) 1894 { 1895 fprintf (stderr, "%s: Line continuation on last line?\n", 1896 filename); 1897 break; 1898 } 1899 } 1900 1901 switch (p[0]) 1902 { 1903 case '#': 1904 if (!strcmp("### MARKER ###", buf)) 1905 marker = 1; 1906 else 1907 { 1908 /* Since we ignore all included files (we only care about their 1909 #define-s here), we don't need to monitor filenames. The final 1910 line number directive is going to refer to the main source file 1911 again. */ 1912 char *end; 1913 unsigned long ln; 1914 1915 p = remove_leading_whitespaces (p + 1); 1916 if (!strncmp(p, "line", 4)) 1917 p += 4; 1918 ln = strtoul (p, &end, 10); 1919 if (ln > 1 && ln < INT_MAX 1920 && *remove_leading_whitespaces (end) == '"') 1921 lineno = ln - 1; 1922 } 1923 /* Ignore comments. */ 1924 case '\0': 1925 continue; 1926 1927 case '<': 1928 if (parse_template (p, lineno)) 1929 continue; 1930 break; 1931 1932 default: 1933 if (!marker) 1934 continue; 1935 break; 1936 } 1937 1938 last = p + strlen (p); 1939 1940 /* Find name. */ 1941 name = next_field (p, ',', &str, last); 1942 1943 i = expand_templates (name, str, opcode_hash_table, &opcode_array, 1944 lineno); 1945 } 1946 1947 /* Process opcode array. */ 1948 for (j = 0; j < i; j++) 1949 { 1950 const char *name = opcode_array[j]->name; 1951 struct opcode_entry *next; 1952 1953 for (next = &opcode_array[j]->entry; next; next = next->next) 1954 { 1955 str = next->opcode; 1956 lineno = next->lineno; 1957 last = str + strlen (str); 1958 output_i386_opcode (table, name, str, last, lineno); 1959 } 1960 } 1961 1962 fclose (fp); 1963 1964 fprintf (table, "};\n"); 1965 1966 /* Generate opcode sets array. */ 1967 fprintf (table, "\n/* i386 opcode sets table. */\n\n"); 1968 fprintf (table, "typedef unsigned short i386_op_off_t;\n"); 1969 fprintf (table, "static const i386_op_off_t i386_op_sets[] =\n{\n "); 1970 1971 for (nr = j = 0; j < i; j++) 1972 { 1973 struct opcode_entry *next = &opcode_array[j]->entry; 1974 1975 if ((j + 1) % 8 != 0) 1976 fprintf (table, "%5u,", nr); 1977 else 1978 fprintf (table, "%5u,\n ", nr); 1979 do 1980 { 1981 ++nr; 1982 next = next->next; 1983 } 1984 while (next); 1985 } 1986 1987 fprintf (table, "%5u\n};\n", nr); 1988 1989 /* Emit mnemonics and associated #define-s. */ 1990 qsort (opcode_array, i, sizeof (*opcode_array), mnemonic_cmp); 1991 1992 fp = fopen ("i386-mnem.h", "w"); 1993 if (fp == NULL) 1994 fail ("can't create i386-mnem.h, errno = %s\n", 1995 xstrerror (errno)); 1996 1997 process_copyright (fp); 1998 1999 fprintf (table, "\n/* i386 mnemonics table. */\n\n"); 2000 fprintf (table, "const char i386_mnemonics[] =\n"); 2001 fprintf (fp, "\nextern const char i386_mnemonics[];\n\n"); 2002 2003 str = NULL; 2004 for (l = strlen (opcode_array[offs = j = 0]->name); j < i; j++) 2005 { 2006 const char *name = opcode_array[j]->name; 2007 const char *next = NULL; 2008 size_t l1 = j + 1 < i ? strlen(next = opcode_array[j + 1]->name) : 0; 2009 2010 if (str == NULL) 2011 str = mkident (name); 2012 if (l < l1 && !strcmp(name, next + l1 - l)) 2013 { 2014 fprintf (fp, "#define MN_%s ", str); 2015 free (str); 2016 str = mkident (next); 2017 fprintf (fp, "(MN_%s + %zu)\n", str, l1 - l); 2018 } 2019 else 2020 { 2021 fprintf (table, " \"\\0\"\"%s\"\n", name); 2022 fprintf (fp, "#define MN_%s %#x\n", str, offs + 1); 2023 offs += strlen (name) + 1; 2024 free (str); 2025 str = NULL; 2026 } 2027 l = l1; 2028 } 2029 2030 fprintf (table, " \"\\0\"\".insn\"\n"); 2031 fprintf (fp, "#define MN__insn %#x\n", offs + 1); 2032 2033 fprintf (table, ";\n"); 2034 2035 fclose (fp); 2036 } 2037 2038 static void 2039 process_i386_registers (FILE *table) 2040 { 2041 FILE *fp; 2042 char buf[2048]; 2043 char *str, *p, *last; 2044 char *reg_name, *reg_type, *reg_flags, *reg_num; 2045 char *dw2_32_num, *dw2_64_num; 2046 int lineno = 0; 2047 2048 filename = "i386-reg.tbl"; 2049 fp = fopen (filename, "r"); 2050 if (fp == NULL) 2051 fail ("can't find i386-reg.tbl for reading, errno = %s\n", 2052 xstrerror (errno)); 2053 2054 fprintf (table, "\n/* i386 register table. */\n\n"); 2055 fprintf (table, "static const reg_entry i386_regtab[] =\n{\n"); 2056 2057 while (!feof (fp)) 2058 { 2059 if (fgets (buf, sizeof (buf), fp) == NULL) 2060 break; 2061 2062 lineno++; 2063 2064 p = remove_leading_whitespaces (buf); 2065 2066 /* Skip comments. */ 2067 str = strstr (p, "//"); 2068 if (str != NULL) 2069 str[0] = '\0'; 2070 2071 /* Remove trailing white spaces. */ 2072 remove_trailing_whitespaces (p); 2073 2074 switch (p[0]) 2075 { 2076 case '#': 2077 fprintf (table, "%s\n", p); 2078 case '\0': 2079 continue; 2080 break; 2081 default: 2082 break; 2083 } 2084 2085 last = p + strlen (p); 2086 2087 /* Find reg_name. */ 2088 reg_name = next_field (p, ',', &str, last); 2089 2090 /* Find reg_type. */ 2091 reg_type = next_field (str, ',', &str, last); 2092 2093 /* Find reg_flags. */ 2094 reg_flags = next_field (str, ',', &str, last); 2095 2096 /* Find reg_num. */ 2097 reg_num = next_field (str, ',', &str, last); 2098 2099 fprintf (table, " { \"%s\",\n ", reg_name); 2100 2101 process_i386_operand_type (table, reg_type, stage_registers, "\t", 2102 lineno); 2103 2104 /* Find 32-bit Dwarf2 register number. */ 2105 dw2_32_num = next_field (str, ',', &str, last); 2106 2107 /* Find 64-bit Dwarf2 register number. */ 2108 dw2_64_num = next_field (str, ',', &str, last); 2109 2110 fprintf (table, ",\n %s, %s, { %s, %s } },\n", 2111 reg_flags, reg_num, dw2_32_num, dw2_64_num); 2112 } 2113 2114 fclose (fp); 2115 2116 fprintf (table, "};\n"); 2117 2118 fprintf (table, "\nstatic const unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n"); 2119 } 2120 2121 static void 2122 process_i386_initializers (void) 2123 { 2124 unsigned int i; 2125 FILE *fp = fopen ("i386-init.h", "w"); 2126 2127 if (fp == NULL) 2128 fail ("can't create i386-init.h, errno = %s\n", 2129 xstrerror (errno)); 2130 2131 process_copyright (fp); 2132 2133 for (i = 0; i < CpuMax; i++) 2134 process_i386_cpu_flag (fp, "0", cpu_flags[i].name, "", " ", -1, i); 2135 2136 for (i = 0; i < ARRAY_SIZE (isa_dependencies); i++) 2137 { 2138 char *deps = xstrdup (isa_dependencies[i].deps); 2139 2140 process_i386_cpu_flag (fp, deps, isa_dependencies[i].name, 2141 "", " ", -1, CpuMax); 2142 free (deps); 2143 } 2144 2145 /* Early x87 is somewhat special: Both 287 and 387 not only add new insns 2146 but also remove some. Hence 8087 isn't a prereq to 287, and 287 isn't 2147 one to 387. We want the reverse to be true though: Disabling 8087 also 2148 is to disable 287+ and later; disabling 287 also means disabling 387+. */ 2149 memcpy (isa_reverse_deps[Cpu287], isa_reverse_deps[Cpu387], 2150 sizeof (isa_reverse_deps[0])); 2151 isa_reverse_deps[Cpu287][Cpu387] = 1; 2152 memcpy (isa_reverse_deps[Cpu8087], isa_reverse_deps[Cpu287], 2153 sizeof (isa_reverse_deps[0])); 2154 isa_reverse_deps[Cpu8087][Cpu287] = 1; 2155 2156 /* While we treat POPCNT as a prereq to SSE4.2, its disabling should not 2157 lead to disabling of anything else. */ 2158 memset (isa_reverse_deps[CpuPOPCNT], 0, sizeof (isa_reverse_deps[0])); 2159 2160 for (i = Cpu686 + 1; i < ARRAY_SIZE (isa_reverse_deps); i++) 2161 { 2162 size_t len; 2163 char *upper; 2164 2165 if (memchr(isa_reverse_deps[i], 1, 2166 ARRAY_SIZE (isa_reverse_deps[0])) == NULL) 2167 continue; 2168 2169 isa_reverse_deps[i][i] = 1; 2170 process_i386_cpu_flag (fp, NULL, cpu_flags[i].name, "", " ", -1, i); 2171 } 2172 2173 fprintf (fp, "\n"); 2174 2175 fclose (fp); 2176 } 2177 2178 /* Program options. */ 2179 #define OPTION_SRCDIR 200 2180 2181 struct option long_options[] = 2182 { 2183 {"srcdir", required_argument, NULL, OPTION_SRCDIR}, 2184 {"debug", no_argument, NULL, 'd'}, 2185 {"version", no_argument, NULL, 'V'}, 2186 {"help", no_argument, NULL, 'h'}, 2187 {0, no_argument, NULL, 0} 2188 }; 2189 2190 static void 2191 print_version (void) 2192 { 2193 printf ("%s: version 1.0\n", program_name); 2194 xexit (0); 2195 } 2196 2197 static void 2198 usage (FILE * stream, int status) 2199 { 2200 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n", 2201 program_name); 2202 xexit (status); 2203 } 2204 2205 int 2206 main (int argc, char **argv) 2207 { 2208 extern int chdir (char *); 2209 char *srcdir = NULL; 2210 int c; 2211 unsigned int i, cpumax; 2212 FILE *table; 2213 2214 program_name = *argv; 2215 xmalloc_set_program_name (program_name); 2216 2217 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF) 2218 switch (c) 2219 { 2220 case OPTION_SRCDIR: 2221 srcdir = optarg; 2222 break; 2223 case 'V': 2224 case 'v': 2225 print_version (); 2226 break; 2227 case 'd': 2228 debug = 1; 2229 break; 2230 case 'h': 2231 case '?': 2232 usage (stderr, 0); 2233 default: 2234 case 0: 2235 break; 2236 } 2237 2238 if (optind != argc) 2239 usage (stdout, 1); 2240 2241 if (srcdir != NULL) 2242 if (chdir (srcdir) != 0) 2243 fail ("unable to change directory to \"%s\", errno = %s\n", 2244 srcdir, xstrerror (errno)); 2245 2246 /* cpu_flags isn't sorted by position. */ 2247 cpumax = 0; 2248 for (i = 0; i < ARRAY_SIZE (cpu_flags); i++) 2249 if (cpu_flags[i].position > cpumax) 2250 cpumax = cpu_flags[i].position; 2251 2252 /* Check the unused bitfield in i386_cpu_flags. */ 2253 #ifdef CpuUnused 2254 static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 2); 2255 2256 if ((cpumax - 1) != CpuMax) 2257 fail ("CpuMax != %d!\n", cpumax); 2258 #else 2259 static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 1); 2260 2261 if (cpumax != CpuMax) 2262 fail ("CpuMax != %d!\n", cpumax); 2263 2264 c = CpuNumOfBits - CpuMax - 1; 2265 if (c) 2266 fail ("%d unused bits in i386_cpu_flags.\n", c); 2267 #endif 2268 2269 /* If this triggers, CpuIsaBits needs to be increased. */ 2270 static_assert (CpuAttrEnums <= (1u << CpuIsaBits)); 2271 2272 /* Check the unused bitfield in i386_cpu_attr. */ 2273 #ifndef CpuAttrUnused 2274 c = CpuAttrNumOfBits - (CpuIsaBits + CpuMax + 1 - CpuAttrEnums); 2275 if (c) 2276 fail ("%d unused bits in i386_cpu_attr.\n", c); 2277 #endif 2278 2279 static_assert (ARRAY_SIZE (opcode_modifiers) == Opcode_Modifier_Num); 2280 2281 /* Check the unused bitfield in i386_operand_type. */ 2282 #ifdef OTUnused 2283 static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH 2284 == OTNum + 1); 2285 #else 2286 static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH 2287 == OTNum); 2288 2289 c = OTNumOfBits - OTNum; 2290 if (c) 2291 fail ("%d unused bits in i386_operand_type.\n", c); 2292 #endif 2293 2294 qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]), 2295 compare); 2296 2297 qsort (opcode_modifiers, ARRAY_SIZE (opcode_modifiers), 2298 sizeof (opcode_modifiers [0]), compare); 2299 2300 qsort (operand_types, ARRAY_SIZE (operand_types), 2301 sizeof (operand_types [0]), compare); 2302 2303 process_i386_initializers (); 2304 2305 table = fopen ("i386-tbl.h", "w"); 2306 if (table == NULL) 2307 fail ("can't create i386-tbl.h, errno = %s\n", 2308 xstrerror (errno)); 2309 2310 process_copyright (table); 2311 2312 process_i386_opcodes (table); 2313 process_i386_registers (table); 2314 2315 fclose (table); 2316 2317 exit (0); 2318 } 2319