| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <getopt.h> | 8 #include <getopt.h> |
| 9 #include <libgen.h> | 9 #include <libgen.h> |
| 10 #include <stdio.h> | 10 #include <stdio.h> |
| 11 #include <stdlib.h> | 11 #include <stdlib.h> |
| 12 #include <string.h> | 12 #include <string.h> |
| 13 | 13 |
| 14 #include <algorithm> | 14 #include <algorithm> |
| 15 #include <iterator> |
| 15 #include <map> | 16 #include <map> |
| 16 #include <set> | 17 #include <set> |
| 17 #include <string> | 18 #include <string> |
| 18 #include <tuple> | 19 #include <tuple> |
| 19 #include <vector> | 20 #include <vector> |
| 20 | 21 |
| 22 #ifndef NACL_TRUSTED_BUT_NOT_TCB |
| 23 #error("This file is not meant for use in the TCB") |
| 24 #endif |
| 25 |
| 26 #ifdef __GNUC__ |
| 27 /* We use operand number formats here. They are defined in SUSv2 and supported |
| 28 on all POSIX systems (including all versions of Linux and MacOS), yet |
| 29 -pedantic warns about them. */ |
| 30 #pragma GCC diagnostic ignored "-Wformat" |
| 31 /* GCC complains even when we explicitly use empty initializer list. Can be |
| 32 easily fixed with data member initializers, but this requires GCC 4.7+. */ |
| 33 #pragma GCC diagnostic ignored "-Wmissing-field-initializers" |
| 34 /* Default is perfectly valid way to handle missing cases. Especially if we |
| 35 only care about very few non-default ones as often here. */ |
| 36 #pragma GCC diagnostic ignored "-Wswitch-enum" |
| 37 #pragma GCC diagnostic error "-Wswitch" |
| 38 #endif |
| 39 |
| 21 template <typename T, size_t N> | 40 template <typename T, size_t N> |
| 22 char (&ArraySizeHelper(T (&array)[N]))[N]; | 41 char (&ArraySizeHelper(T (&array)[N]))[N]; |
| 23 #define arraysize(array) (sizeof(ArraySizeHelper(array))) | 42 #define arraysize(array) (sizeof(ArraySizeHelper(array))) |
| 24 | 43 |
| 25 namespace { | 44 namespace { |
| 26 const char* short_program_name; | 45 const char* short_program_name; |
| 27 | 46 |
| 28 const struct option kProgramOptions[] = { | 47 const struct option kProgramOptions[] = { |
| 29 {"mode", required_argument, NULL, 'm'}, | 48 {"mode", required_argument, NULL, 'm'}, |
| 30 {"disable", required_argument, NULL, 'd'}, | 49 {"disable", required_argument, NULL, 'd'}, |
| 31 {"output", required_argument, NULL, 'o'}, | 50 {"output", required_argument, NULL, 'o'}, |
| 32 {"help", no_argument, NULL, 'h'}, | 51 {"const_file", required_argument, NULL, 'c'}, |
| 33 {"version", no_argument, NULL, 'v'}, | 52 {"help", no_argument, NULL, 'h'}, |
| 34 {NULL, 0, NULL, 0} | 53 {"version", no_argument, NULL, 'v'}, |
| 54 {NULL, 0, NULL, 0} |
| 35 }; | 55 }; |
| 36 | 56 |
| 37 const char kVersion[] = "0.0"; | 57 const char kVersion[] = "0.0"; |
| 38 | 58 |
| 39 const char* const kProgramHelp = "Usage: %1$s [OPTION]... [FILE]...\n" | 59 const char* const kProgramHelp = "Usage: %1$s [OPTION]... [FILE]...\n" |
| 40 "\n" | 60 "\n" |
| 41 "Creates ragel machine which recognizes instructions listed in given files.\n" | 61 "Creates ragel machine which recognizes instructions listed in given files.\n" |
| 42 "\n" | 62 "\n" |
| 43 "Mandatory arguments to long options are mandatory for short options too.\n" | 63 "Mandatory arguments to long options are mandatory for short options too.\n" |
| 44 "\n" | 64 "\n" |
| 45 "Options list:\n" | 65 "Options list:\n" |
| 46 " -m, --mode=mode CPU mode: ia32 for IA32, amd64 for x86-64\n" | 66 " -m, --mode=mode CPU mode: ia32 for IA32, amd64 for x86-64\n" |
| 47 " -d, --disable=action_list disable actions from the comma-separated list\n" | 67 " -d, --disable=action_list disable actions from the comma-separated list\n" |
| 48 " -o, --output=FILE write result to FILE instead of standard output\n" | 68 " -o, --output=FILE write result to FILE instead of standard output\n" |
| 69 " -c, --const_file=FILE wrire result of FILE instead of standard output\n" |
| 49 " -h, --help display this help and exit\n" | 70 " -h, --help display this help and exit\n" |
| 50 " -v, --version output version information and exit\n" | 71 " -v, --version output version information and exit\n" |
| 51 "\n" | 72 "\n" |
| 52 "Here is the full list of possible action types with short descrion of places\n" | 73 "Here is the full list of possible action types with short descrion of places\n" |
| 53 "where they are insered:\n" | 74 "where they are insered:\n" |
| 54 " rex_prefix triggered when legacy REX prefix is parsed\n" | 75 " rex_prefix triggered when legacy REX prefix is parsed\n" |
| 55 " @rex_prefix inserted after possible REX prefix\n" | 76 " @rex_prefix inserted after possible REX prefix\n" |
| 56 " vex_prefix triggered when VEX-encoded action is detected\n" | 77 " vex_prefix triggered when VEX-encoded action is detected\n" |
| 57 " @vex_prefix2 inserted after second byte of 3-byte VEX/XOP prefix\n" | 78 " @vex_prefix2 inserted after second byte of 3-byte VEX/XOP prefix\n" |
| 58 " @vex_prefix3 inserted after third byte of 3-byte VEX/XOP prefix\n" | 79 " @vex_prefix3 inserted after third byte of 3-byte VEX/XOP prefix\n" |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 /* Flags for enabling/disabling based on architecture and validity. */ | 203 /* Flags for enabling/disabling based on architecture and validity. */ |
| 183 "ia32", | 204 "ia32", |
| 184 "amd64", | 205 "amd64", |
| 185 "nacl-ia32-forbidden", | 206 "nacl-ia32-forbidden", |
| 186 "nacl-amd64-forbidden", | 207 "nacl-amd64-forbidden", |
| 187 "nacl-forbidden" | 208 "nacl-forbidden" |
| 188 }; | 209 }; |
| 189 | 210 |
| 190 class Instruction { | 211 class Instruction { |
| 191 public: | 212 public: |
| 192 static bool check_flag_valid(const std::string &flag) { | 213 static void check_flag_valid(const std::string &flag) { |
| 193 if (all_instruction_flags.find(flag) == all_instruction_flags.end()) { | 214 if (all_instruction_flags.find(flag) == all_instruction_flags.end()) { |
| 194 fprintf(stderr, "%s: unknown flag: '%s'\n", | 215 fprintf(stderr, "%s: unknown flag: '%s'\n", |
| 195 short_program_name, flag.c_str()); | 216 short_program_name, flag.c_str()); |
| 196 exit(1); | 217 exit(1); |
| 197 } | 218 } |
| 198 } | 219 } |
| 199 | 220 |
| 200 void add_flag(const std::string &flag) { | 221 void add_flag(const std::string &flag) { |
| 201 check_flag_valid(flag); | 222 check_flag_valid(flag); |
| 202 flags.insert(flag); | 223 flags.insert(flag); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 217 }; | 238 }; |
| 218 std::vector<Operand> operands; | 239 std::vector<Operand> operands; |
| 219 std::vector<std::string> opcodes; | 240 std::vector<std::string> opcodes; |
| 220 std::set<std::string> flags; | 241 std::set<std::string> flags; |
| 221 }; | 242 }; |
| 222 std::vector<Instruction> instructions; | 243 std::vector<Instruction> instructions; |
| 223 | 244 |
| 224 FILE *out_file = stdout; | 245 FILE *out_file = stdout; |
| 225 FILE *const_file = stdout; | 246 FILE *const_file = stdout; |
| 226 char *out_file_name = NULL; | 247 char *out_file_name = NULL; |
| 248 char *const_file_name = NULL; |
| 227 | 249 |
| 228 auto ia32_mode = true; | 250 auto ia32_mode = true; |
| 229 | 251 |
| 230 std::string read_file(const char *filename) { | 252 std::string read_file(const char *filename) { |
| 231 std::string file_content; | 253 std::string file_content; |
| 232 auto file = open(filename, O_RDONLY); | 254 auto file = open(filename, O_RDONLY); |
| 233 char buf[1024]; | 255 char buf[1024]; |
| 234 ssize_t count; | 256 ssize_t count; |
| 235 | 257 |
| 236 if (file == -1) { | 258 if (file == -1) { |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 561 } | 583 } |
| 562 } | 584 } |
| 563 return name; | 585 return name; |
| 564 } | 586 } |
| 565 | 587 |
| 566 void print_common_decoding(void) { | 588 void print_common_decoding(void) { |
| 567 if (enabled(Actions::kRelOperandAction)) { | 589 if (enabled(Actions::kRelOperandAction)) { |
| 568 fprintf(out_file, " action rel8_operand {\n" | 590 fprintf(out_file, " action rel8_operand {\n" |
| 569 " operand0 = JMP_TO;\n" | 591 " operand0 = JMP_TO;\n" |
| 570 " base = REG_RIP;\n" | 592 " base = REG_RIP;\n" |
| 571 " index = REG_NONE;\n" | 593 " index = NO_REG;\n" |
| 572 " scale = 0;\n" | 594 " scale = 0;\n" |
| 573 " disp_type = DISP8;\n" | 595 " disp_type = DISP8;\n" |
| 574 " disp = p;\n" | 596 " disp = p;\n" |
| 575 " }\n" | 597 " }\n" |
| 576 " action rel16_operand {\n" | 598 " action rel16_operand {\n" |
| 577 " operand0 = JMP_TO;\n" | 599 " operand0 = JMP_TO;\n" |
| 578 " base = REG_RIP;\n" | 600 " base = REG_RIP;\n" |
| 579 " index = REG_NONE;\n" | 601 " index = NO_REG;\n" |
| 580 " scale = 0;\n" | 602 " scale = 0;\n" |
| 581 " disp_type = DISP16;\n" | 603 " disp_type = DISP16;\n" |
| 582 " disp = p - 1;\n" | 604 " disp = p - 1;\n" |
| 583 " }\n" | 605 " }\n" |
| 584 " action rel32_operand {\n" | 606 " action rel32_operand {\n" |
| 585 " operand0 = JMP_TO;\n" | 607 " operand0 = JMP_TO;\n" |
| 586 " base = REG_RIP;\n" | 608 " base = REG_RIP;\n" |
| 587 " index = REG_NONE;\n" | 609 " index = NO_REG;\n" |
| 588 " scale = 0;\n" | 610 " scale = 0;\n" |
| 589 " disp_type = DISP32;\n" | 611 " disp_type = DISP32;\n" |
| 590 " disp = p - 3;\n" | 612 " disp = p - 3;\n" |
| 591 " }\n" | 613 " }\n" |
| 592 ""); | 614 ""); |
| 593 } | 615 } |
| 594 fprintf(out_file, | 616 fprintf(out_file, |
| 595 " action branch_not_taken {\n" | 617 " action branch_not_taken {\n" |
| 596 " branch_not_taken = TRUE;\n" | 618 " branch_not_taken = TRUE;\n" |
| 597 " }\n" | 619 " }\n" |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 " action imm64_second_operand {\n" | 700 " action imm64_second_operand {\n" |
| 679 " imm2_operand = IMM64;\n" | 701 " imm2_operand = IMM64;\n" |
| 680 " imm2 = p - 7;\n" | 702 " imm2 = p - 7;\n" |
| 681 " }\n" | 703 " }\n" |
| 682 ""); | 704 ""); |
| 683 } | 705 } |
| 684 if (enabled(Actions::kParseOperands)) { | 706 if (enabled(Actions::kParseOperands)) { |
| 685 if (ia32_mode) { | 707 if (ia32_mode) { |
| 686 fprintf(out_file, " action modrm_only_base {\n" | 708 fprintf(out_file, " action modrm_only_base {\n" |
| 687 " disp_type = DISPNONE;\n" | 709 " disp_type = DISPNONE;\n" |
| 688 " index = REG_NONE;\n" | 710 " index = NO_REG;\n" |
| 689 " base = (*p) & 0x07;\n" | 711 " base = (*p) & 0x07;\n" |
| 690 " scale = 0;\n" | 712 " scale = 0;\n" |
| 691 " }\n" | 713 " }\n" |
| 692 " action modrm_base_disp {\n" | 714 " action modrm_base_disp {\n" |
| 693 " index = REG_NONE;\n" | 715 " index = NO_REG;\n" |
| 694 " base = (*p) & 0x07;\n" | 716 " base = (*p) & 0x07;\n" |
| 695 " scale = 0;\n" | 717 " scale = 0;\n" |
| 696 " }\n" | 718 " }\n" |
| 697 " action modrm_pure_disp {\n" | 719 " action modrm_pure_disp {\n" |
| 698 " base = REG_NONE;\n" | 720 " base = NO_REG;\n" |
| 699 " index = REG_NONE;\n" | 721 " index = NO_REG;\n" |
| 700 " scale = 0;\n" | 722 " scale = 0;\n" |
| 701 " }\n" | 723 " }\n" |
| 702 " action modrm_pure_index {\n" | 724 " action modrm_pure_index {\n" |
| 703 " disp_type = DISPNONE;\n" | 725 " disp_type = DISPNONE;\n" |
| 704 " base = REG_NONE;\n" | 726 " base = NO_REG;\n" |
| 705 " index = index_registers[((*p) & 0x38) >> 3];\n" | 727 " index = index_registers[((*p) & 0x38) >> 3];\n" |
| 706 " scale = ((*p) & 0xc0) >> 6;\n" | 728 " scale = ((*p) & 0xc0) >> 6;\n" |
| 707 " }\n" | 729 " }\n" |
| 708 " action modrm_parse_sib {\n" | 730 " action modrm_parse_sib {\n" |
| 709 " disp_type = DISPNONE;\n" | 731 " disp_type = DISPNONE;\n" |
| 710 " base = (*p) & 0x7;\n" | 732 " base = (*p) & 0x7;\n" |
| 711 " index = index_registers[((*p) & 0x38) >> 3];\n" | 733 " index = index_registers[((*p) & 0x38) >> 3];\n" |
| 712 " scale = ((*p) & 0xc0) >> 6;\n" | 734 " scale = ((*p) & 0xc0) >> 6;\n" |
| 713 " }\n"); | 735 " }\n"); |
| 714 } else { | 736 } else { |
| 715 fprintf(out_file, " action modrm_only_base {\n" | 737 fprintf(out_file, " action modrm_only_base {\n" |
| 716 " disp_type = DISPNONE;\n" | 738 " disp_type = DISPNONE;\n" |
| 717 " index = REG_NONE;\n" | 739 " index = NO_REG;\n" |
| 718 " base = ((*p) & 0x07) |\n" | 740 " base = ((*p) & 0x07) |\n" |
| 719 " ((rex_prefix & 0x01) << 3) |\n" | 741 " ((rex_prefix & 0x01) << 3) |\n" |
| 720 " (((~vex_prefix2) & 0x20) >> 2);\n" | 742 " (((~vex_prefix2) & 0x20) >> 2);\n" |
| 721 " scale = 0;\n" | 743 " scale = 0;\n" |
| 722 " }\n" | 744 " }\n" |
| 723 " action modrm_base_disp {\n" | 745 " action modrm_base_disp {\n" |
| 724 " index = REG_NONE;\n" | 746 " index = NO_REG;\n" |
| 725 " base = ((*p) & 0x07) |\n" | 747 " base = ((*p) & 0x07) |\n" |
| 726 " ((rex_prefix & 0x01) << 3) |\n" | 748 " ((rex_prefix & 0x01) << 3) |\n" |
| 727 " (((~vex_prefix2) & 0x20) >> 2);\n" | 749 " (((~vex_prefix2) & 0x20) >> 2);\n" |
| 728 " scale = 0;\n" | 750 " scale = 0;\n" |
| 729 " }\n" | 751 " }\n" |
| 730 " action modrm_rip {\n" | 752 " action modrm_rip {\n" |
| 731 " index = REG_NONE;\n" | 753 " index = NO_REG;\n" |
| 732 " base = REG_RIP;\n" | 754 " base = REG_RIP;\n" |
| 733 " scale = 0;\n" | 755 " scale = 0;\n" |
| 734 " }\n" | 756 " }\n" |
| 735 " action modrm_pure_index {\n" | 757 " action modrm_pure_index {\n" |
| 736 " disp_type = DISPNONE;\n" | 758 " disp_type = DISPNONE;\n" |
| 737 " base = REG_NONE;\n" | 759 " base = NO_REG;\n" |
| 738 " index = index_registers[(((*p) & 0x38) >> 3) |\n" | 760 " index = index_registers[(((*p) & 0x38) >> 3) |\n" |
| 739 " ((rex_prefix & 0x02) << 2) |\n" | 761 " ((rex_prefix & 0x02) << 2) |\n" |
| 740 " (((~vex_prefix2) & 0x40) >> 3)];\n" | 762 " (((~vex_prefix2) & 0x40) >> 3)];\n" |
| 741 " scale = ((*p) & 0xc0) >> 6;\n" | 763 " scale = ((*p) & 0xc0) >> 6;\n" |
| 742 " }\n" | 764 " }\n" |
| 743 " action modrm_parse_sib {\n" | 765 " action modrm_parse_sib {\n" |
| 744 " disp_type = DISPNONE;\n" | 766 " disp_type = DISPNONE;\n" |
| 745 " base = ((*p) & 0x7) |\n" | 767 " base = ((*p) & 0x7) |\n" |
| 746 " ((rex_prefix & 0x01) << 3) |\n" | 768 " ((rex_prefix & 0x01) << 3) |\n" |
| 747 " (((~vex_prefix2) & 0x20) >> 2);\n" | 769 " (((~vex_prefix2) & 0x20) >> 2);\n" |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 980 static const T vex_fields[] = { | 1002 static const T vex_fields[] = { |
| 981 T { "NONE", 0xe0 }, | 1003 T { "NONE", 0xe0 }, |
| 982 T { "R", 0x60 }, | 1004 T { "R", 0x60 }, |
| 983 T { "X", 0xa0 }, | 1005 T { "X", 0xa0 }, |
| 984 T { "B", 0xc0 }, | 1006 T { "B", 0xc0 }, |
| 985 T { "RX", 0x20 }, | 1007 T { "RX", 0x20 }, |
| 986 T { "RB", 0x40 }, | 1008 T { "RB", 0x40 }, |
| 987 T { "XB", 0x80 }, | 1009 T { "XB", 0x80 }, |
| 988 T { "RXB", 0x00 } | 1010 T { "RXB", 0x00 } |
| 989 }; | 1011 }; |
| 990 for (int vex_it = 0; vex_it < arraysize(vex_fields); ++vex_it) { | 1012 for (size_t vex_it = 0; vex_it < arraysize(vex_fields); ++vex_it) { |
| 991 auto vex = vex_fields[vex_it]; | 1013 auto vex = vex_fields[vex_it]; |
| 992 fprintf(out_file, " VEX_%2$s = %3$s%1$s;\n" | 1014 fprintf(out_file, " VEX_%2$s = %3$s%1$s;\n" |
| 993 "", enabled(Actions::kVexPrefix) && !ia32_mode ? " @vex_prefix2" : "", | 1015 "", enabled(Actions::kVexPrefix) && !ia32_mode ? " @vex_prefix2" : "", |
| 994 vex.first, chartest((c & vex.second) == vex.second)); | 1016 vex.first, chartest((c & vex.second) == vex.second)); |
| 995 } | 1017 } |
| 996 static const T vex_map[] = { | 1018 static const T vex_map[] = { |
| 997 T { "01", 1 }, | 1019 T { "01", 1 }, |
| 998 T { "02", 2 }, | 1020 T { "02", 2 }, |
| 999 T { "03", 3 }, | 1021 T { "03", 3 }, |
| 1000 T { "08", 8 }, | 1022 T { "08", 8 }, |
| 1001 T { "09", 9 }, | 1023 T { "09", 9 }, |
| 1002 T { "0A", 10 }, | 1024 T { "0A", 10 }, |
| 1003 T { "00001", 1 }, | 1025 T { "00001", 1 }, |
| 1004 T { "00010", 2 }, | 1026 T { "00010", 2 }, |
| 1005 T { "00011", 3 }, | 1027 T { "00011", 3 }, |
| 1006 T { "01000", 8 }, | 1028 T { "01000", 8 }, |
| 1007 T { "01001", 9 }, | 1029 T { "01001", 9 }, |
| 1008 T { "01010", 10 }, | 1030 T { "01010", 10 }, |
| 1009 }; | 1031 }; |
| 1010 for (int vex_it = 0; vex_it < arraysize(vex_map); ++vex_it) { | 1032 for (size_t vex_it = 0; vex_it < arraysize(vex_map); ++vex_it) { |
| 1011 auto vex = vex_map[vex_it]; | 1033 auto vex = vex_map[vex_it]; |
| 1012 fprintf(out_file, " VEX_map%1$s = %2$s;\n" | 1034 fprintf(out_file, " VEX_map%1$s = %2$s;\n" |
| 1013 "", vex.first, chartest((c & 0x1f) == vex.second)); | 1035 "", vex.first, chartest((c & 0x1f) == vex.second)); |
| 1014 } | 1036 } |
| 1015 if (enabled(Actions::kOpcode)) { | 1037 if (enabled(Actions::kOpcode)) { |
| 1016 fprintf(out_file, "\n" | 1038 fprintf(out_file, "\n" |
| 1017 " action begin_opcode {\n" | 1039 " action begin_opcode {\n" |
| 1018 " begin_opcode = p;\n" | 1040 " begin_opcode = p;\n" |
| 1019 " }\n" | 1041 " }\n" |
| 1020 " action end_opcode {\n" | 1042 " action end_opcode {\n" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 T { "x87", "ST" }, | 1077 T { "x87", "ST" }, |
| 1056 T { "mmx", "MMX" }, | 1078 T { "mmx", "MMX" }, |
| 1057 T { "xmm", "XMM" }, | 1079 T { "xmm", "XMM" }, |
| 1058 T { "ymm", "YMM" }, | 1080 T { "ymm", "YMM" }, |
| 1059 T { "farptr", "FarPtr" }, | 1081 T { "farptr", "FarPtr" }, |
| 1060 T { "segreg", "SegmentRegister" }, | 1082 T { "segreg", "SegmentRegister" }, |
| 1061 T { "creg", "ControlRegister" }, | 1083 T { "creg", "ControlRegister" }, |
| 1062 T { "dreg", "DebugRegister" }, | 1084 T { "dreg", "DebugRegister" }, |
| 1063 T { "selector", "Selector" } | 1085 T { "selector", "Selector" } |
| 1064 }; | 1086 }; |
| 1065 for (int size_it = 0; size_it < arraysize(sizes); ++size_it) { | 1087 for (size_t size_it = 0; size_it < arraysize(sizes); ++size_it) { |
| 1066 auto size = sizes[size_it]; | 1088 auto size = sizes[size_it]; |
| 1067 fprintf(out_file, " action operand%1$d_%2$s {\n" | 1089 fprintf(out_file, " action operand%1$d_%2$s {\n" |
| 1068 " operand%1$d_type = Operand%3$s;\n" | 1090 " operand%1$d_type = Operand%3$s;\n" |
| 1069 " }\n" | 1091 " }\n" |
| 1070 "", i, size.first, size.second); | 1092 "", i, size.first, size.second); |
| 1071 } | 1093 } |
| 1072 if (ia32_mode) { | 1094 if (ia32_mode) { |
| 1073 fprintf(out_file, " action operand%1$d_absolute_disp {\n" | 1095 fprintf(out_file, " action operand%1$d_absolute_disp {\n" |
| 1074 " operand%1$d = REG_RM;\n" | 1096 " operand%1$d = REG_RM;\n" |
| 1075 " base = REG_NONE;\n" | 1097 " base = NO_REG;\n" |
| 1076 " index = REG_NONE;\n" | 1098 " index = NO_REG;\n" |
| 1077 " scale = 0;\n" | 1099 " scale = 0;\n" |
| 1078 " }\n" | 1100 " }\n" |
| 1079 " action operand%1$d_from_opcode {\n" | 1101 " action operand%1$d_from_opcode {\n" |
| 1080 " operand%1$d = (*p) & 0x7;\n" | 1102 " operand%1$d = (*p) & 0x7;\n" |
| 1081 " }\n" | 1103 " }\n" |
| 1082 " action operand%1$d_from_is4 {\n" | 1104 " action operand%1$d_from_is4 {\n" |
| 1083 " operand%1$d = p[0] >> 4;\n" | 1105 " operand%1$d = p[0] >> 4;\n" |
| 1084 " }\n" | 1106 " }\n" |
| 1085 " action operand%1$d_from_modrm_rm {\n" | 1107 " action operand%1$d_from_modrm_rm {\n" |
| 1086 " operand%1$d = (*p) & 0x07;\n" | 1108 " operand%1$d = (*p) & 0x07;\n" |
| 1087 " }\n" | 1109 " }\n" |
| 1088 " action operand%1$d_from_modrm_reg {\n" | 1110 " action operand%1$d_from_modrm_reg {\n" |
| 1089 " operand%1$d = ((*p) & 0x38) >> 3;\n" | 1111 " operand%1$d = ((*p) & 0x38) >> 3;\n" |
| 1090 " }\n" | 1112 " }\n" |
| 1091 " action operand%1$d_from_modrm_reg_norex {\n" | 1113 " action operand%1$d_from_modrm_reg_norex {\n" |
| 1092 " operand%1$d = ((*p) & 0x38) >> 3;\n" | 1114 " operand%1$d = ((*p) & 0x38) >> 3;\n" |
| 1093 " }\n" | 1115 " }\n" |
| 1094 " action operand%1$d_from_vex {\n" | 1116 " action operand%1$d_from_vex {\n" |
| 1095 " operand%1$d = ((~vex_prefix3) & 0x38) >> 3;\n" | 1117 " operand%1$d = ((~vex_prefix3) & 0x38) >> 3;\n" |
| 1096 " }\n" | 1118 " }\n" |
| 1097 "", i); | 1119 "", i); |
| 1098 } else { | 1120 } else { |
| 1099 fprintf(out_file, " action operand%1$d_absolute_disp {\n" | 1121 fprintf(out_file, " action operand%1$d_absolute_disp {\n" |
| 1100 " operand%1$d = REG_RM;\n" | 1122 " operand%1$d = REG_RM;\n" |
| 1101 " base = REG_NONE;\n" | 1123 " base = NO_REG;\n" |
| 1102 " index = REG_RIZ;\n" | 1124 " index = REG_RIZ;\n" |
| 1103 " scale = 0;\n" | 1125 " scale = 0;\n" |
| 1104 " }\n" | 1126 " }\n" |
| 1105 " action operand%1$d_from_opcode {\n" | 1127 " action operand%1$d_from_opcode {\n" |
| 1106 " operand%1$d = ((*p) & 0x7) |\n" | 1128 " operand%1$d = ((*p) & 0x7) |\n" |
| 1107 " ((rex_prefix & 0x01) << 3) |\n" | 1129 " ((rex_prefix & 0x01) << 3) |\n" |
| 1108 " (((~vex_prefix2) & 0x20) >> 2);\n" | 1130 " (((~vex_prefix2) & 0x20) >> 2);\n" |
| 1109 " }\n" | 1131 " }\n" |
| 1110 " action operand%1$d_from_is4 {\n" | 1132 " action operand%1$d_from_is4 {\n" |
| 1111 " operand%1$d = p[0] >> 4;\n" | 1133 " operand%1$d = p[0] >> 4;\n" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1134 T { "es_rdi", "REG_ES_RDI" }, | 1156 T { "es_rdi", "REG_ES_RDI" }, |
| 1135 T { "immediate", "REG_IMM" }, | 1157 T { "immediate", "REG_IMM" }, |
| 1136 T { "second_immediate", "REG_IMM2" }, | 1158 T { "second_immediate", "REG_IMM2" }, |
| 1137 T { "port_dx", "REG_PORT_DX" }, | 1159 T { "port_dx", "REG_PORT_DX" }, |
| 1138 T { "rax", "REG_RAX" }, | 1160 T { "rax", "REG_RAX" }, |
| 1139 T { "rcx", "REG_RCX" }, | 1161 T { "rcx", "REG_RCX" }, |
| 1140 T { "rdx", "REG_RDX" }, | 1162 T { "rdx", "REG_RDX" }, |
| 1141 T { "rm", "REG_RM" }, | 1163 T { "rm", "REG_RM" }, |
| 1142 T { "st", "REG_ST" } | 1164 T { "st", "REG_ST" } |
| 1143 }; | 1165 }; |
| 1144 for (int type_it = 0; type_it < arraysize(types); ++type_it) { | 1166 for (size_t type_it = 0; type_it < arraysize(types); ++type_it) { |
| 1145 auto type = types[type_it]; | 1167 auto type = types[type_it]; |
| 1146 fprintf(out_file, " action operand%1$d_%2$s {\n" | 1168 fprintf(out_file, " action operand%1$d_%2$s {\n" |
| 1147 " operand%1$d = %3$s;\n" | 1169 " operand%1$d = %3$s;\n" |
| 1148 " }\n" | 1170 " }\n" |
| 1149 "", i, type.first, type.second); | 1171 "", i, type.first, type.second); |
| 1150 } | 1172 } |
| 1151 } | 1173 } |
| 1152 } | 1174 } |
| 1153 if (enabled(Actions::kParseOperandsStates)) { | 1175 if (enabled(Actions::kParseOperandsStates)) { |
| 1154 for (auto i = 0 ; i < 5; ++i) { | 1176 for (auto i = 0 ; i < 5; ++i) { |
| 1155 fprintf(out_file, " action operand%1$d_unused {\n" | 1177 fprintf(out_file, " action operand%1$d_unused {\n" |
| 1156 " operand%1$d_read = false;\n" | 1178 " operand%1$d_read = FALSE;\n" |
| 1157 " operand%1$d_write = false;\n" | 1179 " operand%1$d_write = FALSE;\n" |
| 1158 " }\n" | 1180 " }\n" |
| 1159 " action operand%1$d_read {\n" | 1181 " action operand%1$d_read {\n" |
| 1160 " operand%1$d_read = true;\n" | 1182 " operand%1$d_read = TRUE;\n" |
| 1161 " operand%1$d_write = false;\n" | 1183 " operand%1$d_write = FALSE;\n" |
| 1162 " }\n" | 1184 " }\n" |
| 1163 " action operand%1$d_write {\n" | 1185 " action operand%1$d_write {\n" |
| 1164 " operand%1$d_read = false;\n" | 1186 " operand%1$d_read = FALSE;\n" |
| 1165 " operand%1$d_write = true;\n" | 1187 " operand%1$d_write = TRUE;\n" |
| 1166 " }\n" | 1188 " }\n" |
| 1167 " action operand%1$d_readwrite {\n" | 1189 " action operand%1$d_readwrite {\n" |
| 1168 " operand%1$d_read = true;\n" | 1190 " operand%1$d_read = TRUE;\n" |
| 1169 " operand%1$d_write = true;\n" | 1191 " operand%1$d_write = TRUE;\n" |
| 1170 " }\n" | 1192 " }\n" |
| 1171 "", i); | 1193 "", i); |
| 1172 } | 1194 } |
| 1173 } | 1195 } |
| 1174 } | 1196 } |
| 1175 | 1197 |
| 1176 void print_name_actions(void) { | 1198 void print_name_actions(void) { |
| 1177 for (auto pair_it = instruction_names.begin(); | 1199 for (auto pair_it = instruction_names.begin(); |
| 1178 pair_it != instruction_names.end(); ++pair_it) { | 1200 pair_it != instruction_names.end(); ++pair_it) { |
| 1179 auto &pair = *pair_it; | 1201 auto &pair = *pair_it; |
| 1180 fprintf(out_file, " action instruction_%s" | 1202 fprintf(out_file, " action instruction_%s" |
| 1181 " { instruction_name = instruction_names + %zd; }\n", | 1203 " { instruction_name = instruction_names + %zd; }\n", |
| 1182 c_identifier(pair.first).c_str(), pair.second); | 1204 c_identifier(pair.first).c_str(), pair.second); |
| 1183 } | 1205 } |
| 1184 } | 1206 } |
| 1185 | 1207 |
| 1186 class MarkedInstruction : Instruction { | 1208 class MarkedInstruction : Instruction { |
| 1187 public: | 1209 public: |
| 1188 /* Additional marks are created in the process of parsing. */ | 1210 /* Additional marks are created in the process of parsing. */ |
| 1189 explicit MarkedInstruction(Instruction instruction_) : | 1211 explicit MarkedInstruction(Instruction instruction_) : |
| 1190 Instruction(instruction_), | 1212 Instruction(instruction_), |
| 1191 instruction_class(get_instruction_class(instruction_)), | 1213 instruction_class(get_instruction_class(instruction_)), |
| 1192 opcode_in_modrm(false), opcode_in_imm(false), rex { } { | 1214 rex { }, opcode_in_modrm(false), opcode_in_imm(false) { |
| 1193 if (has_flag("branch_hint")) { | 1215 if (has_flag("branch_hint")) { |
| 1194 optional_prefixes.insert("branch_hint"); | 1216 optional_prefixes.insert("branch_hint"); |
| 1195 } | 1217 } |
| 1196 if (has_flag("condrep")) { | 1218 if (has_flag("condrep")) { |
| 1197 optional_prefixes.insert("condrep"); | 1219 optional_prefixes.insert("condrep"); |
| 1198 } | 1220 } |
| 1199 if (has_flag("rep")) { | 1221 if (has_flag("rep")) { |
| 1200 optional_prefixes.insert("rep"); | 1222 optional_prefixes.insert("rep"); |
| 1201 } | 1223 } |
| 1202 for (auto opcode_it = opcodes.begin(); | 1224 for (auto opcode_it = opcodes.begin(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1230 } | 1252 } |
| 1231 opcode->push_back(')'); | 1253 opcode->push_back(')'); |
| 1232 if (saved_opcode == "0x97") { | 1254 if (saved_opcode == "0x97") { |
| 1233 opcode->erase(1, 5); | 1255 opcode->erase(1, 5); |
| 1234 } | 1256 } |
| 1235 break; | 1257 break; |
| 1236 case '8': | 1258 case '8': |
| 1237 (*opcode) = "("; | 1259 (*opcode) = "("; |
| 1238 opcode->append(saved_opcode); | 1260 opcode->append(saved_opcode); |
| 1239 static const char cc[] = {'9', 'a', 'b', 'c', 'd', 'e', 'f'}; | 1261 static const char cc[] = {'9', 'a', 'b', 'c', 'd', 'e', 'f'}; |
| 1240 for (int c_it = 0; c_it < arraysize(cc); ++c_it) { | 1262 for (size_t c_it = 0; c_it < arraysize(cc); ++c_it) { |
| 1241 auto c = cc[c_it]; | 1263 auto c = cc[c_it]; |
| 1242 opcode->push_back('|'); | 1264 opcode->push_back('|'); |
| 1243 (*(saved_opcode.rbegin())) = c; | 1265 (*(saved_opcode.rbegin())) = c; |
| 1244 opcode->append(saved_opcode); | 1266 opcode->append(saved_opcode); |
| 1245 } | 1267 } |
| 1246 opcode->push_back(')'); | 1268 opcode->push_back(')'); |
| 1247 break; | 1269 break; |
| 1248 default: | 1270 default: |
| 1249 fprintf(stderr, "%s: error - can not use 'r' operand in " | 1271 fprintf(stderr, "%s: error - can not use 'r' operand in " |
| 1250 "instruction '%s'", short_program_name, name.c_str()); | 1272 "instruction '%s'", short_program_name, name.c_str()); |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1502 if (saved_class == InstructionClass::kLSetUnsetDefaultRexW) { | 1524 if (saved_class == InstructionClass::kLSetUnsetDefaultRexW) { |
| 1503 instruction_class = InstructionClass::kRexW; | 1525 instruction_class = InstructionClass::kRexW; |
| 1504 print_one_size_definition_rexw(); | 1526 print_one_size_definition_rexw(); |
| 1505 } | 1527 } |
| 1506 opcode[Lbit] = '0'; | 1528 opcode[Lbit] = '0'; |
| 1507 auto saved_operands = operands; | 1529 auto saved_operands = operands; |
| 1508 for (auto operand_it = operands.begin(); | 1530 for (auto operand_it = operands.begin(); |
| 1509 operand_it != operands.end(); ++operand_it) { | 1531 operand_it != operands.end(); ++operand_it) { |
| 1510 auto &operand = *operand_it; | 1532 auto &operand = *operand_it; |
| 1511 static const char cc[] = {'H', 'L', 'U', 'V', 'W'}; | 1533 static const char cc[] = {'H', 'L', 'U', 'V', 'W'}; |
| 1512 for (int c_it = 0; c_it < arraysize(cc); ++c_it) { | 1534 for (size_t c_it = 0; c_it < arraysize(cc); ++c_it) { |
| 1513 auto c = cc[c_it]; | 1535 auto c = cc[c_it]; |
| 1514 if ((operand.source == c) && | 1536 if ((operand.source == c) && |
| 1515 (*(operand.size.rbegin()) == 'x') && | 1537 (*(operand.size.rbegin()) == 'x') && |
| 1516 (((operand.size.length() > 1) && | 1538 (((operand.size.length() > 1) && |
| 1517 (operand.size[0] == 'p')) || | 1539 (operand.size[0] == 'p')) || |
| 1518 (operand.size.length() == 1))) { | 1540 (operand.size.length() == 1))) { |
| 1519 operand.size.resize(operand.size.length() - 1); | 1541 operand.size.resize(operand.size.length() - 1); |
| 1520 } | 1542 } |
| 1521 } | 1543 } |
| 1522 } | 1544 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1541 } | 1563 } |
| 1542 } | 1564 } |
| 1543 | 1565 |
| 1544 void print_one_size_definition(void) { | 1566 void print_one_size_definition(void) { |
| 1545 /* 64bit commands are not supported in ia32 mode. */ | 1567 /* 64bit commands are not supported in ia32 mode. */ |
| 1546 if (ia32_mode && rex.w) { | 1568 if (ia32_mode && rex.w) { |
| 1547 return; | 1569 return; |
| 1548 } | 1570 } |
| 1549 bool modrm_memory = false; | 1571 bool modrm_memory = false; |
| 1550 bool modrm_register = false; | 1572 bool modrm_register = false; |
| 1551 char operand_source; | 1573 char operand_source = ' '; |
| 1552 for (auto operand_it = operands.begin(); | 1574 for (auto operand_it = operands.begin(); |
| 1553 operand_it != operands.end(); ++operand_it) { | 1575 operand_it != operands.end(); ++operand_it) { |
| 1554 auto &operand = *operand_it; | 1576 auto &operand = *operand_it; |
| 1555 static std::map<char, std::pair<bool, bool> > operand_map { | 1577 static std::map<char, std::pair<bool, bool> > operand_map { |
| 1556 { 'E', std::make_pair(true, true) }, | 1578 { 'E', std::make_pair(true, true) }, |
| 1557 { 'M', std::make_pair(true, false) }, | 1579 { 'M', std::make_pair(true, false) }, |
| 1558 { 'N', std::make_pair(false, true) }, | 1580 { 'N', std::make_pair(false, true) }, |
| 1559 { 'Q', std::make_pair(true, true) }, | 1581 { 'Q', std::make_pair(true, true) }, |
| 1560 { 'R', std::make_pair(false, true) }, | 1582 { 'R', std::make_pair(false, true) }, |
| 1561 { 'U', std::make_pair(false, true) }, | 1583 { 'U', std::make_pair(false, true) }, |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1664 | 1686 |
| 1665 void print_one_size_definition_modrm_memory(void) { | 1687 void print_one_size_definition_modrm_memory(void) { |
| 1666 typedef std::tuple<const char *, bool, bool> T; | 1688 typedef std::tuple<const char *, bool, bool> T; |
| 1667 static const T modes[] = { | 1689 static const T modes[] = { |
| 1668 T { " operand_disp", false, true }, | 1690 T { " operand_disp", false, true }, |
| 1669 T { " operand_rip", false, false }, | 1691 T { " operand_rip", false, false }, |
| 1670 T { " single_register_memory", false, true }, | 1692 T { " single_register_memory", false, true }, |
| 1671 T { " operand_sib_pure_index", true, false }, | 1693 T { " operand_sib_pure_index", true, false }, |
| 1672 T { " operand_sib_base_index", true, true } | 1694 T { " operand_sib_base_index", true, true } |
| 1673 }; | 1695 }; |
| 1674 for (int mode_it = 0; mode_it < arraysize(modes); ++mode_it) { | 1696 for (size_t mode_it = 0; mode_it < arraysize(modes); ++mode_it) { |
| 1675 auto mode = modes[mode_it]; | 1697 auto mode = modes[mode_it]; |
| 1676 print_operator_delimiter(); | 1698 print_operator_delimiter(); |
| 1677 if (mod_reg_is_used()) { | 1699 if (mod_reg_is_used()) { |
| 1678 rex.r = true; | 1700 rex.r = true; |
| 1679 } | 1701 } |
| 1680 if (mod_rm_is_used()) { | 1702 if (mod_rm_is_used()) { |
| 1681 rex.x = std::get<1>(mode); | 1703 rex.x = std::get<1>(mode); |
| 1682 rex.b = std::get<2>(mode); | 1704 rex.b = std::get<2>(mode); |
| 1683 } | 1705 } |
| 1684 print_legacy_prefixes(); | 1706 print_legacy_prefixes(); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1744 | 1766 |
| 1745 bool mod_reg_is_used() { | 1767 bool mod_reg_is_used() { |
| 1746 for (auto operand_it = operands.begin(); | 1768 for (auto operand_it = operands.begin(); |
| 1747 operand_it != operands.end(); ++operand_it) { | 1769 operand_it != operands.end(); ++operand_it) { |
| 1748 auto &operand = *operand_it; | 1770 auto &operand = *operand_it; |
| 1749 if (operand.source == 'C' && | 1771 if (operand.source == 'C' && |
| 1750 required_prefixes.find("0xf0") == required_prefixes.end()) { | 1772 required_prefixes.find("0xf0") == required_prefixes.end()) { |
| 1751 return true; | 1773 return true; |
| 1752 } | 1774 } |
| 1753 static const char cc[] = { 'G', 'P', 'V' }; | 1775 static const char cc[] = { 'G', 'P', 'V' }; |
| 1754 for (int c_it = 0; c_it < arraysize(cc); ++c_it) { | 1776 for (size_t c_it = 0; c_it < arraysize(cc); ++c_it) { |
| 1755 auto c = cc[c_it]; | 1777 auto c = cc[c_it]; |
| 1756 if (operand.source == c) { | 1778 if (operand.source == c) { |
| 1757 return true; | 1779 return true; |
| 1758 } | 1780 } |
| 1759 } | 1781 } |
| 1760 } | 1782 } |
| 1761 return false; | 1783 return false; |
| 1762 } | 1784 } |
| 1763 | 1785 |
| 1764 bool mod_rm_is_used() { | 1786 bool mod_rm_is_used() { |
| 1765 for (auto operand_it = operands.begin(); | 1787 for (auto operand_it = operands.begin(); |
| 1766 operand_it != operands.end(); ++operand_it) { | 1788 operand_it != operands.end(); ++operand_it) { |
| 1767 auto &operand = *operand_it; | 1789 auto &operand = *operand_it; |
| 1768 static const char cc[] = { 'E', 'M', 'N', 'Q', 'R', 'U', 'W' }; | 1790 static const char cc[] = { 'E', 'M', 'N', 'Q', 'R', 'U', 'W' }; |
| 1769 for (int c_it = 0; c_it < arraysize(cc); ++c_it) { | 1791 for (size_t c_it = 0; c_it < arraysize(cc); ++c_it) { |
| 1770 auto c = cc[c_it]; | 1792 auto c = cc[c_it]; |
| 1771 if (operand.source == c) { | 1793 if (operand.source == c) { |
| 1772 return true; | 1794 return true; |
| 1773 } | 1795 } |
| 1774 } | 1796 } |
| 1775 } | 1797 } |
| 1776 return false; | 1798 return false; |
| 1777 } | 1799 } |
| 1778 | 1800 |
| 1779 void print_legacy_prefixes(void) { | 1801 void print_legacy_prefixes(void) { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1910 if (ia32_mode || (!rex.r && !rex.x & !rex.b)) { | 1932 if (ia32_mode || (!rex.r && !rex.x & !rex.b)) { |
| 1911 fprintf(out_file, "NONE"); | 1933 fprintf(out_file, "NONE"); |
| 1912 } else { | 1934 } else { |
| 1913 if (rex.r) fprintf(out_file, "R"); | 1935 if (rex.r) fprintf(out_file, "R"); |
| 1914 if (rex.x) fprintf(out_file, "X"); | 1936 if (rex.x) fprintf(out_file, "X"); |
| 1915 if (rex.b) fprintf(out_file, "B"); | 1937 if (rex.b) fprintf(out_file, "B"); |
| 1916 } | 1938 } |
| 1917 fprintf(out_file, " & VEX_map%s) ", opcodes[1].c_str() + 4); | 1939 fprintf(out_file, " & VEX_map%s) ", opcodes[1].c_str() + 4); |
| 1918 auto third_byte = opcodes[2]; | 1940 auto third_byte = opcodes[2]; |
| 1919 static const char* symbolic_names[] = { "cntl", "dest", "src1", "src" }; | 1941 static const char* symbolic_names[] = { "cntl", "dest", "src1", "src" }; |
| 1920 for (int symbolic_it = 0; | 1942 for (size_t symbolic_it = 0; |
| 1921 symbolic_it < arraysize(symbolic_names); ++symbolic_it) { | 1943 symbolic_it < arraysize(symbolic_names); ++symbolic_it) { |
| 1922 auto symbolic = symbolic_names[symbolic_it]; | 1944 auto symbolic = symbolic_names[symbolic_it]; |
| 1923 for (auto it = third_byte.begin(); it != third_byte.end(); ++it) { | 1945 for (auto it = third_byte.begin(); it != third_byte.end(); ++it) { |
| 1924 if ((third_byte.end() - it) >= strlen(symbolic) && | 1946 auto symbolic_len = strlen(symbolic); |
| 1947 if (static_cast<size_t>(third_byte.end() - it) >= symbolic_len && |
| 1925 !strncmp(&*it, symbolic, strlen(symbolic))) { | 1948 !strncmp(&*it, symbolic, strlen(symbolic))) { |
| 1926 third_byte.replace(it, it + strlen(symbolic), "XXXX"); | 1949 third_byte.replace(it, it + strlen(symbolic), "XXXX"); |
| 1927 break; | 1950 break; |
| 1928 } | 1951 } |
| 1929 } | 1952 } |
| 1930 } | 1953 } |
| 1931 static const std::set<char> third_byte_check[] { | 1954 static const std::set<char> third_byte_check[] { |
| 1932 { '0', '1', 'x', 'X', 'W' }, | 1955 { '0', '1', 'x', 'X', 'W' }, |
| 1933 { '.' }, | 1956 { '.' }, |
| 1934 { '0', '1', 'x', 'X' }, | 1957 { '0', '1', 'x', 'X' }, |
| 1935 { '0', '1', 'x', 'X' }, | 1958 { '0', '1', 'x', 'X' }, |
| 1936 { '0', '1', 'x', 'X' }, | 1959 { '0', '1', 'x', 'X' }, |
| 1937 { '0', '1', 'x', 'X' }, | 1960 { '0', '1', 'x', 'X' }, |
| 1938 { '.' }, | 1961 { '.' }, |
| 1939 { '0', '1', 'x', 'X' }, | 1962 { '0', '1', 'x', 'X' }, |
| 1940 { '.' }, | 1963 { '.' }, |
| 1941 { '0', '1' }, | 1964 { '0', '1' }, |
| 1942 { '0', '1' } | 1965 { '0', '1' } |
| 1943 }; | 1966 }; |
| 1944 auto third_byte_ok = (arraysize(third_byte_check) == | 1967 auto third_byte_ok = (arraysize(third_byte_check) == |
| 1945 third_byte.length()); | 1968 third_byte.length()); |
| 1946 if (third_byte_ok) { | 1969 if (third_byte_ok) { |
| 1947 for (int set_it = 0; set_it < arraysize(third_byte_check); ++set_it) { | 1970 for (size_t set_it = 0; set_it < arraysize(third_byte_check); |
| 1971 ++set_it) { |
| 1948 auto &set = third_byte_check[set_it]; | 1972 auto &set = third_byte_check[set_it]; |
| 1949 if (set.find(third_byte[&set - third_byte_check]) == set.end()) { | 1973 if (set.find(third_byte[&set - third_byte_check]) == set.end()) { |
| 1950 third_byte_ok = false; | 1974 third_byte_ok = false; |
| 1951 break; | 1975 break; |
| 1952 } | 1976 } |
| 1953 } | 1977 } |
| 1954 } | 1978 } |
| 1955 if (third_byte_ok) { | 1979 if (third_byte_ok) { |
| 1956 if (ia32_mode && third_byte[2] == 'X') { | 1980 if (ia32_mode && third_byte[2] == 'X') { |
| 1957 third_byte[2] = '1'; | 1981 third_byte[2] = '1'; |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2361 | 2385 |
| 2362 int main(int argc, char *argv[]) { | 2386 int main(int argc, char *argv[]) { |
| 2363 /* basename(3) may change the passed argument thus we are using copy | 2387 /* basename(3) may change the passed argument thus we are using copy |
| 2364 of argv[0]. This creates tiny memory leak but since we only do that | 2388 of argv[0]. This creates tiny memory leak but since we only do that |
| 2365 once per program invocation it's contained. */ | 2389 once per program invocation it's contained. */ |
| 2366 short_program_name = basename(strdup(argv[0])); | 2390 short_program_name = basename(strdup(argv[0])); |
| 2367 | 2391 |
| 2368 for (;;) { | 2392 for (;;) { |
| 2369 int option_index; | 2393 int option_index; |
| 2370 | 2394 |
| 2371 int option = getopt_long(argc, argv, "d:hm:o:v", | 2395 int option = getopt_long(argc, argv, "c:d:hm:o:v", |
| 2372 kProgramOptions, &option_index); | 2396 kProgramOptions, &option_index); |
| 2373 | 2397 |
| 2374 if (option == -1) { | 2398 if (option == -1) { |
| 2375 break; | 2399 break; |
| 2376 } | 2400 } |
| 2377 | 2401 |
| 2378 switch (option) { | 2402 switch (option) { |
| 2403 case 'c': { |
| 2404 const_file_name = optarg; |
| 2405 break; |
| 2406 } |
| 2379 case 'd': { | 2407 case 'd': { |
| 2380 for (auto action_to_disable = strtok(optarg, ","); | 2408 for (auto action_to_disable = strtok(optarg, ","); |
| 2381 action_to_disable; | 2409 action_to_disable; |
| 2382 action_to_disable = strtok(NULL, ",")) { | 2410 action_to_disable = strtok(NULL, ",")) { |
| 2383 compare_action compare_with_action_to_disable(action_to_disable); | 2411 compare_action compare_with_action_to_disable(action_to_disable); |
| 2384 auto action_number = std::find_if( | 2412 auto action_number = std::find_if( |
| 2385 kDisablableActionsList, | 2413 kDisablableActionsList, |
| 2386 kDisablableActionsList + arraysize(kDisablableActionsList), | 2414 kDisablableActionsList + arraysize(kDisablableActionsList), |
| 2387 compare_with_action_to_disable); | 2415 compare_with_action_to_disable); |
| 2388 if (action_number != | 2416 if (action_number != |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2422 return 1; | 2450 return 1; |
| 2423 default: | 2451 default: |
| 2424 abort(); | 2452 abort(); |
| 2425 } | 2453 } |
| 2426 } | 2454 } |
| 2427 | 2455 |
| 2428 for (auto i = optind; i < argc; ++i) { | 2456 for (auto i = optind; i < argc; ++i) { |
| 2429 load_instructions(argv[i]); | 2457 load_instructions(argv[i]); |
| 2430 } | 2458 } |
| 2431 | 2459 |
| 2432 if (!(out_file = fopen(out_file_name, "w"))) { | 2460 if (out_file_name && !(out_file = fopen(out_file_name, "w"))) { |
| 2433 fprintf(stderr, | 2461 fprintf(stderr, |
| 2434 "%s: can not open '%s' file (%s)\n", | 2462 "%s: can not open '%s' file (%s)\n", |
| 2435 short_program_name, out_file_name, strerror(errno)); | 2463 short_program_name, out_file_name, strerror(errno)); |
| 2436 return 1; | 2464 return 1; |
| 2437 } else if (enabled(Actions::kInstructionName) || | 2465 } else if ((out_file_name || const_file_name) && |
| 2438 enabled(Actions::kParseOperands)) { | 2466 (enabled(Actions::kInstructionName) || |
| 2439 size_t const_name_len = strlen(out_file_name) + 10; | 2467 enabled(Actions::kParseOperands))) { |
| 2440 char* const_name = static_cast<char *>(malloc(const_name_len)); | 2468 size_t const_name_len = 0; |
| 2441 strncpy(const_name, out_file_name, const_name_len); | 2469 if (out_file_name && !const_file_name) { |
| 2442 char* dot_position = strrchr(const_name, '.'); | 2470 const_name_len = strlen(out_file_name) + 10; |
| 2443 if (!dot_position) { | 2471 const_file_name = static_cast<char *>(malloc(const_name_len)); |
| 2444 dot_position = strrchr(const_name, '\0'); | 2472 strcpy(const_file_name, out_file_name); |
| 2473 char* dot_position = strrchr(const_file_name, '.'); |
| 2474 if (!dot_position) { |
| 2475 dot_position = strrchr(const_file_name, '\0'); |
| 2476 } |
| 2477 strcpy(dot_position, "-consts.c"); |
| 2445 } | 2478 } |
| 2446 strncpy(dot_position, | 2479 if (!(const_file = fopen(const_file_name, "w"))) { |
| 2447 "-consts.c", | |
| 2448 const_name_len - (dot_position - const_name)); | |
| 2449 if (!(const_file = fopen(const_name, "w"))) { | |
| 2450 fprintf(stderr, "%s: can not open '%s' file (%s)\n", | 2480 fprintf(stderr, "%s: can not open '%s' file (%s)\n", |
| 2451 short_program_name, const_name, strerror(errno)); | 2481 short_program_name, const_file_name, strerror(errno)); |
| 2452 return 1; | 2482 return 1; |
| 2453 } | 2483 } |
| 2454 free(const_name); | 2484 if (const_name_len) { |
| 2485 free(const_file_name); |
| 2486 const_file_name = NULL; |
| 2487 } |
| 2455 } | 2488 } |
| 2456 | 2489 |
| 2457 if (enabled(Actions::kInstructionName) || | 2490 if (enabled(Actions::kInstructionName) || |
| 2458 enabled(Actions::kParseOperands)) { | 2491 enabled(Actions::kParseOperands)) { |
| 2459 print_consts(); | 2492 print_consts(); |
| 2460 | 2493 |
| 2461 if (out_file == const_file) { | 2494 if (out_file == const_file) { |
| 2462 for (auto i = 0; i < 80; ++i) { | 2495 for (auto i = 0; i < 80; ++i) { |
| 2463 fputc('#', out_file); | 2496 fputc('#', out_file); |
| 2464 } | 2497 } |
| 2465 fputc('\n', out_file); | 2498 fputc('\n', out_file); |
| 2466 } | 2499 } |
| 2467 } | 2500 } |
| 2468 | 2501 |
| 2469 if (ia32_mode) { | 2502 if (ia32_mode) { |
| 2470 fprintf(out_file, "%%%%{\n" | 2503 fprintf(out_file, "%%%%{\n" |
| 2471 " machine decode_x86_32;\n" | 2504 " machine decode_x86_32;\n" |
| 2472 " alphtype unsigned char;\n" | 2505 " alphtype unsigned char;\n" |
| 2473 ""); | 2506 ""); |
| 2474 } else { | 2507 } else { |
| 2475 fprintf(out_file, "END(%%%%{\n" | 2508 fprintf(out_file, "%%%%{\n" |
| 2476 " machine decode_x86_64;\n" | 2509 " machine decode_x86_64;\n" |
| 2477 " alphtype unsigned char;\n" | 2510 " alphtype unsigned char;\n" |
| 2478 ""); | 2511 ""); |
| 2479 } | 2512 } |
| 2480 | 2513 |
| 2481 print_common_decoding(); | 2514 print_common_decoding(); |
| 2482 | 2515 |
| 2483 if (enabled(Actions::kInstructionName)) { | 2516 if (enabled(Actions::kInstructionName)) { |
| 2484 print_name_actions(); | 2517 print_name_actions(); |
| 2485 } | 2518 } |
| 2486 | 2519 |
| 2487 fprintf(out_file, "\n one_instruction ="); | 2520 fprintf(out_file, "\n one_instruction ="); |
| 2488 | 2521 |
| 2489 print_one_instruction_definition(); | 2522 print_one_instruction_definition(); |
| 2490 | 2523 |
| 2491 fprintf(out_file, ");\n" | 2524 fprintf(out_file, ");\n" |
| 2492 "}%%%%\n" | 2525 "}%%%%\n" |
| 2493 ""); | 2526 ""); |
| 2494 return 0; | 2527 return 0; |
| 2495 } | 2528 } |
| OLD | NEW |