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 // A Disassembler object is used to disassemble a block of code instruction by | 5 // A Disassembler object is used to disassemble a block of code instruction by |
6 // instruction. The default implementation of the NameConverter object can be | 6 // instruction. The default implementation of the NameConverter object can be |
7 // overriden to modify register names or to do symbol lookup on addresses. | 7 // overriden to modify register names or to do symbol lookup on addresses. |
8 // | 8 // |
9 // The example below will disassemble a block of code and print it to stdout. | 9 // The example below will disassemble a block of code and print it to stdout. |
10 // | 10 // |
(...skipping 1306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1317 } | 1317 } |
1318 | 1318 |
1319 | 1319 |
1320 // void Decoder::DecodeTypeVFP(Instruction* instr) | 1320 // void Decoder::DecodeTypeVFP(Instruction* instr) |
1321 // vmov: Sn = Rt | 1321 // vmov: Sn = Rt |
1322 // vmov: Rt = Sn | 1322 // vmov: Rt = Sn |
1323 // vcvt: Dd = Sm | 1323 // vcvt: Dd = Sm |
1324 // vcvt: Sd = Dm | 1324 // vcvt: Sd = Dm |
1325 // vcvt.f64.s32 Dd, Dd, #<fbits> | 1325 // vcvt.f64.s32 Dd, Dd, #<fbits> |
1326 // Dd = vabs(Dm) | 1326 // Dd = vabs(Dm) |
| 1327 // Sd = vabs(Sm) |
1327 // Dd = vneg(Dm) | 1328 // Dd = vneg(Dm) |
| 1329 // Sd = vneg(Sm) |
1328 // Dd = vadd(Dn, Dm) | 1330 // Dd = vadd(Dn, Dm) |
| 1331 // Sd = vadd(Sn, Sm) |
1329 // Dd = vsub(Dn, Dm) | 1332 // Dd = vsub(Dn, Dm) |
| 1333 // Sd = vsub(Sn, Sm) |
1330 // Dd = vmul(Dn, Dm) | 1334 // Dd = vmul(Dn, Dm) |
| 1335 // Sd = vmul(Sn, Sm) |
1331 // Dd = vmla(Dn, Dm) | 1336 // Dd = vmla(Dn, Dm) |
| 1337 // Sd = vmla(Sn, Sm) |
1332 // Dd = vmls(Dn, Dm) | 1338 // Dd = vmls(Dn, Dm) |
| 1339 // Sd = vmls(Sn, Sm) |
1333 // Dd = vdiv(Dn, Dm) | 1340 // Dd = vdiv(Dn, Dm) |
| 1341 // Sd = vdiv(Sn, Sm) |
1334 // vcmp(Dd, Dm) | 1342 // vcmp(Dd, Dm) |
| 1343 // vcmp(Sd, Sm) |
| 1344 // Dd = vsqrt(Dm) |
| 1345 // Sd = vsqrt(Sm) |
1335 // vmrs | 1346 // vmrs |
1336 // vmsr | 1347 // vmsr |
1337 // Dd = vsqrt(Dm) | |
1338 void Decoder::DecodeTypeVFP(Instruction* instr) { | 1348 void Decoder::DecodeTypeVFP(Instruction* instr) { |
1339 VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); | 1349 VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); |
1340 VERIFY(instr->Bits(11, 9) == 0x5); | 1350 VERIFY(instr->Bits(11, 9) == 0x5); |
1341 | 1351 |
1342 if (instr->Bit(4) == 0) { | 1352 if (instr->Bit(4) == 0) { |
1343 if (instr->Opc1Value() == 0x7) { | 1353 if (instr->Opc1Value() == 0x7) { |
1344 // Other data processing instructions | 1354 // Other data processing instructions |
1345 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) { | 1355 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) { |
1346 // vmov register to register. | 1356 // vmov register to register. |
1347 if (instr->SzValue() == 0x1) { | 1357 if (instr->SzValue() == 0x1) { |
1348 Format(instr, "vmov'cond.f64 'Dd, 'Dm"); | 1358 Format(instr, "vmov'cond.f64 'Dd, 'Dm"); |
1349 } else { | 1359 } else { |
1350 Format(instr, "vmov'cond.f32 'Sd, 'Sm"); | 1360 Format(instr, "vmov'cond.f32 'Sd, 'Sm"); |
1351 } | 1361 } |
1352 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { | 1362 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) { |
1353 // vabs | 1363 // vabs |
1354 Format(instr, "vabs'cond.f64 'Dd, 'Dm"); | 1364 if (instr->SzValue() == 0x1) { |
| 1365 Format(instr, "vabs'cond.f64 'Dd, 'Dm"); |
| 1366 } else { |
| 1367 Format(instr, "vabs'cond.f32 'Sd, 'Sm"); |
| 1368 } |
1355 } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) { | 1369 } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) { |
1356 // vneg | 1370 // vneg |
1357 Format(instr, "vneg'cond.f64 'Dd, 'Dm"); | 1371 if (instr->SzValue() == 0x1) { |
| 1372 Format(instr, "vneg'cond.f64 'Dd, 'Dm"); |
| 1373 } else { |
| 1374 Format(instr, "vneg'cond.f32 'Sd, 'Sm"); |
| 1375 } |
1358 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { | 1376 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) { |
1359 DecodeVCVTBetweenDoubleAndSingle(instr); | 1377 DecodeVCVTBetweenDoubleAndSingle(instr); |
1360 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { | 1378 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) { |
1361 DecodeVCVTBetweenFloatingPointAndInteger(instr); | 1379 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
1362 } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) && | 1380 } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) && |
1363 (instr->Bit(8) == 1)) { | 1381 (instr->Bit(8) == 1)) { |
1364 // vcvt.f64.s32 Dd, Dd, #<fbits> | 1382 // vcvt.f64.s32 Dd, Dd, #<fbits> |
1365 int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5)); | 1383 int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5)); |
1366 Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd"); | 1384 Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd"); |
1367 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, | 1385 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
1368 ", #%d", fraction_bits); | 1386 ", #%d", fraction_bits); |
1369 } else if (((instr->Opc2Value() >> 1) == 0x6) && | 1387 } else if (((instr->Opc2Value() >> 1) == 0x6) && |
1370 (instr->Opc3Value() & 0x1)) { | 1388 (instr->Opc3Value() & 0x1)) { |
1371 DecodeVCVTBetweenFloatingPointAndInteger(instr); | 1389 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
1372 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && | 1390 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && |
1373 (instr->Opc3Value() & 0x1)) { | 1391 (instr->Opc3Value() & 0x1)) { |
1374 DecodeVCMP(instr); | 1392 DecodeVCMP(instr); |
1375 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { | 1393 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) { |
1376 Format(instr, "vsqrt'cond.f64 'Dd, 'Dm"); | 1394 if (instr->SzValue() == 0x1) { |
| 1395 Format(instr, "vsqrt'cond.f64 'Dd, 'Dm"); |
| 1396 } else { |
| 1397 Format(instr, "vsqrt'cond.f32 'Sd, 'Sm"); |
| 1398 } |
1377 } else if (instr->Opc3Value() == 0x0) { | 1399 } else if (instr->Opc3Value() == 0x0) { |
1378 if (instr->SzValue() == 0x1) { | 1400 if (instr->SzValue() == 0x1) { |
1379 Format(instr, "vmov'cond.f64 'Dd, 'd"); | 1401 Format(instr, "vmov'cond.f64 'Dd, 'd"); |
1380 } else { | 1402 } else { |
1381 Unknown(instr); // Not used by V8. | 1403 Unknown(instr); // Not used by V8. |
1382 } | 1404 } |
1383 } else if (((instr->Opc2Value() == 0x6)) && instr->Opc3Value() == 0x3) { | 1405 } else if (((instr->Opc2Value() == 0x6)) && instr->Opc3Value() == 0x3) { |
1384 bool dp_operation = (instr->SzValue() == 1); | |
1385 // vrintz - round towards zero (truncate) | 1406 // vrintz - round towards zero (truncate) |
1386 if (dp_operation) { | 1407 if (instr->SzValue() == 0x1) { |
1387 Format(instr, "vrintz'cond.f64.f64 'Dd, 'Dm"); | 1408 Format(instr, "vrintz'cond.f64.f64 'Dd, 'Dm"); |
1388 } else { | 1409 } else { |
1389 Unknown(instr); // Not used by V8. | 1410 Format(instr, "vrintz'cond.f32.f32 'Sd, 'Sm"); |
1390 } | 1411 } |
1391 } else { | 1412 } else { |
1392 Unknown(instr); // Not used by V8. | 1413 Unknown(instr); // Not used by V8. |
1393 } | 1414 } |
1394 } else if (instr->Opc1Value() == 0x3) { | 1415 } else if (instr->Opc1Value() == 0x3) { |
1395 if (instr->SzValue() == 0x1) { | 1416 if (instr->SzValue() == 0x1) { |
1396 if (instr->Opc3Value() & 0x1) { | 1417 if (instr->Opc3Value() & 0x1) { |
1397 Format(instr, "vsub'cond.f64 'Dd, 'Dn, 'Dm"); | 1418 Format(instr, "vsub'cond.f64 'Dd, 'Dn, 'Dm"); |
1398 } else { | 1419 } else { |
1399 Format(instr, "vadd'cond.f64 'Dd, 'Dn, 'Dm"); | 1420 Format(instr, "vadd'cond.f64 'Dd, 'Dn, 'Dm"); |
1400 } | 1421 } |
1401 } else { | 1422 } else { |
1402 Unknown(instr); // Not used by V8. | 1423 if (instr->Opc3Value() & 0x1) { |
| 1424 Format(instr, "vsub'cond.f32 'Sd, 'Sn, 'Sm"); |
| 1425 } else { |
| 1426 Format(instr, "vadd'cond.f32 'Sd, 'Sn, 'Sm"); |
| 1427 } |
1403 } | 1428 } |
1404 } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) { | 1429 } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) { |
1405 if (instr->SzValue() == 0x1) { | 1430 if (instr->SzValue() == 0x1) { |
1406 Format(instr, "vmul'cond.f64 'Dd, 'Dn, 'Dm"); | 1431 Format(instr, "vmul'cond.f64 'Dd, 'Dn, 'Dm"); |
1407 } else { | 1432 } else { |
1408 Unknown(instr); // Not used by V8. | 1433 Format(instr, "vmul'cond.f32 'Sd, 'Sn, 'Sm"); |
1409 } | 1434 } |
1410 } else if ((instr->Opc1Value() == 0x0) && !(instr->Opc3Value() & 0x1)) { | 1435 } else if ((instr->Opc1Value() == 0x0) && !(instr->Opc3Value() & 0x1)) { |
1411 if (instr->SzValue() == 0x1) { | 1436 if (instr->SzValue() == 0x1) { |
1412 Format(instr, "vmla'cond.f64 'Dd, 'Dn, 'Dm"); | 1437 Format(instr, "vmla'cond.f64 'Dd, 'Dn, 'Dm"); |
1413 } else { | 1438 } else { |
1414 Unknown(instr); // Not used by V8. | 1439 Format(instr, "vmla'cond.f32 'Sd, 'Sn, 'Sm"); |
1415 } | 1440 } |
1416 } else if ((instr->Opc1Value() == 0x0) && (instr->Opc3Value() & 0x1)) { | 1441 } else if ((instr->Opc1Value() == 0x0) && (instr->Opc3Value() & 0x1)) { |
1417 if (instr->SzValue() == 0x1) { | 1442 if (instr->SzValue() == 0x1) { |
1418 Format(instr, "vmls'cond.f64 'Dd, 'Dn, 'Dm"); | 1443 Format(instr, "vmls'cond.f64 'Dd, 'Dn, 'Dm"); |
1419 } else { | 1444 } else { |
1420 Unknown(instr); // Not used by V8. | 1445 Format(instr, "vmls'cond.f32 'Sd, 'Sn, 'Sm"); |
1421 } | 1446 } |
1422 } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) { | 1447 } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) { |
1423 if (instr->SzValue() == 0x1) { | 1448 if (instr->SzValue() == 0x1) { |
1424 Format(instr, "vdiv'cond.f64 'Dd, 'Dn, 'Dm"); | 1449 Format(instr, "vdiv'cond.f64 'Dd, 'Dn, 'Dm"); |
1425 } else { | 1450 } else { |
1426 Unknown(instr); // Not used by V8. | 1451 Format(instr, "vdiv'cond.f32 'Sd, 'Sn, 'Sm"); |
1427 } | 1452 } |
1428 } else { | 1453 } else { |
1429 Unknown(instr); // Not used by V8. | 1454 Unknown(instr); // Not used by V8. |
1430 } | 1455 } |
1431 } else { | 1456 } else { |
1432 if ((instr->VCValue() == 0x0) && | 1457 if ((instr->VCValue() == 0x0) && |
1433 (instr->VAValue() == 0x0)) { | 1458 (instr->VAValue() == 0x0)) { |
1434 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); | 1459 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); |
1435 } else if ((instr->VLValue() == 0x0) && | 1460 } else if ((instr->VLValue() == 0x0) && |
1436 (instr->VCValue() == 0x1) && | 1461 (instr->VCValue() == 0x1) && |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1494 bool raise_exception_for_qnan = (instr->Bit(7) == 0x1); | 1519 bool raise_exception_for_qnan = (instr->Bit(7) == 0x1); |
1495 | 1520 |
1496 if (dp_operation && !raise_exception_for_qnan) { | 1521 if (dp_operation && !raise_exception_for_qnan) { |
1497 if (instr->Opc2Value() == 0x4) { | 1522 if (instr->Opc2Value() == 0x4) { |
1498 Format(instr, "vcmp'cond.f64 'Dd, 'Dm"); | 1523 Format(instr, "vcmp'cond.f64 'Dd, 'Dm"); |
1499 } else if (instr->Opc2Value() == 0x5) { | 1524 } else if (instr->Opc2Value() == 0x5) { |
1500 Format(instr, "vcmp'cond.f64 'Dd, #0.0"); | 1525 Format(instr, "vcmp'cond.f64 'Dd, #0.0"); |
1501 } else { | 1526 } else { |
1502 Unknown(instr); // invalid | 1527 Unknown(instr); // invalid |
1503 } | 1528 } |
| 1529 } else if (!raise_exception_for_qnan) { |
| 1530 if (instr->Opc2Value() == 0x4) { |
| 1531 Format(instr, "vcmp'cond.f32 'Sd, 'Sm"); |
| 1532 } else if (instr->Opc2Value() == 0x5) { |
| 1533 Format(instr, "vcmp'cond.f32 'Sd, #0.0"); |
| 1534 } else { |
| 1535 Unknown(instr); // invalid |
| 1536 } |
1504 } else { | 1537 } else { |
1505 Unknown(instr); // Not used by V8. | 1538 Unknown(instr); // Not used by V8. |
1506 } | 1539 } |
1507 } | 1540 } |
1508 | 1541 |
1509 | 1542 |
1510 void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) { | 1543 void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) { |
1511 VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); | 1544 VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); |
1512 VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)); | 1545 VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)); |
1513 | 1546 |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1947 v8::internal::PrintF( | 1980 v8::internal::PrintF( |
1948 f, "%p %08x %s\n", | 1981 f, "%p %08x %s\n", |
1949 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1982 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
1950 } | 1983 } |
1951 } | 1984 } |
1952 | 1985 |
1953 | 1986 |
1954 } // namespace disasm | 1987 } // namespace disasm |
1955 | 1988 |
1956 #endif // V8_TARGET_ARCH_ARM | 1989 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |