| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 out_buffer_pos_(0) { | 82 out_buffer_pos_(0) { |
| 83 out_buffer_[out_buffer_pos_] = '\0'; | 83 out_buffer_[out_buffer_pos_] = '\0'; |
| 84 } | 84 } |
| 85 | 85 |
| 86 ~Decoder() {} | 86 ~Decoder() {} |
| 87 | 87 |
| 88 // Writes one disassembled instruction into 'buffer' (0-terminated). | 88 // Writes one disassembled instruction into 'buffer' (0-terminated). |
| 89 // Returns the length of the disassembled machine instruction in bytes. | 89 // Returns the length of the disassembled machine instruction in bytes. |
| 90 int InstructionDecode(byte* instruction); | 90 int InstructionDecode(byte* instruction); |
| 91 | 91 |
| 92 static bool IsConstantPoolAt(byte* instr_ptr); |
| 93 static int ConstantPoolSizeAt(byte* instr_ptr); |
| 94 |
| 92 private: | 95 private: |
| 93 // Bottleneck functions to print into the out_buffer. | 96 // Bottleneck functions to print into the out_buffer. |
| 94 void PrintChar(const char ch); | 97 void PrintChar(const char ch); |
| 95 void Print(const char* str); | 98 void Print(const char* str); |
| 96 | 99 |
| 97 // Printing of common values. | 100 // Printing of common values. |
| 98 void PrintRegister(int reg); | 101 void PrintRegister(int reg); |
| 99 void PrintSRegister(int reg); | 102 void PrintSRegister(int reg); |
| 100 void PrintDRegister(int reg); | 103 void PrintDRegister(int reg); |
| 101 int FormatVFPRegister(Instruction* instr, const char* format); | 104 int FormatVFPRegister(Instruction* instr, const char* format); |
| (...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 } | 895 } |
| 893 } | 896 } |
| 894 } | 897 } |
| 895 | 898 |
| 896 | 899 |
| 897 void Decoder::DecodeType2(Instruction* instr) { | 900 void Decoder::DecodeType2(Instruction* instr) { |
| 898 switch (instr->PUField()) { | 901 switch (instr->PUField()) { |
| 899 case da_x: { | 902 case da_x: { |
| 900 if (instr->HasW()) { | 903 if (instr->HasW()) { |
| 901 Unknown(instr); // not used in V8 | 904 Unknown(instr); // not used in V8 |
| 905 return; |
| 902 } | 906 } |
| 903 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); | 907 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); |
| 904 break; | 908 break; |
| 905 } | 909 } |
| 906 case ia_x: { | 910 case ia_x: { |
| 907 if (instr->HasW()) { | 911 if (instr->HasW()) { |
| 908 Unknown(instr); // not used in V8 | 912 Unknown(instr); // not used in V8 |
| 913 return; |
| 909 } | 914 } |
| 910 Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); | 915 Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); |
| 911 break; | 916 break; |
| 912 } | 917 } |
| 913 case db_x: { | 918 case db_x: { |
| 914 Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w"); | 919 Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w"); |
| 915 break; | 920 break; |
| 916 } | 921 } |
| 917 case ib_x: { | 922 case ib_x: { |
| 918 Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w"); | 923 Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w"); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 default: { | 990 default: { |
| 986 // The PU field is a 2-bit field. | 991 // The PU field is a 2-bit field. |
| 987 UNREACHABLE(); | 992 UNREACHABLE(); |
| 988 break; | 993 break; |
| 989 } | 994 } |
| 990 } | 995 } |
| 991 } | 996 } |
| 992 | 997 |
| 993 | 998 |
| 994 void Decoder::DecodeType4(Instruction* instr) { | 999 void Decoder::DecodeType4(Instruction* instr) { |
| 995 ASSERT(instr->Bit(22) == 0); // Privileged mode currently not supported. | 1000 if (instr->Bit(22) != 0) { |
| 996 if (instr->HasL()) { | 1001 // Privileged mode currently not supported. |
| 997 Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); | 1002 Unknown(instr); |
| 998 } else { | 1003 } else { |
| 999 Format(instr, "stm'cond'pu 'rn'w, 'rlist"); | 1004 if (instr->HasL()) { |
| 1005 Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); |
| 1006 } else { |
| 1007 Format(instr, "stm'cond'pu 'rn'w, 'rlist"); |
| 1008 } |
| 1000 } | 1009 } |
| 1001 } | 1010 } |
| 1002 | 1011 |
| 1003 | 1012 |
| 1004 void Decoder::DecodeType5(Instruction* instr) { | 1013 void Decoder::DecodeType5(Instruction* instr) { |
| 1005 Format(instr, "b'l'cond 'target"); | 1014 Format(instr, "b'l'cond 'target"); |
| 1006 } | 1015 } |
| 1007 | 1016 |
| 1008 | 1017 |
| 1009 void Decoder::DecodeType6(Instruction* instr) { | 1018 void Decoder::DecodeType6(Instruction* instr) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1035 } | 1044 } |
| 1036 return Instruction::kInstrSize; | 1045 return Instruction::kInstrSize; |
| 1037 } | 1046 } |
| 1038 | 1047 |
| 1039 | 1048 |
| 1040 // void Decoder::DecodeTypeVFP(Instruction* instr) | 1049 // void Decoder::DecodeTypeVFP(Instruction* instr) |
| 1041 // vmov: Sn = Rt | 1050 // vmov: Sn = Rt |
| 1042 // vmov: Rt = Sn | 1051 // vmov: Rt = Sn |
| 1043 // vcvt: Dd = Sm | 1052 // vcvt: Dd = Sm |
| 1044 // vcvt: Sd = Dm | 1053 // vcvt: Sd = Dm |
| 1054 // Dd = vabs(Dm) |
| 1055 // Dd = vneg(Dm) |
| 1045 // Dd = vadd(Dn, Dm) | 1056 // Dd = vadd(Dn, Dm) |
| 1046 // Dd = vsub(Dn, Dm) | 1057 // Dd = vsub(Dn, Dm) |
| 1047 // Dd = vmul(Dn, Dm) | 1058 // Dd = vmul(Dn, Dm) |
| 1048 // Dd = vdiv(Dn, Dm) | 1059 // Dd = vdiv(Dn, Dm) |
| 1049 // vcmp(Dd, Dm) | 1060 // vcmp(Dd, Dm) |
| 1050 // vmrs | 1061 // vmrs |
| 1051 // vmsr | 1062 // vmsr |
| 1052 // Dd = vsqrt(Dm) | 1063 // Dd = vsqrt(Dm) |
| 1053 void Decoder::DecodeTypeVFP(Instruction* instr) { | 1064 void Decoder::DecodeTypeVFP(Instruction* instr) { |
| 1054 ASSERT((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); | 1065 ASSERT((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1290 Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]"); | 1301 Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]"); |
| 1291 } else { | 1302 } else { |
| 1292 Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]"); | 1303 Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]"); |
| 1293 } | 1304 } |
| 1294 break; | 1305 break; |
| 1295 default: | 1306 default: |
| 1296 Unknown(instr); // Not used by V8. | 1307 Unknown(instr); // Not used by V8. |
| 1297 break; | 1308 break; |
| 1298 } | 1309 } |
| 1299 } else { | 1310 } else { |
| 1300 UNIMPLEMENTED(); // Not used by V8. | 1311 Unknown(instr); // Not used by V8. |
| 1301 } | 1312 } |
| 1302 } | 1313 } |
| 1303 | 1314 |
| 1315 |
| 1316 bool Decoder::IsConstantPoolAt(byte* instr_ptr) { |
| 1317 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); |
| 1318 return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker; |
| 1319 } |
| 1320 |
| 1321 |
| 1322 int Decoder::ConstantPoolSizeAt(byte* instr_ptr) { |
| 1323 if (IsConstantPoolAt(instr_ptr)) { |
| 1324 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); |
| 1325 return instruction_bits & kConstantPoolLengthMask; |
| 1326 } else { |
| 1327 return -1; |
| 1328 } |
| 1329 } |
| 1330 |
| 1304 | 1331 |
| 1305 // Disassemble the instruction at *instr_ptr into the output buffer. | 1332 // Disassemble the instruction at *instr_ptr into the output buffer. |
| 1306 int Decoder::InstructionDecode(byte* instr_ptr) { | 1333 int Decoder::InstructionDecode(byte* instr_ptr) { |
| 1307 Instruction* instr = Instruction::At(instr_ptr); | 1334 Instruction* instr = Instruction::At(instr_ptr); |
| 1308 // Print raw instruction bytes. | 1335 // Print raw instruction bytes. |
| 1309 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 1336 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| 1310 "%08x ", | 1337 "%08x ", |
| 1311 instr->InstructionBits()); | 1338 instr->InstructionBits()); |
| 1312 if (instr->ConditionField() == kSpecialCondition) { | 1339 if (instr->ConditionField() == kSpecialCondition) { |
| 1313 UNIMPLEMENTED(); | 1340 Unknown(instr); |
| 1341 return Instruction::kInstrSize; |
| 1342 } |
| 1343 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); |
| 1344 if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) { |
| 1345 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| 1346 "constant pool begin (length %d)", |
| 1347 instruction_bits & |
| 1348 kConstantPoolLengthMask); |
| 1314 return Instruction::kInstrSize; | 1349 return Instruction::kInstrSize; |
| 1315 } | 1350 } |
| 1316 switch (instr->TypeValue()) { | 1351 switch (instr->TypeValue()) { |
| 1317 case 0: | 1352 case 0: |
| 1318 case 1: { | 1353 case 1: { |
| 1319 DecodeType01(instr); | 1354 DecodeType01(instr); |
| 1320 break; | 1355 break; |
| 1321 } | 1356 } |
| 1322 case 2: { | 1357 case 2: { |
| 1323 DecodeType2(instr); | 1358 DecodeType2(instr); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1406 | 1441 |
| 1407 | 1442 |
| 1408 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, | 1443 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, |
| 1409 byte* instruction) { | 1444 byte* instruction) { |
| 1410 v8::internal::Decoder d(converter_, buffer); | 1445 v8::internal::Decoder d(converter_, buffer); |
| 1411 return d.InstructionDecode(instruction); | 1446 return d.InstructionDecode(instruction); |
| 1412 } | 1447 } |
| 1413 | 1448 |
| 1414 | 1449 |
| 1415 int Disassembler::ConstantPoolSizeAt(byte* instruction) { | 1450 int Disassembler::ConstantPoolSizeAt(byte* instruction) { |
| 1416 int instruction_bits = *(reinterpret_cast<int*>(instruction)); | 1451 return v8::internal::Decoder::ConstantPoolSizeAt(instruction); |
| 1417 if ((instruction_bits & 0xfff00000) == 0x03000000) { | |
| 1418 return instruction_bits & 0x0000ffff; | |
| 1419 } else { | |
| 1420 return -1; | |
| 1421 } | |
| 1422 } | 1452 } |
| 1423 | 1453 |
| 1424 | 1454 |
| 1425 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { | 1455 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { |
| 1426 NameConverter converter; | 1456 NameConverter converter; |
| 1427 Disassembler d(converter); | 1457 Disassembler d(converter); |
| 1428 for (byte* pc = begin; pc < end;) { | 1458 for (byte* pc = begin; pc < end;) { |
| 1429 v8::internal::EmbeddedVector<char, 128> buffer; | 1459 v8::internal::EmbeddedVector<char, 128> buffer; |
| 1430 buffer[0] = '\0'; | 1460 buffer[0] = '\0'; |
| 1431 byte* prev_pc = pc; | 1461 byte* prev_pc = pc; |
| 1432 pc += d.InstructionDecode(buffer, pc); | 1462 pc += d.InstructionDecode(buffer, pc); |
| 1433 fprintf(f, "%p %08x %s\n", | 1463 fprintf(f, "%p %08x %s\n", |
| 1434 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1464 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
| 1435 } | 1465 } |
| 1436 } | 1466 } |
| 1437 | 1467 |
| 1438 | 1468 |
| 1439 } // namespace disasm | 1469 } // namespace disasm |
| 1440 | 1470 |
| 1441 #endif // V8_TARGET_ARCH_ARM | 1471 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |