Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/disassembler.h" | 5 #include "vm/disassembler.h" |
| 6 | 6 |
| 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 8 #if defined(TARGET_ARCH_IA32) | 8 #if defined(TARGET_ARCH_IA32) |
| 9 #include "platform/utils.h" | 9 #include "platform/utils.h" |
| 10 #include "vm/allocation.h" | 10 #include "vm/allocation.h" |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 esp = 4, | 266 esp = 4, |
| 267 ebp = 5, | 267 ebp = 5, |
| 268 esi = 6, | 268 esi = 6, |
| 269 edi = 7 | 269 edi = 7 |
| 270 }; | 270 }; |
| 271 | 271 |
| 272 // Bottleneck functions to print into the out_buffer. | 272 // Bottleneck functions to print into the out_buffer. |
| 273 void PrintInt(int value); | 273 void PrintInt(int value); |
| 274 void PrintHex(int value); | 274 void PrintHex(int value); |
| 275 void Print(const char* str); | 275 void Print(const char* str); |
| 276 const char* GetBranchPrefix(uint8_t** data); | |
| 277 | |
| 278 bool DecodeInstructionType(const InstructionDesc& idesc, | |
| 279 const char* branch_hint, | |
| 280 uint8_t** data); | |
| 276 | 281 |
| 277 // Printing of common values. | 282 // Printing of common values. |
| 278 void PrintCPURegister(int reg); | 283 void PrintCPURegister(int reg); |
| 279 void PrintCPUByteRegister(int reg); | 284 void PrintCPUByteRegister(int reg); |
| 280 void PrintXmmRegister(int reg); | 285 void PrintXmmRegister(int reg); |
| 281 void PrintAddress(uword addr); | 286 void PrintAddress(uword addr); |
| 282 | 287 |
| 283 typedef void (X86Decoder::*RegisterNamePrinter)(int reg); | 288 typedef void (X86Decoder::*RegisterNamePrinter)(int reg); |
| 284 | 289 |
| 285 int PrintRightOperandHelper(uint8_t* modrmp, | 290 int PrintRightOperandHelper(uint8_t* modrmp, |
| (...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 949 void X86Decoder::CheckPrintStop(uint8_t* data) { | 954 void X86Decoder::CheckPrintStop(uint8_t* data) { |
| 950 // Recognize stop pattern. | 955 // Recognize stop pattern. |
| 951 if (*reinterpret_cast<uint8_t*>(data + 5) == 0xCC) { | 956 if (*reinterpret_cast<uint8_t*>(data + 5) == 0xCC) { |
| 952 Print(" STOP:'"); | 957 Print(" STOP:'"); |
| 953 const char* text = *reinterpret_cast<const char **>(data + 1); | 958 const char* text = *reinterpret_cast<const char **>(data + 1); |
| 954 Print(text); | 959 Print(text); |
| 955 Print("'"); | 960 Print("'"); |
| 956 } | 961 } |
| 957 } | 962 } |
| 958 | 963 |
| 964 const char* X86Decoder::GetBranchPrefix(uint8_t** data) { | |
| 965 // We use these two prefixes only with branch prediction | |
| 966 switch (**data) { | |
| 967 case 0x3E: // ds | |
| 968 (*data)++; | |
| 969 return "predicted taken"; | |
| 970 case 0x2E: // cs | |
| 971 (*data)++; | |
| 972 return "predicted not taken"; | |
| 973 case 0xF0: // lock | |
| 974 Print("lock "); | |
| 975 (*data)++; | |
| 976 return NULL; | |
| 977 default: // Ignore all other instructions. | |
| 978 return NULL; | |
| 979 } | |
| 980 } | |
| 981 | |
| 982 | |
| 983 bool X86Decoder::DecodeInstructionType(const InstructionDesc& idesc, | |
| 984 const char* branch_hint, | |
| 985 uint8_t** data) { | |
| 986 switch (idesc.type) { | |
| 987 case ZERO_OPERANDS_INSTR: | |
| 988 Print(idesc.mnem); | |
| 989 (*data)++; | |
| 990 return true; | |
| 991 | |
| 992 case TWO_OPERANDS_INSTR: | |
| 993 (*data)++; | |
| 994 (*data) += PrintOperands(idesc.mnem, idesc.op_order_, *data); | |
| 995 return true; | |
| 996 | |
| 997 case JUMP_CONDITIONAL_SHORT_INSTR: | |
| 998 (*data) += JumpConditionalShort(*data, branch_hint); | |
| 999 return true; | |
| 1000 | |
| 1001 case REGISTER_INSTR: | |
| 1002 Print(idesc.mnem); | |
| 1003 Print(" "); | |
| 1004 PrintCPURegister(**data & 0x07); | |
| 1005 (*data)++; | |
| 1006 return true; | |
| 1007 | |
| 1008 case MOVE_REG_INSTR: { | |
| 1009 uword addr = *reinterpret_cast<uword*>((*data)+1); | |
|
regis
2012/02/06 21:45:19
Extra pair of parenthesis around *data is not cons
srdjan
2012/02/06 22:07:24
Done.
| |
| 1010 Print("mov "); | |
| 1011 PrintCPURegister(**data & 0x07), | |
| 1012 Print(","); | |
| 1013 PrintAddress(addr); | |
| 1014 (*data) += 5; | |
| 1015 return true; | |
| 1016 } | |
| 1017 | |
| 1018 case CALL_JUMP_INSTR: { | |
| 1019 uword addr = reinterpret_cast<uword>(data) + | |
| 1020 *reinterpret_cast<uword*>(*data+1) + 5; | |
| 1021 Print(idesc.mnem); | |
| 1022 Print(" "); | |
| 1023 PrintAddress(addr); | |
| 1024 (*data) += 5; | |
| 1025 return true; | |
| 1026 } | |
| 1027 | |
| 1028 case SHORT_IMMEDIATE_INSTR: { | |
| 1029 uword addr = *reinterpret_cast<uword*>(*data+1); | |
| 1030 Print(idesc.mnem); | |
| 1031 Print(" eax, "); | |
| 1032 PrintAddress(addr); | |
| 1033 (*data) += 5; | |
| 1034 return true; | |
| 1035 } | |
| 1036 | |
| 1037 case NO_INSTR: | |
| 1038 return false; | |
| 1039 | |
| 1040 default: | |
| 1041 UNIMPLEMENTED(); // This type is not implemented. | |
| 1042 return false; | |
| 1043 } | |
| 1044 } | |
| 1045 | |
| 959 | 1046 |
| 960 int X86Decoder::InstructionDecode(uword pc) { | 1047 int X86Decoder::InstructionDecode(uword pc) { |
| 961 uint8_t* data = reinterpret_cast<uint8_t*>(pc); | 1048 uint8_t* data = reinterpret_cast<uint8_t*>(pc); |
| 962 // Check for hints. | 1049 // Check for hints. |
| 963 const char* branch_hint = NULL; | 1050 const char* branch_hint = GetBranchPrefix(&data); |
| 964 // We use these two prefixes only with branch prediction | 1051 const InstructionDesc& idesc = instruction_table.Get(*data); |
| 965 switch (*data) { | 1052 // Will be set to false if the current instruction |
| 966 case 0x3E: // ds | |
| 967 branch_hint = "predicted taken"; | |
| 968 data++; | |
| 969 break; | |
| 970 case 0x2E: // cs | |
| 971 branch_hint = "predicted not taken"; | |
| 972 data++; | |
| 973 break; | |
| 974 case 0xF0: // lock | |
| 975 Print("lock "); | |
| 976 data++; | |
| 977 break; | |
| 978 default: // Ignore all other instructions. | |
| 979 break; | |
| 980 } | |
| 981 bool processed = true; // Will be set to false if the current instruction | |
| 982 // is not in 'instructions' table. | 1053 // is not in 'instructions' table. |
| 983 const InstructionDesc& idesc = instruction_table.Get(*data); | 1054 bool processed = DecodeInstructionType(idesc, branch_hint, &data); |
| 984 switch (idesc.type) { | |
| 985 case ZERO_OPERANDS_INSTR: | |
| 986 Print(idesc.mnem); | |
| 987 data++; | |
| 988 break; | |
| 989 | |
| 990 case TWO_OPERANDS_INSTR: | |
| 991 data++; | |
| 992 data += PrintOperands(idesc.mnem, idesc.op_order_, data); | |
| 993 break; | |
| 994 | |
| 995 case JUMP_CONDITIONAL_SHORT_INSTR: | |
| 996 data += JumpConditionalShort(data, branch_hint); | |
| 997 break; | |
| 998 | |
| 999 case REGISTER_INSTR: | |
| 1000 Print(idesc.mnem); | |
| 1001 Print(" "); | |
| 1002 PrintCPURegister(*data & 0x07); | |
| 1003 data++; | |
| 1004 break; | |
| 1005 | |
| 1006 case MOVE_REG_INSTR: { | |
| 1007 uword addr = *reinterpret_cast<uword*>(data+1); | |
| 1008 Print("mov "); | |
| 1009 PrintCPURegister(*data & 0x07), | |
| 1010 Print(","); | |
| 1011 PrintAddress(addr); | |
| 1012 data += 5; | |
| 1013 break; | |
| 1014 } | |
| 1015 | |
| 1016 case CALL_JUMP_INSTR: { | |
| 1017 uword addr = reinterpret_cast<uword>(data) + | |
| 1018 *reinterpret_cast<uword*>(data+1) + 5; | |
| 1019 Print(idesc.mnem); | |
| 1020 Print(" "); | |
| 1021 PrintAddress(addr); | |
| 1022 data += 5; | |
| 1023 break; | |
| 1024 } | |
| 1025 | |
| 1026 case SHORT_IMMEDIATE_INSTR: { | |
| 1027 uword addr = *reinterpret_cast<uword*>(data+1); | |
| 1028 Print(idesc.mnem); | |
| 1029 Print(" eax, "); | |
| 1030 PrintAddress(addr); | |
| 1031 data += 5; | |
| 1032 break; | |
| 1033 } | |
| 1034 | |
| 1035 case NO_INSTR: | |
| 1036 processed = false; | |
| 1037 break; | |
| 1038 | |
| 1039 default: | |
| 1040 UNIMPLEMENTED(); // This type is not implemented. | |
| 1041 } | |
| 1042 //---------------------------- | 1055 //---------------------------- |
| 1043 if (!processed) { | 1056 if (!processed) { |
| 1044 switch (*data) { | 1057 switch (*data) { |
| 1045 case 0xC2: | 1058 case 0xC2: |
| 1046 Print("ret "); | 1059 Print("ret "); |
| 1047 PrintHex(*reinterpret_cast<uint16_t*>(data+1)); | 1060 PrintHex(*reinterpret_cast<uint16_t*>(data+1)); |
| 1048 data += 3; | 1061 data += 3; |
| 1049 break; | 1062 break; |
| 1050 | 1063 |
| 1051 case 0x69: // fall through | 1064 case 0x69: // fall through |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1294 Print(" "); | 1307 Print(" "); |
| 1295 PrintXmmRegister(regop); | 1308 PrintXmmRegister(regop); |
| 1296 Print(","); | 1309 Print(","); |
| 1297 data += PrintRightXmmOperand(data); | 1310 data += PrintRightXmmOperand(data); |
| 1298 } else if (*data == 0x1F && | 1311 } else if (*data == 0x1F && |
| 1299 *(data+1) == 0x44 && | 1312 *(data+1) == 0x44 && |
| 1300 *(data+2) == 0x00 && | 1313 *(data+2) == 0x00 && |
| 1301 *(data+3) == 0x00) { | 1314 *(data+3) == 0x00) { |
| 1302 data += 4; | 1315 data += 4; |
| 1303 Print("nop"); | 1316 Print("nop"); |
| 1317 } else if (*data == 0x50) { | |
| 1318 Print("movmskpd "); | |
| 1319 data++; | |
| 1320 int mod, regop, rm; | |
| 1321 GetModRm(*data, &mod, ®op, &rm); | |
| 1322 PrintCPURegister(regop); | |
| 1323 Print(","); | |
| 1324 data += PrintRightXmmOperand(data); | |
| 1304 } else { | 1325 } else { |
| 1305 UNIMPLEMENTED(); | 1326 UNIMPLEMENTED(); |
| 1306 } | 1327 } |
| 1307 } else if (*data == 0x90) { | 1328 } else if (*data == 0x90) { |
| 1308 data++; | 1329 data++; |
| 1309 Print("nop"); | 1330 Print("nop"); |
| 1310 } else { | 1331 } else { |
| 1311 UNIMPLEMENTED(); | 1332 UNIMPLEMENTED(); |
| 1312 } | 1333 } |
| 1313 break; | 1334 break; |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1575 human_buffer, | 1596 human_buffer, |
| 1576 sizeof(human_buffer), | 1597 sizeof(human_buffer), |
| 1577 pc); | 1598 pc); |
| 1578 pc += instruction_length; | 1599 pc += instruction_length; |
| 1579 } | 1600 } |
| 1580 } | 1601 } |
| 1581 | 1602 |
| 1582 } // namespace dart | 1603 } // namespace dart |
| 1583 | 1604 |
| 1584 #endif // defined TARGET_ARCH_IA32 | 1605 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |