OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 975 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 | 986 |
987 | 987 |
988 // Handle all two-byte opcodes, which start with 0x0F. | 988 // Handle all two-byte opcodes, which start with 0x0F. |
989 // These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix. | 989 // These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix. |
990 // We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A. | 990 // We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A. |
991 int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) { | 991 int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) { |
992 byte opcode = *(data + 1); | 992 byte opcode = *(data + 1); |
993 byte* current = data + 2; | 993 byte* current = data + 2; |
994 // At return, "current" points to the start of the next instruction. | 994 // At return, "current" points to the start of the next instruction. |
995 const char* mnemonic = TwoByteMnemonic(opcode); | 995 const char* mnemonic = TwoByteMnemonic(opcode); |
996 if (opcode == 0x1F) { | 996 if (operand_size_ == 0x66) { |
| 997 // 0x66 0x0F prefix. |
| 998 int mod, regop, rm; |
| 999 get_modrm(*current, &mod, ®op, &rm); |
| 1000 const char* mnemonic = "?"; |
| 1001 if (opcode == 0x57) { |
| 1002 mnemonic = "xorpd"; |
| 1003 } else if (opcode == 0x2E) { |
| 1004 mnemonic = "comisd"; |
| 1005 } else if (opcode == 0x2F) { |
| 1006 mnemonic = "ucomisd"; |
| 1007 } else { |
| 1008 UnimplementedInstruction(); |
| 1009 } |
| 1010 AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop)); |
| 1011 current += PrintRightXMMOperand(current); |
| 1012 } else if (group_1_prefix_ == 0xF2) { |
| 1013 // Beginning of instructions with prefix 0xF2. |
| 1014 |
| 1015 if (opcode == 0x11 || opcode == 0x10) { |
| 1016 // MOVSD: Move scalar double-precision fp to/from/between XMM registers. |
| 1017 AppendToBuffer("movsd "); |
| 1018 int mod, regop, rm; |
| 1019 get_modrm(*current, &mod, ®op, &rm); |
| 1020 if (opcode == 0x11) { |
| 1021 current += PrintRightOperand(current); |
| 1022 AppendToBuffer(",%s", NameOfXMMRegister(regop)); |
| 1023 } else { |
| 1024 AppendToBuffer("%s,", NameOfXMMRegister(regop)); |
| 1025 current += PrintRightOperand(current); |
| 1026 } |
| 1027 } else if (opcode == 0x2A) { |
| 1028 // CVTSI2SD: integer to XMM double conversion. |
| 1029 int mod, regop, rm; |
| 1030 get_modrm(*current, &mod, ®op, &rm); |
| 1031 AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop)); |
| 1032 current += PrintRightOperand(current); |
| 1033 } else if ((opcode & 0xF8) == 0x58) { |
| 1034 // XMM arithmetic. Mnemonic was retrieved at the start of this function. |
| 1035 int mod, regop, rm; |
| 1036 get_modrm(*current, &mod, ®op, &rm); |
| 1037 AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop)); |
| 1038 current += PrintRightXMMOperand(current); |
| 1039 } else { |
| 1040 UnimplementedInstruction(); |
| 1041 } |
| 1042 } else if (opcode == 0x2C && group_1_prefix_ == 0xF3) { |
| 1043 // Instruction with prefix 0xF3. |
| 1044 |
| 1045 // CVTTSS2SI: Convert scalar single-precision FP to dword integer. |
| 1046 // Assert that mod is not 3, so source is memory, not an XMM register. |
| 1047 ASSERT_NE(0xC0, *current & 0xC0); |
| 1048 current += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, current); |
| 1049 } else if (opcode == 0x1F) { |
997 // NOP | 1050 // NOP |
998 int mod, regop, rm; | 1051 int mod, regop, rm; |
999 get_modrm(*current, &mod, ®op, &rm); | 1052 get_modrm(*current, &mod, ®op, &rm); |
1000 current++; | 1053 current++; |
1001 if (regop == 4) { // SIB byte present. | 1054 if (regop == 4) { // SIB byte present. |
1002 current++; | 1055 current++; |
1003 } | 1056 } |
1004 if (mod == 1) { // Byte displacement. | 1057 if (mod == 1) { // Byte displacement. |
1005 current += 1; | 1058 current += 1; |
1006 } else if (mod == 2) { // 32-bit displacement. | 1059 } else if (mod == 2) { // 32-bit displacement. |
1007 current += 4; | 1060 current += 4; |
1008 } // else no immediate displacement. | 1061 } // else no immediate displacement. |
1009 AppendToBuffer("nop"); | 1062 AppendToBuffer("nop"); |
1010 | 1063 } else if (opcode == 0xA2 || opcode == 0x31) { |
1011 } else if (opcode == 0xA2 || opcode == 0x31) { | |
1012 // RDTSC or CPUID | 1064 // RDTSC or CPUID |
1013 AppendToBuffer("%s", mnemonic); | 1065 AppendToBuffer("%s", mnemonic); |
1014 | 1066 |
1015 } else if ((opcode & 0xF0) == 0x40) { | 1067 } else if ((opcode & 0xF0) == 0x40) { |
1016 // CMOVcc: conditional move. | 1068 // CMOVcc: conditional move. |
1017 int condition = opcode & 0x0F; | 1069 int condition = opcode & 0x0F; |
1018 const InstructionDesc& idesc = cmov_instructions[condition]; | 1070 const InstructionDesc& idesc = cmov_instructions[condition]; |
1019 byte_size_operand_ = idesc.byte_size_operation; | 1071 byte_size_operand_ = idesc.byte_size_operation; |
1020 current += PrintOperands(idesc.mnem, idesc.op_order_, current); | 1072 current += PrintOperands(idesc.mnem, idesc.op_order_, current); |
1021 | 1073 |
(...skipping 14 matching lines...) Expand all Loading... |
1036 // SHLD, SHRD (double-precision shift), BTS (bit set). | 1088 // SHLD, SHRD (double-precision shift), BTS (bit set). |
1037 AppendToBuffer("%s ", mnemonic); | 1089 AppendToBuffer("%s ", mnemonic); |
1038 int mod, regop, rm; | 1090 int mod, regop, rm; |
1039 get_modrm(*current, &mod, ®op, &rm); | 1091 get_modrm(*current, &mod, ®op, &rm); |
1040 current += PrintRightOperand(current); | 1092 current += PrintRightOperand(current); |
1041 if (opcode == 0xAB) { | 1093 if (opcode == 0xAB) { |
1042 AppendToBuffer(",%s", NameOfCPURegister(regop)); | 1094 AppendToBuffer(",%s", NameOfCPURegister(regop)); |
1043 } else { | 1095 } else { |
1044 AppendToBuffer(",%s,cl", NameOfCPURegister(regop)); | 1096 AppendToBuffer(",%s,cl", NameOfCPURegister(regop)); |
1045 } | 1097 } |
1046 } else if (group_1_prefix_ == 0xF2) { | |
1047 // Beginning of instructions with prefix 0xF2. | |
1048 | |
1049 if (opcode == 0x11 || opcode == 0x10) { | |
1050 // MOVSD: Move scalar double-precision fp to/from/between XMM registers. | |
1051 AppendToBuffer("movsd "); | |
1052 int mod, regop, rm; | |
1053 get_modrm(*current, &mod, ®op, &rm); | |
1054 if (opcode == 0x11) { | |
1055 current += PrintRightOperand(current); | |
1056 AppendToBuffer(",%s", NameOfXMMRegister(regop)); | |
1057 } else { | |
1058 AppendToBuffer("%s,", NameOfXMMRegister(regop)); | |
1059 current += PrintRightOperand(current); | |
1060 } | |
1061 } else if (opcode == 0x2A) { | |
1062 // CVTSI2SD: integer to XMM double conversion. | |
1063 int mod, regop, rm; | |
1064 get_modrm(*current, &mod, ®op, &rm); | |
1065 AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop)); | |
1066 current += PrintRightOperand(current); | |
1067 } else if ((opcode & 0xF8) == 0x58) { | |
1068 // XMM arithmetic. Mnemonic was retrieved at the start of this function. | |
1069 int mod, regop, rm; | |
1070 get_modrm(*current, &mod, ®op, &rm); | |
1071 AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop)); | |
1072 current += PrintRightXMMOperand(current); | |
1073 } else { | |
1074 UnimplementedInstruction(); | |
1075 } | |
1076 } else if (opcode == 0x2C && group_1_prefix_ == 0xF3) { | |
1077 // Instruction with prefix 0xF3. | |
1078 | |
1079 // CVTTSS2SI: Convert scalar single-precision FP to dword integer. | |
1080 // Assert that mod is not 3, so source is memory, not an XMM register. | |
1081 ASSERT_NE(0xC0, *current & 0xC0); | |
1082 current += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, current); | |
1083 } else { | 1098 } else { |
1084 UnimplementedInstruction(); | 1099 UnimplementedInstruction(); |
1085 } | 1100 } |
1086 return static_cast<int>(current - data); | 1101 return static_cast<int>(current - data); |
1087 } | 1102 } |
1088 | 1103 |
1089 | 1104 |
1090 // Mnemonics for two-byte opcode instructions starting with 0x0F. | 1105 // Mnemonics for two-byte opcode instructions starting with 0x0F. |
1091 // The argument is the second byte of the two-byte opcode. | 1106 // The argument is the second byte of the two-byte opcode. |
1092 // Returns NULL if the instruction is not handled here. | 1107 // Returns NULL if the instruction is not handled here. |
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1611 fprintf(f, "%02x", *bp); | 1626 fprintf(f, "%02x", *bp); |
1612 } | 1627 } |
1613 for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) { | 1628 for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) { |
1614 fprintf(f, " "); | 1629 fprintf(f, " "); |
1615 } | 1630 } |
1616 fprintf(f, " %s\n", buffer.start()); | 1631 fprintf(f, " %s\n", buffer.start()); |
1617 } | 1632 } |
1618 } | 1633 } |
1619 | 1634 |
1620 } // namespace disasm | 1635 } // namespace disasm |
OLD | NEW |