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 |