| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #include <string.h> | 8 #include <string.h> |
| 9 | 9 |
| 10 #include "src/v8.h" | 10 #include "src/v8.h" |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 } | 251 } |
| 252 break; | 252 break; |
| 253 } | 253 } |
| 254 default: UNREACHABLE(); | 254 default: UNREACHABLE(); |
| 255 } | 255 } |
| 256 Format(instr, mnemonic, form); | 256 Format(instr, mnemonic, form); |
| 257 } | 257 } |
| 258 | 258 |
| 259 | 259 |
| 260 bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) { | 260 bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) { |
| 261 ASSERT((reg_size == kXRegSizeInBits) || | 261 DCHECK((reg_size == kXRegSizeInBits) || |
| 262 ((reg_size == kWRegSizeInBits) && (value <= 0xffffffff))); | 262 ((reg_size == kWRegSizeInBits) && (value <= 0xffffffff))); |
| 263 | 263 |
| 264 // Test for movz: 16-bits set at positions 0, 16, 32 or 48. | 264 // Test for movz: 16-bits set at positions 0, 16, 32 or 48. |
| 265 if (((value & 0xffffffffffff0000UL) == 0UL) || | 265 if (((value & 0xffffffffffff0000UL) == 0UL) || |
| 266 ((value & 0xffffffff0000ffffUL) == 0UL) || | 266 ((value & 0xffffffff0000ffffUL) == 0UL) || |
| 267 ((value & 0xffff0000ffffffffUL) == 0UL) || | 267 ((value & 0xffff0000ffffffffUL) == 0UL) || |
| 268 ((value & 0x0000ffffffffffffUL) == 0UL)) { | 268 ((value & 0x0000ffffffffffffUL) == 0UL)) { |
| 269 return true; | 269 return true; |
| 270 } | 270 } |
| 271 | 271 |
| (...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1169 mnemonic = "msr"; | 1169 mnemonic = "msr"; |
| 1170 switch (instr->ImmSystemRegister()) { | 1170 switch (instr->ImmSystemRegister()) { |
| 1171 case NZCV: form = "nzcv, 'Xt"; break; | 1171 case NZCV: form = "nzcv, 'Xt"; break; |
| 1172 case FPCR: form = "fpcr, 'Xt"; break; | 1172 case FPCR: form = "fpcr, 'Xt"; break; |
| 1173 default: form = "(unknown), 'Xt"; break; | 1173 default: form = "(unknown), 'Xt"; break; |
| 1174 } | 1174 } |
| 1175 break; | 1175 break; |
| 1176 } | 1176 } |
| 1177 } | 1177 } |
| 1178 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) { | 1178 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) { |
| 1179 ASSERT(instr->Mask(SystemHintMask) == HINT); | 1179 DCHECK(instr->Mask(SystemHintMask) == HINT); |
| 1180 switch (instr->ImmHint()) { | 1180 switch (instr->ImmHint()) { |
| 1181 case NOP: { | 1181 case NOP: { |
| 1182 mnemonic = "nop"; | 1182 mnemonic = "nop"; |
| 1183 form = NULL; | 1183 form = NULL; |
| 1184 break; | 1184 break; |
| 1185 } | 1185 } |
| 1186 } | 1186 } |
| 1187 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) { | 1187 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) { |
| 1188 switch (instr->Mask(MemBarrierMask)) { | 1188 switch (instr->Mask(MemBarrierMask)) { |
| 1189 case DMB: { | 1189 case DMB: { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1239 | 1239 |
| 1240 void Disassembler::ProcessOutput(Instruction* /*instr*/) { | 1240 void Disassembler::ProcessOutput(Instruction* /*instr*/) { |
| 1241 // The base disasm does nothing more than disassembling into a buffer. | 1241 // The base disasm does nothing more than disassembling into a buffer. |
| 1242 } | 1242 } |
| 1243 | 1243 |
| 1244 | 1244 |
| 1245 void Disassembler::Format(Instruction* instr, const char* mnemonic, | 1245 void Disassembler::Format(Instruction* instr, const char* mnemonic, |
| 1246 const char* format) { | 1246 const char* format) { |
| 1247 // TODO(mcapewel) don't think I can use the instr address here - there needs | 1247 // TODO(mcapewel) don't think I can use the instr address here - there needs |
| 1248 // to be a base address too | 1248 // to be a base address too |
| 1249 ASSERT(mnemonic != NULL); | 1249 DCHECK(mnemonic != NULL); |
| 1250 ResetOutput(); | 1250 ResetOutput(); |
| 1251 Substitute(instr, mnemonic); | 1251 Substitute(instr, mnemonic); |
| 1252 if (format != NULL) { | 1252 if (format != NULL) { |
| 1253 buffer_[buffer_pos_++] = ' '; | 1253 buffer_[buffer_pos_++] = ' '; |
| 1254 Substitute(instr, format); | 1254 Substitute(instr, format); |
| 1255 } | 1255 } |
| 1256 buffer_[buffer_pos_] = 0; | 1256 buffer_[buffer_pos_] = 0; |
| 1257 ProcessOutput(instr); | 1257 ProcessOutput(instr); |
| 1258 } | 1258 } |
| 1259 | 1259 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1357 // Disassemble w31/x31 as zero register wzr/xzr. | 1357 // Disassemble w31/x31 as zero register wzr/xzr. |
| 1358 AppendToOutput("%czr", reg_type); | 1358 AppendToOutput("%czr", reg_type); |
| 1359 } | 1359 } |
| 1360 | 1360 |
| 1361 return field_len; | 1361 return field_len; |
| 1362 } | 1362 } |
| 1363 | 1363 |
| 1364 | 1364 |
| 1365 int Disassembler::SubstituteImmediateField(Instruction* instr, | 1365 int Disassembler::SubstituteImmediateField(Instruction* instr, |
| 1366 const char* format) { | 1366 const char* format) { |
| 1367 ASSERT(format[0] == 'I'); | 1367 DCHECK(format[0] == 'I'); |
| 1368 | 1368 |
| 1369 switch (format[1]) { | 1369 switch (format[1]) { |
| 1370 case 'M': { // IMoveImm or IMoveLSL. | 1370 case 'M': { // IMoveImm or IMoveLSL. |
| 1371 if (format[5] == 'I') { | 1371 if (format[5] == 'I') { |
| 1372 uint64_t imm = instr->ImmMoveWide() << (16 * instr->ShiftMoveWide()); | 1372 uint64_t imm = instr->ImmMoveWide() << (16 * instr->ShiftMoveWide()); |
| 1373 AppendToOutput("#0x%" PRIx64, imm); | 1373 AppendToOutput("#0x%" PRIx64, imm); |
| 1374 } else { | 1374 } else { |
| 1375 ASSERT(format[5] == 'L'); | 1375 DCHECK(format[5] == 'L'); |
| 1376 AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide()); | 1376 AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide()); |
| 1377 if (instr->ShiftMoveWide() > 0) { | 1377 if (instr->ShiftMoveWide() > 0) { |
| 1378 AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide()); | 1378 AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide()); |
| 1379 } | 1379 } |
| 1380 } | 1380 } |
| 1381 return 8; | 1381 return 8; |
| 1382 } | 1382 } |
| 1383 case 'L': { | 1383 case 'L': { |
| 1384 switch (format[2]) { | 1384 switch (format[2]) { |
| 1385 case 'L': { // ILLiteral - Immediate Load Literal. | 1385 case 'L': { // ILLiteral - Immediate Load Literal. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1410 } | 1410 } |
| 1411 } | 1411 } |
| 1412 } | 1412 } |
| 1413 case 'C': { // ICondB - Immediate Conditional Branch. | 1413 case 'C': { // ICondB - Immediate Conditional Branch. |
| 1414 int64_t offset = instr->ImmCondBranch() << 2; | 1414 int64_t offset = instr->ImmCondBranch() << 2; |
| 1415 char sign = (offset >= 0) ? '+' : '-'; | 1415 char sign = (offset >= 0) ? '+' : '-'; |
| 1416 AppendToOutput("#%c0x%" PRIx64, sign, offset); | 1416 AppendToOutput("#%c0x%" PRIx64, sign, offset); |
| 1417 return 6; | 1417 return 6; |
| 1418 } | 1418 } |
| 1419 case 'A': { // IAddSub. | 1419 case 'A': { // IAddSub. |
| 1420 ASSERT(instr->ShiftAddSub() <= 1); | 1420 DCHECK(instr->ShiftAddSub() <= 1); |
| 1421 int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub()); | 1421 int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub()); |
| 1422 AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm); | 1422 AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm); |
| 1423 return 7; | 1423 return 7; |
| 1424 } | 1424 } |
| 1425 case 'F': { // IFPSingle, IFPDouble or IFPFBits. | 1425 case 'F': { // IFPSingle, IFPDouble or IFPFBits. |
| 1426 if (format[3] == 'F') { // IFPFBits. | 1426 if (format[3] == 'F') { // IFPFBits. |
| 1427 AppendToOutput("#%d", 64 - instr->FPScale()); | 1427 AppendToOutput("#%d", 64 - instr->FPScale()); |
| 1428 return 8; | 1428 return 8; |
| 1429 } else { | 1429 } else { |
| 1430 AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(), | 1430 AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(), |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1467 default: { | 1467 default: { |
| 1468 UNREACHABLE(); | 1468 UNREACHABLE(); |
| 1469 return 0; | 1469 return 0; |
| 1470 } | 1470 } |
| 1471 } | 1471 } |
| 1472 } | 1472 } |
| 1473 | 1473 |
| 1474 | 1474 |
| 1475 int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr, | 1475 int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr, |
| 1476 const char* format) { | 1476 const char* format) { |
| 1477 ASSERT((format[0] == 'I') && (format[1] == 'B')); | 1477 DCHECK((format[0] == 'I') && (format[1] == 'B')); |
| 1478 unsigned r = instr->ImmR(); | 1478 unsigned r = instr->ImmR(); |
| 1479 unsigned s = instr->ImmS(); | 1479 unsigned s = instr->ImmS(); |
| 1480 | 1480 |
| 1481 switch (format[2]) { | 1481 switch (format[2]) { |
| 1482 case 'r': { // IBr. | 1482 case 'r': { // IBr. |
| 1483 AppendToOutput("#%d", r); | 1483 AppendToOutput("#%d", r); |
| 1484 return 3; | 1484 return 3; |
| 1485 } | 1485 } |
| 1486 case 's': { // IBs+1 or IBs-r+1. | 1486 case 's': { // IBs+1 or IBs-r+1. |
| 1487 if (format[3] == '+') { | 1487 if (format[3] == '+') { |
| 1488 AppendToOutput("#%d", s + 1); | 1488 AppendToOutput("#%d", s + 1); |
| 1489 return 5; | 1489 return 5; |
| 1490 } else { | 1490 } else { |
| 1491 ASSERT(format[3] == '-'); | 1491 DCHECK(format[3] == '-'); |
| 1492 AppendToOutput("#%d", s - r + 1); | 1492 AppendToOutput("#%d", s - r + 1); |
| 1493 return 7; | 1493 return 7; |
| 1494 } | 1494 } |
| 1495 } | 1495 } |
| 1496 case 'Z': { // IBZ-r. | 1496 case 'Z': { // IBZ-r. |
| 1497 ASSERT((format[3] == '-') && (format[4] == 'r')); | 1497 DCHECK((format[3] == '-') && (format[4] == 'r')); |
| 1498 unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits | 1498 unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits |
| 1499 : kWRegSizeInBits; | 1499 : kWRegSizeInBits; |
| 1500 AppendToOutput("#%d", reg_size - r); | 1500 AppendToOutput("#%d", reg_size - r); |
| 1501 return 5; | 1501 return 5; |
| 1502 } | 1502 } |
| 1503 default: { | 1503 default: { |
| 1504 UNREACHABLE(); | 1504 UNREACHABLE(); |
| 1505 return 0; | 1505 return 0; |
| 1506 } | 1506 } |
| 1507 } | 1507 } |
| 1508 } | 1508 } |
| 1509 | 1509 |
| 1510 | 1510 |
| 1511 int Disassembler::SubstituteLiteralField(Instruction* instr, | 1511 int Disassembler::SubstituteLiteralField(Instruction* instr, |
| 1512 const char* format) { | 1512 const char* format) { |
| 1513 ASSERT(strncmp(format, "LValue", 6) == 0); | 1513 DCHECK(strncmp(format, "LValue", 6) == 0); |
| 1514 USE(format); | 1514 USE(format); |
| 1515 | 1515 |
| 1516 switch (instr->Mask(LoadLiteralMask)) { | 1516 switch (instr->Mask(LoadLiteralMask)) { |
| 1517 case LDR_w_lit: | 1517 case LDR_w_lit: |
| 1518 case LDR_x_lit: | 1518 case LDR_x_lit: |
| 1519 case LDR_s_lit: | 1519 case LDR_s_lit: |
| 1520 case LDR_d_lit: AppendToOutput("(addr %p)", instr->LiteralAddress()); break; | 1520 case LDR_d_lit: AppendToOutput("(addr %p)", instr->LiteralAddress()); break; |
| 1521 default: UNREACHABLE(); | 1521 default: UNREACHABLE(); |
| 1522 } | 1522 } |
| 1523 | 1523 |
| 1524 return 6; | 1524 return 6; |
| 1525 } | 1525 } |
| 1526 | 1526 |
| 1527 | 1527 |
| 1528 int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) { | 1528 int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) { |
| 1529 ASSERT(format[0] == 'H'); | 1529 DCHECK(format[0] == 'H'); |
| 1530 ASSERT(instr->ShiftDP() <= 0x3); | 1530 DCHECK(instr->ShiftDP() <= 0x3); |
| 1531 | 1531 |
| 1532 switch (format[1]) { | 1532 switch (format[1]) { |
| 1533 case 'D': { // HDP. | 1533 case 'D': { // HDP. |
| 1534 ASSERT(instr->ShiftDP() != ROR); | 1534 DCHECK(instr->ShiftDP() != ROR); |
| 1535 } // Fall through. | 1535 } // Fall through. |
| 1536 case 'L': { // HLo. | 1536 case 'L': { // HLo. |
| 1537 if (instr->ImmDPShift() != 0) { | 1537 if (instr->ImmDPShift() != 0) { |
| 1538 const char* shift_type[] = {"lsl", "lsr", "asr", "ror"}; | 1538 const char* shift_type[] = {"lsl", "lsr", "asr", "ror"}; |
| 1539 AppendToOutput(", %s #%" PRId64, shift_type[instr->ShiftDP()], | 1539 AppendToOutput(", %s #%" PRId64, shift_type[instr->ShiftDP()], |
| 1540 instr->ImmDPShift()); | 1540 instr->ImmDPShift()); |
| 1541 } | 1541 } |
| 1542 return 3; | 1542 return 3; |
| 1543 } | 1543 } |
| 1544 default: | 1544 default: |
| 1545 UNREACHABLE(); | 1545 UNREACHABLE(); |
| 1546 return 0; | 1546 return 0; |
| 1547 } | 1547 } |
| 1548 } | 1548 } |
| 1549 | 1549 |
| 1550 | 1550 |
| 1551 int Disassembler::SubstituteConditionField(Instruction* instr, | 1551 int Disassembler::SubstituteConditionField(Instruction* instr, |
| 1552 const char* format) { | 1552 const char* format) { |
| 1553 ASSERT(format[0] == 'C'); | 1553 DCHECK(format[0] == 'C'); |
| 1554 const char* condition_code[] = { "eq", "ne", "hs", "lo", | 1554 const char* condition_code[] = { "eq", "ne", "hs", "lo", |
| 1555 "mi", "pl", "vs", "vc", | 1555 "mi", "pl", "vs", "vc", |
| 1556 "hi", "ls", "ge", "lt", | 1556 "hi", "ls", "ge", "lt", |
| 1557 "gt", "le", "al", "nv" }; | 1557 "gt", "le", "al", "nv" }; |
| 1558 int cond; | 1558 int cond; |
| 1559 switch (format[1]) { | 1559 switch (format[1]) { |
| 1560 case 'B': cond = instr->ConditionBranch(); break; | 1560 case 'B': cond = instr->ConditionBranch(); break; |
| 1561 case 'I': { | 1561 case 'I': { |
| 1562 cond = NegateCondition(static_cast<Condition>(instr->Condition())); | 1562 cond = NegateCondition(static_cast<Condition>(instr->Condition())); |
| 1563 break; | 1563 break; |
| 1564 } | 1564 } |
| 1565 default: cond = instr->Condition(); | 1565 default: cond = instr->Condition(); |
| 1566 } | 1566 } |
| 1567 AppendToOutput("%s", condition_code[cond]); | 1567 AppendToOutput("%s", condition_code[cond]); |
| 1568 return 4; | 1568 return 4; |
| 1569 } | 1569 } |
| 1570 | 1570 |
| 1571 | 1571 |
| 1572 int Disassembler::SubstitutePCRelAddressField(Instruction* instr, | 1572 int Disassembler::SubstitutePCRelAddressField(Instruction* instr, |
| 1573 const char* format) { | 1573 const char* format) { |
| 1574 USE(format); | 1574 USE(format); |
| 1575 ASSERT(strncmp(format, "AddrPCRel", 9) == 0); | 1575 DCHECK(strncmp(format, "AddrPCRel", 9) == 0); |
| 1576 | 1576 |
| 1577 int offset = instr->ImmPCRel(); | 1577 int offset = instr->ImmPCRel(); |
| 1578 | 1578 |
| 1579 // Only ADR (AddrPCRelByte) is supported. | 1579 // Only ADR (AddrPCRelByte) is supported. |
| 1580 ASSERT(strcmp(format, "AddrPCRelByte") == 0); | 1580 DCHECK(strcmp(format, "AddrPCRelByte") == 0); |
| 1581 | 1581 |
| 1582 char sign = '+'; | 1582 char sign = '+'; |
| 1583 if (offset < 0) { | 1583 if (offset < 0) { |
| 1584 offset = -offset; | 1584 offset = -offset; |
| 1585 sign = '-'; | 1585 sign = '-'; |
| 1586 } | 1586 } |
| 1587 AppendToOutput("#%c0x%x (addr %p)", sign, offset, | 1587 AppendToOutput("#%c0x%x (addr %p)", sign, offset, |
| 1588 instr->InstructionAtOffset(offset, Instruction::NO_CHECK)); | 1588 instr->InstructionAtOffset(offset, Instruction::NO_CHECK)); |
| 1589 return 13; | 1589 return 13; |
| 1590 } | 1590 } |
| 1591 | 1591 |
| 1592 | 1592 |
| 1593 int Disassembler::SubstituteBranchTargetField(Instruction* instr, | 1593 int Disassembler::SubstituteBranchTargetField(Instruction* instr, |
| 1594 const char* format) { | 1594 const char* format) { |
| 1595 ASSERT(strncmp(format, "BImm", 4) == 0); | 1595 DCHECK(strncmp(format, "BImm", 4) == 0); |
| 1596 | 1596 |
| 1597 int64_t offset = 0; | 1597 int64_t offset = 0; |
| 1598 switch (format[5]) { | 1598 switch (format[5]) { |
| 1599 // BImmUncn - unconditional branch immediate. | 1599 // BImmUncn - unconditional branch immediate. |
| 1600 case 'n': offset = instr->ImmUncondBranch(); break; | 1600 case 'n': offset = instr->ImmUncondBranch(); break; |
| 1601 // BImmCond - conditional branch immediate. | 1601 // BImmCond - conditional branch immediate. |
| 1602 case 'o': offset = instr->ImmCondBranch(); break; | 1602 case 'o': offset = instr->ImmCondBranch(); break; |
| 1603 // BImmCmpa - compare and branch immediate. | 1603 // BImmCmpa - compare and branch immediate. |
| 1604 case 'm': offset = instr->ImmCmpBranch(); break; | 1604 case 'm': offset = instr->ImmCmpBranch(); break; |
| 1605 // BImmTest - test and branch immediate. | 1605 // BImmTest - test and branch immediate. |
| 1606 case 'e': offset = instr->ImmTestBranch(); break; | 1606 case 'e': offset = instr->ImmTestBranch(); break; |
| 1607 default: UNREACHABLE(); | 1607 default: UNREACHABLE(); |
| 1608 } | 1608 } |
| 1609 offset <<= kInstructionSizeLog2; | 1609 offset <<= kInstructionSizeLog2; |
| 1610 char sign = '+'; | 1610 char sign = '+'; |
| 1611 if (offset < 0) { | 1611 if (offset < 0) { |
| 1612 sign = '-'; | 1612 sign = '-'; |
| 1613 } | 1613 } |
| 1614 AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, Abs(offset), | 1614 AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, Abs(offset), |
| 1615 instr->InstructionAtOffset(offset), Instruction::NO_CHECK); | 1615 instr->InstructionAtOffset(offset), Instruction::NO_CHECK); |
| 1616 return 8; | 1616 return 8; |
| 1617 } | 1617 } |
| 1618 | 1618 |
| 1619 | 1619 |
| 1620 int Disassembler::SubstituteExtendField(Instruction* instr, | 1620 int Disassembler::SubstituteExtendField(Instruction* instr, |
| 1621 const char* format) { | 1621 const char* format) { |
| 1622 ASSERT(strncmp(format, "Ext", 3) == 0); | 1622 DCHECK(strncmp(format, "Ext", 3) == 0); |
| 1623 ASSERT(instr->ExtendMode() <= 7); | 1623 DCHECK(instr->ExtendMode() <= 7); |
| 1624 USE(format); | 1624 USE(format); |
| 1625 | 1625 |
| 1626 const char* extend_mode[] = { "uxtb", "uxth", "uxtw", "uxtx", | 1626 const char* extend_mode[] = { "uxtb", "uxth", "uxtw", "uxtx", |
| 1627 "sxtb", "sxth", "sxtw", "sxtx" }; | 1627 "sxtb", "sxth", "sxtw", "sxtx" }; |
| 1628 | 1628 |
| 1629 // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit | 1629 // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit |
| 1630 // registers becomes lsl. | 1630 // registers becomes lsl. |
| 1631 if (((instr->Rd() == kZeroRegCode) || (instr->Rn() == kZeroRegCode)) && | 1631 if (((instr->Rd() == kZeroRegCode) || (instr->Rn() == kZeroRegCode)) && |
| 1632 (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) || | 1632 (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) || |
| 1633 (instr->ExtendMode() == UXTX))) { | 1633 (instr->ExtendMode() == UXTX))) { |
| 1634 if (instr->ImmExtendShift() > 0) { | 1634 if (instr->ImmExtendShift() > 0) { |
| 1635 AppendToOutput(", lsl #%d", instr->ImmExtendShift()); | 1635 AppendToOutput(", lsl #%d", instr->ImmExtendShift()); |
| 1636 } | 1636 } |
| 1637 } else { | 1637 } else { |
| 1638 AppendToOutput(", %s", extend_mode[instr->ExtendMode()]); | 1638 AppendToOutput(", %s", extend_mode[instr->ExtendMode()]); |
| 1639 if (instr->ImmExtendShift() > 0) { | 1639 if (instr->ImmExtendShift() > 0) { |
| 1640 AppendToOutput(" #%d", instr->ImmExtendShift()); | 1640 AppendToOutput(" #%d", instr->ImmExtendShift()); |
| 1641 } | 1641 } |
| 1642 } | 1642 } |
| 1643 return 3; | 1643 return 3; |
| 1644 } | 1644 } |
| 1645 | 1645 |
| 1646 | 1646 |
| 1647 int Disassembler::SubstituteLSRegOffsetField(Instruction* instr, | 1647 int Disassembler::SubstituteLSRegOffsetField(Instruction* instr, |
| 1648 const char* format) { | 1648 const char* format) { |
| 1649 ASSERT(strncmp(format, "Offsetreg", 9) == 0); | 1649 DCHECK(strncmp(format, "Offsetreg", 9) == 0); |
| 1650 const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl", | 1650 const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl", |
| 1651 "undefined", "undefined", "sxtw", "sxtx" }; | 1651 "undefined", "undefined", "sxtw", "sxtx" }; |
| 1652 USE(format); | 1652 USE(format); |
| 1653 | 1653 |
| 1654 unsigned shift = instr->ImmShiftLS(); | 1654 unsigned shift = instr->ImmShiftLS(); |
| 1655 Extend ext = static_cast<Extend>(instr->ExtendMode()); | 1655 Extend ext = static_cast<Extend>(instr->ExtendMode()); |
| 1656 char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x'; | 1656 char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x'; |
| 1657 | 1657 |
| 1658 unsigned rm = instr->Rm(); | 1658 unsigned rm = instr->Rm(); |
| 1659 if (rm == kZeroRegCode) { | 1659 if (rm == kZeroRegCode) { |
| 1660 AppendToOutput("%czr", reg_type); | 1660 AppendToOutput("%czr", reg_type); |
| 1661 } else { | 1661 } else { |
| 1662 AppendToOutput("%c%d", reg_type, rm); | 1662 AppendToOutput("%c%d", reg_type, rm); |
| 1663 } | 1663 } |
| 1664 | 1664 |
| 1665 // Extend mode UXTX is an alias for shift mode LSL here. | 1665 // Extend mode UXTX is an alias for shift mode LSL here. |
| 1666 if (!((ext == UXTX) && (shift == 0))) { | 1666 if (!((ext == UXTX) && (shift == 0))) { |
| 1667 AppendToOutput(", %s", extend_mode[ext]); | 1667 AppendToOutput(", %s", extend_mode[ext]); |
| 1668 if (shift != 0) { | 1668 if (shift != 0) { |
| 1669 AppendToOutput(" #%d", instr->SizeLS()); | 1669 AppendToOutput(" #%d", instr->SizeLS()); |
| 1670 } | 1670 } |
| 1671 } | 1671 } |
| 1672 return 9; | 1672 return 9; |
| 1673 } | 1673 } |
| 1674 | 1674 |
| 1675 | 1675 |
| 1676 int Disassembler::SubstitutePrefetchField(Instruction* instr, | 1676 int Disassembler::SubstitutePrefetchField(Instruction* instr, |
| 1677 const char* format) { | 1677 const char* format) { |
| 1678 ASSERT(format[0] == 'P'); | 1678 DCHECK(format[0] == 'P'); |
| 1679 USE(format); | 1679 USE(format); |
| 1680 | 1680 |
| 1681 int prefetch_mode = instr->PrefetchMode(); | 1681 int prefetch_mode = instr->PrefetchMode(); |
| 1682 | 1682 |
| 1683 const char* ls = (prefetch_mode & 0x10) ? "st" : "ld"; | 1683 const char* ls = (prefetch_mode & 0x10) ? "st" : "ld"; |
| 1684 int level = (prefetch_mode >> 1) + 1; | 1684 int level = (prefetch_mode >> 1) + 1; |
| 1685 const char* ks = (prefetch_mode & 1) ? "strm" : "keep"; | 1685 const char* ks = (prefetch_mode & 1) ? "strm" : "keep"; |
| 1686 | 1686 |
| 1687 AppendToOutput("p%sl%d%s", ls, level, ks); | 1687 AppendToOutput("p%sl%d%s", ls, level, ks); |
| 1688 return 6; | 1688 return 6; |
| 1689 } | 1689 } |
| 1690 | 1690 |
| 1691 int Disassembler::SubstituteBarrierField(Instruction* instr, | 1691 int Disassembler::SubstituteBarrierField(Instruction* instr, |
| 1692 const char* format) { | 1692 const char* format) { |
| 1693 ASSERT(format[0] == 'M'); | 1693 DCHECK(format[0] == 'M'); |
| 1694 USE(format); | 1694 USE(format); |
| 1695 | 1695 |
| 1696 static const char* options[4][4] = { | 1696 static const char* options[4][4] = { |
| 1697 { "sy (0b0000)", "oshld", "oshst", "osh" }, | 1697 { "sy (0b0000)", "oshld", "oshst", "osh" }, |
| 1698 { "sy (0b0100)", "nshld", "nshst", "nsh" }, | 1698 { "sy (0b0100)", "nshld", "nshst", "nsh" }, |
| 1699 { "sy (0b1000)", "ishld", "ishst", "ish" }, | 1699 { "sy (0b1000)", "ishld", "ishst", "ish" }, |
| 1700 { "sy (0b1100)", "ld", "st", "sy" } | 1700 { "sy (0b1100)", "ld", "st", "sy" } |
| 1701 }; | 1701 }; |
| 1702 int domain = instr->ImmBarrierDomain(); | 1702 int domain = instr->ImmBarrierDomain(); |
| 1703 int type = instr->ImmBarrierType(); | 1703 int type = instr->ImmBarrierType(); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1823 decoder.AppendVisitor(&disasm); | 1823 decoder.AppendVisitor(&disasm); |
| 1824 | 1824 |
| 1825 for (byte* pc = start; pc < end; pc += v8::internal::kInstructionSize) { | 1825 for (byte* pc = start; pc < end; pc += v8::internal::kInstructionSize) { |
| 1826 decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(pc)); | 1826 decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(pc)); |
| 1827 } | 1827 } |
| 1828 } | 1828 } |
| 1829 | 1829 |
| 1830 } // namespace disasm | 1830 } // namespace disasm |
| 1831 | 1831 |
| 1832 #endif // V8_TARGET_ARCH_ARM64 | 1832 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |