OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <assert.h> | 5 #include <assert.h> |
6 #include <stdarg.h> | 6 #include <stdarg.h> |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 bool rex_r() { return (rex_ & 0x04) != 0; } | 352 bool rex_r() { return (rex_ & 0x04) != 0; } |
353 | 353 |
354 bool rex_w() { return (rex_ & 0x08) != 0; } | 354 bool rex_w() { return (rex_ & 0x08) != 0; } |
355 | 355 |
356 bool vex_128() { | 356 bool vex_128() { |
357 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX); | 357 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX); |
358 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_; | 358 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_; |
359 return (checked & 4) != 1; | 359 return (checked & 4) != 1; |
360 } | 360 } |
361 | 361 |
| 362 bool vex_none() { |
| 363 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX); |
| 364 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_; |
| 365 return (checked & 3) == 0; |
| 366 } |
| 367 |
362 bool vex_66() { | 368 bool vex_66() { |
363 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX); | 369 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX); |
364 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_; | 370 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_; |
365 return (checked & 3) == 1; | 371 return (checked & 3) == 1; |
366 } | 372 } |
367 | 373 |
368 bool vex_f3() { | 374 bool vex_f3() { |
369 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX); | 375 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX); |
370 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_; | 376 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_; |
371 return (checked & 3) == 2; | 377 return (checked & 3) == 2; |
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
933 case 0xaf: | 939 case 0xaf: |
934 AppendToBuffer("vfnmsub213s%c %s,%s,", float_size_code(), | 940 AppendToBuffer("vfnmsub213s%c %s,%s,", float_size_code(), |
935 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); | 941 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); |
936 current += PrintRightXMMOperand(current); | 942 current += PrintRightXMMOperand(current); |
937 break; | 943 break; |
938 case 0xbf: | 944 case 0xbf: |
939 AppendToBuffer("vfnmsub231s%c %s,%s,", float_size_code(), | 945 AppendToBuffer("vfnmsub231s%c %s,%s,", float_size_code(), |
940 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); | 946 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); |
941 current += PrintRightXMMOperand(current); | 947 current += PrintRightXMMOperand(current); |
942 break; | 948 break; |
| 949 case 0xf7: |
| 950 AppendToBuffer("shlx%c %s,", operand_size_code(), |
| 951 NameOfCPURegister(regop)); |
| 952 current += PrintRightOperand(current); |
| 953 AppendToBuffer(",%s", NameOfCPURegister(vvvv)); |
| 954 break; |
943 default: | 955 default: |
944 UnimplementedInstruction(); | 956 UnimplementedInstruction(); |
945 } | 957 } |
946 } else if (vex_f3() && vex_0f()) { | 958 } else if (vex_f3() && vex_0f()) { |
947 int mod, regop, rm, vvvv = vex_vreg(); | 959 int mod, regop, rm, vvvv = vex_vreg(); |
948 get_modrm(*current, &mod, ®op, &rm); | 960 get_modrm(*current, &mod, ®op, &rm); |
949 switch (opcode) { | 961 switch (opcode) { |
950 case 0x58: | 962 case 0x58: |
951 AppendToBuffer("vaddss %s,%s,", NameOfXMMRegister(regop), | 963 AppendToBuffer("vaddss %s,%s,", NameOfXMMRegister(regop), |
952 NameOfXMMRegister(vvvv)); | 964 NameOfXMMRegister(vvvv)); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1010 current += PrintRightXMMOperand(current); | 1022 current += PrintRightXMMOperand(current); |
1011 break; | 1023 break; |
1012 case 0x5f: | 1024 case 0x5f: |
1013 AppendToBuffer("vmaxsd %s,%s,", NameOfXMMRegister(regop), | 1025 AppendToBuffer("vmaxsd %s,%s,", NameOfXMMRegister(regop), |
1014 NameOfXMMRegister(vvvv)); | 1026 NameOfXMMRegister(vvvv)); |
1015 current += PrintRightXMMOperand(current); | 1027 current += PrintRightXMMOperand(current); |
1016 break; | 1028 break; |
1017 default: | 1029 default: |
1018 UnimplementedInstruction(); | 1030 UnimplementedInstruction(); |
1019 } | 1031 } |
| 1032 } else if (vex_none() && vex_0f38()) { |
| 1033 int mod, regop, rm, vvvv = vex_vreg(); |
| 1034 get_modrm(*current, &mod, ®op, &rm); |
| 1035 const char* mnem = "?"; |
| 1036 switch (opcode) { |
| 1037 case 0xf2: |
| 1038 AppendToBuffer("andn%c %s,%s,", operand_size_code(), |
| 1039 NameOfCPURegister(regop), NameOfCPURegister(vvvv)); |
| 1040 current += PrintRightOperand(current); |
| 1041 break; |
| 1042 case 0xf5: |
| 1043 AppendToBuffer("bzhi%c %s,", operand_size_code(), |
| 1044 NameOfCPURegister(regop)); |
| 1045 current += PrintRightOperand(current); |
| 1046 AppendToBuffer(",%s", NameOfCPURegister(vvvv)); |
| 1047 break; |
| 1048 case 0xf7: |
| 1049 AppendToBuffer("bextr%c %s,", operand_size_code(), |
| 1050 NameOfCPURegister(regop)); |
| 1051 current += PrintRightOperand(current); |
| 1052 AppendToBuffer(",%s", NameOfCPURegister(vvvv)); |
| 1053 break; |
| 1054 case 0xf3: |
| 1055 switch (regop) { |
| 1056 case 1: |
| 1057 mnem = "blsr"; |
| 1058 break; |
| 1059 case 2: |
| 1060 mnem = "blsmsk"; |
| 1061 break; |
| 1062 case 3: |
| 1063 mnem = "blsi"; |
| 1064 break; |
| 1065 default: |
| 1066 UnimplementedInstruction(); |
| 1067 } |
| 1068 AppendToBuffer("%s%c %s,", mnem, operand_size_code(), |
| 1069 NameOfCPURegister(vvvv)); |
| 1070 current += PrintRightOperand(current); |
| 1071 mnem = "?"; |
| 1072 break; |
| 1073 default: |
| 1074 UnimplementedInstruction(); |
| 1075 } |
| 1076 } else if (vex_f2() && vex_0f38()) { |
| 1077 int mod, regop, rm, vvvv = vex_vreg(); |
| 1078 get_modrm(*current, &mod, ®op, &rm); |
| 1079 switch (opcode) { |
| 1080 case 0xf5: |
| 1081 AppendToBuffer("pdep%c %s,%s,", operand_size_code(), |
| 1082 NameOfCPURegister(regop), NameOfCPURegister(vvvv)); |
| 1083 current += PrintRightOperand(current); |
| 1084 break; |
| 1085 case 0xf6: |
| 1086 AppendToBuffer("mulx%c %s,%s,", operand_size_code(), |
| 1087 NameOfCPURegister(regop), NameOfCPURegister(vvvv)); |
| 1088 current += PrintRightOperand(current); |
| 1089 break; |
| 1090 case 0xf7: |
| 1091 AppendToBuffer("shrx%c %s,", operand_size_code(), |
| 1092 NameOfCPURegister(regop)); |
| 1093 current += PrintRightOperand(current); |
| 1094 AppendToBuffer(",%s", NameOfCPURegister(vvvv)); |
| 1095 break; |
| 1096 default: |
| 1097 UnimplementedInstruction(); |
| 1098 } |
| 1099 } else if (vex_f3() && vex_0f38()) { |
| 1100 int mod, regop, rm, vvvv = vex_vreg(); |
| 1101 get_modrm(*current, &mod, ®op, &rm); |
| 1102 switch (opcode) { |
| 1103 case 0xf5: |
| 1104 AppendToBuffer("pext%c %s,%s,", operand_size_code(), |
| 1105 NameOfCPURegister(regop), NameOfCPURegister(vvvv)); |
| 1106 current += PrintRightOperand(current); |
| 1107 break; |
| 1108 case 0xf7: |
| 1109 AppendToBuffer("sarx%c %s,", operand_size_code(), |
| 1110 NameOfCPURegister(regop)); |
| 1111 current += PrintRightOperand(current); |
| 1112 AppendToBuffer(",%s", NameOfCPURegister(vvvv)); |
| 1113 break; |
| 1114 default: |
| 1115 UnimplementedInstruction(); |
| 1116 } |
| 1117 } else if (vex_f2() && vex_0f3a()) { |
| 1118 int mod, regop, rm; |
| 1119 get_modrm(*current, &mod, ®op, &rm); |
| 1120 switch (opcode) { |
| 1121 case 0xf0: |
| 1122 AppendToBuffer("rorx%c %s,", operand_size_code(), |
| 1123 NameOfCPURegister(regop)); |
| 1124 current += PrintRightOperand(current); |
| 1125 switch (operand_size()) { |
| 1126 case OPERAND_DOUBLEWORD_SIZE: |
| 1127 AppendToBuffer(",%d", *current & 0x1f); |
| 1128 break; |
| 1129 case OPERAND_QUADWORD_SIZE: |
| 1130 AppendToBuffer(",%d", *current & 0x3f); |
| 1131 break; |
| 1132 default: |
| 1133 UnimplementedInstruction(); |
| 1134 } |
| 1135 current += 1; |
| 1136 break; |
| 1137 default: |
| 1138 UnimplementedInstruction(); |
| 1139 } |
1020 } else { | 1140 } else { |
1021 UnimplementedInstruction(); | 1141 UnimplementedInstruction(); |
1022 } | 1142 } |
1023 | 1143 |
1024 return static_cast<int>(current - data); | 1144 return static_cast<int>(current - data); |
1025 } | 1145 } |
1026 | 1146 |
1027 | 1147 |
1028 // Returns number of bytes used, including *data. | 1148 // Returns number of bytes used, including *data. |
1029 int DisassemblerX64::FPUInstruction(byte* data) { | 1149 int DisassemblerX64::FPUInstruction(byte* data) { |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1424 int mod, regop, rm; | 1544 int mod, regop, rm; |
1425 get_modrm(*current, &mod, ®op, &rm); | 1545 get_modrm(*current, &mod, ®op, &rm); |
1426 AppendToBuffer("movq %s,", NameOfXMMRegister(regop)); | 1546 AppendToBuffer("movq %s,", NameOfXMMRegister(regop)); |
1427 current += PrintRightXMMOperand(current); | 1547 current += PrintRightXMMOperand(current); |
1428 } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) { | 1548 } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) { |
1429 // XMM arithmetic. Mnemonic was retrieved at the start of this function. | 1549 // XMM arithmetic. Mnemonic was retrieved at the start of this function. |
1430 int mod, regop, rm; | 1550 int mod, regop, rm; |
1431 get_modrm(*current, &mod, ®op, &rm); | 1551 get_modrm(*current, &mod, ®op, &rm); |
1432 AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop)); | 1552 AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop)); |
1433 current += PrintRightXMMOperand(current); | 1553 current += PrintRightXMMOperand(current); |
| 1554 } else if (opcode == 0xB8) { |
| 1555 int mod, regop, rm; |
| 1556 get_modrm(*current, &mod, ®op, &rm); |
| 1557 AppendToBuffer("popcnt%c %s,", operand_size_code(), |
| 1558 NameOfCPURegister(regop)); |
| 1559 current += PrintRightOperand(current); |
| 1560 } else if (opcode == 0xBC) { |
| 1561 int mod, regop, rm; |
| 1562 get_modrm(*current, &mod, ®op, &rm); |
| 1563 AppendToBuffer("tzcnt%c %s,", operand_size_code(), |
| 1564 NameOfCPURegister(regop)); |
| 1565 current += PrintRightOperand(current); |
| 1566 } else if (opcode == 0xBD) { |
| 1567 int mod, regop, rm; |
| 1568 get_modrm(*current, &mod, ®op, &rm); |
| 1569 AppendToBuffer("lzcnt%c %s,", operand_size_code(), |
| 1570 NameOfCPURegister(regop)); |
| 1571 current += PrintRightOperand(current); |
1434 } else if (opcode == 0xC2) { | 1572 } else if (opcode == 0xC2) { |
1435 // Intel manual 2A, Table 3-18. | 1573 // Intel manual 2A, Table 3-18. |
1436 int mod, regop, rm; | 1574 int mod, regop, rm; |
1437 get_modrm(*current, &mod, ®op, &rm); | 1575 get_modrm(*current, &mod, ®op, &rm); |
1438 const char* const pseudo_op[] = {"cmpeqss", "cmpltss", "cmpless", | 1576 const char* const pseudo_op[] = {"cmpeqss", "cmpltss", "cmpless", |
1439 "cmpunordss", "cmpneqss", "cmpnltss", | 1577 "cmpunordss", "cmpneqss", "cmpnltss", |
1440 "cmpnless", "cmpordss"}; | 1578 "cmpnless", "cmpordss"}; |
1441 AppendToBuffer("%s %s,%s", pseudo_op[current[1]], | 1579 AppendToBuffer("%s %s,%s", pseudo_op[current[1]], |
1442 NameOfXMMRegister(regop), NameOfXMMRegister(rm)); | 1580 NameOfXMMRegister(regop), NameOfXMMRegister(rm)); |
1443 current += 2; | 1581 current += 2; |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1636 } else if ((current & 0xF0) == 0x40) { // REX prefix. | 1774 } else if ((current & 0xF0) == 0x40) { // REX prefix. |
1637 setRex(current); | 1775 setRex(current); |
1638 if (rex_w()) AppendToBuffer("REX.W "); | 1776 if (rex_w()) AppendToBuffer("REX.W "); |
1639 } else if ((current & 0xFE) == 0xF2) { // Group 1 prefix (0xF2 or 0xF3). | 1777 } else if ((current & 0xFE) == 0xF2) { // Group 1 prefix (0xF2 or 0xF3). |
1640 group_1_prefix_ = current; | 1778 group_1_prefix_ = current; |
1641 } else if (current == VEX3_PREFIX) { | 1779 } else if (current == VEX3_PREFIX) { |
1642 vex_byte0_ = current; | 1780 vex_byte0_ = current; |
1643 vex_byte1_ = *(data + 1); | 1781 vex_byte1_ = *(data + 1); |
1644 vex_byte2_ = *(data + 2); | 1782 vex_byte2_ = *(data + 2); |
1645 setRex(0x40 | (~(vex_byte1_ >> 5) & 7) | ((vex_byte2_ >> 4) & 8)); | 1783 setRex(0x40 | (~(vex_byte1_ >> 5) & 7) | ((vex_byte2_ >> 4) & 8)); |
1646 data += 2; | 1784 data += 3; |
| 1785 break; // Vex is the last prefix. |
1647 } else if (current == VEX2_PREFIX) { | 1786 } else if (current == VEX2_PREFIX) { |
1648 vex_byte0_ = current; | 1787 vex_byte0_ = current; |
1649 vex_byte1_ = *(data + 1); | 1788 vex_byte1_ = *(data + 1); |
1650 setRex(0x40 | (~(vex_byte1_ >> 5) & 4)); | 1789 setRex(0x40 | (~(vex_byte1_ >> 5) & 4)); |
1651 data++; | 1790 data += 2; |
| 1791 break; // Vex is the last prefix. |
1652 } else { // Not a prefix - an opcode. | 1792 } else { // Not a prefix - an opcode. |
1653 break; | 1793 break; |
1654 } | 1794 } |
1655 data++; | 1795 data++; |
1656 } | 1796 } |
1657 | 1797 |
1658 // Decode AVX instructions. | 1798 // Decode AVX instructions. |
1659 if (vex_byte0_ != 0) { | 1799 if (vex_byte0_ != 0) { |
1660 processed = true; | 1800 processed = true; |
1661 data += AVXInstruction(data); | 1801 data += AVXInstruction(data); |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2176 for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) { | 2316 for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) { |
2177 fprintf(f, " "); | 2317 fprintf(f, " "); |
2178 } | 2318 } |
2179 fprintf(f, " %s\n", buffer.start()); | 2319 fprintf(f, " %s\n", buffer.start()); |
2180 } | 2320 } |
2181 } | 2321 } |
2182 | 2322 |
2183 } // namespace disasm | 2323 } // namespace disasm |
2184 | 2324 |
2185 #endif // V8_TARGET_ARCH_X64 | 2325 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |