Chromium Code Reviews| 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 #ifdef __GNUC__ | |
| 23 /* We use operand number formats here. They are defined in SUSv2 and supported | |
| 24 on all POSIX systems (including all versions of Linux and MacOS), yet | |
| 25 -pedantic warns about them. */ | |
| 26 #pragma GCC diagnostic ignored "-Wformat" | |
| 27 /* GCC complains even when we explicitly use empty initializer list. Can be | |
| 28 easily fixed with data member initializers, but this requires GCC 4.7+. */ | |
| 29 #pragma GCC diagnostic ignored "-Wmissing-field-initializers" | |
| 30 /* Default is perfectly valid way to handle missing cases. Especially if we | |
| 31 only care about very few non-default ones as often here. */ | |
| 32 #pragma GCC diagnostic ignored "-Wswitch-enum" | |
| 33 #pragma GCC diagnostic error "-Wswitch" | |
| 34 #endif | |
| 35 | |
| 21 template <typename T, size_t N> | 36 template <typename T, size_t N> |
| 22 char (&ArraySizeHelper(T (&array)[N]))[N]; | 37 char (&ArraySizeHelper(T (&array)[N]))[N]; |
| 23 #define arraysize(array) (sizeof(ArraySizeHelper(array))) | 38 #define arraysize(array) (sizeof(ArraySizeHelper(array))) |
| 24 | 39 |
| 25 namespace { | 40 namespace { |
| 26 const char* short_program_name; | 41 const char* short_program_name; |
| 27 | 42 |
| 28 const struct option kProgramOptions[] = { | 43 const struct option kProgramOptions[] = { |
| 29 {"mode", required_argument, NULL, 'm'}, | 44 {"mode", required_argument, NULL, 'm'}, |
| 30 {"disable", required_argument, NULL, 'd'}, | 45 {"disable", required_argument, NULL, 'd'}, |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 182 /* Flags for enabling/disabling based on architecture and validity. */ | 197 /* Flags for enabling/disabling based on architecture and validity. */ |
| 183 "ia32", | 198 "ia32", |
| 184 "amd64", | 199 "amd64", |
| 185 "nacl-ia32-forbidden", | 200 "nacl-ia32-forbidden", |
| 186 "nacl-amd64-forbidden", | 201 "nacl-amd64-forbidden", |
| 187 "nacl-forbidden" | 202 "nacl-forbidden" |
| 188 }; | 203 }; |
| 189 | 204 |
| 190 class Instruction { | 205 class Instruction { |
| 191 public: | 206 public: |
| 192 static bool check_flag_valid(const std::string &flag) { | 207 static void check_flag_valid(const std::string &flag) { |
| 193 if (all_instruction_flags.find(flag) == all_instruction_flags.end()) { | 208 if (all_instruction_flags.find(flag) == all_instruction_flags.end()) { |
| 194 fprintf(stderr, "%s: unknown flag: '%s'\n", | 209 fprintf(stderr, "%s: unknown flag: '%s'\n", |
| 195 short_program_name, flag.c_str()); | 210 short_program_name, flag.c_str()); |
| 196 exit(1); | 211 exit(1); |
| 197 } | 212 } |
| 198 } | 213 } |
| 199 | 214 |
| 200 void add_flag(const std::string &flag) { | 215 void add_flag(const std::string &flag) { |
| 201 check_flag_valid(flag); | 216 check_flag_valid(flag); |
| 202 flags.insert(flag); | 217 flags.insert(flag); |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 561 } | 576 } |
| 562 } | 577 } |
| 563 return name; | 578 return name; |
| 564 } | 579 } |
| 565 | 580 |
| 566 void print_common_decoding(void) { | 581 void print_common_decoding(void) { |
| 567 if (enabled(Actions::kRelOperandAction)) { | 582 if (enabled(Actions::kRelOperandAction)) { |
| 568 fprintf(out_file, " action rel8_operand {\n" | 583 fprintf(out_file, " action rel8_operand {\n" |
| 569 " operand0 = JMP_TO;\n" | 584 " operand0 = JMP_TO;\n" |
| 570 " base = REG_RIP;\n" | 585 " base = REG_RIP;\n" |
| 571 " index = REG_NONE;\n" | 586 " index = NO_REG;\n" |
| 572 " scale = 0;\n" | 587 " scale = 0;\n" |
| 573 " disp_type = DISP8;\n" | 588 " disp_type = DISP8;\n" |
| 574 " disp = p;\n" | 589 " disp = p;\n" |
| 575 " }\n" | 590 " }\n" |
| 576 " action rel16_operand {\n" | 591 " action rel16_operand {\n" |
| 577 " operand0 = JMP_TO;\n" | 592 " operand0 = JMP_TO;\n" |
| 578 " base = REG_RIP;\n" | 593 " base = REG_RIP;\n" |
| 579 " index = REG_NONE;\n" | 594 " index = NO_REG;\n" |
| 580 " scale = 0;\n" | 595 " scale = 0;\n" |
| 581 " disp_type = DISP16;\n" | 596 " disp_type = DISP16;\n" |
| 582 " disp = p - 1;\n" | 597 " disp = p - 1;\n" |
| 583 " }\n" | 598 " }\n" |
| 584 " action rel32_operand {\n" | 599 " action rel32_operand {\n" |
| 585 " operand0 = JMP_TO;\n" | 600 " operand0 = JMP_TO;\n" |
| 586 " base = REG_RIP;\n" | 601 " base = REG_RIP;\n" |
| 587 " index = REG_NONE;\n" | 602 " index = NO_REG;\n" |
| 588 " scale = 0;\n" | 603 " scale = 0;\n" |
| 589 " disp_type = DISP32;\n" | 604 " disp_type = DISP32;\n" |
| 590 " disp = p - 3;\n" | 605 " disp = p - 3;\n" |
| 591 " }\n" | 606 " }\n" |
| 592 ""); | 607 ""); |
| 593 } | 608 } |
| 594 fprintf(out_file, | 609 fprintf(out_file, |
| 595 " action branch_not_taken {\n" | 610 " action branch_not_taken {\n" |
| 596 " branch_not_taken = TRUE;\n" | 611 " branch_not_taken = TRUE;\n" |
| 597 " }\n" | 612 " }\n" |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 678 " action imm64_second_operand {\n" | 693 " action imm64_second_operand {\n" |
| 679 " imm2_operand = IMM64;\n" | 694 " imm2_operand = IMM64;\n" |
| 680 " imm2 = p - 7;\n" | 695 " imm2 = p - 7;\n" |
| 681 " }\n" | 696 " }\n" |
| 682 ""); | 697 ""); |
| 683 } | 698 } |
| 684 if (enabled(Actions::kParseOperands)) { | 699 if (enabled(Actions::kParseOperands)) { |
| 685 if (ia32_mode) { | 700 if (ia32_mode) { |
| 686 fprintf(out_file, " action modrm_only_base {\n" | 701 fprintf(out_file, " action modrm_only_base {\n" |
| 687 " disp_type = DISPNONE;\n" | 702 " disp_type = DISPNONE;\n" |
| 688 " index = REG_NONE;\n" | 703 " index = NO_REG;\n" |
| 689 " base = (*p) & 0x07;\n" | 704 " base = (*p) & 0x07;\n" |
| 690 " scale = 0;\n" | 705 " scale = 0;\n" |
| 691 " }\n" | 706 " }\n" |
| 692 " action modrm_base_disp {\n" | 707 " action modrm_base_disp {\n" |
| 693 " index = REG_NONE;\n" | 708 " index = NO_REG;\n" |
| 694 " base = (*p) & 0x07;\n" | 709 " base = (*p) & 0x07;\n" |
| 695 " scale = 0;\n" | 710 " scale = 0;\n" |
| 696 " }\n" | 711 " }\n" |
| 697 " action modrm_pure_disp {\n" | 712 " action modrm_pure_disp {\n" |
| 698 " base = REG_NONE;\n" | 713 " base = NO_REG;\n" |
| 699 " index = REG_NONE;\n" | 714 " index = NO_REG;\n" |
| 700 " scale = 0;\n" | 715 " scale = 0;\n" |
| 701 " }\n" | 716 " }\n" |
| 702 " action modrm_pure_index {\n" | 717 " action modrm_pure_index {\n" |
| 703 " disp_type = DISPNONE;\n" | 718 " disp_type = DISPNONE;\n" |
| 704 " base = REG_NONE;\n" | 719 " base = NO_REG;\n" |
| 705 " index = index_registers[((*p) & 0x38) >> 3];\n" | 720 " index = index_registers[((*p) & 0x38) >> 3];\n" |
| 706 " scale = ((*p) & 0xc0) >> 6;\n" | 721 " scale = ((*p) & 0xc0) >> 6;\n" |
| 707 " }\n" | 722 " }\n" |
| 708 " action modrm_parse_sib {\n" | 723 " action modrm_parse_sib {\n" |
| 709 " disp_type = DISPNONE;\n" | 724 " disp_type = DISPNONE;\n" |
| 710 " base = (*p) & 0x7;\n" | 725 " base = (*p) & 0x7;\n" |
| 711 " index = index_registers[((*p) & 0x38) >> 3];\n" | 726 " index = index_registers[((*p) & 0x38) >> 3];\n" |
| 712 " scale = ((*p) & 0xc0) >> 6;\n" | 727 " scale = ((*p) & 0xc0) >> 6;\n" |
| 713 " }\n"); | 728 " }\n"); |
| 714 } else { | 729 } else { |
| 715 fprintf(out_file, " action modrm_only_base {\n" | 730 fprintf(out_file, " action modrm_only_base {\n" |
| 716 " disp_type = DISPNONE;\n" | 731 " disp_type = DISPNONE;\n" |
| 717 " index = REG_NONE;\n" | 732 " index = NO_REG;\n" |
| 718 " base = ((*p) & 0x07) |\n" | 733 " base = ((*p) & 0x07) |\n" |
| 719 " ((rex_prefix & 0x01) << 3) |\n" | 734 " ((rex_prefix & 0x01) << 3) |\n" |
| 720 " (((~vex_prefix2) & 0x20) >> 2);\n" | 735 " (((~vex_prefix2) & 0x20) >> 2);\n" |
| 721 " scale = 0;\n" | 736 " scale = 0;\n" |
| 722 " }\n" | 737 " }\n" |
| 723 " action modrm_base_disp {\n" | 738 " action modrm_base_disp {\n" |
| 724 " index = REG_NONE;\n" | 739 " index = NO_REG;\n" |
| 725 " base = ((*p) & 0x07) |\n" | 740 " base = ((*p) & 0x07) |\n" |
| 726 " ((rex_prefix & 0x01) << 3) |\n" | 741 " ((rex_prefix & 0x01) << 3) |\n" |
| 727 " (((~vex_prefix2) & 0x20) >> 2);\n" | 742 " (((~vex_prefix2) & 0x20) >> 2);\n" |
| 728 " scale = 0;\n" | 743 " scale = 0;\n" |
| 729 " }\n" | 744 " }\n" |
| 730 " action modrm_rip {\n" | 745 " action modrm_rip {\n" |
| 731 " index = REG_NONE;\n" | 746 " index = NO_REG;\n" |
| 732 " base = REG_RIP;\n" | 747 " base = REG_RIP;\n" |
| 733 " scale = 0;\n" | 748 " scale = 0;\n" |
| 734 " }\n" | 749 " }\n" |
| 735 " action modrm_pure_index {\n" | 750 " action modrm_pure_index {\n" |
| 736 " disp_type = DISPNONE;\n" | 751 " disp_type = DISPNONE;\n" |
| 737 " base = REG_NONE;\n" | 752 " base = NO_REG;\n" |
| 738 " index = index_registers[(((*p) & 0x38) >> 3) |\n" | 753 " index = index_registers[(((*p) & 0x38) >> 3) |\n" |
| 739 " ((rex_prefix & 0x02) << 2) |\n" | 754 " ((rex_prefix & 0x02) << 2) |\n" |
| 740 " (((~vex_prefix2) & 0x40) >> 3)];\n" | 755 " (((~vex_prefix2) & 0x40) >> 3)];\n" |
| 741 " scale = ((*p) & 0xc0) >> 6;\n" | 756 " scale = ((*p) & 0xc0) >> 6;\n" |
| 742 " }\n" | 757 " }\n" |
| 743 " action modrm_parse_sib {\n" | 758 " action modrm_parse_sib {\n" |
| 744 " disp_type = DISPNONE;\n" | 759 " disp_type = DISPNONE;\n" |
| 745 " base = ((*p) & 0x7) |\n" | 760 " base = ((*p) & 0x7) |\n" |
| 746 " ((rex_prefix & 0x01) << 3) |\n" | 761 " ((rex_prefix & 0x01) << 3) |\n" |
| 747 " (((~vex_prefix2) & 0x20) >> 2);\n" | 762 " (((~vex_prefix2) & 0x20) >> 2);\n" |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 980 static const T vex_fields[] = { | 995 static const T vex_fields[] = { |
| 981 T { "NONE", 0xe0 }, | 996 T { "NONE", 0xe0 }, |
| 982 T { "R", 0x60 }, | 997 T { "R", 0x60 }, |
| 983 T { "X", 0xa0 }, | 998 T { "X", 0xa0 }, |
| 984 T { "B", 0xc0 }, | 999 T { "B", 0xc0 }, |
| 985 T { "RX", 0x20 }, | 1000 T { "RX", 0x20 }, |
| 986 T { "RB", 0x40 }, | 1001 T { "RB", 0x40 }, |
| 987 T { "XB", 0x80 }, | 1002 T { "XB", 0x80 }, |
| 988 T { "RXB", 0x00 } | 1003 T { "RXB", 0x00 } |
| 989 }; | 1004 }; |
| 990 for (int vex_it = 0; vex_it < arraysize(vex_fields); ++vex_it) { | 1005 for (size_t vex_it = 0; vex_it < arraysize(vex_fields); ++vex_it) { |
| 991 auto vex = vex_fields[vex_it]; | 1006 auto vex = vex_fields[vex_it]; |
| 992 fprintf(out_file, " VEX_%2$s = %3$s%1$s;\n" | 1007 fprintf(out_file, " VEX_%2$s = %3$s%1$s;\n" |
| 993 "", enabled(Actions::kVexPrefix) && !ia32_mode ? " @vex_prefix2" : "", | 1008 "", enabled(Actions::kVexPrefix) && !ia32_mode ? " @vex_prefix2" : "", |
| 994 vex.first, chartest((c & vex.second) == vex.second)); | 1009 vex.first, chartest((c & vex.second) == vex.second)); |
| 995 } | 1010 } |
| 996 static const T vex_map[] = { | 1011 static const T vex_map[] = { |
| 997 T { "01", 1 }, | 1012 T { "01", 1 }, |
| 998 T { "02", 2 }, | 1013 T { "02", 2 }, |
| 999 T { "03", 3 }, | 1014 T { "03", 3 }, |
| 1000 T { "08", 8 }, | 1015 T { "08", 8 }, |
| 1001 T { "09", 9 }, | 1016 T { "09", 9 }, |
| 1002 T { "0A", 10 }, | 1017 T { "0A", 10 }, |
| 1003 T { "00001", 1 }, | 1018 T { "00001", 1 }, |
| 1004 T { "00010", 2 }, | 1019 T { "00010", 2 }, |
| 1005 T { "00011", 3 }, | 1020 T { "00011", 3 }, |
| 1006 T { "01000", 8 }, | 1021 T { "01000", 8 }, |
| 1007 T { "01001", 9 }, | 1022 T { "01001", 9 }, |
| 1008 T { "01010", 10 }, | 1023 T { "01010", 10 }, |
| 1009 }; | 1024 }; |
| 1010 for (int vex_it = 0; vex_it < arraysize(vex_map); ++vex_it) { | 1025 for (size_t vex_it = 0; vex_it < arraysize(vex_map); ++vex_it) { |
| 1011 auto vex = vex_map[vex_it]; | 1026 auto vex = vex_map[vex_it]; |
| 1012 fprintf(out_file, " VEX_map%1$s = %2$s;\n" | 1027 fprintf(out_file, " VEX_map%1$s = %2$s;\n" |
| 1013 "", vex.first, chartest((c & 0x1f) == vex.second)); | 1028 "", vex.first, chartest((c & 0x1f) == vex.second)); |
| 1014 } | 1029 } |
| 1015 if (enabled(Actions::kOpcode)) { | 1030 if (enabled(Actions::kOpcode)) { |
| 1016 fprintf(out_file, "\n" | 1031 fprintf(out_file, "\n" |
| 1017 " action begin_opcode {\n" | 1032 " action begin_opcode {\n" |
| 1018 " begin_opcode = p;\n" | 1033 " begin_opcode = p;\n" |
| 1019 " }\n" | 1034 " }\n" |
| 1020 " action end_opcode {\n" | 1035 " action end_opcode {\n" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1055 T { "x87", "ST" }, | 1070 T { "x87", "ST" }, |
| 1056 T { "mmx", "MMX" }, | 1071 T { "mmx", "MMX" }, |
| 1057 T { "xmm", "XMM" }, | 1072 T { "xmm", "XMM" }, |
| 1058 T { "ymm", "YMM" }, | 1073 T { "ymm", "YMM" }, |
| 1059 T { "farptr", "FarPtr" }, | 1074 T { "farptr", "FarPtr" }, |
| 1060 T { "segreg", "SegmentRegister" }, | 1075 T { "segreg", "SegmentRegister" }, |
| 1061 T { "creg", "ControlRegister" }, | 1076 T { "creg", "ControlRegister" }, |
| 1062 T { "dreg", "DebugRegister" }, | 1077 T { "dreg", "DebugRegister" }, |
| 1063 T { "selector", "Selector" } | 1078 T { "selector", "Selector" } |
| 1064 }; | 1079 }; |
| 1065 for (int size_it = 0; size_it < arraysize(sizes); ++size_it) { | 1080 for (size_t size_it = 0; size_it < arraysize(sizes); ++size_it) { |
| 1066 auto size = sizes[size_it]; | 1081 auto size = sizes[size_it]; |
| 1067 fprintf(out_file, " action operand%1$d_%2$s {\n" | 1082 fprintf(out_file, " action operand%1$d_%2$s {\n" |
| 1068 " operand%1$d_type = Operand%3$s;\n" | 1083 " operand%1$d_type = Operand%3$s;\n" |
| 1069 " }\n" | 1084 " }\n" |
| 1070 "", i, size.first, size.second); | 1085 "", i, size.first, size.second); |
| 1071 } | 1086 } |
| 1072 if (ia32_mode) { | 1087 if (ia32_mode) { |
| 1073 fprintf(out_file, " action operand%1$d_absolute_disp {\n" | 1088 fprintf(out_file, " action operand%1$d_absolute_disp {\n" |
| 1074 " operand%1$d = REG_RM;\n" | 1089 " operand%1$d = REG_RM;\n" |
| 1075 " base = REG_NONE;\n" | 1090 " base = NO_REG;\n" |
| 1076 " index = REG_NONE;\n" | 1091 " index = NO_REG;\n" |
| 1077 " scale = 0;\n" | 1092 " scale = 0;\n" |
| 1078 " }\n" | 1093 " }\n" |
| 1079 " action operand%1$d_from_opcode {\n" | 1094 " action operand%1$d_from_opcode {\n" |
| 1080 " operand%1$d = (*p) & 0x7;\n" | 1095 " operand%1$d = (*p) & 0x7;\n" |
| 1081 " }\n" | 1096 " }\n" |
| 1082 " action operand%1$d_from_is4 {\n" | 1097 " action operand%1$d_from_is4 {\n" |
| 1083 " operand%1$d = p[0] >> 4;\n" | 1098 " operand%1$d = p[0] >> 4;\n" |
| 1084 " }\n" | 1099 " }\n" |
| 1085 " action operand%1$d_from_modrm_rm {\n" | 1100 " action operand%1$d_from_modrm_rm {\n" |
| 1086 " operand%1$d = (*p) & 0x07;\n" | 1101 " operand%1$d = (*p) & 0x07;\n" |
| 1087 " }\n" | 1102 " }\n" |
| 1088 " action operand%1$d_from_modrm_reg {\n" | 1103 " action operand%1$d_from_modrm_reg {\n" |
| 1089 " operand%1$d = ((*p) & 0x38) >> 3;\n" | 1104 " operand%1$d = ((*p) & 0x38) >> 3;\n" |
| 1090 " }\n" | 1105 " }\n" |
| 1091 " action operand%1$d_from_modrm_reg_norex {\n" | 1106 " action operand%1$d_from_modrm_reg_norex {\n" |
| 1092 " operand%1$d = ((*p) & 0x38) >> 3;\n" | 1107 " operand%1$d = ((*p) & 0x38) >> 3;\n" |
| 1093 " }\n" | 1108 " }\n" |
| 1094 " action operand%1$d_from_vex {\n" | 1109 " action operand%1$d_from_vex {\n" |
| 1095 " operand%1$d = ((~vex_prefix3) & 0x38) >> 3;\n" | 1110 " operand%1$d = ((~vex_prefix3) & 0x38) >> 3;\n" |
| 1096 " }\n" | 1111 " }\n" |
| 1097 "", i); | 1112 "", i); |
| 1098 } else { | 1113 } else { |
| 1099 fprintf(out_file, " action operand%1$d_absolute_disp {\n" | 1114 fprintf(out_file, " action operand%1$d_absolute_disp {\n" |
| 1100 " operand%1$d = REG_RM;\n" | 1115 " operand%1$d = REG_RM;\n" |
| 1101 " base = REG_NONE;\n" | 1116 " base = NO_REG;\n" |
| 1102 " index = REG_RIZ;\n" | 1117 " index = REG_RIZ;\n" |
| 1103 " scale = 0;\n" | 1118 " scale = 0;\n" |
| 1104 " }\n" | 1119 " }\n" |
| 1105 " action operand%1$d_from_opcode {\n" | 1120 " action operand%1$d_from_opcode {\n" |
| 1106 " operand%1$d = ((*p) & 0x7) |\n" | 1121 " operand%1$d = ((*p) & 0x7) |\n" |
| 1107 " ((rex_prefix & 0x01) << 3) |\n" | 1122 " ((rex_prefix & 0x01) << 3) |\n" |
| 1108 " (((~vex_prefix2) & 0x20) >> 2);\n" | 1123 " (((~vex_prefix2) & 0x20) >> 2);\n" |
| 1109 " }\n" | 1124 " }\n" |
| 1110 " action operand%1$d_from_is4 {\n" | 1125 " action operand%1$d_from_is4 {\n" |
| 1111 " operand%1$d = p[0] >> 4;\n" | 1126 " operand%1$d = p[0] >> 4;\n" |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1134 T { "es_rdi", "REG_ES_RDI" }, | 1149 T { "es_rdi", "REG_ES_RDI" }, |
| 1135 T { "immediate", "REG_IMM" }, | 1150 T { "immediate", "REG_IMM" }, |
| 1136 T { "second_immediate", "REG_IMM2" }, | 1151 T { "second_immediate", "REG_IMM2" }, |
| 1137 T { "port_dx", "REG_PORT_DX" }, | 1152 T { "port_dx", "REG_PORT_DX" }, |
| 1138 T { "rax", "REG_RAX" }, | 1153 T { "rax", "REG_RAX" }, |
| 1139 T { "rcx", "REG_RCX" }, | 1154 T { "rcx", "REG_RCX" }, |
| 1140 T { "rdx", "REG_RDX" }, | 1155 T { "rdx", "REG_RDX" }, |
| 1141 T { "rm", "REG_RM" }, | 1156 T { "rm", "REG_RM" }, |
| 1142 T { "st", "REG_ST" } | 1157 T { "st", "REG_ST" } |
| 1143 }; | 1158 }; |
| 1144 for (int type_it = 0; type_it < arraysize(types); ++type_it) { | 1159 for (size_t type_it = 0; type_it < arraysize(types); ++type_it) { |
| 1145 auto type = types[type_it]; | 1160 auto type = types[type_it]; |
| 1146 fprintf(out_file, " action operand%1$d_%2$s {\n" | 1161 fprintf(out_file, " action operand%1$d_%2$s {\n" |
| 1147 " operand%1$d = %3$s;\n" | 1162 " operand%1$d = %3$s;\n" |
| 1148 " }\n" | 1163 " }\n" |
| 1149 "", i, type.first, type.second); | 1164 "", i, type.first, type.second); |
| 1150 } | 1165 } |
| 1151 } | 1166 } |
| 1152 } | 1167 } |
| 1153 if (enabled(Actions::kParseOperandsStates)) { | 1168 if (enabled(Actions::kParseOperandsStates)) { |
| 1154 for (auto i = 0 ; i < 5; ++i) { | 1169 for (auto i = 0 ; i < 5; ++i) { |
| 1155 fprintf(out_file, " action operand%1$d_unused {\n" | 1170 fprintf(out_file, " action operand%1$d_unused {\n" |
| 1156 " operand%1$d_read = false;\n" | 1171 " operand%1$d_read = FALSE;\n" |
| 1157 " operand%1$d_write = false;\n" | 1172 " operand%1$d_write = FALSE;\n" |
| 1158 " }\n" | 1173 " }\n" |
| 1159 " action operand%1$d_read {\n" | 1174 " action operand%1$d_read {\n" |
| 1160 " operand%1$d_read = true;\n" | 1175 " operand%1$d_read = TRUE;\n" |
| 1161 " operand%1$d_write = false;\n" | 1176 " operand%1$d_write = FALSE;\n" |
| 1162 " }\n" | 1177 " }\n" |
| 1163 " action operand%1$d_write {\n" | 1178 " action operand%1$d_write {\n" |
| 1164 " operand%1$d_read = false;\n" | 1179 " operand%1$d_read = FALSE;\n" |
| 1165 " operand%1$d_write = true;\n" | 1180 " operand%1$d_write = TRUE;\n" |
| 1166 " }\n" | 1181 " }\n" |
| 1167 " action operand%1$d_readwrite {\n" | 1182 " action operand%1$d_readwrite {\n" |
| 1168 " operand%1$d_read = true;\n" | 1183 " operand%1$d_read = TRUE;\n" |
| 1169 " operand%1$d_write = true;\n" | 1184 " operand%1$d_write = TRUE;\n" |
| 1170 " }\n" | 1185 " }\n" |
| 1171 "", i); | 1186 "", i); |
| 1172 } | 1187 } |
| 1173 } | 1188 } |
| 1174 } | 1189 } |
| 1175 | 1190 |
| 1176 void print_name_actions(void) { | 1191 void print_name_actions(void) { |
| 1177 for (auto pair_it = instruction_names.begin(); | 1192 for (auto pair_it = instruction_names.begin(); |
| 1178 pair_it != instruction_names.end(); ++pair_it) { | 1193 pair_it != instruction_names.end(); ++pair_it) { |
| 1179 auto &pair = *pair_it; | 1194 auto &pair = *pair_it; |
| 1180 fprintf(out_file, " action instruction_%s" | 1195 fprintf(out_file, " action instruction_%s" |
| 1181 " { instruction_name = instruction_names + %zd; }\n", | 1196 " { instruction_name = instruction_names + %zd; }\n", |
| 1182 c_identifier(pair.first).c_str(), pair.second); | 1197 c_identifier(pair.first).c_str(), pair.second); |
| 1183 } | 1198 } |
| 1184 } | 1199 } |
| 1185 | 1200 |
| 1186 class MarkedInstruction : Instruction { | 1201 class MarkedInstruction : Instruction { |
| 1187 public: | 1202 public: |
| 1188 /* Additional marks are created in the process of parsing. */ | 1203 /* Additional marks are created in the process of parsing. */ |
| 1189 explicit MarkedInstruction(Instruction instruction_) : | 1204 explicit MarkedInstruction(Instruction instruction_) : |
| 1190 Instruction(instruction_), | 1205 Instruction(instruction_), |
| 1191 instruction_class(get_instruction_class(instruction_)), | 1206 instruction_class(get_instruction_class(instruction_)), |
| 1192 opcode_in_modrm(false), opcode_in_imm(false), rex { } { | 1207 rex { }, opcode_in_modrm(false), opcode_in_imm(false) { |
| 1193 if (has_flag("branch_hint")) { | 1208 if (has_flag("branch_hint")) { |
| 1194 optional_prefixes.insert("branch_hint"); | 1209 optional_prefixes.insert("branch_hint"); |
| 1195 } | 1210 } |
| 1196 if (has_flag("condrep")) { | 1211 if (has_flag("condrep")) { |
| 1197 optional_prefixes.insert("condrep"); | 1212 optional_prefixes.insert("condrep"); |
| 1198 } | 1213 } |
| 1199 if (has_flag("rep")) { | 1214 if (has_flag("rep")) { |
| 1200 optional_prefixes.insert("rep"); | 1215 optional_prefixes.insert("rep"); |
| 1201 } | 1216 } |
| 1202 for (auto opcode_it = opcodes.begin(); | 1217 for (auto opcode_it = opcodes.begin(); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1230 } | 1245 } |
| 1231 opcode->push_back(')'); | 1246 opcode->push_back(')'); |
| 1232 if (saved_opcode == "0x97") { | 1247 if (saved_opcode == "0x97") { |
| 1233 opcode->erase(1, 5); | 1248 opcode->erase(1, 5); |
| 1234 } | 1249 } |
| 1235 break; | 1250 break; |
| 1236 case '8': | 1251 case '8': |
| 1237 (*opcode) = "("; | 1252 (*opcode) = "("; |
| 1238 opcode->append(saved_opcode); | 1253 opcode->append(saved_opcode); |
| 1239 static const char cc[] = {'9', 'a', 'b', 'c', 'd', 'e', 'f'}; | 1254 static const char cc[] = {'9', 'a', 'b', 'c', 'd', 'e', 'f'}; |
| 1240 for (int c_it = 0; c_it < arraysize(cc); ++c_it) { | 1255 for (size_t c_it = 0; c_it < arraysize(cc); ++c_it) { |
| 1241 auto c = cc[c_it]; | 1256 auto c = cc[c_it]; |
| 1242 opcode->push_back('|'); | 1257 opcode->push_back('|'); |
| 1243 (*(saved_opcode.rbegin())) = c; | 1258 (*(saved_opcode.rbegin())) = c; |
| 1244 opcode->append(saved_opcode); | 1259 opcode->append(saved_opcode); |
| 1245 } | 1260 } |
| 1246 opcode->push_back(')'); | 1261 opcode->push_back(')'); |
| 1247 break; | 1262 break; |
| 1248 default: | 1263 default: |
| 1249 fprintf(stderr, "%s: error - can not use 'r' operand in " | 1264 fprintf(stderr, "%s: error - can not use 'r' operand in " |
| 1250 "instruction '%s'", short_program_name, name.c_str()); | 1265 "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) { | 1517 if (saved_class == InstructionClass::kLSetUnsetDefaultRexW) { |
| 1503 instruction_class = InstructionClass::kRexW; | 1518 instruction_class = InstructionClass::kRexW; |
| 1504 print_one_size_definition_rexw(); | 1519 print_one_size_definition_rexw(); |
| 1505 } | 1520 } |
| 1506 opcode[Lbit] = '0'; | 1521 opcode[Lbit] = '0'; |
| 1507 auto saved_operands = operands; | 1522 auto saved_operands = operands; |
| 1508 for (auto operand_it = operands.begin(); | 1523 for (auto operand_it = operands.begin(); |
| 1509 operand_it != operands.end(); ++operand_it) { | 1524 operand_it != operands.end(); ++operand_it) { |
| 1510 auto &operand = *operand_it; | 1525 auto &operand = *operand_it; |
| 1511 static const char cc[] = {'H', 'L', 'U', 'V', 'W'}; | 1526 static const char cc[] = {'H', 'L', 'U', 'V', 'W'}; |
| 1512 for (int c_it = 0; c_it < arraysize(cc); ++c_it) { | 1527 for (size_t c_it = 0; c_it < arraysize(cc); ++c_it) { |
| 1513 auto c = cc[c_it]; | 1528 auto c = cc[c_it]; |
| 1514 if ((operand.source == c) && | 1529 if ((operand.source == c) && |
| 1515 (*(operand.size.rbegin()) == 'x') && | 1530 (*(operand.size.rbegin()) == 'x') && |
| 1516 (((operand.size.length() > 1) && | 1531 (((operand.size.length() > 1) && |
| 1517 (operand.size[0] == 'p')) || | 1532 (operand.size[0] == 'p')) || |
| 1518 (operand.size.length() == 1))) { | 1533 (operand.size.length() == 1))) { |
| 1519 operand.size.resize(operand.size.length() - 1); | 1534 operand.size.resize(operand.size.length() - 1); |
| 1520 } | 1535 } |
| 1521 } | 1536 } |
| 1522 } | 1537 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1541 } | 1556 } |
| 1542 } | 1557 } |
| 1543 | 1558 |
| 1544 void print_one_size_definition(void) { | 1559 void print_one_size_definition(void) { |
| 1545 /* 64bit commands are not supported in ia32 mode. */ | 1560 /* 64bit commands are not supported in ia32 mode. */ |
| 1546 if (ia32_mode && rex.w) { | 1561 if (ia32_mode && rex.w) { |
| 1547 return; | 1562 return; |
| 1548 } | 1563 } |
| 1549 bool modrm_memory = false; | 1564 bool modrm_memory = false; |
| 1550 bool modrm_register = false; | 1565 bool modrm_register = false; |
| 1551 char operand_source; | 1566 char operand_source = ' '; |
| 1552 for (auto operand_it = operands.begin(); | 1567 for (auto operand_it = operands.begin(); |
| 1553 operand_it != operands.end(); ++operand_it) { | 1568 operand_it != operands.end(); ++operand_it) { |
| 1554 auto &operand = *operand_it; | 1569 auto &operand = *operand_it; |
| 1555 static std::map<char, std::pair<bool, bool> > operand_map { | 1570 static std::map<char, std::pair<bool, bool> > operand_map { |
| 1556 { 'E', std::make_pair(true, true) }, | 1571 { 'E', std::make_pair(true, true) }, |
| 1557 { 'M', std::make_pair(true, false) }, | 1572 { 'M', std::make_pair(true, false) }, |
| 1558 { 'N', std::make_pair(false, true) }, | 1573 { 'N', std::make_pair(false, true) }, |
| 1559 { 'Q', std::make_pair(true, true) }, | 1574 { 'Q', std::make_pair(true, true) }, |
| 1560 { 'R', std::make_pair(false, true) }, | 1575 { 'R', std::make_pair(false, true) }, |
| 1561 { 'U', std::make_pair(false, true) }, | 1576 { 'U', std::make_pair(false, true) }, |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1665 | 1680 |
| 1666 void print_one_size_definition_modrm_memory(void) { | 1681 void print_one_size_definition_modrm_memory(void) { |
| 1667 typedef std::tuple<const char *, bool, bool> T; | 1682 typedef std::tuple<const char *, bool, bool> T; |
| 1668 static const T modes[] = { | 1683 static const T modes[] = { |
| 1669 T { " operand_disp", false, true }, | 1684 T { " operand_disp", false, true }, |
| 1670 T { " operand_rip", false, false }, | 1685 T { " operand_rip", false, false }, |
| 1671 T { " single_register_memory", false, true }, | 1686 T { " single_register_memory", false, true }, |
| 1672 T { " operand_sib_pure_index", true, false }, | 1687 T { " operand_sib_pure_index", true, false }, |
| 1673 T { " operand_sib_base_index", true, true } | 1688 T { " operand_sib_base_index", true, true } |
| 1674 }; | 1689 }; |
| 1675 for (int mode_it = 0; mode_it < arraysize(modes); ++mode_it) { | 1690 for (size_t mode_it = 0; mode_it < arraysize(modes); ++mode_it) { |
| 1676 auto mode = modes[mode_it]; | 1691 auto mode = modes[mode_it]; |
| 1677 print_operator_delimeter(); | 1692 print_operator_delimeter(); |
| 1678 if (mod_reg_is_used()) { | 1693 if (mod_reg_is_used()) { |
| 1679 rex.r = true; | 1694 rex.r = true; |
| 1680 } | 1695 } |
| 1681 if (mod_rm_is_used()) { | 1696 if (mod_rm_is_used()) { |
| 1682 rex.x = std::get<1>(mode); | 1697 rex.x = std::get<1>(mode); |
| 1683 rex.b = std::get<2>(mode); | 1698 rex.b = std::get<2>(mode); |
| 1684 } | 1699 } |
| 1685 print_legacy_prefixes(); | 1700 print_legacy_prefixes(); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1745 | 1760 |
| 1746 bool mod_reg_is_used() { | 1761 bool mod_reg_is_used() { |
| 1747 for (auto operand_it = operands.begin(); | 1762 for (auto operand_it = operands.begin(); |
| 1748 operand_it != operands.end(); ++operand_it) { | 1763 operand_it != operands.end(); ++operand_it) { |
| 1749 auto &operand = *operand_it; | 1764 auto &operand = *operand_it; |
| 1750 if (operand.source == 'C' && | 1765 if (operand.source == 'C' && |
| 1751 required_prefixes.find("0xf0") == required_prefixes.end()) { | 1766 required_prefixes.find("0xf0") == required_prefixes.end()) { |
| 1752 return true; | 1767 return true; |
| 1753 } | 1768 } |
| 1754 static const char cc[] = { 'G', 'P', 'V' }; | 1769 static const char cc[] = { 'G', 'P', 'V' }; |
| 1755 for (int c_it = 0; c_it < arraysize(cc); ++c_it) { | 1770 for (size_t c_it = 0; c_it < arraysize(cc); ++c_it) { |
| 1756 auto c = cc[c_it]; | 1771 auto c = cc[c_it]; |
| 1757 if (operand.source == c) { | 1772 if (operand.source == c) { |
| 1758 return true; | 1773 return true; |
| 1759 } | 1774 } |
| 1760 } | 1775 } |
| 1761 } | 1776 } |
| 1762 return false; | 1777 return false; |
| 1763 } | 1778 } |
| 1764 | 1779 |
| 1765 bool mod_rm_is_used() { | 1780 bool mod_rm_is_used() { |
| 1766 for (auto operand_it = operands.begin(); | 1781 for (auto operand_it = operands.begin(); |
| 1767 operand_it != operands.end(); ++operand_it) { | 1782 operand_it != operands.end(); ++operand_it) { |
| 1768 auto &operand = *operand_it; | 1783 auto &operand = *operand_it; |
| 1769 static const char cc[] = { 'E', 'M', 'N', 'Q', 'R', 'U', 'W' }; | 1784 static const char cc[] = { 'E', 'M', 'N', 'Q', 'R', 'U', 'W' }; |
| 1770 for (int c_it = 0; c_it < arraysize(cc); ++c_it) { | 1785 for (size_t c_it = 0; c_it < arraysize(cc); ++c_it) { |
| 1771 auto c = cc[c_it]; | 1786 auto c = cc[c_it]; |
| 1772 if (operand.source == c) { | 1787 if (operand.source == c) { |
| 1773 return true; | 1788 return true; |
| 1774 } | 1789 } |
| 1775 } | 1790 } |
| 1776 } | 1791 } |
| 1777 return false; | 1792 return false; |
| 1778 } | 1793 } |
| 1779 | 1794 |
| 1780 void print_legacy_prefixes(void) { | 1795 void print_legacy_prefixes(void) { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1911 if (ia32_mode || (!rex.r && !rex.x & !rex.b)) { | 1926 if (ia32_mode || (!rex.r && !rex.x & !rex.b)) { |
| 1912 fprintf(out_file, "NONE"); | 1927 fprintf(out_file, "NONE"); |
| 1913 } else { | 1928 } else { |
| 1914 if (rex.r) fprintf(out_file, "R"); | 1929 if (rex.r) fprintf(out_file, "R"); |
| 1915 if (rex.x) fprintf(out_file, "X"); | 1930 if (rex.x) fprintf(out_file, "X"); |
| 1916 if (rex.b) fprintf(out_file, "B"); | 1931 if (rex.b) fprintf(out_file, "B"); |
| 1917 } | 1932 } |
| 1918 fprintf(out_file, " & VEX_map%s) ", opcodes[1].c_str() + 4); | 1933 fprintf(out_file, " & VEX_map%s) ", opcodes[1].c_str() + 4); |
| 1919 auto third_byte = opcodes[2]; | 1934 auto third_byte = opcodes[2]; |
| 1920 static const char* symbolic_names[] = { "cntl", "dest", "src1", "src" }; | 1935 static const char* symbolic_names[] = { "cntl", "dest", "src1", "src" }; |
| 1921 for (int symbolic_it = 0; | 1936 for (size_t symbolic_it = 0; |
| 1922 symbolic_it < arraysize(symbolic_names); ++symbolic_it) { | 1937 symbolic_it < arraysize(symbolic_names); ++symbolic_it) { |
| 1923 auto symbolic = symbolic_names[symbolic_it]; | 1938 auto symbolic = symbolic_names[symbolic_it]; |
| 1924 for (auto it = third_byte.begin(); it != third_byte.end(); ++it) { | 1939 for (auto it = third_byte.begin(); it != third_byte.end(); ++it) { |
| 1925 if ((third_byte.end() - it) >= strlen(symbolic) && | 1940 if (static_cast<size_t>(third_byte.end() - it) >= |
| 1926 !strncmp(&*it, symbolic, strlen(symbolic))) { | 1941 strlen(symbolic) && |
| 1942 !strncmp(&*it, symbolic, strlen(symbolic))) { | |
|
pasko-google - do not use
2012/04/05 14:16:38
I do not like how this is formatted. Should be shi
khim
2012/04/05 16:38:43
Whatever. I don't really care about this file (I h
| |
| 1927 third_byte.replace(it, it + strlen(symbolic), "XXXX"); | 1943 third_byte.replace(it, it + strlen(symbolic), "XXXX"); |
| 1928 break; | 1944 break; |
| 1929 } | 1945 } |
| 1930 } | 1946 } |
| 1931 } | 1947 } |
| 1932 static const std::set<char> third_byte_check[] { | 1948 static const std::set<char> third_byte_check[] { |
| 1933 { '0', '1', 'x', 'X', 'W' }, | 1949 { '0', '1', 'x', 'X', 'W' }, |
| 1934 { '.' }, | 1950 { '.' }, |
| 1935 { '0', '1', 'x', 'X' }, | 1951 { '0', '1', 'x', 'X' }, |
| 1936 { '0', '1', 'x', 'X' }, | 1952 { '0', '1', 'x', 'X' }, |
| 1937 { '0', '1', 'x', 'X' }, | 1953 { '0', '1', 'x', 'X' }, |
| 1938 { '0', '1', 'x', 'X' }, | 1954 { '0', '1', 'x', 'X' }, |
| 1939 { '.' }, | 1955 { '.' }, |
| 1940 { '0', '1', 'x', 'X' }, | 1956 { '0', '1', 'x', 'X' }, |
| 1941 { '.' }, | 1957 { '.' }, |
| 1942 { '0', '1' }, | 1958 { '0', '1' }, |
| 1943 { '0', '1' } | 1959 { '0', '1' } |
| 1944 }; | 1960 }; |
| 1945 auto third_byte_ok = (arraysize(third_byte_check) == | 1961 auto third_byte_ok = (arraysize(third_byte_check) == |
| 1946 third_byte.length()); | 1962 third_byte.length()); |
|
pasko-google - do not use
2012/04/05 14:16:38
spacing, better be:
bool third_byte_ok =
(arra
khim
2012/04/05 16:38:43
Done.
| |
| 1947 if (third_byte_ok) { | 1963 if (third_byte_ok) { |
| 1948 for (int set_it = 0; set_it < arraysize(third_byte_check); ++set_it) { | 1964 for (size_t set_it = 0; set_it < arraysize(third_byte_check); |
| 1965 ++set_it) { | |
|
pasko-google - do not use
2012/04/05 14:16:38
shiftwidth = 4
khim
2012/04/05 16:38:43
Done.
| |
| 1949 auto &set = third_byte_check[set_it]; | 1966 auto &set = third_byte_check[set_it]; |
| 1950 if (set.find(third_byte[&set - third_byte_check]) == set.end()) { | 1967 if (set.find(third_byte[&set - third_byte_check]) == set.end()) { |
| 1951 third_byte_ok = false; | 1968 third_byte_ok = false; |
| 1952 break; | 1969 break; |
| 1953 } | 1970 } |
| 1954 } | 1971 } |
| 1955 } | 1972 } |
| 1956 if (third_byte_ok) { | 1973 if (third_byte_ok) { |
| 1957 if (ia32_mode && third_byte[2] == 'X') { | 1974 if (ia32_mode && third_byte[2] == 'X') { |
| 1958 third_byte[2] = '1'; | 1975 third_byte[2] = '1'; |
| (...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2487 | 2504 |
| 2488 fprintf(out_file, "\n one_instruction ="); | 2505 fprintf(out_file, "\n one_instruction ="); |
| 2489 | 2506 |
| 2490 print_one_instruction_definition(); | 2507 print_one_instruction_definition(); |
| 2491 | 2508 |
| 2492 fprintf(out_file, ");\n" | 2509 fprintf(out_file, ");\n" |
| 2493 "}%%%%\n" | 2510 "}%%%%\n" |
| 2494 ""); | 2511 ""); |
| 2495 return 0; | 2512 return 0; |
| 2496 } | 2513 } |
| OLD | NEW |